python-tado 0.17.6__tar.gz → 0.17.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {python_tado-0.17.6 → python_tado-0.17.7}/AUTHORS +1 -0
  2. {python_tado-0.17.6/python_tado.egg-info → python_tado-0.17.7}/PKG-INFO +1 -1
  3. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/const.py +1 -1
  4. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/exceptions.py +3 -0
  5. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/http/__init__.py +1 -1
  6. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/http/http.py +32 -1
  7. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/interface.py +157 -35
  8. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/zone.py +39 -11
  9. {python_tado-0.17.6 → python_tado-0.17.7/python_tado.egg-info}/PKG-INFO +1 -1
  10. {python_tado-0.17.6 → python_tado-0.17.7}/setup.py +1 -1
  11. {python_tado-0.17.6 → python_tado-0.17.7}/LICENSE +0 -0
  12. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/__init__.py +0 -0
  13. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/__main__.py +0 -0
  14. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/logging/__init__.py +0 -0
  15. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/logging/logging.py +0 -0
  16. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/polyfill/__init__.py +0 -0
  17. {python_tado-0.17.6 → python_tado-0.17.7}/PyTado/polyfill/strenum.py +0 -0
  18. {python_tado-0.17.6 → python_tado-0.17.7}/README.md +0 -0
  19. {python_tado-0.17.6 → python_tado-0.17.7}/python_tado.egg-info/SOURCES.txt +0 -0
  20. {python_tado-0.17.6 → python_tado-0.17.7}/python_tado.egg-info/dependency_links.txt +0 -0
  21. {python_tado-0.17.6 → python_tado-0.17.7}/python_tado.egg-info/entry_points.txt +0 -0
  22. {python_tado-0.17.6 → python_tado-0.17.7}/python_tado.egg-info/not-zip-safe +0 -0
  23. {python_tado-0.17.6 → python_tado-0.17.7}/python_tado.egg-info/requires.txt +0 -0
  24. {python_tado-0.17.6 → python_tado-0.17.7}/python_tado.egg-info/top_level.txt +0 -0
  25. {python_tado-0.17.6 → python_tado-0.17.7}/setup.cfg +0 -0
  26. {python_tado-0.17.6 → python_tado-0.17.7}/tests/test_tado.py +0 -0
  27. {python_tado-0.17.6 → python_tado-0.17.7}/tests/test_zone.py +0 -0
@@ -2,3 +2,4 @@ Author: Chris Jewell <chrism0dwk@gmail.com>
2
2
  Modified: Gareth Jeanne <contact@garethjeanne.co.uk>
3
3
  Wolfgang Malgadey <w.malgadey@gmail.com>
4
4
  Matt Clayton <matt.r.clayton@gmail.com>
5
+ Karl Beecken <karl@beecken.berlin>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-tado
3
- Version: 0.17.6
3
+ Version: 0.17.7
4
4
  Summary: PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon
5
5
  Home-page: https://github.com/wmalgadey/PyTado
6
6
  Author: chrism0dwk, w.malgadey
@@ -43,7 +43,7 @@ CONST_HORIZONTAL_SWING_RIGHT = "RIGHT"
43
43
 
44
44
  # When we change the temperature setting, we need an overlay mode
45
45
  CONST_OVERLAY_TADO_MODE = "NEXT_TIME_BLOCK" # wait until tado changes the mode automatic
46
- CONST_OVERLAY_MANUAL = "MANUAL" # the user has change the temperature or mode manually
46
+ CONST_OVERLAY_MANUAL = "MANUAL" # the user has changed the temperature or mode manually
47
47
  CONST_OVERLAY_TIMER = "TIMER" # the temperature will be reset after a timespan
48
48
 
49
49
  # Heat always comes first since we get the
@@ -8,6 +8,9 @@ class TadoException(Exception):
8
8
  class TadoNotSupportedException(TadoException):
9
9
  """Exception to indicate a requested action is not supported by Tado."""
10
10
 
11
+ class TadoXNotSupportedException(TadoException):
12
+ """Exception to indicate a requested action is not supported by the Tado X API."""
13
+
11
14
 
