"""Support for powerwall binary sensors.""" from typing import TYPE_CHECKING, override from tesla_powerwall import GridStatus, MeterType from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .coordinator import PowerwallConfigEntry from .entity import PowerWallEntity CONNECTED_GRID_STATUSES = { GridStatus.TRANSITION_TO_GRID, GridStatus.CONNECTED, } async def async_setup_entry( hass: HomeAssistant, entry: PowerwallConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up the powerwall sensors.""" powerwall_data = entry.runtime_data base_info = powerwall_data["base_info"] if base_info.restricted: # Running and Connected sensors require /api/sitemaster which 404s on PW3. sensor_classes: tuple[type[PowerWallEntity], ...] = ( PowerWallGridServicesActiveSensor, PowerWallGridStatusSensor, PowerWallChargingStatusSensor, ) else: sensor_classes = ( PowerWallRunningSensor, PowerWallGridServicesActiveSensor, PowerWallGridStatusSensor, PowerWallConnectedSensor, PowerWallChargingStatusSensor, ) async_add_entities( [sensor_class(powerwall_data) for sensor_class in sensor_classes] ) class PowerWallRunningSensor(PowerWallEntity, BinarySensorEntity): """Representation of an Powerwall running sensor.""" _attr_translation_key = "status" _attr_device_class = BinarySensorDeviceClass.POWER @property @override def unique_id(self) -> str: """Device Uniqueid.""" return f"{self.base_unique_id}_running" @property @override def is_on(self) -> bool: """Get the powerwall running state.""" site_master = self.data.site_master if TYPE_CHECKING: assert site_master is not None return site_master.is_running class PowerWallConnectedSensor(PowerWallEntity, BinarySensorEntity): """Representation of an Powerwall connected sensor.""" _attr_translation_key = "connected_to_tesla" _attr_device_class = BinarySensorDeviceClass.CONNECTIVITY @property @override def unique_id(self) -> str: """Device Uniqueid.""" return f"{self.base_unique_id}_connected_to_tesla" @property @override def is_on(self) -> bool: """Get the powerwall connected to tesla state.""" site_master = self.data.site_master if TYPE_CHECKING: assert site_master is not None return site_master.is_connected_to_tesla class PowerWallGridServicesActiveSensor(PowerWallEntity, BinarySensorEntity): """Representation of a Powerwall grid services active sensor.""" _attr_translation_key = "grid_services_active" _attr_device_class = BinarySensorDeviceClass.POWER @property @override def unique_id(self) -> str: """Device Uniqueid.""" return f"{self.base_unique_id}_grid_services_active" @property @override def is_on(self) -> bool: """Grid services is active.""" return self.data.grid_services_active class PowerWallGridStatusSensor(PowerWallEntity, BinarySensorEntity): """Representation of an Powerwall grid status sensor.""" _attr_translation_key = "grid_status" _attr_device_class = BinarySensorDeviceClass.POWER @property @override def unique_id(self) -> str: """Device Uniqueid.""" return f"{self.base_unique_id}_grid_status" @property @override def is_on(self) -> bool: """Grid is online.""" return self.data.grid_status in CONNECTED_GRID_STATUSES class PowerWallChargingStatusSensor(PowerWallEntity, BinarySensorEntity): """Representation of an Powerwall charging status sensor.""" _attr_device_class = BinarySensorDeviceClass.BATTERY_CHARGING @property @override def available(self) -> bool: """Powerwall is available.""" # Return False if no battery is installed return ( super().available and self.data.meters.get_meter(MeterType.BATTERY) is not None ) @property @override def unique_id(self) -> str: """Device Uniqueid.""" return f"{self.base_unique_id}_powerwall_charging" # pylint: disable=home-assistant-entity-unique-id-redundant-domain @property @override def is_on(self) -> bool: """Powerwall is charging.""" meter = self.data.meters.get_meter(MeterType.BATTERY) # Meter cannot be None because of the available property if TYPE_CHECKING: assert meter is not None # is_sending_to returns true for values greater than 100 watts return meter.is_sending_to()