pyisyox.runtime.group module¶
Runtime Group — IoX scenes (a.k.a. controller-side groups).
A group represents a controller-managed collection of nodes — the IoX
“scene” concept. Sending a command to the group’s address is the same
wire shape as sending to a node (GET /rest/nodes/{addr}/cmd/{cmd});
the controller broadcasts to every member.
Group commands are sent raw without editor-codec validation: the
nodeDefId attribute on a <group> element (typically
"InsteonDimmer") is a scene-class label, not a profile-level
nodedef, so there’s no editor table to validate parameters against.
The well-known group commands are documented in the IoX REST guide:
DON (with optional level), DOF, DFON / DFOF (fast on/
off), BRT / DIM (manual brighten/dim). Pre-encode any
parameters as integers — the same shape pyisyox.runtime.Node
produces internally.
Groups don’t carry live property state of their own — there’s no
properties dict — because the wire-level group has no observable
attribute beyond its membership. State events flow through individual
member nodes.
Sourced from <group flag="132"> elements in the legacy
/rest/nodes XML. flag="12" (the special “ISY” group
representing the controller itself) is filtered out at parse time.
- class Group(record, profile, client, nodes=None)[source]¶
Bases:
objectUser-facing handle for one group / scene in the controller.
- Parameters:
record (GroupRecord)
profile (Profile)
client (IoXClient)
nodes (dict[str, NodeRecord] | None)
- classmethod from_record(record, profile, client, nodes=None)[source]¶
Construct a Group from a parsed record.
Pass
nodes(the controller’sloaded.nodesdict) to enable thegroup_all_onderived property. Without it the group is purely command-issuing.- Parameters:
record (GroupRecord)
profile (Profile)
client (IoXClient)
nodes (dict[str, NodeRecord] | None)
- Return type:
- property address: str¶
Group address — usually a 5-digit integer string or
"ADR####"for special groups like~zAuto DR.
- property nodedef_id: str¶
Scene-class label (
"InsteonDimmer"etc.). Not a real profile nodedef — see module docstring.
- property member_addresses: tuple[str, ...]¶
Addresses of the nodes that belong to this group.
Sourced from the
<members>element in/rest/nodesXML. Order matches the controller’s declaration order. Includes both controllers and responders; usecontroller_addressesfor the controller subset.
- property controller_addresses: tuple[str, ...]¶
Subset of
member_addressesthat the controller flags as scene controllers (<link type="16">).Empty when the group has no explicit controller (e.g. virtual scenes / SmartLinc-style automation groups).
- property has_state_target: bool¶
Whether the scene maintains any member on/off state.
Truewhen link targets resolved and at least one member has anon/offintent. A resolved scene with only fire-only / config links (cmdBL/BEEP/…, or empty) →False: it has no steady state, so a consumer should model it as a momentary button, not a switch. When targets are unresolved we can’t tell, so assumeTrue(the safe default — keep it a stateful scene).
- property has_dimmable_members: bool¶
True iff any member node is a dimmable load.
Nodedef-derived via
pyisyox.runtime.Node.is_dimmable, so it’s robust and — unlikehas_state_target— does not depend on/api/groupslink resolution (works on older firmware too). Consumers pair it withhas_state_targetto pick the scene’s HA platform: no state target → button; else dimmable members → on/off light (preserving light semantics + the group/more-info framework, noswitch_as_x); else → switch. Scenes have no settable brightness — fade/brt/dim are separate manual commands — so “light” here is on/off only.Returns
Falsewithout a node-registry reference. Members missing from the registry are skipped (defensive). Memoised on first access (oneNode+find_nodedefper member) — the result is static for this record, so repeated reads (e.g.to_dict) don’t rebuild it.
- property group_all_on: bool¶
True iff every on-target member currently reports an “on” state.
Computed on access from the controller’s node registry. Stateless members — motion sensors, RemoteLincs, binary-alarm devices, see
_STATELESS_NODEDEF_IDS— are excluded; theirSTisn’t a persistent state.When
/api/groupslink targets resolved, the aggregate is over the scene’s on-target members only (see_on_set()) — so a radio-style keypad scene (one button on-target, the rest driven off) tracks correctly instead of being structurally never-all-on. Otherwise it falls back to the legacy all-member behaviour. ReturnsFalsewhen the group has no node-registry reference, the (on-target / member) set is empty, a member is missing from the registry, or any counted member’sSTis missing or zero.Cheap:
O(N), computed on read — the underlyingSTvalues mutate in place via the WS dispatcher, so each access reflects the latest state.
- property group_any_on: bool¶
True iff at least one on-target member currently reports “on”.
Companion to
group_all_on; this is the aggregation HA scene-switch consumers want for theiris_on. When/api/groupslink targets resolved it considers only the scene’s on-target members (see_on_set()), so a scene reads on iff a member it actually drives on is on — not merely because some always-lit keypad button is non-zero. Otherwise it falls back to the legacy “any stateful member non-zero” behaviour (whatpyisy.Group.statusdid). Stateless members and members not in the registry are skipped.Returns
Falsewith no node-registry reference, an empty (on-target / member) set, or when every counted member’sSTis missing or zero. Cheap:O(N), computed on read.
- async send_command(command_id, *params)[source]¶
Send a command to every member of this group.
Wire shape:
GET /rest/nodes/{group_addr}/cmd/{command_id}[/{p1}...]. The controller broadcasts to each member; results aren’t returned per-member.Unlike
Node.send_command(), parameters are not validated through the editor codec — group nodedefs aren’t profile-resolvable. Pass already-encoded integers; consumers are responsible for sanity checks (e.g. clamp on-level to 0-100). Common usage:await group.send_command("DON")— turn the scene on to its programmed levelawait group.send_command("DON", 75)— explicit on-levelawait group.send_command("DOF")await group.send_command("DFON")/"DFOF"— fastawait group.send_command("BRT")/"DIM"— manual brighten/dim step
- async rename(name)[source]¶
Rename this group / scene.
Wire shape:
POST /api/nodes/{address}with{"name": "<str>", "nodeType": "group"}. ThenodeTypefield is required by the server even though the address already disambiguates — without it the call is rejected.- Parameters:
name (str)
- Return type:
None