From d76607e945f73be0c4742e48bb24d5c5f4d34d1f Mon Sep 17 00:00:00 2001 From: Robert Hillis Date: Tue, 13 Jul 2021 15:56:34 -0400 Subject: [PATCH] Use entity class attributes for august (#52744) --- .../components/august/binary_sensor.py | 74 ++++--------------- homeassistant/components/august/camera.py | 12 +-- homeassistant/components/august/entity.py | 28 +++---- homeassistant/components/august/lock.py | 53 ++++--------- homeassistant/components/august/sensor.py | 62 +++------------- 5 files changed, 52 insertions(+), 177 deletions(-) diff --git a/homeassistant/components/august/binary_sensor.py b/homeassistant/components/august/binary_sensor.py index e72d4b186a5..97faf444f3b 100644 --- a/homeassistant/components/august/binary_sensor.py +++ b/homeassistant/components/august/binary_sensor.py @@ -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()}" diff --git a/homeassistant/components/august/camera.py b/homeassistant/components/august/camera.py index daaa7624aa3..6bb47a06eee 100644 --- a/homeassistant/components/august/camera.py +++ b/homeassistant/components/august/camera.py @@ -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" diff --git a/homeassistant/components/august/entity.py b/homeassistant/components/august/entity.py index b2a93948449..af8c858a1d4 100644 --- a/homeassistant/components/august/entity.py +++ b/homeassistant/components/august/entity.py @@ -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() diff --git a/homeassistant/components/august/lock.py b/homeassistant/components/august/lock.py index 6e4ee7e6f5c..e74eded3557 100644 --- a/homeassistant/components/august/lock.py +++ b/homeassistant/components/august/lock.py @@ -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] diff --git a/homeassistant/components/august/sensor.py b/homeassistant/components/august/sensor.py index 1d973a83fc3..a174964f349 100644 --- a/homeassistant/components/august/sensor.py +++ b/homeassistant/components/august/sensor.py @@ -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: