Use entity class attributes for august (#52744)

This commit is contained in:
Robert Hillis 2021-07-13 15:56:34 -04:00 committed by GitHub
parent 12ac666459
commit d76607e945
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 177 deletions

View File

@ -126,34 +126,18 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class AugustDoorBinarySensor(AugustEntityMixin, BinarySensorEntity): class AugustDoorBinarySensor(AugustEntityMixin, BinarySensorEntity):
"""Representation of an August Door binary sensor.""" """Representation of an August Door binary sensor."""
_attr_device_class = DEVICE_CLASS_DOOR
def __init__(self, data, sensor_type, device): def __init__(self, data, sensor_type, device):
"""Initialize the sensor.""" """Initialize the sensor."""
super().__init__(data, device) super().__init__(data, device)
self._data = data self._data = data
self._sensor_type = sensor_type self._sensor_type = sensor_type
self._device = device self._device = device
self._attr_name = f"{device.device_name} Open"
self._attr_unique_id = f"{self._device_id}_open"
self._update_from_data() self._update_from_data()
@property
def available(self):
"""Return the availability of this sensor."""
return self._detail.bridge_is_online
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._detail.door_state == LockDoorStatus.OPEN
@property
def device_class(self):
"""Return the class of this device."""
return DEVICE_CLASS_DOOR
@property
def name(self):
"""Return the name of the binary sensor."""
return f"{self._device.device_name} Open"
@callback @callback
def _update_from_data(self): def _update_from_data(self):
"""Get the latest state of the sensor and update activity.""" """Get the latest state of the sensor and update activity."""
@ -173,11 +157,8 @@ class AugustDoorBinarySensor(AugustEntityMixin, BinarySensorEntity):
if bridge_activity is not None: if bridge_activity is not None:
update_lock_detail_from_activity(self._detail, bridge_activity) update_lock_detail_from_activity(self._detail, bridge_activity)
self._attr_available = self._detail.bridge_is_online
@property self._attr_is_on = self._detail.door_state == LockDoorStatus.OPEN
def unique_id(self) -> str:
"""Get the unique of the door open binary sensor."""
return f"{self._device_id}_open"
class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity): class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
@ -189,36 +170,18 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
self._check_for_off_update_listener = None self._check_for_off_update_listener = None
self._data = data self._data = data
self._sensor_type = sensor_type self._sensor_type = sensor_type
self._device = device self._attr_device_class = self._sensor_config[SENSOR_DEVICE_CLASS]
self._state = None self._attr_name = f"{device.device_name} {self._sensor_config[SENSOR_NAME]}"
self._available = False self._attr_unique_id = (
f"{self._device_id}_{self._sensor_config[SENSOR_NAME].lower()}"
)
self._update_from_data() self._update_from_data()
@property
def available(self):
"""Return the availability of this sensor."""
return self._available
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@property @property
def _sensor_config(self): def _sensor_config(self):
"""Return the config for the sensor.""" """Return the config for the sensor."""
return SENSOR_TYPES_DOORBELL[self._sensor_type] return SENSOR_TYPES_DOORBELL[self._sensor_type]
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return self._sensor_config[SENSOR_DEVICE_CLASS]
@property
def name(self):
"""Return the name of the binary sensor."""
return f"{self._device.device_name} {self._sensor_config[SENSOR_NAME]}"
@property @property
def _state_provider(self): def _state_provider(self):
"""Return the state provider for the binary sensor.""" """Return the state provider for the binary sensor."""
@ -233,19 +196,19 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
def _update_from_data(self): def _update_from_data(self):
"""Get the latest state of the sensor.""" """Get the latest state of the sensor."""
self._cancel_any_pending_updates() self._cancel_any_pending_updates()
self._state = self._state_provider(self._data, self._detail) self._attr_is_on = self._state_provider(self._data, self._detail)
if self._is_time_based: if self._is_time_based:
self._available = _retrieve_online_state(self._data, self._detail) self._attr_available = _retrieve_online_state(self._data, self._detail)
self._schedule_update_to_recheck_turn_off_sensor() self._schedule_update_to_recheck_turn_off_sensor()
else: else:
self._available = True self._attr_available = True
def _schedule_update_to_recheck_turn_off_sensor(self): def _schedule_update_to_recheck_turn_off_sensor(self):
"""Schedule an update to recheck the sensor to see if it is ready to turn off.""" """Schedule an update to recheck the sensor to see if it is ready to turn off."""
# If the sensor is already off there is nothing to do # If the sensor is already off there is nothing to do
if not self._state: if not self.is_on:
return return
# self.hass is only available after setup is completed # self.hass is only available after setup is completed
@ -258,7 +221,7 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
"""Timer callback for sensor update.""" """Timer callback for sensor update."""
self._check_for_off_update_listener = None self._check_for_off_update_listener = None
self._update_from_data() self._update_from_data()
if not self._state: if not self.is_on:
self.async_write_ha_state() self.async_write_ha_state()
self._check_for_off_update_listener = async_call_later( self._check_for_off_update_listener = async_call_later(
@ -277,8 +240,3 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
"""Call the mixin to subscribe and setup an async_track_point_in_utc_time to turn off the sensor if needed.""" """Call the mixin to subscribe and setup an async_track_point_in_utc_time to turn off the sensor if needed."""
self._schedule_update_to_recheck_turn_off_sensor() self._schedule_update_to_recheck_turn_off_sensor()
await super().async_added_to_hass() await super().async_added_to_hass()
@property
def unique_id(self) -> str:
"""Get the unique id of the doorbell sensor."""
return f"{self._device_id}_{self._sensor_config[SENSOR_NAME].lower()}"

View File

@ -35,11 +35,8 @@ class AugustCamera(AugustEntityMixin, Camera):
self._session = session self._session = session
self._image_url = None self._image_url = None
self._image_content = None self._image_content = None
self._attr_name = f"{device.device_name} Camera"
@property self._attr_unique_id = f"{self._device_id:s}_camera"
def name(self):
"""Return the name of this device."""
return f"{self._device.device_name} Camera"
@property @property
def is_recording(self): def is_recording(self):
@ -81,8 +78,3 @@ class AugustCamera(AugustEntityMixin, Camera):
self._session, timeout=self._timeout self._session, timeout=self._timeout
) )
return self._image_content return self._image_content
@property
def unique_id(self) -> str:
"""Get the unique id of the camera."""
return f"{self._device_id:s}_camera"

