"""Support for Tractive switches.""" from dataclasses import dataclass import logging from typing import Any, Literal, override from aiotractive.exceptions import TractiveError from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from . import Trackables, TractiveClient, TractiveConfigEntry from .const import ( ATTR_BUZZER, ATTR_LED, ATTR_LIVE_TRACKING, ATTR_POWER_SAVING, DOMAIN, TRACKER_SWITCH_STATUS_UPDATED, ) from .entity import TractiveEntity _LOGGER = logging.getLogger(__name__) @dataclass(frozen=True, kw_only=True) class TractiveSwitchEntityDescription(SwitchEntityDescription): """Class describing Tractive switch entities.""" method: Literal["async_set_buzzer", "async_set_led", "async_set_live_tracking"] SWITCH_TYPES: tuple[TractiveSwitchEntityDescription, ...] = ( TractiveSwitchEntityDescription( key=ATTR_BUZZER, translation_key="tracker_buzzer", method="async_set_buzzer", entity_category=EntityCategory.CONFIG, ), TractiveSwitchEntityDescription( key=ATTR_LED, translation_key="tracker_led", method="async_set_led", entity_category=EntityCategory.CONFIG, ), TractiveSwitchEntityDescription( key=ATTR_LIVE_TRACKING, translation_key="live_tracking", method="async_set_live_tracking", entity_category=EntityCategory.CONFIG, ), ) async def async_setup_entry( hass: HomeAssistant, entry: TractiveConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up Tractive switches.""" client = entry.runtime_data.client trackables = entry.runtime_data.trackables entities = [ TractiveSwitch(hass, entry, client, item, description) for description in SWITCH_TYPES for item in trackables ] async_add_entities(entities) class TractiveSwitch(TractiveEntity, SwitchEntity): """Tractive switch.""" entity_description: TractiveSwitchEntityDescription def __init__( self, hass: HomeAssistant, entry: TractiveConfigEntry, client: TractiveClient, item: Trackables, description: TractiveSwitchEntityDescription, ) -> None: """Initialize switch entity.""" super().__init__( hass, entry, client, item.trackable, item.tracker_details, f"{TRACKER_SWITCH_STATUS_UPDATED}-{item.tracker_details['_id']}", ) self._attr_unique_id = f"{item.trackable['_id']}_{description.key}" self._tracker = item.tracker self._method = getattr(self, description.method) self.entity_description = description @callback @override def handle_status_update(self, event: dict[str, Any]) -> None: """Handle status update.""" if ATTR_POWER_SAVING in event: self._attr_available = not event[ATTR_POWER_SAVING] if self.entity_description.key in event: self._attr_is_on = event[self.entity_description.key] self.async_write_ha_state() @override async def async_turn_on(self, **kwargs: Any) -> None: """Turn on a switch.""" try: result = await self._method(True) except TractiveError as error: raise HomeAssistantError( translation_domain=DOMAIN, translation_key="failed_to_turn_on", translation_placeholders={"entity": self.entity_id}, ) from error # Write state back to avoid switch flips with a slow response if result["pending"]: self._attr_is_on = True self.async_write_ha_state() @override async def async_turn_off(self, **kwargs: Any) -> None: """Turn off a switch.""" try: result = await self._method(False) except TractiveError as error: raise HomeAssistantError( translation_domain=DOMAIN, translation_key="failed_to_turn_off", translation_placeholders={"entity": self.entity_id}, ) from error # Write state back to avoid switch flips with a slow response if result["pending"]: self._attr_is_on = False self.async_write_ha_state() async def async_set_buzzer(self, active: bool) -> dict[str, Any]: """Set the buzzer on/off.""" return await self._tracker.set_buzzer_active(active) async def async_set_led(self, active: bool) -> dict[str, Any]: """Set the LED on/off.""" return await self._tracker.set_led_active(active) async def async_set_live_tracking(self, active: bool) -> dict[str, Any]: """Set the live tracking on/off.""" return await self._tracker.set_live_tracking_active(active)