plugwise 1.0.0__tar.gz → 1.1.0a0__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 (32) hide show
  1. {plugwise-1.0.0 → plugwise-1.1.0a0}/PKG-INFO +1 -1
  2. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/constants.py +2 -0
  3. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/data.py +39 -1
  4. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/smile.py +0 -1
  5. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/util.py +3 -0
  6. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise.egg-info/PKG-INFO +1 -1
  7. {plugwise-1.0.0 → plugwise-1.1.0a0}/pyproject.toml +1 -1
  8. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_adam.py +153 -153
  9. {plugwise-1.0.0 → plugwise-1.1.0a0}/LICENSE +0 -0
  10. {plugwise-1.0.0 → plugwise-1.1.0a0}/README.md +0 -0
  11. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/__init__.py +0 -0
  12. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/common.py +0 -0
  13. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/exceptions.py +0 -0
  14. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/helper.py +0 -0
  15. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/legacy/data.py +0 -0
  16. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/legacy/helper.py +0 -0
  17. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/legacy/smile.py +0 -0
  18. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise/py.typed +0 -0
  19. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise.egg-info/SOURCES.txt +0 -0
  20. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise.egg-info/dependency_links.txt +0 -0
  21. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise.egg-info/requires.txt +0 -0
  22. {plugwise-1.0.0 → plugwise-1.1.0a0}/plugwise.egg-info/top_level.txt +0 -0
  23. {plugwise-1.0.0 → plugwise-1.1.0a0}/setup.cfg +0 -0
  24. {plugwise-1.0.0 → plugwise-1.1.0a0}/setup.py +0 -0
  25. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_anna.py +0 -0
  26. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_generic.py +0 -0
  27. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_init.py +0 -0
  28. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_legacy_anna.py +0 -0
  29. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_legacy_generic.py +0 -0
  30. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_legacy_p1.py +0 -0
  31. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_legacy_stretch.py +0 -0
  32. {plugwise-1.0.0 → plugwise-1.1.0a0}/tests/test_p1.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: plugwise
3
- Version: 1.0.0
3
+ Version: 1.1.0a0
4
4
  Summary: Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3.
5
5
  Home-page: https://github.com/plugwise/python-plugwise
6
6
  Author: Plugwise device owners
@@ -258,6 +258,7 @@ ApplianceType = Literal[
258
258
  ]
259
259
 