12
15
  class TadoCredentialsException(TadoException):
13
16
  """Exception to indicate something with credentials"""
@@ -1 +1 @@
1
- from .http import Action, Domain, Endpoint, Http, Mode, TadoRequest
1
+ from .http import Action, Domain, Endpoint, Http, Mode, TadoRequest, TadoXRequest
@@ -6,6 +6,7 @@ import json
6
6
  import logging
7
7
  import pprint
8
8
  from datetime import datetime, timedelta
9
+ from typing import Union
9
10
 
10
11
  try:
11
12
  from enum import StrEnum, ReprEnum
@@ -26,6 +27,11 @@ class Endpoint(StrEnum):
26
27
  MOBILE = "https://my.tado.com/mobile/1.9/"
27
28
  EIQ = "https://energy-insights.tado.com/api/"
28
29
 
30
+ class EndpointX(StrEnum):
31
+ """Endpoint URL Enum"""
32
+ API = "https://hops.tado.com/"
33
+ EIQ = "https://energy-insights.tado.com/api/"
34
+
29
35
 
30
36
  class Domain(StrEnum):
31
37
  """API Request Domain Enum"""
@@ -40,6 +46,7 @@ class Action(StrEnum):
40
46
  SET = "POST"
41
47
  RESET = "DELETE"
42
48
  CHANGE = "PUT"
49
+ UPDATE = "PATCH"
43
50
 
44
51
 
45
52
  class Mode(Enum):
@@ -58,6 +65,16 @@ class TadoRequest:
58
65
  device = None
59
66
  mode = Mode.OBJECT
60
67
 
68
+ class TadoXRequest:
69
+ """Data Container"""
70
+ endpoint = EndpointX.API
71
+ command = None
72
+ action = Action.GET
73
+ payload = None
74
+ domain = Domain.HOME
75
+ device = None
76
+ mode = Mode.OBJECT
77
+
61
78
 
62
79
  class TadoResponse:
63
80
  """Unimplemented Response Container
@@ -83,6 +100,8 @@ class Http:
83
100
  # Id
84
101
  id = 0
85
102
 
103
+ isX = False
104
+
86
105
  __username = None
87
106
  __password = None
88
107
 
@@ -111,7 +130,7 @@ class Http:
111
130
  f"Response:\n\tStatusCode: {response_status}\n\tData: {response.json()}"
112
131
  )
113
132
 
114
- def request(self, request: TadoRequest):
133
+ def request(self, request: Union[TadoRequest, TadoXRequest]):
115
134
  """Request something from the API with a TadoRequest"""
116
135
  self.__refresh_token()
117
136
 
@@ -250,6 +269,7 @@ class Http:
250
269
  if response.status_code == 200:
251
270
  self.__set_oauth_header(response.json())
252
271
  self.__get_id()
272
+ self.__check_x()
253
273
 
254
274
  def __get_id(self):
255
275
  if self.id == 0:
@@ -257,3 +277,14 @@ class Http:
257
277
  request.action = Action.GET
258
278
  request.domain = Domain.ME
259
279
  self.id = self.request(request)['homes'][0]['id']
280
+
281
+ def __check_x(self):
282
+ # get home info
283
+ request = TadoRequest()
284
+ request.action = Action.GET
285
+ request.domain = Domain.HOME
286
+ request.command = ""
287
+ home = self.request(request)
288
+ if 'generation' in home and home['generation'] == 'LINE_X':
289
+ self.isX = True
290
+ self.log.debug("Tado X API detected")
@@ -7,10 +7,11 @@ import logging
7
7
  import warnings
8
8
  from enum import IntEnum
9
9
 
10
- from .exceptions import TadoNotSupportedException
11
- from PyTado.http import Action, Domain, Endpoint, Http, Mode, TadoRequest
10
+ from .exceptions import TadoNotSupportedException, TadoXNotSupportedException
11
+ from PyTado.http import Action, Domain, Endpoint, Http, Mode, TadoRequest, TadoXRequest
12
12
  from PyTado.logging import Logger
13
13
  from .zone import TadoZone
14
+ from typing import Any
14
15
 
15
16
 
16
17
  class Tado:
@@ -77,10 +78,16 @@ class Tado:
77
78
  Gets device information.
78
79
  """
