Lock operation sensors for August (#32593)
* adkj * reduce * Convert august to async Async io was added to py-august 0.24 * Fix lint * Lock operation sensors for august * Tracking lock operation method allows user presence detection at the lock * revert lock changes * fix activity count merge conflict reversion * Fix revert that come back with the conflict
This commit is contained in:
parent
b9a9a92145
commit
ae147fd9c7
8 changed files with 437 additions and 3 deletions
|
@ -1,12 +1,26 @@
|
|||
"""Support for August sensors."""
|
||||
import logging
|
||||
|
||||
from august.activity import ActivityType
|
||||
|
||||
from homeassistant.components.sensor import DEVICE_CLASS_BATTERY
|
||||
from homeassistant.const import UNIT_PERCENTAGE
|
||||
from homeassistant.const import ATTR_ENTITY_PICTURE, UNIT_PERCENTAGE
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from .const import DATA_AUGUST, DOMAIN
|
||||
from .const import (
|
||||
ATTR_OPERATION_AUTORELOCK,
|
||||
ATTR_OPERATION_KEYPAD,
|
||||
ATTR_OPERATION_METHOD,
|
||||
ATTR_OPERATION_REMOTE,
|
||||
DATA_AUGUST,
|
||||
DOMAIN,
|
||||
OPERATION_METHOD_AUTORELOCK,
|
||||
OPERATION_METHOD_KEYPAD,
|
||||
OPERATION_METHOD_MOBILE_DEVICE,
|
||||
OPERATION_METHOD_REMOTE,
|
||||
)
|
||||
from .entity import AugustEntityMixin
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -42,6 +56,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
data = hass.data[DOMAIN][config_entry.entry_id][DATA_AUGUST]
|
||||
devices = []
|
||||
|
||||
operation_sensors = []
|
||||
batteries = {
|
||||
"device_battery": [],
|
||||
"linked_keypad_battery": [],
|
||||
|
@ -51,6 +66,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
for device in data.locks:
|
||||
batteries["device_battery"].append(device)
|
||||
batteries["linked_keypad_battery"].append(device)
|
||||
operation_sensors.append(device)
|
||||
|
||||
for sensor_type in SENSOR_TYPES_BATTERY:
|
||||
for device in batteries[sensor_type]:
|
||||
|
@ -70,9 +86,111 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
)
|
||||
devices.append(AugustBatterySensor(data, sensor_type, device))
|
||||
|
||||
for device in operation_sensors:
|
||||
devices.append(AugustOperatorSensor(data, device))
|
||||
|
||||
async_add_entities(devices, True)
|
||||
|
||||
|
||||
class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, Entity):
|
||||
"""Representation of an August lock operation sensor."""
|
||||
|
||||
def __init__(self, data, device):
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(data, device)
|
||||
self._data = data
|
||||
self._device = device
|
||||
self._state = None
|
||||
self._operated_remote = None
|
||||
self._operated_keypad = None
|
||||
self._operated_autorelock = None
|
||||
self._operated_time = None
|
||||
self._available = False
|
||||
self._entity_picture = None
|
||||
self._update_from_data()
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return the availability of this sensor."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return f"{self._device.device_name} Operator"
|
||||
|
||||
@callback
|
||||
def _update_from_data(self):
|
||||
"""Get the latest state of the sensor and update activity."""
|
||||
lock_activity = self._data.activity_stream.get_latest_device_activity(
|
||||
self._device_id, [ActivityType.LOCK_OPERATION]
|
||||
)
|
||||
|
||||
if lock_activity is not None:
|
||||
self._available = True
|
||||
self._state = lock_activity.operated_by
|
||||
self._operated_remote = lock_activity.operated_remote
|
||||
self._operated_keypad = lock_activity.operated_keypad
|
||||
self._operated_autorelock = lock_activity.operated_autorelock
|
||||
self._entity_picture = lock_activity.operator_thumbnail_url
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device specific state attributes."""
|
||||
attributes = {}
|
||||
|
||||
if self._operated_remote is not None:
|
||||
attributes[ATTR_OPERATION_REMOTE] = self._operated_remote
|
||||
if self._operated_keypad is not None:
|
||||
attributes[ATTR_OPERATION_KEYPAD] = self._operated_keypad
|
||||
if self._operated_autorelock is not None:
|
||||
attributes[ATTR_OPERATION_AUTORELOCK] = self._operated_autorelock
|
||||
|
||||
if self._operated_remote:
|
||||
attributes[ATTR_OPERATION_METHOD] = OPERATION_METHOD_REMOTE
|
||||
elif self._operated_keypad:
|
||||
attributes[ATTR_OPERATION_METHOD] = OPERATION_METHOD_KEYPAD
|
||||
elif self._operated_autorelock:
|
||||
attributes[ATTR_OPERATION_METHOD] = OPERATION_METHOD_AUTORELOCK
|
||||
else:
|
||||
attributes[ATTR_OPERATION_METHOD] = OPERATION_METHOD_MOBILE_DEVICE
|
||||
|
||||
return attributes
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Restore ATTR_CHANGED_BY on startup since it is likely no longer in the activity log."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
last_state = await self.async_get_last_state()
|
||||
if not last_state:
|
||||
return
|
||||
|
||||
self._state = last_state.state
|
||||
if ATTR_ENTITY_PICTURE in last_state.attributes:
|
||||
self._entity_picture = last_state.attributes[ATTR_ENTITY_PICTURE]
|
||||
if ATTR_OPERATION_REMOTE in last_state.attributes:
|
||||
self._operated_remote = last_state.attributes[ATTR_OPERATION_REMOTE]
|
||||
if ATTR_OPERATION_KEYPAD in last_state.attributes:
|
||||
self._operated_keypad = last_state.attributes[ATTR_OPERATION_KEYPAD]
|
||||
if ATTR_OPERATION_AUTORELOCK in last_state.attributes:
|
||||
self._operated_autorelock = last_state.attributes[ATTR_OPERATION_AUTORELOCK]
|
||||
|
||||
@property
|
||||
def entity_picture(self):
|
||||
"""Return the entity picture to use in the frontend, if any."""
|
||||
return self._entity_picture
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Get the unique id of the device sensor."""
|
||||
return f"{self._device_id}_lock_operator"
|
||||
|
||||
|
||||
class AugustBatterySensor(AugustEntityMixin, Entity):
|
||||
"""Representation of an August sensor."""
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue