From b23c6a1e534d53451a44b6de2140bee8a66cbb66 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:00:51 +0530 Subject: [PATCH 01/12] water_sensor capability --- src/dirigera/hub/hub.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/dirigera/hub/hub.py b/src/dirigera/hub/hub.py index e3047b1..b8eaf47 100644 --- a/src/dirigera/hub/hub.py +++ b/src/dirigera/hub/hub.py @@ -342,6 +342,24 @@ def get_scene_by_id(self, scene_id: str) -> Scene: data = self.get(f"/scenes/{scene_id}") return dict_to_scene(data, self) + def get_water_sensors(self) -> List[WaterSensor]: + """ + Fetches all water sensors registered in the Hub + """ + devices = self.get("/devices") + water_sensors = list(filter(lambda x: x["type"] == "waterSensor", devices)) + return [dict_to_water_sensor(water_sensor, self) for water_sensor in water_sensors] + + def get_water_sensor_by_id(self, id_: str) -> WaterSensor: + """ + Fetches a water sensor by its id + if that water sensors does not exist or is a device of another type raises ValueError + """ + water_sensor = self._get_device_data_by_id(id_) + if water_sensor["type"] != "waterSensor": + raise ValueError("Device is not a WaterSensor") + return dict_to_water_sensor(water_sensor, self) + def get_all_devices(self) -> List[Device]: """ Fetches all devices registered in the Hub From f7a0ee6f4638bb334208665619edd39a22c73d47 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:03:22 +0530 Subject: [PATCH 02/12] Create water_sensor.py --- src/dirigera/devices/water_sensor.py | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/dirigera/devices/water_sensor.py diff --git a/src/dirigera/devices/water_sensor.py b/src/dirigera/devices/water_sensor.py new file mode 100644 index 0000000..6d9605b --- /dev/null +++ b/src/dirigera/devices/water_sensor.py @@ -0,0 +1,30 @@ +from __future__ import annotations +from typing import Any, Dict +from .device import Attributes, Device +from ..hub.abstract_smart_home_hub import AbstractSmartHomeHub + + +class WaterSensorAttributes(Attributes): + battery_percentage: int + water_leak_detected: bool + +class WaterSensor(Device): + dirigera_client: AbstractSmartHomeHub + attributes: WaterSensorAttributes + + def reload(self) -> WaterSensor: + data = self.dirigera_client.get(route=f"/devices/{self.id}") + return WaterSensor(dirigeraClient=self.dirigera_client, **data) + + def set_name(self, name: str) -> None: + if "customName" not in self.capabilities.can_receive: + raise AssertionError("This sensor does not support the set_name function") + + data = [{"attributes": {"customName": name}}] + self.dirigera_client.patch(route=f"/devices/{self.id}", data=data) + self.attributes.custom_name = name + +def dict_to_water_sensor( + data: Dict[str, Any], dirigera_client: AbstractSmartHomeHub +) -> WaterSensor: + return WaterSensor(dirigeraClient=dirigera_client, **data) From c96cb4806e6137d5f2d8436312d249705f35a8c5 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:06:00 +0530 Subject: [PATCH 03/12] Create test_water_sensor.py --- tests/test_water_sensor.py | 127 +++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 tests/test_water_sensor.py diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py new file mode 100644 index 0000000..4b1dbf1 --- /dev/null +++ b/tests/test_water_sensor.py @@ -0,0 +1,127 @@ +from typing import Any, Dict +import pytest +from src.dirigera.hub.abstract_smart_home_hub import FakeDirigeraHub +from src.dirigera.devices.water_sensor import dict_to_water_sensor +from src.dirigera.devices.water_sensor import WaterSensor +from src.dirigera.devices.device import StartupEnum + + +@pytest.fixture(name="fake_client") +def fixture_fake_client() -> FakeDirigeraHub: + return FakeDirigeraHub() + + +@pytest.fixture(name="fake_water_sensor_dict") +def fixture_water_sensor_dict() -> Dict: + return { + "id": "2b107b0b-73f0-4809-a900-4783273d7104_1", + "type": "sensor", + "deviceType": "waterSensor", + "createdAt": "2024-04-17T12:19:50.000Z", + "isReachable": True, + "lastSeen": "2024-04-17T12:34:42.000Z", + "attributes": { + "customName": "Watermelder", + "firmwareVersion": "1.0.7", + "hardwareVersion": "1", + "manufacturer": "IKEA of Sweden", + "model": "BADRING Water Leakage Sensor", + "productCode": "E2202", + "serialNumber": "3410F4FFFE8F815D", + "batteryPercentage": 100, + "waterLeakDetected": False, + "permittingJoin": False, + "otaPolicy": "autoUpdate", + "otaProgress": 0, + "otaScheduleEnd": "00:00", + "otaScheduleStart": "00:00", + "otaState": "readyToCheck", + "otaStatus": "upToDate" + }, + "capabilities": { + "canSend": [], + "canReceive": [ +"customName" + ] + }, + "room": { + "id": "f1743e4c-3a87-4f6b-90a4-3e915b8ed753", + "name": "Zolder", + "color": "ikea_pink_no_8", + "icon": "rooms_washing_machine" + }, + "deviceSet": [], + "remoteLinks": [], + "isHidden": False + } + + +@pytest.fixture(name="fake_water_sensor") +def fixture_water_sensor(fake_water_sensor_dict: Dict, fake_client: FakeDirigeraHub) -> WaterSensor: + return WaterSensor(dirigeraClient=fake_client, **fake_water_sensor_dict) + +def test_set_name(fake_water_sensor: WaterSensor, fake_client: FakeDirigeraHub) -> None: + new_name = "teapot" + fake_water_sensor.set_name(new_name) + action = fake_client.patch_actions.pop() + assert action["route"] == f"/devices/{fake_water_sensor.id}" + assert action["data"] == [{"attributes": {"customName": new_name}}] + assert fake_water_sensor.attributes.custom_name == new_name + +def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: + data = { + "id": "2b107b0b-73f0-4809-a900-4783273d7104_1", + "type": "sensor", + "deviceType": "waterSensor", + "createdAt": "2024-04-17T12:19:50.000Z", + "isReachable": True, + "lastSeen": "2024-04-17T12:34:42.000Z", + "attributes": { + "customName": "Watermelder", + "firmwareVersion": "1.0.7", + "hardwareVersion": "1", + "manufacturer": "IKEA of Sweden", + "model": "BADRING Water Leakage Sensor", + "productCode": "E2202", + "serialNumber": "3410F4FFFE8F815D", + "batteryPercentage": 100, + "waterLeakDetected": False, + "permittingJoin": False, + "otaPolicy": "autoUpdate", + "otaProgress": 0, + "otaScheduleEnd": "00:00", + "otaScheduleStart": "00:00", + "otaState": "readyToCheck", + "otaStatus": "upToDate" + }, + "capabilities": { + "canSend": [], + "canReceive": [ + "customName" + ] + }, + "room": { + "id": "f1743e4c-3a87-4f6b-90a4-3e915b8ed753", + "name": "Zolder", + "color": "ikea_pink_no_8", + "icon": "rooms_washing_machine" + }, + "deviceSet": [], + "remoteLinks": [], + "isHidden": False + } + water_sensor = dict_to_water_sensor(data, fake_client) + assert water_sensor.dirigera_client == fake_client + assert water_sensor.id == data["id"] + assert water_sensor.is_reachable == data["isReachable"] + assert water_sensor.attributes.battery_percentage == data["attributes"]["batteryPercentage"] + assert water_sensor.attributes.water_leak_detected == data["attributes"]["waterLeakDetected"] + assert water_sensor.attributes.custom_name == data["attributes"]["customName"] + assert water_sensor.capabilities.can_receive == data["capabilities"]["canReceive"] + assert water_sensor.room.id == data["room"]["id"] + assert water_sensor.room.name == data["room"]["name"] + assert water_sensor.attributes.firmware_version == data["attributes"]["firmwareVersion"] + assert water_sensor.attributes.hardware_version == data["attributes"]["hardwareVersion"] + assert water_sensor.attributes.model == data["attributes"]["model"] + assert water_sensor.attributes.manufacturer == data["attributes"]["manufacturer"] + assert water_sensor.attributes.serial_number == data["attributes"]["serialNumber"] From e8bac505ea7b555a84af10022724f277074cae3a Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:14:37 +0530 Subject: [PATCH 04/12] Update hub.py --- src/dirigera/hub/hub.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dirigera/hub/hub.py b/src/dirigera/hub/hub.py index b8eaf47..9dd52b5 100644 --- a/src/dirigera/hub/hub.py +++ b/src/dirigera/hub/hub.py @@ -19,6 +19,7 @@ from ..devices.motion_sensor import MotionSensor, dict_to_motion_sensor from ..devices.open_close_sensor import OpenCloseSensor, dict_to_open_close_sensor from ..devices.scene import Action, Info, Scene, SceneType, Trigger, dict_to_scene +from ..devices.water_sensor import WaterSensor, dict_to_water_sensor urllib3.disable_warnings(category=InsecureRequestWarning) From 20739723fac8483c4554c36f93ecbab0e71bbff1 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:19:38 +0530 Subject: [PATCH 05/12] Update water_sensor.py --- src/dirigera/devices/water_sensor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dirigera/devices/water_sensor.py b/src/dirigera/devices/water_sensor.py index 6d9605b..5f21755 100644 --- a/src/dirigera/devices/water_sensor.py +++ b/src/dirigera/devices/water_sensor.py @@ -3,7 +3,6 @@ from .device import Attributes, Device from ..hub.abstract_smart_home_hub import AbstractSmartHomeHub - class WaterSensorAttributes(Attributes): battery_percentage: int water_leak_detected: bool From 1848166a02fb691143666525b90307aea33e484d Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:20:54 +0530 Subject: [PATCH 06/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index 4b1dbf1..cafa55e 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -3,8 +3,6 @@ from src.dirigera.hub.abstract_smart_home_hub import FakeDirigeraHub from src.dirigera.devices.water_sensor import dict_to_water_sensor from src.dirigera.devices.water_sensor import WaterSensor -from src.dirigera.devices.device import StartupEnum - @pytest.fixture(name="fake_client") def fixture_fake_client() -> FakeDirigeraHub: From 8f55431c60fe2819bbac50886d34bb9f458ee7ee Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:22:24 +0530 Subject: [PATCH 07/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index cafa55e..760f7ff 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -1,4 +1,4 @@ -from typing import Any, Dict +from typing import Dict import pytest from src.dirigera.hub.abstract_smart_home_hub import FakeDirigeraHub from src.dirigera.devices.water_sensor import dict_to_water_sensor From 174c9201f2652fcab05699e0855bbbfe45b5fa88 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:34:20 +0530 Subject: [PATCH 08/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index 760f7ff..bf7030b 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -112,8 +112,8 @@ def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: assert water_sensor.dirigera_client == fake_client assert water_sensor.id == data["id"] assert water_sensor.is_reachable == data["isReachable"] - assert water_sensor.attributes.battery_percentage == data["attributes"]["batteryPercentage"] - assert water_sensor.attributes.water_leak_detected == data["attributes"]["waterLeakDetected"] + assert water_sensor.attributes.battery_percentage == 100 + assert ! water_sensor.attributes.water_leak_detected assert water_sensor.attributes.custom_name == data["attributes"]["customName"] assert water_sensor.capabilities.can_receive == data["capabilities"]["canReceive"] assert water_sensor.room.id == data["room"]["id"] From cf6d1fa706afeb6bcb7ba30e5b1c0dadb12cd3cb Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:35:41 +0530 Subject: [PATCH 09/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index bf7030b..6ec6c29 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -113,7 +113,7 @@ def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: assert water_sensor.id == data["id"] assert water_sensor.is_reachable == data["isReachable"] assert water_sensor.attributes.battery_percentage == 100 - assert ! water_sensor.attributes.water_leak_detected + #assert water_sensor.attributes.water_leak_detected assert water_sensor.attributes.custom_name == data["attributes"]["customName"] assert water_sensor.capabilities.can_receive == data["capabilities"]["canReceive"] assert water_sensor.room.id == data["room"]["id"] From 14f62cc9dcc4f75140ac455adc52aa0b0eb6c758 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:36:46 +0530 Subject: [PATCH 10/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index 6ec6c29..8aef607 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -113,7 +113,6 @@ def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: assert water_sensor.id == data["id"] assert water_sensor.is_reachable == data["isReachable"] assert water_sensor.attributes.battery_percentage == 100 - #assert water_sensor.attributes.water_leak_detected assert water_sensor.attributes.custom_name == data["attributes"]["customName"] assert water_sensor.capabilities.can_receive == data["capabilities"]["canReceive"] assert water_sensor.room.id == data["room"]["id"] From 5d17337cafc703bcdcf59a55280bfff15697dfc0 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:39:12 +0530 Subject: [PATCH 11/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index 8aef607..c6be9d0 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -27,7 +27,7 @@ def fixture_water_sensor_dict() -> Dict: "productCode": "E2202", "serialNumber": "3410F4FFFE8F815D", "batteryPercentage": 100, - "waterLeakDetected": False, + "waterLeakDetected": True, "permittingJoin": False, "otaPolicy": "autoUpdate", "otaProgress": 0, @@ -83,7 +83,7 @@ def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: "productCode": "E2202", "serialNumber": "3410F4FFFE8F815D", "batteryPercentage": 100, - "waterLeakDetected": False, + "waterLeakDetected": True, "permittingJoin": False, "otaPolicy": "autoUpdate", "otaProgress": 0, @@ -113,12 +113,4 @@ def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: assert water_sensor.id == data["id"] assert water_sensor.is_reachable == data["isReachable"] assert water_sensor.attributes.battery_percentage == 100 - assert water_sensor.attributes.custom_name == data["attributes"]["customName"] - assert water_sensor.capabilities.can_receive == data["capabilities"]["canReceive"] - assert water_sensor.room.id == data["room"]["id"] - assert water_sensor.room.name == data["room"]["name"] - assert water_sensor.attributes.firmware_version == data["attributes"]["firmwareVersion"] - assert water_sensor.attributes.hardware_version == data["attributes"]["hardwareVersion"] - assert water_sensor.attributes.model == data["attributes"]["model"] - assert water_sensor.attributes.manufacturer == data["attributes"]["manufacturer"] - assert water_sensor.attributes.serial_number == data["attributes"]["serialNumber"] + assert water_sensor.attributes.water_leak_detected From 44b44290967e8ec0c1cc0739d13be86ab3cecac6 Mon Sep 17 00:00:00 2001 From: Sanjoy Ghosh Date: Wed, 17 Apr 2024 21:40:13 +0530 Subject: [PATCH 12/12] Update test_water_sensor.py --- tests/test_water_sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_water_sensor.py b/tests/test_water_sensor.py index c6be9d0..a55c5e5 100644 --- a/tests/test_water_sensor.py +++ b/tests/test_water_sensor.py @@ -113,4 +113,4 @@ def test_dict_to_water_sensor(fake_client: FakeDirigeraHub) -> None: assert water_sensor.id == data["id"] assert water_sensor.is_reachable == data["isReachable"] assert water_sensor.attributes.battery_percentage == 100 - assert water_sensor.attributes.water_leak_detected + assert water_sensor.attributes.water_leak_detected