79
80
 
80
- request = TadoRequest()
81
- request.command = "devices"
82
-
83
- return self.http.request(request)
81
+ if self.http.isX:
82
+ request = TadoXRequest()
83
+ request.command = "roomsAndDevices"
84
+ rooms: list[dict[str, Any]] = self.http.request(request)['rooms']
85
+ devices = [device for room in rooms for device in room['devices']]
86
+ return devices
87
+ else:
88
+ request = TadoRequest()
89
+ request.command = "devices"
90
+ return self.http.request(request)
84
91
 
85
92
  # <editor-fold desc="Deprecated">
86
93
  def getZones(self):
@@ -96,10 +103,15 @@ class Tado:
96
103
  Gets zones information.
97
104
  """
98
105
 
99
- request = TadoRequest()
100
- request.command = "zones"
106
+ if self.http.isX:
107
+ request = TadoXRequest()
108
+ request.command = "roomsAndDevices"
109
+ return self.http.request(request)['rooms']
110
+ else:
111
+ request = TadoRequest()
112
+ request.command = "zones"
113
+ return self.http.request(request)
101
114
 
102
- return self.http.request(request)
103
115
 
104
116
  # <editor-fold desc="Deprecated">
105
117
  def getZoneState(self, zone):
@@ -114,8 +126,10 @@ class Tado:
114
126
  """
115
127
  Gets current state of Zone as a TadoZone object.
116
128
  """
117
-
118
- return TadoZone(self.get_state(zone), zone)
129
+ if self.http.isX:
130
+ return TadoZone(self.get_state(zone), zone, isX=True)
131
+ else:
132
+ return TadoZone(self.get_state(zone), zone)
119
133
 
120
134
  # <editor-fold desc="Deprecated">
121
135
  def getZoneStates(self):
@@ -131,8 +145,12 @@ class Tado:
131
145
  Gets current states of all zones.
132
146
  """
133
147
 
134
- request = TadoRequest()
135
- request.command = "zoneStates"
148
+ if self.http.isX:
149
+ request = TadoXRequest()
150
+ request.command = "rooms"
151
+ else:
152
+ request = TadoRequest()
153
+ request.command = "zoneStates"
136
154
 
137
155
  return self.http.request(request)
138
156
 
@@ -149,10 +167,14 @@ class Tado:
149
167
  """
150
168
  Gets current state of Zone.
151
169
  """
152
-
153
- request = TadoRequest()
154
- request.command = f"zones/{zone}/state"
155
- data = {**self.http.request(request), **self.get_zone_overlay_default(zone)}
170
+ if self.http.isX:
171
+ request = TadoXRequest()
172
+ request.command = f"rooms/{zone}"
173
+ data = self.http.request(request)
174
+ else:
175
+ request = TadoRequest()
176
+ request.command = f"zones/{zone}/state"
177
+ data = {**self.http.request(request), **self.get_zone_overlay_default(zone)}
156
178
 
157
179
  return data
158
180
 
@@ -236,7 +258,10 @@ class Tado:
236
258
  def get_capabilities(self, zone):
237
259
  """
238
260
  Gets current capabilities of zone.
261
+ TODO: This method is not currently supported by the Tado X API, check if it is needed
239
262
  """
263
+ if self.http.isX:
264
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
240
265
 
241
266
  request = TadoRequest()
242
267
  request.command = f"zones/{zone:d}/capabilities"
