def async_on_node_ready(node: ZwaveNode) -> None: """Handle node ready event.""" LOGGER.debug("Processing node %s", node) # register (or update) node in device registry register_node_in_dev_reg(hass, entry, dev_reg, client, node) # run discovery on all node values and create/update entities for disc_info in async_discover_values(node): LOGGER.debug("Discovered entity: %s", disc_info) # This migration logic was added in 2021.3 to handle a breaking change to # the value_id format. Some time in the future, this call (as well as the # helper functions) can be removed. async_migrate_discovered_value(ent_reg, client, disc_info) async_dispatcher_send( hass, f"{DOMAIN}_{entry.entry_id}_add_{disc_info.platform}", disc_info) # add listener for stateless node value notification events node.on( "value notification", lambda event: async_on_value_notification(event[ "value_notification"]), ) # add listener for stateless node notification events node.on("notification", lambda event: async_on_notification(event["notification"]))
async def async_on_node_ready(node: ZwaveNode) -> None: """Handle node ready event.""" LOGGER.debug("Processing node %s", node) # register (or update) node in device registry device = register_node_in_dev_reg( hass, entry, dev_reg, client, node, remove_device ) # We only want to create the defaultdict once, even on reinterviews if device.id not in registered_unique_ids: registered_unique_ids[device.id] = defaultdict(set) value_updates_disc_info: dict[str, ZwaveDiscoveryInfo] = {} # run discovery on all node values and create/update entities await asyncio.gather( *( async_handle_discovery_info(device, disc_info, value_updates_disc_info) for disc_info in async_discover_node_values( node, device, discovered_value_ids ) ) ) # add listeners to handle new values that get added later for event in ("value added", "value updated", "metadata updated"): entry.async_on_unload( node.on( event, lambda event: hass.async_create_task( async_on_value_added(value_updates_disc_info, event["value"]) ), ) ) # add listener for stateless node value notification events entry.async_on_unload( node.on( "value notification", lambda event: async_on_value_notification(event["value_notification"]), ) ) # add listener for stateless node notification events entry.async_on_unload( node.on( "notification", lambda event: async_on_notification(event["notification"]), ) )
async def websocket_subscribe_node_statistics( hass: HomeAssistant, connection: ActiveConnection, msg: dict, node: Node, ) -> None: """Subsribe to the statistics updates for a node.""" @callback def async_cleanup() -> None: """Remove signal listeners.""" for unsub in unsubs: unsub() @callback def forward_stats(event: dict) -> None: statistics: NodeStatistics = event["statistics_updated"] connection.send_message( websocket_api.event_message( msg[ID], { "event": event["event"], "source": "node", "node_id": node.node_id, **_get_node_statistics_dict(statistics), }, )) msg[DATA_UNSUBSCRIBE] = unsubs = [ node.on("statistics updated", forward_stats) ] connection.subscriptions[msg["id"]] = async_cleanup connection.send_result(msg[ID], _get_node_statistics_dict(node.statistics))
def async_on_node_ready(node: ZwaveNode) -> None: """Handle node ready event.""" LOGGER.debug("Processing node %s", node) # register (or update) node in device registry register_node_in_dev_reg(hass, entry, dev_reg, client, node) # run discovery on all node values and create/update entities for disc_info in async_discover_values(node): LOGGER.debug("Discovered entity: %s", disc_info) async_dispatcher_send( hass, f"{DOMAIN}_{entry.entry_id}_add_{disc_info.platform}", disc_info) # add listener for stateless node value notification events node.on( "value notification", lambda event: async_on_value_notification(event[ "value_notification"]), ) # add listener for stateless node notification events node.on("notification", lambda event: async_on_notification(event["notification"]))
async def websocket_subscribe_firmware_update_status( hass: HomeAssistant, connection: ActiveConnection, msg: dict, node: Node, ) -> None: """Subscribe to the status of a firmware update.""" @callback def async_cleanup() -> None: """Remove signal listeners.""" for unsub in unsubs: unsub() @callback def forward_progress(event: dict) -> None: progress: FirmwareUpdateProgress = event["firmware_update_progress"] connection.send_message( websocket_api.event_message( msg[ID], { "event": event["event"], **_get_firmware_update_progress_dict(progress), }, ) ) @callback def forward_finished(event: dict) -> None: finished: FirmwareUpdateFinished = event["firmware_update_finished"] connection.send_message( websocket_api.event_message( msg[ID], { "event": event["event"], "status": finished.status, "wait_time": finished.wait_time, }, ) ) msg[DATA_UNSUBSCRIBE] = unsubs = [ node.on("firmware update progress", forward_progress), node.on("firmware update finished", forward_finished), ] connection.subscriptions[msg["id"]] = async_cleanup progress = node.firmware_update_progress connection.send_result( msg[ID], _get_firmware_update_progress_dict(progress) if progress else None )
async def websocket_refresh_node_info( hass: HomeAssistant, connection: ActiveConnection, msg: dict, node: Node, ) -> None: """Re-interview a node.""" @callback def async_cleanup() -> None: """Remove signal listeners.""" for unsub in unsubs: unsub() @callback def forward_event(event: dict) -> None: connection.send_message( websocket_api.event_message(msg[ID], {"event": event["event"]}) ) @callback def forward_stage(event: dict) -> None: connection.send_message( websocket_api.event_message( msg[ID], {"event": event["event"], "stage": event["stageName"]} ) ) connection.subscriptions[msg["id"]] = async_cleanup msg[DATA_UNSUBSCRIBE] = unsubs = [ node.on("interview started", forward_event), node.on("interview completed", forward_event), node.on("interview stage completed", forward_stage), node.on("interview failed", forward_event), ] result = await node.async_refresh_info() connection.send_result(msg[ID], result)
async def websocket_subscribe_firmware_update_status( opp: OpenPeerPower, connection: ActiveConnection, msg: dict, node: Node, ) -> None: """Subsribe to the status of a firmware update.""" @callback def async_cleanup() -> None: """Remove signal listeners.""" for unsub in unsubs: unsub() @callback def forward_progress(event: dict) -> None: progress: FirmwareUpdateProgress = event["firmware_update_progress"] connection.send_message( websocket_api.event_message( msg[ID], { "event": event["event"], "sent_fragments": progress.sent_fragments, "total_fragments": progress.total_fragments, }, ) ) @callback def forward_finished(event: dict) -> None: finished: FirmwareUpdateFinished = event["firmware_update_finished"] connection.send_message( websocket_api.event_message( msg[ID], { "event": event["event"], "status": finished.status, "wait_time": finished.wait_time, }, ) ) unsubs = [ node.on("firmware update progress", forward_progress), node.on("firmware update finished", forward_finished), ] connection.subscriptions[msg["id"]] = async_cleanup connection.send_result(msg[ID])
async def async_on_node_ready(node: ZwaveNode) -> None: """Handle node ready event.""" LOGGER.debug("Processing node %s", node) platform_setup_tasks = entry_opp_data[DATA_PLATFORM_SETUP] # register (or update) node in device registry device = register_node_in_dev_reg(opp, entry, dev_reg, client, node) # We only want to create the defaultdict once, even on reinterviews if device.id not in registered_unique_ids: registered_unique_ids[device.id] = defaultdict(set) value_updates_disc_info = [] # run discovery on all node values and create/update entities for disc_info in async_discover_values(node): platform = disc_info.platform # This migration logic was added in 2021.3 to handle a breaking change to # the value_id format. Some time in the future, this call (as well as the # helper functions) can be removed. async_migrate_discovered_value( opp, ent_reg, registered_unique_ids[device.id][platform], device, client, disc_info, ) if platform not in platform_setup_tasks: platform_setup_tasks[platform] = opp.async_create_task( opp.config_entries.async_forward_entry_setup( entry, platform)) await platform_setup_tasks[platform] LOGGER.debug("Discovered entity: %s", disc_info) async_dispatcher_send(opp, f"{DOMAIN}_{entry.entry_id}_add_{platform}", disc_info) # Capture discovery info for values we want to watch for updates if disc_info.assumed_state: value_updates_disc_info.append(disc_info) # add listener for value updated events if necessary if value_updates_disc_info: unsubscribe_callbacks.append( node.on( "value updated", lambda event: async_on_value_updated( value_updates_disc_info, event["value"]), )) # add listener for stateless node value notification events unsubscribe_callbacks.append( node.on( "value notification", lambda event: async_on_value_notification(event[ "value_notification"]), )) # add listener for stateless node notification events unsubscribe_callbacks.append( node.on( "notification", lambda event: async_on_notification(event["notification"]), ))
def async_on_node_ready(node: ZwaveNode) -> None: """Handle node ready event.""" LOGGER.debug("Processing node %s", node) # register (or update) node in device registry register_node_in_dev_reg(hass, entry, dev_reg, client, node) # run discovery on all node values and create/update entities for disc_info in async_discover_values(node): LOGGER.debug("Discovered entity: %s", disc_info) # This migration logic was added in 2021.3 to handle a breaking change to # the value_id format. Some time in the future, this code block # (as well as get_old_value_id helper and migrate_entity closure) can be # removed. value_ids = [ # 2021.2.* format get_old_value_id(disc_info.primary_value), # 2021.3.0b0 format disc_info.primary_value.value_id, ] new_unique_id = get_unique_id( client.driver.controller.home_id, disc_info.primary_value.value_id, ) for value_id in value_ids: old_unique_id = get_unique_id( client.driver.controller.home_id, f"{disc_info.primary_value.node.node_id}.{value_id}", ) # Most entities have the same ID format, but notification binary sensors # have a state key in their ID so we need to handle them differently if (disc_info.platform == "binary_sensor" and disc_info.platform_hint == "notification"): for state_key in disc_info.primary_value.metadata.states: # ignore idle key (0) if state_key == "0": continue migrate_entity( disc_info.platform, f"{old_unique_id}.{state_key}", f"{new_unique_id}.{state_key}", ) # Once we've iterated through all state keys, we can move on to the # next item continue migrate_entity(disc_info.platform, old_unique_id, new_unique_id) async_dispatcher_send( hass, f"{DOMAIN}_{entry.entry_id}_add_{disc_info.platform}", disc_info) # add listener for stateless node value notification events node.on( "value notification", lambda event: async_on_value_notification(event[ "value_notification"]), ) # add listener for stateless node notification events node.on("notification", lambda event: async_on_notification(event["notification"]))