From e6a6b0fc7ddac1b3e2da7e415b742a7b26161bb1 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 09:32:37 +0200 Subject: [PATCH 01/50] Add battery binary_sensor for devices with a battery --- plugwise/util.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugwise/util.py b/plugwise/util.py index 0aba3d2d8..1c3164550 100644 --- a/plugwise/util.py +++ b/plugwise/util.py @@ -138,6 +138,9 @@ def common_match_cases( sp_key = cast(SpecialType, measurement) data[sp_key] = value + if "battery" in data["sensors"]: + data["binary_sensors"]["battery"] = False + def escape_illegal_xml_characters(xmldata: str) -> str: """Replace illegal &-characters.""" From a5acdc78f3f287caa9fbbacc66f705929d8bd113 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 09:42:31 +0200 Subject: [PATCH 02/50] Update device-asserts --- tests/test_adam.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_adam.py b/tests/test_adam.py index 0a97cb10f..7cb70651d 100644 --- a/tests/test_adam.py +++ b/tests/test_adam.py @@ -38,7 +38,7 @@ async def test_connect_adam_zone_per_device(self): assert smile._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE assert smile._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA assert smile._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA - assert self.device_items == 315 + assert self.device_items == 323 assert "af82e4ccf9c548528166d38e560662a4" in self.notifications await smile.delete_notification() @@ -116,7 +116,7 @@ async def test_connect_adam_multiple_devices_per_zone(self): assert smile._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE assert smile._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA assert smile._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA - assert self.device_items == 315 + assert self.device_items == 323 assert "af82e4ccf9c548528166d38e560662a4" in self.notifications @@ -154,7 +154,7 @@ async def test_adam_heatpump_cooling(self): assert smile._last_active["a562019b0b1f47a4bde8ebe3dbe3e8a9"] == WERKDAG_SCHEMA assert smile._last_active["8cf650a4c10c44819e426bed406aec34"] == WERKDAG_SCHEMA assert smile._last_active["5cc21042f87f4b4c94ccb5537c47a53f"] == WERKDAG_SCHEMA - assert self.device_items == 415 + assert self.device_items == 417 await smile.close_connection() await self.disconnect(server, client) @@ -250,7 +250,7 @@ async def test_connect_adam_plus_anna_new(self): assert smile.gateway_id == "da224107914542988a88561b4452b0f6" assert smile._last_active["f2bf9048bef64cc5b6d5110154e33c81"] == "Weekschema" assert smile._last_active["f871b8c4d63549319221e294e4f88074"] == "Badkamer" - assert self.device_items == 147 + assert self.device_items == 149 assert self.device_list == [ "da224107914542988a88561b4452b0f6", "056ee145a816487eaa69243c3280f8bf", @@ -392,7 +392,7 @@ async def test_adam_plus_jip(self): assert smile._last_active["06aecb3d00354375924f50c47af36bd2"] is None assert smile._last_active["d27aede973b54be484f6842d1b2802ad"] is None assert smile._last_active["13228dab8ce04617af318a2888b3c548"] is None - assert self.device_items == 213 + assert self.device_items == 217 # Negative test result = await self.tinker_thermostat( From ad85b79d48c9f2c37a4cbb9d099d35c32b743d1e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 09:49:21 +0200 Subject: [PATCH 03/50] Save updated fixtures --- fixtures/adam_heatpump_cooling/all_data.json | 8 +++++- fixtures/adam_jip/all_data.json | 14 +++++++++- .../all_data.json | 26 ++++++++++++++++++- fixtures/adam_plus_anna_new/all_data.json | 8 +++++- fixtures/adam_zone_per_device/all_data.json | 26 ++++++++++++++++++- fixtures/m_adam_cooling/all_data.json | 8 +++++- fixtures/m_adam_heating/all_data.json | 8 +++++- fixtures/m_adam_jip/all_data.json | 14 +++++++++- .../all_data.json | 26 ++++++++++++++++++- 9 files changed, 129 insertions(+), 9 deletions(-) diff --git a/fixtures/adam_heatpump_cooling/all_data.json b/fixtures/adam_heatpump_cooling/all_data.json index 17be405a5..9c3d887c3 100644 --- a/fixtures/adam_heatpump_cooling/all_data.json +++ b/fixtures/adam_heatpump_cooling/all_data.json @@ -47,6 +47,9 @@ "Weekend", "off" ], + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-10T02:00:00+02:00", @@ -521,6 +524,9 @@ "Weekend", "off" ], + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-10T02:00:00+02:00", @@ -632,7 +638,7 @@ "cooling_present": true, "gateway_id": "7d97fc3117784cfdafe347bcedcbbbcb", "heater_id": "0ca13e8176204ca7bf6f09de59f81c83", - "item_count": 415, + "item_count": 417, "notifications": {}, "reboot": true, "smile_name": "Adam" diff --git a/fixtures/adam_jip/all_data.json b/fixtures/adam_jip/all_data.json index 922b3ddc5..6d89af4a9 100644 --- a/fixtures/adam_jip/all_data.json +++ b/fixtures/adam_jip/all_data.json @@ -3,6 +3,9 @@ "1346fbd8498d4dbcab7e18d51b771f3d": { "active_preset": "no_frost", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -97,6 +100,9 @@ "6f3e9d7084214c21b9dfa46f6eeb8700": { "active_preset": "home", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -152,6 +158,9 @@ "a6abc6a129ee499c88a4d420cc413b47": { "active_preset": "home", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -263,6 +272,9 @@ "f61f1a2535f54f52ad006a3d18e459ca": { "active_preset": "home", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermometer", "firmware": "2020-09-01T02:00:00+02:00", @@ -298,7 +310,7 @@ "cooling_present": false, "gateway_id": "b5c2386c6f6342669e50fe49dd05b188", "heater_id": "e4684553153b44afbef2200885f379dc", - "item_count": 213, + "item_count": 217, "notifications": {}, "reboot": true, "smile_name": "Adam" diff --git a/fixtures/adam_multiple_devices_per_zone/all_data.json b/fixtures/adam_multiple_devices_per_zone/all_data.json index 9c17df507..d3fb29b59 100644 --- a/fixtures/adam_multiple_devices_per_zone/all_data.json +++ b/fixtures/adam_multiple_devices_per_zone/all_data.json @@ -82,6 +82,9 @@ }, "680423ff840043738f42cc7f1ff97a36": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -115,6 +118,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -199,6 +205,9 @@ }, "a2c3583e0a6349358998b760cea82d2a": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -255,6 +264,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-08-02T02:00:00+02:00", "hardware": "255", @@ -306,6 +318,9 @@ }, "d3da73bde12a47d5a6b8f9dad971f2ec": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -339,6 +354,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -379,6 +397,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "thermostatic_radiator_valve", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -421,6 +442,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -473,7 +497,7 @@ "cooling_present": false, "gateway_id": "fe799307f1624099878210aa0b9f1475", "heater_id": "90986d591dcd426cae3ec3e8111ff730", - "item_count": 315, + "item_count": 323, "notifications": { "af82e4ccf9c548528166d38e560662a4": { "warning": "Node Plug (with MAC address 000D6F000D13CB01, in room 'n.a.') has been unreachable since 23:03 2020-01-18. Please check the connection and restart the device." diff --git a/fixtures/adam_plus_anna_new/all_data.json b/fixtures/adam_plus_anna_new/all_data.json index 438084e68..c49338e88 100644 --- a/fixtures/adam_plus_anna_new/all_data.json +++ b/fixtures/adam_plus_anna_new/all_data.json @@ -27,6 +27,9 @@ }, "1772a4ea304041adb83f357b751341ff": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2020-11-04T01:00:00+01:00", "hardware": "1", @@ -184,6 +187,9 @@ "Weekschema", "off" ], + "binary_sensors": { + "battery": false + }, "control_state": "preheating", "dev_class": "zone_thermostat", "firmware": "2016-10-10T02:00:00+02:00", @@ -231,7 +237,7 @@ "cooling_present": false, "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", - "item_count": 147, + "item_count": 149, "notifications": {}, "reboot": true, "smile_name": "Adam" diff --git a/fixtures/adam_zone_per_device/all_data.json b/fixtures/adam_zone_per_device/all_data.json index 119e098fe..90a2902c5 100644 --- a/fixtures/adam_zone_per_device/all_data.json +++ b/fixtures/adam_zone_per_device/all_data.json @@ -82,6 +82,9 @@ }, "680423ff840043738f42cc7f1ff97a36": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -115,6 +118,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -199,6 +205,9 @@ }, "a2c3583e0a6349358998b760cea82d2a": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -255,6 +264,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-08-02T02:00:00+02:00", "hardware": "255", @@ -306,6 +318,9 @@ }, "d3da73bde12a47d5a6b8f9dad971f2ec": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -339,6 +354,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -379,6 +397,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "thermostatic_radiator_valve", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -421,6 +442,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -473,7 +497,7 @@ "cooling_present": false, "gateway_id": "fe799307f1624099878210aa0b9f1475", "heater_id": "90986d591dcd426cae3ec3e8111ff730", - "item_count": 315, + "item_count": 323, "notifications": { "af82e4ccf9c548528166d38e560662a4": { "warning": "Node Plug (with MAC address 000D6F000D13CB01, in room 'n.a.') has been unreachable since 23:03 2020-01-18. Please check the connection and restart the device." diff --git a/fixtures/m_adam_cooling/all_data.json b/fixtures/m_adam_cooling/all_data.json index 759d0094d..e44991367 100644 --- a/fixtures/m_adam_cooling/all_data.json +++ b/fixtures/m_adam_cooling/all_data.json @@ -28,6 +28,9 @@ }, "1772a4ea304041adb83f357b751341ff": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2020-11-04T01:00:00+01:00", "hardware": "1", @@ -116,6 +119,9 @@ "Weekschema", "off" ], + "binary_sensors": { + "battery": false + }, "control_state": "preheating", "dev_class": "zone_thermostat", "firmware": "2016-10-10T02:00:00+02:00", @@ -163,7 +169,7 @@ "cooling_present": true, "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", - "item_count": 147, + "item_count": 149, "notifications": {}, "reboot": true, "smile_name": "Adam" diff --git a/fixtures/m_adam_heating/all_data.json b/fixtures/m_adam_heating/all_data.json index e2c23df42..2db199a15 100644 --- a/fixtures/m_adam_heating/all_data.json +++ b/fixtures/m_adam_heating/all_data.json @@ -33,6 +33,9 @@ }, "1772a4ea304041adb83f357b751341ff": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2020-11-04T01:00:00+01:00", "hardware": "1", @@ -115,6 +118,9 @@ "Weekschema", "off" ], + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-10T02:00:00+02:00", @@ -162,7 +168,7 @@ "cooling_present": false, "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", - "item_count": 147, + "item_count": 149, "notifications": {}, "reboot": true, "smile_name": "Adam" diff --git a/fixtures/m_adam_jip/all_data.json b/fixtures/m_adam_jip/all_data.json index 7888d7778..ae13051d5 100644 --- a/fixtures/m_adam_jip/all_data.json +++ b/fixtures/m_adam_jip/all_data.json @@ -3,6 +3,9 @@ "1346fbd8498d4dbcab7e18d51b771f3d": { "active_preset": "no_frost", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -97,6 +100,9 @@ "6f3e9d7084214c21b9dfa46f6eeb8700": { "active_preset": "home", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -152,6 +158,9 @@ "a6abc6a129ee499c88a4d420cc413b47": { "active_preset": "home", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -263,6 +272,9 @@ "f61f1a2535f54f52ad006a3d18e459ca": { "active_preset": "home", "available": true, + "binary_sensors": { + "battery": false + }, "control_state": "off", "dev_class": "zone_thermometer", "firmware": "2020-09-01T02:00:00+02:00", @@ -298,7 +310,7 @@ "cooling_present": false, "gateway_id": "b5c2386c6f6342669e50fe49dd05b188", "heater_id": "e4684553153b44afbef2200885f379dc", - "item_count": 213, + "item_count": 217, "notifications": {}, "reboot": true, "smile_name": "Adam" diff --git a/fixtures/m_adam_multiple_devices_per_zone/all_data.json b/fixtures/m_adam_multiple_devices_per_zone/all_data.json index c88773abe..12291ddb2 100644 --- a/fixtures/m_adam_multiple_devices_per_zone/all_data.json +++ b/fixtures/m_adam_multiple_devices_per_zone/all_data.json @@ -82,6 +82,9 @@ }, "680423ff840043738f42cc7f1ff97a36": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -115,6 +118,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -199,6 +205,9 @@ }, "a2c3583e0a6349358998b760cea82d2a": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -255,6 +264,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-08-02T02:00:00+02:00", "hardware": "255", @@ -306,6 +318,9 @@ }, "d3da73bde12a47d5a6b8f9dad971f2ec": { "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -339,6 +354,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -371,6 +389,9 @@ "e7693eb9582644e5b865dba8d4447cf1": { "active_preset": "no_frost", "available": true, + "binary_sensors": { + "battery": false + }, "dev_class": "thermostatic_radiator_valve", "firmware": "2019-03-27T01:00:00+01:00", "hardware": "1", @@ -412,6 +433,9 @@ "CV Jessie", "off" ], + "binary_sensors": { + "battery": false + }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", "hardware": "255", @@ -464,7 +488,7 @@ "cooling_present": false, "gateway_id": "fe799307f1624099878210aa0b9f1475", "heater_id": "90986d591dcd426cae3ec3e8111ff730", - "item_count": 315, + "item_count": 323, "notifications": { "af82e4ccf9c548528166d38e560662a4": { "warning": "Node Plug (with MAC address 000D6F000D13CB01, in room 'n.a.') has been unreachable since 23:03 2020-01-18. Please check the connection and restart the device." From d2e6822eef46d58cf0da153a4f2481c498367bdf Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 13:45:14 +0200 Subject: [PATCH 04/50] Find MAC address of device with low battery --- plugwise/helper.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugwise/helper.py b/plugwise/helper.py index b772a770c..38911ec00 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -6,6 +6,7 @@ import asyncio import datetime as dt +import re from typing import cast from plugwise.common import SmileCommon @@ -646,6 +647,14 @@ def _get_plugwise_notifications(self) -> None: msg_type = notification.find("type").text msg = notification.find("message").text self._notifications.update({msg_id: {msg_type: msg}}) + + # Change Battery is low message to update binary_sensor + matches = ["Battery", "below"] + if all(x in msg for x in matches): + mac_pattern = "(?:([0-9A-Fa-f]{2}){8})" + mac_address = re.findall(mac_pattern, msg) + LOGGER.debug("HOI mac_address: %s", mac_address) + LOGGER.debug("Plugwise notifications: %s", self._notifications) except AttributeError: # pragma: no cover LOGGER.debug( From d4e388dafd465bf813c131a7a80ec9d52503cbfa Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:04:03 +0200 Subject: [PATCH 05/50] Adam_plus_anna_new: add battery-low notification --- userdata/adam_plus_anna_new/core.domain_objects.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/userdata/adam_plus_anna_new/core.domain_objects.xml b/userdata/adam_plus_anna_new/core.domain_objects.xml index 67a2e1626..721fea0ea 100644 --- a/userdata/adam_plus_anna_new/core.domain_objects.xml +++ b/userdata/adam_plus_anna_new/core.domain_objects.xml @@ -1834,6 +1834,18 @@ + + message + local + Battery of Lisa is low. + Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%. + + + + 2021-12-07T22:05:22.690+02:00 + 2021-12-07T22:05:22.774+02:00 + + Plugwise 160-01 From e34da5bb23ccc618e8fc397fa8a19f21e0222721 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:11:43 +0200 Subject: [PATCH 06/50] Update corresponding test-json --- tests/data/adam/adam_plus_anna_new.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/adam/adam_plus_anna_new.json b/tests/data/adam/adam_plus_anna_new.json index 911e787b4..49f151e2d 100644 --- a/tests/data/adam/adam_plus_anna_new.json +++ b/tests/data/adam/adam_plus_anna_new.json @@ -10,7 +10,7 @@ "zigbee_mac_address": "000D6F000D5A168D", "vendor": "Plugwise", "binary_sensors": { - "plugwise_notification": false + "plugwise_notification": true }, "sensors": { "outdoor_temperature": 9.19 From 506d91601e4d8d7f4ac4aa6815864947137d38be Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:13:23 +0200 Subject: [PATCH 07/50] Save updated fixtures --- fixtures/adam_plus_anna_new/all_data.json | 8 ++++++-- fixtures/m_adam_cooling/all_data.json | 8 ++++++-- fixtures/m_adam_heating/all_data.json | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/fixtures/adam_plus_anna_new/all_data.json b/fixtures/adam_plus_anna_new/all_data.json index c49338e88..bbd3e16f8 100644 --- a/fixtures/adam_plus_anna_new/all_data.json +++ b/fixtures/adam_plus_anna_new/all_data.json @@ -158,7 +158,7 @@ }, "da224107914542988a88561b4452b0f6": { "binary_sensors": { - "plugwise_notification": false + "plugwise_notification": true }, "dev_class": "gateway", "firmware": "3.7.8", @@ -238,7 +238,11 @@ "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", "item_count": 149, - "notifications": {}, + "notifications": { + "996d1258bed54f8b895be4eafe7a5e4e": { + "message": "Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%." + } + }, "reboot": true, "smile_name": "Adam" } diff --git a/fixtures/m_adam_cooling/all_data.json b/fixtures/m_adam_cooling/all_data.json index e44991367..f180efc7f 100644 --- a/fixtures/m_adam_cooling/all_data.json +++ b/fixtures/m_adam_cooling/all_data.json @@ -84,7 +84,7 @@ }, "da224107914542988a88561b4452b0f6": { "binary_sensors": { - "plugwise_notification": false + "plugwise_notification": true }, "dev_class": "gateway", "firmware": "3.7.8", @@ -170,7 +170,11 @@ "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", "item_count": 149, - "notifications": {}, + "notifications": { + "996d1258bed54f8b895be4eafe7a5e4e": { + "message": "Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%." + } + }, "reboot": true, "smile_name": "Adam" } diff --git a/fixtures/m_adam_heating/all_data.json b/fixtures/m_adam_heating/all_data.json index 2db199a15..04a8c867a 100644 --- a/fixtures/m_adam_heating/all_data.json +++ b/fixtures/m_adam_heating/all_data.json @@ -89,7 +89,7 @@ }, "da224107914542988a88561b4452b0f6": { "binary_sensors": { - "plugwise_notification": false + "plugwise_notification": true }, "dev_class": "gateway", "firmware": "3.7.8", @@ -169,7 +169,11 @@ "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", "item_count": 149, - "notifications": {}, + "notifications": { + "996d1258bed54f8b895be4eafe7a5e4e": { + "message": "Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%." + } + }, "reboot": true, "smile_name": "Adam" } From 50eb35a549219cb32bce9d3b17851d760386bd92 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:13:59 +0200 Subject: [PATCH 08/50] Full test output --- scripts/tests_and_coverage.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/tests_and_coverage.sh b/scripts/tests_and_coverage.sh index b8dd17c9e..2e4a45336 100755 --- a/scripts/tests_and_coverage.sh +++ b/scripts/tests_and_coverage.sh @@ -31,7 +31,8 @@ set +u if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "test_and_coverage" ] ; then # Python tests (rerun with debug if failures) - PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ + # PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || + PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ fi if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "linting" ] ; then From 957e382aef3375226d74df8d8866fa77d5e08fd4 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:25:03 +0200 Subject: [PATCH 09/50] Correct regex --- plugwise/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index 38911ec00..8b0440807 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -651,7 +651,7 @@ def _get_plugwise_notifications(self) -> None: # Change Battery is low message to update binary_sensor matches = ["Battery", "below"] if all(x in msg for x in matches): - mac_pattern = "(?:([0-9A-Fa-f]{2}){8})" + mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" mac_address = re.findall(mac_pattern, msg) LOGGER.debug("HOI mac_address: %s", mac_address) From f0cae50bee82ef74e8f63993e102010fdecedc16 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:37:31 +0200 Subject: [PATCH 10/50] Filter out battery-low notification --- plugwise/helper.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index 8b0440807..478c7580d 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -646,14 +646,17 @@ def _get_plugwise_notifications(self) -> None: msg_id = notification.attrib["id"] msg_type = notification.find("type").text msg = notification.find("message").text - self._notifications.update({msg_id: {msg_type: msg}}) # Change Battery is low message to update binary_sensor matches = ["Battery", "below"] + mac_address: str | None = None if all(x in msg for x in matches): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" mac_address = re.findall(mac_pattern, msg) LOGGER.debug("HOI mac_address: %s", mac_address) + + if mac_address is None: + self._notifications.update({msg_id: {msg_type: msg}}) LOGGER.debug("Plugwise notifications: %s", self._notifications) except AttributeError: # pragma: no cover From 5536e664742e6753547d5184bd4d77e24c93bdf7 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:38:02 +0200 Subject: [PATCH 11/50] Revert "Update corresponding test-json" This reverts commit e34da5bb23ccc618e8fc397fa8a19f21e0222721. --- tests/data/adam/adam_plus_anna_new.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/adam/adam_plus_anna_new.json b/tests/data/adam/adam_plus_anna_new.json index 49f151e2d..911e787b4 100644 --- a/tests/data/adam/adam_plus_anna_new.json +++ b/tests/data/adam/adam_plus_anna_new.json @@ -10,7 +10,7 @@ "zigbee_mac_address": "000D6F000D5A168D", "vendor": "Plugwise", "binary_sensors": { - "plugwise_notification": true + "plugwise_notification": false }, "sensors": { "outdoor_temperature": 9.19 From c21332842689b1244418f31f9b1c12739d9f850f Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:39:03 +0200 Subject: [PATCH 12/50] Ruff fix --- plugwise/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/helper.py b/plugwise/helper.py index 478c7580d..924e89e39 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -654,7 +654,7 @@ def _get_plugwise_notifications(self) -> None: mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" mac_address = re.findall(mac_pattern, msg) LOGGER.debug("HOI mac_address: %s", mac_address) - + if mac_address is None: self._notifications.update({msg_id: {msg_type: msg}}) From c6ec50dfb3f1911a70262c0ec543b684f785287d Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:40:01 +0200 Subject: [PATCH 13/50] Save updated fixtures, again --- fixtures/adam_plus_anna_new/all_data.json | 8 ++------ fixtures/m_adam_cooling/all_data.json | 8 ++------ fixtures/m_adam_heating/all_data.json | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/fixtures/adam_plus_anna_new/all_data.json b/fixtures/adam_plus_anna_new/all_data.json index bbd3e16f8..c49338e88 100644 --- a/fixtures/adam_plus_anna_new/all_data.json +++ b/fixtures/adam_plus_anna_new/all_data.json @@ -158,7 +158,7 @@ }, "da224107914542988a88561b4452b0f6": { "binary_sensors": { - "plugwise_notification": true + "plugwise_notification": false }, "dev_class": "gateway", "firmware": "3.7.8", @@ -238,11 +238,7 @@ "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", "item_count": 149, - "notifications": { - "996d1258bed54f8b895be4eafe7a5e4e": { - "message": "Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%." - } - }, + "notifications": {}, "reboot": true, "smile_name": "Adam" } diff --git a/fixtures/m_adam_cooling/all_data.json b/fixtures/m_adam_cooling/all_data.json index f180efc7f..e44991367 100644 --- a/fixtures/m_adam_cooling/all_data.json +++ b/fixtures/m_adam_cooling/all_data.json @@ -84,7 +84,7 @@ }, "da224107914542988a88561b4452b0f6": { "binary_sensors": { - "plugwise_notification": true + "plugwise_notification": false }, "dev_class": "gateway", "firmware": "3.7.8", @@ -170,11 +170,7 @@ "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", "item_count": 149, - "notifications": { - "996d1258bed54f8b895be4eafe7a5e4e": { - "message": "Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%." - } - }, + "notifications": {}, "reboot": true, "smile_name": "Adam" } diff --git a/fixtures/m_adam_heating/all_data.json b/fixtures/m_adam_heating/all_data.json index 04a8c867a..2db199a15 100644 --- a/fixtures/m_adam_heating/all_data.json +++ b/fixtures/m_adam_heating/all_data.json @@ -89,7 +89,7 @@ }, "da224107914542988a88561b4452b0f6": { "binary_sensors": { - "plugwise_notification": true + "plugwise_notification": false }, "dev_class": "gateway", "firmware": "3.7.8", @@ -169,11 +169,7 @@ "gateway_id": "da224107914542988a88561b4452b0f6", "heater_id": "056ee145a816487eaa69243c3280f8bf", "item_count": 149, - "notifications": { - "996d1258bed54f8b895be4eafe7a5e4e": { - "message": "Battery of Lisa (with MAC address 000D6F000C869B61, in room 'Bathroom') is below 30%." - } - }, + "notifications": {}, "reboot": true, "smile_name": "Adam" } From 8ac4731271d990811a06d1e9e3d0e285fc78e47a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:44:22 +0200 Subject: [PATCH 14/50] Remove no longer valud comment --- plugwise/smile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugwise/smile.py b/plugwise/smile.py index 21f31a237..1b9824508 100644 --- a/plugwise/smile.py +++ b/plugwise/smile.py @@ -129,7 +129,6 @@ def get_all_devices(self) -> None: async def async_update(self) -> PlugwiseData: """Perform an incremental update for updating the various device states.""" - # Perform a full update at day-change self.gw_data: GatewayData = {} self.gw_devices: dict[str, DeviceData] = {} try: From f79cfcf3954fffa141faec962aedff6c7c75ad52 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 14:58:21 +0200 Subject: [PATCH 15/50] Move battery-is-low detection to data.py --- plugwise/data.py | 13 +++++++++++++ plugwise/helper.py | 13 +------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index e1d46caee..e1d67ccf6 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -63,6 +63,19 @@ def _add_or_update_notifications( self, device_id: str, device: DeviceData, data: DeviceData ) -> None: """Helper-function adding or updating the Plugwise notifications.""" + # Use Battery-is-low message to update battery binary_sensor + matches = ["Battery", "below"] + if self._notifications: + for msg_id, notification in self._notifications.items(): + mac_address: str | None = None + if all(x in notification.get("message") for x in matches): + mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" + mac_address = re.findall(mac_pattern, msg) + LOGGER.debug("HOI mac_address: %s", mac_address) + + if mac_address is not None: + self._notifications.pop(msg_id) + if ( device_id == self.gateway_id and ( diff --git a/plugwise/helper.py b/plugwise/helper.py index 924e89e39..bc9bc04b1 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -646,18 +646,7 @@ def _get_plugwise_notifications(self) -> None: msg_id = notification.attrib["id"] msg_type = notification.find("type").text msg = notification.find("message").text - - # Change Battery is low message to update binary_sensor - matches = ["Battery", "below"] - mac_address: str | None = None - if all(x in msg for x in matches): - mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" - mac_address = re.findall(mac_pattern, msg) - LOGGER.debug("HOI mac_address: %s", mac_address) - - if mac_address is None: - self._notifications.update({msg_id: {msg_type: msg}}) - + self._notifications.update({msg_id: {msg_type: msg}}) LOGGER.debug("Plugwise notifications: %s", self._notifications) except AttributeError: # pragma: no cover LOGGER.debug( From 11511b4c031f9fe1e6775926511234817c38106b Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:02:37 +0200 Subject: [PATCH 16/50] Add debugging --- plugwise/data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise/data.py b/plugwise/data.py index e1d67ccf6..3704b7d30 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -66,6 +66,7 @@ def _add_or_update_notifications( # Use Battery-is-low message to update battery binary_sensor matches = ["Battery", "below"] if self._notifications: + lOGGER.debug("HOI: %s", self._notifications) for msg_id, notification in self._notifications.items(): mac_address: str | None = None if all(x in notification.get("message") for x in matches): From 7e44ddb5dbf33315ce1504cfc1ba23c8262245a6 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:04:06 +0200 Subject: [PATCH 17/50] Import LOGGER --- plugwise/data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise/data.py b/plugwise/data.py index 3704b7d30..825fc701d 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -7,6 +7,7 @@ from plugwise.constants import ( ADAM, ANNA, + LOGGER, MAX_SETPOINT, MIN_SETPOINT, NONE, From 0f90d87ef4520fe4fc4f0c87b8459c214457b574 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:05:59 +0200 Subject: [PATCH 18/50] Fix typo --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 825fc701d..75a54dad1 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -67,7 +67,7 @@ def _add_or_update_notifications( # Use Battery-is-low message to update battery binary_sensor matches = ["Battery", "below"] if self._notifications: - lOGGER.debug("HOI: %s", self._notifications) + LOGGER.debug("HOI: %s", self._notifications) for msg_id, notification in self._notifications.items(): mac_address: str | None = None if all(x in notification.get("message") for x in matches): From ba0678ea41065142c04726892e18cf9b7337edf1 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:07:20 +0200 Subject: [PATCH 19/50] Add guarding --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 75a54dad1..78c4fcaa7 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -70,7 +70,7 @@ def _add_or_update_notifications( LOGGER.debug("HOI: %s", self._notifications) for msg_id, notification in self._notifications.items(): mac_address: str | None = None - if all(x in notification.get("message") for x in matches): + if "message" in notification and all(x in notification.get("message") for x in matches): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" mac_address = re.findall(mac_pattern, msg) LOGGER.debug("HOI mac_address: %s", mac_address) From 49b7d9eff66fba4bd9dd13c41b60e467599f8a4e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:08:24 +0200 Subject: [PATCH 20/50] Move import re --- plugwise/data.py | 2 ++ plugwise/helper.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 78c4fcaa7..28ef16884 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -4,6 +4,8 @@ """ from __future__ import annotations +import re + from plugwise.constants import ( ADAM, ANNA, diff --git a/plugwise/helper.py b/plugwise/helper.py index bc9bc04b1..b772a770c 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -6,7 +6,6 @@ import asyncio import datetime as dt -import re from typing import cast from plugwise.common import SmileCommon From d3f74f3970570e39fa531fe6ea3af42c759f73d7 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:10:35 +0200 Subject: [PATCH 21/50] Add walrus for msg --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 28ef16884..f55a28505 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -72,7 +72,7 @@ def _add_or_update_notifications( LOGGER.debug("HOI: %s", self._notifications) for msg_id, notification in self._notifications.items(): mac_address: str | None = None - if "message" in notification and all(x in notification.get("message") for x in matches): + if "message" in notification and all(x in (msg := notification.get("message")) for x in matches): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" mac_address = re.findall(mac_pattern, msg) LOGGER.debug("HOI mac_address: %s", mac_address) From a5351a6ceb86604a08d7ffefa9b66953c033f7f1 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:16:33 +0200 Subject: [PATCH 22/50] Optimize when to execute self._add_or_update_notifications(() --- plugwise/data.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index f55a28505..1dd7593f3 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -57,7 +57,8 @@ def _update_gw_devices(self) -> None: """ for device_id, device in self.gw_devices.items(): data = self._get_device_data(device_id) - self._add_or_update_notifications(device_id, device, data) + if device_id == self.gateway_id: + self._add_or_update_notifications(device_id, device, data) device.update(data) self._update_for_cooling(device) remove_empty_platform_dicts(device) From f17c33ff03c42ca82434afcef2db72196b1fa144 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 15:21:29 +0200 Subject: [PATCH 23/50] Avoid dictionary changed size during iteration --- plugwise/data.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 1dd7593f3..fc72bf85c 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -70,8 +70,7 @@ def _add_or_update_notifications( # Use Battery-is-low message to update battery binary_sensor matches = ["Battery", "below"] if self._notifications: - LOGGER.debug("HOI: %s", self._notifications) - for msg_id, notification in self._notifications.items(): + for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None if "message" in notification and all(x in (msg := notification.get("message")) for x in matches): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" From 84e6ff6af49bc7b57292f1eb7677348541f45893 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 19:59:08 +0200 Subject: [PATCH 24/50] Implement battery-binary_sensor updateing --- plugwise/data.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index fc72bf85c..d63bfa1d6 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -22,6 +22,14 @@ from plugwise.util import remove_empty_platform_dicts +def _update_battery_binary_sensors(device_id: str, device: DeviceData, mac_list: list[str]) -> None: + """Helper-function updating the battery-binary_sensor of battery-power devices.""" + if "battery" in device["binary_sensors"]: + if device["binary_sensors"]["battery"] and device["zigbee_mac_address"] not in mac_list: + device["binary_sensors"]["battery"] = False + if device["zigbee_mac_address"] in mac_list: + device["binary_sensors"]["battery"] = True + class SmileData(SmileHelper): """The Plugwise Smile main class.""" @@ -55,20 +63,24 @@ def _update_gw_devices(self) -> None: Collect data for each device and add to self.gw_devices. """ + mac_list: list[str] = [] for device_id, device in self.gw_devices.items(): data = self._get_device_data(device_id) if device_id == self.gateway_id: - self._add_or_update_notifications(device_id, device, data) + mac_list = self._add_or_update_notifications(device_id, device, data) device.update(data) + if mac_list: + _update_battery_binary_sensors(device_id, device, mac_list) self._update_for_cooling(device) remove_empty_platform_dicts(device) def _add_or_update_notifications( self, device_id: str, device: DeviceData, data: DeviceData - ) -> None: + ) -> list[str] | None: """Helper-function adding or updating the Plugwise notifications.""" # Use Battery-is-low message to update battery binary_sensor matches = ["Battery", "below"] + mac_address_list: list[str] = [] if self._notifications: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None @@ -79,6 +91,7 @@ def _add_or_update_notifications( if mac_address is not None: self._notifications.pop(msg_id) + mac_address_list.append(mac_address) if ( device_id == self.gateway_id @@ -92,6 +105,8 @@ def _add_or_update_notifications( data["binary_sensors"]["plugwise_notification"] = bool(self._notifications) self._count += 1 + return mac_address_list + def _update_for_cooling(self, device: DeviceData) -> None: """Helper-function for adding/updating various cooling-related values.""" # For Anna and heating + cooling, replace setpoint with setpoint_high/_low From 4f0b3960891b645d62386163d55e9ac4e8af5136 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 20:10:02 +0200 Subject: [PATCH 25/50] Debug --- plugwise/data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugwise/data.py b/plugwise/data.py index d63bfa1d6..7bf5ae7f8 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -70,6 +70,7 @@ def _update_gw_devices(self) -> None: mac_list = self._add_or_update_notifications(device_id, device, data) device.update(data) if mac_list: + LOGGER.debug("HOI mac-list: %s", mac_list) _update_battery_binary_sensors(device_id, device, mac_list) self._update_for_cooling(device) remove_empty_platform_dicts(device) From cb7741f0a982f8165c0deb28f1bd1c563f463d7b Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 20:18:41 +0200 Subject: [PATCH 26/50] Try --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 7bf5ae7f8..f0af589ea 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -87,7 +87,7 @@ def _add_or_update_notifications( mac_address: str | None = None if "message" in notification and all(x in (msg := notification.get("message")) for x in matches): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" - mac_address = re.findall(mac_pattern, msg) + mac_address = re.findall(mac_pattern, msg)[0] LOGGER.debug("HOI mac_address: %s", mac_address) if mac_address is not None: From efdcb78d72a8b08e6464c16ddd01b95709cb8e69 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 20:21:16 +0200 Subject: [PATCH 27/50] Save updated fixtures --- fixtures/adam_plus_anna_new/all_data.json | 2 +- fixtures/m_adam_cooling/all_data.json | 2 +- fixtures/m_adam_heating/all_data.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fixtures/adam_plus_anna_new/all_data.json b/fixtures/adam_plus_anna_new/all_data.json index c49338e88..6b850c1c8 100644 --- a/fixtures/adam_plus_anna_new/all_data.json +++ b/fixtures/adam_plus_anna_new/all_data.json @@ -188,7 +188,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery": true }, "control_state": "preheating", "dev_class": "zone_thermostat", diff --git a/fixtures/m_adam_cooling/all_data.json b/fixtures/m_adam_cooling/all_data.json index e44991367..be9cbfa53 100644 --- a/fixtures/m_adam_cooling/all_data.json +++ b/fixtures/m_adam_cooling/all_data.json @@ -120,7 +120,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery": true }, "control_state": "preheating", "dev_class": "zone_thermostat", diff --git a/fixtures/m_adam_heating/all_data.json b/fixtures/m_adam_heating/all_data.json index 2db199a15..7db92408e 100644 --- a/fixtures/m_adam_heating/all_data.json +++ b/fixtures/m_adam_heating/all_data.json @@ -119,7 +119,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery": true }, "control_state": "off", "dev_class": "zone_thermostat", From b37f6affe8bdbfa2b892087cdec125e38f067323 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sun, 11 Aug 2024 20:21:53 +0200 Subject: [PATCH 28/50] Revert "Full test output" This reverts commit 50eb35a549219cb32bce9d3b17851d760386bd92. --- scripts/tests_and_coverage.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/tests_and_coverage.sh b/scripts/tests_and_coverage.sh index 2e4a45336..b8dd17c9e 100755 --- a/scripts/tests_and_coverage.sh +++ b/scripts/tests_and_coverage.sh @@ -31,8 +31,7 @@ set +u if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "test_and_coverage" ] ; then # Python tests (rerun with debug if failures) - # PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || - PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ + PYTHONPATH=$(pwd) pytest -qx tests/ --cov='.' --no-cov-on-fail --cov-report term-missing || PYTHONPATH=$(pwd) pytest -xrpP --log-level debug tests/ fi if [ -z "${GITHUB_ACTIONS}" ] || [ "$1" == "linting" ] ; then From 356f02b582cf86cf8144abc3d91c4c8290bc9828 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 08:11:12 +0200 Subject: [PATCH 29/50] Remove debugging, rearrange code --- plugwise/data.py | 39 ++++++++++++++++++--------------------- plugwise/util.py | 9 +++++++++ 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index f0af589ea..5e5b4e140 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -19,17 +19,9 @@ DeviceData, ) from plugwise.helper import SmileHelper -from plugwise.util import remove_empty_platform_dicts +from plugwise.util import remove_empty_platform_dicts, update_battery_binary_sensors -def _update_battery_binary_sensors(device_id: str, device: DeviceData, mac_list: list[str]) -> None: - """Helper-function updating the battery-binary_sensor of battery-power devices.""" - if "battery" in device["binary_sensors"]: - if device["binary_sensors"]["battery"] and device["zigbee_mac_address"] not in mac_list: - device["binary_sensors"]["battery"] = False - if device["zigbee_mac_address"] in mac_list: - device["binary_sensors"]["battery"] = True - class SmileData(SmileHelper): """The Plugwise Smile main class.""" @@ -67,33 +59,40 @@ def _update_gw_devices(self) -> None: for device_id, device in self.gw_devices.items(): data = self._get_device_data(device_id) if device_id == self.gateway_id: - mac_list = self._add_or_update_notifications(device_id, device, data) + self._add_or_update_notifications(device_id, device, data) + mac_list = self._detect_low_batteries(device_id, device, data) device.update(data) if mac_list: - LOGGER.debug("HOI mac-list: %s", mac_list) - _update_battery_binary_sensors(device_id, device, mac_list) + update_battery_binary_sensors(device_id, device, mac_list) self._update_for_cooling(device) remove_empty_platform_dicts(device) - def _add_or_update_notifications( + def _detect_low_batteries( self, device_id: str, device: DeviceData, data: DeviceData - ) -> list[str] | None: - """Helper-function adding or updating the Plugwise notifications.""" - # Use Battery-is-low message to update battery binary_sensor + ) -> list[str]: + """Helper-function updating the battery binary_sensor status from a Battery-is-low message.""" matches = ["Battery", "below"] mac_address_list: list[str] = [] if self._notifications: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None - if "message" in notification and all(x in (msg := notification.get("message")) for x in matches): + if ( + "message" in notification + and all(x in (msg := notification.get("message")) for x in matches) + ): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" - mac_address = re.findall(mac_pattern, msg)[0] - LOGGER.debug("HOI mac_address: %s", mac_address) + mac_address = re.findall(mac_pattern, msg)[0] # re.findall() outputs a list if mac_address is not None: self._notifications.pop(msg_id) mac_address_list.append(mac_address) + return mac_address_list + + def _add_or_update_notifications( + self, device_id: str, device: DeviceData, data: DeviceData + ) -> None: + """Helper-function adding or updating the Plugwise notifications.""" if ( device_id == self.gateway_id and ( @@ -106,8 +105,6 @@ def _add_or_update_notifications( data["binary_sensors"]["plugwise_notification"] = bool(self._notifications) self._count += 1 - return mac_address_list - def _update_for_cooling(self, device: DeviceData) -> None: """Helper-function for adding/updating various cooling-related values.""" # For Anna and heating + cooling, replace setpoint with setpoint_high/_low diff --git a/plugwise/util.py b/plugwise/util.py index 1c3164550..12d09a3b8 100644 --- a/plugwise/util.py +++ b/plugwise/util.py @@ -245,3 +245,12 @@ def version_to_model(version: str | None) -> str | None: model = HW_MODELS.get(version[-2:] + version[-4:-2] + version[-6:-4]) return model if model is not None else "Unknown" + + +def update_battery_binary_sensors(device_id: str, device: DeviceData, mac_list: list[str]) -> None: + """Helper-function updating the battery-binary_sensor of battery-power devices.""" + if "battery" in device["binary_sensors"]: + if device["binary_sensors"]["battery"] and device["zigbee_mac_address"] not in mac_list: + device["binary_sensors"]["battery"] = False + if device["zigbee_mac_address"] in mac_list: + device["binary_sensors"]["battery"] = True From a4d56b4f7d084913b765fb81646aa1273dd3a135 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 08:29:54 +0200 Subject: [PATCH 30/50] Put lines in correct order --- plugwise/data.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 5e5b4e140..03dbcd625 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -9,7 +9,6 @@ from plugwise.constants import ( ADAM, ANNA, - LOGGER, MAX_SETPOINT, MIN_SETPOINT, NONE, @@ -59,8 +58,8 @@ def _update_gw_devices(self) -> None: for device_id, device in self.gw_devices.items(): data = self._get_device_data(device_id) if device_id == self.gateway_id: - self._add_or_update_notifications(device_id, device, data) mac_list = self._detect_low_batteries(device_id, device, data) + self._add_or_update_notifications(device_id, device, data) device.update(data) if mac_list: update_battery_binary_sensors(device_id, device, mac_list) @@ -70,14 +69,14 @@ def _update_gw_devices(self) -> None: def _detect_low_batteries( self, device_id: str, device: DeviceData, data: DeviceData ) -> list[str]: - """Helper-function updating the battery binary_sensor status from a Battery-is-low message.""" + """Helper-function updating the battery binary_sensor status from a Battery-is-low message.""" matches = ["Battery", "below"] mac_address_list: list[str] = [] if self._notifications: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None if ( - "message" in notification + "message" in notification and all(x in (msg := notification.get("message")) for x in matches) ): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" From 0962607b260eeb0e71356c8f0b5f7dedebf7ac4d Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 19:27:35 +0200 Subject: [PATCH 31/50] Update/correct test-json files --- tests/data/adam/adam_plus_anna_new.json | 3 +++ tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/data/adam/adam_plus_anna_new.json b/tests/data/adam/adam_plus_anna_new.json index 911e787b4..608d4303e 100644 --- a/tests/data/adam/adam_plus_anna_new.json +++ b/tests/data/adam/adam_plus_anna_new.json @@ -70,6 +70,9 @@ "name": "Lisa Badkamer", "zigbee_mac_address": "000D6F000C869B61", "vendor": "Plugwise", + "binary_sensors": { + "battery": true + }, "sensors": { "temperature": 16.5, "setpoint": 18, diff --git a/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json b/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json index e357757de..b08fae87f 100644 --- a/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json +++ b/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json @@ -27,6 +27,9 @@ "available": false }, "e2f4322d57924fa090fbbc48b3a140dc": { + "binary_sensors": { + "battery": false + }, "mode": "off" }, "da224107914542988a88561b4452b0f6": { From b3818388c8247bbb72680a867791f33ca90f8309 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 19:31:22 +0200 Subject: [PATCH 32/50] Remove unneeded lines --- plugwise/util.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugwise/util.py b/plugwise/util.py index 12d09a3b8..29ec75018 100644 --- a/plugwise/util.py +++ b/plugwise/util.py @@ -249,8 +249,5 @@ def version_to_model(version: str | None) -> str | None: def update_battery_binary_sensors(device_id: str, device: DeviceData, mac_list: list[str]) -> None: """Helper-function updating the battery-binary_sensor of battery-power devices.""" - if "battery" in device["binary_sensors"]: - if device["binary_sensors"]["battery"] and device["zigbee_mac_address"] not in mac_list: - device["binary_sensors"]["battery"] = False - if device["zigbee_mac_address"] in mac_list: + if "battery" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list: device["binary_sensors"]["battery"] = True From 4d858b113558aaa792c7e404b9112ea0397e6a1e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 19:36:00 +0200 Subject: [PATCH 33/50] Revert break-out of update_battery_binary_sensors() function --- plugwise/data.py | 10 +++++++--- plugwise/util.py | 6 ------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 03dbcd625..29352c7e4 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -18,7 +18,7 @@ DeviceData, ) from plugwise.helper import SmileHelper -from plugwise.util import remove_empty_platform_dicts, update_battery_binary_sensors +from plugwise.util import remove_empty_platform_dicts class SmileData(SmileHelper): @@ -60,10 +60,14 @@ def _update_gw_devices(self) -> None: if device_id == self.gateway_id: mac_list = self._detect_low_batteries(device_id, device, data) self._add_or_update_notifications(device_id, device, data) + device.update(data) - if mac_list: - update_battery_binary_sensors(device_id, device, mac_list) + + if mac_list and "battery" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list: + device["binary_sensors"]["battery"] = True + self._update_for_cooling(device) + remove_empty_platform_dicts(device) def _detect_low_batteries( diff --git a/plugwise/util.py b/plugwise/util.py index 29ec75018..1c3164550 100644 --- a/plugwise/util.py +++ b/plugwise/util.py @@ -245,9 +245,3 @@ def version_to_model(version: str | None) -> str | None: model = HW_MODELS.get(version[-2:] + version[-4:-2] + version[-6:-4]) return model if model is not None else "Unknown" - - -def update_battery_binary_sensors(device_id: str, device: DeviceData, mac_list: list[str]) -> None: - """Helper-function updating the battery-binary_sensor of battery-power devices.""" - if "battery" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list: - device["binary_sensors"]["battery"] = True From b6f7ace277bbcc61f9d65d46a37bd5067c844e40 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 19:43:23 +0200 Subject: [PATCH 34/50] Add battery to related classes in const.py --- plugwise/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugwise/constants.py b/plugwise/constants.py index 677766796..7d3903bdf 100644 --- a/plugwise/constants.py +++ b/plugwise/constants.py @@ -258,6 +258,7 @@ ] BinarySensorType = Literal[ + "battery", "compressor_state", "cooling_enabled", "cooling_state", @@ -409,6 +410,7 @@ class ModelData(TypedDict): class SmileBinarySensors(TypedDict, total=False): """Smile Binary Sensors class.""" + battery: bool compressor_state: bool cooling_enabled: bool cooling_state: bool From d453c8f7ff8bdffd3e8797935fba09edd01e1e86 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 19:50:05 +0200 Subject: [PATCH 35/50] Unwrap, try fixing mypy errors --- plugwise/data.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 29352c7e4..0e75f6713 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -79,12 +79,10 @@ def _detect_low_batteries( if self._notifications: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None - if ( - "message" in notification - and all(x in (msg := notification.get("message")) for x in matches) - ): + if "message" in notification and all(x in (msg := notification.get("message")) for x in matches): mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" - mac_address = re.findall(mac_pattern, msg)[0] # re.findall() outputs a list + if msg is not None: + mac_address = re.findall(mac_pattern, msg)[0] # re.findall() outputs a list if mac_address is not None: self._notifications.pop(msg_id) From a47ece3279a158592b381094aa044328400bcaed Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 20:07:02 +0200 Subject: [PATCH 36/50] Rearrange adam test-cases --- tests/test_adam.py | 298 ++++++++++++++++++++++----------------------- 1 file changed, 149 insertions(+), 149 deletions(-) diff --git a/tests/test_adam.py b/tests/test_adam.py index 7cb70651d..34e2f57c0 100644 --- a/tests/test_adam.py +++ b/tests/test_adam.py @@ -14,7 +14,155 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outside-init - """Tests for Adam standalone, i.e. not combined with Anna or Jip.""" + """Tests for Adam.""" + + @pytest.mark.asyncio + async def test_connect_adam_plus_anna_new(self): + """Test extended Adam (firmware 3.8) with Anna and a switch-group setup.""" + self.smile_setup = "adam_plus_anna_new" + + testdata = self.load_testdata(SMILE_TYPE, self.smile_setup) + server, smile, client = await self.connect_wrapper() + assert smile.smile_hostname == "smile000000" + + self.validate_test_basics( + _LOGGER, + smile, + smile_type=None, + smile_version="3.7.8", + ) + + await self.device_test(smile, "2023-12-17 00:00:01", testdata) + assert smile.gateway_id == "da224107914542988a88561b4452b0f6" + assert smile._last_active["f2bf9048bef64cc5b6d5110154e33c81"] == "Weekschema" + assert smile._last_active["f871b8c4d63549319221e294e4f88074"] == "Badkamer" + assert self.device_items == 149 + assert self.device_list == [ + "da224107914542988a88561b4452b0f6", + "056ee145a816487eaa69243c3280f8bf", + "67d73d0bd469422db25a618a5fb8eeb0", + "e2f4322d57924fa090fbbc48b3a140dc", + "29542b2b6a6a4169acecc15c72a599b8", + "ad4838d7d35c4d6ea796ee12ae5aedf8", + "1772a4ea304041adb83f357b751341ff", + "854f8a9b0e7e425db97f1f110e1ce4b3", + "2568cc4b9c1e401495d4741a5f89bee1", + "e8ef2a01ed3b4139a53bf749204fe6b4", + ] + + result = await self.tinker_thermostat( + smile, + "f2bf9048bef64cc5b6d5110154e33c81", + good_schedules=["Weekschema", "Badkamer", "Test"], + ) + assert result + + # Special test-case for turning a schedule off based on only the location id. + await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "off") + + # Special test-case for turning a schedule off for a location via the option "off". + await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "on", "off") + + # bad schedule-state test + result = await self.tinker_thermostat_schedule( + smile, + "f2bf9048bef64cc5b6d5110154e33c81", + "bad", + good_schedules=["Badkamer"], + single=True, + ) + assert result + + smile._schedule_old_states["f2bf9048bef64cc5b6d5110154e33c81"][ + "Badkamer" + ] = "off" + result_1 = await self.tinker_thermostat_schedule( + smile, + "f2bf9048bef64cc5b6d5110154e33c81", + "on", + good_schedules=["Badkamer"], + single=True, + ) + result_2 = await self.tinker_thermostat_schedule( + smile, + "f2bf9048bef64cc5b6d5110154e33c81", + "on", + good_schedules=["Badkamer"], + single=True, + ) + assert result_1 and result_2 + + switch_change = await self.tinker_switch( + smile, + "e8ef2a01ed3b4139a53bf749204fe6b4", + ["2568cc4b9c1e401495d4741a5f89bee1", "29542b2b6a6a4169acecc15c72a599b8"], + ) + assert switch_change + switch_change = await self.tinker_switch( + smile, "056ee145a816487eaa69243c3280f8bf", model="dhw_cm_switch" + ) + assert switch_change + switch_change = await self.tinker_switch( + smile, "854f8a9b0e7e425db97f1f110e1ce4b3", model="lock" + ) + assert switch_change + switch_change = await self.tinker_switch( + smile, "2568cc4b9c1e401495d4741a5f89bee1" + ) + assert not switch_change + + tinkered = await self.tinker_gateway_mode(smile) + assert not tinkered + + tinkered = await self.tinker_regulation_mode(smile) + assert not tinkered + + tinkered = await self.tinker_max_boiler_temp(smile) + assert not tinkered + + # Now change some data and change directory reading xml from + # emulating reading newer dataset after an update_interval + testdata_updated = self.load_testdata( + SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA" + ) + self.smile_setup = "updated/adam_plus_anna_new" + await self.device_test( + smile, "2022-01-16 00:00:01", testdata_updated, initialize=False + ) + + # Simulate receiving no xml-data after a requesting a reboot of the gateway + self.smile_setup = "reboot/adam_plus_anna_new" + try: + await self.device_test(smile, initialize=False) + except pw_exceptions.PlugwiseError: + _LOGGER.debug("Receiving no data after a reboot is properly handled") + + # Simulate receiving xml-data with + self.smile_setup = "error/adam_plus_anna_new" + try: + await self.device_test(smile, initialize=False) + except pw_exceptions.ResponseError: + _LOGGER.debug("Receiving error-data from the Gateway") + + await smile.close_connection() + await self.disconnect(server, client) + + self.smile_setup = "adam_plus_anna_new" + testdata = self.load_testdata(SMILE_TYPE, self.smile_setup) + server, smile, client = await self.connect_wrapper(raise_timeout=True) + await self.device_test(smile, "2023-12-17 00:00:01", testdata, skip_testing=True) + + tinkered = await self.tinker_max_boiler_temp(smile, unhappy=True) + assert tinkered + + tinkered = await self.tinker_gateway_mode(smile, unhappy=True) + assert tinkered + + tinkered = await self.tinker_regulation_mode(smile, unhappy=True) + assert tinkered + + await smile.close_connection() + await self.disconnect(server, client) @pytest.mark.asyncio async def test_connect_adam_zone_per_device(self): @@ -230,154 +378,6 @@ async def test_connect_adam_plus_anna(self): await smile.close_connection() await self.disconnect(server, client) - @pytest.mark.asyncio - async def test_connect_adam_plus_anna_new(self): - """Test extended Adam (firmware 3.8) with Anna and a switch-group setup.""" - self.smile_setup = "adam_plus_anna_new" - - testdata = self.load_testdata(SMILE_TYPE, self.smile_setup) - server, smile, client = await self.connect_wrapper() - assert smile.smile_hostname == "smile000000" - - self.validate_test_basics( - _LOGGER, - smile, - smile_type=None, - smile_version="3.7.8", - ) - - await self.device_test(smile, "2023-12-17 00:00:01", testdata) - assert smile.gateway_id == "da224107914542988a88561b4452b0f6" - assert smile._last_active["f2bf9048bef64cc5b6d5110154e33c81"] == "Weekschema" - assert smile._last_active["f871b8c4d63549319221e294e4f88074"] == "Badkamer" - assert self.device_items == 149 - assert self.device_list == [ - "da224107914542988a88561b4452b0f6", - "056ee145a816487eaa69243c3280f8bf", - "67d73d0bd469422db25a618a5fb8eeb0", - "e2f4322d57924fa090fbbc48b3a140dc", - "29542b2b6a6a4169acecc15c72a599b8", - "ad4838d7d35c4d6ea796ee12ae5aedf8", - "1772a4ea304041adb83f357b751341ff", - "854f8a9b0e7e425db97f1f110e1ce4b3", - "2568cc4b9c1e401495d4741a5f89bee1", - "e8ef2a01ed3b4139a53bf749204fe6b4", - ] - - result = await self.tinker_thermostat( - smile, - "f2bf9048bef64cc5b6d5110154e33c81", - good_schedules=["Weekschema", "Badkamer", "Test"], - ) - assert result - - # Special test-case for turning a schedule off based on only the location id. - await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "off") - - # Special test-case for turning a schedule off for a location via the option "off". - await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "on", "off") - - # bad schedule-state test - result = await self.tinker_thermostat_schedule( - smile, - "f2bf9048bef64cc5b6d5110154e33c81", - "bad", - good_schedules=["Badkamer"], - single=True, - ) - assert result - - smile._schedule_old_states["f2bf9048bef64cc5b6d5110154e33c81"][ - "Badkamer" - ] = "off" - result_1 = await self.tinker_thermostat_schedule( - smile, - "f2bf9048bef64cc5b6d5110154e33c81", - "on", - good_schedules=["Badkamer"], - single=True, - ) - result_2 = await self.tinker_thermostat_schedule( - smile, - "f2bf9048bef64cc5b6d5110154e33c81", - "on", - good_schedules=["Badkamer"], - single=True, - ) - assert result_1 and result_2 - - switch_change = await self.tinker_switch( - smile, - "e8ef2a01ed3b4139a53bf749204fe6b4", - ["2568cc4b9c1e401495d4741a5f89bee1", "29542b2b6a6a4169acecc15c72a599b8"], - ) - assert switch_change - switch_change = await self.tinker_switch( - smile, "056ee145a816487eaa69243c3280f8bf", model="dhw_cm_switch" - ) - assert switch_change - switch_change = await self.tinker_switch( - smile, "854f8a9b0e7e425db97f1f110e1ce4b3", model="lock" - ) - assert switch_change - switch_change = await self.tinker_switch( - smile, "2568cc4b9c1e401495d4741a5f89bee1" - ) - assert not switch_change - - tinkered = await self.tinker_gateway_mode(smile) - assert not tinkered - - tinkered = await self.tinker_regulation_mode(smile) - assert not tinkered - - tinkered = await self.tinker_max_boiler_temp(smile) - assert not tinkered - - # Now change some data and change directory reading xml from - # emulating reading newer dataset after an update_interval - testdata_updated = self.load_testdata( - SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA" - ) - self.smile_setup = "updated/adam_plus_anna_new" - await self.device_test( - smile, "2022-01-16 00:00:01", testdata_updated, initialize=False - ) - - # Simulate receiving no xml-data after a requesting a reboot of the gateway - self.smile_setup = "reboot/adam_plus_anna_new" - try: - await self.device_test(smile, initialize=False) - except pw_exceptions.PlugwiseError: - _LOGGER.debug("Receiving no data after a reboot is properly handled") - - # Simulate receiving xml-data with - self.smile_setup = "error/adam_plus_anna_new" - try: - await self.device_test(smile, initialize=False) - except pw_exceptions.ResponseError: - _LOGGER.debug("Receiving error-data from the Gateway") - - await smile.close_connection() - await self.disconnect(server, client) - - self.smile_setup = "adam_plus_anna_new" - testdata = self.load_testdata(SMILE_TYPE, self.smile_setup) - server, smile, client = await self.connect_wrapper(raise_timeout=True) - await self.device_test(smile, "2023-12-17 00:00:01", testdata, skip_testing=True) - - tinkered = await self.tinker_max_boiler_temp(smile, unhappy=True) - assert tinkered - - tinkered = await self.tinker_gateway_mode(smile, unhappy=True) - assert tinkered - - tinkered = await self.tinker_regulation_mode(smile, unhappy=True) - assert tinkered - - await smile.close_connection() - await self.disconnect(server, client) - @pytest.mark.asyncio async def test_adam_plus_jip(self): """Test Adam with Jip setup.""" From 6a1c25d977b1b88f13c7452e35703932f0115233 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 20:17:49 +0200 Subject: [PATCH 37/50] Avoid double naming --- plugwise/constants.py | 4 ++-- plugwise/data.py | 6 +++--- plugwise/util.py | 2 +- tests/data/adam/adam_plus_anna_new.json | 5 ++++- tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/plugwise/constants.py b/plugwise/constants.py index 7d3903bdf..ffe9378b3 100644 --- a/plugwise/constants.py +++ b/plugwise/constants.py @@ -258,7 +258,7 @@ ] BinarySensorType = Literal[ - "battery", + "battery_state", "compressor_state", "cooling_enabled", "cooling_state", @@ -410,7 +410,7 @@ class ModelData(TypedDict): class SmileBinarySensors(TypedDict, total=False): """Smile Binary Sensors class.""" - battery: bool + battery_state: bool compressor_state: bool cooling_enabled: bool cooling_state: bool diff --git a/plugwise/data.py b/plugwise/data.py index 0e75f6713..4cd49d666 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -63,8 +63,8 @@ def _update_gw_devices(self) -> None: device.update(data) - if mac_list and "battery" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list: - device["binary_sensors"]["battery"] = True + if mac_list and "battery_state" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list: + device["binary_sensors"]["battery_state"] = True self._update_for_cooling(device) @@ -73,7 +73,7 @@ def _update_gw_devices(self) -> None: def _detect_low_batteries( self, device_id: str, device: DeviceData, data: DeviceData ) -> list[str]: - """Helper-function updating the battery binary_sensor status from a Battery-is-low message.""" + """Helper-function updating the battery_state binary_sensor status from a Battery-is-low message.""" matches = ["Battery", "below"] mac_address_list: list[str] = [] if self._notifications: diff --git a/plugwise/util.py b/plugwise/util.py index 1c3164550..a818d6d03 100644 --- a/plugwise/util.py +++ b/plugwise/util.py @@ -139,7 +139,7 @@ def common_match_cases( data[sp_key] = value if "battery" in data["sensors"]: - data["binary_sensors"]["battery"] = False + data["binary_sensors"]["battery_state"] = False def escape_illegal_xml_characters(xmldata: str) -> str: diff --git a/tests/data/adam/adam_plus_anna_new.json b/tests/data/adam/adam_plus_anna_new.json index 608d4303e..0073e5101 100644 --- a/tests/data/adam/adam_plus_anna_new.json +++ b/tests/data/adam/adam_plus_anna_new.json @@ -71,7 +71,7 @@ "zigbee_mac_address": "000D6F000C869B61", "vendor": "Plugwise", "binary_sensors": { - "battery": true + "battery_state": true }, "sensors": { "temperature": 16.5, @@ -181,6 +181,9 @@ "name": "Tom Badkamer", "zigbee_mac_address": "000D6F000C8FF5EE", "vendor": "Plugwise", + "binary_sensors": { + "battery_state": false + }, "sensors": { "temperature": 17.6, "setpoint": 18, diff --git a/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json b/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json index b08fae87f..044192bac 100644 --- a/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json +++ b/tests/data/adam/adam_plus_anna_new_UPDATED_DATA.json @@ -28,7 +28,7 @@ }, "e2f4322d57924fa090fbbc48b3a140dc": { "binary_sensors": { - "battery": false + "battery_state": false }, "mode": "off" }, From 11fe01f1a02646c2113bf306eda861cdb18216a7 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 20:20:41 +0200 Subject: [PATCH 38/50] Save updated fixtures --- fixtures/adam_heatpump_cooling/all_data.json | 4 ++-- fixtures/adam_jip/all_data.json | 8 ++++---- .../adam_multiple_devices_per_zone/all_data.json | 16 ++++++++-------- fixtures/adam_plus_anna_new/all_data.json | 4 ++-- fixtures/adam_zone_per_device/all_data.json | 16 ++++++++-------- fixtures/m_adam_cooling/all_data.json | 4 ++-- fixtures/m_adam_heating/all_data.json | 4 ++-- fixtures/m_adam_jip/all_data.json | 8 ++++---- .../all_data.json | 16 ++++++++-------- 9 files changed, 40 insertions(+), 40 deletions(-) diff --git a/fixtures/adam_heatpump_cooling/all_data.json b/fixtures/adam_heatpump_cooling/all_data.json index 9c3d887c3..f77f34504 100644 --- a/fixtures/adam_heatpump_cooling/all_data.json +++ b/fixtures/adam_heatpump_cooling/all_data.json @@ -48,7 +48,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -525,7 +525,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", diff --git a/fixtures/adam_jip/all_data.json b/fixtures/adam_jip/all_data.json index 6d89af4a9..c33e9fdc1 100644 --- a/fixtures/adam_jip/all_data.json +++ b/fixtures/adam_jip/all_data.json @@ -4,7 +4,7 @@ "active_preset": "no_frost", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -101,7 +101,7 @@ "active_preset": "home", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -159,7 +159,7 @@ "active_preset": "home", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -273,7 +273,7 @@ "active_preset": "home", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermometer", diff --git a/fixtures/adam_multiple_devices_per_zone/all_data.json b/fixtures/adam_multiple_devices_per_zone/all_data.json index d3fb29b59..cbc006143 100644 --- a/fixtures/adam_multiple_devices_per_zone/all_data.json +++ b/fixtures/adam_multiple_devices_per_zone/all_data.json @@ -83,7 +83,7 @@ "680423ff840043738f42cc7f1ff97a36": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -119,7 +119,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -206,7 +206,7 @@ "a2c3583e0a6349358998b760cea82d2a": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -265,7 +265,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-08-02T02:00:00+02:00", @@ -319,7 +319,7 @@ "d3da73bde12a47d5a6b8f9dad971f2ec": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -355,7 +355,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -398,7 +398,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermostatic_radiator_valve", "firmware": "2019-03-27T01:00:00+01:00", @@ -443,7 +443,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", diff --git a/fixtures/adam_plus_anna_new/all_data.json b/fixtures/adam_plus_anna_new/all_data.json index 6b850c1c8..c047f2d76 100644 --- a/fixtures/adam_plus_anna_new/all_data.json +++ b/fixtures/adam_plus_anna_new/all_data.json @@ -28,7 +28,7 @@ "1772a4ea304041adb83f357b751341ff": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2020-11-04T01:00:00+01:00", @@ -188,7 +188,7 @@ "off" ], "binary_sensors": { - "battery": true + "battery_state": true }, "control_state": "preheating", "dev_class": "zone_thermostat", diff --git a/fixtures/adam_zone_per_device/all_data.json b/fixtures/adam_zone_per_device/all_data.json index 90a2902c5..5a86937be 100644 --- a/fixtures/adam_zone_per_device/all_data.json +++ b/fixtures/adam_zone_per_device/all_data.json @@ -83,7 +83,7 @@ "680423ff840043738f42cc7f1ff97a36": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -119,7 +119,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -206,7 +206,7 @@ "a2c3583e0a6349358998b760cea82d2a": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -265,7 +265,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-08-02T02:00:00+02:00", @@ -319,7 +319,7 @@ "d3da73bde12a47d5a6b8f9dad971f2ec": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -355,7 +355,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -398,7 +398,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermostatic_radiator_valve", "firmware": "2019-03-27T01:00:00+01:00", @@ -443,7 +443,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", diff --git a/fixtures/m_adam_cooling/all_data.json b/fixtures/m_adam_cooling/all_data.json index be9cbfa53..64092e682 100644 --- a/fixtures/m_adam_cooling/all_data.json +++ b/fixtures/m_adam_cooling/all_data.json @@ -29,7 +29,7 @@ "1772a4ea304041adb83f357b751341ff": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2020-11-04T01:00:00+01:00", @@ -120,7 +120,7 @@ "off" ], "binary_sensors": { - "battery": true + "battery_state": true }, "control_state": "preheating", "dev_class": "zone_thermostat", diff --git a/fixtures/m_adam_heating/all_data.json b/fixtures/m_adam_heating/all_data.json index 7db92408e..a99d4659e 100644 --- a/fixtures/m_adam_heating/all_data.json +++ b/fixtures/m_adam_heating/all_data.json @@ -34,7 +34,7 @@ "1772a4ea304041adb83f357b751341ff": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2020-11-04T01:00:00+01:00", @@ -119,7 +119,7 @@ "off" ], "binary_sensors": { - "battery": true + "battery_state": true }, "control_state": "off", "dev_class": "zone_thermostat", diff --git a/fixtures/m_adam_jip/all_data.json b/fixtures/m_adam_jip/all_data.json index ae13051d5..86508c55e 100644 --- a/fixtures/m_adam_jip/all_data.json +++ b/fixtures/m_adam_jip/all_data.json @@ -4,7 +4,7 @@ "active_preset": "no_frost", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -101,7 +101,7 @@ "active_preset": "home", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -159,7 +159,7 @@ "active_preset": "home", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermostat", @@ -273,7 +273,7 @@ "active_preset": "home", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "control_state": "off", "dev_class": "zone_thermometer", diff --git a/fixtures/m_adam_multiple_devices_per_zone/all_data.json b/fixtures/m_adam_multiple_devices_per_zone/all_data.json index 12291ddb2..b788b43da 100644 --- a/fixtures/m_adam_multiple_devices_per_zone/all_data.json +++ b/fixtures/m_adam_multiple_devices_per_zone/all_data.json @@ -83,7 +83,7 @@ "680423ff840043738f42cc7f1ff97a36": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -119,7 +119,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -206,7 +206,7 @@ "a2c3583e0a6349358998b760cea82d2a": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -265,7 +265,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-08-02T02:00:00+02:00", @@ -319,7 +319,7 @@ "d3da73bde12a47d5a6b8f9dad971f2ec": { "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermo_sensor", "firmware": "2019-03-27T01:00:00+01:00", @@ -355,7 +355,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", @@ -390,7 +390,7 @@ "active_preset": "no_frost", "available": true, "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "thermostatic_radiator_valve", "firmware": "2019-03-27T01:00:00+01:00", @@ -434,7 +434,7 @@ "off" ], "binary_sensors": { - "battery": false + "battery_state": false }, "dev_class": "zone_thermostat", "firmware": "2016-10-27T02:00:00+02:00", From 7c9cb42e897a60f47ac1f84a0be9d14a46a18982 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 20:28:25 +0200 Subject: [PATCH 39/50] Improve code --- plugwise/data.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 4cd49d666..da220e2a7 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -74,15 +74,15 @@ def _detect_low_batteries( self, device_id: str, device: DeviceData, data: DeviceData ) -> list[str]: """Helper-function updating the battery_state binary_sensor status from a Battery-is-low message.""" - matches = ["Battery", "below"] mac_address_list: list[str] = [] + mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" + matches = ["Battery", "below"] if self._notifications: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None - if "message" in notification and all(x in (msg := notification.get("message")) for x in matches): - mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" - if msg is not None: - mac_address = re.findall(mac_pattern, msg)[0] # re.findall() outputs a list + message: str | None = notification.get("message") + if message is not None and all(x in message for x in matches): + mac_address = re.findall(mac_pattern, message)[0] # re.findall() outputs a list if mac_address is not None: self._notifications.pop(msg_id) From bc9601e39220f85fab5dbb98087546836cb907ae Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 12 Aug 2024 20:46:04 +0200 Subject: [PATCH 40/50] Fix 3 CodeSmells --- plugwise/data.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index da220e2a7..a8d7e488f 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -70,9 +70,7 @@ def _update_gw_devices(self) -> None: remove_empty_platform_dicts(device) - def _detect_low_batteries( - self, device_id: str, device: DeviceData, data: DeviceData - ) -> list[str]: + def _detect_low_batteries(self) -> list[str]: """Helper-function updating the battery_state binary_sensor status from a Battery-is-low message.""" mac_address_list: list[str] = [] mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" From a7c4ad3a4f6b4639183a07122cb3262d1d23f69a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 08:14:52 +0200 Subject: [PATCH 41/50] Fix function-call also --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index a8d7e488f..ca8f247f0 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -58,7 +58,7 @@ def _update_gw_devices(self) -> None: for device_id, device in self.gw_devices.items(): data = self._get_device_data(device_id) if device_id == self.gateway_id: - mac_list = self._detect_low_batteries(device_id, device, data) + mac_list = self._detect_low_batteries() self._add_or_update_notifications(device_id, device, data) device.update(data) From b88d1ac83e754dd484b82f95e2382e9dbe9b29c6 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 08:19:54 +0200 Subject: [PATCH 42/50] Implement as suggested --- plugwise/data.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index ca8f247f0..0f649f44a 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -80,7 +80,9 @@ def _detect_low_batteries(self) -> list[str]: mac_address: str | None = None message: str | None = notification.get("message") if message is not None and all(x in message for x in matches): - mac_address = re.findall(mac_pattern, message)[0] # re.findall() outputs a list + mac_addresses = re.findall(mac_pattern, message) + if mac_addresses: + mac_address = mac_addresses[0] # re.findall() outputs a list if mac_address is not None: self._notifications.pop(msg_id) From 109af625ff94e40a4ce81af722ace5b39e79f68a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 08:25:43 +0200 Subject: [PATCH 43/50] Add walrus as suggested --- plugwise/data.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 0f649f44a..8341f18a7 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -79,10 +79,8 @@ def _detect_low_batteries(self) -> list[str]: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None message: str | None = notification.get("message") - if message is not None and all(x in message for x in matches): - mac_addresses = re.findall(mac_pattern, message) - if mac_addresses: - mac_address = mac_addresses[0] # re.findall() outputs a list + if message is not None and all(x in message for x in matches) and (mac_addresses := re.findall(mac_pattern, message)): + mac_address = mac_addresses[0] # re.findall() outputs a list if mac_address is not None: self._notifications.pop(msg_id) From da055269cc6c745e6f027c0f47dd71c30e2098b0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 18:29:56 +0200 Subject: [PATCH 44/50] Update regex pattern --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 8341f18a7..4fa6cd044 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -73,7 +73,7 @@ def _update_gw_devices(self) -> None: def _detect_low_batteries(self) -> list[str]: """Helper-function updating the battery_state binary_sensor status from a Battery-is-low message.""" mac_address_list: list[str] = [] - mac_pattern = "(?:[0-9A-F]{2}){7}(?:[0-9A-F]{2})" + mac_pattern = "(?:[0-9A-F]{2}){8}" matches = ["Battery", "below"] if self._notifications: for msg_id, notification in list(self._notifications.items()): From 9a78d91ddf5eb2c0166d7a04097411f3b57a89f6 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 18:35:41 +0200 Subject: [PATCH 45/50] Change battery_state to true when the percentage is less than 15(%) --- plugwise/data.py | 7 ++++++- tests/data/adam/adam_plus_anna_new.json | 2 +- userdata/adam_plus_anna_new/core.domain_objects.xml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 4fa6cd044..8b72ef964 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -63,7 +63,12 @@ def _update_gw_devices(self) -> None: device.update(data) - if mac_list and "battery_state" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list: + if ( + mac_list + and "battery_state" in device["binary_sensors"] + and device["zigbee_mac_address"] in mac_list + and device["sensors"]["battery"] < 15 + ): device["binary_sensors"]["battery_state"] = True self._update_for_cooling(device) diff --git a/tests/data/adam/adam_plus_anna_new.json b/tests/data/adam/adam_plus_anna_new.json index 0073e5101..55d2a9028 100644 --- a/tests/data/adam/adam_plus_anna_new.json +++ b/tests/data/adam/adam_plus_anna_new.json @@ -76,7 +76,7 @@ "sensors": { "temperature": 16.5, "setpoint": 18, - "battery": 38 + "battery": 14 }, "temperature_offset": { "lower_bound": -2, diff --git a/userdata/adam_plus_anna_new/core.domain_objects.xml b/userdata/adam_plus_anna_new/core.domain_objects.xml index 721fea0ea..574c7f7d7 100644 --- a/userdata/adam_plus_anna_new/core.domain_objects.xml +++ b/userdata/adam_plus_anna_new/core.domain_objects.xml @@ -137,7 +137,7 @@ - 0.38 + 0.14 From 9486b6abf9fd0cd1b1e085fa832aa12f74208444 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 19:21:13 +0200 Subject: [PATCH 46/50] Save updated fixtures --- fixtures/adam_plus_anna_new/all_data.json | 2 +- fixtures/m_adam_cooling/all_data.json | 2 +- fixtures/m_adam_heating/all_data.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fixtures/adam_plus_anna_new/all_data.json b/fixtures/adam_plus_anna_new/all_data.json index c047f2d76..c69356300 100644 --- a/fixtures/adam_plus_anna_new/all_data.json +++ b/fixtures/adam_plus_anna_new/all_data.json @@ -201,7 +201,7 @@ "preset_modes": ["no_frost", "asleep", "vacation", "home", "away"], "select_schedule": "Badkamer", "sensors": { - "battery": 38, + "battery": 14, "setpoint": 18.0, "temperature": 16.5 }, diff --git a/fixtures/m_adam_cooling/all_data.json b/fixtures/m_adam_cooling/all_data.json index 64092e682..2806e0cba 100644 --- a/fixtures/m_adam_cooling/all_data.json +++ b/fixtures/m_adam_cooling/all_data.json @@ -133,7 +133,7 @@ "preset_modes": ["no_frost", "asleep", "vacation", "home", "away"], "select_schedule": "Badkamer", "sensors": { - "battery": 38, + "battery": 14, "setpoint": 23.5, "temperature": 23.9 }, diff --git a/fixtures/m_adam_heating/all_data.json b/fixtures/m_adam_heating/all_data.json index a99d4659e..447d7bd2d 100644 --- a/fixtures/m_adam_heating/all_data.json +++ b/fixtures/m_adam_heating/all_data.json @@ -132,7 +132,7 @@ "preset_modes": ["no_frost", "asleep", "vacation", "home", "away"], "select_schedule": "Badkamer", "sensors": { - "battery": 38, + "battery": 14, "setpoint": 15.0, "temperature": 17.9 }, From f2276fcafd2a9c6da386f9257434ed58f263b125 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 19:27:03 +0200 Subject: [PATCH 47/50] Implement coderabbitai suggestions --- plugwise/data.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 8b72ef964..f348e6a69 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -63,12 +63,13 @@ def _update_gw_devices(self) -> None: device.update(data) - if ( + is_battery_low = ( mac_list and "battery_state" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list and device["sensors"]["battery"] < 15 - ): + ) + if is_battery_low: device["binary_sensors"]["battery_state"] = True self._update_for_cooling(device) @@ -78,13 +79,13 @@ def _update_gw_devices(self) -> None: def _detect_low_batteries(self) -> list[str]: """Helper-function updating the battery_state binary_sensor status from a Battery-is-low message.""" mac_address_list: list[str] = [] - mac_pattern = "(?:[0-9A-F]{2}){8}" + mac_pattern = re.compile(r"(?:[0-9A-F]{2}){8}") matches = ["Battery", "below"] if self._notifications: for msg_id, notification in list(self._notifications.items()): mac_address: str | None = None message: str | None = notification.get("message") - if message is not None and all(x in message for x in matches) and (mac_addresses := re.findall(mac_pattern, message)): + if message is not None and all(x in message for x in matches) and (mac_addresses := mac_pattern.findall(message)): mac_address = mac_addresses[0] # re.findall() outputs a list if mac_address is not None: From 3a19eae01a636e066729e74aa34949fb1febcd91 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 19:41:18 +0200 Subject: [PATCH 48/50] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c540c4b..d711eab69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v1.1.0 + +- New Feature: add a battery_state binary_sensor for battery-powered devices and block the related battery-low notifications. + ## v1.0.0 - First formal release to v1.0.0! From ad1ac0df20162a26c78318d9afa2abb50b407dd0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 19:52:49 +0200 Subject: [PATCH 49/50] Add different battery-level limits for different device-types --- plugwise/data.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index f348e6a69..603a6988d 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -67,7 +67,10 @@ def _update_gw_devices(self) -> None: mac_list and "battery_state" in device["binary_sensors"] and device["zigbee_mac_address"] in mac_list - and device["sensors"]["battery"] < 15 + and ( + (device["dev_class"] in ("thermo_sensor", "thermostatic_radiator_valve") and device["sensors"]["battery"] < 30) + or (device["dev_class"] in ("zone_thermometer", "zone_thermostat") and device["sensors"]["battery"] < 15) + ) ) if is_battery_low: device["binary_sensors"]["battery_state"] = True From 4efa17561978c89a01800d41d2a1e1f036470607 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 13 Aug 2024 20:10:47 +0200 Subject: [PATCH 50/50] Bump to v1.1.0a0 test-version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f7010951e..43d584380 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise" -version = "1.0.0" +version = "1.1.0a0" license = {file = "LICENSE"} description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3." readme = "README.md"