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):
"""Representation of an August Door binary sensor."""
_attr_device_class = DEVICE_CLASS_DOOR
def __init__(self, data, sensor_type, device):
"""Initialize the sensor."""
super().__init__(data, device)
self._data = data
self._sensor_type = sensor_type
self._device = device
self._attr_name = f"{device.device_name} Open"
self._attr_unique_id = f"{self._device_id}_open"
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
def _update_from_data(self):
"""Get the latest state of the sensor and update activity."""
@ -173,11 +157,8 @@ class AugustDoorBinarySensor(AugustEntityMixin, BinarySensorEntity):
if bridge_activity is not None:
update_lock_detail_from_activity(self._detail, bridge_activity)
@property
def unique_id(self) -> str:
"""Get the unique of the door open binary sensor."""
return f"{self._device_id}_open"
self._attr_available = self._detail.bridge_is_online
self._attr_is_on = self._detail.door_state == LockDoorStatus.OPEN
class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
@ -189,36 +170,18 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
self._check_for_off_update_listener = None
self._data = data
self._sensor_type = sensor_type
self._device = device
self._state = None
self._available = False
self._attr_device_class = self._sensor_config[SENSOR_DEVICE_CLASS]
self._attr_name = f"{device.device_name} {self._sensor_config[SENSOR_NAME]}"
self._attr_unique_id = (
f"{self._device_id}_{self._sensor_config[SENSOR_NAME].lower()}"
)
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
def _sensor_config(self):
"""Return the config for the sensor."""
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
def _state_provider(self):
"""Return the state provider for the binary sensor."""
@ -233,19 +196,19 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
def _update_from_data(self):
"""Get the latest state of the sensor."""
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:
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()
else:
self._available = True
self._attr_available = True
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."""
# If the sensor is already off there is nothing to do
if not self._state:
if not self.is_on:
return
# self.hass is only available after setup is completed
@ -258,7 +221,7 @@ class AugustDoorbellBinarySensor(AugustEntityMixin, BinarySensorEntity):
"""Timer callback for sensor update."""
self._check_for_off_update_listener = None
self._update_from_data()
if not self._state:
if not self.is_on:
self.async_write_ha_state()
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."""
self._schedule_update_to_recheck_turn_off_sensor()
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._image_url = None
self._image_content = None
@property
def name(self):
"""Return the name of this device."""
return f"{self._device.device_name} Camera"
self._attr_name = f"{device.device_name} Camera"
self._attr_unique_id = f"{self._device_id:s}_camera"
@property
def is_recording(self):
@ -81,8 +78,3 @@ class AugustCamera(AugustEntityMixin, Camera):
self._session, timeout=self._timeout
)
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):
"""Base implementation for August device."""
_attr_should_poll = False
def __init__(self, data, device):
"""Initialize an August device."""
super().__init__()
self._data = data
self._device = device
@property
def should_poll(self):
"""Return False, updates are controlled via the hub."""
return False
self._attr_device_info = {
"identifiers": {(DOMAIN, self._device_id)},
"name": device.device_name,
"manufacturer": MANUFACTURER,
"sw_version": self._detail.firmware_version,
"model": self._detail.model,
"suggested_area": _remove_device_types(device.device_name, DEVICE_TYPES),
}
@property
def _device_id(self):
@ -30,19 +35,6 @@ class AugustEntityMixin(Entity):
def _detail(self):
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
def _update_from_data_and_write_state(self):
self._update_from_data()

View File

@ -31,8 +31,8 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
self._data = data
self._device = device
self._lock_status = None
self._changed_by = None
self._available = False
self._attr_name = device.device_name
self._attr_unique_id = f"{self._device_id:s}_lock"
self._update_from_data()
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)
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:
self._lock_status = self._detail.lock_status
@ -72,7 +72,7 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
)
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)
# If the source is pubnub the lock must be online since its a live update
if lock_activity.source == SOURCE_PUBNUB:
@ -86,38 +86,18 @@ class AugustLock(AugustEntityMixin, RestoreEntity, LockEntity):
update_lock_detail_from_activity(self._detail, bridge_activity)
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:
return None
return 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_is_locked = None
else:
self._attr_is_locked = self._lock_status is LockStatus.LOCKED
self._attr_extra_state_attributes = {
ATTR_BATTERY_LEVEL: self._detail.battery_level
}
if self._detail.keypad is not None:
attributes["keypad_battery_level"] = self._detail.keypad.battery_level
return attributes
self._attr_extra_state_attributes[
"keypad_battery_level"
] = self._detail.keypad.battery_level
async def async_added_to_hass(self):
"""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
if ATTR_CHANGED_BY in last_state.attributes:
self._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"
self._attr_changed_by = last_state.attributes[ATTR_CHANGED_BY]

View File

@ -125,25 +125,13 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
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."""
@ -156,9 +144,9 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
self._device_id, {ActivityType.LOCK_OPERATION}
)
self._available = True
self._attr_available = True
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_keypad = lock_activity.operated_keypad
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:
return
self._state = last_state.state
self._attr_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:
@ -219,54 +207,24 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
class AugustBatterySensor(AugustEntityMixin, SensorEntity):
"""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):
"""Initialize the sensor."""
super().__init__(data, device)
self._data = data
self._sensor_type = sensor_type
self._device = device
self._old_device = old_device
self._state = None
self._available = False
self._attr_name = f"{device.device_name} Battery"
self._attr_unique_id = f"{self._device_id}_{sensor_type}"
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
def _update_from_data(self):
"""Get the latest state of the sensor."""
state_provider = SENSOR_TYPES_BATTERY[self._sensor_type]["state_provider"]
self._state = state_provider(self._detail)
self._available = self._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}"
self._attr_state = state_provider(self._detail)
self._attr_available = self._attr_state is not None
@property
def old_unique_id(self) -> str: