From 62e6b30db797ad11638f99be453570ac5c401876 Mon Sep 17 00:00:00 2001 From: Tobias Sauerwein Date: Sat, 13 Jan 2024 21:51:34 +0100 Subject: [PATCH] Update bticino (#486) * Update BNCS * feat: add centralized ventilation controller NLLF --- CHANGELOG.md | 4 +- fixtures/homesdata.json | 1641 +++++++++-------- .../homestatus_91763b24c43d3e344f424e8b.json | 10 + src/pyatmo/home.py | 2 +- src/pyatmo/modules/__init__.py | 3 +- src/pyatmo/modules/bticino.py | 4 +- src/pyatmo/modules/device_types.py | 5 + src/pyatmo/modules/legrand.py | 5 +- src/pyatmo/modules/module.py | 33 + tests/common.py | 2 +- tests/test_camera.py | 4 +- tests/test_energy.py | 2 +- tests/test_fan.py | 18 + tests/test_home.py | 4 +- tests/test_shutter.py | 2 +- tests/test_switch.py | 2 +- tests/test_weather.py | 2 +- 17 files changed, 926 insertions(+), 817 deletions(-) create mode 100644 tests/test_fan.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 1131c067..e7884928 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- +- Add NLLF centralized ventilation controller ### Changed @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- +- Add BNSC switch capability ### Security diff --git a/fixtures/homesdata.json b/fixtures/homesdata.json index b921bb44..7e7e753e 100644 --- a/fixtures/homesdata.json +++ b/fixtures/homesdata.json @@ -1,817 +1,856 @@ { - "body": { - "homes": [ - { - "id": "91763b24c43d3e344f424e8b", - "name": "MYHOME", - "altitude": 112, - "coordinates": [52.516263, 13.377726], - "country": "DE", - "timezone": "Europe/Berlin", - "rooms": [ - { - "id": "2746182631", - "name": "Livingroom", - "type": "livingroom", - "module_ids": ["12:34:56:00:01:ae"] - }, - { - "id": "3688132631", - "name": "Hall", - "type": "custom", - "module_ids": [ - "12:34:56:00:f1:62", - "12:34:56:10:f1:66", - "12:34:56:00:e3:9b", - "0009999992", - "0009999993" - ] - }, - { - "id": "2833524037", - "name": "Entrada", - "type": "lobby", - "module_ids": ["12:34:56:03:a5:54"] - }, - { - "id": "2940411577", - "name": "Cocina", - "type": "kitchen", - "module_ids": ["12:34:56:03:a0:ac"] - }, - { - "id": "222452125", - "name": "Bureau", - "type": "electrical_cabinet", - "module_ids": ["12:34:56:20:f5:44", "12:34:56:20:f5:8c"], - "modules": ["12:34:56:20:f5:44", "12:34:56:20:f5:8c"], - "therm_relay": "12:34:56:20:f5:44", - "true_temperature_available": true - }, - { - "id": "100007519", - "name": "Cabinet", - "type": "electrical_cabinet", - "module_ids": [ - "12:34:56:00:16:0e", - "12:34:56:00:16:0e#0", - "12:34:56:00:16:0e#1", - "12:34:56:00:16:0e#2", - "12:34:56:00:16:0e#3", - "12:34:56:00:16:0e#4", - "12:34:56:00:16:0e#5", - "12:34:56:00:16:0e#6", - "12:34:56:00:16:0e#7", - "12:34:56:00:16:0e#8" - ] - }, - { - "id": "1002003001", - "name": "Corridor", - "type": "corridor", - "module_ids": ["10:20:30:bd:b8:1e"] - }, - { - "id": "100007520", - "name": "Toilettes", - "type": "toilets", - "module_ids": ["00:11:22:33:00:11:45:fe"] - } - ], - "modules": [ - { - "id": "12:34:56:00:fa:d0", - "type": "NAPlug", - "name": "Thermostat", - "setup_date": 1494963356, - "modules_bridged": [ - "12:34:56:00:01:ae", - "12:34:56:03:a0:ac", - "12:34:56:03:a5:54" - ] - }, - { - "id": "12:34:56:00:01:ae", - "type": "NATherm1", - "name": "Livingroom", - "setup_date": 1494963356, - "room_id": "2746182631", - "bridge": "12:34:56:00:fa:d0" - }, - { - "id": "12:34:56:03:a5:54", - "type": "NRV", - "name": "Valve1", - "setup_date": 1554549767, - "room_id": "2833524037", - "bridge": "12:34:56:00:fa:d0" - }, - { - "id": "12:34:56:03:a0:ac", - "type": "NRV", - "name": "Valve2", - "setup_date": 1554554444, - "room_id": "2940411577", - "bridge": "12:34:56:00:fa:d0" - }, - { - "id": "12:34:56:00:f1:62", - "type": "NACamera", - "name": "Hall", - "setup_date": 1544828430, - "room_id": "3688132631", - "modules_bridged": ["12:34:56:00:86:99", "12:34:56:00:e3:9b"] - }, - { - "id": "12:34:56:10:f1:66", - "type": "NDB", - "name": "Netatmo-Doorbell", - "setup_date": 1602691361, - "room_id": "3688132631", - "reachable": true, - "hk_device_id": "123456007df1", - "customer_id": "1000010", - "network_lock": false, - "quick_display_zone": 62 - }, - { - "id": "12:34:56:10:b9:0e", - "type": "NOC", - "name": "Front", - "setup_date": 1509290599, - "reachable": true, - "customer_id": "A00010", - "network_lock": false, - "use_pincode": false - }, - { - "id": "12:34:56:20:f5:44", - "type": "OTH", - "name": "Modulating Relay", - "setup_date": 1607443936, - "room_id": "222452125", - "reachable": true, - "modules_bridged": ["12:34:56:20:f5:8c"], - "hk_device_id": "12:34:56:20:d0:c5", - "capabilities": [ - { - "name": "automatism", - "available": true + "body": { + "homes": [ + { + "id": "91763b24c43d3e344f424e8b", + "name": "MYHOME", + "altitude": 112, + "coordinates": [ + 52.516263, + 13.377726 + ], + "country": "DE", + "timezone": "Europe/Berlin", + "rooms": [ + { + "id": "2746182631", + "name": "Livingroom", + "type": "livingroom", + "module_ids": [ + "12:34:56:00:01:ae" + ] + }, + { + "id": "3688132631", + "name": "Hall", + "type": "custom", + "module_ids": [ + "12:34:56:00:f1:62", + "12:34:56:10:f1:66", + "12:34:56:00:e3:9b", + "0009999992", + "0009999993" + ] + }, + { + "id": "2833524037", + "name": "Entrada", + "type": "lobby", + "module_ids": [ + "12:34:56:03:a5:54" + ] + }, + { + "id": "2940411577", + "name": "Cocina", + "type": "kitchen", + "module_ids": [ + "12:34:56:03:a0:ac" + ] + }, + { + "id": "222452125", + "name": "Bureau", + "type": "electrical_cabinet", + "module_ids": [ + "12:34:56:20:f5:44", + "12:34:56:20:f5:8c" + ], + "modules": [ + "12:34:56:20:f5:44", + "12:34:56:20:f5:8c" + ], + "therm_relay": "12:34:56:20:f5:44", + "true_temperature_available": true + }, + { + "id": "100007519", + "name": "Cabinet", + "type": "electrical_cabinet", + "module_ids": [ + "12:34:56:00:16:0e", + "12:34:56:00:16:0e#0", + "12:34:56:00:16:0e#1", + "12:34:56:00:16:0e#2", + "12:34:56:00:16:0e#3", + "12:34:56:00:16:0e#4", + "12:34:56:00:16:0e#5", + "12:34:56:00:16:0e#6", + "12:34:56:00:16:0e#7", + "12:34:56:00:16:0e#8" + ] + }, + { + "id": "1002003001", + "name": "Corridor", + "type": "corridor", + "module_ids": [ + "10:20:30:bd:b8:1e" + ] + }, + { + "id": "100007520", + "name": "Toilettes", + "type": "toilets", + "module_ids": [ + "00:11:22:33:00:11:45:fe" + ] + } + ], + "modules": [ + { + "id": "12:34:56:00:fa:d0", + "type": "NAPlug", + "name": "Thermostat", + "setup_date": 1494963356, + "modules_bridged": [ + "12:34:56:00:01:ae", + "12:34:56:03:a0:ac", + "12:34:56:03:a5:54" + ] + }, + { + "id": "12:34:56:00:01:ae", + "type": "NATherm1", + "name": "Livingroom", + "setup_date": 1494963356, + "room_id": "2746182631", + "bridge": "12:34:56:00:fa:d0" + }, + { + "id": "12:34:56:03:a5:54", + "type": "NRV", + "name": "Valve1", + "setup_date": 1554549767, + "room_id": "2833524037", + "bridge": "12:34:56:00:fa:d0" + }, + { + "id": "12:34:56:03:a0:ac", + "type": "NRV", + "name": "Valve2", + "setup_date": 1554554444, + "room_id": "2940411577", + "bridge": "12:34:56:00:fa:d0" + }, + { + "id": "12:34:56:00:f1:62", + "type": "NACamera", + "name": "Hall", + "setup_date": 1544828430, + "room_id": "3688132631", + "modules_bridged": [ + "12:34:56:00:86:99", + "12:34:56:00:e3:9b" + ] + }, + { + "id": "12:34:56:10:f1:66", + "type": "NDB", + "name": "Netatmo-Doorbell", + "setup_date": 1602691361, + "room_id": "3688132631", + "reachable": true, + "hk_device_id": "123456007df1", + "customer_id": "1000010", + "network_lock": false, + "quick_display_zone": 62 + }, + { + "id": "12:34:56:10:b9:0e", + "type": "NOC", + "name": "Front", + "setup_date": 1509290599, + "reachable": true, + "customer_id": "A00010", + "network_lock": false, + "use_pincode": false + }, + { + "id": "12:34:56:20:f5:44", + "type": "OTH", + "name": "Modulating Relay", + "setup_date": 1607443936, + "room_id": "222452125", + "reachable": true, + "modules_bridged": [ + "12:34:56:20:f5:8c" + ], + "hk_device_id": "12:34:56:20:d0:c5", + "capabilities": [ + { + "name": "automatism", + "available": true + } + ], + "max_modules_nb": 21 + }, + { + "id": "12:34:56:20:f5:8c", + "type": "OTM", + "name": "Bureau Modulate", + "setup_date": 1607443939, + "room_id": "222452125", + "bridge": "12:34:56:20:f5:44" + }, + { + "id": "12:34:56:30:d5:d4", + "type": "NBG", + "name": "module iDiamant", + "setup_date": 1562262465, + "room_id": "222452125", + "modules_bridged": [ + "0009999992", + "0009999993" + ] + }, + { + "id": "0009999992", + "type": "NBR", + "name": "Entrance Blinds", + "setup_date": 1578551339, + "room_id": "3688132631", + "bridge": "12:34:56:30:d5:d4" + }, + { + "id": "0009999993", + "type": "NBO", + "name": "Bubendorff blind", + "setup_date": 1594132017, + "room_id": "3688132631", + "bridge": "12:34:56:30:d5:d4" + }, + { + "id": "12:34:56:80:bb:26", + "type": "NAMain", + "name": "Villa", + "setup_date": 1419453350, + "room_id": "4122897288", + "reachable": true, + "modules_bridged": [ + "12:34:56:80:44:92", + "12:34:56:80:7e:18", + "12:34:56:80:1c:42", + "12:34:56:80:c1:ea" + ], + "customer_id": "C00016", + "hardware_version": 251, + "public_ext_data": false, + "public_ext_counter": 0, + "alarm_config": { + "default_alarm": [ + { + "db_alarm_number": 0 + }, + { + "db_alarm_number": 1 + }, + { + "db_alarm_number": 2 + }, + { + "db_alarm_number": 6 + }, + { + "db_alarm_number": 4 + }, + { + "db_alarm_number": 5 + }, + { + "db_alarm_number": 7 + }, + { + "db_alarm_number": 22 } ], - "max_modules_nb": 21 - }, - { - "id": "12:34:56:20:f5:8c", - "type": "OTM", - "name": "Bureau Modulate", - "setup_date": 1607443939, - "room_id": "222452125", - "bridge": "12:34:56:20:f5:44" - }, - { - "id": "12:34:56:30:d5:d4", - "type": "NBG", - "name": "module iDiamant", - "setup_date": 1562262465, - "room_id": "222452125", - "modules_bridged": ["0009999992", "0009999993"] - }, - { - "id": "0009999992", - "type": "NBR", - "name": "Entrance Blinds", - "setup_date": 1578551339, - "room_id": "3688132631", - "bridge": "12:34:56:30:d5:d4" - }, - { - "id": "0009999993", - "type": "NBO", - "name": "Bubendorff blind", - "setup_date": 1594132017, - "room_id": "3688132631", - "bridge": "12:34:56:30:d5:d4" + "personnalized": [ + { + "threshold": 20, + "data_type": 1, + "direction": 0, + "db_alarm_number": 8 + }, + { + "threshold": 17, + "data_type": 1, + "direction": 1, + "db_alarm_number": 9 + }, + { + "threshold": 65, + "data_type": 4, + "direction": 0, + "db_alarm_number": 16 + }, + { + "threshold": 19, + "data_type": 8, + "direction": 0, + "db_alarm_number": 22 + } + ] }, - { - "id": "12:34:56:80:bb:26", - "type": "NAMain", - "name": "Villa", - "setup_date": 1419453350, - "room_id": "4122897288", - "reachable": true, - "modules_bridged": [ - "12:34:56:80:44:92", - "12:34:56:80:7e:18", - "12:34:56:80:1c:42", - "12:34:56:80:c1:ea" - ], - "customer_id": "C00016", - "hardware_version": 251, - "public_ext_data": false, - "public_ext_counter": 0, - "alarm_config": { - "default_alarm": [ - { - "db_alarm_number": 0 - }, - { - "db_alarm_number": 1 - }, - { - "db_alarm_number": 2 - }, - { - "db_alarm_number": 6 - }, - { - "db_alarm_number": 4 - }, - { - "db_alarm_number": 5 - }, + "module_offset": { + "12:34:56:80:bb:26": { + "a": 0.1 + }, + "03:00:00:03:1b:0e": { + "a": 0 + } + } + }, + { + "id": "12:34:56:80:1c:42", + "type": "NAModule1", + "name": "Outdoor", + "setup_date": 1448565785, + "bridge": "12:34:56:80:bb:26" + }, + { + "id": "12:34:56:80:c1:ea", + "type": "NAModule3", + "name": "Rain", + "setup_date": 1591770206, + "bridge": "12:34:56:80:bb:26" + }, + { + "id": "12:34:56:80:44:92", + "type": "NAModule4", + "name": "Bedroom", + "setup_date": 1484997703, + "bridge": "12:34:56:80:bb:26" + }, + { + "id": "12:34:56:80:7e:18", + "type": "NAModule4", + "name": "Bathroom", + "setup_date": 1543579864, + "bridge": "12:34:56:80:bb:26" + }, + { + "id": "12:34:56:03:1b:e4", + "type": "NAModule2", + "name": "Garden", + "setup_date": 1543579864, + "bridge": "12:34:56:80:bb:26" + }, + { + "id": "12:34:56:80:60:40", + "type": "NLG", + "name": "Prise Control", + "setup_date": 1641841257, + "room_id": "1310352496", + "modules_bridged": [ + "12:34:56:80:00:12:ac:f2", + "12:34:56:80:00:c3:69:3c", + "12:34:56:00:00:a1:4c:da", + "12:34:56:00:01:01:01:a1", + "00:11:22:33:00:11:45:fe", + "12:34:56:00:01:01:01:b1" + ] + }, + { + "id": "12:34:56:80:00:12:ac:f2", + "type": "NLP", + "name": "Prise", + "setup_date": 1641841262, + "room_id": "1310352496", + "bridge": "12:34:56:80:60:40" + }, + { + "id": "12:34:56:80:00:c3:69:3c", + "type": "NLT", + "name": "Commande sans fil", + "setup_date": 1641841262, + "bridge": "12:34:56:80:60:40" + }, + { + "id": "12:34:56:00:86:99", + "type": "NACamDoorTag", + "name": "Window Hall", + "setup_date": 1581177375, + "bridge": "12:34:56:00:f1:62", + "category": "window" + }, + { + "id": "12:34:56:00:e3:9b", + "type": "NIS", + "setup_date": 1620479901, + "bridge": "12:34:56:00:f1:62", + "name": "Sirene in hall" + }, + { + "id": "12:34:56:00:16:0e", + "type": "NLE", + "name": "Écocompteur", + "setup_date": 1644496884, + "room_id": "100007519", + "modules_bridged": [ + "12:34:56:00:16:0e#0", + "12:34:56:00:16:0e#1", + "12:34:56:00:16:0e#2", + "12:34:56:00:16:0e#3", + "12:34:56:00:16:0e#4", + "12:34:56:00:16:0e#5", + "12:34:56:00:16:0e#6", + "12:34:56:00:16:0e#7", + "12:34:56:00:16:0e#8" + ] + }, + { + "id": "12:34:56:00:16:0e#0", + "type": "NLE", + "name": "Line 1", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#1", + "type": "NLE", + "name": "Line 2", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#2", + "type": "NLE", + "name": "Line 3", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#3", + "type": "NLE", + "name": "Line 4", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#4", + "type": "NLE", + "name": "Line 5", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#5", + "type": "NLE", + "name": "Total", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#6", + "type": "NLE", + "name": "Gas", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#7", + "type": "NLE", + "name": "Hot water", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:16:0e#8", + "type": "NLE", + "name": "Cold water", + "setup_date": 1644496886, + "room_id": "100007519", + "bridge": "12:34:56:00:16:0e" + }, + { + "id": "12:34:56:00:00:a1:4c:da", + "type": "NLPC", + "name": "Consumption meter", + "setup_date": 1638376602, + "room_id": "100008999", + "bridge": "12:34:56:80:60:40" + }, + { + "id": "10:20:30:bd:b8:1e", + "type": "BNS", + "name": "Smarther", + "setup_date": 1638022197, + "room_id": "1002003001" + }, + { + "id": "00:11:22:33:00:11:45:fe", + "type": "NLF", + "on": false, + "brightness": 63, + "firmware_revision": 57, + "last_seen": 1657086939, + "power": 0, + "reachable": true, + "bridge": "12:34:56:80:60:40" + }, + { + "id": "12:34:56:00:01:01:01:a1", + "type": "NLFN", + "name": "Bathroom light", + "setup_date": 1598367404, + "room_id": "1002003001", + "bridge": "12:34:56:80:60:40" + }, + { + "id": "12:34:56:00:01:01:01:b1", + "type": "NLLF", + "name": "Centralized ventilation controler", + "setup_date": 1598367504, + "room_id": "1002003001", + "bridge": "12:34:56:80:60:40" + } + ], + "schedules": [ + { + "zones": [ + { + "type": 0, + "name": "Comfort", + "rooms_temp": [ { - "db_alarm_number": 7 - }, + "temp": 21, + "room_id": "2746182631" + } + ], + "id": 0 + }, + { + "type": 1, + "name": "Night", + "rooms_temp": [ { - "db_alarm_number": 22 + "temp": 17, + "room_id": "2746182631" } ], - "personnalized": [ + "id": 1 + }, + { + "type": 5, + "name": "Eco", + "rooms_temp": [ { - "threshold": 20, - "data_type": 1, - "direction": 0, - "db_alarm_number": 8 - }, + "temp": 17, + "room_id": "2746182631" + } + ], + "id": 4 + } + ], + "timetable": [ + { + "zone_id": 1, + "m_offset": 0 + }, + { + "zone_id": 0, + "m_offset": 360 + }, + { + "zone_id": 4, + "m_offset": 420 + }, + { + "zone_id": 0, + "m_offset": 960 + }, + { + "zone_id": 1, + "m_offset": 1410 + }, + { + "zone_id": 0, + "m_offset": 1800 + }, + { + "zone_id": 4, + "m_offset": 1860 + }, + { + "zone_id": 0, + "m_offset": 2400 + }, + { + "zone_id": 1, + "m_offset": 2850 + }, + { + "zone_id": 0, + "m_offset": 3240 + }, + { + "zone_id": 4, + "m_offset": 3300 + }, + { + "zone_id": 0, + "m_offset": 3840 + }, + { + "zone_id": 1, + "m_offset": 4290 + }, + { + "zone_id": 0, + "m_offset": 4680 + }, + { + "zone_id": 4, + "m_offset": 4740 + }, + { + "zone_id": 0, + "m_offset": 5280 + }, + { + "zone_id": 1, + "m_offset": 5730 + }, + { + "zone_id": 0, + "m_offset": 6120 + }, + { + "zone_id": 4, + "m_offset": 6180 + }, + { + "zone_id": 0, + "m_offset": 6720 + }, + { + "zone_id": 1, + "m_offset": 7170 + }, + { + "zone_id": 0, + "m_offset": 7620 + }, + { + "zone_id": 1, + "m_offset": 8610 + }, + { + "zone_id": 0, + "m_offset": 9060 + }, + { + "zone_id": 1, + "m_offset": 10050 + } + ], + "hg_temp": 7, + "away_temp": 14, + "name": "Default", + "selected": true, + "id": "591b54a2764ff4d50d8b5795", + "type": "therm" + }, + { + "zones": [ + { + "type": 0, + "name": "Comfort", + "rooms_temp": [ { - "threshold": 17, - "data_type": 1, - "direction": 1, - "db_alarm_number": 9 - }, + "temp": 21, + "room_id": "2746182631" + } + ], + "id": 0 + }, + { + "type": 1, + "name": "Night", + "rooms_temp": [ { - "threshold": 65, - "data_type": 4, - "direction": 0, - "db_alarm_number": 16 - }, + "temp": 17, + "room_id": "2746182631" + } + ], + "id": 1 + }, + { + "type": 5, + "name": "Eco", + "rooms_temp": [ { - "threshold": 19, - "data_type": 8, - "direction": 0, - "db_alarm_number": 22 + "temp": 17, + "room_id": "2746182631" } - ] + ], + "id": 4 + } + ], + "timetable": [ + { + "zone_id": 1, + "m_offset": 0 }, - "module_offset": { - "12:34:56:80:bb:26": { - "a": 0.1 - }, - "03:00:00:03:1b:0e": { - "a": 0 - } + { + "zone_id": 0, + "m_offset": 360 + }, + { + "zone_id": 4, + "m_offset": 420 + }, + { + "zone_id": 0, + "m_offset": 960 + }, + { + "zone_id": 1, + "m_offset": 1410 + }, + { + "zone_id": 0, + "m_offset": 1800 + }, + { + "zone_id": 4, + "m_offset": 1860 + }, + { + "zone_id": 0, + "m_offset": 2400 + }, + { + "zone_id": 1, + "m_offset": 2850 + }, + { + "zone_id": 0, + "m_offset": 3240 + }, + { + "zone_id": 4, + "m_offset": 3300 + }, + { + "zone_id": 0, + "m_offset": 3840 + }, + { + "zone_id": 1, + "m_offset": 4290 + }, + { + "zone_id": 0, + "m_offset": 4680 + }, + { + "zone_id": 4, + "m_offset": 4740 + }, + { + "zone_id": 0, + "m_offset": 5280 + }, + { + "zone_id": 1, + "m_offset": 5730 + }, + { + "zone_id": 0, + "m_offset": 6120 + }, + { + "zone_id": 4, + "m_offset": 6180 + }, + { + "zone_id": 0, + "m_offset": 6720 + }, + { + "zone_id": 1, + "m_offset": 7170 + }, + { + "zone_id": 0, + "m_offset": 7620 + }, + { + "zone_id": 1, + "m_offset": 8610 + }, + { + "zone_id": 0, + "m_offset": 9060 + }, + { + "zone_id": 1, + "m_offset": 10050 } - }, - { - "id": "12:34:56:80:1c:42", - "type": "NAModule1", - "name": "Outdoor", - "setup_date": 1448565785, - "bridge": "12:34:56:80:bb:26" - }, - { - "id": "12:34:56:80:c1:ea", - "type": "NAModule3", - "name": "Rain", - "setup_date": 1591770206, - "bridge": "12:34:56:80:bb:26" - }, - { - "id": "12:34:56:80:44:92", - "type": "NAModule4", - "name": "Bedroom", - "setup_date": 1484997703, - "bridge": "12:34:56:80:bb:26" - }, - { - "id": "12:34:56:80:7e:18", - "type": "NAModule4", - "name": "Bathroom", - "setup_date": 1543579864, - "bridge": "12:34:56:80:bb:26" - }, - { - "id": "12:34:56:03:1b:e4", - "type": "NAModule2", - "name": "Garden", - "setup_date": 1543579864, - "bridge": "12:34:56:80:bb:26" - }, - { - "id": "12:34:56:80:60:40", - "type": "NLG", - "name": "Prise Control", - "setup_date": 1641841257, - "room_id": "1310352496", - "modules_bridged": [ - "12:34:56:80:00:12:ac:f2", - "12:34:56:80:00:c3:69:3c", - "12:34:56:00:00:a1:4c:da", - "12:34:56:00:01:01:01:a1", - "00:11:22:33:00:11:45:fe" - ] - }, - { - "id": "12:34:56:80:00:12:ac:f2", - "type": "NLP", - "name": "Prise", - "setup_date": 1641841262, - "room_id": "1310352496", - "bridge": "12:34:56:80:60:40" - }, - { - "id": "12:34:56:80:00:c3:69:3c", - "type": "NLT", - "name": "Commande sans fil", - "setup_date": 1641841262, - "bridge": "12:34:56:80:60:40" - }, - { - "id": "12:34:56:00:86:99", - "type": "NACamDoorTag", - "name": "Window Hall", - "setup_date": 1581177375, - "bridge": "12:34:56:00:f1:62", - "category": "window" - }, - { - "id": "12:34:56:00:e3:9b", - "type": "NIS", - "setup_date": 1620479901, - "bridge": "12:34:56:00:f1:62", - "name": "Sirene in hall" - }, - { - "id": "12:34:56:00:16:0e", - "type": "NLE", - "name": "Écocompteur", - "setup_date": 1644496884, - "room_id": "100007519", - "modules_bridged": [ - "12:34:56:00:16:0e#0", - "12:34:56:00:16:0e#1", - "12:34:56:00:16:0e#2", - "12:34:56:00:16:0e#3", - "12:34:56:00:16:0e#4", - "12:34:56:00:16:0e#5", - "12:34:56:00:16:0e#6", - "12:34:56:00:16:0e#7", - "12:34:56:00:16:0e#8" - ] - }, - { - "id": "12:34:56:00:16:0e#0", - "type": "NLE", - "name": "Line 1", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#1", - "type": "NLE", - "name": "Line 2", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#2", - "type": "NLE", - "name": "Line 3", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#3", - "type": "NLE", - "name": "Line 4", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#4", - "type": "NLE", - "name": "Line 5", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#5", - "type": "NLE", - "name": "Total", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#6", - "type": "NLE", - "name": "Gas", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#7", - "type": "NLE", - "name": "Hot water", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:16:0e#8", - "type": "NLE", - "name": "Cold water", - "setup_date": 1644496886, - "room_id": "100007519", - "bridge": "12:34:56:00:16:0e" - }, - { - "id": "12:34:56:00:00:a1:4c:da", - "type": "NLPC", - "name": "Consumption meter", - "setup_date": 1638376602, - "room_id": "100008999", - "bridge": "12:34:56:80:60:40" - }, - { - "id": "10:20:30:bd:b8:1e", - "type": "BNS", - "name": "Smarther", - "setup_date": 1638022197, - "room_id": "1002003001" - }, - { - "id": "00:11:22:33:00:11:45:fe", - "type": "NLF", - "on": false, - "brightness": 63, - "firmware_revision": 57, - "last_seen": 1657086939, - "power": 0, - "reachable": true, - "bridge": "12:34:56:80:60:40" - }, - { - "id": "12:34:56:00:01:01:01:a1", - "type": "NLFN", - "name": "Bathroom light", - "setup_date": 1598367404, - "room_id": "1002003001", - "bridge": "12:34:56:80:60:40" - } - ], - "schedules": [ - { - "zones": [ - { - "type": 0, - "name": "Comfort", - "rooms_temp": [ - { - "temp": 21, - "room_id": "2746182631" - } - ], - "id": 0 - }, - { - "type": 1, - "name": "Night", - "rooms_temp": [ - { - "temp": 17, - "room_id": "2746182631" - } - ], - "id": 1 - }, - { - "type": 5, - "name": "Eco", - "rooms_temp": [ - { - "temp": 17, - "room_id": "2746182631" - } - ], - "id": 4 - } - ], - "timetable": [ - { - "zone_id": 1, - "m_offset": 0 - }, - { - "zone_id": 0, - "m_offset": 360 - }, - { - "zone_id": 4, - "m_offset": 420 - }, - { - "zone_id": 0, - "m_offset": 960 - }, - { - "zone_id": 1, - "m_offset": 1410 - }, - { - "zone_id": 0, - "m_offset": 1800 - }, - { - "zone_id": 4, - "m_offset": 1860 - }, - { - "zone_id": 0, - "m_offset": 2400 - }, - { - "zone_id": 1, - "m_offset": 2850 - }, - { - "zone_id": 0, - "m_offset": 3240 - }, - { - "zone_id": 4, - "m_offset": 3300 - }, - { - "zone_id": 0, - "m_offset": 3840 - }, - { - "zone_id": 1, - "m_offset": 4290 - }, - { - "zone_id": 0, - "m_offset": 4680 - }, - { - "zone_id": 4, - "m_offset": 4740 - }, - { - "zone_id": 0, - "m_offset": 5280 - }, - { - "zone_id": 1, - "m_offset": 5730 - }, - { - "zone_id": 0, - "m_offset": 6120 - }, - { - "zone_id": 4, - "m_offset": 6180 - }, - { - "zone_id": 0, - "m_offset": 6720 - }, - { - "zone_id": 1, - "m_offset": 7170 - }, - { - "zone_id": 0, - "m_offset": 7620 - }, - { - "zone_id": 1, - "m_offset": 8610 - }, - { - "zone_id": 0, - "m_offset": 9060 - }, - { - "zone_id": 1, - "m_offset": 10050 - } - ], - "hg_temp": 7, - "away_temp": 14, - "name": "Default", - "selected": true, - "id": "591b54a2764ff4d50d8b5795", - "type": "therm" - }, - { - "zones": [ - { - "type": 0, - "name": "Comfort", - "rooms_temp": [ - { - "temp": 21, - "room_id": "2746182631" - } - ], - "id": 0 - }, - { - "type": 1, - "name": "Night", - "rooms_temp": [ - { - "temp": 17, - "room_id": "2746182631" - } - ], - "id": 1 - }, - { - "type": 5, - "name": "Eco", - "rooms_temp": [ - { - "temp": 17, - "room_id": "2746182631" - } - ], - "id": 4 - } - ], - "timetable": [ - { - "zone_id": 1, - "m_offset": 0 - }, - { - "zone_id": 0, - "m_offset": 360 - }, - { - "zone_id": 4, - "m_offset": 420 - }, - { - "zone_id": 0, - "m_offset": 960 - }, - { - "zone_id": 1, - "m_offset": 1410 - }, - { - "zone_id": 0, - "m_offset": 1800 - }, - { - "zone_id": 4, - "m_offset": 1860 - }, - { - "zone_id": 0, - "m_offset": 2400 - }, - { - "zone_id": 1, - "m_offset": 2850 - }, - { - "zone_id": 0, - "m_offset": 3240 - }, - { - "zone_id": 4, - "m_offset": 3300 - }, - { - "zone_id": 0, - "m_offset": 3840 - }, - { - "zone_id": 1, - "m_offset": 4290 - }, - { - "zone_id": 0, - "m_offset": 4680 - }, - { - "zone_id": 4, - "m_offset": 4740 - }, - { - "zone_id": 0, - "m_offset": 5280 - }, - { - "zone_id": 1, - "m_offset": 5730 - }, - { - "zone_id": 0, - "m_offset": 6120 - }, - { - "zone_id": 4, - "m_offset": 6180 - }, - { - "zone_id": 0, - "m_offset": 6720 - }, - { - "zone_id": 1, - "m_offset": 7170 - }, - { - "zone_id": 0, - "m_offset": 7620 - }, - { - "zone_id": 1, - "m_offset": 8610 - }, - { - "zone_id": 0, - "m_offset": 9060 - }, - { - "zone_id": 1, - "m_offset": 10050 - } - ], - "hg_temp": 7, - "away_temp": 14, - "name": "Winter", - "id": "b1b54a2f45795764f59d50d8", - "type": "therm" - } - ], - "therm_setpoint_default_duration": 120, - "persons": [ - { - "id": "91827374-7e04-5298-83ad-a0cb8372dff1", - "pseudo": "John Doe", - "url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7" - }, - { - "id": "91827375-7e04-5298-83ae-a0cb8372dff2", - "pseudo": "Jane Doe", - "url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72" - }, - { - "id": "91827376-7e04-5298-83af-a0cb8372dff3", - "pseudo": "Richard Doe", - "url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8" - } - ], - "therm_mode": "schedule" - }, - { - "id": "91763b24c43d3e344f424e8c", - "altitude": 112, - "coordinates": [52.516263, 13.377726], - "country": "DE", - "timezone": "Europe/Berlin", - "therm_setpoint_default_duration": 180, - "therm_mode": "schedule" - } - ], - "user": { - "email": "john@doe.com", - "language": "de-DE", - "locale": "de-DE", - "feel_like_algorithm": 0, - "unit_pressure": 0, - "unit_system": 0, - "unit_wind": 0, - "all_linked": false, - "type": "netatmo", - "id": "91763b24c43d3e344f424e8b" + ], + "hg_temp": 7, + "away_temp": 14, + "name": "Winter", + "id": "b1b54a2f45795764f59d50d8", + "type": "therm" + } + ], + "therm_setpoint_default_duration": 120, + "persons": [ + { + "id": "91827374-7e04-5298-83ad-a0cb8372dff1", + "pseudo": "John Doe", + "url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d7" + }, + { + "id": "91827375-7e04-5298-83ae-a0cb8372dff2", + "pseudo": "Jane Doe", + "url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c24b808a89f8d1730039d2c69928b029d67fc40cb2d7fb69ecdf2bb8b72" + }, + { + "id": "91827376-7e04-5298-83af-a0cb8372dff3", + "pseudo": "Richard Doe", + "url": "https://netatmocameraimage.blob.core.windows.net/production/d74fad765b9100ef480720a9a4a95c2d1730fb69ecdf2bb8b72039d2c69928b029d67fc40cb2d74b808a89f8" + } + ], + "therm_mode": "schedule" + }, + { + "id": "91763b24c43d3e344f424e8c", + "altitude": 112, + "coordinates": [ + 52.516263, + 13.377726 + ], + "country": "DE", + "timezone": "Europe/Berlin", + "therm_setpoint_default_duration": 180, + "therm_mode": "schedule" } - }, - "status": "ok", - "time_exec": 0.056135892868042, - "time_server": 1559171003 - } + ], + "user": { + "email": "john@doe.com", + "language": "de-DE", + "locale": "de-DE", + "feel_like_algorithm": 0, + "unit_pressure": 0, + "unit_system": 0, + "unit_wind": 0, + "all_linked": false, + "type": "netatmo", + "id": "91763b24c43d3e344f424e8b" + } + }, + "status": "ok", + "time_exec": 0.056135892868042, + "time_server": 1559171003 +} diff --git a/fixtures/homestatus_91763b24c43d3e344f424e8b.json b/fixtures/homestatus_91763b24c43d3e344f424e8b.json index 330d4452..212fc55b 100644 --- a/fixtures/homestatus_91763b24c43d3e344f424e8b.json +++ b/fixtures/homestatus_91763b24c43d3e344f424e8b.json @@ -317,6 +317,16 @@ "power": 0, "reachable": true, "bridge": "12:34:56:80:60:40" + }, + { + "id": "12:34:56:00:01:01:01:b1", + "type": "NLLF", + "firmware_revision": 60, + "last_seen": 1657086949, + "power": 11, + "reachable": true, + "bridge": "12:34:56:80:60:40", + "fan_speed": 1 } ], "rooms": [ diff --git a/src/pyatmo/home.py b/src/pyatmo/home.py index ac6dd2cd..3828ef75 100644 --- a/src/pyatmo/home.py +++ b/src/pyatmo/home.py @@ -70,7 +70,7 @@ def __init__(self, auth: AbstractAsyncAuth, raw_data: RawData) -> None: } self.events = {} - def get_module(self, module) -> Module: + def get_module(self, module: dict) -> Module: """Return module.""" try: diff --git a/src/pyatmo/modules/__init__.py b/src/pyatmo/modules/__init__.py index 4e697963..d9364ddb 100644 --- a/src/pyatmo/modules/__init__.py +++ b/src/pyatmo/modules/__init__.py @@ -55,7 +55,7 @@ Z3L, NLunknown, ) -from .module import Camera, Dimmer, Module, Shutter, Switch +from .module import Camera, Dimmer, Fan, Module, Shutter, Switch from .netatmo import ( NCO, NDB, @@ -101,6 +101,7 @@ "Camera", "Dimmer", "EBU", + "Fan", "Location", "Module", "NACamDoorTag", diff --git a/src/pyatmo/modules/bticino.py b/src/pyatmo/modules/bticino.py index 05682161..ebfd32d0 100644 --- a/src/pyatmo/modules/bticino.py +++ b/src/pyatmo/modules/bticino.py @@ -24,8 +24,8 @@ class BNEU(Module): """BTicino external unit.""" -class BNCS(Module): - """BTicino camera.""" +class BNCS(Switch): + """Bticino module Controlled Socket.""" class BNXM(Module): diff --git a/src/pyatmo/modules/device_types.py b/src/pyatmo/modules/device_types.py index 3f670b1c..41ac94ff 100644 --- a/src/pyatmo/modules/device_types.py +++ b/src/pyatmo/modules/device_types.py @@ -141,6 +141,7 @@ class DeviceCategory(str, Enum): meter = "meter" dimmer = "dimmer" opening = "opening" + fan = "fan" # pylint: enable=C0103 @@ -199,6 +200,8 @@ class DeviceCategory(str, Enum): DeviceType.BNIL: DeviceCategory.switch, DeviceType.BNLD: DeviceCategory.dimmer, DeviceType.NIS: DeviceCategory.siren, + DeviceType.BNCS: DeviceCategory.switch, + DeviceType.NLLF: DeviceCategory.fan, } @@ -238,6 +241,7 @@ class DeviceCategory(str, Enum): DeviceType.NLFN: ("Legrand", "Light switch/dimmer with neutral"), DeviceType.NLM: ("Legrand", "Light micro module"), DeviceType.NLL: ("Legrand", "Italian light switch with neutral"), + DeviceType.NLLF: ("Legrand", "Centralized ventilation device"), DeviceType.NLV: ("Legrand/BTicino", "Shutters"), DeviceType.NLLV: ("Legrand/BTicino", "Shutters"), DeviceType.NLLM: ("Legrand/BTicino", "Shutters"), @@ -271,6 +275,7 @@ class DeviceCategory(str, Enum): DeviceType.BNTR: ("BTicino", "Module towel rail"), DeviceType.BNIL: ("BTicino", "Intelligent light"), DeviceType.BNLD: ("BTicino", "Dimmer"), + DeviceType.BNCS: ("BTicino", "Controlled socket"), # Bubbendorf shutters DeviceType.NBG: ("Bubbendorf", "Gateway"), DeviceType.NBR: ("Bubbendorf", "Roller Shutter"), diff --git a/src/pyatmo/modules/legrand.py b/src/pyatmo/modules/legrand.py index 5be62285..ebf954c2 100644 --- a/src/pyatmo/modules/legrand.py +++ b/src/pyatmo/modules/legrand.py @@ -8,6 +8,7 @@ ContactorMixin, Dimmer, EnergyMixin, + Fan, FirmwareMixin, HistoryMixin, Module, @@ -133,8 +134,8 @@ class NLUO(Dimmer): """Legrand NLUO device stub.""" -class NLLF(Module): - """Legrand NLLF device stub.""" +class NLLF(Fan): + """Legrand NLLF fan/ventilation device.""" class NLunknown(Module): diff --git a/src/pyatmo/modules/module.py b/src/pyatmo/modules/module.py index 95a94713..b4f1d81a 100644 --- a/src/pyatmo/modules/module.py +++ b/src/pyatmo/modules/module.py @@ -372,6 +372,33 @@ async def async_off(self) -> bool: return await self.async_set_switch(False) +class FanSpeedMixin(EntityBase): + """Mixin for fan speed data.""" + + def __init__(self, home: Home, module: ModuleT): + """Initialize fan speed mixin.""" + + super().__init__(home, module) # type: ignore # mypy issue 4335 + self.fan_speed: int | None = None + + async def async_set_fan_speed(self, speed: int) -> bool: + """Set fan speed.""" + + json_fan_speed = { + "modules": [ + { + "id": self.entity_id, + # fan speed is clamped between 1 and 2 + # since only NLLF is such a device + # and it can only supports fan_speed 1 or 2 + "fan_speed": max(min(2, speed), 1), + "bridge": self.bridge, + }, + ], + } + return await self.home.async_set_state(json_fan_speed) + + class ShutterMixin(EntityBase): """Mixin for shutter data.""" @@ -733,4 +760,10 @@ class Shutter(FirmwareMixin, ShutterMixin, Module): ... +class Fan(FirmwareMixin, FanSpeedMixin, PowerMixin, Module): + """Class to represent a Netatmo ventilation device.""" + + ... + + # pylint: enable=too-many-ancestors diff --git a/tests/common.py b/tests/common.py index ac956de4..a210be34 100644 --- a/tests/common.py +++ b/tests/common.py @@ -1,4 +1,4 @@ -"""Define shared fixtures.""" +"""Define shared test helpers.""" # pylint: disable=redefined-outer-name, protected-access, unused-argument from __future__ import annotations diff --git a/tests/test_camera.py b/tests/test_camera.py index ce2b495e..d9d3018e 100644 --- a/tests/test_camera.py +++ b/tests/test_camera.py @@ -1,4 +1,4 @@ -"""Define tests for climate module.""" +"""Define tests for camera module.""" import json from unittest.mock import AsyncMock, patch @@ -35,6 +35,8 @@ async def test_async_NOC(async_home): # pylint: disable=invalid-name assert module.firmware_revision == 3002000 assert module.firmware_name == "3.2.0" assert module.monitoring is True + assert module.alim_status == 2 + assert module.is_local is False assert module.floodlight == "auto" with open("fixtures/status_ok.json", encoding="utf-8") as json_file: diff --git a/tests/test_energy.py b/tests/test_energy.py index 5a7dce67..06ec2408 100644 --- a/tests/test_energy.py +++ b/tests/test_energy.py @@ -1,4 +1,4 @@ -"""Define tests for climate module.""" +"""Define tests for energy module.""" from pyatmo import DeviceType import pytest diff --git a/tests/test_fan.py b/tests/test_fan.py new file mode 100644 index 00000000..6c3a2c0c --- /dev/null +++ b/tests/test_fan.py @@ -0,0 +1,18 @@ +"""Define tests for fan module.""" + +from pyatmo import DeviceType +import pytest + +# pylint: disable=F6401 + + +@pytest.mark.asyncio +async def test_async_fan_NLLF(async_home): # pylint: disable=invalid-name + """Test NLLF Legrand centralized ventilation controller.""" + module_id = "12:34:56:00:01:01:01:b1" + assert module_id in async_home.modules + module = async_home.modules[module_id] + assert module.device_type == DeviceType.NLLF + assert module.power == 11 + assert module.firmware_revision == 60 + assert module.fan_speed == 1 diff --git a/tests/test_home.py b/tests/test_home.py index df042098..5b1506c4 100644 --- a/tests/test_home.py +++ b/tests/test_home.py @@ -1,4 +1,4 @@ -"""Define tests for climate module.""" +"""Define tests for home module.""" import datetime as dt import json from unittest.mock import AsyncMock, patch @@ -26,7 +26,7 @@ async def test_async_home(async_home): DeviceType.NBO, } assert len(async_home.rooms) == 8 - assert len(async_home.modules) == 37 + assert len(async_home.modules) == 38 assert async_home.modules != room.modules module_id = "12:34:56:10:f1:66" diff --git a/tests/test_shutter.py b/tests/test_shutter.py index 11bbe3bc..b2f3df78 100644 --- a/tests/test_shutter.py +++ b/tests/test_shutter.py @@ -1,4 +1,4 @@ -"""Define tests for climate module.""" +"""Define tests for shutter module.""" import json from unittest.mock import AsyncMock, patch diff --git a/tests/test_switch.py b/tests/test_switch.py index a718d852..af5034ce 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -1,4 +1,4 @@ -"""Define tests for climate module.""" +"""Define tests for switch module.""" from pyatmo import DeviceType import pytest diff --git a/tests/test_weather.py b/tests/test_weather.py index 6bd67d7d..fac69461 100644 --- a/tests/test_weather.py +++ b/tests/test_weather.py @@ -1,4 +1,4 @@ -"""Define tests for climate module.""" +"""Define tests for weaather module.""" import pyatmo from pyatmo import DeviceType