Exemple #1
0
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),
            },
        ))
Exemple #2
0
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},
                    )
                )
            )
Exemple #3
0
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]))
Exemple #4
0
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))
Exemple #5
0
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}))
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
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"]))
Exemple #10
0
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))
Exemple #11
0
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}))
Exemple #12
0
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))
Exemple #13
0
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")
Exemple #14
0
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