WebSocket reference¶
Every server-pushed broadcast and every client command of the WebSocket API, generated from assets/wsapi.json (catalogue version 2.1). The envelope, subscription matching, central scoping and resume rules are described in External Client Wire Contract; authentication and connection set-up in REST & WebSocket API.
In a topic, {name} placeholders stand for one topic segment. In an argument list, a type ending in ? marks an optional argument.
Broadcasts¶
alarm_panel¶
| Name | Topic | Payload | Description |
|---|---|---|---|
alarm.countdown | alarm.panel | AlarmCountdownPayload | Server-pushed: a running exit/entry delay on an alarm zone ticked (once per second). |
alarm.health_changed | alarm.panel | AlarmHealthChangedPayload | Server-pushed: the alarm subsystem's health verdict changed (siren stop-verification, service degradations). |
alarm.journal_appended | alarm.panel | AlarmJournalAppendedPayload | Server-pushed: a new entry was appended to the alarm engine's event journal. Payload carries the entry head; clients needing full detail call GET /alarm/journal. |
alarm.notification | alarm.panel | AlarmNotificationPayload | Server-pushed: one enrolled notification output fired for an alarm — a deliberate, per-zone, mode-filtered notification signal (one-shot at fire time, never cancelled by a later silence). |
alarm.panel_changed | alarm.panel | AlarmPanelChangedPayload | Alarm-control-panel entity projection changed (state, availability, code policy, identity, or removal). |
alarm.readiness_changed | alarm.panel | AlarmReadinessChangedPayload | Server-pushed: an alarm zone's per-mode arm-readiness was recomputed (docs/alarm-concept.md §6.3). Carries the full per-mode map, not a delta. |
alarm.reminder | alarm.panel | AlarmReminderPayload | Server-pushed: an arm schedule elapsed with auto-arm off while the zone was not in the scheduled mode, so the engine notifies rather than arming (docs/alarm-concept.md §15 row 19). |
alarm.state_changed | alarm.panel | AlarmStateChangedPayload | Server-pushed: an alarm zone's arm-state-machine transitioned (docs/alarm-concept.md §5). |
alarm.triggered | alarm.panel | AlarmTriggeredPayload | Server-pushed: an alarm zone entered triggered and an incident was opened (or re-adopted after a restart / reconnect). |
alarm.walktest_progress | alarm.panel | AlarmWalkTestProgressPayload | Server-pushed: a walk-test session on an alarm zone recorded a sensor activation. |
central¶
| Name | Topic | Payload | Description |
|---|---|---|---|
central.features_changed | central.{name}.features | CentralFeaturesChangedPayload | Server-pushed: the set of features a central offers changed (its first bring-up resolved the system, or the daemon's credential gained or lost a scope). Carries the complete current set keyed by feature, each with available, reason and scope, so the UI shows or hides what the central can do without polling /system/ccu. |
central.readiness_changed | central.{name}.readiness | CentralReadinessChangedPayload | Server-pushed: a CentralUnit's readiness-gated southbound bring-up advanced a phase (waiting_for_ccu -> loading_hub -> loading_devices -> ready), pushed live so the UI distinguishes a central still initializing from one that is offline. |
central.state_changed | central.{name}.state | CentralStateChangedPayload | Server-pushed: a CentralUnit transitioned between lifecycle states (CONNECTING, READY, STOPPED, …). |
custom_data_point¶
| Name | Topic | Payload | Description |
|---|---|---|---|
custom_data_point.state_changed | device.{address}.cdps.{name} | CustomDataPointStateChangedPayload | Server-pushed: a CCU data-point change observable to a Custom-DP altered the CDP's aggregated state. SPA tiles subscribe to one CDP-scoped topic instead of N per-DP topics. |
datapoint¶
| Name | Topic | Payload | Description |
|---|---|---|---|
datapoint.optimistic_rolled_back | device.{address}.channels.{channel}.data_points.{parameter} | OptimisticRollbackPayload | Server-pushed: an optimistic write was rolled back (CCU never confirmed within TTL, or rejected it). Rides the same data_points topic as datapoint.value_changed — subscribers route by envelope type. |
datapoint.value_changed | device.{address}.channels.{channel}.data_points.{parameter} | DataPointValueChangedPayload | Server-pushed: the value of a wire data-point changed on the CCU. One topic per (device, channel, parameter) tuple. Subscribe with classify:true to receive inline category / data_point_type on the payload (default off). value is the raw CCU wire value; when the data point declares a non-trivial multiplier the payload also carries display_value, the same reading expressed in the unit the data point names. It matches the display_value on the REST data-point summary, so a client that seeds from REST and updates from here shows one consistent number. NOT filtered by onboarding release state: a device an operator has accepted but not yet released streams values here like any other, because the Config UI needs them to verify the device before releasing it. A consumer that adopts devices must therefore drop these frames for a device whose released is false — the state arrives on device.created and is lifted by device.released, both on the device's lifecycle topic. Filtering the device LIST alone is not enough. |
devices¶
| Name | Topic | Payload | Description |
|---|---|---|---|
device.availability_changed | device.{address}.lifecycle | DeviceAvailabilityChangedPayload | Server-pushed: a device's effective reachability flipped (its interface lost the connection, or the device itself reported UNREACH / STICKY_UNREACH). Rides the same device.{address}.lifecycle topic as device.created — subscribers route by envelope type. |
device.created | device.{address}.lifecycle | DeviceCreatedPayload | Server-pushed: a device the daemon did not know before was observed in the registry. Not sent for the full-inventory announcement the CCU repeats after every reconnect — only an address the device registry does not already hold is announced, so a client may treat this frame as a genuine arrival rather than filtering the fleet out of it. The source field says which kind: NEW is a pairing, REFRESH a factory-reset re-pair (the device kept its address but rebuilt its channels), MANUAL an operator accepting a device out of the deferred-creation inbox, CACHE a device restored from the persisted description cache at boot. |
device.metadata_changed | device.{address}.lifecycle | DeviceMetadataChangedPayload | Server-pushed: a device or one of its channels was renamed, or its room / function assignment changed. Rides the same device.{address}.lifecycle topic as device.created — subscribers route by envelope type. Address is always the DEVICE address even when a channel changed, because a client materialises a device's name and area as one unit and has to re-read the whole device to stay consistent. |
device.refreshed | device.{address}.lifecycle | DeviceRefreshedPayload | Server-pushed: a device's VALUES data was observed from the CCU — a pushed event or an active read (boot seed, periodic sweep, operator refresh), whether or not any value changed. Throttled by the daemon to one frame per device per two-second window, so refreshed_at may trail the device's exact latest observation by up to that window; the REST device summary's availability.LastRefreshed carries the exact value. Rides the same device.{address}.lifecycle topic as device.created — subscribers route by envelope type. |
device.released | device.{address}.lifecycle | DeviceReleasedPayload | Server-pushed: an operator finished onboarding a device — it stops being withheld from the ecosystems (MQTT and therefore Home Assistant, the Matter bridge, outbound webhooks) and may now be adopted by a consumer of this API too. Rides the same device.{address}.lifecycle topic as device.created; subscribers route by envelope type. A broadcast rather than a reply, because the consumer that needs it is precisely the one that was already connected and filtered the device out on its device.created frame: without this push it would never learn the device became adoptable. NOTE: this API does not withhold an unreleased device — the Config UI has to see it to configure it — so a consumer that adopts devices filters on the released field of device.created and this frame lifts that filter. |
device.removed | device.{address}.lifecycle | DeviceRemovedPayload | Server-pushed: the CCU reported a device deletion. The same topic carries device.created — subscribers route by envelope type. |
device.trigger | device.{address}.channels.{channel}.trigger | DeviceTriggerPayload | Server-pushed: a non-state device event fired (keypress, impulse, device error) — one topic per (device, channel). Payload event_type / parameter disambiguate which trigger fired. Distinct from datapoint.value_changed. |
hub¶
| Name | Topic | Payload | Description |
|---|---|---|---|
connectivity.changed | hub.{central}.connectivity.{interface_id} | HubConnectivityChangedPayload | Server-pushed: per-interface reachability flipped. Topic is scoped per central and per interface id. |
hub.alarm_message | hub.{central}.alarm_messages | HubCountChangedPayload | Server-pushed: the central's alarm-message list changed. Payload carries the current count; clients refresh the full list via GET /alarm-messages. |
hub.inbox_changed | hub.{central}.inbox | HubCountChangedPayload | Server-pushed: the central's inbox (pending pairing candidates) changed. Payload carries the current device count; clients refresh via GET /inbox. |
hub.install_mode_changed | hub.{central}.install_mode | InstallModeChangedPayload | Server-pushed: the CCU install-mode (pairing window) changed state. Topic is scoped per central. |
hub.metrics_changed | hub.{central}.metrics | HubMetricChangedPayload | Server-pushed: a hub metric (system health, connection latency, last-event age) was re-observed. Payload carries the metric name, value and unit. |
hub.program_changed | hub.{central}.programs.{id} | ProgramChangedPayload | Server-pushed: a CCU program's activity flag changed (CCU WebUI toggle or a client write). A program is two controls — the activity flag decides whether it reacts at all, the execution runs it once — and a deactivated program refuses the execution, so execute_available travels with the flag. Topic is scoped per central and per program-id. |
hub.program_executed | hub.{central}.programs.{id} | ProgramExecutedPayload | Server-pushed: a CCU program finished executing (Zentralenprogramm). Topic is scoped per central and per program-id. |
hub.service_message | hub.{central}.service_messages | HubCountChangedPayload | Server-pushed: the central's service-message list changed. Payload carries the current count; clients refresh the full list via GET /service-messages. |
hub.system_update_changed | hub.{central}.system_update | HubSystemUpdateChangedPayload | Server-pushed: the central's CCU firmware-/system-update state changed. Payload carries the current/available firmware, whether an update is available, and whether one is installing; clients can drop their update-status poll loop and refresh via GET /system/update if needed. |
hub.sysvar_changed | hub.{central}.sysvars.{name} | SysvarChangedPayload | Server-pushed: a CCU system variable's value changed. Topic is scoped per central and per sysvar name. |
node¶
| Name | Topic | Payload | Description |
|---|---|---|---|
node.endpoints_changed | node.endpoints_changed | NodeEndpointsChangedPayload | Server-pushed: the node reassembled its bridged endpoints (a central became ready, a device was paired or removed, the operator changed the exposure selection or ran the maintenance reassemble). Empty payload; reload GET /api/v1/node/endpoints. |
node.exposure_changed | node.exposure_changed | ExposureEvent | Server-pushed: the exposure selection changed through PUT /api/v1/node/exposure. Payload: the keys of the changed items (loom's source keys, central\|address\|channel\|kind\|key). |
node.fabric_added | node.fabric_added | FabricEvent | Server-pushed: a controller commissioned the node (post-AddNOC). Payload: the fabric's index, vendor and label — go-fabric-ui's FabricEvent, as its SSE stream (GET /api/v1/node/stream) carries it. |
node.fabric_removed | node.fabric_removed | FabricEvent | Server-pushed: a fabric was removed — by the operator (DELETE /api/v1/node/fabrics/{index}, the factory reset) or by the controller itself (RemoveFabric). Payload: the fabric index. |
node.surface_changed | node.surface_changed | SurfaceChangedEvent | Server-pushed: an assembly changed the surface the node serves on one endpoint (its ConfigurationVersion was raised). Payload: the endpoint's key, "" for the root; one event per endpoint. Reload GET /api/v1/node/surface or GET /api/v1/node/endpoints. |
node.window_closed | node.window_closed | WindowEvent | Server-pushed: the commissioning window closed (commissioned, timed out, revoked). |
node.window_opened | node.window_opened | WindowEvent | Server-pushed: a commissioning window opened (the operator's POST /api/v1/node/pairing/window, a commissioner's AdministratorCommissioning). The payload carries the discriminator only; the passcode and the pairing codes stay in the admin-gated GET /api/v1/node/pairing response. |
schedules¶
| Name | Topic | Payload | Description |
|---|---|---|---|
schedules.changed | device.{address}.lifecycle | ScheduleChangedPayload | Server-pushed: a channel's week profile changed — written through this daemon, or observed on the CCU. Carries the channel whose schedule moved so a client can re-read it; the profile body is not inlined because a week profile is large and most subscribers only need to invalidate. |
security¶
| Name | Topic | Payload | Description |
|---|---|---|---|
security.class_changed | security.state | SecurityClassChangedPayload | Server-pushed: one hazard or fault class went active or inactive, or its source set changed while it stayed active. |
security.fault_changed | security.faults | SecurityFaultChangedPayload | Server-pushed: a fault opened, cleared or was acknowledged. Carries the standing fault count after the change. |
security.notification | security.notifications | SecurityNotificationPayload | Server-pushed: one rendered report, with prose plus the i18n key and args to re-render it. A covert report (duress code, silent panic) rides this broadcast only under alarm.duress_visibility: full — the WebSocket is a local screen surface. |
security.state_changed | security.state | SecurityStateChangedPayload | Server-pushed: the folded severity of the Security & Safety domain changed. Carries the fold only; read GET /security for the detail. |
security.zone_changed | security.state | SecurityZoneChangedPayload | Server-pushed: one alarm zone's security view changed. Never fires on an installation without an alarm engine, where the domain still reports classes and faults. |
system¶
| Name | Topic | Payload | Description |
|---|---|---|---|
addon_update.state_changed | system.addon_update | AddonUpdateStatus | Server-pushed: the add-on self-updater changed state (check finished, download/install progressing, failure). Only emitted on platforms where self-update is supported. |
daemon_status.changed | system.daemon_status | DaemonStatusPayload | Server-pushed: the daemon is stopping. Emitted once during a graceful shutdown, before the servers stop, so a client can tell a stopping daemon apart from its own connection dropping — the distinction MQTT clients get from the broker's last will. A killed daemon cannot send it; detecting that stays the client's own job from its connection state. |
pairing.requests_changed | system.pairing | PairingRequestsChangedPayload | Server-pushed: the pending client-pairing list changed (a request arrived, was decided, expired or was withdrawn — ADR 0076). Carries only the pending count; the codes and request details stay behind the admin-gated GET /pairing-requests, which the tokens panel fetches on this signal. |
system.status_changed | system.{central}.status | SystemStatusChangedPayload | Server-pushed: an aggregated system-status transition (component health, callback state, degraded interfaces, …). Topic is scoped per central. |
Commands¶
alarm_panel¶
| Name | Arguments | Description |
|---|---|---|
alarm_panel.acknowledge | zone_id: string, code: string? | Acknowledge (clear) a finished incident on an alarm zone. |
alarm_panel.arm | zone_id: string, mode: string, force: boolean?, skip_delay: boolean?, bypass: array?, code: string? | Arm an alarm zone. May return synchronously as armed, or arming while counting down the mode's exit delay. |
alarm_panel.codes_create | code: object | Create an alarm code (operator). The cleartext PIN is write-only and hashed before persistence. |
alarm_panel.codes_delete | id: string | Delete an alarm code (operator). |
alarm_panel.codes_list | List alarm codes (operator). Codes are security material, so even the list is operator-gated; the argon2id hash and cleartext PIN are never returned. | |
alarm_panel.codes_update | id: string, code: object | Replace an alarm code (operator). An empty PIN keeps the stored hash. |
alarm_panel.disarm | zone_id: string, code: string? | Disarm an alarm zone. |
alarm_panel.journal | zone_id: string?, class: string?, from: string?, to: string?, limit: integer? | Query the alarm engine's event journal, newest first. |
alarm_panel.panels | List the alarm-control-panel entity projections (HA-state view incl. the master panel). | |
alarm_panel.readiness | zone_id: string | Return the per-mode arm-readiness of an alarm zone. |
alarm_panel.silence | zone_id: string, code: string? | Silence the active incident on an alarm zone without disarming. |
alarm_panel.silence_all | Silence the active incident on every alarm zone at once. | |
alarm_panel.state | Return the live status of every alarm zone: state, mode, bypassed sensors, active incident, running countdown, per-mode readiness, and walk-test-active flag. | |
alarm_panel.walktest_status | zone_id: string | Return the live status of a walk-test session on an alarm zone. |
alarms¶
| Name | Arguments | Description |
|---|---|---|
alarm_messages.ack | id: string, central_name: string? | Acknowledge (clear) a single alarm message by id. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
alarm_messages.ack_all | central_name: string? | Acknowledge (clear) every active alarm message in one pass. The response carries the number acknowledged. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
alarm_messages.list | central_name: string? | List all active CCU alarm messages. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
service_messages.ack | id: string, central_name: string? | Acknowledge (clear) a single service message by id. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
service_messages.ack_all | central_name: string? | Acknowledge (clear) every quittable service message in one pass. The response carries the number acknowledged. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
service_messages.disable | id: string | Disable (permanently suppress) a single service message by id. Resolves the message's channel + service parameter and suppresses it on the CCU via Interface.suppressServiceMessages until cleared via service_messages.unsuppress. |
service_messages.list | central_name: string? | List all active CCU service messages (UNREACH, low-battery, config-pending, etc.). Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
service_messages.suppressed | List the permanently-suppressed service-message channel parameters across every central. Reconciled against each CCU's live Interface.getSuppressedServiceMessages. | |
service_messages.unsuppress | channel: string, parameter: string?, interface: string? | Clear a permanent service-message suppression. Params: channel (required), parameter (empty = all parameters of the channel), interface (optional, resolved from the stored suppression). |
backup¶
| Name | Arguments | Description |
|---|---|---|
backup.status | central_name: string? | Return the current status of a running or last-completed CCU backup operation. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
backup.trigger | central_name: string? | Trigger a CCU configuration backup asynchronously. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
backups.trigger | central_name: string | Trigger the create-and-download backup flow for exactly the named central (multi-CCU-correct counterpart to backup.trigger, which always targets the first registered central). Returns the backup/job id. |
calc_dp¶
| Name | Arguments | Description |
|---|---|---|
calc_dp.get | device: string, channel_no: integer?, name: string | Return a single calculated data point by device address, channel number, and name. |
calc_dp.list | device: string?, channel_no: integer? | List all calculated data points for all devices (or a single device / channel when params supplied). |
ccu¶
| Name | Arguments | Description |
|---|---|---|
ccu.cache_clear | central: string?, device: string?, interface: string?, kind: string? | Clear CCU-derivable caches scoped by kind (global/central/interface/device) and trigger a re-pull. Omitting kind defaults to global. Mirrors Python ws_clear_cache (websocket_api.py:1885). |
ccu.device_statistics | Return per-interface device statistics: total, unreachable, and firmware-updatable counts plus grand totals. Mirrors Python ws_get_device_statistics (V8-N11). | |
ccu.get_hub_data | Return service-message count and alarm-message count from hub data points. Mirrors Python ws_get_hub_data (websocket_api.py:2052). | |
ccu.get_rssi_info | Return per-device RF reception strength (RSSI_DEVICE / RSSI_PEER in dBm), battery state (battery_level, low_battery), and reachability, read from the device model's maintenance channel across every central. Works for HmIP and BidCos alike; only devices that report an RSSI reading are listed. | |
ccu.get_signal_quality | Return RSSI, reachability, and low-battery state for every known device. Mirrors Python ws_get_signal_quality (websocket_api.py:2158). | |
ccu.reload_channel_config | channel_address: string | Trigger a CCU-side channel-config reload for the addressed channel: re-pull paramset descriptions (VALUES/MASTER/LINK) + MASTER values and refresh the channel's data points. Mirrors Channel.reload_channel_config (model/device.py:1448). |
ccu.reload_device_config | device_address: string | Trigger a CCU-side device-config reload for the addressed device. Mirrors Python ws_panel_reload_device_config (websocket_api.py:2285). Closes parity_audit gap L-7002. |
ccu.throttle_stats | Return per-interface command-throttle diagnostics (in_flight, waiting, burst_downgrades, waited_for_burst_slot). Mirrors Python ws_get_command_throttle_stats (V8-N9). |
cdp¶
| Name | Arguments | Description |
|---|---|---|
cdp.get | device: string, name: string | Return a single custom data point by device address and name. |
cdp.invoke | device: string, name: string, operation: string, params: object?, priority: string? | Invoke an operation on a custom data point (turn_on, set_temperature, open, …). Operation arguments use the units and scales a Home Assistant client expects, matching what the custom-data-point STATE reports — not the CCU wire values, which live on the data-point plane. Concretely for a colour light: set_color takes {hue, saturation} with hue in degrees 0..360 and saturation 0..100, the same scale state.color.s reports back; the daemon converts to the wire SATURATION fraction 0..1 itself. Read and write therefore need no conversion in either direction — scaling state.color.s before sending it back is the mistake this note exists to prevent. |
cdp.list | device: string? | List all custom data points of all devices (or a single device when 'device' param is supplied). |
central¶
| Name | Arguments | Description |
|---|---|---|
central.connectivity | Report per-interface connectivity details for all configured centrals. | |
central.create_links | address: string?, channel: string?, device_address: string? | Enable CCU click-event forwarding. Without channel every press-event channel of the device is switched on; with channel (a channel address) only that single channel is touched. Mirrors Python create_central_links. |
central.info | Return identity and version information for the connected CCU. | |
central.links_status | address: string?, device_address: string? | Report whether a device supports central links, how many channels are eligible, and which channels (address, number, eligible) can drive central click events. |
central.reconcile | Kick off an ad-hoc reconciliation pass against the CCU device registry. | |
central.remove_links | address: string?, channel: string?, device_address: string? | Tear down CCU click-event forwarding. Without channel the whole device is switched off; with channel (a channel address) only that single channel is touched. Mirrors Python remove_central_links. |
central.system_health | Return a combined system-health snapshot from the CCU's perspective. |
change_history¶
| Name | Arguments | Description |
|---|---|---|
change_history.clear | Clear (truncate) the persisted paramset-write history log. Mirrors Python ws_clear_change_history (V8-N16). | |
change_history.list | limit: integer?, channel_address: string? | List recent paramset-write history entries, optionally filtered by channel address. |
config¶
| Name | Arguments | Description |
|---|---|---|
config.reload_channel_config | channel_address: string | Trigger a CCU-side channel-config reload for the addressed channel: re-pull paramset descriptions (VALUES/MASTER/LINK) + MASTER values and refresh the channel's data points. Mirrors Channel.reload_channel_config (model/device.py:1448). |
config.reload_device_config | device_address: string | Trigger a CCU-side device-config reload for the addressed device. Mirrors Python ws_reload_device_config (websocket_api.py:1735). Closes parity_audit gap L-7002. |
config.session.changes | central_name: string?, channel_address: string, paramset_key: string | Return the current pending changes for an open config session. channel_address and paramset_key identify the session, the same pair config.session.open was called with. |
config.session.discard | central_name: string?, channel_address: string, paramset_key: string | Discard all pending changes and close the config session. channel_address and paramset_key identify the session, the same pair config.session.open was called with. |
config.session.open | central_name: string?, channel_address: string, paramset_key: string | Open a config session for a channel/paramset pair and return its initial values. |
config.session.redo | central_name: string?, channel_address: string, paramset_key: string | Re-apply the most recently undone change in the open config session. channel_address and paramset_key identify the session, the same pair config.session.open was called with. |
config.session.save | central_name: string?, channel_address: string, paramset_key: string | Write the pending changes of the open config session to the CCU and close the session. channel_address and paramset_key identify the session, the same pair config.session.open was called with. |
config.session.set | central_name: string?, channel_address: string, paramset_key: string, parameter: string?, value: any | Stage a single parameter change into the open config session. |
config.session.undo | central_name: string?, channel_address: string, paramset_key: string | Undo the most recent staged change in the open config session. channel_address and paramset_key identify the session, the same pair config.session.open was called with. |
devices¶
| Name | Arguments | Description |
|---|---|---|
device.install_mode | address: string, duration_seconds: integer? | Put a single device into pairing install-mode for a given duration. |
device.rename | address: string, name: string, include_channels: boolean? | Rename a device on the CCU. When include_channels is true every channel is renamed along with the '<name>:<channelNo>' pattern. |
device.rename_channel | address: string, channel: integer, name: string | Rename a single channel on the CCU. |
device.replace | address: string, old_address: string, central: string? | Swap a paired device for a new one. The CCU migrates direct links, teams and ReGa references; the old device is unpaired. Supported on BidCos-RF and BidCos-Wired only. |
device.replace_candidates | address: string, central: string? | List the already-paired devices the new (inbox) device may replace. Supported on BidCos-RF and BidCos-Wired only. |
device.restore_config | address: string | Re-transmit the centrally stored configuration (all channels' MASTER paramsets + link peerings) to a device after a factory reset. Supported on HmIP-RF and BidCos-RF only. |
device.set_channel_functions | address: string, channel: integer, functions: array | Replace a single channel's function (Gewerk) assignments. An empty array clears the set. |
device.set_channel_rooms | address: string, channel: integer, rooms: array | Replace a single channel's room assignments. An empty array clears the set. |
device.set_team | address: string, channel: integer, team: string? | Assign a channel to a team (e.g. smoke-detector teaming). A null/empty team resets to the channel's default team. BidCos-RF and HmIP-RF only. |
device.team_candidates | address: string, channel: integer | List the team channels a channel may be assigned to (same team tag). Supported on BidCos-RF and HmIP-RF only. |
device.test | address: string | Run the CCU's per-device communication / function test (radio test frame + ACK). Blocks until complete or the poll window elapses. Radio interfaces only. |
devices.export_definition | address: string | Export a device definition as an aiohomematic-compatible zip (device + paramset descriptions, anonymised). Returns model, filename and base64-encoded zip data. |
devices.get | address: string | Return the full detail record for a single device by address. |
devices.list | Return a summary list of all registered devices sorted by address. |
firmware¶
| Name | Arguments | Description |
|---|---|---|
firmware.info | central_name: string? | Report the current and available firmware versions and pending update status. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
firmware.refresh | Force-refresh the firmware cache from the CCU (re-fetch available firmware metadata). Mirrors Python ws_refresh_firmware_data (V8-N13). | |
firmware.update | central_name: string? | Trigger the CCU firmware update and reboot sequence. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
groups¶
| Name | Arguments | Description |
|---|---|---|
groups.create | type_id: string, name: string, forbid_single_operation: boolean?, members: array?, central: string? | Create a heating group via the CCU jpages proxy (ADR 0055, GR02). Admin-gated. central selects the target CCU (optional when only one is configured). Returns the created group. |
groups.delete | id: integer, central: string? | Delete a heating group by id via the jpages delete path. Admin-gated. |
groups.list | central: string? | List Homematic heating groups (HmIP / BidCos), grouped by central, read from each CCU's groups.gson via CCU.getHeatingGroupList. Read-only; omit central to aggregate over all centrals or set it to scope to one. Creating/editing/deleting groups runs through the CCU jpages proxy (ADR 0055) and is a separate surface. |
groups.suitable_members | type_id: string, central: string? | The devices assignable to a group of the given type (assignable + leftover buckets). Read. |
groups.types | central: string? | The group types a new group can be created as. Read. |
groups.update | id: integer, name: string, forbid_single_operation: boolean?, members: array?, central: string? | Edit an existing heating group (name, members, operate-only-via-group flag) via the jpages save path. Admin-gated. |
inbox¶
| Name | Arguments | Description |
|---|---|---|
inbox.accept | device_address: string, name: string?, include_channels: boolean?, rooms: array?, functions: array? | Promote a paired-but-unconfigured inbox device into the active device set. A device parked by delay_new_device_creation is materialised at the same time. Optional first-time configuration (name, include_channels, rooms, functions) is applied best-effort right after the accept; omit them to only accept. |
inbox.list | central_name: string? | List devices waiting for acceptance: those the CCU has seen in pairing mode and, when delay_new_device_creation is enabled, those this daemon parked (flagged pending_creation). Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
incidents¶
| Name | Arguments | Description |
|---|---|---|
incidents.clear | Clear all entries from the incident store. Mirrors Python ws_clear_incidents (V8-N17). | |
incidents.get | Alias for incidents.list kept for Python ws_get_incidents name parity (L12). Returns the same payload as incidents.list. | |
incidents.list | Return all stored diagnostic incidents ordered by last_seen descending. Mirrors Python ws_get_incidents (L12). |
install_mode¶
| Name | Arguments | Description |
|---|---|---|
install_mode.disable | interface_id: string, central_name: string? | Close the pairing window for the named interface. interface_id accepts either the bare interface type ("HmIP-RF") or the composite <central>-<interface> id other commands publish (e.g. devices.list, ccu.get_signal_quality); both resolve to the same pairing window. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
install_mode.enable | interface_id: string, duration_seconds: integer, sgtin: string?, key: string?, central_name: string? | Open the pairing window for the named interface for a given duration in seconds. Passing sgtin + key (together) requests the keyserver-less HmIP LOCAL teach-in restricted to that one device. interface_id accepts either the bare interface type ("HmIP-RF") or the composite <central>-<interface> id other commands publish (e.g. devices.list, ccu.get_signal_quality); both resolve to the same pairing window. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
install_mode.search | interface_id: string, central_name: string?, central: string? | Scan the wired bus (BidCos-Wired) for new devices; returns the count found (they join the inbox for acceptance). Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. central is accepted as a deprecated alias for central_name. |
install_mode.status | central_name: string? | Report the current pairing-mode state per interface. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
links¶
| Name | Arguments | Description |
|---|---|---|
links.activate_paramset | receiver_channel_address: string, sender_channel_address: string, long_press: boolean | Test a direct link at the device: trigger the receiver's LINK paramset for the sender (short or long keypress). Physically actuates the receiver. |
links.add | sender: string, receiver: string, name: string?, description: string? | Create a new direct link between a sender and a receiver channel. |
links.apply_profile | interface_id: string?, sender_channel_address: string, receiver_channel_address: string, profile_id: integer, edit_token: string | Write a link profile to the LINK paramset of (receiver_channel_address, sender_channel_address). The value set is the profile's fixed constraint values plus the declared defaults of its loose constraints; a loose constraint carrying no default is not written, so the device keeps its current value for it. One consequence is worth knowing before building on this: applying a profile does not guarantee that a later links.get_profiles reports it as the active one, because the parameters that distinguish sibling profiles are frequently loose without a default. This is a configuration write and requires the per-resource edit lock: pass edit_token issued by POST /sessions/edit with key channel:{receiver_channel_address}:LINK:{sender_channel_address}, or the write is rejected with a 'locked' command error. |
links.get_form_schema | interface_id: string, sender_channel_address: string, receiver_channel_address: string | Return the form schema (descriptions + current values) for a link paramset between sender and receiver. Mirrors Python ws_get_link_form_schema (websocket_api.py:1057). |
links.get_paramset | address: string, peer_address: string | Read the LINK paramset on the given channel keyed by the peer channel address. Mirrors Python ws_get_link_paramset (websocket_api.py:1313). Closes parity_audit gap G-03. |
links.get_profiles | interface_id: string?, sender_channel_address: string, receiver_channel_address: string, locale: string? | Return available easymode profiles for a link between sender and receiver channel types. Mirrors Python ws_get_link_profiles (websocket_api.py:1123). Stub until Phase-11. |
links.linkable_channels | device_address: string | Return the channels eligible to be linked against a given device. |
links.list | device_address: string | List all direct links a device participates in. |
links.list_all | central: string? | Global direct-link overview across all centrals (or one when 'central' is set). Each link carries its owning central_name and interface_id. |
links.put_paramset | address: string, peer_address: string, parameters: object, edit_token: string | Write values to the LINK paramset on the given channel keyed by the peer channel address. This is a configuration write and is gated behind the same per-resource edit lock as the REST route: pass edit_token issued by POST /sessions/edit with key channel:{address}:LINK:{peer_address}, or the write is rejected with a 'locked' command error. The lock carries the peer because the paramset does — two links on one channel are two resources. |
links.remove | sender: string, receiver: string | Delete an existing direct link between a sender and a receiver channel. |
links.set_info | sender: string, receiver: string, name: string?, description: string? | Change the name and/or description of an existing direct link. |
paramsets¶
| Name | Arguments | Description |
|---|---|---|
paramset.copy | source_channel_address: string, target_channel_address: string, paramset_key: string? | Copy a paramset (VALUES or MASTER) from a source channel to a target channel by reading + writing the values. Distinct from links.copy (peer-to-peer link-entry copy). Mirrors Python ws_copy_paramset (websocket_api.py:916). Closes parity_audit gap L-7015. |
paramset.description | channel_address: string, paramset_key: string?, central_name: string? | Return the parameter descriptors for a channel/paramset pair. |
paramset.determine | interface_id: string, channel_address: string, parameter_id: string | Auto-detect a parameter value from the device via determine_parameter. Mirrors Python ws_determine_parameter (websocket_api.py:2556). Stub until Phase-11. |
paramset.form_schema | address: string, channel_no: integer, paramset: string?, locale: string?, peer: string? | Return the form schema (descriptions + grouping) for a channel paramset. Mirrors Python ws_get_form_schema (websocket_api.py:252). Closes parity_audit gap G-27. |
paramset.get | central_name: string?, channel_address: string, paramset_key: string | Return the current values for a channel/paramset pair. |
paramset.put | channel_address: string, paramset_key: string, values: object, edit_token: string? | Write a paramset directly to the CCU without a session (non-transactional from a daemon-session perspective, but atomic on the wire: forwarded as one setParamsetValues XML-RPC call so the CCU applies all values together or none). Returns {written: N} on success; for MASTER the daemon additionally re-reads the stored paramset and reports readback_divergences (every parameter whose stored value differs from the sent one) and readback_error (the post-write read failed; divergences unknown) — an interface process may answer ok and still drop, clamp or coerce a value, so an empty readback_divergences is the only trustworthy full acknowledgement. paramset_key accepts MASTER and VALUES only. LINK is refused here: a LINK paramset belongs to a channel PAIR and is addressed by its partner, which this command carries no argument for — use links.put_paramset with address and peer_address. MASTER writes are configuration changes gated behind the per-resource edit lock: pass edit_token (issued by POST /sessions/edit with key channel:{channel_address}:MASTER) or the write is rejected with a 'locked' command error. VALUES writes are ungated. |
programs¶
| Name | Arguments | Description |
|---|---|---|
programs.delete | id: string, central_name: string? | Delete a CCU program by id. Removes the program from the CCU (dom.DeleteObject) and drops it from the hub mirror. Admin-gated, mirroring the REST DELETE /programs/{id} route (deletion is irreversible). Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
programs.execute | id: string, check_conditions: boolean?, central_name: string? | Execute a CCU program by id. When check_conditions is true the CCU evaluates the program's "if" condition and runs the program only when it is satisfied; when false (the default) the program runs unconditionally. executed reports whether the program actually ran — always true for an unconditional run, false for a condition-checked run whose condition was not met. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
programs.list | include_internal: boolean?, central_name: string? | List all CCU programs. Each entry carries optional channel / device_address fields when the program is associated with a device (device identifier in the program name); absent fields mean the entity belongs on the central hub card. include_internal overrides whether internal (Tmp_*) programs are listed; when omitted the central's include_internal_programs config default applies. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
recording¶
| Name | Arguments | Description |
|---|---|---|
recording.start | Start the diagnostic RPC session recorder across all centrals (clears prior data). Mirrors Python record_session (start). | |
recording.status | Report whether the diagnostic RPC session recorder is currently capturing. | |
recording.stop | Stop the diagnostic RPC session recorder across all centrals. Mirrors Python record_session (stop). |
schedules¶
| Name | Arguments | Description |
|---|---|---|
schedules.active_profile.set | channel_address: string, profile_index: integer | Select the active climate profile (P1..P6) on a thermostat channel. profile_index is 1-based here (P1 is 1); the REST field active_profile_index is 0-based, so add 1 when feeding one to the other. |
schedules.climate.copy_profile | source_channel_address: string, source_profile: number, target_channel_address: string, target_profile: number | Copy a single climate profile from a source channel/profile to a target channel/profile. Mirrors Python copy_schedule_profile. |
schedules.climate.get | channel_address: string | Read the active climate week-program for a thermostat channel. |
schedules.climate.set | channel_address: string, profile: object | Write a climate week-program back to a thermostat channel. The result carries "corrections" only when the stored schedule differs from the submitted one: a time with an hour of 24 and a non-zero minute is stored as 23:55, matching the CCU's own climate editor. Each entry names profile, weekday, period (0-based), field (start_time|end_time), requested and applied. |
schedules.copy | source_device_address: string, target_device_address: string | Copy the whole week schedule from a source device to a target device (channels auto-resolved). Mirrors Python copy_schedule. |
schedules.device.active_profile.set | device_address: string, profile: string | Select the active climate profile by name (e.g. P1..P6) on the resolved schedule channel of a device. |
schedules.device.get | device_address: string | Read the unified schedule DTO for a device, resolving the correct channel automatically. |
schedules.device.set | device_address: string, profile: object | Write a schedule back to the resolved schedule channel of a device. Carries the same optional "corrections" list as schedules.climate.set. |
schedules.list_devices | List all devices that expose a weekly schedule (week-profile data point). Mirrors Python ws_list_schedule_devices (websocket_api.py:1491). | |
schedules.set_enabled | device_address: string, enabled: boolean, channel_key: string? | Enable or disable the weekly program on a device. Mirrors Python ws_set_schedule_enabled (websocket_api.py:1698). Stub until Phase-11. |
system¶
| Name | Arguments | Description |
|---|---|---|
addon_update.check | Kick a release check of the CCU add-on self-updater (ADR 0057). Fire-and-forget: progress and outcome arrive on addon_update.state_changed. Unregistered (unknown command) on platforms without the self-update capability. | |
addon_update.install | Start the verified download + firmware install of the latest CCU add-on release (ADR 0057). Fire-and-forget: the daemon restarts on success; failures surface on addon_update.state_changed. Unregistered on platforms without the self-update capability. | |
system.commands | Return the list of all registered WS command names (introspection endpoint). | |
system.health | Return a health snapshot including overall status, score, and per-component details. | |
system.user_permissions | Return the effective role and permissions for the authenticated user. Mirrors Python ws_get_user_permissions (websocket_api.py:2727). |
sysvars¶
| Name | Arguments | Description |
|---|---|---|
sysvars.fetch | central_name: string | Force re-pull the CCU system-variable catalogue into the hub model. Optional central_name scopes the refresh to one CCU. Mirrors Python fetch_system_variables. |
sysvars.list | central_name: string? | List all CCU system variables. Each entry carries optional channel / device_address fields when the variable is associated with a device (explicit CCU channel assignment or a device identifier in the name); absent fields mean the entity belongs on the central hub card. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
sysvars.set | name: string, value: any, central_name: string? | Update the value of a CCU system variable by name. Targets one CCU: central_name selects it, and may be omitted only when a single central is configured — with several the command is rejected rather than resolved against an arbitrary one. |
sysvars.usage | name: string, central_name: string | List the CCU programs that reference a system variable (native DPEnumUsagePrograms). Optional central_name disambiguates across CCUs. |
taxonomy¶
| Name | Arguments | Description |
|---|---|---|
taxonomy.list | central: string? | Every central's taxonomy trees — rooms, functions and further enums — with each node's path, empty nodes included. Optional central narrows to one; an unknown central is not_found. Same answer as REST GET /taxonomy. |
taxonomy.node_create | central: string?, enum: string, parent_path: string?, name: string | Create a taxonomy node below parent_path (absent or empty: a root node). A nested node needs the central's taxonomy.tree feature; a CCU's rooms and functions are flat. Returns {path}. Operator-gated. |
taxonomy.node_delete | central: string?, enum: string, path: string | Delete a taxonomy node and its subtree; the addresses assigned to them keep existing and lose the assignment. Operator-gated. |
taxonomy.node_update | central: string?, enum: string, path: string, name: string?, parent_path: string?, position: integer? | Rename a taxonomy node (name) and/or move it below parent_path (empty string: the root) at position. Moving needs taxonomy.tree. Operator-gated. |