Initial commit
This commit is contained in:
180
button.py
Normal file
180
button.py
Normal file
@@ -0,0 +1,180 @@
|
||||
"""Button platform for MedMate integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||
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_SCHEDULE,
|
||||
CONF_TIMES,
|
||||
TIME_SLOTS,
|
||||
)
|
||||
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 buttons."""
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
buttons = [
|
||||
MedMateFillPrescriptionButton(coordinator, config_entry),
|
||||
]
|
||||
|
||||
# Add take dose buttons for each scheduled time
|
||||
schedule = coordinator.data.get(CONF_SCHEDULE, {})
|
||||
scheduled_times = schedule.get(CONF_TIMES, [])
|
||||
|
||||
for time_slot in scheduled_times:
|
||||
if time_slot in TIME_SLOTS:
|
||||
buttons.append(
|
||||
MedMateTakeDoseButton(coordinator, config_entry, time_slot)
|
||||
)
|
||||
|
||||
async_add_entities(buttons)
|
||||
|
||||
|
||||
class MedMateBaseButton(CoordinatorEntity, ButtonEntity):
|
||||
"""Base button for MedMate."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: MedMateDataUpdateCoordinator,
|
||||
config_entry: ConfigEntry,
|
||||
description: ButtonEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the button."""
|
||||
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 MedMateFillPrescriptionButton(MedMateBaseButton):
|
||||
"""Button to fill prescription."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: MedMateDataUpdateCoordinator,
|
||||
config_entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Initialize the fill prescription button."""
|
||||
description = ButtonEntityDescription(
|
||||
key="fill_prescription",
|
||||
name="Fill Prescription",
|
||||
icon="mdi:pill",
|
||||
)
|
||||
super().__init__(coordinator, config_entry, description)
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Handle the button press."""
|
||||
success = await self.coordinator.async_fill_prescription()
|
||||
|
||||
if success:
|
||||
_LOGGER.info(
|
||||
"Prescription filled for medicine: %s",
|
||||
self.coordinator.data.get(CONF_MEDICINE_NAME)
|
||||
)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Failed to fill prescription for medicine: %s",
|
||||
self.coordinator.data.get(CONF_MEDICINE_NAME)
|
||||
)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if button is available."""
|
||||
if not super().available:
|
||||
return False
|
||||
|
||||
# Only available if prescription is active and has repeats left
|
||||
return self.coordinator.data.get("prescription_active", False)
|
||||
|
||||
|
||||
class MedMateTakeDoseButton(MedMateBaseButton):
|
||||
"""Button to take a dose."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: MedMateDataUpdateCoordinator,
|
||||
config_entry: ConfigEntry,
|
||||
time_slot: str,
|
||||
) -> None:
|
||||
"""Initialize the take dose button."""
|
||||
self.time_slot = time_slot
|
||||
time_slot_name = TIME_SLOTS.get(time_slot, time_slot.title())
|
||||
|
||||
description = ButtonEntityDescription(
|
||||
key=f"take_dose_{time_slot}",
|
||||
name=f"Take {time_slot_name} Dose",
|
||||
icon="mdi:hand-heart",
|
||||
)
|
||||
super().__init__(coordinator, config_entry, description)
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Handle the button press."""
|
||||
success = await self.coordinator.async_take_dose(self.time_slot)
|
||||
|
||||
if success:
|
||||
_LOGGER.info(
|
||||
"Dose taken for medicine: %s at %s",
|
||||
self.coordinator.data.get(CONF_MEDICINE_NAME),
|
||||
self.time_slot
|
||||
)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Failed to record dose for medicine: %s at %s",
|
||||
self.coordinator.data.get(CONF_MEDICINE_NAME),
|
||||
self.time_slot
|
||||
)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if button is available."""
|
||||
if not super().available:
|
||||
return False
|
||||
|
||||
# Only available if there's inventory
|
||||
inventory = self.coordinator.data.get("inventory", 0)
|
||||
return inventory > 0
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return additional state attributes."""
|
||||
return {
|
||||
"time_slot": self.time_slot,
|
||||
"current_inventory": self.coordinator.data.get("inventory", 0),
|
||||
}
|
||||
Reference in New Issue
Block a user