Minor deCONZ clean up (#76323)

* Rename secondary_temperature with internal_temperature

* Prefix binary and sensor descriptions matching on all sensor devices with COMMON_

* Always create entities in the same order

Its been reported previously that if the integration is removed and setup again that entity IDs can change if not sorted in the numerical order

* Rename alarmsystems to alarm_systems

* Use websocket enums

* Don't use legacy pydeconz constants

* Bump pydeconz to v103

* unsub -> unsubscribe
This commit is contained in:
Robert Svensson 2022-08-06 01:34:27 +02:00 committed by GitHub
parent 742877f79b
commit c2f026d0a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 38 additions and 35 deletions

View File

@ -48,7 +48,7 @@ def get_alarm_system_id_for_unique_id(
gateway: DeconzGateway, unique_id: str
) -> str | None:
"""Retrieve alarm system ID the unique ID is registered to."""
for alarm_system in gateway.api.alarmsystems.values():
for alarm_system in gateway.api.alarm_systems.values():
if unique_id in alarm_system.devices:
return alarm_system.resource_id
return None
@ -122,27 +122,27 @@ class DeconzAlarmControlPanel(DeconzDevice[AncillaryControl], AlarmControlPanelE
async def async_alarm_arm_away(self, code: str | None = None) -> None:
"""Send arm away command."""
if code:
await self.gateway.api.alarmsystems.arm(
await self.gateway.api.alarm_systems.arm(
self.alarm_system_id, AlarmSystemArmAction.AWAY, code
)
async def async_alarm_arm_home(self, code: str | None = None) -> None:
"""Send arm home command."""
if code:
await self.gateway.api.alarmsystems.arm(
await self.gateway.api.alarm_systems.arm(
self.alarm_system_id, AlarmSystemArmAction.STAY, code
)
async def async_alarm_arm_night(self, code: str | None = None) -> None:
"""Send arm night command."""
if code:
await self.gateway.api.alarmsystems.arm(
await self.gateway.api.alarm_systems.arm(
self.alarm_system_id, AlarmSystemArmAction.NIGHT, code
)
async def async_alarm_disarm(self, code: str | None = None) -> None:
"""Send disarm command."""
if code:
await self.gateway.api.alarmsystems.arm(
await self.gateway.api.alarm_systems.arm(
self.alarm_system_id, AlarmSystemArmAction.DISARM, code
)

View File

@ -159,7 +159,7 @@ ENTITY_DESCRIPTIONS = {
],
}
BINARY_SENSOR_DESCRIPTIONS = [
COMMON_BINARY_SENSOR_DESCRIPTIONS = [
DeconzBinarySensorDescription(
key="tampered",
value_fn=lambda device: device.tampered,
@ -215,7 +215,8 @@ async def async_setup_entry(
sensor = gateway.api.sensors[sensor_id]
for description in (
ENTITY_DESCRIPTIONS.get(type(sensor), []) + BINARY_SENSOR_DESCRIPTIONS
ENTITY_DESCRIPTIONS.get(type(sensor), [])
+ COMMON_BINARY_SENSOR_DESCRIPTIONS
):
if (
not hasattr(sensor, description.key)
@ -283,8 +284,8 @@ class DeconzBinarySensor(DeconzDevice[SensorResources], BinarySensorEntity):
if self._device.on is not None:
attr[ATTR_ON] = self._device.on
if self._device.secondary_temperature is not None:
attr[ATTR_TEMPERATURE] = self._device.secondary_temperature
if self._device.internal_temperature is not None:
attr[ATTR_TEMPERATURE] = self._device.internal_temperature
if isinstance(self._device, Presence):

View File

@ -26,7 +26,7 @@ async def async_get_config_entry_diagnostics(
gateway.api.config.raw, REDACT_DECONZ_CONFIG
)
diag["websocket_state"] = (
gateway.api.websocket.state if gateway.api.websocket else "Unknown"
gateway.api.websocket.state.value if gateway.api.websocket else "Unknown"
)
diag["deconz_ids"] = gateway.deconz_ids
diag["entities"] = gateway.entities
@ -37,7 +37,7 @@ async def async_get_config_entry_diagnostics(
}
for event in gateway.events
}
diag["alarm_systems"] = {k: v.raw for k, v in gateway.api.alarmsystems.items()}
diag["alarm_systems"] = {k: v.raw for k, v in gateway.api.alarm_systems.items()}
diag["groups"] = {k: v.raw for k, v in gateway.api.groups.items()}
diag["lights"] = {k: v.raw for k, v in gateway.api.lights.items()}
diag["scenes"] = {k: v.raw for k, v in gateway.api.scenes.items()}

View File

@ -169,7 +169,7 @@ class DeconzGateway:
)
)
for device_id in deconz_device_interface:
for device_id in sorted(deconz_device_interface, key=int):
async_add_device(EventType.ADDED, device_id)
initializing = False

View File

@ -3,7 +3,7 @@
"name": "deCONZ",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/deconz",
"requirements": ["pydeconz==102"],
"requirements": ["pydeconz==103"],
"ssdp": [
{
"manufacturer": "Royal Philips Electronics",

View File

@ -6,7 +6,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from pydeconz.models.event import EventType
from pydeconz.models.sensor.presence import PRESENCE_DELAY, Presence
from pydeconz.models.sensor.presence import Presence
from homeassistant.components.number import (
DOMAIN,
@ -42,7 +42,7 @@ ENTITY_DESCRIPTIONS = {
key="delay",
value_fn=lambda device: device.delay,
suffix="Delay",
update_key=PRESENCE_DELAY,
update_key="delay",
native_max_value=65535,
native_min_value=0,
native_step=1,

View File

@ -209,7 +209,7 @@ ENTITY_DESCRIPTIONS = {
}
SENSOR_DESCRIPTIONS = [
COMMON_SENSOR_DESCRIPTIONS = [
DeconzSensorDescription(
key="battery",
value_fn=lambda device: device.battery,
@ -221,8 +221,8 @@ SENSOR_DESCRIPTIONS = [
entity_category=EntityCategory.DIAGNOSTIC,
),
DeconzSensorDescription(
key="secondary_temperature",
value_fn=lambda device: device.secondary_temperature,
key="internal_temperature",
value_fn=lambda device: device.internal_temperature,
suffix="Temperature",
update_key="temperature",
device_class=SensorDeviceClass.TEMPERATURE,
@ -253,7 +253,7 @@ async def async_setup_entry(
known_entities = set(gateway.entities[DOMAIN])
for description in (
ENTITY_DESCRIPTIONS.get(type(sensor), []) + SENSOR_DESCRIPTIONS
ENTITY_DESCRIPTIONS.get(type(sensor), []) + COMMON_SENSOR_DESCRIPTIONS
):
if (
not hasattr(sensor, description.key)
@ -341,8 +341,8 @@ class DeconzSensor(DeconzDevice[SensorResources], SensorEntity):
if self._device.on is not None:
attr[ATTR_ON] = self._device.on
if self._device.secondary_temperature is not None:
attr[ATTR_TEMPERATURE] = self._device.secondary_temperature
if self._device.internal_temperature is not None:
attr[ATTR_TEMPERATURE] = self._device.internal_temperature
if isinstance(self._device, Consumption):
attr[ATTR_POWER] = self._device.power
@ -383,14 +383,16 @@ class DeconzBatteryTracker:
self.sensor = gateway.api.sensors[sensor_id]
self.gateway = gateway
self.async_add_entities = async_add_entities
self.unsub = self.sensor.subscribe(self.async_update_callback)
self.unsubscribe = self.sensor.subscribe(self.async_update_callback)
@callback
def async_update_callback(self) -> None:
"""Update the device's state."""
if "battery" in self.sensor.changed_keys:
self.unsub()
self.unsubscribe()
known_entities = set(self.gateway.entities[DOMAIN])
entity = DeconzSensor(self.sensor, self.gateway, SENSOR_DESCRIPTIONS[0])
entity = DeconzSensor(
self.sensor, self.gateway, COMMON_SENSOR_DESCRIPTIONS[0]
)
if entity.unique_id not in known_entities:
self.async_add_entities([entity])

View File

@ -1461,7 +1461,7 @@ pydaikin==2.7.0
pydanfossair==0.1.0
# homeassistant.components.deconz
pydeconz==102
pydeconz==103
# homeassistant.components.delijn
pydelijn==1.0.0

View File

@ -1004,7 +1004,7 @@ pycoolmasternet-async==0.1.2
pydaikin==2.7.0
# homeassistant.components.deconz
pydeconz==102
pydeconz==103
# homeassistant.components.dexcom
pydexcom==0.2.3

View File

@ -3,7 +3,7 @@ from __future__ import annotations
from unittest.mock import patch
from pydeconz.websocket import SIGNAL_CONNECTION_STATE, SIGNAL_DATA
from pydeconz.websocket import Signal
import pytest
from tests.components.light.conftest import mock_light_profiles # noqa: F401
@ -20,10 +20,10 @@ def mock_deconz_websocket():
if data:
mock.return_value.data = data
await pydeconz_gateway_session_handler(signal=SIGNAL_DATA)
await pydeconz_gateway_session_handler(signal=Signal.DATA)
elif state:
mock.return_value.state = state
await pydeconz_gateway_session_handler(signal=SIGNAL_CONNECTION_STATE)
await pydeconz_gateway_session_handler(signal=Signal.CONNECTION_STATE)
else:
raise NotImplementedError

View File

@ -1,6 +1,6 @@
"""Test deCONZ diagnostics."""
from pydeconz.websocket import STATE_RUNNING
from pydeconz.websocket import State
from homeassistant.components.deconz.const import CONF_MASTER_GATEWAY
from homeassistant.components.diagnostics import REDACTED
@ -17,7 +17,7 @@ async def test_entry_diagnostics(
"""Test config entry diagnostics."""
config_entry = await setup_deconz_integration(hass, aioclient_mock)
await mock_deconz_websocket(state=STATE_RUNNING)
await mock_deconz_websocket(state=State.RUNNING)
await hass.async_block_till_done()
assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
@ -44,7 +44,7 @@ async def test_entry_diagnostics(
"uuid": "1234",
"websocketport": 1234,
},
"websocket_state": STATE_RUNNING,
"websocket_state": State.RUNNING.value,
"deconz_ids": {},
"entities": {
str(Platform.ALARM_CONTROL_PANEL): [],

View File

@ -5,7 +5,7 @@ from copy import deepcopy
from unittest.mock import patch
import pydeconz
from pydeconz.websocket import STATE_RETRYING, STATE_RUNNING
from pydeconz.websocket import State
import pytest
from homeassistant.components import ssdp
@ -223,12 +223,12 @@ async def test_connection_status_signalling(
assert hass.states.get("binary_sensor.presence").state == STATE_OFF
await mock_deconz_websocket(state=STATE_RETRYING)
await mock_deconz_websocket(state=State.RETRYING)
await hass.async_block_till_done()
assert hass.states.get("binary_sensor.presence").state == STATE_UNAVAILABLE
await mock_deconz_websocket(state=STATE_RUNNING)
await mock_deconz_websocket(state=State.RUNNING)
await hass.async_block_till_done()
assert hass.states.get("binary_sensor.presence").state == STATE_OFF