View File

@ -11,16 +11,21 @@ DEVICE_TYPES = ["keypad", "lock", "camera", "doorbell", "door", "bell"]
class AugustEntityMixin(Entity): class AugustEntityMixin(Entity):
"""Base implementation for August device.""" """Base implementation for August device."""
_attr_should_poll = False
def __init__(self, data, device): def __init__(self, data, device):
"""Initialize an August device.""" """Initialize an August device."""
super().__init__() super().__init__()
self._data = data self._data = data
self._device = device self._device = device
self._attr_device_info = {
@property "identifiers": {(DOMAIN, self._device_id)},
def should_poll(self): "name": device.device_name,
"""Return False, updates are controlled via the hub.""" "manufacturer": MANUFACTURER,
return False "sw_version": self._detail.firmware_version,
"model": self._detail.model,
"suggested_area": _remove_device_types(device.device_name, DEVICE_TYPES),
}
@property @property
def _device_id(self): def _device_id(self):
@ -30,19 +35,6 @@ class AugustEntityMixin(Entity):
def _detail(self): def _detail(self):
return self._data.get_device_detail(self._device.device_id) return self._data.get_device_detail(self._device.device_id)
@property
def device_info(self):
"""Return the device_info of the device."""
name = self._device.device_name
return {
"identifiers": {(DOMAIN, self._device_id)},
"name": name,
"manufacturer": MANUFACTURER,
"sw_version": self._detail.firmware_version,
"model": self._detail.model,
"suggested_area": _remove_device_types(name, DEVICE_TYPES),
}
@callback @callback
def _update_from_data_and_write_state(self): def _update_from_data_and_write_state(self):
self._update_from_data() self._update_from_data()

View File

