deCONZ - battery sensor instead of battery attribute (#26591)
* Allow all sensors to create battery sensors * Neither binary sensor, climate nor sensor will have battery attributespull/26648/head
parent
24f1ff0aef
commit
41c9ed5d51
|
@ -2,7 +2,7 @@
|
||||||
from pydeconz.sensor import Presence, Vibration
|
from pydeconz.sensor import Presence, Vibration
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||||
from homeassistant.const import ATTR_BATTERY_LEVEL, ATTR_TEMPERATURE
|
from homeassistant.const import ATTR_TEMPERATURE
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ ATTR_VIBRATIONSTRENGTH = "vibrationstrength"
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
"""Old way of setting up deCONZ platforms."""
|
"""Old way of setting up deCONZ platforms."""
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
|
@ -56,7 +55,7 @@ class DeconzBinarySensor(DeconzDevice, BinarySensorDevice):
|
||||||
def async_update_callback(self, force_update=False):
|
def async_update_callback(self, force_update=False):
|
||||||
"""Update the sensor's state."""
|
"""Update the sensor's state."""
|
||||||
changed = set(self._device.changed_keys)
|
changed = set(self._device.changed_keys)
|
||||||
keys = {"battery", "on", "reachable", "state"}
|
keys = {"on", "reachable", "state"}
|
||||||
if force_update or any(key in changed for key in keys):
|
if force_update or any(key in changed for key in keys):
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
@ -79,8 +78,6 @@ class DeconzBinarySensor(DeconzDevice, BinarySensorDevice):
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes of the sensor."""
|
"""Return the state attributes of the sensor."""
|
||||||
attr = {}
|
attr = {}
|
||||||
if self._device.battery:
|
|
||||||
attr[ATTR_BATTERY_LEVEL] = self._device.battery
|
|
||||||
|
|
||||||
if self._device.on is not None:
|
if self._device.on is not None:
|
||||||
attr[ATTR_ON] = self._device.on
|
attr[ATTR_ON] = self._device.on
|
||||||
|
|
|
@ -8,7 +8,7 @@ from homeassistant.components.climate.const import (
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
SUPPORT_TARGET_TEMPERATURE,
|
SUPPORT_TARGET_TEMPERATURE,
|
||||||
)
|
)
|
||||||
from homeassistant.const import ATTR_BATTERY_LEVEL, ATTR_TEMPERATURE, TEMP_CELSIUS
|
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ SUPPORT_HVAC = [HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF]
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
"""Old way of setting up deCONZ platforms."""
|
"""Old way of setting up deCONZ platforms."""
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
|
@ -120,9 +119,6 @@ class DeconzThermostat(DeconzDevice, ClimateDevice):
|
||||||
"""Return the state attributes of the thermostat."""
|
"""Return the state attributes of the thermostat."""
|
||||||
attr = {}
|
attr = {}
|
||||||
|
|
||||||
if self._device.battery:
|
|
||||||
attr[ATTR_BATTERY_LEVEL] = self._device.battery
|
|
||||||
|
|
||||||
if self._device.offset:
|
if self._device.offset:
|
||||||
attr[ATTR_OFFSET] = self._device.offset
|
attr[ATTR_OFFSET] = self._device.offset
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ class DeconzBase:
|
||||||
@property
|
@property
|
||||||
def serial(self):
|
def serial(self):
|
||||||
"""Return a serial number for this device."""
|
"""Return a serial number for this device."""
|
||||||
if self.unique_id is None or self.unique_id.count(":") != 7:
|
if self._device.uniqueid is None or self._device.uniqueid.count(":") != 7:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self.unique_id.split("-", 1)[0]
|
return self._device.uniqueid.split("-", 1)[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self):
|
def device_info(self):
|
||||||
|
|
|
@ -27,6 +27,11 @@ class DeconzEvent(DeconzBase):
|
||||||
self.event_id = slugify(self._device.name)
|
self.event_id = slugify(self._device.name)
|
||||||
_LOGGER.debug("deCONZ event created: %s", self.event_id)
|
_LOGGER.debug("deCONZ event created: %s", self.event_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device(self):
|
||||||
|
"""Return Event device."""
|
||||||
|
return self._device
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_will_remove_from_hass(self) -> None:
|
def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect event object when removed."""
|
"""Disconnect event object when removed."""
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
"""Support for deCONZ sensors."""
|
"""Support for deCONZ sensors."""
|
||||||
from pydeconz.sensor import Consumption, Daylight, LightLevel, Power, Switch
|
from pydeconz.sensor import Consumption, Daylight, LightLevel, Power, Switch
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import ATTR_TEMPERATURE, ATTR_VOLTAGE, DEVICE_CLASS_BATTERY
|
||||||
ATTR_BATTERY_LEVEL,
|
|
||||||
ATTR_TEMPERATURE,
|
|
||||||
ATTR_VOLTAGE,
|
|
||||||
DEVICE_CLASS_BATTERY,
|
|
||||||
)
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from .const import ATTR_DARK, ATTR_ON, NEW_SENSOR
|
from .const import ATTR_DARK, ATTR_ON, NEW_SENSOR
|
||||||
from .deconz_device import DeconzDevice
|
from .deconz_device import DeconzDevice
|
||||||
|
@ -24,41 +18,48 @@ ATTR_EVENT_ID = "event_id"
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
"""Old way of setting up deCONZ platforms."""
|
"""Old way of setting up deCONZ platforms."""
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the deCONZ sensors."""
|
"""Set up the deCONZ sensors."""
|
||||||
gateway = get_gateway_from_config_entry(hass, config_entry)
|
gateway = get_gateway_from_config_entry(hass, config_entry)
|
||||||
|
|
||||||
|
batteries = set()
|
||||||
entity_handler = DeconzEntityHandler(gateway)
|
entity_handler = DeconzEntityHandler(gateway)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_sensor(sensors):
|
def async_add_sensor(sensors):
|
||||||
"""Add sensors from deCONZ."""
|
"""Add sensors from deCONZ.
|
||||||
|
|
||||||
|
Create DeconzEvent if part of ZHAType list.
|
||||||
|
Create DeconzSensor if not a ZHAType and not a binary sensor.
|
||||||
|
Create DeconzBattery if sensor has a battery attribute.
|
||||||
|
"""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
for sensor in sensors:
|
for sensor in sensors:
|
||||||
|
|
||||||
if not sensor.BINARY:
|
|
||||||
|
|
||||||
if sensor.type in Switch.ZHATYPE:
|
if sensor.type in Switch.ZHATYPE:
|
||||||
|
|
||||||
if gateway.option_allow_clip_sensor or not sensor.type.startswith(
|
if gateway.option_allow_clip_sensor or not sensor.type.startswith(
|
||||||
"CLIP"
|
"CLIP"
|
||||||
):
|
):
|
||||||
event = DeconzEvent(sensor, gateway)
|
new_event = DeconzEvent(sensor, gateway)
|
||||||
hass.async_create_task(event.async_update_device_registry())
|
hass.async_create_task(new_event.async_update_device_registry())
|
||||||
gateway.events.append(event)
|
gateway.events.append(new_event)
|
||||||
|
|
||||||
if sensor.battery:
|
elif not sensor.BINARY:
|
||||||
entities.append(DeconzBattery(sensor, gateway))
|
|
||||||
|
|
||||||
else:
|
|
||||||
new_sensor = DeconzSensor(sensor, gateway)
|
new_sensor = DeconzSensor(sensor, gateway)
|
||||||
entity_handler.add_entity(new_sensor)
|
entity_handler.add_entity(new_sensor)
|
||||||
entities.append(new_sensor)
|
entities.append(new_sensor)
|
||||||
|
|
||||||
|
if sensor.battery:
|
||||||
|
new_battery = DeconzBattery(sensor, gateway)
|
||||||
|
if new_battery.unique_id not in batteries:
|
||||||
|
batteries.add(new_battery.unique_id)
|
||||||
|
entities.append(new_battery)
|
||||||
|
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
gateway.listeners.append(
|
gateway.listeners.append(
|
||||||
|
@ -77,7 +78,7 @@ class DeconzSensor(DeconzDevice):
|
||||||
def async_update_callback(self, force_update=False):
|
def async_update_callback(self, force_update=False):
|
||||||
"""Update the sensor's state."""
|
"""Update the sensor's state."""
|
||||||
changed = set(self._device.changed_keys)
|
changed = set(self._device.changed_keys)
|
||||||
keys = {"battery", "on", "reachable", "state"}
|
keys = {"on", "reachable", "state"}
|
||||||
if force_update or any(key in changed for key in keys):
|
if force_update or any(key in changed for key in keys):
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
@ -105,8 +106,6 @@ class DeconzSensor(DeconzDevice):
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes of the sensor."""
|
"""Return the state attributes of the sensor."""
|
||||||
attr = {}
|
attr = {}
|
||||||
if self._device.battery:
|
|
||||||
attr[ATTR_BATTERY_LEVEL] = self._device.battery
|
|
||||||
|
|
||||||
if self._device.on is not None:
|
if self._device.on is not None:
|
||||||
attr[ATTR_ON] = self._device.on
|
attr[ATTR_ON] = self._device.on
|
||||||
|
@ -133,13 +132,6 @@ class DeconzSensor(DeconzDevice):
|
||||||
class DeconzBattery(DeconzDevice):
|
class DeconzBattery(DeconzDevice):
|
||||||
"""Battery class for when a device is only represented as an event."""
|
"""Battery class for when a device is only represented as an event."""
|
||||||
|
|
||||||
def __init__(self, device, gateway):
|
|
||||||
"""Register dispatcher callback for update of battery state."""
|
|
||||||
super().__init__(device, gateway)
|
|
||||||
|
|
||||||
self._name = "{} {}".format(self._device.name, "Battery Level")
|
|
||||||
self._unit_of_measurement = "%"
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, force_update=False):
|
def async_update_callback(self, force_update=False):
|
||||||
"""Update the battery's state, if needed."""
|
"""Update the battery's state, if needed."""
|
||||||
|
@ -148,6 +140,11 @@ class DeconzBattery(DeconzDevice):
|
||||||
if force_update or any(key in changed for key in keys):
|
if force_update or any(key in changed for key in keys):
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return a unique identifier for this device."""
|
||||||
|
return f"{self.serial}-battery"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the battery."""
|
"""Return the state of the battery."""
|
||||||
|
@ -156,7 +153,7 @@ class DeconzBattery(DeconzDevice):
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the battery."""
|
"""Return the name of the battery."""
|
||||||
return self._name
|
return f"{self._device.name} Battery Level"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self):
|
def device_class(self):
|
||||||
|
@ -166,10 +163,16 @@ class DeconzBattery(DeconzDevice):
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
"""Return the unit of measurement of this entity."""
|
"""Return the unit of measurement of this entity."""
|
||||||
return self._unit_of_measurement
|
return "%"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes of the battery."""
|
"""Return the state attributes of the battery."""
|
||||||
attr = {ATTR_EVENT_ID: slugify(self._device.name)}
|
attr = {}
|
||||||
|
|
||||||
|
if self._device.type in Switch.ZHATYPE:
|
||||||
|
for event in self.gateway.events:
|
||||||
|
if self._device == event.device:
|
||||||
|
attr[ATTR_EVENT_ID] = event.event_id
|
||||||
|
|
||||||
return attr
|
return attr
|
||||||
|
|
Loading…
Reference in New Issue