Skip to content

Associations

An association binds a hardware Node (by MAC) to a placed entity. The RTLS server has two separate association resources, and the SDK exposes one sub-client for each:

  • trackable_objects_associations — node ↔ Tag (server fields: mac_address + obj_uid). Exposed as client.tag_associations.
  • win_anchor_associations — node ↔ Anchor (server fields: mac_address + win_uid). Exposed as client.anchor_associations.

Quick reference — client.tag_associations (tag ↔ node)

Method What it does
client.tag_associations.list() All open trackable-associations in scope.
client.tag_associations.list_active_in_period(start, end) Trackable-associations active in the window.
client.tag_associations.create(mac, obj_uid) Open one tag association.
client.tag_associations.open(mac, obj_uid) Close any open association for this mac or this obj_uid (trackable), then create a fresh one (clean 1:1 binding).
client.tag_associations.close(uid) Close one association.
client.tag_associations.bulk_create(pairs) Open many; continue-on-error BulkResult.

Quick reference — client.anchor_associations (anchor ↔ node)

Method What it does
client.anchor_associations.list() Open anchor-associations only.
client.anchor_associations.list_all() Open + closed (sends ?all=true).
client.anchor_associations.create(mac, win_uid) Bind a MAC to a placed anchor.
client.anchor_associations.open(mac, win_uid) Close any open association for this mac or this win_uid, then create a fresh one (enforces a clean 1:1 binding).
client.anchor_associations.update(uid, *, mac=..., win_uid=...) Rebind to a different MAC or anchor. The server requires both fields on the wire; the SDK fills the unchanged one via list_all() if you only pass one.
client.anchor_associations.close(...) Close by AnchorAssociation, uid, or mac / win_uid kwargs.
client.anchor_associations.delete(uid) Hard-delete a row (after close).

Open anchor associations come back from the wire with closed_at = "9999-12-31T23:59:59.000Z"; the SDK maps that sentinel to None so assoc.closed_at is None is the open/closed predicate.

Writing

client.tag_associations.create("aabbccddeeff", tag.uid)
client.tag_associations.close(assoc_uid)

MAC is normalized to bare 12-hex lowercase before sending; six input formats accepted, malformed input raises ValueError.

Bulk

result = client.tag_associations.bulk_create([
    ("aabbccddee01", "tag-1"),
    ("aabbccddee02", "tag-2"),
])
print(f"{len(result.failures)} failed")

Each tuple is (mac, obj_uid). Continue-on-error for server-side failures (a duplicate, a missing tag uid, etc.). A malformed MAC aborts the whole batch — programmer error, not a server-recoverable case.

Model — TagAssociation

Field Type Notes
uid str Server-assigned.
mac_address str \| None Bound node's MAC (bare 12-hex).
obj_uid str \| None Bound tag's uid.
opened_at / closed_at datetime \| None Lifecycle stamps.

Model — AnchorAssociation

Field Type Notes
uid str \| None Server-assigned.
mac_address str \| None Bound node's MAC (bare 12-hex).
win_uid str \| None Bound anchor's uid (the SDK uses win_uid on both the wire and the method surface).
opened_at / closed_at datetime \| None Lifecycle stamps. closed_at is None for open associations (the 9999 sentinel is hidden).

Full field list.

  • Hardware: Nodes. nodes.release closes associations as part of its compound.
  • Placed: Tags for client.tag_associations, Anchors for client.anchor_associations.

See also