From 83cbecd43efb5418be6b511b3388edffc0a57c1b Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Fri, 15 Nov 2024 11:19:58 +0000 Subject: [PATCH 01/11] Make overlay_active functional --- src/tadoasync/tadoasync.py | 4 +++ tests/__snapshots__/test_tado.ambr | 42 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/tadoasync/tadoasync.py b/src/tadoasync/tadoasync.py index e5bd77e..5fdccf8 100644 --- a/src/tadoasync/tadoasync.py +++ b/src/tadoasync/tadoasync.py @@ -256,6 +256,7 @@ async def get_zone_state(self, zone_id: int) -> ZoneState: """Get the zone state.""" response = await self._request(f"homes/{self._home_id}/zones/{zone_id}/state") zone_state = ZoneState.from_json(response) + await self.update_zone_data(zone_state) return zone_state @@ -537,6 +538,9 @@ async def update_zone_data(self, data: ZoneState) -> None: # pylint: disable=to data.current_hvac_mode, CONST_HVAC_COOL ) + # The overlay is active if the current mode is not smart schedule + data.overlay_active = data.current_hvac_mode != CONST_MODE_SMART_SCHEDULE + if data.activity_data_points.heating_power is not None: # This needs to be validated if this is actually in! data.heating_power = data.heating_power = ( diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 78f26b2..b3fd5bd 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -316,7 +316,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -424,7 +424,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -532,7 +532,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -640,7 +640,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -743,7 +743,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -851,7 +851,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -959,7 +959,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -1062,7 +1062,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -1170,7 +1170,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', @@ -1259,7 +1259,7 @@ 'open_window_attr': None, 'open_window_detected': False, 'overlay': None, - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': None, 'overlay_type': None, @@ -1367,7 +1367,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -1469,7 +1469,7 @@ 'open_window_attr': None, 'open_window_detected': False, 'overlay': None, - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': None, 'overlay_type': None, @@ -1577,7 +1577,7 @@ 'open_window_attr': None, 'open_window_detected': False, 'overlay': None, - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': None, 'overlay_type': None, @@ -1709,7 +1709,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -1851,7 +1851,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -1992,7 +1992,7 @@ 'termination': None, 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': None, 'overlay_type': 'MANUAL', @@ -2137,7 +2137,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -2267,7 +2267,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -2360,7 +2360,7 @@ 'open_window_attr': None, 'open_window_detected': False, 'overlay': None, - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': None, 'overlay_type': None, @@ -2467,7 +2467,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', @@ -2569,7 +2569,7 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', From 99028f67bdae318aa67fdfaf1ba2097b393f8550 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Sun, 17 Nov 2024 19:50:46 +0000 Subject: [PATCH 02/11] Update the model --- src/tadoasync/models.py | 25 ++-- tests/__snapshots__/test_tado.ambr | 192 ++++++++++++++++++++++++++++- tests/fixtures/zones_no_owd.json | 150 ++++++++++++++++++++++ tests/test_tado.py | 12 ++ 4 files changed, 368 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/zones_no_owd.json diff --git a/src/tadoasync/models.py b/src/tadoasync/models.py index c523865..410fbbf 100644 --- a/src/tadoasync/models.py +++ b/src/tadoasync/models.py @@ -171,13 +171,24 @@ class Zone(DataClassORJSONMixin): # pylint: disable=too-many-instance-attribute date_created: str = field(metadata=field_options(alias="dateCreated")) device_types: list[str] = field(metadata=field_options(alias="deviceTypes")) devices: list[Device] - report_available: bool = field(metadata=field_options(alias="reportAvailable")) - show_schedule_detup: bool = field(metadata=field_options(alias="showScheduleSetup")) - supports_dazzle: bool = field(metadata=field_options(alias="supportsDazzle")) - dazzle_enabled: bool = field(metadata=field_options(alias="dazzleEnabled")) - dazzle_mode: DazzleMode = field(metadata=field_options(alias="dazzleMode")) - open_window_detection: OpenWindowDetection = field( - metadata=field_options(alias="openWindowDetection") + dazzle_mode: DazzleMode | None = field( + metadata=field_options(alias="dazzleMode"), + default=None, + ) + open_window_detection: OpenWindowDetection | None = field( + metadata=field_options(alias="openWindowDetection"), default=None + ) + report_available: bool = field( + metadata=field_options(alias="reportAvailable"), default=False + ) + show_schedule_setup: bool = field( + metadata=field_options(alias="showScheduleSetup"), default=False + ) + supports_dazzle: bool = field( + metadata=field_options(alias="supportsDazzle"), default=False + ) + dazzle_enabled: bool = field( + metadata=field_options(alias="dazzleEnabled"), default=False ) diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index b3fd5bd..0025411 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -3359,7 +3359,7 @@ 'timeout_in_seconds': 900, }), 'report_available': False, - 'show_schedule_detup': False, + 'show_schedule_setup': False, 'supports_dazzle': True, 'type': 'HEATING', }), @@ -3408,7 +3408,7 @@ 'timeout_in_seconds': 900, }), 'report_available': False, - 'show_schedule_detup': True, + 'show_schedule_setup': True, 'supports_dazzle': True, 'type': 'HEATING', }), @@ -3457,7 +3457,7 @@ 'timeout_in_seconds': 900, }), 'report_available': False, - 'show_schedule_detup': True, + 'show_schedule_setup': True, 'supports_dazzle': True, 'type': 'HEATING', }), @@ -3506,7 +3506,191 @@ 'timeout_in_seconds': 900, }), 'report_available': False, - 'show_schedule_detup': True, + 'show_schedule_setup': True, + 'supports_dazzle': True, + 'type': 'HEATING', + }), + ]) +# --- +# name: test_get_zones_no_owd + list([ + dict({ + 'date_created': '2023-04-12T12:58:12.737Z', + 'dazzle_enabled': True, + 'dazzle_mode': dict({ + 'enabled': True, + 'supported': True, + }), + 'device_types': list([ + 'VA02', + ]), + 'devices': list([ + dict({ + 'battery_state': 'NORMAL', + 'characteristics': dict({ + 'capabilities': list([ + 'INSIDE_TEMPERATURE_MEASUREMENT', + 'IDENTIFY', + ]), + }), + 'child_lock_enabled': True, + 'connection_state': dict({ + 'timestamp': '2024-02-27T20:30:13.976Z', + 'value': True, + }), + 'current_fw_version': '95.1', + 'device_type': 'VA02', + 'in_pairing_mode': None, + 'mounting_state': dict({ + 'timestamp': '2024-02-04T10:17:00.266Z', + 'value': 'CALIBRATED', + }), + 'mounting_state_with_error': 'CALIBRATED', + 'orientation': 'HORIZONTAL', + 'serial_no': 'Serial1', + 'short_serial_no': 'ShortSerial1', + }), + ]), + 'id': 2, + 'name': 'Zone1', + 'open_window_detection': None, + 'report_available': False, + 'show_schedule_setup': False, + 'supports_dazzle': True, + 'type': 'HEATING', + }), + dict({ + 'date_created': '2023-01-29T16:02:14.530Z', + 'dazzle_enabled': True, + 'dazzle_mode': dict({ + 'enabled': True, + 'supported': True, + }), + 'device_types': list([ + 'VA02', + ]), + 'devices': list([ + dict({ + 'battery_state': 'NORMAL', + 'characteristics': dict({ + 'capabilities': list([ + 'INSIDE_TEMPERATURE_MEASUREMENT', + 'IDENTIFY', + ]), + }), + 'child_lock_enabled': True, + 'connection_state': dict({ + 'timestamp': '2024-02-27T20:32:05.188Z', + 'value': True, + }), + 'current_fw_version': '95.1', + 'device_type': 'VA02', + 'in_pairing_mode': None, + 'mounting_state': dict({ + 'timestamp': '2023-10-09T15:39:08.131Z', + 'value': 'CALIBRATED', + }), + 'mounting_state_with_error': 'CALIBRATED', + 'orientation': 'HORIZONTAL', + 'serial_no': 'Serial2', + 'short_serial_no': 'ShortSerial2', + }), + ]), + 'id': 1, + 'name': 'Zone2', + 'open_window_detection': None, + 'report_available': False, + 'show_schedule_setup': True, + 'supports_dazzle': True, + 'type': 'HEATING', + }), + dict({ + 'date_created': '2023-04-14T07:52:56.352Z', + 'dazzle_enabled': True, + 'dazzle_mode': dict({ + 'enabled': True, + 'supported': True, + }), + 'device_types': list([ + 'VA02', + ]), + 'devices': list([ + dict({ + 'battery_state': 'NORMAL', + 'characteristics': dict({ + 'capabilities': list([ + 'INSIDE_TEMPERATURE_MEASUREMENT', + 'IDENTIFY', + ]), + }), + 'child_lock_enabled': True, + 'connection_state': dict({ + 'timestamp': '2024-02-27T20:31:11.417Z', + 'value': True, + }), + 'current_fw_version': '95.1', + 'device_type': 'VA02', + 'in_pairing_mode': None, + 'mounting_state': dict({ + 'timestamp': '2024-02-26T13:33:10.647Z', + 'value': 'CALIBRATED', + }), + 'mounting_state_with_error': 'CALIBRATED', + 'orientation': 'HORIZONTAL', + 'serial_no': 'Serial3', + 'short_serial_no': 'ShortSerial3', + }), + ]), + 'id': 3, + 'name': 'Zone3', + 'open_window_detection': None, + 'report_available': False, + 'show_schedule_setup': True, + 'supports_dazzle': True, + 'type': 'HEATING', + }), + dict({ + 'date_created': '2023-04-14T07:58:45.196Z', + 'dazzle_enabled': True, + 'dazzle_mode': dict({ + 'enabled': True, + 'supported': True, + }), + 'device_types': list([ + 'VA02', + ]), + 'devices': list([ + dict({ + 'battery_state': 'NORMAL', + 'characteristics': dict({ + 'capabilities': list([ + 'INSIDE_TEMPERATURE_MEASUREMENT', + 'IDENTIFY', + ]), + }), + 'child_lock_enabled': True, + 'connection_state': dict({ + 'timestamp': '2024-02-27T20:33:21.903Z', + 'value': True, + }), + 'current_fw_version': '95.1', + 'device_type': 'VA02', + 'in_pairing_mode': None, + 'mounting_state': dict({ + 'timestamp': '2024-02-19T17:23:30.537Z', + 'value': 'CALIBRATED', + }), + 'mounting_state_with_error': 'CALIBRATED', + 'orientation': 'HORIZONTAL', + 'serial_no': 'Serial4', + 'short_serial_no': 'ShortSerial4', + }), + ]), + 'id': 4, + 'name': 'Zone4', + 'open_window_detection': None, + 'report_available': False, + 'show_schedule_setup': True, 'supports_dazzle': True, 'type': 'HEATING', }), diff --git a/tests/fixtures/zones_no_owd.json b/tests/fixtures/zones_no_owd.json new file mode 100644 index 0000000..e948d9f --- /dev/null +++ b/tests/fixtures/zones_no_owd.json @@ -0,0 +1,150 @@ +[ + { + "id": 2, + "name": "Zone1", + "type": "HEATING", + "dateCreated": "2023-04-12T12:58:12.737Z", + "deviceTypes": ["VA02"], + "devices": [ + { + "deviceType": "VA02", + "serialNo": "Serial1", + "shortSerialNo": "ShortSerial1", + "currentFwVersion": "95.1", + "connectionState": { + "value": true, + "timestamp": "2024-02-27T20:30:13.976Z" + }, + "characteristics": { + "capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"] + }, + "mountingState": { + "value": "CALIBRATED", + "timestamp": "2024-02-04T10:17:00.266Z" + }, + "mountingStateWithError": "CALIBRATED", + "batteryState": "NORMAL", + "orientation": "HORIZONTAL", + "childLockEnabled": true, + "duties": ["ZONE_UI", "ZONE_DRIVER", "ZONE_LEADER"] + } + ], + "reportAvailable": false, + "showScheduleSetup": false, + "supportsDazzle": true, + "dazzleEnabled": true, + "dazzleMode": { "supported": true, "enabled": true }, + "openWindowDetection": null + }, + { + "id": 1, + "name": "Zone2", + "type": "HEATING", + "dateCreated": "2023-01-29T16:02:14.530Z", + "deviceTypes": ["VA02"], + "devices": [ + { + "deviceType": "VA02", + "serialNo": "Serial2", + "shortSerialNo": "ShortSerial2", + "currentFwVersion": "95.1", + "connectionState": { + "value": true, + "timestamp": "2024-02-27T20:32:05.188Z" + }, + "characteristics": { + "capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"] + }, + "mountingState": { + "value": "CALIBRATED", + "timestamp": "2023-10-09T15:39:08.131Z" + }, + "mountingStateWithError": "CALIBRATED", + "batteryState": "NORMAL", + "orientation": "HORIZONTAL", + "childLockEnabled": true, + "duties": ["ZONE_UI", "ZONE_DRIVER", "ZONE_LEADER"] + } + ], + "reportAvailable": false, + "showScheduleSetup": true, + "supportsDazzle": true, + "dazzleEnabled": true, + "dazzleMode": { "supported": true, "enabled": true }, + "openWindowDetection": null + }, + { + "id": 3, + "name": "Zone3", + "type": "HEATING", + "dateCreated": "2023-04-14T07:52:56.352Z", + "deviceTypes": ["VA02"], + "devices": [ + { + "deviceType": "VA02", + "serialNo": "Serial3", + "shortSerialNo": "ShortSerial3", + "currentFwVersion": "95.1", + "connectionState": { + "value": true, + "timestamp": "2024-02-27T20:31:11.417Z" + }, + "characteristics": { + "capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"] + }, + "mountingState": { + "value": "CALIBRATED", + "timestamp": "2024-02-26T13:33:10.647Z" + }, + "mountingStateWithError": "CALIBRATED", + "batteryState": "NORMAL", + "orientation": "HORIZONTAL", + "childLockEnabled": true, + "duties": ["ZONE_UI", "ZONE_DRIVER", "ZONE_LEADER"] + } + ], + "reportAvailable": false, + "showScheduleSetup": true, + "supportsDazzle": true, + "dazzleEnabled": true, + "dazzleMode": { "supported": true, "enabled": true }, + "openWindowDetection": null + }, + { + "id": 4, + "name": "Zone4", + "type": "HEATING", + "dateCreated": "2023-04-14T07:58:45.196Z", + "deviceTypes": ["VA02"], + "devices": [ + { + "deviceType": "VA02", + "serialNo": "Serial4", + "shortSerialNo": "ShortSerial4", + "currentFwVersion": "95.1", + "connectionState": { + "value": true, + "timestamp": "2024-02-27T20:33:21.903Z" + }, + "characteristics": { + "capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"] + }, + "mountingState": { + "value": "CALIBRATED", + "timestamp": "2024-02-19T17:23:30.537Z" + }, + "mountingStateWithError": "CALIBRATED", + "batteryState": "NORMAL", + "orientation": "HORIZONTAL", + "childLockEnabled": true, + "duties": ["ZONE_UI", "ZONE_DRIVER", "ZONE_LEADER"] + } + ], + "reportAvailable": false, + "showScheduleSetup": true, + "supportsDazzle": true, + "dazzleEnabled": true, + "dazzleMode": { "supported": true, "enabled": true }, + "openWindowDetection": null + } +] diff --git a/tests/test_tado.py b/tests/test_tado.py index 8009bb9..b9114ac 100644 --- a/tests/test_tado.py +++ b/tests/test_tado.py @@ -233,6 +233,18 @@ async def test_get_zones( assert await python_tado.get_zones() == snapshot +async def test_get_zones_no_owd( + python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion +) -> None: + """Test get zones.""" + responses.get( + f"{TADO_API_URL}/homes/1/zones", + status=200, + body=load_fixture("zones_no_owd.json"), + ) + assert await python_tado.get_zones() == snapshot + + async def test_get_zone_states_heating_power( python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion ) -> None: From 922e5801098f33d135f8610e713da5aff49984ed Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Sun, 17 Nov 2024 20:06:41 +0000 Subject: [PATCH 03/11] Add water heater --- src/tadoasync/models.py | 3 +++ tests/__snapshots__/test_tado.ambr | 19 +++++++++++++++++++ tests/fixtures/capabilities_water_heater.json | 17 +++++++++++++++++ tests/test_tado.py | 12 ++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 tests/fixtures/capabilities_water_heater.json diff --git a/src/tadoasync/models.py b/src/tadoasync/models.py index 410fbbf..f81f236 100644 --- a/src/tadoasync/models.py +++ b/src/tadoasync/models.py @@ -289,6 +289,9 @@ class Capabilities(DataClassORJSONMixin): type: str temperatures: Temperatures + can_set_temperature: bool | None = field( + metadata=field_options(alias="canSetTemperature"), default=None + ) @dataclass diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 0025411..14d3001 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -15,6 +15,7 @@ # --- # name: test_get_capabilities dict({ + 'can_set_temperature': None, 'temperatures': dict({ 'celsius': dict({ 'max': 25.0, @@ -30,6 +31,24 @@ 'type': 'HEATING', }) # --- +# name: test_get_capabilities_water_heater + dict({ + 'can_set_temperature': True, + 'temperatures': dict({ + 'celsius': dict({ + 'max': 31.0, + 'min': 16.0, + 'step': 1.0, + }), + 'fahrenheit': dict({ + 'max': 88.0, + 'min': 61.0, + 'step': 1.0, + }), + }), + 'type': 'HOT_WATER', + }) +# --- # name: test_get_device_info dict({ 'celsius': 0.0, diff --git a/tests/fixtures/capabilities_water_heater.json b/tests/fixtures/capabilities_water_heater.json new file mode 100644 index 0000000..ff0b20f --- /dev/null +++ b/tests/fixtures/capabilities_water_heater.json @@ -0,0 +1,17 @@ +{ + "canSetTemperature": true, + "DRY": {}, + "type": "HOT_WATER", + "temperatures": { + "celsius": { + "min": 16, + "max": 31, + "step": 1 + }, + "fahrenheit": { + "step": 1, + "max": 88, + "min": 61 + } + } +} diff --git a/tests/test_tado.py b/tests/test_tado.py index b9114ac..6e7c335 100644 --- a/tests/test_tado.py +++ b/tests/test_tado.py @@ -316,6 +316,18 @@ async def test_get_capabilities( assert await python_tado.get_capabilities(1) == snapshot +async def test_get_capabilities_water_heater( + python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion +) -> None: + """Test get capabilities.""" + responses.get( + f"{TADO_API_URL}/homes/1/zones/1/capabilities", + status=200, + body=load_fixture("capabilities_water_heater.json"), + ) + assert await python_tado.get_capabilities(1) == snapshot + + async def test_reset_zone_overlay_success( python_tado: Tado, responses: aioresponses ) -> None: From d17ba2d51c2d42ac027629d7a158ac9559925d03 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Sun, 17 Nov 2024 20:13:43 +0000 Subject: [PATCH 04/11] Start for AC --- src/tadoasync/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tadoasync/models.py b/src/tadoasync/models.py index f81f236..b229879 100644 --- a/src/tadoasync/models.py +++ b/src/tadoasync/models.py @@ -288,7 +288,7 @@ class Capabilities(DataClassORJSONMixin): """Capabilities model represents the capabilities of a zone.""" type: str - temperatures: Temperatures + temperatures: Temperatures | None = None can_set_temperature: bool | None = field( metadata=field_options(alias="canSetTemperature"), default=None ) From 8b06a0dcdba06fa7ce5cfd2954819894b7636ff5 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Sun, 17 Nov 2024 20:30:16 +0000 Subject: [PATCH 05/11] Adding AC's --- src/tadoasync/models.py | 46 ++++++++++++ tests/__snapshots__/test_tado.ambr | 71 +++++++++++++++++++ tests/fixtures/capabilities_ac.json | 46 ++++++++++++ tests/fixtures/capabilities_water_heater.json | 1 - tests/test_tado.py | 12 ++++ 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/capabilities_ac.json diff --git a/src/tadoasync/models.py b/src/tadoasync/models.py index b229879..e25d58e 100644 --- a/src/tadoasync/models.py +++ b/src/tadoasync/models.py @@ -293,6 +293,52 @@ class Capabilities(DataClassORJSONMixin): metadata=field_options(alias="canSetTemperature"), default=None ) + # Air conditioning specifics + auto: AutoAC | None = field(metadata=field_options(alias="AUTO"), default=None) + cool: CoolAC | None = field(metadata=field_options(alias="COOL"), default=None) + dry: DryAC | None = field(metadata=field_options(alias="DRY"), default=None) + fan: FanAC | None = field(metadata=field_options(alias="FAN"), default=None) + heat: HeatAC | None = field(metadata=field_options(alias="HEAT"), default=None) + + +@dataclass +class AutoAC(DataClassORJSONMixin): + """AutoAC model represents the auto AC capabilities of a zone.""" + + fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) + swing_modes: list[str] = field(metadata=field_options(alias="swings")) + + +@dataclass +class CoolAC(DataClassORJSONMixin): + """CoolAC model represents the cool AC capabilities of a zone.""" + + fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) + swing_modes: list[str] = field(metadata=field_options(alias="swings")) + + +@dataclass +class DryAC(DataClassORJSONMixin): + """DryAC model represents the dry AC capabilities of a zone.""" + + swing_modes: list[str] = field(metadata=field_options(alias="swings")) + + +@dataclass +class FanAC(DataClassORJSONMixin): + """FanAC model represents the fan AC capabilities of a zone.""" + + fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) + swing_modes: list[str] = field(metadata=field_options(alias="swings")) + + +@dataclass +class HeatAC(DataClassORJSONMixin): + """HeatAC model represents the heat AC capabilities of a zone.""" + + fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) + swing_modes: list[str] = field(metadata=field_options(alias="swings")) + @dataclass class TemperatureOffset(DataClassORJSONMixin): diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 14d3001..08a93ca 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -15,7 +15,12 @@ # --- # name: test_get_capabilities dict({ + 'auto': None, 'can_set_temperature': None, + 'cool': None, + 'dry': None, + 'fan': None, + 'heat': None, 'temperatures': dict({ 'celsius': dict({ 'max': 25.0, @@ -31,9 +36,75 @@ 'type': 'HEATING', }) # --- +# name: test_get_capabilities_ac + dict({ + 'auto': dict({ + 'fan_speeds': list([ + 'AUTO', + 'HIGH', + 'MIDDLE', + 'LOW', + ]), + 'swing_modes': list([ + 'OFF', + 'ON', + ]), + }), + 'can_set_temperature': None, + 'cool': dict({ + 'fan_speeds': list([ + 'AUTO', + 'HIGH', + 'MIDDLE', + 'LOW', + ]), + 'swing_modes': list([ + 'OFF', + 'ON', + ]), + }), + 'dry': dict({ + 'swing_modes': list([ + 'OFF', + 'ON', + ]), + }), + 'fan': dict({ + 'fan_speeds': list([ + 'AUTO', + 'HIGH', + 'MIDDLE', + 'LOW', + ]), + 'swing_modes': list([ + 'OFF', + 'ON', + ]), + }), + 'heat': dict({ + 'fan_speeds': list([ + 'AUTO', + 'HIGH', + 'MIDDLE', + 'LOW', + ]), + 'swing_modes': list([ + 'OFF', + 'ON', + ]), + }), + 'temperatures': None, + 'type': 'AIR_CONDITIONING', + }) +# --- # name: test_get_capabilities_water_heater dict({ + 'auto': None, 'can_set_temperature': True, + 'cool': None, + 'dry': None, + 'fan': None, + 'heat': None, 'temperatures': dict({ 'celsius': dict({ 'max': 31.0, diff --git a/tests/fixtures/capabilities_ac.json b/tests/fixtures/capabilities_ac.json new file mode 100644 index 0000000..fbb1312 --- /dev/null +++ b/tests/fixtures/capabilities_ac.json @@ -0,0 +1,46 @@ +{ + "type": "AIR_CONDITIONING", + "AUTO": { + "fanSpeeds": ["AUTO", "HIGH", "MIDDLE", "LOW"], + "swings": ["OFF", "ON"] + }, + "COOL": { + "temperatures": { + "celsius": { + "min": 18, + "max": 30, + "step": 1.0 + }, + "fahrenheit": { + "min": 64, + "max": 86, + "step": 1.0 + } + }, + "fanSpeeds": ["AUTO", "HIGH", "MIDDLE", "LOW"], + "swings": ["OFF", "ON"] + }, + "DRY": { + "swings": ["OFF", "ON"] + }, + "FAN": { + "fanSpeeds": ["AUTO", "HIGH", "MIDDLE", "LOW"], + "swings": ["OFF", "ON"] + }, + "HEAT": { + "temperatures": { + "celsius": { + "min": 16, + "max": 30, + "step": 1.0 + }, + "fahrenheit": { + "min": 61, + "max": 86, + "step": 1.0 + } + }, + "fanSpeeds": ["AUTO", "HIGH", "MIDDLE", "LOW"], + "swings": ["OFF", "ON"] + } +} diff --git a/tests/fixtures/capabilities_water_heater.json b/tests/fixtures/capabilities_water_heater.json index ff0b20f..44edf80 100644 --- a/tests/fixtures/capabilities_water_heater.json +++ b/tests/fixtures/capabilities_water_heater.json @@ -1,6 +1,5 @@ { "canSetTemperature": true, - "DRY": {}, "type": "HOT_WATER", "temperatures": { "celsius": { diff --git a/tests/test_tado.py b/tests/test_tado.py index 6e7c335..45f0774 100644 --- a/tests/test_tado.py +++ b/tests/test_tado.py @@ -328,6 +328,18 @@ async def test_get_capabilities_water_heater( assert await python_tado.get_capabilities(1) == snapshot +async def test_get_capabilities_ac( + python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion +) -> None: + """Test get capabilities.""" + responses.get( + f"{TADO_API_URL}/homes/1/zones/1/capabilities", + status=200, + body=load_fixture("capabilities_ac.json"), + ) + assert await python_tado.get_capabilities(1) == snapshot + + async def test_reset_zone_overlay_success( python_tado: Tado, responses: aioresponses ) -> None: From 00965c596c59aca068928ae8c4493271f1aeb956 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Mon, 18 Nov 2024 21:47:20 +0000 Subject: [PATCH 06/11] Adding better device info --- src/tadoasync/tadoasync.py | 12 ++++++++---- tests/__snapshots__/test_tado.ambr | 23 +++++++++++++++++++++++ tests/fixtures/device_info.json | 17 ++++++++++++++++- tests/fixtures/device_info_attribute.json | 1 + tests/test_tado.py | 16 ++++++++++++++-- 5 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 tests/fixtures/device_info_attribute.json diff --git a/src/tadoasync/tadoasync.py b/src/tadoasync/tadoasync.py index 5fdccf8..cde0bec 100644 --- a/src/tadoasync/tadoasync.py +++ b/src/tadoasync/tadoasync.py @@ -363,11 +363,15 @@ async def set_zone_overlay( ) async def get_device_info( - self, serial_no: str, attribute: str - ) -> TemperatureOffset: + self, serial_no: str, attribute: str | None = None + ) -> TemperatureOffset | Device: """Get the device info.""" - response = await self._request(f"devices/{serial_no}/{attribute}") - return TemperatureOffset.from_json(response) + if attribute == "temperatureOffset": + response = await self._request(f"devices/{serial_no}/{attribute}") + return TemperatureOffset.from_json(response) + + response = await self._request(f"devices/{serial_no}/") + return Device.from_json(response) async def set_child_lock(self, serial_no: str, child_lock: bool | None) -> None: """Set the child lock.""" diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 08a93ca..0da8044 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -121,6 +121,29 @@ }) # --- # name: test_get_device_info + dict({ + 'battery_state': None, + 'characteristics': dict({ + 'capabilities': list([ + 'RADIO_ENCRYPTION_KEY_ACCESS', + ]), + }), + 'child_lock_enabled': None, + 'connection_state': dict({ + 'timestamp': '2024-11-18T21:41:49.404Z', + 'value': True, + }), + 'current_fw_version': '92.1', + 'device_type': 'IB01', + 'in_pairing_mode': False, + 'mounting_state': None, + 'mounting_state_with_error': None, + 'orientation': None, + 'serial_no': 'SerialNo1', + 'short_serial_no': 'ShortSerialNo1', + }) +# --- +# name: test_get_device_info_attribute dict({ 'celsius': 0.0, 'fahrenheit': 0.0, diff --git a/tests/fixtures/device_info.json b/tests/fixtures/device_info.json index 362f5ce..9752771 100644 --- a/tests/fixtures/device_info.json +++ b/tests/fixtures/device_info.json @@ -1 +1,16 @@ -{ "celsius": 0.0, "fahrenheit": 0.0 } +{ + "deviceType": "IB01", + "serialNo": "SerialNo1", + "shortSerialNo": "ShortSerialNo1", + "currentFwVersion": "92.1", + "connectionState": { + "value": true, + "timestamp": "2024-11-18T21:41:49.404Z" + }, + "characteristics": { + "capabilities": [ + "RADIO_ENCRYPTION_KEY_ACCESS" + ] + }, + "inPairingMode": false +} diff --git a/tests/fixtures/device_info_attribute.json b/tests/fixtures/device_info_attribute.json new file mode 100644 index 0000000..362f5ce --- /dev/null +++ b/tests/fixtures/device_info_attribute.json @@ -0,0 +1 @@ +{ "celsius": 0.0, "fahrenheit": 0.0 } diff --git a/tests/test_tado.py b/tests/test_tado.py index 45f0774..801ba43 100644 --- a/tests/test_tado.py +++ b/tests/test_tado.py @@ -381,18 +381,30 @@ async def test_set_presence_auto_delete( await python_tado.set_presence(presence) -async def test_get_device_info( +async def test_get_device_info_attribute( python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion ) -> None: """Test get device info.""" responses.get( f"{TADO_API_URL}/devices/1/temperatureOffset", status=200, - body=load_fixture("device_info.json"), + body=load_fixture("device_info_attribute.json"), ) assert await python_tado.get_device_info("1", "temperatureOffset") == snapshot +async def test_get_device_info( + python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion +) -> None: + """Test get device info.""" + responses.get( + f"{TADO_API_URL}/devices/1/", + status=200, + body=load_fixture("device_info.json"), + ) + assert await python_tado.get_device_info("1") == snapshot + + async def test_geofencing_supported( python_tado: Tado, responses: aioresponses, snapshot: SnapshotAssertion ) -> None: From 9b64db5ff6f2ed1b145b7b61dd76045ee14198ee Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Sun, 1 Dec 2024 21:56:48 +0000 Subject: [PATCH 07/11] Add preparation --- src/tadoasync/tadoasync.py | 2 ++ tests/__snapshots__/test_tado.ambr | 42 +++++++++++++++--------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/tadoasync/tadoasync.py b/src/tadoasync/tadoasync.py index cde0bec..42bd854 100644 --- a/src/tadoasync/tadoasync.py +++ b/src/tadoasync/tadoasync.py @@ -523,6 +523,8 @@ async def update_zone_data(self, data: ZoneState) -> None: # pylint: disable=to else CONST_FAN_SPEED_OFF ) + data.preparation = hasattr(data, "preparation") and data.preparation is not None + data.open_window_detected = ( hasattr(data, "open_window_detected") and data.open_window_detected is not None diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 0da8044..316174b 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -435,7 +435,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 50.4, @@ -543,7 +543,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 62.5, @@ -651,7 +651,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 60.9, @@ -759,7 +759,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 62.0, @@ -862,7 +862,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 62.0, @@ -970,7 +970,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 60.9, @@ -1078,7 +1078,7 @@ 'overlay_type': 'MANUAL', 'power': 'OFF', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 48.2, @@ -1181,7 +1181,7 @@ 'overlay_type': 'MANUAL', 'power': 'OFF', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 62.0, @@ -1289,7 +1289,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 61.6, @@ -1378,7 +1378,7 @@ 'overlay_type': None, 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 60.0, @@ -1486,7 +1486,7 @@ 'overlay_type': 'MANUAL', 'power': 'OFF', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 49.2, @@ -1588,7 +1588,7 @@ 'overlay_type': None, 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 42.3, @@ -1696,7 +1696,7 @@ 'overlay_type': None, 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 45.2, @@ -1828,7 +1828,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 45.2, @@ -1970,7 +1970,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 45.2, @@ -2111,7 +2111,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 45.2, @@ -2256,7 +2256,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 45.2, @@ -2386,7 +2386,7 @@ 'overlay_type': 'MANUAL', 'power': 'OFF', 'precision': 0.1, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 45.2, @@ -2479,7 +2479,7 @@ 'overlay_type': None, 'power': 'ON', 'precision': None, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ }), 'setting': dict({ @@ -2586,7 +2586,7 @@ 'overlay_type': 'MANUAL', 'power': 'ON', 'precision': None, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ }), 'setting': dict({ @@ -2688,7 +2688,7 @@ 'overlay_type': 'MANUAL', 'power': 'OFF', 'precision': None, - 'preparation': None, + 'preparation': False, 'sensor_data_points': dict({ }), 'setting': dict({ From 3e3c9d85179845be69e6fcad7b3e86b79b7e26fa Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Mon, 2 Dec 2024 20:47:43 +0000 Subject: [PATCH 08/11] Add optional swing mode --- src/tadoasync/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tadoasync/models.py b/src/tadoasync/models.py index e25d58e..8eb8faf 100644 --- a/src/tadoasync/models.py +++ b/src/tadoasync/models.py @@ -321,7 +321,9 @@ class CoolAC(DataClassORJSONMixin): class DryAC(DataClassORJSONMixin): """DryAC model represents the dry AC capabilities of a zone.""" - swing_modes: list[str] = field(metadata=field_options(alias="swings")) + swing_modes: list[str] | None = field( + default=None, metadata=field_options(alias="swings") + ) @dataclass From 4ded7a44c0b361823702ae1b7dbfaaefc8b52a8d Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Mon, 2 Dec 2024 21:04:24 +0000 Subject: [PATCH 09/11] Adding optionals for AC's --- src/tadoasync/models.py | 35 +++++++++++++++++++++++------- tests/__snapshots__/test_tado.ambr | 25 +++++++++++++++++++++ 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/tadoasync/models.py b/src/tadoasync/models.py index 8eb8faf..9a3d1c1 100644 --- a/src/tadoasync/models.py +++ b/src/tadoasync/models.py @@ -305,16 +305,26 @@ class Capabilities(DataClassORJSONMixin): class AutoAC(DataClassORJSONMixin): """AutoAC model represents the auto AC capabilities of a zone.""" - fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) - swing_modes: list[str] = field(metadata=field_options(alias="swings")) + fan_speeds: list[str] | None = field( + default=None, metadata=field_options(alias="fanSpeeds") + ) + swing_modes: list[str] | None = field( + default=None, metadata=field_options(alias="swings") + ) + light: str | None = None @dataclass class CoolAC(DataClassORJSONMixin): """CoolAC model represents the cool AC capabilities of a zone.""" - fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) - swing_modes: list[str] = field(metadata=field_options(alias="swings")) + fan_speeds: list[str] | None = field( + default=None, metadata=field_options(alias="fanSpeeds") + ) + swing_modes: list[str] | None = field( + default=None, metadata=field_options(alias="swings") + ) + temperatures: Temperatures | None = None @dataclass @@ -330,16 +340,25 @@ class DryAC(DataClassORJSONMixin): class FanAC(DataClassORJSONMixin): """FanAC model represents the fan AC capabilities of a zone.""" - fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) - swing_modes: list[str] = field(metadata=field_options(alias="swings")) + fan_speeds: list[str] | None = field( + default=None, metadata=field_options(alias="fanSpeeds") + ) + swing_modes: list[str] | None = field( + default=None, metadata=field_options(alias="swings") + ) @dataclass class HeatAC(DataClassORJSONMixin): """HeatAC model represents the heat AC capabilities of a zone.""" - fan_speeds: list[str] = field(metadata=field_options(alias="fanSpeeds")) - swing_modes: list[str] = field(metadata=field_options(alias="swings")) + fan_speeds: list[str] | None = field( + default=None, metadata=field_options(alias="fanSpeeds") + ) + swing_modes: list[str] | None = field( + default=None, metadata=field_options(alias="swings") + ) + temperatures: Temperatures | None = None @dataclass diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 316174b..2cc5343 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -45,6 +45,7 @@ 'MIDDLE', 'LOW', ]), + 'light': None, 'swing_modes': list([ 'OFF', 'ON', @@ -62,6 +63,18 @@ 'OFF', 'ON', ]), + 'temperatures': dict({ + 'celsius': dict({ + 'max': 30.0, + 'min': 18.0, + 'step': 1.0, + }), + 'fahrenheit': dict({ + 'max': 86.0, + 'min': 64.0, + 'step': 1.0, + }), + }), }), 'dry': dict({ 'swing_modes': list([ @@ -92,6 +105,18 @@ 'OFF', 'ON', ]), + 'temperatures': dict({ + 'celsius': dict({ + 'max': 30.0, + 'min': 16.0, + 'step': 1.0, + }), + 'fahrenheit': dict({ + 'max': 86.0, + 'min': 61.0, + 'step': 1.0, + }), + }), }), 'temperatures': None, 'type': 'AIR_CONDITIONING', From 4486b4a61bd3eaf3a54a0724e48d0f46cbf891e3 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Mon, 2 Dec 2024 22:06:46 +0000 Subject: [PATCH 10/11] Proper zone_state assignment --- src/tadoasync/tadoasync.py | 7 +- tests/__snapshots__/test_tado.ambr | 198 +++++++++---------- tests/fixtures/zone_states_ac_power.dry.json | 4 +- tests/fixtures/zone_states_ac_power.fan.json | 4 +- tests/test_tado.py | 1 - 5 files changed, 108 insertions(+), 106 deletions(-) diff --git a/src/tadoasync/tadoasync.py b/src/tadoasync/tadoasync.py index 42bd854..d7423d2 100644 --- a/src/tadoasync/tadoasync.py +++ b/src/tadoasync/tadoasync.py @@ -250,6 +250,10 @@ async def get_zone_states(self) -> list[ZoneStates]: zone_id: ZoneState.from_dict(zone_state_dict) for zone_id, zone_state_dict in obj["zoneStates"].items() } + + for zone_state in zone_states.values(): + await self.update_zone_data(zone_state) + return [ZoneStates(zone_states=zone_states)] async def get_zone_state(self, zone_id: int) -> ZoneState: @@ -473,8 +477,7 @@ async def update_zone_data(self, data: ZoneState) -> None: # pylint: disable=to data.current_fan_speed = None data.current_fan_level = None - # If there is no overlay, the mode will always be - # "SMART_SCHEDULE" + # If there is no overlay, the mode will always be "SMART_SCHEDULE" data.current_hvac_mode = CONST_MODE_OFF data.current_swing_mode = CONST_MODE_OFF data.current_vertical_swing_mode = CONST_VERTICAL_SWING_OFF diff --git a/tests/__snapshots__/test_tado.ambr b/tests/__snapshots__/test_tado.ambr index 2cc5343..64010a0 100644 --- a/tests/__snapshots__/test_tado.ambr +++ b/tests/__snapshots__/test_tado.ambr @@ -2737,8 +2737,8 @@ dict({ 'zone_states': dict({ '1': dict({ - 'ac_power': None, - 'ac_power_timestamp': None, + 'ac_power': 'ON', + 'ac_power_timestamp': '2024-07-05T04:02:40.867Z', 'activity_data_points': dict({ 'ac_power': dict({ 'timestamp': '2024-07-05T04:02:40.867Z', @@ -2747,18 +2747,18 @@ }), 'heating_power': None, }), - 'available': False, + 'available': True, 'connection': None, 'current_fan_level': None, - 'current_fan_speed': None, + 'current_fan_speed': 'AUTO', 'current_horizontal_swing_mode': None, - 'current_humidity': None, - 'current_humidity_timestamp': None, - 'current_hvac_action': None, - 'current_hvac_mode': None, + 'current_humidity': 62.0, + 'current_humidity_timestamp': '2024-07-05T04:02:07.396Z', + 'current_hvac_action': 'DRYING', + 'current_hvac_mode': 'DRY', 'current_swing_mode': None, - 'current_temp': None, - 'current_temp_timestamp': None, + 'current_temp': 25.01, + 'current_temp_timestamp': '2024-07-05T04:02:07.396Z', 'current_vertical_swing_mode': None, 'default_overlay_termination_duration': None, 'default_overlay_termination_type': None, @@ -2777,14 +2777,14 @@ }), 'open_window': None, 'open_window_attr': None, - 'open_window_detected': None, + 'open_window_detected': False, 'overlay': dict({ 'projected_expiry': None, 'setting': dict({ 'fan_level': None, 'fan_speed': None, 'horizontal_swing': None, - 'mode': 'FAN', + 'mode': 'DRY', 'power': 'ON', 'swing': None, 'temperature': None, @@ -2798,13 +2798,13 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, - 'overlay_termination_type': None, + 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', - 'power': None, - 'precision': None, - 'preparation': None, + 'power': 'ON', + 'precision': 0.1, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 62.0, @@ -2826,7 +2826,7 @@ 'fan_level': None, 'fan_speed': None, 'horizontal_swing': None, - 'mode': 'FAN', + 'mode': 'DRY', 'power': 'ON', 'swing': None, 'temperature': None, @@ -2846,8 +2846,8 @@ dict({ 'zone_states': dict({ '1': dict({ - 'ac_power': None, - 'ac_power_timestamp': None, + 'ac_power': 'ON', + 'ac_power_timestamp': '2024-07-05T04:02:40.867Z', 'activity_data_points': dict({ 'ac_power': dict({ 'timestamp': '2024-07-05T04:02:40.867Z', @@ -2856,18 +2856,18 @@ }), 'heating_power': None, }), - 'available': False, + 'available': True, 'connection': None, 'current_fan_level': None, - 'current_fan_speed': None, + 'current_fan_speed': 'AUTO', 'current_horizontal_swing_mode': None, - 'current_humidity': None, - 'current_humidity_timestamp': None, - 'current_hvac_action': None, - 'current_hvac_mode': None, + 'current_humidity': 62.0, + 'current_humidity_timestamp': '2024-07-05T04:02:07.396Z', + 'current_hvac_action': 'FAN', + 'current_hvac_mode': 'FAN', 'current_swing_mode': None, - 'current_temp': None, - 'current_temp_timestamp': None, + 'current_temp': 25.01, + 'current_temp_timestamp': '2024-07-05T04:02:07.396Z', 'current_vertical_swing_mode': None, 'default_overlay_termination_duration': None, 'default_overlay_termination_type': None, @@ -2886,14 +2886,14 @@ }), 'open_window': None, 'open_window_attr': None, - 'open_window_detected': None, + 'open_window_detected': False, 'overlay': dict({ 'projected_expiry': None, 'setting': dict({ 'fan_level': None, 'fan_speed': None, 'horizontal_swing': None, - 'mode': 'DRY', + 'mode': 'FAN', 'power': 'ON', 'swing': None, 'temperature': None, @@ -2907,13 +2907,13 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, - 'overlay_termination_type': None, + 'overlay_termination_type': 'TADO_MODE', 'overlay_type': 'MANUAL', - 'power': None, - 'precision': None, - 'preparation': None, + 'power': 'ON', + 'precision': 0.1, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 62.0, @@ -2935,7 +2935,7 @@ 'fan_level': None, 'fan_speed': None, 'horizontal_swing': None, - 'mode': 'DRY', + 'mode': 'FAN', 'power': 'ON', 'swing': None, 'temperature': None, @@ -2966,26 +2966,26 @@ 'value': None, }), }), - 'available': False, + 'available': True, 'connection': None, 'current_fan_level': None, 'current_fan_speed': None, 'current_horizontal_swing_mode': None, - 'current_humidity': None, - 'current_humidity_timestamp': None, - 'current_hvac_action': None, - 'current_hvac_mode': None, + 'current_humidity': 51.0, + 'current_humidity_timestamp': '2024-02-27T20:37:02.553Z', + 'current_hvac_action': 'IDLE', + 'current_hvac_mode': 'HEAT', 'current_swing_mode': None, - 'current_temp': None, - 'current_temp_timestamp': None, + 'current_temp': 17.98, + 'current_temp_timestamp': '2024-02-27T20:37:02.553Z', 'current_vertical_swing_mode': None, 'default_overlay_termination_duration': None, 'default_overlay_termination_type': None, 'geolocation_override': False, 'geolocation_override_disable_time': None, 'heating_power': None, - 'heating_power_percentage': None, - 'heating_power_timestamp': None, + 'heating_power_percentage': 0.0, + 'heating_power_timestamp': '2024-02-27T20:30:01.259Z', 'is_away': False, 'link': dict({ 'state': 'ONLINE', @@ -3014,7 +3014,7 @@ }), 'open_window': None, 'open_window_attr': None, - 'open_window_detected': None, + 'open_window_detected': False, 'overlay': dict({ 'projected_expiry': None, 'setting': dict({ @@ -3040,13 +3040,13 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, - 'overlay_termination_type': None, + 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', - 'power': None, - 'precision': None, - 'preparation': None, + 'power': 'ON', + 'precision': 0.1, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 51.0, @@ -3081,7 +3081,7 @@ 'vertical_swing': None, }), 'tado_mode': 'HOME', - 'target_temp': None, + 'target_temp': 17.0, 'termination_condition': None, }), '2': dict({ @@ -3096,26 +3096,26 @@ 'value': None, }), }), - 'available': False, + 'available': True, 'connection': None, 'current_fan_level': None, 'current_fan_speed': None, 'current_horizontal_swing_mode': None, - 'current_humidity': None, - 'current_humidity_timestamp': None, - 'current_hvac_action': None, - 'current_hvac_mode': None, + 'current_humidity': 56.9, + 'current_humidity_timestamp': '2024-02-27T20:38:14.791Z', + 'current_hvac_action': 'HEATING', + 'current_hvac_mode': 'HEAT', 'current_swing_mode': None, - 'current_temp': None, - 'current_temp_timestamp': None, + 'current_temp': 14.89, + 'current_temp_timestamp': '2024-02-27T20:38:14.791Z', 'current_vertical_swing_mode': None, 'default_overlay_termination_duration': None, 'default_overlay_termination_type': None, 'geolocation_override': False, 'geolocation_override_disable_time': None, 'heating_power': None, - 'heating_power_percentage': None, - 'heating_power_timestamp': None, + 'heating_power_percentage': 11.0, + 'heating_power_timestamp': '2024-02-27T20:37:22.791Z', 'is_away': False, 'link': dict({ 'state': 'ONLINE', @@ -3126,7 +3126,7 @@ }), 'open_window': None, 'open_window_attr': None, - 'open_window_detected': None, + 'open_window_detected': False, 'overlay': dict({ 'projected_expiry': None, 'setting': dict({ @@ -3152,13 +3152,13 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, - 'overlay_termination_type': None, + 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', - 'power': None, - 'precision': None, - 'preparation': None, + 'power': 'ON', + 'precision': 0.1, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 56.9, @@ -3193,7 +3193,7 @@ 'vertical_swing': None, }), 'tado_mode': 'HOME', - 'target_temp': None, + 'target_temp': 15.0, 'termination_condition': None, }), '3': dict({ @@ -3208,26 +3208,26 @@ 'value': None, }), }), - 'available': False, + 'available': True, 'connection': None, 'current_fan_level': None, 'current_fan_speed': None, 'current_horizontal_swing_mode': None, - 'current_humidity': None, - 'current_humidity_timestamp': None, - 'current_hvac_action': None, - 'current_hvac_mode': None, + 'current_humidity': 55.5, + 'current_humidity_timestamp': '2024-02-27T20:37:12.297Z', + 'current_hvac_action': 'IDLE', + 'current_hvac_mode': 'HEAT', 'current_swing_mode': None, - 'current_temp': None, - 'current_temp_timestamp': None, + 'current_temp': 17.52, + 'current_temp_timestamp': '2024-02-27T20:37:12.297Z', 'current_vertical_swing_mode': None, 'default_overlay_termination_duration': None, 'default_overlay_termination_type': None, 'geolocation_override': False, 'geolocation_override_disable_time': None, 'heating_power': None, - 'heating_power_percentage': None, - 'heating_power_timestamp': None, + 'heating_power_percentage': 0.0, + 'heating_power_timestamp': '2024-02-27T20:28:21.301Z', 'is_away': False, 'link': dict({ 'state': 'ONLINE', @@ -3256,7 +3256,7 @@ }), 'open_window': None, 'open_window_attr': None, - 'open_window_detected': None, + 'open_window_detected': False, 'overlay': dict({ 'projected_expiry': None, 'setting': dict({ @@ -3282,13 +3282,13 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, - 'overlay_termination_type': None, + 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', - 'power': None, - 'precision': None, - 'preparation': None, + 'power': 'ON', + 'precision': 0.1, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 55.5, @@ -3323,7 +3323,7 @@ 'vertical_swing': None, }), 'tado_mode': 'HOME', - 'target_temp': None, + 'target_temp': 17.0, 'termination_condition': None, }), '4': dict({ @@ -3338,26 +3338,26 @@ 'value': None, }), }), - 'available': False, + 'available': True, 'connection': None, 'current_fan_level': None, 'current_fan_speed': None, 'current_horizontal_swing_mode': None, - 'current_humidity': None, - 'current_humidity_timestamp': None, - 'current_hvac_action': None, - 'current_hvac_mode': None, + 'current_humidity': 63.3, + 'current_humidity_timestamp': '2024-02-27T20:37:20.931Z', + 'current_hvac_action': 'OFF', + 'current_hvac_mode': 'OFF', 'current_swing_mode': None, - 'current_temp': None, - 'current_temp_timestamp': None, + 'current_temp': 18.57, + 'current_temp_timestamp': '2024-02-27T20:37:20.931Z', 'current_vertical_swing_mode': None, 'default_overlay_termination_duration': None, 'default_overlay_termination_type': None, 'geolocation_override': False, 'geolocation_override_disable_time': None, 'heating_power': None, - 'heating_power_percentage': None, - 'heating_power_timestamp': None, + 'heating_power_percentage': 0.0, + 'heating_power_timestamp': '2024-02-27T20:27:18.903Z', 'is_away': False, 'link': dict({ 'state': 'ONLINE', @@ -3386,7 +3386,7 @@ }), 'open_window': None, 'open_window_attr': None, - 'open_window_detected': None, + 'open_window_detected': False, 'overlay': dict({ 'projected_expiry': None, 'setting': dict({ @@ -3407,13 +3407,13 @@ }), 'type': 'MANUAL', }), - 'overlay_active': None, + 'overlay_active': True, 'overlay_termination_timestamp': None, - 'overlay_termination_type': None, + 'overlay_termination_type': 'MANUAL', 'overlay_type': 'MANUAL', - 'power': None, - 'precision': None, - 'preparation': None, + 'power': 'OFF', + 'precision': 0.1, + 'preparation': False, 'sensor_data_points': dict({ 'humidity': dict({ 'percentage': 63.3, diff --git a/tests/fixtures/zone_states_ac_power.dry.json b/tests/fixtures/zone_states_ac_power.dry.json index 29a52cb..753f72a 100644 --- a/tests/fixtures/zone_states_ac_power.dry.json +++ b/tests/fixtures/zone_states_ac_power.dry.json @@ -33,7 +33,7 @@ }, "setting": { "type": "AIR_CONDITIONING", - "mode": "FAN", + "mode": "DRY", "power": "ON" }, "type": "MANUAL" @@ -53,7 +53,7 @@ "nextScheduleChange": null, "setting": { "type": "AIR_CONDITIONING", - "mode": "FAN", + "mode": "DRY", "power": "ON" } } diff --git a/tests/fixtures/zone_states_ac_power.fan.json b/tests/fixtures/zone_states_ac_power.fan.json index 753f72a..29a52cb 100644 --- a/tests/fixtures/zone_states_ac_power.fan.json +++ b/tests/fixtures/zone_states_ac_power.fan.json @@ -33,7 +33,7 @@ }, "setting": { "type": "AIR_CONDITIONING", - "mode": "DRY", + "mode": "FAN", "power": "ON" }, "type": "MANUAL" @@ -53,7 +53,7 @@ "nextScheduleChange": null, "setting": { "type": "AIR_CONDITIONING", - "mode": "DRY", + "mode": "FAN", "power": "ON" } } diff --git a/tests/test_tado.py b/tests/test_tado.py index 801ba43..f34ef7d 100644 --- a/tests/test_tado.py +++ b/tests/test_tado.py @@ -260,7 +260,6 @@ async def test_get_zone_states_heating_power( @pytest.mark.parametrize( ("fixture_file"), [ - # Go through the different modes ("zone_states_ac_power.dry.json"), ("zone_states_ac_power.fan.json"), ], From c314e5cd3276f61cccae3900da119b00f293ced6 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Mon, 2 Dec 2024 22:11:46 +0000 Subject: [PATCH 11/11] Upgrade to version 0.1.19 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 63885c3..a50df8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "tadoasync" -version = "0.1.18" +version = "0.1.19" authors = ["Erwin Douna "] classifiers = [ "Development Status :: 5 - Production/Stable",