core/homeassistant/components/fully_kiosk/switch.py

158 lines
5.6 KiB
Python

"""Fully Kiosk Browser switch."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from fullykiosk import FullyKiosk
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.const import EntityCategory
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import FullyKioskConfigEntry
from .coordinator import FullyKioskDataUpdateCoordinator
from .entity import FullyKioskEntity
@dataclass(frozen=True, kw_only=True)
class FullySwitchEntityDescription(SwitchEntityDescription):
"""Fully Kiosk Browser switch entity description."""
on_action: Callable[[FullyKiosk], Any]
off_action: Callable[[FullyKiosk], Any]
is_on_fn: Callable[[dict[str, Any]], Any]
mqtt_on_event: str | None
mqtt_off_event: str | None
SWITCHES: tuple[FullySwitchEntityDescription, ...] = (
FullySwitchEntityDescription(
key="screensaver",
translation_key="screensaver",
on_action=lambda fully: fully.startScreensaver(),
off_action=lambda fully: fully.stopScreensaver(),
is_on_fn=lambda data: data.get("isInScreensaver"),
mqtt_on_event="onScreensaverStart",
mqtt_off_event="onScreensaverStop",
),
FullySwitchEntityDescription(
key="maintenance",
translation_key="maintenance",
entity_category=EntityCategory.CONFIG,
on_action=lambda fully: fully.enableLockedMode(),
off_action=lambda fully: fully.disableLockedMode(),
is_on_fn=lambda data: data.get("maintenanceMode"),
mqtt_on_event=None,
mqtt_off_event=None,
),
FullySwitchEntityDescription(
key="kiosk",
translation_key="kiosk",
entity_category=EntityCategory.CONFIG,
on_action=lambda fully: fully.lockKiosk(),
off_action=lambda fully: fully.unlockKiosk(),
is_on_fn=lambda data: data.get("kioskLocked"),
mqtt_on_event=None,
mqtt_off_event=None,
),
FullySwitchEntityDescription(
key="motion-detection",
translation_key="motion_detection",
entity_category=EntityCategory.CONFIG,
on_action=lambda fully: fully.enableMotionDetection(),
off_action=lambda fully: fully.disableMotionDetection(),
is_on_fn=lambda data: data["settings"].get("motionDetection"),
mqtt_on_event=None,
mqtt_off_event=None,
),
FullySwitchEntityDescription(
key="screenOn",
translation_key="screen_on",
on_action=lambda fully: fully.screenOn(),
off_action=lambda fully: fully.screenOff(),
is_on_fn=lambda data: data.get("screenOn"),
mqtt_on_event="screenOn",
mqtt_off_event="screenOff",
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: FullyKioskConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Fully Kiosk Browser switch."""
coordinator = config_entry.runtime_data
async_add_entities(
FullySwitchEntity(coordinator, description) for description in SWITCHES
)
class FullySwitchEntity(FullyKioskEntity, SwitchEntity):
"""Fully Kiosk Browser switch entity."""
entity_description: FullySwitchEntityDescription
def __init__(
self,
coordinator: FullyKioskDataUpdateCoordinator,
description: FullySwitchEntityDescription,
) -> None:
"""Initialize the Fully Kiosk Browser switch entity."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.data['deviceID']}-{description.key}"
self._turned_on_subscription: CALLBACK_TYPE | None = None
self._turned_off_subscription: CALLBACK_TYPE | None = None
async def async_added_to_hass(self) -> None:
"""When entity is added to hass."""
await super().async_added_to_hass()
description = self.entity_description
self._turned_on_subscription = await self.mqtt_subscribe(
description.mqtt_off_event, self._turn_off
)
self._turned_off_subscription = await self.mqtt_subscribe(
description.mqtt_on_event, self._turn_on
)
async def async_will_remove_from_hass(self) -> None:
"""Close MQTT subscriptions when removed."""
await super().async_will_remove_from_hass()
if self._turned_off_subscription is not None:
self._turned_off_subscription()
if self._turned_on_subscription is not None:
self._turned_on_subscription()
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
await self.entity_description.on_action(self.coordinator.fully)
await self.coordinator.async_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
await self.entity_description.off_action(self.coordinator.fully)
await self.coordinator.async_refresh()
def _turn_off(self, **kwargs: Any) -> None:
"""Optimistically turn off."""
self._attr_is_on = False
self.async_write_ha_state()
def _turn_on(self, **kwargs: Any) -> None:
"""Optimistically turn on."""
self._attr_is_on = True
self.async_write_ha_state()
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._attr_is_on = bool(self.entity_description.is_on_fn(self.coordinator.data))
self.async_write_ha_state()