Split devices¶
Some physical devices expose multiple controllable endpoints (multi-zone lights, security sensors, portable AC power toggles). aioafero splits them into separate logical devices so integrations can expose one entity per zone.
Not every device with more than one brightness control is split. RGB+WW fixtures such
as flushmounts and RGBCW strips expose separate color and white dimming
channels on one fixture; those stay a single light (see Dual-channel RGB+WW lights).
How splitting works¶
During discovery, a controller’s
DEVICE_SPLIT_CALLBACKStransforms oneAferoDeviceinto several clones with synthetic IDs.Each clone stores a
SplitDeviceIdonsplit(for example identifierlightand instancemain).str(split)is the synthetic id{parent_id}-{identifier}-{instance}. Polls and writes usesplit.parent_idso names such aslight-sensor-enableddo not collide with the split token.spliton the model enablesStandardMixinproperties:id— the synthetic ID (entity identity), same asstr(split)update_id—split.parent_idused for API writesinstance—split.instancesplit_identifier—split.identifier(integrations that still key off the token)
Dual-channel RGB+WW lights¶
Some lights expose separate RGB and warm-white LED drivers on one metadevice. The API
uses distinct brightness functionInstance values — typically color, white,
and primary — while color controls (color-rgb, color-mode,
color-temperature) often share a null instance across the whole fixture.
These fixtures are not split into {parent}-light-color /
{parent}-light-white light clones. Splitting would drop the shared
null-instance color states and break RGB/CCT control. Channel independence is
exposed on the combined Light as:
Light.channels— per-channel brightness and on/off (color/white toggles are not cloned into Switch resources)LightController.set_state(..., channel=)— toggle or dim a single channel
Detection: both color and white brightness zones (from states, functions, or
capabilities). True multi-zone lights such as main/trim still split normally.
Integrations may expose one light entity or two (color + white) using the helpers in Lights.
Implementing a new split type¶
On the primary controller (non-split class):
Register a callback in
DEVICE_SPLIT_CALLBACKSthat returnsCallbackResponsewithsplit_devices=[...]andremove_original=....
On the split model:
Use a unique synthetic
_id, not the parent metadevice ID.Set
splitto aSplitDeviceId(AferoDevice.apply_split) and usestr(split)as the synthetic_id.Inherit
StandardMixinwhen the model needsupdate_id/instance.
Existing split patterns¶
Lights — true multi-zone
lightinstances (for examplemain/trim); parent may become a Wi-Fi metadata device. Dual-channel RGB+WW fixtures are excluded (see Dual-channel RGB+WW lights).Portable ACs —
powertoggle →bridge.switches.Exhaust fans — toggles, fan, and light instances on one unit.
Security systems — sensors extracted to
bridge.security_systems_sensors.
Pollers deduplicate by parent metadevice ID so split entities do not multiply API traffic.
State polls merge incoming rows into the cached AferoDevice by
functionClass / functionInstance so partial responses do not drop other zones.
See Bridge configuration and lifecycle.