@@ -258,7 +283,11 @@ class Tado:
258
283
  """
259
284
 
260
285
  data = self.get_state(zone)['sensorDataPoints']
261
- return {'temperature': data['insideTemperature']['celsius'],
286
+ if self.http.isX:
287
+ return {'temperature': data['insideTemperature']['value'],
288
+ 'humidity': data['humidity']['percentage']}
289
+ else:
290
+ return {'temperature': data['insideTemperature']['celsius'],
262
291
  'humidity': data['humidity']['percentage']}
263
292
 
264
293
  # <editor-fold desc="Deprecated">
@@ -275,15 +304,21 @@ class Tado:
275
304
  Get the Timetable type currently active
276
305
  """
277
306
 
278
- request = TadoRequest()
279
- request.command = f"zones/{zone:d}/schedule/activeTimetable"
280
- request.mode = Mode.PLAIN
281
- data = self.http.request(request)
307
+ if self.http.isX:
308
+ # Not currently supported by the Tado X API
309
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
310
+ else:
311
+ request = TadoRequest()
312
+ request.command = f"zones/{zone:d}/schedule/activeTimetable"
313
+ request.mode = Mode.PLAIN
314
+ data = self.http.request(request)
315
+
316
+ if "id" in data:
317
+ return Tado.Timetable(data["id"])
318
+
319
+ raise Exception(f"Returned data did not contain \"id\" : {str(data)}")
282
320
 
283
- if "id" in data:
284
- return Tado.Timetable(data["id"])
285
321
 
286
- raise Exception(f"Returned data did not contain \"id\" : {str(data)}")
287
322
 
288
323
  # <editor-fold desc="Deprecated">
289
324
  def getHistoric(self, zone, date):
@@ -328,6 +363,10 @@ class Tado:
328
363
  id = 3 : SEVEN_DAY (MONDAY, TUESDAY, WEDNESDAY ...)
329
364
  """
330
365
 
366
+ if self.http.isX:
367
+ # Not currently supported by the Tado X API
368
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
369
+
331
370
  # Type checking
332
371
  if not isinstance(_id, Tado.Timetable):
333
372
  raise TypeError('id must be an instance of Tado.Timetable')
@@ -350,12 +389,19 @@ class Tado:
350
389
 
351
390
  # </editor-fold>
352
391
 
353
- def get_schedule(self, zone, _id, day=None):
392
+ def get_schedule(self, zone, _id=None, day=None):
354
393
  """
355
394
  Get the JSON representation of the schedule for a zone.
356
395
  Zone has 3 different schedules, one for each timetable (see setTimetable)
357
396
  """
358
397
 
398
+ if self.http.isX:
399
+ request = TadoXRequest()
400
+ request.command = f'rooms/{zone}/schedule'
401
+ return self.http.request(request)
402
+
403
+ if not _id:
404
+ raise ValueError('id must be an instance of Tado.Timetable')
359
405
  # Type checking
360
406
  if not isinstance(_id, Tado.Timetable):
361
407
  raise TypeError('id must be an instance of Tado.Timetable')
@@ -377,14 +423,25 @@ class Tado:
377
423
 
378
424
  # </editor-fold>
379
425
 
380
- def set_schedule(self, zone, _id, day, data):
426
+ def set_schedule(self, zone, data, _id=None, day=None):
381
427
  """
382
- Set the schedule for a zone, day is required
428
+ Set the schedule for a zone, day is required for non-X API
383
429
  """
384
430
 
431
+ # TODO: sometimes gives back 400 error
432
+ if self.http.isX:
433
+ request = TadoXRequest()
434
+ request.action = Action.SET
435
+ request.command = f'rooms/{zone}/schedule'
436
+ request.payload = data
437
+ request.mode = Mode.OBJECT
438
+ return self.http.request(request)
439
+
385
440
  # Type checking
386
441
  if not isinstance(_id, Tado.Timetable):
387
442
  raise TypeError('id must be an instance of Tado.Timetable')
443
+ if not isinstance(day, int):
444
+ raise ValueError('day must be an integer')
388
445
 
389
446
  request = TadoRequest()
390
447
  request.command = f"zones/{zone:d}/schedule/timetables/{_id:d}/blocks/{day}"
@@ -427,7 +484,10 @@ class Tado:
427
484
  Gets air quality information
428
485
  """
429
486
 
