show metadata for locks
This commit is contained in:
parent
3cb164cae0
commit
a22192846c
|
@ -38,7 +38,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
|
||||
api.set_update_token_callback(__update_entry)
|
||||
|
||||
|
||||
hass.data[DOMAIN][username] = {}
|
||||
|
||||
hass.data[DOMAIN][username]["api"] = api
|
||||
|
@ -48,4 +47,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
await hass.config_entries.async_forward_entry_setup(entry, "button")
|
||||
await hass.config_entries.async_forward_entry_setup(entry, "sensor")
|
||||
await hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")
|
||||
return True
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN
|
||||
from .reos_api import ReosApi, ReosLockModel
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
|
||||
coordinator = hass.data[DOMAIN][config_entry.data["username"]]["coordinator"]
|
||||
|
||||
async_add_entities(ReosDoorIsFavorite(lock, coordinator) for _, lock in coordinator.data.items())
|
||||
|
||||
class BinarySensorBase(CoordinatorEntity, BinarySensorEntity):
|
||||
|
||||
def update_value(self) -> None:
|
||||
pass
|
||||
|
||||
def __format_id(self, name: str) -> str:
|
||||
return name.lower().replace(' ', '_')
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator, name: str) -> None:
|
||||
super().__init__(coordinator, context=model.lock_id)
|
||||
self._model = model
|
||||
self.idx = self._model.lock_id
|
||||
self._attr_unique_id = f"reos_lock_{self._model.lock_id}_{self.__format_id(name)}"
|
||||
self._attr_name = f"{self._model.display} {name}"
|
||||
self.update_value()
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
self._model = self.coordinator.data[self.idx]
|
||||
self.update_value()
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self.idx)},
|
||||
)
|
||||
|
||||
class ReosDoorIsFavorite(BinarySensorBase):
|
||||
|
||||
def update_value(self) -> None:
|
||||
self._attr_is_on = self._model.is_favorite
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator) -> None:
|
||||
super().__init__(model, coordinator, "Is Favorite")
|
|
@ -25,15 +25,15 @@ class ReosDoorButton(CoordinatorEntity, ButtonEntity):
|
|||
super().__init__(coordinator, context=model.lock_id)
|
||||
self._model = model
|
||||
self.idx = self._model.lock_id
|
||||
self._attr_unique_id = f"reos_lock_{self._model.lock_id}"
|
||||
self._attr_name = self._model.display
|
||||
self._attr_unique_id = f"reos_lock_{self._model.lock_id}_buzzer"
|
||||
self._attr_name = f"{self._model.display} Buzzer"
|
||||
self._attr_device_class = "door"
|
||||
self._attr_icon = "mdi:door"
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
self._model = self.coordinator.data[self.idx]
|
||||
_LOGGER.info(f"_handle_coordinator_update for {self.idx}")
|
||||
_LOGGER.info("_handle_coordinator_update for %s", self.idx)
|
||||
self.async_write_ha_state()
|
||||
|
||||
def press(self, **kwargs) -> None:
|
||||
|
@ -41,4 +41,7 @@ class ReosDoorButton(CoordinatorEntity, ButtonEntity):
|
|||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
return None
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self.idx)},
|
||||
name=self._model.display
|
||||
)
|
||||
|
|
|
@ -23,7 +23,7 @@ class ReosCoordinator(DataUpdateCoordinator):
|
|||
hass,
|
||||
_LOGGER,
|
||||
name="Reos Locks",
|
||||
update_interval=timedelta(hours=24),
|
||||
update_interval=timedelta(hours=6),
|
||||
)
|
||||
self.api = api
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
from homeassistant.core import HomeAssistant
|
||||
from datetime import datetime
|
||||
import dateutil.parser
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import logging
|
||||
|
@ -72,6 +74,12 @@ class ReosApi:
|
|||
_json = await response.json()
|
||||
return _json["access_token"], _json["refresh_token"]
|
||||
|
||||
def __parse_datetime(self, dt: datetime) -> datetime | None:
|
||||
if dt is not None:
|
||||
return dateutil.parser.parse(str(dt))
|
||||
else:
|
||||
return None
|
||||
|
||||
async def open_lock(self, lock_id: int) -> None:
|
||||
async with await self.__get_session() as session:
|
||||
await session.post(f"{PROTOCOL}://{self.host}{LOCK_OPEN_ENDPOINT}", json={"lockId": lock_id})
|
||||
|
@ -104,19 +112,27 @@ class ReosApi:
|
|||
_attr["title"],
|
||||
_attr["display_title"],
|
||||
_attr["is_favorite"],
|
||||
self
|
||||
self,
|
||||
updated_at=self.__parse_datetime(_attr["updated_at"]),
|
||||
created_at=self.__parse_datetime(_attr["created_at"]),
|
||||
available_from=self.__parse_datetime(_attr["available_from"]),
|
||||
available_to=self.__parse_datetime(_attr["available_to"])
|
||||
)
|
||||
locks.append(_lock)
|
||||
return locks
|
||||
|
||||
|
||||
class ReosLockModel:
|
||||
def __init__(self, id: int, name: str, display: str, is_favorite: bool, api: ReosApi) -> None:
|
||||
def __init__(self, id: int, name: str, display: str, is_favorite: bool, api: ReosApi, available_from: datetime = None, available_to: datetime = None, created_at: datetime = None, updated_at: datetime = None) -> None:
|
||||
self._id = id
|
||||
self.name = name
|
||||
self.display = display
|
||||
self._api = api
|
||||
self.is_favorite = is_favorite
|
||||
self.available_from = available_from
|
||||
self.available_to = available_to
|
||||
self.created_at = created_at
|
||||
self.updated_at = updated_at
|
||||
|
||||
@property
|
||||
def lock_id(self) -> int:
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN
|
||||
from .reos_api import ReosApi, ReosLockModel
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
|
||||
coordinator = hass.data[DOMAIN][config_entry.data["username"]]["coordinator"]
|
||||
|
||||
async_add_entities(ReosDoorUpdatedAt(lock, coordinator) for _, lock in coordinator.data.items())
|
||||
async_add_entities(ReosDoorCreatedAt(lock, coordinator) for _, lock in coordinator.data.items())
|
||||
async_add_entities(ReosDoorAvailableFrom(lock, coordinator) for _, lock in coordinator.data.items())
|
||||
async_add_entities(ReosDoorAvailableTo(lock, coordinator) for _, lock in coordinator.data.items())
|
||||
|
||||
class SensorBase(CoordinatorEntity, SensorEntity):
|
||||
|
||||
def update_value(self) -> None:
|
||||
pass
|
||||
|
||||
def __format_id(self, name: str) -> str:
|
||||
return name.lower().replace(' ', '_')
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator, name: str) -> None:
|
||||
super().__init__(coordinator, context=model.lock_id)
|
||||
self._model = model
|
||||
self.idx = self._model.lock_id
|
||||
self._attr_unique_id = f"reos_lock_{self._model.lock_id}_{self.__format_id(name)}"
|
||||
self._attr_name = f"{self._model.display} {name}"
|
||||
self.update_value()
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
self._model = self.coordinator.data[self.idx]
|
||||
self.update_value()
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self.idx)},
|
||||
)
|
||||
|
||||
|
||||
class TimestampSensorBase(SensorBase):
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator, name: str) -> None:
|
||||
super().__init__(model, coordinator, name)
|
||||
self._attr_device_class = SensorDeviceClass.TIMESTAMP
|
||||
|
||||
|
||||
class ReosDoorUpdatedAt(TimestampSensorBase):
|
||||
|
||||
def update_value(self) -> None:
|
||||
self._attr_native_value = self._model.updated_at
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator) -> None:
|
||||
super().__init__(model, coordinator, "Updated At")
|
||||
|
||||
class ReosDoorCreatedAt(TimestampSensorBase):
|
||||
|
||||
def update_value(self) -> None:
|
||||
self._attr_native_value = self._model.created_at
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator) -> None:
|
||||
super().__init__(model, coordinator, "Created At")
|
||||
|
||||
class ReosDoorAvailableFrom(TimestampSensorBase):
|
||||
|
||||
def update_value(self) -> None:
|
||||
self._attr_native_value = self._model.available_from
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator) -> None:
|
||||
super().__init__(model, coordinator, "Available From")
|
||||
|
||||
class ReosDoorAvailableTo(TimestampSensorBase):
|
||||
|
||||
def update_value(self) -> None:
|
||||
self._attr_native_value = self._model.available_to
|
||||
|
||||
def __init__(self, model: ReosLockModel, coordinator) -> None:
|
||||
super().__init__(model, coordinator, "Available To")
|
Loading…
Reference in New Issue