From 160e3bda23d68123788b7881687e61dd334d9e09 Mon Sep 17 00:00:00 2001 From: Stephan Uhle Date: Fri, 19 Aug 2022 13:28:03 +0200 Subject: [PATCH 01/14] Add edl21 sensor unit mapping for Hz (#76783) Added sensor unit mapping for Hz. --- homeassistant/components/edl21/sensor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/edl21/sensor.py b/homeassistant/components/edl21/sensor.py index 65603b0c8c4..730acabbc98 100644 --- a/homeassistant/components/edl21/sensor.py +++ b/homeassistant/components/edl21/sensor.py @@ -22,6 +22,7 @@ from homeassistant.const import ( ELECTRIC_POTENTIAL_VOLT, ENERGY_KILO_WATT_HOUR, ENERGY_WATT_HOUR, + FREQUENCY_HERTZ, POWER_WATT, ) from homeassistant.core import HomeAssistant, callback @@ -252,6 +253,7 @@ SENSOR_UNIT_MAPPING = { "A": ELECTRIC_CURRENT_AMPERE, "V": ELECTRIC_POTENTIAL_VOLT, "°": DEGREE, + "Hz": FREQUENCY_HERTZ, } From 81a5c0f9b5dfa85105d13c01b131a176578bf85e Mon Sep 17 00:00:00 2001 From: Dave Atherton Date: Fri, 19 Aug 2022 10:51:27 +0100 Subject: [PATCH 02/14] Change growatt server URL (#76824) Co-authored-by: Chris Straffon --- homeassistant/components/growatt_server/const.py | 6 +++++- homeassistant/components/growatt_server/sensor.py | 14 +++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/growatt_server/const.py b/homeassistant/components/growatt_server/const.py index 4fcc4887843..4e548ef2c2a 100644 --- a/homeassistant/components/growatt_server/const.py +++ b/homeassistant/components/growatt_server/const.py @@ -8,11 +8,15 @@ DEFAULT_PLANT_ID = "0" DEFAULT_NAME = "Growatt" SERVER_URLS = [ - "https://server.growatt.com/", + "https://server-api.growatt.com/", "https://server-us.growatt.com/", "http://server.smten.com/", ] +DEPRECATED_URLS = [ + "https://server.growatt.com/", +] + DEFAULT_URL = SERVER_URLS[0] DOMAIN = "growatt_server" diff --git a/homeassistant/components/growatt_server/sensor.py b/homeassistant/components/growatt_server/sensor.py index db045242987..c90bfa6f3fb 100644 --- a/homeassistant/components/growatt_server/sensor.py +++ b/homeassistant/components/growatt_server/sensor.py @@ -19,6 +19,7 @@ from .const import ( CONF_PLANT_ID, DEFAULT_PLANT_ID, DEFAULT_URL, + DEPRECATED_URLS, DOMAIN, LOGIN_INVALID_AUTH_CODE, ) @@ -62,12 +63,23 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Growatt sensor.""" - config = config_entry.data + config = {**config_entry.data} username = config[CONF_USERNAME] password = config[CONF_PASSWORD] url = config.get(CONF_URL, DEFAULT_URL) name = config[CONF_NAME] + # If the URL has been deprecated then change to the default instead + if url in DEPRECATED_URLS: + _LOGGER.info( + "URL: %s has been deprecated, migrating to the latest default: %s", + url, + DEFAULT_URL, + ) + url = DEFAULT_URL + config[CONF_URL] = url + hass.config_entries.async_update_entry(config_entry, data=config) + api = growattServer.GrowattApi() api.server_url = url From 1150c3a51a17ee055a25935cb24b43f3c2f13f9a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 19 Aug 2022 20:14:47 -1000 Subject: [PATCH 03/14] Bump pySwitchbot to 0.18.12 (#77040) --- homeassistant/components/switchbot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index e70f467ae74..b4d7c69b315 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -2,7 +2,7 @@ "domain": "switchbot", "name": "SwitchBot", "documentation": "https://www.home-assistant.io/integrations/switchbot", - "requirements": ["PySwitchbot==0.18.10"], + "requirements": ["PySwitchbot==0.18.12"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/requirements_all.txt b/requirements_all.txt index 01d1c95d878..2447664e02f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,7 +37,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.18.10 +PySwitchbot==0.18.12 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1b5068e81fb..082abb6349e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -33,7 +33,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.18.10 +PySwitchbot==0.18.12 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From df5b57431dae3e2c87fedc4c6d1a14820fb86f2f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 21 Aug 2022 08:36:27 -1000 Subject: [PATCH 04/14] Bump pySwitchbot to 0.18.14 (#77090) --- homeassistant/components/switchbot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index b4d7c69b315..5631134cdf6 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -2,7 +2,7 @@ "domain": "switchbot", "name": "SwitchBot", "documentation": "https://www.home-assistant.io/integrations/switchbot", - "requirements": ["PySwitchbot==0.18.12"], + "requirements": ["PySwitchbot==0.18.14"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/requirements_all.txt b/requirements_all.txt index 2447664e02f..0999d6eafd1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,7 +37,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.18.12 +PySwitchbot==0.18.14 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 082abb6349e..41c538e3c2b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -33,7 +33,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.18.12 +PySwitchbot==0.18.14 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From 94d8863da957e4c960cdb11942a0ca4426d45a10 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 22 Aug 2022 09:03:32 +0200 Subject: [PATCH 05/14] Protect against an exception in Shelly climate platform (#77102) Check if state in HVACMode --- homeassistant/components/shelly/climate.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/shelly/climate.py b/homeassistant/components/shelly/climate.py index 453d67f39a7..a3f42c4a928 100644 --- a/homeassistant/components/shelly/climate.py +++ b/homeassistant/components/shelly/climate.py @@ -188,7 +188,10 @@ class BlockSleepingClimate( def hvac_mode(self) -> HVACMode: """HVAC current mode.""" if self.device_block is None: - return HVACMode(self.last_state.state) if self.last_state else HVACMode.OFF + if self.last_state and self.last_state.state in list(HVACMode): + return HVACMode(self.last_state.state) + return HVACMode.OFF + if self.device_block.mode is None or self._check_is_off(): return HVACMode.OFF From b8b4031d31836e65ea591a019018517eea788234 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Tue, 23 Aug 2022 20:53:43 -0400 Subject: [PATCH 06/14] Bump ZHA dependencies (#77125) --- homeassistant/components/zha/manifest.json | 8 ++++---- requirements_all.txt | 8 ++++---- requirements_test_all.txt | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 1eb2536fed6..0648cbd86f7 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -4,15 +4,15 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ - "bellows==0.32.0", + "bellows==0.33.1", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.78", "zigpy-deconz==0.18.0", - "zigpy==0.49.1", + "zigpy==0.50.2", "zigpy-xbee==0.15.0", - "zigpy-zigate==0.9.1", - "zigpy-znp==0.8.1" + "zigpy-zigate==0.9.2", + "zigpy-znp==0.8.2" ], "usb": [ { diff --git a/requirements_all.txt b/requirements_all.txt index 0999d6eafd1..c7d812d2ba3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -396,7 +396,7 @@ beautifulsoup4==4.11.1 # beewi_smartclim==0.0.10 # homeassistant.components.zha -bellows==0.32.0 +bellows==0.33.1 # homeassistant.components.bmw_connected_drive bimmer_connected==0.10.2 @@ -2529,13 +2529,13 @@ zigpy-deconz==0.18.0 zigpy-xbee==0.15.0 # homeassistant.components.zha -zigpy-zigate==0.9.1 +zigpy-zigate==0.9.2 # homeassistant.components.zha -zigpy-znp==0.8.1 +zigpy-znp==0.8.2 # homeassistant.components.zha -zigpy==0.49.1 +zigpy==0.50.2 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 41c538e3c2b..303d24f2699 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -320,7 +320,7 @@ base36==0.1.1 beautifulsoup4==4.11.1 # homeassistant.components.zha -bellows==0.32.0 +bellows==0.33.1 # homeassistant.components.bmw_connected_drive bimmer_connected==0.10.2 @@ -1703,13 +1703,13 @@ zigpy-deconz==0.18.0 zigpy-xbee==0.15.0 # homeassistant.components.zha -zigpy-zigate==0.9.1 +zigpy-zigate==0.9.2 # homeassistant.components.zha -zigpy-znp==0.8.1 +zigpy-znp==0.8.2 # homeassistant.components.zha -zigpy==0.49.1 +zigpy==0.50.2 # homeassistant.components.zwave_js zwave-js-server-python==0.39.0 From 58debaf8371c7ca920d053ca127c6f77c1de7df4 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Sat, 6 Aug 2022 01:34:27 +0200 Subject: [PATCH 07/14] 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 --- .../components/deconz/alarm_control_panel.py | 10 +++++----- .../components/deconz/binary_sensor.py | 9 +++++---- .../components/deconz/diagnostics.py | 4 ++-- homeassistant/components/deconz/gateway.py | 2 +- homeassistant/components/deconz/manifest.json | 2 +- homeassistant/components/deconz/number.py | 4 ++-- homeassistant/components/deconz/sensor.py | 20 ++++++++++--------- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/deconz/conftest.py | 6 +++--- tests/components/deconz/test_diagnostics.py | 6 +++--- tests/components/deconz/test_gateway.py | 6 +++--- 12 files changed, 38 insertions(+), 35 deletions(-) diff --git a/homeassistant/components/deconz/alarm_control_panel.py b/homeassistant/components/deconz/alarm_control_panel.py index bf0f39b75d0..f2758d8da75 100644 --- a/homeassistant/components/deconz/alarm_control_panel.py +++ b/homeassistant/components/deconz/alarm_control_panel.py @@ -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 @@ -123,27 +123,27 @@ class DeconzAlarmControlPanel(DeconzDevice, AlarmControlPanelEntity): 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 ) diff --git a/homeassistant/components/deconz/binary_sensor.py b/homeassistant/components/deconz/binary_sensor.py index 814dec443e0..7e7f98ed634 100644 --- a/homeassistant/components/deconz/binary_sensor.py +++ b/homeassistant/components/deconz/binary_sensor.py @@ -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) @@ -284,8 +285,8 @@ class DeconzBinarySensor(DeconzDevice, 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): diff --git a/homeassistant/components/deconz/diagnostics.py b/homeassistant/components/deconz/diagnostics.py index 11854421512..5b7986fc4c9 100644 --- a/homeassistant/components/deconz/diagnostics.py +++ b/homeassistant/components/deconz/diagnostics.py @@ -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()} diff --git a/homeassistant/components/deconz/gateway.py b/homeassistant/components/deconz/gateway.py index f8e4548cf91..6f29cef5190 100644 --- a/homeassistant/components/deconz/gateway.py +++ b/homeassistant/components/deconz/gateway.py @@ -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 diff --git a/homeassistant/components/deconz/manifest.json b/homeassistant/components/deconz/manifest.json index e4e412056e6..51de538324f 100644 --- a/homeassistant/components/deconz/manifest.json +++ b/homeassistant/components/deconz/manifest.json @@ -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", diff --git a/homeassistant/components/deconz/number.py b/homeassistant/components/deconz/number.py index 4c0959f950d..5e528dc2bb2 100644 --- a/homeassistant/components/deconz/number.py +++ b/homeassistant/components/deconz/number.py @@ -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, diff --git a/homeassistant/components/deconz/sensor.py b/homeassistant/components/deconz/sensor.py index 15af1b3dd8f..b8bb0e8ffea 100644 --- a/homeassistant/components/deconz/sensor.py +++ b/homeassistant/components/deconz/sensor.py @@ -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) @@ -342,8 +342,8 @@ class DeconzSensor(DeconzDevice, 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 @@ -384,14 +384,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]) diff --git a/requirements_all.txt b/requirements_all.txt index c7d812d2ba3..f0fe00302e9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1455,7 +1455,7 @@ pydaikin==2.7.0 pydanfossair==0.1.0 # homeassistant.components.deconz -pydeconz==102 +pydeconz==103 # homeassistant.components.delijn pydelijn==1.0.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 303d24f2699..c6497de3a13 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1001,7 +1001,7 @@ pycoolmasternet-async==0.1.2 pydaikin==2.7.0 # homeassistant.components.deconz -pydeconz==102 +pydeconz==103 # homeassistant.components.dexcom pydexcom==0.2.3 diff --git a/tests/components/deconz/conftest.py b/tests/components/deconz/conftest.py index 8b92e94416a..44411ca40cf 100644 --- a/tests/components/deconz/conftest.py +++ b/tests/components/deconz/conftest.py @@ -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 diff --git a/tests/components/deconz/test_diagnostics.py b/tests/components/deconz/test_diagnostics.py index d0905f5ba5f..459e0e910ab 100644 --- a/tests/components/deconz/test_diagnostics.py +++ b/tests/components/deconz/test_diagnostics.py @@ -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): [], diff --git a/tests/components/deconz/test_gateway.py b/tests/components/deconz/test_gateway.py index e6ded3981c4..9471752eb8d 100644 --- a/tests/components/deconz/test_gateway.py +++ b/tests/components/deconz/test_gateway.py @@ -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 From 0c617a04712049f78051e99efae45513b30e8a29 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Thu, 25 Aug 2022 04:00:54 +0200 Subject: [PATCH 08/14] Fix level controllable output controls in deCONZ (#77223) Fix level controllable output controls --- homeassistant/components/deconz/cover.py | 17 ++- homeassistant/components/deconz/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/deconz/test_cover.py | 108 ++++++++++++++++++ 5 files changed, 125 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/deconz/cover.py b/homeassistant/components/deconz/cover.py index 3e56882f15a..423978ea21b 100644 --- a/homeassistant/components/deconz/cover.py +++ b/homeassistant/components/deconz/cover.py @@ -4,6 +4,7 @@ from __future__ import annotations from typing import Any, cast from pydeconz.interfaces.lights import CoverAction +from pydeconz.models import ResourceType from pydeconz.models.event import EventType from pydeconz.models.light.cover import Cover @@ -23,9 +24,9 @@ from .deconz_device import DeconzDevice from .gateway import DeconzGateway, get_gateway_from_config_entry DECONZ_TYPE_TO_DEVICE_CLASS = { - "Level controllable output": CoverDeviceClass.DAMPER, - "Window covering controller": CoverDeviceClass.SHADE, - "Window covering device": CoverDeviceClass.SHADE, + ResourceType.LEVEL_CONTROLLABLE_OUTPUT.value: CoverDeviceClass.DAMPER, + ResourceType.WINDOW_COVERING_CONTROLLER.value: CoverDeviceClass.SHADE, + ResourceType.WINDOW_COVERING_DEVICE.value: CoverDeviceClass.SHADE, } @@ -72,6 +73,8 @@ class DeconzCover(DeconzDevice, CoverEntity): self._attr_device_class = DECONZ_TYPE_TO_DEVICE_CLASS.get(cover.type) + self.legacy_mode = cover.type == ResourceType.LEVEL_CONTROLLABLE_OUTPUT.value + @property def current_cover_position(self) -> int: """Return the current position of the cover.""" @@ -88,6 +91,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, lift=position, + legacy_mode=self.legacy_mode, ) async def async_open_cover(self, **kwargs: Any) -> None: @@ -95,6 +99,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, action=CoverAction.OPEN, + legacy_mode=self.legacy_mode, ) async def async_close_cover(self, **kwargs: Any) -> None: @@ -102,6 +107,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, action=CoverAction.CLOSE, + legacy_mode=self.legacy_mode, ) async def async_stop_cover(self, **kwargs: Any) -> None: @@ -109,6 +115,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, action=CoverAction.STOP, + legacy_mode=self.legacy_mode, ) @property @@ -124,6 +131,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, tilt=position, + legacy_mode=self.legacy_mode, ) async def async_open_cover_tilt(self, **kwargs: Any) -> None: @@ -131,6 +139,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, tilt=0, + legacy_mode=self.legacy_mode, ) async def async_close_cover_tilt(self, **kwargs: Any) -> None: @@ -138,6 +147,7 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, tilt=100, + legacy_mode=self.legacy_mode, ) async def async_stop_cover_tilt(self, **kwargs: Any) -> None: @@ -145,4 +155,5 @@ class DeconzCover(DeconzDevice, CoverEntity): await self.gateway.api.lights.covers.set_state( id=self._device.resource_id, action=CoverAction.STOP, + legacy_mode=self.legacy_mode, ) diff --git a/homeassistant/components/deconz/manifest.json b/homeassistant/components/deconz/manifest.json index 51de538324f..38c78d849da 100644 --- a/homeassistant/components/deconz/manifest.json +++ b/homeassistant/components/deconz/manifest.json @@ -3,7 +3,7 @@ "name": "deCONZ", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/deconz", - "requirements": ["pydeconz==103"], + "requirements": ["pydeconz==104"], "ssdp": [ { "manufacturer": "Royal Philips Electronics", diff --git a/requirements_all.txt b/requirements_all.txt index f0fe00302e9..682e15fa104 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1455,7 +1455,7 @@ pydaikin==2.7.0 pydanfossair==0.1.0 # homeassistant.components.deconz -pydeconz==103 +pydeconz==104 # homeassistant.components.delijn pydelijn==1.0.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c6497de3a13..9fa2b046e9b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1001,7 +1001,7 @@ pycoolmasternet-async==0.1.2 pydaikin==2.7.0 # homeassistant.components.deconz -pydeconz==103 +pydeconz==104 # homeassistant.components.dexcom pydexcom==0.2.3 diff --git a/tests/components/deconz/test_cover.py b/tests/components/deconz/test_cover.py index 0c37edc221d..f2f4c7d7a2d 100644 --- a/tests/components/deconz/test_cover.py +++ b/tests/components/deconz/test_cover.py @@ -213,3 +213,111 @@ async def test_tilt_cover(hass, aioclient_mock): blocking=True, ) assert aioclient_mock.mock_calls[4][2] == {"stop": True} + + +async def test_level_controllable_output_cover(hass, aioclient_mock): + """Test that tilting a cover works.""" + data = { + "lights": { + "0": { + "etag": "4cefc909134c8e99086b55273c2bde67", + "hascolor": False, + "lastannounced": "2022-08-08T12:06:18Z", + "lastseen": "2022-08-14T14:22Z", + "manufacturername": "Keen Home Inc", + "modelid": "SV01-410-MP-1.0", + "name": "Vent", + "state": { + "alert": "none", + "bri": 242, + "on": False, + "reachable": True, + "sat": 10, + }, + "swversion": "0x00000012", + "type": "Level controllable output", + "uniqueid": "00:22:a3:00:00:00:00:00-01", + } + } + } + with patch.dict(DECONZ_WEB_REQUEST, data): + config_entry = await setup_deconz_integration(hass, aioclient_mock) + + assert len(hass.states.async_all()) == 1 + covering_device = hass.states.get("cover.vent") + assert covering_device.state == STATE_OPEN + assert covering_device.attributes[ATTR_CURRENT_TILT_POSITION] == 97 + + # Verify service calls for tilting cover + + mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/0/state") + + # Service open cover + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_OPEN_COVER, + {ATTR_ENTITY_ID: "cover.vent"}, + blocking=True, + ) + assert aioclient_mock.mock_calls[1][2] == {"on": False} + + # Service close cover + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_CLOSE_COVER, + {ATTR_ENTITY_ID: "cover.vent"}, + blocking=True, + ) + assert aioclient_mock.mock_calls[2][2] == {"on": True} + + # Service set cover position + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_SET_COVER_POSITION, + {ATTR_ENTITY_ID: "cover.vent", ATTR_POSITION: 40}, + blocking=True, + ) + assert aioclient_mock.mock_calls[3][2] == {"bri": 152} + + # Service set tilt cover + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_SET_COVER_TILT_POSITION, + {ATTR_ENTITY_ID: "cover.vent", ATTR_TILT_POSITION: 40}, + blocking=True, + ) + assert aioclient_mock.mock_calls[4][2] == {"sat": 152} + + # Service open tilt cover + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_OPEN_COVER_TILT, + {ATTR_ENTITY_ID: "cover.vent"}, + blocking=True, + ) + assert aioclient_mock.mock_calls[5][2] == {"sat": 0} + + # Service close tilt cover + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_CLOSE_COVER_TILT, + {ATTR_ENTITY_ID: "cover.vent"}, + blocking=True, + ) + assert aioclient_mock.mock_calls[6][2] == {"sat": 254} + + # Service stop cover movement + + await hass.services.async_call( + COVER_DOMAIN, + SERVICE_STOP_COVER_TILT, + {ATTR_ENTITY_ID: "cover.vent"}, + blocking=True, + ) + assert aioclient_mock.mock_calls[7][2] == {"bri_inc": 0} From 3efc5bb0bea3fcb96ff625af2ed31c5074351317 Mon Sep 17 00:00:00 2001 From: mkmer Date: Wed, 24 Aug 2022 03:53:17 -0400 Subject: [PATCH 09/14] Fix Aladdin connect multiple doors on one device (#77226) Fixed Multiple doors device_info --- homeassistant/components/aladdin_connect/cover.py | 4 +++- homeassistant/components/aladdin_connect/sensor.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/aladdin_connect/cover.py b/homeassistant/components/aladdin_connect/cover.py index f032fcecbe0..ee0955cbb3d 100644 --- a/homeassistant/components/aladdin_connect/cover.py +++ b/homeassistant/components/aladdin_connect/cover.py @@ -90,6 +90,7 @@ class AladdinDevice(CoverEntity): self._number = device["door_number"] self._name = device["name"] self._serial = device["serial"] + self._model = device["model"] self._attr_unique_id = f"{self._device_id}-{self._number}" self._attr_has_entity_name = True @@ -97,9 +98,10 @@ class AladdinDevice(CoverEntity): def device_info(self) -> DeviceInfo | None: """Device information for Aladdin Connect cover.""" return DeviceInfo( - identifiers={(DOMAIN, self._device_id)}, + identifiers={(DOMAIN, f"{self._device_id}-{self._number}")}, name=self._name, manufacturer="Overhead Door", + model=self._model, ) async def async_added_to_hass(self) -> None: diff --git a/homeassistant/components/aladdin_connect/sensor.py b/homeassistant/components/aladdin_connect/sensor.py index 68631c57fc8..05db7bc19c5 100644 --- a/homeassistant/components/aladdin_connect/sensor.py +++ b/homeassistant/components/aladdin_connect/sensor.py @@ -102,7 +102,7 @@ class AladdinConnectSensor(SensorEntity): def device_info(self) -> DeviceInfo | None: """Device information for Aladdin Connect sensors.""" return DeviceInfo( - identifiers={(DOMAIN, self._device_id)}, + identifiers={(DOMAIN, f"{self._device_id}-{self._number}")}, name=self._name, manufacturer="Overhead Door", ) From 88451e3002225d819fe768825cfc3f4c0ff6e531 Mon Sep 17 00:00:00 2001 From: donoghdb <85128952+donoghdb@users.noreply.github.com> Date: Wed, 24 Aug 2022 07:18:10 +0100 Subject: [PATCH 10/14] Fix met_eireann default wind speed unit (#77229) Update default units --- homeassistant/components/met_eireann/weather.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/met_eireann/weather.py b/homeassistant/components/met_eireann/weather.py index f20f0e1254a..b872e9a8df6 100644 --- a/homeassistant/components/met_eireann/weather.py +++ b/homeassistant/components/met_eireann/weather.py @@ -13,7 +13,7 @@ from homeassistant.const import ( CONF_NAME, LENGTH_MILLIMETERS, PRESSURE_HPA, - SPEED_METERS_PER_SECOND, + SPEED_KILOMETERS_PER_HOUR, TEMP_CELSIUS, ) from homeassistant.core import HomeAssistant @@ -58,7 +58,7 @@ class MetEireannWeather(CoordinatorEntity, WeatherEntity): _attr_native_precipitation_unit = LENGTH_MILLIMETERS _attr_native_pressure_unit = PRESSURE_HPA _attr_native_temperature_unit = TEMP_CELSIUS - _attr_native_wind_speed_unit = SPEED_METERS_PER_SECOND + _attr_native_wind_speed_unit = SPEED_KILOMETERS_PER_HOUR def __init__(self, coordinator, config, hourly): """Initialise the platform with a data instance and site.""" From abaf89f57daca1510201714dfc8a764c0084df7b Mon Sep 17 00:00:00 2001 From: Matthias Alphart Date: Wed, 24 Aug 2022 09:57:57 +0200 Subject: [PATCH 11/14] Update xknx to 1.0.1 (#77244) --- homeassistant/components/knx/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/knx/manifest.json b/homeassistant/components/knx/manifest.json index 0f9b6b4b95a..bb5599939db 100644 --- a/homeassistant/components/knx/manifest.json +++ b/homeassistant/components/knx/manifest.json @@ -3,7 +3,7 @@ "name": "KNX", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/knx", - "requirements": ["xknx==1.0.0"], + "requirements": ["xknx==1.0.1"], "codeowners": ["@Julius2342", "@farmio", "@marvin-w"], "quality_scale": "platinum", "iot_class": "local_push", diff --git a/requirements_all.txt b/requirements_all.txt index 682e15fa104..df5bef18de6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2473,7 +2473,7 @@ xboxapi==2.0.1 xiaomi-ble==0.6.4 # homeassistant.components.knx -xknx==1.0.0 +xknx==1.0.1 # homeassistant.components.bluesound # homeassistant.components.fritz diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9fa2b046e9b..e6637b90fac 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1665,7 +1665,7 @@ xbox-webapi==2.0.11 xiaomi-ble==0.6.4 # homeassistant.components.knx -xknx==1.0.0 +xknx==1.0.1 # homeassistant.components.bluesound # homeassistant.components.fritz From c169a957ab9f0ffcacb6e820c3cacba4460b5877 Mon Sep 17 00:00:00 2001 From: mletenay Date: Thu, 25 Aug 2022 08:43:09 +0200 Subject: [PATCH 12/14] Fix grid_export_limit unit for DT inverters (#77290) FIx grid_export_limit unit for DT inverters --- homeassistant/components/goodwe/number.py | 30 ++++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/goodwe/number.py b/homeassistant/components/goodwe/number.py index 00d8d9d0cae..f8d3979879f 100644 --- a/homeassistant/components/goodwe/number.py +++ b/homeassistant/components/goodwe/number.py @@ -25,6 +25,7 @@ class GoodweNumberEntityDescriptionBase: getter: Callable[[Inverter], Awaitable[int]] setter: Callable[[Inverter, int], Awaitable[None]] + filter: Callable[[Inverter], bool] @dataclass @@ -35,17 +36,33 @@ class GoodweNumberEntityDescription( NUMBERS = ( + # non DT inverters (limit in W) GoodweNumberEntityDescription( key="grid_export_limit", name="Grid export limit", icon="mdi:transmission-tower", entity_category=EntityCategory.CONFIG, native_unit_of_measurement=POWER_WATT, - getter=lambda inv: inv.get_grid_export_limit(), - setter=lambda inv, val: inv.set_grid_export_limit(val), native_step=100, native_min_value=0, native_max_value=10000, + getter=lambda inv: inv.get_grid_export_limit(), + setter=lambda inv, val: inv.set_grid_export_limit(val), + filter=lambda inv: type(inv).__name__ != "DT", + ), + # DT inverters (limit is in %) + GoodweNumberEntityDescription( + key="grid_export_limit", + name="Grid export limit", + icon="mdi:transmission-tower", + entity_category=EntityCategory.CONFIG, + native_unit_of_measurement=PERCENTAGE, + native_step=1, + native_min_value=0, + native_max_value=100, + getter=lambda inv: inv.get_grid_export_limit(), + setter=lambda inv, val: inv.set_grid_export_limit(val), + filter=lambda inv: type(inv).__name__ == "DT", ), GoodweNumberEntityDescription( key="battery_discharge_depth", @@ -53,11 +70,12 @@ NUMBERS = ( icon="mdi:battery-arrow-down", entity_category=EntityCategory.CONFIG, native_unit_of_measurement=PERCENTAGE, - getter=lambda inv: inv.get_ongrid_battery_dod(), - setter=lambda inv, val: inv.set_ongrid_battery_dod(val), native_step=1, native_min_value=0, native_max_value=99, + getter=lambda inv: inv.get_ongrid_battery_dod(), + setter=lambda inv, val: inv.set_ongrid_battery_dod(val), + filter=lambda inv: True, ), ) @@ -73,7 +91,7 @@ async def async_setup_entry( entities = [] - for description in NUMBERS: + for description in filter(lambda dsc: dsc.filter(inverter), NUMBERS): try: current_value = await description.getter(inverter) except (InverterError, ValueError): @@ -82,7 +100,7 @@ async def async_setup_entry( continue entities.append( - InverterNumberEntity(device_info, description, inverter, current_value), + InverterNumberEntity(device_info, description, inverter, current_value) ) async_add_entities(entities) From f700a2ea1c9777608a22f6093414a74b747086d9 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 25 Aug 2022 14:13:44 -0400 Subject: [PATCH 13/14] Bumped version to 2022.8.7 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index f75c1802375..18da32c5e05 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "6" +PATCH_VERSION: Final = "7" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0) diff --git a/pyproject.toml b/pyproject.toml index e69bdd747d2..b9e6608e9b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.8.6" +version = "2022.8.7" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From c420242656076ce4afcacaac2c1ecfbb599f7a38 Mon Sep 17 00:00:00 2001 From: mkmer Date: Wed, 17 Aug 2022 03:09:19 -0400 Subject: [PATCH 14/14] Add BLE sensor to Aladdin_connect (#76221) * Add BLE sensor Default Enable BLE & Battery for Model 02 * recommended changes * Recommended changes Model 02 -> 01 (oops) 2x async_block_till_done() not needed. --- .../components/aladdin_connect/model.py | 1 + .../components/aladdin_connect/sensor.py | 15 +++- tests/components/aladdin_connect/conftest.py | 3 + .../components/aladdin_connect/test_sensor.py | 81 ++++++++++++++++++- 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/aladdin_connect/model.py b/homeassistant/components/aladdin_connect/model.py index 63624b223a9..9b250459d3b 100644 --- a/homeassistant/components/aladdin_connect/model.py +++ b/homeassistant/components/aladdin_connect/model.py @@ -12,3 +12,4 @@ class DoorDevice(TypedDict): name: str status: str serial: str + model: str diff --git a/homeassistant/components/aladdin_connect/sensor.py b/homeassistant/components/aladdin_connect/sensor.py index 05db7bc19c5..5fcc75fa27c 100644 --- a/homeassistant/components/aladdin_connect/sensor.py +++ b/homeassistant/components/aladdin_connect/sensor.py @@ -56,6 +56,15 @@ SENSORS: tuple[AccSensorEntityDescription, ...] = ( state_class=SensorStateClass.MEASUREMENT, value_fn=AladdinConnectClient.get_rssi_status, ), + AccSensorEntityDescription( + key="ble_strength", + name="BLE Strength", + device_class=SensorDeviceClass.SIGNAL_STRENGTH, + entity_registry_enabled_default=False, + native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS, + state_class=SensorStateClass.MEASUREMENT, + value_fn=AladdinConnectClient.get_ble_strength, + ), ) @@ -89,14 +98,17 @@ class AladdinConnectSensor(SensorEntity): device: DoorDevice, description: AccSensorEntityDescription, ) -> None: - """Initialize a sensor for an Abode device.""" + """Initialize a sensor for an Aladdin Connect device.""" self._device_id = device["device_id"] self._number = device["door_number"] self._name = device["name"] + self._model = device["model"] self._acc = acc self.entity_description = description self._attr_unique_id = f"{self._device_id}-{self._number}-{description.key}" self._attr_has_entity_name = True + if self._model == "01" and description.key in ("battery_level", "ble_strength"): + self._attr_entity_registry_enabled_default = True @property def device_info(self) -> DeviceInfo | None: @@ -105,6 +117,7 @@ class AladdinConnectSensor(SensorEntity): identifiers={(DOMAIN, f"{self._device_id}-{self._number}")}, name=self._name, manufacturer="Overhead Door", + model=self._model, ) @property diff --git a/tests/components/aladdin_connect/conftest.py b/tests/components/aladdin_connect/conftest.py index c8f7d240ba5..ee9afed9823 100644 --- a/tests/components/aladdin_connect/conftest.py +++ b/tests/components/aladdin_connect/conftest.py @@ -11,6 +11,7 @@ DEVICE_CONFIG_OPEN = { "status": "open", "link_status": "Connected", "serial": "12345", + "model": "02", } @@ -31,6 +32,8 @@ def fixture_mock_aladdinconnect_api(): mock_opener.get_battery_status.return_value = "99" mock_opener.async_get_rssi_status = AsyncMock(return_value="-55") mock_opener.get_rssi_status.return_value = "-55" + mock_opener.async_get_ble_strength = AsyncMock(return_value="-45") + mock_opener.get_ble_strength.return_value = "-45" mock_opener.get_doors = AsyncMock(return_value=[DEVICE_CONFIG_OPEN]) mock_opener.register_callback = mock.Mock(return_value=True) diff --git a/tests/components/aladdin_connect/test_sensor.py b/tests/components/aladdin_connect/test_sensor.py index 3702bcd9efa..282f6d3e04c 100644 --- a/tests/components/aladdin_connect/test_sensor.py +++ b/tests/components/aladdin_connect/test_sensor.py @@ -1,6 +1,6 @@ """Test the Aladdin Connect Sensors.""" from datetime import timedelta -from unittest.mock import MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch from homeassistant.components.aladdin_connect.const import DOMAIN from homeassistant.components.aladdin_connect.cover import SCAN_INTERVAL @@ -10,6 +10,17 @@ from homeassistant.util.dt import utcnow from tests.common import MockConfigEntry, async_fire_time_changed +DEVICE_CONFIG_MODEL_01 = { + "device_id": 533255, + "door_number": 1, + "name": "home", + "status": "closed", + "link_status": "Connected", + "serial": "12345", + "model": "01", +} + + CONFIG = {"username": "test-user", "password": "test-password"} RELOAD_AFTER_UPDATE_DELAY = timedelta(seconds=31) @@ -83,3 +94,71 @@ async def test_sensors( state = hass.states.get("sensor.home_wi_fi_rssi") assert state + + +async def test_sensors_model_01( + hass: HomeAssistant, + mock_aladdinconnect_api: MagicMock, +) -> None: + """Test Sensors for AladdinConnect.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + data=CONFIG, + unique_id="test-id", + ) + config_entry.add_to_hass(hass) + + await hass.async_block_till_done() + + with patch( + "homeassistant.components.aladdin_connect.AladdinConnectClient", + return_value=mock_aladdinconnect_api, + ): + mock_aladdinconnect_api.get_doors = AsyncMock( + return_value=[DEVICE_CONFIG_MODEL_01] + ) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + registry = entity_registry.async_get(hass) + entry = registry.async_get("sensor.home_battery_level") + assert entry + assert entry.disabled is False + assert entry.disabled_by is None + state = hass.states.get("sensor.home_battery_level") + assert state + + entry = registry.async_get("sensor.home_wi_fi_rssi") + await hass.async_block_till_done() + assert entry + assert entry.disabled + assert entry.disabled_by is entity_registry.RegistryEntryDisabler.INTEGRATION + update_entry = registry.async_update_entity( + entry.entity_id, **{"disabled_by": None} + ) + await hass.async_block_till_done() + assert update_entry != entry + assert update_entry.disabled is False + state = hass.states.get("sensor.home_wi_fi_rssi") + assert state is None + + update_entry = registry.async_update_entity( + entry.entity_id, **{"disabled_by": None} + ) + await hass.async_block_till_done() + async_fire_time_changed( + hass, + utcnow() + SCAN_INTERVAL, + ) + await hass.async_block_till_done() + + state = hass.states.get("sensor.home_wi_fi_rssi") + assert state + + entry = registry.async_get("sensor.home_ble_strength") + await hass.async_block_till_done() + assert entry + assert entry.disabled is False + assert entry.disabled_by is None + state = hass.states.get("sensor.home_ble_strength") + assert state