430
- request = TadoRequest()
487
+ if self.http.isX:
488
+ request = TadoXRequest()
489
+ else:
490
+ request = TadoRequest()
431
491
  request.command = "airComfort"
432
492
 
433
493
  return self.http.request(request)
@@ -461,6 +521,11 @@ class Tado:
461
521
  Gets getAppUsersRelativePositions data
462
522
  """
463
523
 
524
+ if self.http.isX:
525
+ # Not currently supported by the Tado X API
526
+ # TODO: reverse engineer mobile API
527
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
528
+
464
529
  request = TadoRequest()
465
530
  request.command = "getAppUsersRelativePositions"
466
531
  request.endpoint = Endpoint.MOBILE
@@ -500,12 +565,19 @@ class Tado:
500
565
  Delete current overlay
501
566
  """
502
567
 
503
- request = TadoRequest()
504
- request.command = f"zones/{zone:d}/overlay"
505
- request.action = Action.RESET
506
- request.mode = Mode.PLAIN
568
+ if self.http.isX:
569
+ request = TadoXRequest()
570
+ request.command = f"rooms/{zone}/resumeSchedule"
571
+ request.action = Action.SET
507
572
 
508
- return self.http.request(request)
573
+ return self.http.request(request)
574
+ else:
575
+ request = TadoRequest()
576
+ request.command = f"zones/{zone:d}/overlay"
577
+ request.action = Action.RESET
578
+ request.mode = Mode.PLAIN
579
+
580
+ return self.http.request(request)
509
581
 
510
582
  # <editor-fold desc="Deprecated">
511
583
  def setZoneOverlay(self, zone, overlayMode, setTemp=None, duration=None, deviceType='HEATING', power="ON",
@@ -540,9 +612,24 @@ class Tado:
540
612
 
541
613
  post_data = {
542
614
  "setting": {"type": device_type, "power": power},
543
- "termination": {"typeSkillBasedApp": overlay_mode},
615
+ "termination": {"type": overlay_mode},
544
616
  }
545
617
 
618
+ if self.http.isX:
619
+ if set_temp is not None:
620
+ post_data["setting"]["temperature"] = {"value": set_temp, "valueRaw": set_temp, "precision": 0.1}
621
+
622
+ if duration is not None:
623
+ post_data["termination"]["durationInSeconds"] = duration
624
+
625
+ request = TadoXRequest()
626
+ request.command = f"rooms/{zone}/manualControl"
627
+ request.action = Action.SET
628
+ request.payload = post_data
629
+
630
+ return self.http.request(request)
631
+
632
+
546
633
  if set_temp is not None:
547
634
  post_data["setting"]["temperature"] = {"celsius": set_temp}
548
635
  if fan_speed is not None:
@@ -584,6 +671,10 @@ class Tado:
584
671
  Get current overlay default settings for zone.
585
672
  """
586
673
 
674
+ if self.http.isX:
675
+ # Not currently supported by the Tado X API
676
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
677
+
587
678
  request = TadoRequest()
588
679
  request.command = f"zones/{zone:d}/defaultOverlay"
589
680
 
@@ -698,6 +789,12 @@ class Tado:
698
789
 
699
790
  data = self.get_state(zone)
700
791
 
792
+ if self.http.isX:
793
+ if 'activated'in data['openWindow']:
794
+ return {'openWindowDetected': True}
795
+ else:
796
+ return {'openWindowDetected': False}
797
+
701
798
  if "openWindowDetected" in data:
702
799
  return {'openWindowDetected': data['openWindowDetected']}
703
800
  else:
@@ -718,6 +815,10 @@ class Tado:
718
815
  Note: This can only be set if an open window was detected in this zone
719
816
  """
720
817
 
818
+ if self.http.isX:
819
+ # Not currently supported by the Tado X API
820
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
821
+
721
822
  request = TadoRequest()
722
823
  request.command = f"zones/{zone:d}/state/openWindow/activate"
723
824
  request.action = Action.SET
@@ -739,6 +840,10 @@ class Tado:
739
840
  Sets the window in zone to closed
740
841
  """
741
842
 
843
+ if self.http.isX:
844
+ # TODO test with X
845
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
846
+
742
847
  request = TadoRequest()
743
848
  request.command = f"zones/{zone:d}/state/openWindow"
744
849
  request.action = Action.RESET
@@ -761,6 +866,12 @@ class Tado:
761
866
  Gets information about devices
762
867
  with option to get specific info i.e. cmd='temperatureOffset'
763
868
  """
869
+
870
+ if self.http.isX:
871
+ # Not currently supported by the Tado X API
872
+ # Is included in the roomsAndDevices endpoint
873
+ raise TadoXNotSupportedException("This method is not currently supported by the Tado X API")
874
+
764
875
  request = TadoRequest()
765
876
  request.command = cmd
766
877
  request.action = Action.GET
@@ -783,6 +894,15 @@ class Tado:
783
894
  Set the Temperature offset on the device.
784
895
  """
785
896
 
897
+ if self.http.isX:
898
+ request = TadoXRequest()
899
+ request.command = f"roomsAndDevices/devices/{device_id}"
900
+ request.action = Action.UPDATE
901
+ request.payload = {"temperatureOffset": offset}
902
+
903
+ return self.http.request(request)
904
+
905
+
786
906
  request = TadoRequest()
787
907
  request.command = "temperatureOffset"
788
908
  request.action = Action.CHANGE
@@ -914,6 +1034,7 @@ class Tado:
914
1034
  def get_zone_control(self, zone):
915
1035
  """
916
1036
  Get zone control information
1037
+ TODO: Test with X
917
1038
  """
918
1039
 
919
1040
  request = TadoRequest()
@@ -924,6 +1045,7 @@ class Tado:
924
1045
  def set_zone_heating_circuit(self, zone, heating_circuit):
925
1046
  """
926
1047
  Sets the heating circuit for a zone
1048
+ TODO: Test with X
927
1049
  """
928
1050
 
929
1051
  request = TadoRequest()
@@ -9,6 +9,7 @@ from .const import (
9
9
  CONST_HVAC_IDLE,
10
10
  CONST_HVAC_OFF,
11
11
  CONST_LINK_OFFLINE,
12
+ CONST_MODE_HEAT,
12
13
  CONST_MODE_OFF,
13
14
  CONST_MODE_SMART_SCHEDULE,
14
15
  DEFAULT_TADO_PRECISION,
@@ -27,7 +28,7 @@ _LOGGER = logging.getLogger(__name__)
27
28
  class TadoZone:
28
29
  """Represent a tado zone."""
29
30
 
30
- def __init__(self, data, zone_id):
31
+ def __init__(self, data, zone_id, isX: bool = False):
31
32
  """Create a tado zone."""
32
33
  self._data = data
33
34
  self._zone_id = zone_id
@@ -54,7 +55,6 @@ class TadoZone:
54
55
  self._heating_power = None
55
56
  self._heating_power_percentage = None
56
57
  self._tado_mode = None
57
- self._overlay_active = None
58
58
  self._overlay_termination_type = None
59
59
  self._overlay_termination_timestamp = None
60
60
  self._preparation = None
@@ -64,6 +64,7 @@ class TadoZone:
64
64
  self._precision = DEFAULT_TADO_PRECISION
65
65
  self._default_overlay_termination_type = None
66
66
  self._default_overlay_termination_duration = None
67
+ self.isX = isX
67
68
  self.update_data(data)
68
69
 
69
70
  @property
@@ -238,11 +239,13 @@ class TadoZone:
238
239
  sensor_data = data["sensorDataPoints"]
239
240
 
240
241
  if "insideTemperature" in sensor_data:
241
- temperature = float(sensor_data["insideTemperature"]["celsius"])
242
- self._current_temp = temperature
243
- self._current_temp_timestamp = sensor_data["insideTemperature"][
244
- "timestamp"
245
- ]
242
+ if self.isX:
243
+ self._current_temp = float(sensor_data["insideTemperature"]["value"])
244
+ self._current_temp_timestamp = None
245
+ else:
246
+ temperature = float(sensor_data["insideTemperature"]["celsius"])
247
+ self._current_temp = temperature
248
+ self._current_temp_timestamp = sensor_data["insideTemperature"]["timestamp"]
246
249
  if "precision" in sensor_data["insideTemperature"]:
247
250
  self._precision = sensor_data["insideTemperature"]["precision"][
248
251
  "celsius"
@@ -251,7 +254,10 @@ class TadoZone:
251
254
  if "humidity" in sensor_data:
252
255
  humidity = float(sensor_data["humidity"]["percentage"])
253
256
  self._current_humidity = humidity
254
- self._current_humidity_timestamp = sensor_data["humidity"]["timestamp"]
257
+ if self.isX:
258
+ self._current_humidity_timestamp = None
259
+ else:
260
+ self._current_humidity_timestamp = sensor_data["humidity"]["timestamp"]
255
261
 
256
262
  self._is_away = None
257
263
  self._tado_mode = None
@@ -259,9 +265,12 @@ class TadoZone:
259
265
  self._is_away = data["tadoMode"] == "AWAY"
260
266
  self._tado_mode = data["tadoMode"]
261
267
 
268
+
262
269
  self._link = None
263
270
  if "link" in data:
264
271
  self._link = data["link"]["state"]
272
+ if "connection" in data:
273
+ self._link = data["connection"]["state"]
265
274
 
266
275
  self._current_hvac_action = CONST_HVAC_OFF
267
276
 
@@ -271,8 +280,11 @@ class TadoZone:
271
280
  "temperature" in data["setting"]
272
281
  and data["setting"]["temperature"] is not None
273
282
  ):
274
- setting = float(data["setting"]["temperature"]["celsius"])
275
- self._target_temp = setting
283
+ if self.isX:
284
+ self._target_temp = float(data["setting"]["temperature"]["value"])
285
+ else:
286
+ setting = float(data["setting"]["temperature"]["celsius"])
287
+ self._target_temp = setting
276
288
 
277
289
  setting = data["setting"]
278
290
 
@@ -378,5 +390,21 @@ class TadoZone:
378
390
  if "terminationCondition" in data:
379
391
  self._default_overlay_termination_type = data["terminationCondition"].get('type',None)
380
392
  self._default_overlay_termination_duration = data["terminationCondition"].get('durationInSeconds',None)
393
+
394
+ if self.isX:
395
+ if self._power == "ON":
396
+ self._current_hvac_action = CONST_HVAC_IDLE if data["heatingPower"]["percentage"] == 0 else CONST_HVAC_HEAT
397
+ self._heating_power_percentage = data["heatingPower"]["percentage"]
398
+ else:
399
+ self._heating_power_percentage = 0
400
+ self._current_hvac_action = CONST_HVAC_OFF
381
401
 
382
-
402
+ if "manualControlTermination" in data:
403
+ if data["manualControlTermination"]:
404
+ self._current_hvac_mode = CONST_MODE_HEAT if self._power == "ON" else CONST_MODE_OFF
405
+ self._overlay_termination_type = data["manualControlTermination"]["type"]
406
+ self._overlay_termination_timestamp = data["manualControlTermination"]["projectedExpiry"]
407
+ else:
408
+ self._overlay_termination_type = None
409
+ self._overlay_termination_timestamp = None
410
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-tado
3
- Version: 0.17.6
3
+ Version: 0.17.7
4
4
  Summary: PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon
5
5
  Home-page: https://github.com/wmalgadey/PyTado
6
6
  Author: chrism0dwk, w.malgadey
@@ -19,7 +19,7 @@ readme = open(here('README.md')).read()
19
19
  requirements = [x.strip() for x in open(here('requirements.txt')).readlines()]
20
20
 
21
21
  setup(name='python-tado',
22
- version='0.17.6',
22
+ version='0.17.7',
23
23
  description='PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon',
24
24
  long_description=readme,
25
25
  keywords='tado',
File without changes
File without changes
File without changes