260
260
  BinarySensorType = Literal[
261
+ "battery_state",
261
262
  "compressor_state",
262
263
  "cooling_enabled",
263
264
  "cooling_state",
@@ -409,6 +410,7 @@ class ModelData(TypedDict):
409
410
  class SmileBinarySensors(TypedDict, total=False):
410
411
  """Smile Binary Sensors class."""
411
412
 
413
+ battery_state: bool
412
414
  compressor_state: bool
413
415
  cooling_enabled: bool
414
416
  cooling_state: bool
@@ -4,6 +4,8 @@ Plugwise Smile protocol data-collection helpers.
4
4
  """
5
5
  from __future__ import annotations
6
6
 
7
+ import re
8
+
7
9
  from plugwise.constants import (
8
10
  ADAM,
9
11
  ANNA,
@@ -52,13 +54,49 @@ class SmileData(SmileHelper):
52
54
 
53
55
  Collect data for each device and add to self.gw_devices.
54
56
  """
57
+ mac_list: list[str] = []
55
58
  for device_id, device in self.gw_devices.items():
56
59
  data = self._get_device_data(device_id)
57
- self._add_or_update_notifications(device_id, device, data)
60
+ if device_id == self.gateway_id:
61
+ mac_list = self._detect_low_batteries()
62
+ self._add_or_update_notifications(device_id, device, data)
63
+
58
64
  device.update(data)
65
+
66
+ is_battery_low = (
67
+ mac_list
68
+ and "battery_state" in device["binary_sensors"]
69
+ and device["zigbee_mac_address"] in mac_list
70
+ and (
71
+ (device["dev_class"] in ("thermo_sensor", "thermostatic_radiator_valve") and device["sensors"]["battery"] < 30)
72
+ or (device["dev_class"] in ("zone_thermometer", "zone_thermostat") and device["sensors"]["battery"] < 15)
73
+ )
74
+ )
75
+ if is_battery_low:
76
+ device["binary_sensors"]["battery_state"] = True
77
+
59
78
  self._update_for_cooling(device)
79
+
60
80
  remove_empty_platform_dicts(device)
61
81
 
82
+ def _detect_low_batteries(self) -> list[str]:
83
+ """Helper-function updating the battery_state binary_sensor status from a Battery-is-low message."""
84
+ mac_address_list: list[str] = []
85
+ mac_pattern = re.compile(r"(?:[0-9A-F]{2}){8}")
86
+ matches = ["Battery", "below"]
87
+ if self._notifications:
88
+ for msg_id, notification in list(self._notifications.items()):
89
+ mac_address: str | None = None
90
+ message: str | None = notification.get("message")
91
+ if message is not None and all(x in message for x in matches) and (mac_addresses := mac_pattern.findall(message)):
92
+ mac_address = mac_addresses[0] # re.findall() outputs a list
93
+
94
+ if mac_address is not None:
95
+ self._notifications.pop(msg_id)
96
+ mac_address_list.append(mac_address)
97
+
98
+ return mac_address_list
99
+
62
100
  def _add_or_update_notifications(
63
101
  self, device_id: str, device: DeviceData, data: DeviceData
64
102
  ) -> None:
@@ -129,7 +129,6 @@ class SmileAPI(SmileComm, SmileData):
129
129
 
130
130
  async def async_update(self) -> PlugwiseData:
131
131
  """Perform an incremental update for updating the various device states."""
132
- # Perform a full update at day-change
133
132
  self.gw_data: GatewayData = {}
134
133
  self.gw_devices: dict[str, DeviceData] = {}
135
134
  try:
@@ -138,6 +138,9 @@ def common_match_cases(
138
138
  sp_key = cast(SpecialType, measurement)
139
139
  data[sp_key] = value
140
140
 
141
+ if "battery" in data["sensors"]:
142
+ data["binary_sensors"]["battery_state"] = False
143
+
141
144
 
142
145
  def escape_illegal_xml_characters(xmldata: str) -> str:
143
146
  """Replace illegal &-characters."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: plugwise
3
- Version: 1.0.0
3
+ Version: 1.1.0a0
4
4
  Summary: Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3.
5
5
  Home-page: https://github.com/plugwise/python-plugwise
6
6
  Author: Plugwise device owners
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "plugwise"
7
- version = "1.0.0"
7
+ version = "1.1.0a0"
8
8
  license = {file = "LICENSE"}
9
9
  description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
10
10
  readme = "README.md"
@@ -14,7 +14,155 @@ WERKDAG_SCHEMA = "Werkdag schema"
14
14
 
15
15
 
16
16
  class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outside-init
17
- """Tests for Adam standalone, i.e. not combined with Anna or Jip."""
17
+ """Tests for Adam."""
18
+
19
+ @pytest.mark.asyncio
20
+ async def test_connect_adam_plus_anna_new(self):
21
+ """Test extended Adam (firmware 3.8) with Anna and a switch-group setup."""
22
+ self.smile_setup = "adam_plus_anna_new"
23
+
24
+ testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
25
+ server, smile, client = await self.connect_wrapper()
26
+ assert smile.smile_hostname == "smile000000"
27
+
28
+ self.validate_test_basics(
29
+ _LOGGER,
30
+ smile,
31
+ smile_type=None,
32
+ smile_version="3.7.8",
33
+ )
34
+
35
+ await self.device_test(smile, "2023-12-17 00:00:01", testdata)
36
+ assert smile.gateway_id == "da224107914542988a88561b4452b0f6"
37
+ assert smile._last_active["f2bf9048bef64cc5b6d5110154e33c81"] == "Weekschema"
38
+ assert smile._last_active["f871b8c4d63549319221e294e4f88074"] == "Badkamer"
39
+ assert self.device_items == 149
40
+ assert self.device_list == [
41
+ "da224107914542988a88561b4452b0f6",
42
+ "056ee145a816487eaa69243c3280f8bf",
43
+ "67d73d0bd469422db25a618a5fb8eeb0",
44
+ "e2f4322d57924fa090fbbc48b3a140dc",
45
+ "29542b2b6a6a4169acecc15c72a599b8",
46
+ "ad4838d7d35c4d6ea796ee12ae5aedf8",
47
+ "1772a4ea304041adb83f357b751341ff",
48
+ "854f8a9b0e7e425db97f1f110e1ce4b3",
49
+ "2568cc4b9c1e401495d4741a5f89bee1",
50
+ "e8ef2a01ed3b4139a53bf749204fe6b4",
51
+ ]
52
+
53
+ result = await self.tinker_thermostat(
54
+ smile,
55
+ "f2bf9048bef64cc5b6d5110154e33c81",
56
+ good_schedules=["Weekschema", "Badkamer", "Test"],
57
+ )
58
+ assert result
59
+
60
+ # Special test-case for turning a schedule off based on only the location id.
61
+ await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "off")
62
+
63
+ # Special test-case for turning a schedule off for a location via the option "off".
64
+ await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "on", "off")
65
+
66
+ # bad schedule-state test
67
+ result = await self.tinker_thermostat_schedule(
68
+ smile,
69
+ "f2bf9048bef64cc5b6d5110154e33c81",
70
+ "bad",
71
+ good_schedules=["Badkamer"],
72
+ single=True,
73
+ )
74
+ assert result
75
+
76
+ smile._schedule_old_states["f2bf9048bef64cc5b6d5110154e33c81"][
77
+ "Badkamer"
78
+ ] = "off"
79
+ result_1 = await self.tinker_thermostat_schedule(
80
+ smile,
81
+ "f2bf9048bef64cc5b6d5110154e33c81",
82
+ "on",
83
+ good_schedules=["Badkamer"],
84
+ single=True,
85
+ )
86
+ result_2 = await self.tinker_thermostat_schedule(
87
+ smile,
88
+ "f2bf9048bef64cc5b6d5110154e33c81",
89
+ "on",
90
+ good_schedules=["Badkamer"],
91
+ single=True,
92
+ )
93
+ assert result_1 and result_2
94
+
95
+ switch_change = await self.tinker_switch(
96
+ smile,
97
+ "e8ef2a01ed3b4139a53bf749204fe6b4",
98
+ ["2568cc4b9c1e401495d4741a5f89bee1", "29542b2b6a6a4169acecc15c72a599b8"],
99
+ )
100
+ assert switch_change
101
+ switch_change = await self.tinker_switch(
102
+ smile, "056ee145a816487eaa69243c3280f8bf", model="dhw_cm_switch"
103
+ )
104
+ assert switch_change
105
+ switch_change = await self.tinker_switch(
106
+ smile, "854f8a9b0e7e425db97f1f110e1ce4b3", model="lock"
107
+ )
108
+ assert switch_change
109
+ switch_change = await self.tinker_switch(
110
+ smile, "2568cc4b9c1e401495d4741a5f89bee1"
111
+ )
112
+ assert not switch_change
113
+
114
+ tinkered = await self.tinker_gateway_mode(smile)
115
+ assert not tinkered
116
+
117
+ tinkered = await self.tinker_regulation_mode(smile)
118
+ assert not tinkered
119
+
120
+ tinkered = await self.tinker_max_boiler_temp(smile)
121
+ assert not tinkered
122
+
123
+ # Now change some data and change directory reading xml from
124
+ # emulating reading newer dataset after an update_interval
125
+ testdata_updated = self.load_testdata(
126
+ SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
127
+ )
128
+ self.smile_setup = "updated/adam_plus_anna_new"
129
+ await self.device_test(
130
+ smile, "2022-01-16 00:00:01", testdata_updated, initialize=False
131
+ )
132
+
133
+ # Simulate receiving no xml-data after a requesting a reboot of the gateway
134
+ self.smile_setup = "reboot/adam_plus_anna_new"
135
+ try:
136
+ await self.device_test(smile, initialize=False)
137
+ except pw_exceptions.PlugwiseError:
138
+ _LOGGER.debug("Receiving no data after a reboot is properly handled")
139
+
140
+ # Simulate receiving xml-data with <error>
141
+ self.smile_setup = "error/adam_plus_anna_new"
142
+ try:
143
+ await self.device_test(smile, initialize=False)
144
+ except pw_exceptions.ResponseError:
145
+ _LOGGER.debug("Receiving error-data from the Gateway")
146
+
147
+ await smile.close_connection()
148
+ await self.disconnect(server, client)
149
+
150
+ self.smile_setup = "adam_plus_anna_new"
151
+ testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
152
+ server, smile, client = await self.connect_wrapper(raise_timeout=True)
153
+ await self.device_test(smile, "2023-12-17 00:00:01", testdata, skip_testing=True)
154
+
155
+ tinkered = await self.tinker_max_boiler_temp(smile, unhappy=True)
156
+ assert tinkered
157
+
158
+ tinkered = await self.tinker_gateway_mode(smile, unhappy=True)
159
+ assert tinkered
160
+
161
+ tinkered = await self.tinker_regulation_mode(smile, unhappy=True)
162
+ assert tinkered
163
+
164
+ await smile.close_connection()
165
+ await self.disconnect(server, client)
18
166
 
19
167
  @pytest.mark.asyncio
20
168
  async def test_connect_adam_zone_per_device(self):
@@ -38,7 +186,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
38
186
  assert smile._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE
39
187
  assert smile._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA
40
188
  assert smile._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA
41
- assert self.device_items == 315
189
+ assert self.device_items == 323
42
190
 
43
191
  assert "af82e4ccf9c548528166d38e560662a4" in self.notifications
44
192
  await smile.delete_notification()
@@ -116,7 +264,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
116
264
  assert smile._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE
117
265
  assert smile._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA
118
266
  assert smile._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA
119
- assert self.device_items == 315
267
+ assert self.device_items == 323
120
268
 
121
269
  assert "af82e4ccf9c548528166d38e560662a4" in self.notifications
122
270
 
@@ -154,7 +302,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
154
302
  assert smile._last_active["a562019b0b1f47a4bde8ebe3dbe3e8a9"] == WERKDAG_SCHEMA
155
303
  assert smile._last_active["8cf650a4c10c44819e426bed406aec34"] == WERKDAG_SCHEMA
156
304
  assert smile._last_active["5cc21042f87f4b4c94ccb5537c47a53f"] == WERKDAG_SCHEMA
157
- assert self.device_items == 415
305
+ assert self.device_items == 417
158
306
 
159
307
  await smile.close_connection()
160
308
  await self.disconnect(server, client)
@@ -230,154 +378,6 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
230
378
  await smile.close_connection()
231
379
  await self.disconnect(server, client)
232
380
 
233
- @pytest.mark.asyncio
234
- async def test_connect_adam_plus_anna_new(self):
235
- """Test extended Adam (firmware 3.8) with Anna and a switch-group setup."""
236
- self.smile_setup = "adam_plus_anna_new"
237
-
238
- testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
239
- server, smile, client = await self.connect_wrapper()
240
- assert smile.smile_hostname == "smile000000"
241
-
242
- self.validate_test_basics(
243
- _LOGGER,
244
- smile,
245
- smile_type=None,
246
- smile_version="3.7.8",
247
- )
248
-
249
- await self.device_test(smile, "2023-12-17 00:00:01", testdata)
250
- assert smile.gateway_id == "da224107914542988a88561b4452b0f6"
251
- assert smile._last_active["f2bf9048bef64cc5b6d5110154e33c81"] == "Weekschema"
252
- assert smile._last_active["f871b8c4d63549319221e294e4f88074"] == "Badkamer"
253
- assert self.device_items == 147
254
- assert self.device_list == [
255
- "da224107914542988a88561b4452b0f6",
256
- "056ee145a816487eaa69243c3280f8bf",
257
- "67d73d0bd469422db25a618a5fb8eeb0",
258
- "e2f4322d57924fa090fbbc48b3a140dc",
259
- "29542b2b6a6a4169acecc15c72a599b8",
260
- "ad4838d7d35c4d6ea796ee12ae5aedf8",
261
- "1772a4ea304041adb83f357b751341ff",
262
- "854f8a9b0e7e425db97f1f110e1ce4b3",
263
- "2568cc4b9c1e401495d4741a5f89bee1",
264
- "e8ef2a01ed3b4139a53bf749204fe6b4",
265
- ]
266
-
267
- result = await self.tinker_thermostat(
268
- smile,
269
- "f2bf9048bef64cc5b6d5110154e33c81",
270
- good_schedules=["Weekschema", "Badkamer", "Test"],
271
- )
272
- assert result
273
-
274
- # Special test-case for turning a schedule off based on only the location id.
275
- await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "off")
276
-
277
- # Special test-case for turning a schedule off for a location via the option "off".
278
- await smile.set_schedule_state("f2bf9048bef64cc5b6d5110154e33c81", "on", "off")
279
-
280
- # bad schedule-state test
281
- result = await self.tinker_thermostat_schedule(
282
- smile,
283
- "f2bf9048bef64cc5b6d5110154e33c81",
284
- "bad",
285
- good_schedules=["Badkamer"],
286
- single=True,
287
- )
288
- assert result
289
-
290
- smile._schedule_old_states["f2bf9048bef64cc5b6d5110154e33c81"][
291
- "Badkamer"
292
- ] = "off"
293
- result_1 = await self.tinker_thermostat_schedule(
294
- smile,
295
- "f2bf9048bef64cc5b6d5110154e33c81",
296
- "on",
297
- good_schedules=["Badkamer"],
298
- single=True,
299
- )
300
- result_2 = await self.tinker_thermostat_schedule(
301
- smile,
302
- "f2bf9048bef64cc5b6d5110154e33c81",
303
- "on",
304
- good_schedules=["Badkamer"],
305
- single=True,
306
- )
307
- assert result_1 and result_2
308
-
309
- switch_change = await self.tinker_switch(
310
- smile,
311
- "e8ef2a01ed3b4139a53bf749204fe6b4",
312
- ["2568cc4b9c1e401495d4741a5f89bee1", "29542b2b6a6a4169acecc15c72a599b8"],
313
- )
314
- assert switch_change
315
- switch_change = await self.tinker_switch(
316
- smile, "056ee145a816487eaa69243c3280f8bf", model="dhw_cm_switch"
317
- )
318
- assert switch_change
319
- switch_change = await self.tinker_switch(
320
- smile, "854f8a9b0e7e425db97f1f110e1ce4b3", model="lock"
321
- )
322
- assert switch_change
323
- switch_change = await self.tinker_switch(
324
- smile, "2568cc4b9c1e401495d4741a5f89bee1"
325
- )
326
- assert not switch_change
327
-
328
- tinkered = await self.tinker_gateway_mode(smile)
329
- assert not tinkered
330
-
331
- tinkered = await self.tinker_regulation_mode(smile)
332
- assert not tinkered
333
-
334
- tinkered = await self.tinker_max_boiler_temp(smile)
335
- assert not tinkered
336
-
337
- # Now change some data and change directory reading xml from
338
- # emulating reading newer dataset after an update_interval
339
- testdata_updated = self.load_testdata(
340
- SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
341
- )
342
- self.smile_setup = "updated/adam_plus_anna_new"
343
- await self.device_test(
344
- smile, "2022-01-16 00:00:01", testdata_updated, initialize=False
345
- )
346
-
347
- # Simulate receiving no xml-data after a requesting a reboot of the gateway
348
- self.smile_setup = "reboot/adam_plus_anna_new"
349
- try:
350
- await self.device_test(smile, initialize=False)
351
- except pw_exceptions.PlugwiseError:
352
- _LOGGER.debug("Receiving no data after a reboot is properly handled")
353
-
354
- # Simulate receiving xml-data with <error>
355
- self.smile_setup = "error/adam_plus_anna_new"
356
- try:
357
- await self.device_test(smile, initialize=False)
358
- except pw_exceptions.ResponseError:
359
- _LOGGER.debug("Receiving error-data from the Gateway")
360
-
361
- await smile.close_connection()
362
- await self.disconnect(server, client)
363
-
364
- self.smile_setup = "adam_plus_anna_new"
365
- testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
366
- server, smile, client = await self.connect_wrapper(raise_timeout=True)
367
- await self.device_test(smile, "2023-12-17 00:00:01", testdata, skip_testing=True)
368
-
369
- tinkered = await self.tinker_max_boiler_temp(smile, unhappy=True)
370
- assert tinkered
371
-
372
- tinkered = await self.tinker_gateway_mode(smile, unhappy=True)
373
- assert tinkered
374
-
375
- tinkered = await self.tinker_regulation_mode(smile, unhappy=True)
376
- assert tinkered
377
-
378
- await smile.close_connection()
379
- await self.disconnect(server, client)
380
-
381
381
  @pytest.mark.asyncio
382
382
  async def test_adam_plus_jip(self):
383
383
  """Test Adam with Jip setup."""
@@ -392,7 +392,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
392
392
  assert smile._last_active["06aecb3d00354375924f50c47af36bd2"] is None
393
393
  assert smile._last_active["d27aede973b54be484f6842d1b2802ad"] is None
394
394
  assert smile._last_active["13228dab8ce04617af318a2888b3c548"] is None
395
- assert self.device_items == 213
395
+ assert self.device_items == 217
396
396
 
397
397
  # Negative test
398
398
  result = await self.tinker_thermostat(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes