"""Binary sensor platform for MedMate integration.""" from __future__ import annotations import logging from datetime import datetime, date from typing import Any from homeassistant.components.binary_sensor import ( BinarySensorEntity, BinarySensorEntityDescription, BinarySensorDeviceClass, ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import ( DOMAIN, CONF_MEDICINE_NAME, CONF_PRESCRIPTION, CONF_EXPIRY_DATE, CONF_REPEATS_LEFT, ) from .coordinator import MedMateDataUpdateCoordinator _LOGGER = logging.getLogger(__name__) async def async_setup_entry( hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up MedMate binary sensors.""" coordinator = hass.data[DOMAIN][config_entry.entry_id] binary_sensors = [ MedMateDoseDueSensor(coordinator, config_entry), MedMatePrescriptionActiveSensor(coordinator, config_entry), MedMateLowInventorySensor(coordinator, config_entry), ] async_add_entities(binary_sensors) class MedMateBaseBinarySensor(CoordinatorEntity, BinarySensorEntity): """Base binary sensor for MedMate.""" def __init__( self, coordinator: MedMateDataUpdateCoordinator, config_entry: ConfigEntry, description: BinarySensorEntityDescription, ) -> None: """Initialize the binary sensor.""" super().__init__(coordinator) self.entity_description = description self.config_entry = config_entry self._medicine_id = config_entry.data.get("medicine_id") # Set unique_id self._attr_unique_id = f"{self._medicine_id}_{description.key}" @property def device_info(self) -> dict[str, Any]: """Return device information.""" medicine_name = self.coordinator.data.get(CONF_MEDICINE_NAME, "Unknown Medicine") return { "identifiers": {(DOMAIN, self._medicine_id)}, "name": f"MedMate - {medicine_name}", "manufacturer": "MedMate", "model": "Medicine Tracker", "sw_version": "1.0.0", } @property def available(self) -> bool: """Return if entity is available.""" return self.coordinator.last_update_success and bool(self.coordinator.data) class MedMateDoseDueSensor(MedMateBaseBinarySensor): """Binary sensor for dose due status.""" def __init__( self, coordinator: MedMateDataUpdateCoordinator, config_entry: ConfigEntry, ) -> None: """Initialize the dose due sensor.""" description = BinarySensorEntityDescription( key="dose_due", name="Dose Due", icon="mdi:alarm", ) super().__init__(coordinator, config_entry, description) @property def is_on(self) -> bool: """Return true if dose is due.""" return self.coordinator.data.get("dose_due", False) @property def extra_state_attributes(self) -> dict[str, Any]: """Return additional state attributes.""" data = self.coordinator.data next_dose = data.get("next_dose") attrs = {} if next_dose: if isinstance(next_dose, str): try: next_dose = datetime.fromisoformat(next_dose) except ValueError: next_dose = None attrs["next_dose"] = next_dose return attrs class MedMatePrescriptionActiveSensor(MedMateBaseBinarySensor): """Binary sensor for prescription active status.""" def __init__( self, coordinator: MedMateDataUpdateCoordinator, config_entry: ConfigEntry, ) -> None: """Initialize the prescription active sensor.""" description = BinarySensorEntityDescription( key="prescription_active", name="Prescription Active", icon="mdi:file-document", ) super().__init__(coordinator, config_entry, description) @property def is_on(self) -> bool: """Return true if prescription is active.""" return self.coordinator.data.get("prescription_active", False) @property def extra_state_attributes(self) -> dict[str, Any]: """Return additional state attributes.""" data = self.coordinator.data prescription = data.get(CONF_PRESCRIPTION, {}) return { "expiry_date": prescription.get(CONF_EXPIRY_DATE), "repeats_left": prescription.get(CONF_REPEATS_LEFT, 0), } class MedMateLowInventorySensor(MedMateBaseBinarySensor): """Binary sensor for low inventory warning.""" def __init__( self, coordinator: MedMateDataUpdateCoordinator, config_entry: ConfigEntry, ) -> None: """Initialize the low inventory sensor.""" description = BinarySensorEntityDescription( key="low_inventory", name="Low Inventory", icon="mdi:alert-circle", device_class=BinarySensorDeviceClass.PROBLEM, ) super().__init__(coordinator, config_entry, description) @property def is_on(self) -> bool: """Return true if inventory is low.""" data = self.coordinator.data inventory = data.get("inventory", 0) # Consider inventory low if less than 7 doses remain # This assumes daily medication - could be made configurable return inventory < 7 @property def extra_state_attributes(self) -> dict[str, Any]: """Return additional state attributes.""" data = self.coordinator.data return { "current_inventory": data.get("inventory", 0), "low_threshold": 7, }