From 4de68351a83dd48d54b0c7faf88a3f2224ee3ad1 Mon Sep 17 00:00:00 2001 From: tmenguy Date: Sun, 18 Aug 2024 23:35:17 +0200 Subject: [PATCH] Energy support, NLE support (#503) * Release v8.0.3 (#488) * Update BNCS * feat: add centralized ventilation controller NLLF --------- Signed-off-by: Tobias Sauerwein * Initial commit for support of all schedule types, and fix for historical energy data * Corrected devices to use hstoryMixin to get energy * Merged historyMixin and Energy has they are effectively doing the sum, introduces a sum energy and an helper to be used in homeassistant primarily * removed the daily update * added a reset measures method to be used directly by external libreries * reset now resets timings too * Try to get a proper historical data in case of peak / off_peak energy mode, add some tests * Fixed correctly the timing end/start of measures * Fixed correctly the timing end/start of measures * Fixed correctly the timing end/start of measures * support correct empty measures * removed specidif energy exception to use th egeneric API error, 0lus some logging * removed specidif energy exception to use th egeneric API error, 0lus some logging * removed specidif energy exception to use th egeneric API error, 0lus some logging * removed specidif energy exception to use th egeneric API error, 0lus some logging * async update for all homes * async update for all homes * async update for all homes * async update for all homes * async update for all homes * async update for all homes * async update for all homes * async update for all homes * async update for all homes * added some tests for historical data * added some tests for historical data * added a way to get the data sum * added throttling exception * fix for num calls estimation * fix for num calls estimation * changed type for energy * changed type for energy * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling * all tests pass * added energy sum * added energy sum * added energy sum * added energy sum * PEP cleaning to prepare PR * adjusting estimation calculus * adjusting estimation calculus * adjusting estimation calculus * slight refactor for readability * Support error for unreachable home and bridges ....it is an error, not a normal call * Support error for unreachable home and bridges ....it is an error, not a normal call * remove global energy sum support, no needed anymore, was adding complexity * remove global energy sum support, no needed anymore, was adding complexity * refactor to use self.homes where it should be * setting schedules list back as the global list of schedules, for retro-compatibility * Black.... * Ruff.... * Ruff.... * Ruff.... * Ruff.... then black funny game * black.... then ruff funny game * black and ruff game * black and ruff game * YABT .. yet another Black Test * Cleaned supported homes with a way simpler approach, thx @cgtobi * keep black API * keep black API * Added back a list of available homes to be able to select the one needed or not * white space * Merge remote-tracking branch 'refs/remotes/upstream/development' into development # Conflicts: # src/pyatmo/modules/bticino.py * Support NLE "connected ecocometer" that is a bridge * Support NLE "connected ecocometer" that is a bridge...and has no power data in teh homestatus API * Support NLE "connected ecocometer" that is a bridge...and has no power data in teh homestatus API * Support NLE "connected ecocometer" that is a bridge...and has no power data in teh homestatus API * Black / Rust * Black / Rust * Black / Rust * Remove schedule code API calls, etc ... to make it compatible with old lib * Remove schedule code API calls, etc ... to make it compatible with old lib * Remove schedule code API calls, etc ... to make it compatible with old lib * Remove schedule code API calls, etc ... to make it compatible with old lib * Black / Rust * Black / Rust * Black / Rust * Black / Rust * Black / Rust * Black / Ruff * Black / Ruff * some first remarks from PR fixes * removed home update boolean as output, and raise conditionally a reachability error * removed home update boolean as output, and raise conditionally a reachability error * rieman energy method extraction * last PR comments * black / ruff --------- Signed-off-by: Tobias Sauerwein Co-authored-by: Tobias Sauerwein --- .../getmeasure_12_34_56_00_00_a1_4c_da.json | 517 -- ...y_from_grid$2_12_34_56_00_00_a1_4c_da.json | 517 ++ ...y_from_grid$2_98_76_54_32_10_00_00_69.json | 247 + .../home_multi_status_error_disconnected.json | 15 + fixtures/homesdata_multi.json | 6441 +++++++++++++++++ src/pyatmo/__init__.py | 12 +- src/pyatmo/account.py | 28 +- src/pyatmo/auth.py | 14 +- src/pyatmo/const.py | 3 + src/pyatmo/exceptions.py | 12 + src/pyatmo/helpers.py | 4 +- src/pyatmo/home.py | 38 +- src/pyatmo/modules/base_class.py | 59 +- src/pyatmo/modules/legrand.py | 37 +- src/pyatmo/modules/module.py | 420 +- tests/common.py | 15 +- tests/conftest.py | 28 +- tests/test_energy.py | 134 +- tests/test_home.py | 32 +- tests/testing_main_template.py | 48 + 20 files changed, 7990 insertions(+), 631 deletions(-) delete mode 100644 fixtures/getmeasure_12_34_56_00_00_a1_4c_da.json create mode 100644 fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_12_34_56_00_00_a1_4c_da.json create mode 100644 fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_98_76_54_32_10_00_00_69.json create mode 100644 fixtures/home_multi_status_error_disconnected.json create mode 100644 fixtures/homesdata_multi.json create mode 100644 tests/testing_main_template.py diff --git a/fixtures/getmeasure_12_34_56_00_00_a1_4c_da.json b/fixtures/getmeasure_12_34_56_00_00_a1_4c_da.json deleted file mode 100644 index 9eb499ab..00000000 --- a/fixtures/getmeasure_12_34_56_00_00_a1_4c_da.json +++ /dev/null @@ -1,517 +0,0 @@ -{ - "body": [ - { - "beg_time": 1644049789, - "step_time": 3600, - "value": [ - [ - 197 - ], - [ - 262 - ], - [ - 168 - ], - [ - 219 - ], - [ - 224 - ], - [ - 299 - ], - [ - 343 - ], - [ - 443 - ], - [ - 317 - ], - [ - 229 - ], - [ - 147 - ], - [ - 178 - ], - [ - 340 - ], - [ - 536 - ], - [ - 471 - ], - [ - 397 - ], - [ - 290 - ], - [ - 302 - ], - [ - 309 - ], - [ - 219 - ], - [ - 154 - ], - [ - 163 - ], - [ - 146 - ], - [ - 189 - ], - [ - 256 - ], - [ - 162 - ], - [ - 1288 - ], - [ - 256 - ], - [ - 709 - ], - [ - 310 - ], - [ - 379 - ], - [ - 296 - ], - [ - 230 - ], - [ - 505 - ], - [ - 362 - ], - [ - 611 - ], - [ - 597 - ], - [ - 505 - ], - [ - 431 - ], - [ - 1538 - ], - [ - 265 - ], - [ - 187 - ], - [ - 162 - ], - [ - 150 - ], - [ - 155 - ], - [ - 147 - ], - [ - 211 - ], - [ - 211 - ], - [ - 272 - ], - [ - 271 - ], - [ - 331 - ], - [ - 180 - ], - [ - 184 - ], - [ - 182 - ], - [ - 232 - ], - [ - 288 - ], - [ - 266 - ], - [ - 256 - ], - [ - 249 - ], - [ - 372 - ], - [ - 379 - ], - [ - 585 - ], - [ - 387 - ], - [ - 277 - ], - [ - 223 - ], - [ - 202 - ], - [ - 163 - ], - [ - 143 - ], - [ - 158 - ], - [ - 145 - ], - [ - 232 - ], - [ - 231 - ], - [ - 160 - ], - [ - 261 - ], - [ - 376 - ], - [ - 216 - ], - [ - 202 - ], - [ - 295 - ], - [ - 310 - ], - [ - 235 - ], - [ - 188 - ], - [ - 269 - ], - [ - 250 - ], - [ - 334 - ], - [ - 434 - ], - [ - 353 - ], - [ - 279 - ], - [ - 266 - ], - [ - 226 - ], - [ - 179 - ], - [ - 149 - ], - [ - 146 - ], - [ - 143 - ], - [ - 136 - ], - [ - 173 - ], - [ - 221 - ], - [ - 190 - ], - [ - 177 - ], - [ - 290 - ], - [ - 352 - ], - [ - 252 - ], - [ - 284 - ], - [ - 173 - ], - [ - 165 - ], - [ - 144 - ], - [ - 175 - ], - [ - 268 - ], - [ - 363 - ], - [ - 544 - ], - [ - 515 - ], - [ - 525 - ], - [ - 431 - ], - [ - 225 - ], - [ - 183 - ], - [ - 178 - ], - [ - 155 - ], - [ - 170 - ], - [ - 156 - ], - [ - 169 - ], - [ - 226 - ], - [ - 255 - ], - [ - 273 - ], - [ - 466 - ], - [ - 406 - ], - [ - 333 - ], - [ - 194 - ], - [ - 234 - ], - [ - 271 - ], - [ - 238 - ], - [ - 221 - ], - [ - 205 - ], - [ - 258 - ], - [ - 430 - ], - [ - 446 - ], - [ - 390 - ], - [ - 306 - ], - [ - 223 - ], - [ - 165 - ], - [ - 154 - ], - [ - 147 - ], - [ - 155 - ], - [ - 140 - ], - [ - 153 - ], - [ - 228 - ], - [ - 237 - ], - [ - 201 - ], - [ - 183 - ], - [ - 194 - ], - [ - 135 - ], - [ - 206 - ], - [ - 215 - ], - [ - 147 - ], - [ - 159 - ], - [ - 185 - ], - [ - 168 - ], - [ - 257 - ], - [ - 262 - ], - [ - 141 - ], - [ - 151 - ], - [ - 157 - ], - [ - 133 - ], - [ - 147 - ], - [ - 135 - ], - [ - 139 - ], - [ - 136 - ], - [ - 127 - ], - [ - 169 - ], - [ - 259 - ] - ] - } - ], - "status": "ok", - "time_exec": 0.5533828735351562, - "time_server": 1647935044 -} diff --git a/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_12_34_56_00_00_a1_4c_da.json b/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_12_34_56_00_00_a1_4c_da.json new file mode 100644 index 00000000..1c1d1694 --- /dev/null +++ b/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_12_34_56_00_00_a1_4c_da.json @@ -0,0 +1,517 @@ +{ + "body": [ + { + "beg_time": 1644049789, + "step_time": 3600, + "value": [ + [ null, + 197 + ,null, null], + [null, + 262 + ,null, null], + [null, + 168 + ,null, null], + [null, + 219 + ,null, null], + [null, + 224 + ,null, null], + [null, + 299 + ,null, null], + [null, + 343 + ,null, null], + [null, + 443 + ,null, null], + [null, + 317 + ,null, null], + [null, + 229 + ,null, null], + [null, + 147 + ,null, null], + [null, + 178 + ,null, null], + [null, + 340 + ,null, null], + [null, + 536 + ,null, null], + [null, + 471 + ,null, null], + [null, + 397 + ,null, null], + [null, + 290 + ,null, null], + [null, + 302 + ,null, null], + [null, + 309 + ,null, null], + [null, + 219 + ,null, null], + [null, + 154 + ,null, null], + [null, + 163 + ,null, null], + [null, + 146 + ,null, null], + [null, + 189 + ,null, null], + [null, + 256 + ,null, null], + [null, + 162 + ,null, null], + [null, + 1288 + ,null, null], + [null, + 256 + ,null, null], + [null, + 709 + ,null, null], + [null, + 310 + ,null, null], + [null, + 379 + ,null, null], + [null, + 296 + ,null, null], + [null, + 230 + ,null, null], + [null, + 505 + ,null, null], + [null, + 362 + ,null, null], + [null, + 611 + ,null, null], + [null, + 597 + ,null, null], + [null, + 505 + ,null, null], + [null, + 431 + ,null, null], + [null, + 1538 + ,null, null], + [null, + 265 + ,null, null], + [null, + 187 + ,null, null], + [null, + 162 + ,null, null], + [null, + 150 + ,null, null], + [null, + 155 + ,null, null], + [null, + 147 + ,null, null], + [null, + 211 + ,null, null], + [null, + 211 + ,null, null], + [null, + 272 + ,null, null], + [null, + 271 + ,null, null], + [null, + 331 + ,null, null], + [null, + 180 + ,null, null], + [null, + 184 + ,null, null], + [null, + 182 + ,null, null], + [null, + 232 + ,null, null], + [null, + 288 + ,null, null], + [null, + 266 + ,null, null], + [null, + 256 + ,null, null], + [null, + 249 + ,null, null], + [null, + 372 + ,null, null], + [null, + 379 + ,null, null], + [null, + 585 + ,null, null], + [null, + 387 + ,null, null], + [null, + 277 + ,null, null], + [null, + 223 + ,null, null], + [null, + 202 + ,null, null], + [null, + 163 + ,null, null], + [null, + 143 + ,null, null], + [null, + 158 + ,null, null], + [null, + 145 + ,null, null], + [null, + 232 + ,null, null], + [null, + 231 + ,null, null], + [null, + 160 + ,null, null], + [null, + 261 + ,null, null], + [null, + 376 + ,null, null], + [null, + 216 + ,null, null], + [null, + 202 + ,null, null], + [null, + 295 + ,null, null], + [null, + 310 + ,null, null], + [null, + 235 + ,null, null], + [null, + 188 + ,null, null], + [null, + 269 + ,null, null], + [null, + 250 + ,null, null], + [null, + 334 + ,null, null], + [null, + 434 + ,null, null], + [null, + 353 + ,null, null], + [null, + 279 + ,null, null], + [null, + 266 + ,null, null], + [null, + 226 + ,null, null], + [null, + 179 + ,null, null], + [null, + 149 + ,null, null], + [null, + 146 + ,null, null], + [null, + 143 + ,null, null], + [null, + 136 + ,null, null], + [null, + 173 + ,null, null], + [null, + 221 + ,null, null], + [null, + 190 + ,null, null], + [null, + 177 + ,null, null], + [null, + 290 + ,null, null], + [null, + 352 + ,null, null], + [null, + 252 + ,null, null], + [null, + 284 + ,null, null], + [null, + 173 + ,null, null], + [null, + 165 + ,null, null], + [null, + 144 + ,null, null], + [null, + 175 + ,null, null], + [null, + 268 + ,null, null], + [null, + 363 + ,null, null], + [null, + 544 + ,null, null], + [null, + 515 + ,null, null], + [null, + 525 + ,null, null], + [null, + 431 + ,null, null], + [null, + 225 + ,null, null], + [null, + 183 + ,null, null], + [null, + 178 + ,null, null], + [null, + 155 + ,null, null], + [null, + 170 + ,null, null], + [null, + 156 + ,null, null], + [null, + 169 + ,null, null], + [null, + 226 + ,null, null], + [null, + 255 + ,null, null], + [null, + 273 + ,null, null], + [null, + 466 + ,null, null], + [null, + 406 + ,null, null], + [null, + 333 + ,null, null], + [null, + 194 + ,null, null], + [null, + 234 + ,null, null], + [null, + 271 + ,null, null], + [null, + 238 + ,null, null], + [null, + 221 + ,null, null], + [null, + 205 + ,null, null], + [null, + 258 + ,null, null], + [null, + 430 + ,null, null], + [null, + 446 + ,null, null], + [null, + 390 + ,null, null], + [null, + 306 + ,null, null], + [null, + 223 + ,null, null], + [null, + 165 + ,null, null], + [null, + 154 + ,null, null], + [null, + 147 + ,null, null], + [null, + 155 + ,null, null], + [null, + 140 + ,null, null], + [null, + 153 + ,null, null], + [null, + 228 + ,null, null], + [null, + 237 + ,null, null], + [null, + 201 + ,null, null], + [null, + 183 + ,null, null], + [null, + 194 + ,null, null], + [null, + 135 + ,null, null], + [null, + 206 + ,null, null], + [null, + 215 + ,null, null], + [null, + 147 + ,null, null], + [null, + 159 + ,null, null], + [null, + 185 + ,null, null], + [null, + 168 + ,null, null], + [null, + 257 + ,null, null], + [null, + 262 + ,null, null], + [null, + 141 + ,null, null], + [null, + 151 + ,null, null], + [null, + 157 + ,null, null], + [null, + 133 + ,null, null], + [null, + 147 + ,null, null], + [null, + 135 + ,null, null], + [null, + 139 + ,null, null], + [null, + 136 + ,null, null], + [null, + 127 + ,null, null], + [null, + 169 + ,null, null], + [null, + 259, null, null + ] + ] + } + ], + "status": "ok", + "time_exec": 0.5533828735351562, + "time_server": 1647935044 +} diff --git a/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_98_76_54_32_10_00_00_69.json b/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_98_76_54_32_10_00_00_69.json new file mode 100644 index 00000000..3e11402e --- /dev/null +++ b/fixtures/getmeasure_sum_energy_buy_from_grid,sum_energy_buy_from_grid$0,sum_energy_buy_from_grid$1,sum_energy_buy_from_grid$2_98_76_54_32_10_00_00_69.json @@ -0,0 +1,247 @@ +{ + "body": [ + { + "beg_time": 1721772900, + "step_time": 1800, + "value": [ + [ + null, + 20, + null, + null + ], + [ + null, + 19, + null, + null + ], + [ + null, + 16, + null, + null + ], + [ + null, + 11, + null, + null + ], + [ + null, + 18, + null, + null + ], + [ + null, + 14, + null, + null + ], + [ + null, + 14, + null, + null + ], + [ + null, + 64, + null, + null + ], + [ + null, + 100, + null, + null + ], + [ + null, + 58, + null, + null + ], + [ + null, + 39, + null, + null + ], + [ + null, + 24, + null, + null + ], + [ + null, + 19, + null, + null + ], + [ + null, + 19, + null, + null + ], + [ + null, + 712, + null, + null + ], + [ + null, + 724, + null, + null + ], + [ + null, + 711, + null, + null + ], + [ + null, + 498, + 212, + null + ], + [ + null, + null, + 717, + null + ], + [ + null, + null, + 714, + null + ], + [ + null, + null, + 714, + null + ], + [ + null, + null, + 711, + null + ], + [ + null, + null, + 706, + null + ], + [ + null, + null, + 704, + null + ], + [ + null, + null, + 706, + null + ], + [ + null, + null, + 709, + null + ], + [ + null, + null, + 714, + null + ], + [ + null, + null, + 712, + null + ], + [ + null, + null, + 238, + 477 + ], + [ + null, + null, + null, + 714 + ], + [ + null, + null, + null, + 722 + ], + [ + null, + null, + null, + 713 + ], + [ + null, + null, + null, + 709 + ], + [ + null, + null, + null, + 714 + ], + [ + null, + null, + 477, + 241 + ], + [ + null, + null, + 710, + null + ], + [ + null, + null, + 710, + null + ], + [ + null, + null, + 707, + null + ], + [ + null, + null, + 16, + null + ] + ] + } + ], + "status": "ok", + "time_exec": 0.025647878646850586, + "time_server": 1721852913 +} \ No newline at end of file diff --git a/fixtures/home_multi_status_error_disconnected.json b/fixtures/home_multi_status_error_disconnected.json new file mode 100644 index 00000000..f94595bf --- /dev/null +++ b/fixtures/home_multi_status_error_disconnected.json @@ -0,0 +1,15 @@ +{ + "status":"ok", + "body":{ + "errors":[ + { + "code":6, + "id":"aa:aa:aa:aa:aa:aa" + } + ], + "home":{ + "id":"aaaaaaaaaaabbbbbbbbbbccc" + } + }, + "time_server":1559292039 +} \ No newline at end of file diff --git a/fixtures/homesdata_multi.json b/fixtures/homesdata_multi.json new file mode 100644 index 00000000..17a53e74 --- /dev/null +++ b/fixtures/homesdata_multi.json @@ -0,0 +1,6441 @@ +{ + "body": { + "homes": [ + { + "id": "aaaaaaaaaaabbbbbbbbbbccc", + "name": "A BIG HOME", + "altitude": 284, + "coordinates": [ + 26.234678, + 83.234678 + ], + "country": "FR", + "timezone": "Europe/Paris", + "rooms": [ + { + "id": "3707962039", + "name": "Cuisine", + "type": "kitchen", + "module_ids": [ + "98:76:54:32:10:00:00:03", + "98:76:54:32:10:00:00:05", + "98:76:54:32:10:00:00:06", + "98:76:54:32:10:00:00:07", + "98:76:54:32:10:00:00:09", + "98:76:54:32:10:00:00:28", + "98:76:54:32:10:00:00:37", + "98:76:54:32:10:00:00:38", + "98:76:54:32:10:00:00:40", + "98:76:54:32:10:00:00:50" + ] + }, + { + "id": "596817675", + "name": "Vestibule", + "type": "lobby", + "module_ids": [ + "98:76:54:32:10:00:00:01", + "98:76:54:32:10:00:00:02", + "98:76:54:32:10:00:00:08", + "98:76:54:32:10:00:00:13", + "98:76:54:32:10:00:00:14", + "98:76:54:32:10:00:00:15", + "98:76:54:32:10:00:00:16", + "98:76:54:32:10:00:00:27", + "98:76:54:32:10:00:00:29", + "98:76:54:32:10:00:00:32", + "98:76:54:32:10:00:00:36", + "98:76:54:32:10:00:00:39" + ] + }, + { + "id": "1462100035", + "name": "Salon", + "type": "livingroom", + "module_ids": [ + "98:76:54:32:10:00:00:04", + "98:76:54:32:10:00:00:24#1", + "98:76:54:32:10:00:00:34", + "98:76:54:32:10:00:00:52", + "98:76:54:32:10:00:00:60", + "98:76:54:32:10:00:00:63", + "98:76:54:32:10:00:00:66", + "98:76:54:32:10:00:00:73", + "98:76:54:32:10:00:00:75" + ] + }, + { + "id": "3435163850", + "name": "Chambre A", + "type": "bedroom", + "module_ids": [ + "98:76:54:32:10:00:00:26", + "98:76:54:32:10:00:00:51" + ] + }, + { + "id": "737850817", + "name": "Extérieur", + "type": "outdoor", + "module_ids": [ + "98:76:54:32:10:00:00:10", + "98:76:54:32:10:00:00:41", + "98:76:54:32:10:00:00:42", + "98:76:54:32:10:00:00:53", + "98:76:54:32:10:00:00:54", + "98:76:54:32:10:00:00:55", + "98:76:54:32:10:00:00:56" + ] + }, + { + "id": "842662884", + "name": "Bibliothèque", + "type": "home_office", + "module_ids": [ + "98:76:54:32:10:00:00:11", + "98:76:54:32:10:00:00:12", + "98:76:54:32:10:00:00:24#2", + "98:76:54:32:10:00:00:25" + ] + }, + { + "id": "3194154910", + "name": "Salle à manger", + "type": "dining_room", + "module_ids": [ + "98:76:54:32:10:00:00:30", + "98:76:54:32:10:00:00:31", + "98:76:54:32:10:00:00:33", + "98:76:54:32:10:00:00:72" + ] + }, + { + "id": "2370728183", + "name": "Atelier", + "type": "custom", + "module_ids": [ + "98:76:54:32:10:00:00:18", + "98:76:54:32:10:00:00:23" + ] + }, + { + "id": "2042969726", + "name": "Chambre B", + "type": "bedroom", + "module_ids": [ + "98:76:54:32:10:00:00:19", + "98:76:54:32:10:00:00:20", + "98:76:54:32:10:00:00:46" + ] + }, + { + "id": "2754296835", + "name": "Placard Technique", + "type": "electrical_cabinet", + "module_ids": [ + "aa:aa:aa:aa:aa:aa", + "98:76:54:32:10:00:00:22", + "98:76:54:32:10:00:00:48", + "98:76:54:32:10:00:00:59", + "98:76:54:32:10:00:00:67", + "98:76:54:32:10:00:00:68", + "98:76:54:32:10:00:00:69", + "98:76:54:32:10:00:00:77", + "98:76:54:32:10:00:00:78", + "98:76:54:32:10:00:00:79" + ] + }, + { + "id": "1662974901", + "name": "Dressing", + "type": "custom", + "module_ids": [ + "98:76:54:32:10:00:00:21", + "98:76:54:32:10:00:00:35" + ] + }, + { + "id": "873035982", + "name": "Chambre C", + "type": "bedroom", + "module_ids": [ + "98:76:54:32:10:00:00:17", + "98:76:54:32:10:00:00:43", + "98:76:54:32:10:00:00:76" + ] + }, + { + "id": "3795659199", + "name": "Chambre D", + "type": "bedroom", + "module_ids": [ + "98:76:54:32:10:00:00:57" + ] + }, + { + "id": "2102454491", + "name": "Buanderie", + "type": "custom", + "module_ids": [ + "98:76:54:32:10:00:00:45" + ] + }, + { + "id": "93888250", + "name": "Salle de bains Des Enfants", + "type": "bathroom", + "module_ids": [ + "98:76:54:32:10:00:00:44" + ] + }, + { + "id": "3497055021", + "name": "Chambre Brice", + "type": "bedroom", + "module_ids": [ + "98:76:54:32:10:00:00:47", + "98:76:54:32:10:00:00:74" + ] + }, + { + "id": "2061006239", + "name": "Pool house", + "type": "custom", + "module_ids": [ + "98:76:54:32:10:00:00:58", + "98:76:54:32:10:00:00:61", + "98:76:54:32:10:00:00:62", + "98:76:54:32:10:00:00:64", + "98:76:54:32:10:00:00:65", + "98:76:54:32:10:00:00:71" + ] + }, + { + "id": "927970817", + "name": "Salle de bains Des Parents", + "type": "bathroom", + "module_ids": [ + "98:76:54:32:10:00:00:49" + ] + }, + { + "id": "1641945290", + "name": "Salle de bains D’Arthur", + "type": "bathroom", + "module_ids": [ + "98:76:54:32:10:00:00:70" + ] + } + ], + "modules": [ + { + "id": "aa:aa:aa:aa:aa:aa", + "type": "NLG", + "name": "Legrand Gateway", + "setup_date": 1572624665, + "room_id": "2754296835", + "modules_bridged": [ + "98:76:54:32:10:00:00:01", + "98:76:54:32:10:00:00:02", + "98:76:54:32:10:00:00:03", + "98:76:54:32:10:00:00:04", + "98:76:54:32:10:00:00:05", + "98:76:54:32:10:00:00:06", + "98:76:54:32:10:00:00:07", + "98:76:54:32:10:00:00:08", + "98:76:54:32:10:00:00:09", + "98:76:54:32:10:00:00:10", + "98:76:54:32:10:00:00:11", + "98:76:54:32:10:00:00:12", + "98:76:54:32:10:00:00:13", + "98:76:54:32:10:00:00:14", + "98:76:54:32:10:00:00:15", + "98:76:54:32:10:00:00:16", + "98:76:54:32:10:00:00:17", + "98:76:54:32:10:00:00:18", + "98:76:54:32:10:00:00:19", + "98:76:54:32:10:00:00:20", + "98:76:54:32:10:00:00:21", + "98:76:54:32:10:00:00:22", + "98:76:54:32:10:00:00:23", + "98:76:54:32:10:00:00:24", + "98:76:54:32:10:00:00:24#1", + "98:76:54:32:10:00:00:24#2", + "98:76:54:32:10:00:00:25", + "98:76:54:32:10:00:00:26", + "98:76:54:32:10:00:00:27", + "98:76:54:32:10:00:00:28", + "98:76:54:32:10:00:00:29", + "98:76:54:32:10:00:00:30", + "98:76:54:32:10:00:00:31", + "98:76:54:32:10:00:00:32", + "98:76:54:32:10:00:00:33", + "98:76:54:32:10:00:00:34", + "98:76:54:32:10:00:00:35", + "98:76:54:32:10:00:00:36", + "98:76:54:32:10:00:00:37", + "98:76:54:32:10:00:00:38", + "98:76:54:32:10:00:00:39", + "98:76:54:32:10:00:00:40", + "98:76:54:32:10:00:00:41", + "98:76:54:32:10:00:00:42", + "98:76:54:32:10:00:00:43", + "98:76:54:32:10:00:00:44", + "98:76:54:32:10:00:00:45", + "98:76:54:32:10:00:00:46", + "98:76:54:32:10:00:00:47", + "98:76:54:32:10:00:00:48", + "98:76:54:32:10:00:00:49", + "98:76:54:32:10:00:00:50", + "98:76:54:32:10:00:00:51", + "98:76:54:32:10:00:00:52", + "98:76:54:32:10:00:00:53", + "98:76:54:32:10:00:00:54", + "98:76:54:32:10:00:00:55", + "98:76:54:32:10:00:00:03#1", + "98:76:54:32:10:00:00:03#2", + "98:76:54:32:10:00:00:07#1", + "98:76:54:32:10:00:00:07#2", + "98:76:54:32:10:00:00:08#1", + "98:76:54:32:10:00:00:08#2", + "98:76:54:32:10:00:00:28#1", + "98:76:54:32:10:00:00:28#2", + "98:76:54:32:10:00:00:29#1", + "98:76:54:32:10:00:00:29#2", + "98:76:54:32:10:00:00:30#1", + "98:76:54:32:10:00:00:30#2", + "98:76:54:32:10:00:00:50#1", + "98:76:54:32:10:00:00:50#2", + "98:76:54:32:10:00:00:56", + "98:76:54:32:10:00:00:57", + "98:76:54:32:10:00:00:58", + "98:76:54:32:10:00:00:59", + "98:76:54:32:10:00:00:60", + "98:76:54:32:10:00:00:61", + "98:76:54:32:10:00:00:62", + "98:76:54:32:10:00:00:63", + "98:76:54:32:10:00:00:63#1", + "98:76:54:32:10:00:00:63#2", + "98:76:54:32:10:00:00:64", + "98:76:54:32:10:00:00:64#1", + "98:76:54:32:10:00:00:64#2", + "98:76:54:32:10:00:00:65", + "98:76:54:32:10:00:00:65#1", + "98:76:54:32:10:00:00:65#2", + "98:76:54:32:10:00:00:66", + "98:76:54:32:10:00:00:66#1", + "98:76:54:32:10:00:00:66#2", + "98:76:54:32:10:00:00:67", + "98:76:54:32:10:00:00:68", + "98:76:54:32:10:00:00:69", + "98:76:54:32:10:00:00:70", + "98:76:54:32:10:00:00:71", + "98:76:54:32:10:00:00:72", + "98:76:54:32:10:00:00:73", + "98:76:54:32:10:00:00:74", + "98:76:54:32:10:00:00:75", + "98:76:54:32:10:00:00:76", + "98:76:54:32:10:00:00:77", + "98:76:54:32:10:00:00:78", + "98:76:54:32:10:00:00:79" + ] + }, + { + "id": "98:76:54:32:10:00:00:01", + "type": "NLP", + "name": "Buffet", + "setup_date": 1572624686, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "light" + }, + { + "id": "98:76:54:32:10:00:00:02", + "type": "NLT", + "name": "Commande entrée sortie principale", + "setup_date": 1572624686, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:03", + "type": "NLD", + "name": "Boutons Cuisine Haut", + "setup_date": 1572629067, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:04", + "type": "NLV", + "name": "volet", + "setup_date": 1572798965, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:05", + "type": "NLM", + "name": "Verrière", + "setup_date": 1574591975, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:06", + "type": "NLM", + "name": "ilot", + "setup_date": 1574591975, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:07", + "type": "NLD", + "name": "Bouton Cuisine milieu", + "setup_date": 1574592863, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:08", + "type": "NLD", + "name": "Entrée Bouton Portail et dehors", + "setup_date": 1574593140, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:09", + "type": "NLT", + "name": "Bouton pour exterieur porte fenetre", + "setup_date": 1605358560, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:10", + "type": "NLM", + "name": "Olivier", + "setup_date": 1605359274, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:11", + "type": "NLP", + "name": "Lampadaire", + "setup_date": 1605369621, + "room_id": "842662884", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "light" + }, + { + "id": "98:76:54:32:10:00:00:12", + "type": "NLT", + "name": "Bouton Bibliotheque", + "setup_date": 1607175439, + "room_id": "842662884", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:13", + "type": "NLF", + "name": "Couloir enfants", + "setup_date": 1612299365, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:14", + "type": "NLT", + "name": "Couloir enfants 2", + "setup_date": 1612299777, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:15", + "type": "NLT", + "name": "Couloir enfants 3", + "setup_date": 1612299852, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:16", + "type": "NLT", + "name": "Couloir enfants 1", + "setup_date": 1613565493, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:17", + "type": "NLF", + "name": "Lumière C", + "setup_date": 1617390843, + "room_id": "873035982", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:18", + "type": "NLM", + "name": "Néon", + "setup_date": 1643544945, + "room_id": "2370728183", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:19", + "type": "NLT", + "name": "Couloir A interrupteur", + "setup_date": 1643794135, + "room_id": "2042969726", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:20", + "type": "NLF", + "name": "Couloir A", + "setup_date": 1643794453, + "room_id": "2042969726", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:21", + "type": "NLPT", + "name": "Dressing", + "setup_date": 1643809582, + "room_id": "1662974901", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:22", + "type": "NLPM", + "name": "Onduleur Serveurs Mais Local Technique", + "setup_date": 1643911516, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "other" + }, + { + "id": "98:76:54:32:10:00:00:23", + "type": "NLT", + "name": "Interrupteur neon", + "setup_date": 1644008400, + "room_id": "2370728183", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:24", + "type": "NLIS", + "setup_date": 1645651106, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:24#1", + "type": "NLIS", + "name": "Niche", + "setup_date": 1645651106, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:24#2", + "type": "NLIS", + "name": "Escalier", + "setup_date": 1645651106, + "room_id": "842662884", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:25", + "type": "NLT", + "name": "Bouton Escalier", + "setup_date": 1645651356, + "room_id": "842662884", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:26", + "type": "NLPT", + "name": "Lumière Chambre E", + "setup_date": 1645657974, + "room_id": "3435163850", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:27", + "type": "NLPT", + "name": "Entrée", + "setup_date": 1645658118, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:28", + "type": "NLD", + "name": "Bouton cuisine bas", + "setup_date": 1645659939, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:29", + "type": "NLD", + "name": "Bouton double entrée porte", + "setup_date": 1645660346, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:30", + "type": "NLD", + "name": "Bouton double salle à manger", + "setup_date": 1645660684, + "room_id": "3194154910", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:31", + "type": "NLF", + "name": "Placard", + "setup_date": 1645662093, + "room_id": "3194154910", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:32", + "type": "NLT", + "name": "Bouton plafond entrée couloir", + "setup_date": 1645662629, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:33", + "type": "NLPT", + "name": "Table", + "setup_date": 1645889017, + "room_id": "3194154910", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:34", + "type": "NLPT", + "name": "Baie Vitrée", + "setup_date": 1645889069, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:35", + "type": "NLC", + "name": "Radiateur Dressing", + "setup_date": 1645894862, + "room_id": "1662974901", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:36", + "type": "NLC", + "name": "Radiateur Entrée", + "setup_date": 1645899253, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:37", + "type": "NLC", + "name": "Radiateur Cuisine Dressing", + "setup_date": 1645902157, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:38", + "type": "NLC", + "name": "Radiateur Cuisine Entrée", + "setup_date": 1645902199, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:39", + "type": "NLT", + "name": "Commande sans fil couloir enfant pour entrée", + "setup_date": 1646074736, + "room_id": "596817675", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:40", + "type": "NLPT", + "name": "Couloir Parents", + "setup_date": 1646568523, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:41", + "type": "NLPT", + "name": "Jardin", + "setup_date": 1646568567, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:42", + "type": "NLPT", + "name": "Facade", + "setup_date": 1646568594, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:43", + "type": "NLC", + "name": "Radiateur FF", + "setup_date": 1646581781, + "room_id": "873035982", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:44", + "type": "NLC", + "name": "Radiateur Salle De Bain Enfants", + "setup_date": 1646828219, + "room_id": "93888250", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:45", + "type": "NLC", + "name": "Radiateur Buanderie", + "setup_date": 1646828251, + "room_id": "2102454491", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:46", + "type": "NLC", + "name": "Radiateur A", + "setup_date": 1646828278, + "room_id": "2042969726", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:47", + "type": "NLC", + "name": "Radiateur B", + "setup_date": 1646828308, + "room_id": "3497055021", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:48", + "type": "NLM", + "name": "Cam Porte", + "setup_date": 1653579677, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:49", + "type": "NLC", + "name": "Radiateur Sèche Serviette E", + "setup_date": 1667205824, + "room_id": "927970817", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:50", + "type": "NLAO", + "name": "Porte vitree sans pile", + "setup_date": 1668001531, + "room_id": "3707962039", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:51", + "type": "NLC", + "name": "Radiateur E", + "setup_date": 1668339519, + "room_id": "3435163850", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:52", + "type": "NLM", + "name": "Meurtrières", + "setup_date": 1671560972, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:53", + "type": "NLPT", + "name": "Parking", + "setup_date": 1672948768, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:54", + "type": "NLM", + "name": "Barbecue", + "setup_date": 1672948768, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:55", + "type": "NLAO", + "name": "Bouton sans pile cuisine ete", + "setup_date": 1672949735, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:03#1", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:03#2", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:07#1", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:07#2", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:08#1", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:08#2", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:28#1", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:28#2", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:29#1", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:29#2", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:30#1", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:30#2", + "type": "NLD", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:50#1", + "type": "NLAO", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:50#2", + "type": "NLAO", + "setup_date": 1673873611, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:56", + "type": "NLM", + "name": "Piscine", + "setup_date": 1691244631, + "room_id": "737850817", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:57", + "type": "NLC", + "name": "Radiateur DD", + "setup_date": 1692093769, + "room_id": "3795659199", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:58", + "type": "NLM", + "name": "Salle de bain", + "setup_date": 1692094781, + "room_id": "2061006239", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:59", + "type": "NLP", + "name": "Prise Pool House Relais Zigbee", + "setup_date": 1692095384, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "router" + }, + { + "id": "98:76:54:32:10:00:00:60", + "type": "NLPT", + "name": "Plafonnier", + "setup_date": 1692095856, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:61", + "type": "NLPT", + "name": "Terrasse Piscine", + "setup_date": 1693848343, + "room_id": "2061006239", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:62", + "type": "NLPT", + "name": "Lumière", + "setup_date": 1693848357, + "room_id": "2061006239", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:63", + "type": "NLD", + "name": "Salon Commande Double Haut", + "setup_date": 1694336106, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:63#1", + "type": "NLD", + "setup_date": 1694336106, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:63#2", + "type": "NLD", + "setup_date": 1694336106, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:64", + "type": "NLD", + "name": "Commande Pool House Gauche", + "setup_date": 1694336110, + "room_id": "2061006239", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:64#1", + "type": "NLD", + "setup_date": 1694336110, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:64#2", + "type": "NLD", + "setup_date": 1694336110, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:65", + "type": "NLD", + "name": "Commande Pool House Droite", + "setup_date": 1694336143, + "room_id": "2061006239", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:65#1", + "type": "NLD", + "setup_date": 1694336143, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:65#2", + "type": "NLD", + "setup_date": 1694336143, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:66", + "type": "NLD", + "name": "Commande Double Bas", + "setup_date": 1698577707, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:66#1", + "type": "NLD", + "setup_date": 1698577707, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:66#2", + "type": "NLD", + "setup_date": 1698577707, + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:67", + "type": "NLPO", + "name": "Cumulus Parents", + "setup_date": 1699128857, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "water_heater" + }, + { + "id": "98:76:54:32:10:00:00:68", + "type": "NLPO", + "name": "Cumulus DD", + "setup_date": 1699132798, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "water_heater" + }, + { + "id": "98:76:54:32:10:00:00:69", + "type": "NLPC", + "name": "Compteur Filtration Local Technique", + "setup_date": 1711797163, + "room_id": "2754296835", + "bridge": "00:04:74:22:52:38" + }, + { + "id": "98:76:54:32:10:00:00:70", + "type": "NLC", + "name": "Radiateur Sèche Serviette A", + "setup_date": 1702133314, + "room_id": "1641945290", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator" + }, + { + "id": "98:76:54:32:10:00:00:71", + "type": "NLPO", + "name": "Cumulus Pool House", + "setup_date": 1702135239, + "room_id": "2061006239", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "water_heater" + }, + { + "id": "98:76:54:32:10:00:00:72", + "type": "NLC", + "name": "Radiateur Sol Salle À Manger", + "setup_date": 1707332251, + "room_id": "3194154910", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator_without_pilot_wire" + }, + { + "id": "98:76:54:32:10:00:00:73", + "type": "NLC", + "name": "Radiateur Sol Salon", + "setup_date": 1707332251, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "radiator_without_pilot_wire" + }, + { + "id": "98:76:54:32:10:00:00:74", + "type": "NLP", + "name": "Setup PC B", + "setup_date": 1707332620, + "room_id": "3497055021", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "router" + }, + { + "id": "98:76:54:32:10:00:00:75", + "type": "NLPM", + "name": "Setup TV Apple TV Switch Salon", + "setup_date": 1707333771, + "room_id": "1462100035", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "multimedia" + }, + { + "id": "98:76:54:32:10:00:00:76", + "type": "NLP", + "name": "Mesure PC Switch C", + "setup_date": 1707335636, + "room_id": "873035982", + "bridge": "aa:aa:aa:aa:aa:aa", + "appliance_type": "router" + }, + { + "id": "98:76:54:32:10:00:00:77", + "type": "NLPC", + "name": "Compteur Plaque Sèche-Linge PC Buanderie Plan Cuisine", + "setup_date": 1707339526, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:78", + "type": "NLPC", + "name": "Compteur Congel Micro-onde Frigo PC WC", + "setup_date": 1708185348, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa" + }, + { + "id": "98:76:54:32:10:00:00:79", + "type": "NLPC", + "name": "Compteur Lave-linge Four Lave Lave-Vaisselle PC TV Chambre ", + "setup_date": 1708185369, + "room_id": "2754296835", + "bridge": "aa:aa:aa:aa:aa:aa" + } + ], + "temperature_control_mode": "heating", + "therm_mode": "schedule", + "therm_setpoint_default_duration": 180, + "schedules": [ + { + "timetable": [ + { + "zone_id": 1, + "m_offset": 0 + }, + { + "zone_id": 0, + "m_offset": 360 + }, + { + "zone_id": 1, + "m_offset": 510 + }, + { + "zone_id": 5, + "m_offset": 960 + }, + { + "zone_id": 1, + "m_offset": 1200 + }, + { + "zone_id": 2, + "m_offset": 1260 + }, + { + "zone_id": 1, + "m_offset": 1380 + }, + { + "zone_id": 0, + "m_offset": 1800 + }, + { + "zone_id": 1, + "m_offset": 1950 + }, + { + "zone_id": 5, + "m_offset": 2400 + }, + { + "zone_id": 1, + "m_offset": 2640 + }, + { + "zone_id": 2, + "m_offset": 2700 + }, + { + "zone_id": 1, + "m_offset": 2820 + }, + { + "zone_id": 0, + "m_offset": 3240 + }, + { + "zone_id": 1, + "m_offset": 3390 + }, + { + "zone_id": 5, + "m_offset": 3840 + }, + { + "zone_id": 1, + "m_offset": 4080 + }, + { + "zone_id": 2, + "m_offset": 4140 + }, + { + "zone_id": 1, + "m_offset": 4260 + }, + { + "zone_id": 0, + "m_offset": 4680 + }, + { + "zone_id": 1, + "m_offset": 4830 + }, + { + "zone_id": 5, + "m_offset": 5280 + }, + { + "zone_id": 1, + "m_offset": 5520 + }, + { + "zone_id": 2, + "m_offset": 5580 + }, + { + "zone_id": 1, + "m_offset": 5700 + }, + { + "zone_id": 0, + "m_offset": 6120 + }, + { + "zone_id": 1, + "m_offset": 6270 + }, + { + "zone_id": 5, + "m_offset": 6720 + }, + { + "zone_id": 1, + "m_offset": 6960 + }, + { + "zone_id": 2, + "m_offset": 7020 + }, + { + "zone_id": 1, + "m_offset": 7140 + }, + { + "zone_id": 0, + "m_offset": 7560 + }, + { + "zone_id": 1, + "m_offset": 7710 + }, + { + "zone_id": 5, + "m_offset": 8160 + }, + { + "zone_id": 1, + "m_offset": 8400 + }, + { + "zone_id": 2, + "m_offset": 8460 + }, + { + "zone_id": 1, + "m_offset": 8580 + }, + { + "zone_id": 0, + "m_offset": 9000 + }, + { + "zone_id": 1, + "m_offset": 9150 + }, + { + "zone_id": 5, + "m_offset": 9600 + }, + { + "zone_id": 1, + "m_offset": 9840 + }, + { + "zone_id": 2, + "m_offset": 9900 + }, + { + "zone_id": 1, + "m_offset": 10020 + } + ], + "zones": [ + { + "name": "Comfort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Éco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Nuit", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Confort sauf chambres parents", + "id": 5, + "type": 4, + "rooms_temp": [ + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Chambre parents only", + "id": 2, + "type": 4, + "rooms_temp": [ + { + "room_id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + } + ], + "name": "Planning Hiver", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "61fa621cdd99943657260882", + "type": "therm", + "selected": true + }, + { + "timetable": [ + { + "zone_id": 2, + "m_offset": 0 + } + ], + "zones": [ + { + "name": "Comfort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Éco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Nuit", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Off", + "id": 2, + "type": 4, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + } + ], + "name": "Planning ete", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "625a76ceec2cce72075ac55a", + "type": "therm" + }, + { + "timetable": [ + { + "zone_id": 0, + "m_offset": 0 + } + ], + "zones": [ + { + "name": "Comfort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Night", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Eco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + } + ], + "name": "Full", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "63a44ba0735ffc27410f2331", + "type": "therm" + }, + { + "timetable": [ + { + "zone_id": 4, + "m_offset": 0 + }, + { + "zone_id": 0, + "m_offset": 300 + }, + { + "zone_id": 4, + "m_offset": 420 + }, + { + "zone_id": 0, + "m_offset": 855 + }, + { + "zone_id": 4, + "m_offset": 1140 + }, + { + "zone_id": 0, + "m_offset": 1740 + }, + { + "zone_id": 4, + "m_offset": 1860 + }, + { + "zone_id": 0, + "m_offset": 2295 + }, + { + "zone_id": 4, + "m_offset": 2580 + }, + { + "zone_id": 0, + "m_offset": 3180 + }, + { + "zone_id": 4, + "m_offset": 3300 + }, + { + "zone_id": 0, + "m_offset": 3735 + }, + { + "zone_id": 4, + "m_offset": 4020 + }, + { + "zone_id": 0, + "m_offset": 4620 + }, + { + "zone_id": 4, + "m_offset": 4740 + }, + { + "zone_id": 0, + "m_offset": 5175 + }, + { + "zone_id": 4, + "m_offset": 5460 + }, + { + "zone_id": 0, + "m_offset": 6060 + }, + { + "zone_id": 4, + "m_offset": 6180 + }, + { + "zone_id": 0, + "m_offset": 6615 + }, + { + "zone_id": 4, + "m_offset": 6900 + }, + { + "zone_id": 0, + "m_offset": 7500 + }, + { + "zone_id": 4, + "m_offset": 7620 + }, + { + "zone_id": 0, + "m_offset": 8055 + }, + { + "zone_id": 4, + "m_offset": 8340 + }, + { + "zone_id": 0, + "m_offset": 8940 + }, + { + "zone_id": 4, + "m_offset": 9060 + }, + { + "zone_id": 0, + "m_offset": 9495 + }, + { + "zone_id": 4, + "m_offset": 9780 + } + ], + "zones": [ + { + "name": "Comfort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Éco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Nuit", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + } + ], + "name": "Planning Hiver frileux", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "63c5b63b766611525b0b1e4d", + "type": "therm" + }, + { + "timetable": [ + { + "zone_id": 1, + "m_offset": 0 + }, + { + "zone_id": 0, + "m_offset": 300 + }, + { + "zone_id": 4, + "m_offset": 420 + }, + { + "zone_id": 0, + "m_offset": 1020 + }, + { + "zone_id": 1, + "m_offset": 1140 + }, + { + "zone_id": 0, + "m_offset": 1740 + }, + { + "zone_id": 4, + "m_offset": 1860 + }, + { + "zone_id": 0, + "m_offset": 2460 + }, + { + "zone_id": 1, + "m_offset": 2580 + }, + { + "zone_id": 0, + "m_offset": 3180 + }, + { + "zone_id": 4, + "m_offset": 3300 + }, + { + "zone_id": 0, + "m_offset": 3900 + }, + { + "zone_id": 1, + "m_offset": 4020 + }, + { + "zone_id": 0, + "m_offset": 4620 + }, + { + "zone_id": 4, + "m_offset": 4740 + }, + { + "zone_id": 0, + "m_offset": 5340 + }, + { + "zone_id": 1, + "m_offset": 5460 + }, + { + "zone_id": 0, + "m_offset": 6060 + }, + { + "zone_id": 4, + "m_offset": 6180 + }, + { + "zone_id": 0, + "m_offset": 6780 + }, + { + "zone_id": 1, + "m_offset": 6900 + }, + { + "zone_id": 0, + "m_offset": 7560 + }, + { + "zone_id": 4, + "m_offset": 7680 + }, + { + "zone_id": 0, + "m_offset": 8220 + }, + { + "zone_id": 1, + "m_offset": 8340 + }, + { + "zone_id": 0, + "m_offset": 9000 + }, + { + "zone_id": 4, + "m_offset": 9120 + }, + { + "zone_id": 0, + "m_offset": 9660 + }, + { + "zone_id": 1, + "m_offset": 9780 + } + ], + "zones": [ + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Nuit", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Confort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Éco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + } + ], + "name": "Chambres et SDB", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "6413ac548decf9f28b0efc4e", + "type": "therm" + }, + { + "timetable": [ + { + "zone_id": 5, + "m_offset": 0 + }, + { + "zone_id": 2, + "m_offset": 360 + }, + { + "zone_id": 5, + "m_offset": 450 + }, + { + "zone_id": 2, + "m_offset": 1020 + }, + { + "zone_id": 5, + "m_offset": 1080 + }, + { + "zone_id": 2, + "m_offset": 1800 + }, + { + "zone_id": 5, + "m_offset": 1890 + }, + { + "zone_id": 2, + "m_offset": 2460 + }, + { + "zone_id": 5, + "m_offset": 2520 + }, + { + "zone_id": 2, + "m_offset": 3240 + }, + { + "zone_id": 5, + "m_offset": 3330 + }, + { + "zone_id": 2, + "m_offset": 3900 + }, + { + "zone_id": 5, + "m_offset": 3960 + }, + { + "zone_id": 2, + "m_offset": 4680 + }, + { + "zone_id": 5, + "m_offset": 4770 + }, + { + "zone_id": 2, + "m_offset": 5340 + }, + { + "zone_id": 5, + "m_offset": 5400 + }, + { + "zone_id": 2, + "m_offset": 6120 + }, + { + "zone_id": 5, + "m_offset": 6210 + }, + { + "zone_id": 2, + "m_offset": 6780 + }, + { + "zone_id": 5, + "m_offset": 6840 + }, + { + "zone_id": 2, + "m_offset": 7680 + }, + { + "zone_id": 5, + "m_offset": 7740 + }, + { + "zone_id": 2, + "m_offset": 8220 + }, + { + "zone_id": 5, + "m_offset": 8280 + }, + { + "zone_id": 2, + "m_offset": 9120 + }, + { + "zone_id": 5, + "m_offset": 9180 + }, + { + "zone_id": 2, + "m_offset": 9660 + }, + { + "zone_id": 5, + "m_offset": 9720 + } + ], + "zones": [ + { + "name": "Comfort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Night", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Eco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "away" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "away" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "927970817", + "therm_setpoint_fp": "away" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "away" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "SDB seulement", + "id": 2, + "type": 4, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Tout Off", + "id": 5, + "type": 4, + "rooms_temp": [ + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Chambres Confort and All Off", + "id": 6, + "type": 4, + "rooms_temp": [ + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Chambres Eco and all Off", + "id": 7, + "type": 4, + "rooms_temp": [ + { + "room_id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "1662974901", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3707962039", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "comfort" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Chambres Eco SDB Confort All OFF", + "id": 8, + "type": 4, + "rooms_temp": [ + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "away" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "away" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "away" + }, + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "away" + }, + { + "id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "away" + }, + { + "id": "93888250", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "927970817", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + }, + { + "name": "Chambres & SDB Confort All OFF", + "id": 9, + "type": 4, + "rooms_temp": [ + { + "room_id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "room_id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ], + "modules": [], + "rooms": [ + { + "id": "1662974901", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "2042969726", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3435163850", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3497055021", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3707962039", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "3795659199", + "therm_setpoint_fp": "comfort" + }, + { + "id": "596817675", + "therm_setpoint_fp": "frost_guard" + }, + { + "id": "873035982", + "therm_setpoint_fp": "comfort" + }, + { + "id": "93888250", + "therm_setpoint_fp": "comfort" + }, + { + "id": "927970817", + "therm_setpoint_fp": "comfort" + }, + { + "id": "1641945290", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2102454491", + "therm_setpoint_fp": "frost_guard" + } + ] + } + ], + "name": "SDM seulement", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "65428fdc7349fc4e49034381", + "type": "therm" + }, + { + "timetable": [ + { + "zone_id": 1, + "m_offset": 300 + }, + { + "zone_id": 3, + "m_offset": 540 + }, + { + "zone_id": 2, + "m_offset": 960 + }, + { + "zone_id": 0, + "m_offset": 1020 + }, + { + "zone_id": 1, + "m_offset": 1740 + }, + { + "zone_id": 3, + "m_offset": 1980 + }, + { + "zone_id": 2, + "m_offset": 2400 + }, + { + "zone_id": 0, + "m_offset": 2460 + }, + { + "zone_id": 1, + "m_offset": 3180 + }, + { + "zone_id": 3, + "m_offset": 3420 + }, + { + "zone_id": 2, + "m_offset": 3840 + }, + { + "zone_id": 0, + "m_offset": 3900 + }, + { + "zone_id": 1, + "m_offset": 4620 + }, + { + "zone_id": 3, + "m_offset": 4860 + }, + { + "zone_id": 2, + "m_offset": 5280 + }, + { + "zone_id": 0, + "m_offset": 5340 + }, + { + "zone_id": 1, + "m_offset": 6060 + }, + { + "zone_id": 3, + "m_offset": 6300 + }, + { + "zone_id": 2, + "m_offset": 6720 + }, + { + "zone_id": 0, + "m_offset": 6780 + }, + { + "zone_id": 1, + "m_offset": 7500 + }, + { + "zone_id": 3, + "m_offset": 7740 + }, + { + "zone_id": 2, + "m_offset": 8160 + }, + { + "zone_id": 0, + "m_offset": 8220 + }, + { + "zone_id": 1, + "m_offset": 8940 + }, + { + "zone_id": 3, + "m_offset": 9180 + }, + { + "zone_id": 2, + "m_offset": 9600 + }, + { + "zone_id": 0, + "m_offset": 9660 + } + ], + "zones": [ + { + "id": 0, + "modules": [ + { + "id": "98:76:54:32:10:00:00:67", + "bridge": "aa:aa:aa:aa:aa:aa", + "on": false + } + ] + }, + { + "id": 1, + "modules": [ + { + "id": "98:76:54:32:10:00:00:67", + "bridge": "aa:aa:aa:aa:aa:aa", + "on": true + } + ] + }, + { + "id": 2, + "modules": [ + { + "id": "98:76:54:32:10:00:00:67", + "bridge": "aa:aa:aa:aa:aa:aa", + "on": true + } + ] + }, + { + "id": 3, + "modules": [ + { + "id": "98:76:54:32:10:00:00:67", + "bridge": "aa:aa:aa:aa:aa:aa", + "on": false + } + ] + } + ], + "name": "Planning d'actions", + "default": false, + "timetable_sunrise": [], + "timetable_sunset": [], + "id": "64fa4a1266404bbb130f4b71", + "type": "event", + "selected": true + }, + { + "timetable": [], + "zones": [], + "name": "Hiver", + "default": false, + "timetable_sunrise": [], + "timetable_sunset": [], + "id": "65c3f82f61e0a3ec5401640f", + "type": "event" + }, + { + "timetable": [ + { + "zone_id": 0, + "m_offset": 0 + }, + { + "zone_id": 1, + "m_offset": 130 + }, + { + "zone_id": 0, + "m_offset": 430 + }, + { + "zone_id": 1, + "m_offset": 850 + }, + { + "zone_id": 0, + "m_offset": 1030 + }, + { + "zone_id": 1, + "m_offset": 1570 + }, + { + "zone_id": 0, + "m_offset": 1870 + }, + { + "zone_id": 1, + "m_offset": 2290 + }, + { + "zone_id": 0, + "m_offset": 2470 + }, + { + "zone_id": 1, + "m_offset": 3010 + }, + { + "zone_id": 0, + "m_offset": 3310 + }, + { + "zone_id": 1, + "m_offset": 3730 + }, + { + "zone_id": 0, + "m_offset": 3910 + }, + { + "zone_id": 1, + "m_offset": 4450 + }, + { + "zone_id": 0, + "m_offset": 4750 + }, + { + "zone_id": 1, + "m_offset": 5170 + }, + { + "zone_id": 0, + "m_offset": 5350 + }, + { + "zone_id": 1, + "m_offset": 5890 + }, + { + "zone_id": 0, + "m_offset": 6190 + }, + { + "zone_id": 1, + "m_offset": 6610 + }, + { + "zone_id": 0, + "m_offset": 6790 + }, + { + "zone_id": 1, + "m_offset": 7330 + }, + { + "zone_id": 0, + "m_offset": 7630 + }, + { + "zone_id": 1, + "m_offset": 8050 + }, + { + "zone_id": 0, + "m_offset": 8230 + }, + { + "zone_id": 1, + "m_offset": 8770 + }, + { + "zone_id": 0, + "m_offset": 9070 + }, + { + "zone_id": 1, + "m_offset": 9490 + }, + { + "zone_id": 0, + "m_offset": 9670 + } + ], + "zones": [ + { + "id": 0, + "price": 0.27, + "price_type": "peak" + }, + { + "id": 1, + "price": 0.2068, + "price_type": "off_peak" + } + ], + "name": "electricity", + "default": false, + "tariff": "edf_tarif_bleu", + "tariff_option": "peak_and_off_peak", + "power_threshold": 36, + "contract_power_unit": "kW", + "id": "60ce3d057a24d640444c4f1c", + "type": "electricity", + "selected": true + } + ] + }, + { + "id": "eeeeeeeeeffffffffffaaaaa", + "name": "A SECOND HOME", + "altitude": 200, + "coordinates": [ + 34.345576, + 89.667112 + ], + "country": "FR", + "timezone": "Europe/Paris", + "rooms": [ + { + "id": "1468717414", + "name": "Cave", + "type": "garage", + "module_ids": [ + "12:34:56:78:90:00:00:09", + "12:34:56:78:90:00:00:20", + "12:34:56:78:90:00:00:33" + ] + }, + { + "id": "738709350", + "name": "Salon", + "type": "livingroom", + "module_ids": [ + "bb:bb:bb:bb:bb:bb", + "12:34:56:78:90:00:00:01", + "12:34:56:78:90:00:00:02", + "12:34:56:78:90:00:00:03", + "12:34:56:78:90:00:00:04", + "12:34:56:78:90:00:00:05", + "12:34:56:78:90:00:00:06", + "12:34:56:78:90:00:00:07", + "12:34:56:78:90:00:00:08", + "12:34:56:78:90:00:00:10", + "12:34:56:78:90:00:00:23", + "12:34:56:78:90:00:00:24", + "12:34:56:78:90:00:00:29", + "12:34:56:78:90:00:00:30" + ] + }, + { + "id": "3098890768", + "name": "Entrée", + "type": "lobby", + "module_ids": [ + "12:34:56:78:90:00:00:11" + ] + }, + { + "id": "70754041", + "name": "Salle de bains", + "type": "bathroom", + "module_ids": [ + "12:34:56:78:90:00:00:12", + "12:34:56:78:90:00:00:26" + ] + }, + { + "id": "1761556353", + "name": "Nouveaux toilettes", + "type": "toilets", + "module_ids": [ + "12:34:56:78:90:00:00:13" + ] + }, + { + "id": "968846272", + "name": "Anciens Toilettes", + "type": "toilets", + "module_ids": [ + "12:34:56:78:90:00:00:14" + ] + }, + { + "id": "4008422910", + "name": "Palier", + "type": "corridor", + "module_ids": [ + "12:34:56:78:90:00:00:15", + "12:34:56:78:90:00:00:18", + "12:34:56:78:90:00:00:31" + ] + }, + { + "id": "2640531479", + "name": "Chambre parents", + "type": "bedroom", + "module_ids": [ + "12:34:56:78:90:00:00:16", + "12:34:56:78:90:00:00:27" + ] + }, + { + "id": "2667868658", + "name": "Chambre Older", + "type": "bedroom", + "module_ids": [ + "12:34:56:78:90:00:00:17", + "12:34:56:78:90:00:00:22" + ] + }, + { + "id": "3783425301", + "name": "Chambre Enfants", + "type": "bedroom", + "module_ids": [ + "12:34:56:78:90:00:00:19", + "12:34:56:78:90:00:00:28" + ] + }, + { + "id": "68319658", + "name": "Chambre Old", + "type": "bedroom", + "module_ids": [ + "12:34:56:78:90:00:00:25" + ] + }, + { + "id": "1156588698", + "name": "Jardin", + "type": "outdoor", + "module_ids": [ + "12:34:56:78:90:00:00:21" + ] + }, + { + "id": "1229033409", + "name": "Grenier", + "type": "custom", + "module_ids": [ + "12:34:56:78:90:00:00:32", + "12:34:56:78:90:00:00:34" + ] + } + ], + "modules": [ + { + "id": "bb:bb:bb:bb:bb:bb", + "type": "NLG", + "name": "Legrand Gateway", + "setup_date": 1692558574, + "room_id": "738709350", + "modules_bridged": [ + "12:34:56:78:90:00:00:01", + "12:34:56:78:90:00:00:02", + "12:34:56:78:90:00:00:03", + "12:34:56:78:90:00:00:04", + "12:34:56:78:90:00:00:05", + "12:34:56:78:90:00:00:06", + "12:34:56:78:90:00:00:07", + "12:34:56:78:90:00:00:08", + "12:34:56:78:90:00:00:09", + "12:34:56:78:90:00:00:10", + "12:34:56:78:90:00:00:11", + "12:34:56:78:90:00:00:12", + "12:34:56:78:90:00:00:13", + "12:34:56:78:90:00:00:14", + "12:34:56:78:90:00:00:15", + "12:34:56:78:90:00:00:16", + "12:34:56:78:90:00:00:17", + "12:34:56:78:90:00:00:18", + "12:34:56:78:90:00:00:19", + "12:34:56:78:90:00:00:20", + "12:34:56:78:90:00:00:21", + "12:34:56:78:90:00:00:22", + "12:34:56:78:90:00:00:23", + "12:34:56:78:90:00:00:24", + "12:34:56:78:90:00:00:25", + "12:34:56:78:90:00:00:26", + "12:34:56:78:90:00:00:27", + "12:34:56:78:90:00:00:28", + "12:34:56:78:90:00:00:29", + "12:34:56:78:90:00:00:30", + "12:34:56:78:90:00:00:31", + "12:34:56:78:90:00:00:32", + "12:34:56:78:90:00:00:33", + "12:34:56:78:90:00:00:34" + ] + }, + { + "id": "12:34:56:78:90:00:00:01", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 1", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:02", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 2", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:03", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 3", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:04", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 4", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:05", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 5", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:06", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 6", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:07", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 7", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:08", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 8", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:09", + "type": "NLPO", + "name": "OL Cumulus", + "setup_date": 1692558628, + "room_id": "1468717414", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "water_heater" + }, + { + "id": "12:34:56:78:90:00:00:10", + "type": "NLPT", + "name": "OL Lumière Cuisine", + "setup_date": 1692558628, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:11", + "type": "NLPT", + "name": "OL Escalier", + "setup_date": 1692558628, + "room_id": "3098890768", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:12", + "type": "NLPT", + "name": "OL Éclairage Salle de bain", + "setup_date": 1692558628, + "room_id": "70754041", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:13", + "type": "NLPT", + "name": "OL Lumière nouveaux toilettes", + "setup_date": 1692558628, + "room_id": "1761556353", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:14", + "type": "NLPT", + "name": "OL Lumière anciens toilettes", + "setup_date": 1692558628, + "room_id": "968846272", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:15", + "type": "NLPT", + "name": "OL Lumière palier salle de bain", + "setup_date": 1692558628, + "room_id": "4008422910", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:16", + "type": "NLPT", + "name": "OL Lumière chambre A", + "setup_date": 1692558628, + "room_id": "2640531479", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:17", + "type": "NLPT", + "name": "OL Lumière Chambre Older", + "setup_date": 1692558628, + "room_id": "2667868658", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:18", + "type": "NLPT", + "name": "OL Lumière Palier", + "setup_date": 1692558628, + "room_id": "4008422910", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:19", + "type": "NLPT", + "name": "OL Lumière enfants", + "setup_date": 1692558628, + "room_id": "3783425301", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:20", + "type": "NLM", + "name": "OL Lumière Cave", + "setup_date": 1692643741, + "room_id": "1468717414", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:21", + "type": "NLM", + "name": "OL Lumière Jardin", + "setup_date": 1692643763, + "room_id": "1156588698", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:22", + "type": "NLC", + "name": "OL Radiateur Chambre Older", + "setup_date": 1692644489, + "room_id": "2667868658", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:23", + "type": "NLC", + "name": "OL Radiateur Salon Fenêtre", + "setup_date": 1692644493, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:24", + "type": "NLC", + "name": "OL Radiateur Salon Porte", + "setup_date": 1692644497, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:25", + "type": "NLC", + "name": "OL Radiateur Chambre Old", + "setup_date": 1692644501, + "room_id": "68319658", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:26", + "type": "NLC", + "name": "OL Radiateur Serviette", + "setup_date": 1692644506, + "room_id": "70754041", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:27", + "type": "NLC", + "name": "OL Radiateur Chambre A", + "setup_date": 1692644509, + "room_id": "2640531479", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:28", + "type": "NLC", + "name": "OL Radiateur Chambre E", + "setup_date": 1693159267, + "room_id": "3783425301", + "bridge": "bb:bb:bb:bb:bb:bb", + "appliance_type": "radiator" + }, + { + "id": "12:34:56:78:90:00:00:29", + "type": "NLPT", + "name": "OL Salle à manger", + "setup_date": 1696921179, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:30", + "type": "NLPT", + "name": "OL Plan de travail", + "setup_date": 1696921199, + "room_id": "738709350", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:31", + "type": "NLAO", + "name": "Commande On/Off (Sans-Fil, Sans Pile) 9", + "setup_date": 1696922170, + "room_id": "4008422910", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:32", + "type": "NLPT", + "name": "OL Lumière Grenier", + "setup_date": 1696949709, + "room_id": "1229033409", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:33", + "type": "NLAO", + "name": "Commande Cave", + "setup_date": 1696949890, + "room_id": "1468717414", + "bridge": "bb:bb:bb:bb:bb:bb" + }, + { + "id": "12:34:56:78:90:00:00:34", + "type": "NLAO", + "name": "Commande Grenier", + "setup_date": 1696951661, + "room_id": "1229033409", + "bridge": "bb:bb:bb:bb:bb:bb" + } + ], + "temperature_control_mode": "heating", + "therm_mode": "hg", + "therm_setpoint_default_duration": 180, + "schedules": [ + { + "timetable": [ + { + "zone_id": 1, + "m_offset": 0 + }, + { + "zone_id": 0, + "m_offset": 420 + }, + { + "zone_id": 4, + "m_offset": 480 + }, + { + "zone_id": 0, + "m_offset": 1140 + }, + { + "zone_id": 1, + "m_offset": 1320 + }, + { + "zone_id": 0, + "m_offset": 1860 + }, + { + "zone_id": 4, + "m_offset": 1920 + }, + { + "zone_id": 0, + "m_offset": 2580 + }, + { + "zone_id": 1, + "m_offset": 2760 + }, + { + "zone_id": 0, + "m_offset": 3300 + }, + { + "zone_id": 4, + "m_offset": 3360 + }, + { + "zone_id": 0, + "m_offset": 4020 + }, + { + "zone_id": 1, + "m_offset": 4200 + }, + { + "zone_id": 0, + "m_offset": 4740 + }, + { + "zone_id": 4, + "m_offset": 4800 + }, + { + "zone_id": 0, + "m_offset": 5460 + }, + { + "zone_id": 1, + "m_offset": 5640 + }, + { + "zone_id": 0, + "m_offset": 6180 + }, + { + "zone_id": 4, + "m_offset": 6240 + }, + { + "zone_id": 0, + "m_offset": 6900 + }, + { + "zone_id": 1, + "m_offset": 7080 + }, + { + "zone_id": 0, + "m_offset": 7620 + }, + { + "zone_id": 4, + "m_offset": 7800 + }, + { + "zone_id": 0, + "m_offset": 8220 + }, + { + "zone_id": 1, + "m_offset": 8520 + }, + { + "zone_id": 0, + "m_offset": 9060 + }, + { + "zone_id": 4, + "m_offset": 9240 + }, + { + "zone_id": 0, + "m_offset": 9660 + }, + { + "zone_id": 1, + "m_offset": 9960 + } + ], + "zones": [ + { + "name": "Comfort", + "id": 0, + "type": 0, + "rooms_temp": [ + { + "room_id": "738709350", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "70754041", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2640531479", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2667868658", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3783425301", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "68319658", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "738709350", + "therm_setpoint_fp": "comfort" + }, + { + "id": "70754041", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2640531479", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2667868658", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3783425301", + "therm_setpoint_fp": "comfort" + }, + { + "id": "68319658", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Night", + "id": 1, + "type": 1, + "rooms_temp": [ + { + "room_id": "738709350", + "therm_setpoint_fp": "away" + }, + { + "room_id": "70754041", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2640531479", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2667868658", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3783425301", + "therm_setpoint_fp": "away" + }, + { + "room_id": "68319658", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "738709350", + "therm_setpoint_fp": "away" + }, + { + "id": "70754041", + "therm_setpoint_fp": "away" + }, + { + "id": "2640531479", + "therm_setpoint_fp": "away" + }, + { + "id": "2667868658", + "therm_setpoint_fp": "away" + }, + { + "id": "3783425301", + "therm_setpoint_fp": "away" + }, + { + "id": "68319658", + "therm_setpoint_fp": "away" + } + ] + }, + { + "name": "Comfort+", + "id": 3, + "type": 8, + "rooms_temp": [ + { + "room_id": "738709350", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "70754041", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2640531479", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "2667868658", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "3783425301", + "therm_setpoint_fp": "comfort" + }, + { + "room_id": "68319658", + "therm_setpoint_fp": "comfort" + } + ], + "modules": [], + "rooms": [ + { + "id": "738709350", + "therm_setpoint_fp": "comfort" + }, + { + "id": "70754041", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2640531479", + "therm_setpoint_fp": "comfort" + }, + { + "id": "2667868658", + "therm_setpoint_fp": "comfort" + }, + { + "id": "3783425301", + "therm_setpoint_fp": "comfort" + }, + { + "id": "68319658", + "therm_setpoint_fp": "comfort" + } + ] + }, + { + "name": "Eco", + "id": 4, + "type": 5, + "rooms_temp": [ + { + "room_id": "738709350", + "therm_setpoint_fp": "away" + }, + { + "room_id": "70754041", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2640531479", + "therm_setpoint_fp": "away" + }, + { + "room_id": "2667868658", + "therm_setpoint_fp": "away" + }, + { + "room_id": "3783425301", + "therm_setpoint_fp": "away" + }, + { + "room_id": "68319658", + "therm_setpoint_fp": "away" + } + ], + "modules": [], + "rooms": [ + { + "id": "738709350", + "therm_setpoint_fp": "away" + }, + { + "id": "70754041", + "therm_setpoint_fp": "away" + }, + { + "id": "2640531479", + "therm_setpoint_fp": "away" + }, + { + "id": "2667868658", + "therm_setpoint_fp": "away" + }, + { + "id": "3783425301", + "therm_setpoint_fp": "away" + }, + { + "id": "68319658", + "therm_setpoint_fp": "away" + } + ] + } + ], + "name": "Mon planning de chauffe", + "default": false, + "away_temp": 12, + "hg_temp": 7, + "id": "64e3b6102853d9405304b27a", + "type": "therm", + "selected": true + }, + { + "timetable": [], + "zones": [], + "name": "Planning d'actions", + "default": false, + "timetable_sunrise": [], + "timetable_sunset": [], + "id": "64ee68e2c8419b37790c5050", + "type": "event", + "selected": true + }, + { + "timetable": [ + { + "zone_id": 0, + "m_offset": 0 + } + ], + "zones": [ + { + "id": 0, + "price": 0.2516, + "price_type": "basic" + } + ], + "name": "electricity", + "default": false, + "tariff": "edf_tarif_bleu", + "tariff_option": "basic", + "power_threshold": 9, + "contract_power_unit": "kVA", + "id": "64e28390bc6d555f2d05c684", + "type": "electricity", + "selected": true + } + ] + } + ], + "user": { + "email": "john.doe@doe.com", + "language": "fr-FR", + "locale": "fr-FR", + "feel_like_algorithm": 0, + "unit_pressure": 0, + "unit_system": 0, + "unit_wind": 0, + "id": "111111111112222222333333" + } + }, + "status": "ok", + "time_exec": 0.07427000999450684, + "time_server": 1709762264 +} \ No newline at end of file diff --git a/src/pyatmo/__init__.py b/src/pyatmo/__init__.py index 4ef12ea8..ca3a8a89 100644 --- a/src/pyatmo/__init__.py +++ b/src/pyatmo/__init__.py @@ -3,7 +3,15 @@ from pyatmo import const, modules from pyatmo.account import AsyncAccount from pyatmo.auth import AbstractAsyncAuth -from pyatmo.exceptions import ApiError, InvalidHome, InvalidRoom, NoDevice, NoSchedule +from pyatmo.exceptions import ( + ApiError, + ApiErrorThrottling, + ApiHomeReachabilityError, + InvalidHome, + InvalidRoom, + NoDevice, + NoSchedule, +) from pyatmo.home import Home from pyatmo.modules import Module from pyatmo.modules.device_types import DeviceType @@ -12,6 +20,8 @@ __all__ = [ "AbstractAsyncAuth", "ApiError", + "ApiErrorThrottling", + "ApiHomeReachabilityError", "AsyncAccount", "InvalidHome", "InvalidRoom", diff --git a/src/pyatmo/account.py b/src/pyatmo/account.py index 69dad18a..466337cc 100644 --- a/src/pyatmo/account.py +++ b/src/pyatmo/account.py @@ -36,6 +36,7 @@ def __init__(self, auth: AbstractAsyncAuth, favorite_stations: bool = True) -> N self.auth: AbstractAsyncAuth = auth self.user: str | None = None + self.all_homes_id: dict[str, str] = {} self.homes: dict[str, Home] = {} self.raw_data: RawData = {} self.favorite_stations: bool = favorite_stations @@ -49,16 +50,31 @@ def __repr__(self) -> str: f"{self.__class__.__name__}(user={self.user}, home_ids={self.homes.keys()}" ) - def process_topology(self) -> None: + def process_topology(self, disabled_homes_ids: list[str] | None = None) -> None: """Process topology information from /homesdata.""" + if disabled_homes_ids is None: + disabled_homes_ids = [] + for home in self.raw_data["homes"]: - if (home_id := home["id"]) in self.homes: + + home_id = home.get("id", "Unknown") + home_name = home.get("name", "Unknown") + self.all_homes_id[home_id] = home_name + + if home_id in disabled_homes_ids: + if home_id in self.homes: + del self.homes[home_id] + continue + + if home_id in self.homes: self.homes[home_id].update_topology(home) else: self.homes[home_id] = Home(self.auth, raw_data=home) - async def async_update_topology(self) -> None: + async def async_update_topology( + self, disabled_homes_ids: list[str] | None = None + ) -> None: """Retrieve topology data from /homesdata.""" resp = await self.auth.async_post_api_request( @@ -68,7 +84,7 @@ async def async_update_topology(self) -> None: self.user = self.raw_data.get("user", {}).get("email") - self.process_topology() + self.process_topology(disabled_homes_ids=disabled_homes_ids) async def async_update_status(self, home_id: str) -> None: """Retrieve status data from /homestatus.""" @@ -77,7 +93,7 @@ async def async_update_status(self, home_id: str) -> None: params={"home_id": home_id}, ) raw_data = extract_raw_data(await resp.json(), HOME) - await self.homes[home_id].update(raw_data) + await self.homes[home_id].update(raw_data, do_raise_for_reachability_error=True) async def async_update_events(self, home_id: str) -> None: """Retrieve events from /getevents.""" @@ -105,6 +121,7 @@ async def async_update_measures( home_id: str, module_id: str, start_time: int | None = None, + end_time: int | None = None, interval: MeasureInterval = MeasureInterval.HOUR, days: int = 7, ) -> None: @@ -112,6 +129,7 @@ async def async_update_measures( await getattr(self.homes[home_id].modules[module_id], "async_update_measures")( start_time=start_time, + end_time=end_time, interval=interval, days=days, ) diff --git a/src/pyatmo/auth.py b/src/pyatmo/auth.py index e94ed410..e401124d 100644 --- a/src/pyatmo/auth.py +++ b/src/pyatmo/auth.py @@ -17,7 +17,7 @@ WEBHOOK_URL_ADD_ENDPOINT, WEBHOOK_URL_DROP_ENDPOINT, ) -from pyatmo.exceptions import ApiError +from pyatmo.exceptions import ApiError, ApiErrorThrottling LOG = logging.getLogger(__name__) @@ -146,7 +146,8 @@ async def handle_error_response(self, resp, resp_status, url): """Handle error response.""" try: resp_json = await resp.json() - raise ApiError( + + message = ( f"{resp_status} - " f"{ERRORS.get(resp_status, '')} - " f"{resp_json['error']['message']} " @@ -154,6 +155,15 @@ async def handle_error_response(self, resp, resp_status, url): f"when accessing '{url}'", ) + if resp_status == 403 and resp_json["error"]["code"] == 26: + raise ApiErrorThrottling( + message, + ) + else: + raise ApiError( + message, + ) + except (JSONDecodeError, ContentTypeError) as exc: raise ApiError( f"{resp_status} - " diff --git a/src/pyatmo/const.py b/src/pyatmo/const.py index f182dfc2..1a471d67 100644 --- a/src/pyatmo/const.py +++ b/src/pyatmo/const.py @@ -102,3 +102,6 @@ ACCESSORY_WIND_TIME_TYPE = "wind_timeutc" ACCESSORY_GUST_STRENGTH_TYPE = "gust_strength" ACCESSORY_GUST_ANGLE_TYPE = "gust_angle" + +# 2 days of dynamic historical data stored +MAX_HISTORY_TIME_FRAME = 24 * 2 * 3600 diff --git a/src/pyatmo/exceptions.py b/src/pyatmo/exceptions.py index 4ed5f120..31cc8c69 100644 --- a/src/pyatmo/exceptions.py +++ b/src/pyatmo/exceptions.py @@ -37,6 +37,18 @@ class ApiError(Exception): pass +class ApiErrorThrottling(ApiError): + """Raised when an API error is encountered.""" + + pass + + +class ApiHomeReachabilityError(ApiError): + """Raised when an API error is encountered.""" + + pass + + class InvalidState(Exception): """Raised when an invalid state is encountered.""" diff --git a/src/pyatmo/helpers.py b/src/pyatmo/helpers.py index 72c5a822..9833d5b0 100644 --- a/src/pyatmo/helpers.py +++ b/src/pyatmo/helpers.py @@ -39,7 +39,7 @@ def extract_raw_data(resp: Any, tag: str) -> dict[str, Any]: return {"public": resp["body"], "errors": []} if resp is None or "body" not in resp or tag not in resp["body"]: - LOG.debug("Server response: %s", resp) + LOG.debug("Server response (tag: %s): %s", tag, resp) raise NoDevice("No device found, errors in response") if tag == "homes": @@ -49,7 +49,7 @@ def extract_raw_data(resp: Any, tag: str) -> dict[str, Any]: } if not (raw_data := fix_id(resp["body"].get(tag))): - LOG.debug("Server response: %s", resp) + LOG.debug("Server response (tag: %s): %s", tag, resp) raise NoDevice("No device data available") return {tag: raw_data, "errors": resp["body"].get("errors", [])} diff --git a/src/pyatmo/home.py b/src/pyatmo/home.py index 0c593969..71b5fbed 100644 --- a/src/pyatmo/home.py +++ b/src/pyatmo/home.py @@ -20,7 +20,12 @@ RawData, ) from pyatmo.event import Event -from pyatmo.exceptions import InvalidSchedule, InvalidState, NoSchedule +from pyatmo.exceptions import ( + ApiHomeReachabilityError, + InvalidSchedule, + InvalidState, + NoSchedule, +) from pyatmo.modules import Module from pyatmo.person import Person from pyatmo.room import Room @@ -94,10 +99,7 @@ def update_topology(self, raw_data: RawData) -> None: raw_modules = raw_data.get("modules", []) for module in raw_modules: if (module_id := module["id"]) not in self.modules: - self.modules[module_id] = getattr(modules, module["type"])( - home=self, - module=module, - ) + self.modules[module_id] = self.get_module(module) else: self.modules[module_id].update_topology(module) @@ -125,27 +127,39 @@ def update_topology(self, raw_data: RawData) -> None: for s in raw_data.get(SCHEDULES, []) } - async def update(self, raw_data: RawData) -> None: + async def update( + self, raw_data: RawData, do_raise_for_reachability_error=False + ) -> None: """Update home with the latest data.""" - + has_error = False for module in raw_data.get("errors", []): + has_error = True await self.modules[module["id"]].update({}) data = raw_data["home"] + has_an_update = False for module in data.get("modules", []): + has_an_update = True if module["id"] not in self.modules: self.update_topology({"modules": [module]}) await self.modules[module["id"]].update(module) for room in data.get("rooms", []): + has_an_update = True self.rooms[room["id"]].update(room) self.events = { s["id"]: Event(home_id=self.entity_id, raw_data=s) for s in data.get(EVENTS, []) } + if len(self.events) > 0: + has_an_update = True + + has_one_module_reachable = False for module in self.modules.values(): + if module.reachable: + has_one_module_reachable = True if hasattr(module, "events"): setattr( module, @@ -157,6 +171,16 @@ async def update(self, raw_data: RawData) -> None: ], ) + if ( + do_raise_for_reachability_error + and has_error + and has_one_module_reachable is False + and has_an_update is False + ): + raise ApiHomeReachabilityError( + "No Home update could be performed, all modules unreachable and not updated", + ) + def get_selected_schedule(self) -> Schedule | None: """Return selected schedule for given home.""" diff --git a/src/pyatmo/modules/base_class.py b/src/pyatmo/modules/base_class.py index c8bc5578..5541a23c 100644 --- a/src/pyatmo/modules/base_class.py +++ b/src/pyatmo/modules/base_class.py @@ -3,18 +3,22 @@ from __future__ import annotations from abc import ABC +import bisect from collections.abc import Iterable from dataclasses import dataclass import logging +from operator import itemgetter from typing import TYPE_CHECKING, Any -from pyatmo.const import RawData +from pyatmo.const import MAX_HISTORY_TIME_FRAME, RawData from pyatmo.modules.device_types import DeviceType if TYPE_CHECKING: from pyatmo.event import EventTypes from pyatmo.home import Home +from time import time + LOG = logging.getLogger(__name__) @@ -51,6 +55,9 @@ class EntityBase: entity_id: str home: Home bridge: str | None + history_features: set[str] + history_features_values: dict[str, [int, int]] | {} + name: str | None class NetatmoBase(EntityBase, ABC): @@ -61,6 +68,8 @@ def __init__(self, raw_data: RawData) -> None: self.entity_id = raw_data["id"] self.name = raw_data.get("name", f"Unknown {self.entity_id}") + self.history_features_values = {} + self.history_features = set() def update_topology(self, raw_data: RawData) -> None: """Update topology.""" @@ -82,6 +91,54 @@ def _update_attributes(self, raw_data: RawData) -> None: for key, val in self.__dict__.items() } + now = int(time()) + for hist_feature in self.history_features: + if hist_feature in self.__dict__: + val = getattr(self, hist_feature) + if val is None: + continue + + self.add_history_data(hist_feature, val, now) + + def add_history_data(self, feature: str, value, time: int) -> None: + """Add historical data at the given time.""" + + # get the feature values rolling buffer + hist_f = self.history_features_values.setdefault(feature, []) + if not hist_f or hist_f[-1][0] <= time: + hist_f.append((time, value, self.entity_id)) + else: + i = bisect.bisect_left(hist_f, time, key=itemgetter(0)) + + if i < len(hist_f): + if hist_f[i][0] == time: + hist_f[i] = (time, value, self.entity_id) + i = None + + if i is not None: + hist_f.insert(i, (time, value, self.entity_id)) + + # keep timing history to a maximum representative time + while len(hist_f) > 0 and hist_f[-1][0] - hist_f[0][0] > MAX_HISTORY_TIME_FRAME: + hist_f.pop(0) + + def get_history_data(self, feature: str, from_ts: int, to_ts: int | None = None): + """Retrieve historical data.""" + + hist_f = self.history_features_values.get(feature, []) + + if not hist_f: + return [] + + in_s = bisect.bisect_left(hist_f, from_ts, key=itemgetter(0)) + + if to_ts is None: + out_s = len(hist_f) + else: + out_s = bisect.bisect_right(hist_f, to_ts, key=itemgetter(0)) + + return hist_f[in_s:out_s] + @dataclass class Location: diff --git a/src/pyatmo/modules/legrand.py b/src/pyatmo/modules/legrand.py index 0fe68e4f..058a5df8 100644 --- a/src/pyatmo/modules/legrand.py +++ b/src/pyatmo/modules/legrand.py @@ -7,11 +7,12 @@ from pyatmo.modules.module import ( BatteryMixin, ContactorMixin, + DimmableMixin, Dimmer, - EnergyMixin, + EnergyHistoryLegacyMixin, + EnergyHistoryMixin, Fan, FirmwareMixin, - HistoryMixin, Module, OffloadMixin, PowerMixin, @@ -31,15 +32,15 @@ class NLG(FirmwareMixin, OffloadMixin, WifiMixin, Module): """Legrand gateway.""" -class NLT(FirmwareMixin, BatteryMixin, Module): - """Legrand global remote control.""" +class NLT(DimmableMixin, FirmwareMixin, BatteryMixin, SwitchMixin, Module): + """Legrand global remote control...but also wireless switch, like NLD.""" -class NLP(Switch, HistoryMixin, PowerMixin, OffloadMixin, Module): +class NLP(Switch, OffloadMixin): """Legrand plug.""" -class NLPM(Switch): +class NLPM(Switch, OffloadMixin): """Legrand mobile plug.""" @@ -47,7 +48,7 @@ class NLPO(ContactorMixin, OffloadMixin, Switch): """Legrand contactor.""" -class NLPT(Switch): +class NLPT(Switch, OffloadMixin): """Legrand latching relay/teleruptor.""" @@ -75,11 +76,11 @@ class NLIS(Switch): """Legrand double switch.""" -class NLD(Dimmer): - """Legrand Double On/Off dimmer remote.""" +class NLD(DimmableMixin, FirmwareMixin, BatteryMixin, SwitchMixin, Module): + """Legrand Double On/Off dimmer remote. Wireless 2 button switch light.""" -class NLL(FirmwareMixin, EnergyMixin, WifiMixin, SwitchMixin, Module): +class NLL(Switch, WifiMixin): """Legrand / BTicino italian light switch with neutral.""" @@ -95,19 +96,19 @@ class NLLM(FirmwareMixin, RfMixin, ShutterMixin, Module): """Legrand / BTicino shutters.""" -class NLPC(FirmwareMixin, HistoryMixin, PowerMixin, EnergyMixin, Module): +class NLPC(FirmwareMixin, EnergyHistoryMixin, PowerMixin, Module): """Legrand / BTicino connected energy meter.""" -class NLE(FirmwareMixin, HistoryMixin, PowerMixin, EnergyMixin, Module): - """Legrand / BTicino connected ecometer.""" +class NLE(FirmwareMixin, EnergyHistoryLegacyMixin, Module): + """Legrand / BTicino connected ecometer. no power supported for the NLE (in the home status API).""" -class NLPS(FirmwareMixin, PowerMixin, EnergyMixin, Module): +class NLPS(FirmwareMixin, EnergyHistoryMixin, PowerMixin, Module): """Legrand / BTicino smart load shedder.""" -class NLC(FirmwareMixin, SwitchMixin, HistoryMixin, PowerMixin, OffloadMixin, Module): +class NLC(Switch, OffloadMixin): """Legrand / BTicino cable outlet.""" @@ -115,7 +116,7 @@ class NLDD(FirmwareMixin, Module): """Legrand NLDD dimmer remote control.""" -class NLUP(FirmwareMixin, PowerMixin, SwitchMixin, Module): +class NLUP(Switch): """Legrand NLUP Power outlet.""" @@ -135,7 +136,7 @@ class NLUO(Dimmer): """Legrand NLUO device stub.""" -class NLLF(Fan): +class NLLF(Fan, PowerMixin, EnergyHistoryMixin): """Legrand NLLF fan/ventilation device.""" @@ -159,7 +160,7 @@ class NLTS(Module): """NLTS motion sensor.""" -class NLPD(FirmwareMixin, SwitchMixin, EnergyMixin, PowerMixin, Module): +class NLPD(Switch, OffloadMixin): """NLPD dry contact.""" diff --git a/src/pyatmo/modules/module.py b/src/pyatmo/modules/module.py index 415821eb..64901659 100644 --- a/src/pyatmo/modules/module.py +++ b/src/pyatmo/modules/module.py @@ -2,7 +2,7 @@ from __future__ import annotations -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone from enum import Enum import logging from typing import TYPE_CHECKING, Any @@ -18,6 +18,9 @@ from pyatmo.event import Event from pyatmo.home import Home +from operator import itemgetter +from time import time + LOG = logging.getLogger(__name__) ModuleT = dict[str, Any] @@ -41,6 +44,8 @@ "device_category", "device_type", "features", + "history_features", + "history_features_values", } @@ -289,16 +294,6 @@ def __init__(self, home: Home, module: ModuleT): self.appliance_type: str | None = None -class EnergyMixin(EntityBase): - """Mixin for energy data.""" - - def __init__(self, home: Home, module: ModuleT): - """Initialize energy mixin.""" - - super().__init__(home, module) # type: ignore # mypy issue 4335 - self.sum_energy_elec: int | None = None - - class PowerMixin(EntityBase): """Mixin for power data.""" @@ -307,6 +302,7 @@ def __init__(self, home: Home, module: ModuleT): super().__init__(home, module) # type: ignore # mypy issue 4335 self.power: int | None = None + self.history_features.add("power") class EventMixin(EntityBase): @@ -618,18 +614,66 @@ class MeasureType(Enum): BOILEROFF = "boileroff" SUM_BOILER_ON = "sum_boiler_on" SUM_BOILER_OFF = "sum_boiler_off" - SUM_ENERGY_ELEC = "sum_energy_elec" - SUM_ENERGY_ELEC_BASIC = "sum_energy_elec$0" - SUM_ENERGY_ELEC_PEAK = "sum_energy_elec$1" - SUM_ENERGY_ELEC_OFF_PEAK = "sum_energy_elec$2" - SUM_ENERGY_PRICE = "sum_energy_price" - SUM_ENERGY_PRICE_BASIC = "sum_energy_price$0" - SUM_ENERGY_PRICE_PEAK = "sum_energy_price$1" - SUM_ENERGY_PRICE_OFF_PEAK = "sum_energy_price$2" + SUM_ENERGY_ELEC = "sum_energy_buy_from_grid" + SUM_ENERGY_ELEC_BASIC = "sum_energy_buy_from_grid$0" + SUM_ENERGY_ELEC_PEAK = "sum_energy_buy_from_grid$1" + SUM_ENERGY_ELEC_OFF_PEAK = "sum_energy_buy_from_grid$2" + SUM_ENERGY_PRICE = "sum_energy_buy_from_grid_price" + SUM_ENERGY_PRICE_BASIC = "sum_energy_buy_from_grid_price$0" + SUM_ENERGY_PRICE_PEAK = "sum_energy_buy_from_grid_price$1" + SUM_ENERGY_PRICE_OFF_PEAK = "sum_energy_buy_from_grid_price$2" + SUM_ENERGY_ELEC_LEGACY = "sum_energy_elec" + SUM_ENERGY_ELEC_BASIC_LEGACY = "sum_energy_elec$0" + SUM_ENERGY_ELEC_PEAK_LEGACY = "sum_energy_elec$1" + SUM_ENERGY_ELEC_OFF_PEAK_LEGACY = "sum_energy_elec$2" + + +MEASURE_INTERVAL_TO_SECONDS = { + MeasureInterval.HALF_HOUR: 1800, + MeasureInterval.HOUR: 3600, + MeasureInterval.THREE_HOURS: 10800, + MeasureInterval.DAY: 86400, + MeasureInterval.WEEK: 604800, + MeasureInterval.MONTH: 2592000, +} +ENERGY_FILTERS = f"{MeasureType.SUM_ENERGY_ELEC.value},{MeasureType.SUM_ENERGY_ELEC_BASIC.value},{MeasureType.SUM_ENERGY_ELEC_PEAK.value},{MeasureType.SUM_ENERGY_ELEC_OFF_PEAK.value}" +ENERGY_FILTERS_LEGACY = f"{MeasureType.SUM_ENERGY_ELEC_LEGACY.value},{MeasureType.SUM_ENERGY_ELEC_BASIC_LEGACY.value},{MeasureType.SUM_ENERGY_ELEC_PEAK_LEGACY.value},{MeasureType.SUM_ENERGY_ELEC_OFF_PEAK_LEGACY.value}" +ENERGY_FILTERS_MODES = ["generic", "basic", "peak", "off_peak"] -class HistoryMixin(EntityBase): - """Mixin for history data.""" + +def compute_riemann_sum( + power_data: list[tuple[int, float]], conservative: bool = False +): + """Compute energy from power with a rieman sum.""" + + delta_energy = 0 + if power_data and len(power_data) > 1: + + # compute a rieman sum, as best as possible , trapezoidal, taking pessimistic asumption + # as we don't want to artifically go up the previous one + # (except in rare exceptions like reset, 0 , etc) + + for i in range(len(power_data) - 1): + + dt_h = float(power_data[i + 1][0] - power_data[i][0]) / 3600.0 + + if conservative: + d_p_w = 0 + else: + d_p_w = abs(float(power_data[i + 1][1] - power_data[i][1])) + + d_nrj_wh = dt_h * ( + min(power_data[i + 1][1], power_data[i][1]) + 0.5 * d_p_w + ) + + delta_energy += d_nrj_wh + + return delta_energy + + +class EnergyHistoryMixin(EntityBase): + """Mixin for Energy history data.""" def __init__(self, home: Home, module: ModuleT): """Initialize history mixin.""" @@ -637,26 +681,304 @@ def __init__(self, home: Home, module: ModuleT): super().__init__(home, module) # type: ignore # mypy issue 4335 self.historical_data: list[dict[str, Any]] | None = None self.start_time: int | None = None + self.end_time: int | None = None self.interval: MeasureInterval | None = None + self.sum_energy_elec: int | None = None + self.sum_energy_elec_peak: int | None = None + self.sum_energy_elec_off_peak: int | None = None + self._anchor_for_power_adjustment: int | None = None + self.in_reset: bool | False = False + + def reset_measures(self, start_power_time, in_reset=True): + """Reset energy measures.""" + self.in_reset = in_reset + self.historical_data = [] + if start_power_time is None: + self._anchor_for_power_adjustment = start_power_time + else: + self._anchor_for_power_adjustment = int(start_power_time.timestamp()) + self.sum_energy_elec = 0 + self.sum_energy_elec_peak = 0 + self.sum_energy_elec_off_peak = 0 + + def get_sum_energy_elec_power_adapted( + self, to_ts: int | float | None = None, conservative: bool = False + ): + """Compute proper energy value with adaptation from power.""" + v = self.sum_energy_elec + + if v is None: + return None, 0 + + delta_energy = 0 + + if not self.in_reset: + + if to_ts is None: + to_ts = int(time()) + + from_ts = self._anchor_for_power_adjustment + + if ( + from_ts is not None + and from_ts < to_ts + and isinstance(self, PowerMixin) + and isinstance(self, NetatmoBase) + ): + power_data = self.get_history_data( + "power", from_ts=from_ts, to_ts=to_ts + ) + if isinstance( + self, EnergyHistoryMixin + ): # well to please the linter.... + delta_energy = compute_riemann_sum(power_data, conservative) + + return v, delta_energy + + def _log_energy_error(self, start_time, end_time, msg=None, body=None): + if body is None: + body = "NO BODY" + LOG.debug( + "ENERGY collection error %s %s %s %s %s %s %s", + msg, + self.name, + datetime.fromtimestamp(start_time), + datetime.fromtimestamp(end_time), + start_time, + end_time, + body, + ) async def async_update_measures( self, start_time: int | None = None, + end_time: int | None = None, interval: MeasureInterval = MeasureInterval.HOUR, days: int = 7, ) -> None: """Update historical data.""" - end_time = int(datetime.now().timestamp()) + if end_time is None: + end_time = int(datetime.now().timestamp()) + if start_time is None: - start_time = end_time - days * 24 * 60 * 60 + end = datetime.fromtimestamp(end_time) + start_time = end - timedelta(days=days) + start_time = int(start_time.timestamp()) + + prev_start_time = self.start_time + prev_end_time = self.end_time + + self.start_time = start_time + self.end_time = end_time + + # the legrand/netatmo handling of start and endtime is very peculiar + # for 30mn/1h/3h intervals : in fact the starts is asked_start + intervals/2 ! + # => so shift of 15mn, 30mn and 1h30 + # for 1day : start is ALWAYS 12am (half day) of the first day of the range + # for 1week : it will be half week ALWAYS, ie on a thursday at 12am (half day) + # in fact in the case for all intervals the reported dates are "the middle" of the ranges + + delta_range = MEASURE_INTERVAL_TO_SECONDS.get(interval, 0) // 2 + + filters, raw_data = await self._energy_API_calls(start_time, end_time, interval) + + hist_good_vals = await self._get_aligned_energy_values_and_mode( + start_time, end_time, delta_range, raw_data + ) + + self.historical_data = [] + prev_sum_energy_elec = self.sum_energy_elec + self.sum_energy_elec = 0 + self.sum_energy_elec_peak = 0 + self.sum_energy_elec_off_peak = 0 + + # no data at all: we know nothing for the end: best guess, it is the start + self._anchor_for_power_adjustment = start_time + + self.in_reset = False + + if len(hist_good_vals) == 0: + # nothing has been updated or changed it can nearly be seen as an error, but the api is answering correctly + # so we probably have to reset to 0 anyway as it means there were no exisitng + # historical data for this time range + + LOG.debug( + "NO VALUES energy update %s from: %s to %s, prev_sum=%s", + self.name, + datetime.fromtimestamp(start_time), + datetime.fromtimestamp(end_time), + prev_sum_energy_elec if prev_sum_energy_elec is not None else "NOTHING", + ) + else: + + await self._prepare_exported_historical_data( + start_time, + end_time, + delta_range, + hist_good_vals, + prev_end_time, + prev_start_time, + prev_sum_energy_elec, + ) + + async def _prepare_exported_historical_data( + self, + start_time, + end_time, + delta_range, + hist_good_vals, + prev_end_time, + prev_start_time, + prev_sum_energy_elec, + ): + computed_start = 0 + computed_end = 0 + computed_end_for_calculus = 0 + for cur_start_time, val, vals in hist_good_vals: + + self.sum_energy_elec += val + + modes = [] + val_modes = [] + + for i, v in enumerate(vals): + if v is not None: + modes.append(ENERGY_FILTERS_MODES[i]) + val_modes.append(v) + if ENERGY_FILTERS_MODES[i] == "off_peak": + self.sum_energy_elec_off_peak += v + elif ENERGY_FILTERS_MODES[i] == "peak": + self.sum_energy_elec_peak += v + + c_start = cur_start_time + c_end = cur_start_time + 2 * delta_range + + if computed_start == 0: + computed_start = c_start + computed_end = c_end + + # - delta_range not sure, revert ... it seems the energy value effectively stops at those mid values + computed_end_for_calculus = c_end # - delta_range + + start_time_string = f"{datetime.fromtimestamp(c_start + 1, tz=timezone.utc).isoformat().split('+')[0]}Z" + end_time_string = f"{datetime.fromtimestamp(c_end, tz=timezone.utc).isoformat().split('+')[0]}Z" + self.historical_data.append( + { + "duration": (2 * delta_range) // 60, + "startTime": start_time_string, + "endTime": end_time_string, + "Wh": val, + "energyMode": modes, + "WhPerModes": val_modes, + "startTimeUnix": c_start, + "endTimeUnix": c_end, + }, + ) + if ( + prev_sum_energy_elec is not None + and prev_sum_energy_elec > self.sum_energy_elec + ): + msg = ( + "ENERGY GOING DOWN %s from: %s to %s " + "computed_start: %s, computed_end: %s, " + "sum=%f prev_sum=%f prev_start: %s, prev_end %s" + ) + LOG.debug( + msg, + self.name, + datetime.fromtimestamp(start_time), + datetime.fromtimestamp(end_time), + datetime.fromtimestamp(computed_start), + datetime.fromtimestamp(computed_end), + self.sum_energy_elec, + prev_sum_energy_elec, + datetime.fromtimestamp(prev_start_time), + datetime.fromtimestamp(prev_end_time), + ) + else: + msg = ( + "Success in energy update %s from: %s to %s " + "computed_start: %s, computed_end: %s , sum=%s prev_sum=%s" + ) + LOG.debug( + msg, + self.name, + datetime.fromtimestamp(start_time), + datetime.fromtimestamp(end_time), + datetime.fromtimestamp(computed_start), + datetime.fromtimestamp(computed_end), + self.sum_energy_elec, + prev_sum_energy_elec if prev_sum_energy_elec is not None else "NOTHING", + ) + + self._anchor_for_power_adjustment = computed_end_for_calculus + + async def _get_aligned_energy_values_and_mode( + self, start_time, end_time, delta_range, raw_data + ): + hist_good_vals = [] + values_lots = raw_data + + for values_lot in values_lots: + try: + start_lot_time = int(values_lot["beg_time"]) + except Exception: + self._log_energy_error( + start_time, + end_time, + msg="beg_time missing", + body=values_lots, + ) + raise ApiError( + f"Energy badly formed resp beg_time missing: {values_lots} - " + f"module: {self.name}" + ) from None + + interval_sec = values_lot.get("step_time") + if interval_sec is None: + if len(values_lot.get("value", [])) > 1: + self._log_energy_error( + start_time, + end_time, + msg="step_time missing", + body=values_lots, + ) + interval_sec = 2 * delta_range + else: + interval_sec = int(interval_sec) + + # align the start on the begining of the segment + cur_start_time = start_lot_time - interval_sec // 2 + for val_arr in values_lot.get("value", []): + vals = [] + val = 0 + for v in val_arr: + if v is not None: + v = int(v) + val += v + vals.append(v) + else: + vals.append(None) + + hist_good_vals.append((cur_start_time, val, vals)) + cur_start_time = cur_start_time + interval_sec + + hist_good_vals = sorted(hist_good_vals, key=itemgetter(0)) + return hist_good_vals + + def _get_energy_filers(self): + return ENERGY_FILTERS + + async def _energy_API_calls(self, start_time, end_time, interval): + + filters = self._get_energy_filers() - data_point = MeasureType.SUM_ENERGY_ELEC_BASIC.value params = { "device_id": self.bridge, "module_id": self.entity_id, "scale": interval.value, - "type": data_point, + "type": filters, "date_begin": start_time, "date_end": end_time, } @@ -665,27 +987,30 @@ async def async_update_measures( endpoint=GETMEASURE_ENDPOINT, params=params, ) - raw_data = await resp.json() - data = raw_data["body"][0] - interval_sec = int(data["step_time"]) - interval_min = interval_sec // 60 + rw_dt_f = await resp.json() + rw_dt = rw_dt_f.get("body") - self.historical_data = [] - self.start_time = int(data["beg_time"]) - start_time = self.start_time - for value in data["value"]: - end_time = start_time + interval_sec - self.historical_data.append( - { - "duration": interval_min, - "startTime": f"{datetime.fromtimestamp(start_time + 1, tz=timezone.utc).isoformat().split('+')[0]}Z", - "endTime": f"{datetime.fromtimestamp(end_time, tz=timezone.utc).isoformat().split('+')[0]}Z", - "Wh": value[0], - }, + if rw_dt is None: + self._log_energy_error( + start_time, end_time, msg=f"direct from {filters}", body=rw_dt_f ) + raise ApiError( + f"Energy badly formed resp: {rw_dt_f} - " + f"module: {self.name} - " + f"when accessing '{filters}'" + ) + + raw_data = rw_dt - start_time = end_time + return filters, raw_data + + +class EnergyHistoryLegacyMixin(EnergyHistoryMixin): + """Mixin for Energy history data, Using legacy APis (used for NLE).""" + + def _get_energy_filers(self): + return ENERGY_FILTERS_LEGACY class Module(NetatmoBase): @@ -720,6 +1045,15 @@ async def update(self, raw_data: RawData) -> None: self.update_topology(raw_data) self.update_features() + # If we have an NLE as a bridge all its bridged modules will have to be reachable + if self.device_type == DeviceType.NLE: + # if there is a bridge it means it is a leaf + if self.bridge: + self.reachable = True + elif self.modules: + # this NLE is a bridge itself : make it not available + self.reachable = False + if not self.reachable and self.modules: # Update bridged modules and associated rooms for module_id in self.modules: @@ -759,7 +1093,7 @@ async def update(self, raw_data: RawData) -> None: await self.async_update_camera_urls() -class Switch(FirmwareMixin, PowerMixin, SwitchMixin, Module): +class Switch(FirmwareMixin, EnergyHistoryMixin, PowerMixin, SwitchMixin, Module): """Class to represent a Netatmo switch.""" ... diff --git a/tests/common.py b/tests/common.py index f030959b..3bff5404 100644 --- a/tests/common.py +++ b/tests/common.py @@ -61,11 +61,22 @@ async def fake_post_request(*args, **kwargs): elif endpoint == "getmeasure": module_id = kwargs.get("params", {}).get("module_id") + type = kwargs.get("params", {}).get("type") payload = json.loads( - load_fixture(f"{endpoint}_{module_id.replace(':', '_')}.json"), + load_fixture(f"{endpoint}_{type}_{module_id.replace(':', '_')}.json"), ) else: - payload = json.loads(load_fixture(f"{endpoint}.json")) + postfix = kwargs.get("POSTFIX", None) + if postfix is not None: + payload = json.loads(load_fixture(f"{endpoint}_{postfix}.json")) + else: + payload = json.loads(load_fixture(f"{endpoint}.json")) return MockResponse(payload, 200) + + +async def fake_post_request_multi(*args, **kwargs): + kwargs["POSTFIX"] = "multi" + r = await fake_post_request(*args, **kwargs) + return r diff --git a/tests/conftest.py b/tests/conftest.py index 5c596d57..bd9bfdea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,7 +7,7 @@ import pyatmo import pytest -from .common import fake_post_request +from .common import fake_post_request, fake_post_request_multi @contextmanager @@ -44,3 +44,29 @@ async def async_home(async_account): home_id = "91763b24c43d3e344f424e8b" await async_account.async_update_status(home_id) yield async_account.homes[home_id] + + +@pytest.fixture(scope="function") +async def async_account_multi(async_auth): + """AsyncAccount fixture.""" + account = pyatmo.AsyncAccount(async_auth) + + with patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", + fake_post_request_multi, + ), patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_request", + fake_post_request_multi, + ): + await account.async_update_topology( + disabled_homes_ids=["eeeeeeeeeffffffffffaaaaa"] + ) + yield account + + +@pytest.fixture(scope="function") +async def async_home_multi(async_account_multi): + """AsyncClimate fixture for home_id 91763b24c43d3e344f424e8b.""" + home_id = "aaaaaaaaaaabbbbbbbbbbccc" + await async_account_multi.async_update_status(home_id) + yield async_account_multi.homes[home_id] diff --git a/tests/test_energy.py b/tests/test_energy.py index 06ec2408..511bf815 100644 --- a/tests/test_energy.py +++ b/tests/test_energy.py @@ -1,7 +1,15 @@ """Define tests for energy module.""" -from pyatmo import DeviceType +import datetime as dt +import json +from unittest.mock import AsyncMock, patch + +from pyatmo import ApiHomeReachabilityError, DeviceType +from pyatmo.modules.module import EnergyHistoryMixin, MeasureInterval import pytest +import time_machine + +from tests.common import MockResponse # pylint: disable=F6401 @@ -14,3 +22,127 @@ async def test_async_energy_NLPC(async_home): # pylint: disable=invalid-name module = async_home.modules[module_id] assert module.device_type == DeviceType.NLPC assert module.power == 476 + + +@time_machine.travel(dt.datetime(2022, 2, 12, 7, 59, 49)) +@pytest.mark.asyncio +async def test_historical_data_retrieval(async_account): + """Test retrieval of historical measurements.""" + home_id = "91763b24c43d3e344f424e8b" + await async_account.async_update_events(home_id=home_id) + home = async_account.homes[home_id] + + module_id = "12:34:56:00:00:a1:4c:da" + assert module_id in home.modules + module = home.modules[module_id] + assert module.device_type == DeviceType.NLPC + + await async_account.async_update_measures(home_id=home_id, module_id=module_id) + # changed the reference here as start and stop data was not calculated in the spirit of the netatmo api where their time data is in the fact representing the "middle" of the range and not the begining + assert module.historical_data[0] == { + "Wh": 197, + "duration": 60, + "endTime": "2022-02-05T08:59:49Z", + "endTimeUnix": 1644051589, + "energyMode": ["basic"], + "WhPerModes": [197], + "startTime": "2022-02-05T07:59:50Z", + "startTimeUnix": 1644047989, + } + assert module.historical_data[-1] == { + "Wh": 259, + "duration": 60, + "endTime": "2022-02-12T07:59:49Z", + "endTimeUnix": 1644652789, + "energyMode": ["basic"], + "WhPerModes": [259], + "startTime": "2022-02-12T06:59:50Z", + "startTimeUnix": 1644649189, + } + assert len(module.historical_data) == 168 + + +@time_machine.travel(dt.datetime(2024, 7, 24, 22, 00, 10)) +@pytest.mark.asyncio +async def test_historical_data_retrieval_multi(async_account_multi): + """Test retrieval of historical measurements.""" + home_id = "aaaaaaaaaaabbbbbbbbbbccc" + + home = async_account_multi.homes[home_id] + + module_id = "98:76:54:32:10:00:00:69" + assert module_id in home.modules + module = home.modules[module_id] + assert module.device_type == DeviceType.NLPC + + strt = int(dt.datetime.fromisoformat("2024-07-24 00:00:00").timestamp()) + end_time = int(dt.datetime.fromisoformat("2024-07-24 22:27:00").timestamp()) + + await async_account_multi.async_update_measures( + home_id=home_id, + module_id=module_id, + interval=MeasureInterval.HALF_HOUR, + start_time=strt, + end_time=end_time, + ) + assert isinstance(module, EnergyHistoryMixin) + + assert module.historical_data[0] == { + "Wh": 20, + "duration": 30, + "endTime": "2024-07-23T22:30:00Z", + "endTimeUnix": 1721773800, + "energyMode": ["basic"], + "WhPerModes": [20], + "startTime": "2024-07-23T22:00:01Z", + "startTimeUnix": 1721772000, + } + assert module.historical_data[17] == { + "Wh": 710, + "WhPerModes": [498, 212], + "duration": 30, + "endTime": "2024-07-24T07:00:00Z", + "endTimeUnix": 1721804400, + "energyMode": ["basic", "peak"], + "startTime": "2024-07-24T06:30:01Z", + "startTimeUnix": 1721802600, + } + + assert module.historical_data[-1] == { + "Wh": 16, + "WhPerModes": [16], + "duration": 30, + "endTime": "2024-07-24T17:30:00Z", + "endTimeUnix": 1721842200, + "energyMode": ["peak"], + "startTime": "2024-07-24T17:00:01Z", + "startTimeUnix": 1721840400, + } + + assert len(module.historical_data) == 39 + assert module.sum_energy_elec == 17547 + assert module.sum_energy_elec_off_peak == 4290 + assert module.sum_energy_elec_peak == 10177 + + +async def test_disconnected_main_bridge(async_account_multi): + """Test retrieval of historical measurements.""" + home_id = "aaaaaaaaaaabbbbbbbbbbccc" + + with open( + "fixtures/home_multi_status_error_disconnected.json", + encoding="utf-8", + ) as json_file: + home_status_fixture = json.load(json_file) + mock_home_status_resp = MockResponse(home_status_fixture, 200) + + with patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", + AsyncMock(return_value=mock_home_status_resp), + ) as mock_request: + try: + await async_account_multi.async_update_status(home_id) + except ApiHomeReachabilityError: + pass # expected error + else: + assert False diff --git a/tests/test_home.py b/tests/test_home.py index 67bf922c..70e85b6c 100644 --- a/tests/test_home.py +++ b/tests/test_home.py @@ -1,13 +1,12 @@ """Define tests for home module.""" -import datetime as dt +# import datetime as dt import json from unittest.mock import AsyncMock, patch import pyatmo from pyatmo import DeviceType, NoDevice import pytest -import time_machine from tests.common import MockResponse @@ -145,35 +144,6 @@ async def test_home_event_update(async_account): assert events[1].event_type == "connection" -@time_machine.travel(dt.datetime(2022, 2, 12, 7, 59, 49)) -@pytest.mark.asyncio -async def test_historical_data_retrieval(async_account): - """Test retrieval of historical measurements.""" - home_id = "91763b24c43d3e344f424e8b" - await async_account.async_update_events(home_id=home_id) - home = async_account.homes[home_id] - - module_id = "12:34:56:00:00:a1:4c:da" - assert module_id in home.modules - module = home.modules[module_id] - assert module.device_type == DeviceType.NLPC - - await async_account.async_update_measures(home_id=home_id, module_id=module_id) - assert module.historical_data[0] == { - "Wh": 197, - "duration": 60, - "startTime": "2022-02-05T08:29:50Z", - "endTime": "2022-02-05T09:29:49Z", - } - assert module.historical_data[-1] == { - "Wh": 259, - "duration": 60, - "startTime": "2022-02-12T07:29:50Z", - "endTime": "2022-02-12T08:29:49Z", - } - assert len(module.historical_data) == 168 - - def test_device_types_missing(): """Test handling of missing device types.""" diff --git a/tests/testing_main_template.py b/tests/testing_main_template.py new file mode 100644 index 00000000..5d17423a --- /dev/null +++ b/tests/testing_main_template.py @@ -0,0 +1,48 @@ +import asyncio + +from aiohttp import ClientSession +import pyatmo +from pyatmo.auth import AbstractAsyncAuth +from pyatmo.modules.module import MeasureInterval + +MY_TOKEN_FROM_NETATMO = "MY_TOKEN" + + +class MyAuth(AbstractAsyncAuth): + + async def async_get_access_token(self): + + return MY_TOKEN_FROM_NETATMO + + +async def main(): + session = ClientSession() + async_auth = MyAuth(session) + account = pyatmo.AsyncAccount(async_auth) + + t = asyncio.create_task(account.async_update_topology()) + home_id = "MY_HOME_ID" + module_id = "MY_MODULE_ID" + + await asyncio.gather(t) + + await account.async_update_status(home_id=home_id) + + strt = 1709766000 + 10 * 60 # 1709421000+15*60 + end = 1709852400 + 10 * 60 + await account.async_update_measures( + home_id=home_id, + module_id=module_id, + interval=MeasureInterval.HALF_HOUR, + start_time=strt, + end_time=end, + ) + + # print(account) + + +if __name__ == "__main__": + + topology = asyncio.run(main()) + + # print(topology)