@ -31,8 +31,8 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
self._data = data self._data = data
self._device = device self._device = device
self._lock_status = None self._lock_status = None
self._changed_by = None self._attr_name = device.device_name
self._available = False self._attr_unique_id = f"{self._device_id:s}_lock"
self._update_from_data() self._update_from_data()
async def async_lock(self, **kwargs): async def async_lock(self, **kwargs):
@ -56,7 +56,7 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
self._data.async_signal_device_id_update(self._device_id) self._data.async_signal_device_id_update(self._device_id)
def _update_lock_status_from_detail(self): def _update_lock_status_from_detail(self):
self._available = self._detail.bridge_is_online self._attr_available = self._detail.bridge_is_online
if self._lock_status != self._detail.lock_status: if self._lock_status != self._detail.lock_status:
self._lock_status = self._detail.lock_status self._lock_status = self._detail.lock_status
@ -72,7 +72,7 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
) )
if lock_activity is not None: if lock_activity is not None:
self._changed_by = lock_activity.operated_by self._attr_changed_by = lock_activity.operated_by
update_lock_detail_from_activity(self._detail, lock_activity) update_lock_detail_from_activity(self._detail, lock_activity)
# If the source is pubnub the lock must be online since its a live update # If the source is pubnub the lock must be online since its a live update
if lock_activity.source == SOURCE_PUBNUB: if lock_activity.source == SOURCE_PUBNUB:
@ -86,38 +86,18 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
update_lock_detail_from_activity(self._detail, bridge_activity) update_lock_detail_from_activity(self._detail, bridge_activity)
self._update_lock_status_from_detail() self._update_lock_status_from_detail()
@property
def name(self):
"""Return the name of this device."""
return self._device.device_name
@property
def available(self):
"""Return the availability of this sensor."""
return self._available
@property
def is_locked(self):
"""Return true if device is on."""
if self._lock_status is None or self._lock_status is LockStatus.UNKNOWN: if self._lock_status is None or self._lock_status is LockStatus.UNKNOWN:
return None self._attr_is_locked = None
return self._lock_status is LockStatus.LOCKED else:
self._attr_is_locked = self._lock_status is LockStatus.LOCKED
@property
def changed_by(self):
"""Last change triggered by."""
return self._changed_by
@property
def extra_state_attributes(self):
"""Return the device specific state attributes."""
attributes = {ATTR_BATTERY_LEVEL: self._detail.battery_level}
self._attr_extra_state_attributes = {
ATTR_BATTERY_LEVEL: self._detail.battery_level
}
if self._detail.keypad is not None: if self._detail.keypad is not None:
attributes["keypad_battery_level"] = self._detail.keypad.battery_level self._attr_extra_state_attributes[
"keypad_battery_level"
return attributes ] = self._detail.keypad.battery_level
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Restore ATTR_CHANGED_BY on startup since it is likely no longer in the activity log.""" """Restore ATTR_CHANGED_BY on startup since it is likely no longer in the activity log."""
@ -128,9 +108,4 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
return return
if ATTR_CHANGED_BY in last_state.attributes: if ATTR_CHANGED_BY in last_state.attributes:
self._changed_by = last_state.attributes[ATTR_CHANGED_BY] self._attr_changed_by = last_state.attributes[ATTR_CHANGED_BY]
@property
def unique_id(self) -> str:
"""Get the unique id of the lock."""
return f"{self._device_id:s}_lock"

View File

@ -125,25 +125,13 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
super().__init__(data, device) super().__init__(data, device)
self._data = data self._data = data
self._device = device self._device = device
self._state = None
self._operated_remote = None self._operated_remote = None
self._operated_keypad = None self._operated_keypad = None
self._operated_autorelock = None self._operated_autorelock = None
self._operated_time = None self._operated_time = None
self._available = False
self._entity_picture = None self._entity_picture = None
self._update_from_data() 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 @property
def name(self): def name(self):
"""Return the name of the sensor.""" """Return the name of the sensor."""
@ -156,9 +144,9 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
self._device_id, {ActivityType.LOCK_OPERATION} self._device_id, {ActivityType.LOCK_OPERATION}
) )
self._available = True self._attr_available = True
if lock_activity is not None: if lock_activity is not None:
self._state = lock_activity.operated_by self._attr_state = lock_activity.operated_by
self._operated_remote = lock_activity.operated_remote self._operated_remote = lock_activity.operated_remote
self._operated_keypad = lock_activity.operated_keypad self._operated_keypad = lock_activity.operated_keypad
self._operated_autorelock = lock_activity.operated_autorelock self._operated_autorelock = lock_activity.operated_autorelock
@ -195,7 +183,7 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
if not last_state or last_state.state == STATE_UNAVAILABLE: if not last_state or last_state.state == STATE_UNAVAILABLE:
return return
self._state = last_state.state self._attr_state = last_state.state
if ATTR_ENTITY_PICTURE in last_state.attributes: if ATTR_ENTITY_PICTURE in last_state.attributes:
self._entity_picture = last_state.attributes[ATTR_ENTITY_PICTURE] self._entity_picture = last_state.attributes[ATTR_ENTITY_PICTURE]
if ATTR_OPERATION_REMOTE in last_state.attributes: if ATTR_OPERATION_REMOTE in last_state.attributes:
@ -219,54 +207,24 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
class AugustBatterySensor(AugustEntityMixin, SensorEntity): class AugustBatterySensor(AugustEntityMixin, SensorEntity):
"""Representation of an August sensor.""" """Representation of an August sensor."""
_attr_device_class = DEVICE_CLASS_BATTERY
_attr_unit_of_measurement = PERCENTAGE
def __init__(self, data, sensor_type, device, old_device): def __init__(self, data, sensor_type, device, old_device):
"""Initialize the sensor.""" """Initialize the sensor."""
super().__init__(data, device) super().__init__(data, device)
self._data = data
self._sensor_type = sensor_type self._sensor_type = sensor_type
self._device = device
self._old_device = old_device self._old_device = old_device
self._state = None self._attr_name = f"{device.device_name} Battery"
self._available = False self._attr_unique_id = f"{self._device_id}_{sensor_type}"
self._update_from_data() 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 unit_of_measurement(self):
"""Return the unit of measurement."""
return PERCENTAGE
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return DEVICE_CLASS_BATTERY
@property
def name(self):
"""Return the name of the sensor."""
device_name = self._device.device_name
return f"{device_name} Battery"
@callback @callback
def _update_from_data(self): def _update_from_data(self):
"""Get the latest state of the sensor.""" """Get the latest state of the sensor."""
state_provider = SENSOR_TYPES_BATTERY[self._sensor_type]["state_provider"] state_provider = SENSOR_TYPES_BATTERY[self._sensor_type]["state_provider"]
self._state = state_provider(self._detail) self._attr_state = state_provider(self._detail)
self._available = self._state is not None self._attr_available = self._attr_state is not None
@property
def unique_id(self) -> str:
"""Get the unique id of the device sensor."""
return f"{self._device_id}_{self._sensor_type}"
@property @property
def old_unique_id(self) -> str: def old_unique_id(self) -> str: