def websocket_get_themes(hass: HomeAssistant, connection: ActiveConnection, msg: dict) -> None: """Handle get themes command.""" if hass.config.safe_mode: connection.send_message( websocket_api.result_message( msg["id"], { "themes": { "safe_mode": { "primary-color": "#db4437", "accent-color": "#ffca28", } }, "default_theme": "safe_mode", }, )) return connection.send_message( websocket_api.result_message( msg["id"], { "themes": hass.data[DATA_THEMES], "default_theme": hass.data[DATA_DEFAULT_THEME], "default_dark_theme": hass.data.get(DATA_DEFAULT_DARK_THEME), }, ))
async def _async_events_consumer( subscriptions_setup_complete_time: dt, connection: ActiveConnection, msg_id: int, stream_queue: asyncio.Queue[Event], event_processor: EventProcessor, ) -> None: """Stream events from the queue.""" event_processor.switch_to_live() while True: events: list[Event] = [await stream_queue.get()] # If the event is older than the last db # event we already sent it so we skip it. if events[0].time_fired <= subscriptions_setup_complete_time: continue # We sleep for the EVENT_COALESCE_TIME so # we can group events together to minimize # the number of websocket messages when the # system is overloaded with an event storm await asyncio.sleep(EVENT_COALESCE_TIME) while not stream_queue.empty(): events.append(stream_queue.get_nowait()) if logbook_events := event_processor.humanify( async_event_to_row(e) for e in events ): connection.send_message( JSON_DUMP( messages.event_message( msg_id, {"events": logbook_events}, ) ) )
async def websocket_subscribe(hass: HomeAssistant, connection: ActiveConnection, msg: dict): """Subscribe to supervisor events.""" @callback def forward_messages(data): """Forward events to websocket.""" connection.send_message(websocket_api.event_message(msg[WS_ID], data)) connection.subscriptions[msg[WS_ID]] = async_dispatcher_connect( hass, EVENT_SUPERVISOR_EVENT, forward_messages) connection.send_message(websocket_api.result_message(msg[WS_ID]))
def websocket_get_panels(hass: HomeAssistant, connection: ActiveConnection, msg: dict) -> None: """Handle get panels command.""" user_is_admin = connection.user.is_admin panels = { panel_key: panel.to_response() for panel_key, panel in connection.hass.data[DATA_PANELS].items() if user_is_admin or not panel.require_admin } connection.send_message(websocket_api.result_message(msg["id"], panels))
async def websocket_get_translations(hass: HomeAssistant, connection: ActiveConnection, msg: dict) -> None: """Handle get translations command.""" resources = await async_get_translations( hass, msg["language"], msg["category"], msg.get("integration"), msg.get("config_flow"), ) connection.send_message( websocket_api.result_message(msg["id"], {"resources": resources}))
async def websocket_get_group(hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]) -> None: """Get ZHA group.""" zha_gateway: ZHAGateway = hass.data[DATA_ZHA][DATA_ZHA_GATEWAY] group_id: int = msg[GROUP_ID] if not (zha_group := zha_gateway.groups.get(group_id)): connection.send_message( websocket_api.error_message(msg[ID], websocket_api.const.ERR_NOT_FOUND, "ZHA Group not found")) return
async def websocket_get_device(hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]) -> None: """Get ZHA devices.""" zha_gateway: ZHAGateway = hass.data[DATA_ZHA][DATA_ZHA_GATEWAY] ieee: EUI64 = msg[ATTR_IEEE] if not (zha_device := zha_gateway.devices.get(ieee)): connection.send_message( websocket_api.error_message(msg[ID], websocket_api.const.ERR_NOT_FOUND, "ZHA Device not found")) return
async def websocket_remove_group_members(hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]) -> None: """Remove members from a ZHA group.""" zha_gateway: ZHAGateway = hass.data[DATA_ZHA][DATA_ZHA_GATEWAY] group_id: int = msg[GROUP_ID] members: list[GroupMember] = msg[ATTR_MEMBERS] if not (zha_group := zha_gateway.groups.get(group_id)): connection.send_message( websocket_api.error_message(msg[ID], websocket_api.const.ERR_NOT_FOUND, "ZHA Group not found")) return
async def websocket_set_user_data( hass: HomeAssistant, connection: ActiveConnection, msg: dict, store: Store, data: dict[str, Any], ) -> None: """Handle set global data command. Async friendly. """ data[msg["key"]] = msg["value"] await store.async_save(data) connection.send_message(websocket_api.result_message(msg["id"]))
def _async_send_empty_response(connection: ActiveConnection, msg_id: int, start_time: dt, end_time: dt | None) -> None: """Send an empty response. The current case for this is when they ask for entity_ids that will all be filtered away because they have UOMs or state_class. """ connection.send_result(msg_id) stream_end_time = end_time or dt_util.utcnow() empty_stream_message = _generate_stream_message([], start_time, stream_end_time) empty_response = messages.event_message(msg_id, empty_stream_message) connection.send_message(JSON_DUMP(empty_response))
async def websocket_get_user_data( hass: HomeAssistant, connection: ActiveConnection, msg: dict, store: Store, data: dict[str, Any], ) -> None: """Handle get global data command. Async friendly. """ connection.send_message( websocket_api.result_message( msg["id"], {"value": data.get(msg["key"]) if "key" in msg else data}))
async def websocket_get_bindable_devices(hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]) -> None: """Directly bind devices.""" zha_gateway: ZHAGateway = hass.data[DATA_ZHA][DATA_ZHA_GATEWAY] source_ieee: EUI64 = msg[ATTR_IEEE] source_device = zha_gateway.get_device(source_ieee) devices = [ device.zha_device_info for device in zha_gateway.devices.values() if async_is_bindable_target(source_device, device) ] _LOGGER.debug( "Get bindable devices: %s: [%s], %s: [%s]", ATTR_SOURCE_IEEE, source_ieee, "bindable devices", devices, ) connection.send_message(websocket_api.result_message(msg[ID], devices))
async def websocket_remove_device(hass: HomeAssistant, connection: ActiveConnection, msg: dict) -> None: """Delete device.""" device_id = msg["device_id"] dev_registry = await hass.helpers.device_registry.async_get_registry() device = dev_registry.async_get(device_id) if not device: connection.send_error(msg["id"], websocket_api.const.ERR_NOT_FOUND, "Device not found") return for config_entry in device.config_entries: config_entry = hass.config_entries.async_get_entry(config_entry) # Only delete the device if it belongs to a Tasmota device entry if config_entry.domain == DOMAIN: dev_registry.async_remove_device(device_id) connection.send_message(websocket_api.result_message(msg["id"])) return connection.send_error(msg["id"], websocket_api.const.ERR_NOT_FOUND, "Non Tasmota device")
async def _async_send_historical_events( hass: HomeAssistant, connection: ActiveConnection, msg_id: int, start_time: dt, end_time: dt, formatter: Callable[[int, Any], dict[str, Any]], event_processor: EventProcessor, partial: bool, ) -> dt | None: """Select historical data from the database and deliver it to the websocket. If the query is considered a big query we will split the request into two chunks so that they get the recent events first and the select that is expected to take a long time comes in after to ensure they are not stuck at a loading screen and can start looking at the data right away. This function returns the time of the most recent event we sent to the websocket. """ is_big_query = ( not event_processor.entity_ids and not event_processor.device_ids and ((end_time - start_time) > timedelta(hours=BIG_QUERY_HOURS)) ) if not is_big_query: message, last_event_time = await _async_get_ws_stream_events( hass, msg_id, start_time, end_time, formatter, event_processor, partial, ) # If there is no last_event_time, there are no historical # results, but we still send an empty message # if its the last one (not partial) so # consumers of the api know their request was # answered but there were no results if last_event_time or not partial: connection.send_message(message) return last_event_time # This is a big query so we deliver # the first three hours and then # we fetch the old data recent_query_start = end_time - timedelta(hours=BIG_QUERY_RECENT_HOURS) recent_message, recent_query_last_event_time = await _async_get_ws_stream_events( hass, msg_id, recent_query_start, end_time, formatter, event_processor, partial=True, ) if recent_query_last_event_time: connection.send_message(recent_message) older_message, older_query_last_event_time = await _async_get_ws_stream_events( hass, msg_id, start_time, recent_query_start, formatter, event_processor, partial, ) # If there is no last_event_time, there are no historical # results, but we still send an empty message # if its the last one (not partial) so # consumers of the api know their request was # answered but there were no results if older_query_last_event_time or not partial: connection.send_message(older_message) # Returns the time of the newest event return recent_query_last_event_time or older_query_last_event_time