plugwise 1.6.2__tar.gz → 1.6.3__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.6.2 → plugwise-1.6.3}/PKG-INFO +1 -1
  2. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/data.py +19 -18
  3. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/helper.py +7 -3
  4. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/smile.py +2 -0
  5. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise.egg-info/PKG-INFO +1 -1
  6. {plugwise-1.6.2 → plugwise-1.6.3}/pyproject.toml +1 -1
  7. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_adam.py +2 -0
  8. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_anna.py +30 -0
  9. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_init.py +12 -4
  10. {plugwise-1.6.2 → plugwise-1.6.3}/LICENSE +0 -0
  11. {plugwise-1.6.2 → plugwise-1.6.3}/README.md +0 -0
  12. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/__init__.py +0 -0
  13. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/common.py +0 -0
  14. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/constants.py +0 -0
  15. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/exceptions.py +0 -0
  16. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/legacy/data.py +0 -0
  17. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/legacy/helper.py +0 -0
  18. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/legacy/smile.py +0 -0
  19. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/py.typed +0 -0
  20. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise/util.py +0 -0
  21. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise.egg-info/SOURCES.txt +0 -0
  22. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise.egg-info/dependency_links.txt +0 -0
  23. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise.egg-info/requires.txt +0 -0
  24. {plugwise-1.6.2 → plugwise-1.6.3}/plugwise.egg-info/top_level.txt +0 -0
  25. {plugwise-1.6.2 → plugwise-1.6.3}/setup.cfg +0 -0
  26. {plugwise-1.6.2 → plugwise-1.6.3}/setup.py +0 -0
  27. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_generic.py +0 -0
  28. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_legacy_anna.py +0 -0
  29. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_legacy_generic.py +0 -0
  30. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_legacy_p1.py +0 -0
  31. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_legacy_stretch.py +0 -0
  32. {plugwise-1.6.2 → plugwise-1.6.3}/tests/test_p1.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: plugwise
3
- Version: 1.6.2
3
+ Version: 1.6.3
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
@@ -198,7 +198,8 @@ class SmileData(SmileHelper):
198
198
  # Switching groups data
199
199
  self._entity_switching_group(entity, data)
200
200
  # Adam data
201
- self._get_adam_data(entity, data)
201
+ if self.smile(ADAM):
202
+ self._get_adam_data(entity, data)
202
203
 
203
204
  # Thermostat data for Anna (presets, temperatures etc)
204
205
  if self.smile(ANNA) and entity["dev_class"] == "thermostat":
@@ -225,26 +226,26 @@ class SmileData(SmileHelper):
225
226
  """Helper-function for _get_entity_data().
226
227
 
227
228
  Determine Adam heating-status for on-off heating via valves,
228
- available regulations_modes and thermostat control_states.
229
+ available regulations_modes and thermostat control_states,
230
+ and add missing cooling_enabled when required.
229
231
  """
230
- if self.smile(ADAM):
232
+ if entity["dev_class"] == "heater_central":
231
233
  # Indicate heating_state based on valves being open in case of city-provided heating
232
- if (
233
- entity["dev_class"] == "heater_central"
234
- and self._on_off_device
235
- and isinstance(self._heating_valves(), int)
236
- ):
234
+ if self._on_off_device and isinstance(self._heating_valves(), int):
237
235
  data["binary_sensors"]["heating_state"] = self._heating_valves() != 0
238
-
239
- # Show the allowed regulation_modes and gateway_modes
240
- if entity["dev_class"] == "gateway":
241
- if self._reg_allowed_modes:
242
- data["regulation_modes"] = self._reg_allowed_modes
243
- self._count += 1
244
- if self._gw_allowed_modes:
245
- data["gateway_modes"] = self._gw_allowed_modes
246
- self._count += 1
247
-
236
+ # Add cooling_enabled binary_sensor
237
+ if "binary_sensors" in data:
238
+ if "cooling_enabled" not in data["binary_sensors"] and self._cooling_present:
239
+ data["binary_sensors"]["cooling_enabled"] = self._cooling_enabled
240
+
241
+ # Show the allowed regulation_modes and gateway_modes
242
+ if entity["dev_class"] == "gateway":
243
+ if self._reg_allowed_modes:
244
+ data["regulation_modes"] = self._reg_allowed_modes
245
+ self._count += 1
246
+ if self._gw_allowed_modes:
247
+ data["gateway_modes"] = self._gw_allowed_modes
248
+ self._count += 1
248
249
 
249
250
  def _climate_data(
250
251
  self,
@@ -798,7 +798,9 @@ class SmileHelper(SmileCommon):
798
798
  # Techneco Elga has cooling-capability
799
799
  self._cooling_present = True
800
800
  data["model"] = "Generic heater/cooler"
801
- self._cooling_enabled = data["elga_status_code"] in (8, 9)
801
+ # Cooling_enabled in xml does NOT show the correct status!
802
+ # Setting it specifically:
803
+ self._cooling_enabled = data["binary_sensors"]["cooling_enabled"] = data["elga_status_code"] in (8, 9)
802
804
  data["binary_sensors"]["cooling_state"] = self._cooling_active = (
803
805
  data["elga_status_code"] == 8
804
806
  )
@@ -812,11 +814,13 @@ class SmileHelper(SmileCommon):
812
814
 
813
815
  def _update_loria_cooling(self, data: GwEntityData) -> None:
814
816
  """Loria/Thermastage: base cooling-related on cooling_state and modulation_level."""
815
- self._cooling_enabled = data["binary_sensors"]["cooling_state"]
817
+ # For Loria/Thermastage it's not clear if cooling_enabled in xml shows the correct status,
818
+ # setting it specifically:
819
+ self._cooling_enabled = data["binary_sensors"]["cooling_enabled"] = data["binary_sensors"]["cooling_state"]
816
820
  self._cooling_active = data["sensors"]["modulation_level"] == 100
817
821
  # For Loria the above does not work (pw-beta issue #301)
818
822
  if "cooling_ena_switch" in data["switches"]:
819
- self._cooling_enabled = data["switches"]["cooling_ena_switch"]
823
+ self._cooling_enabled = data["binary_sensors"]["cooling_enabled"] = data["switches"]["cooling_ena_switch"]
820
824
  self._cooling_active = data["binary_sensors"]["cooling_state"]
821
825
 
822
826
  def _cleanup_data(self, data: GwEntityData) -> None:
@@ -131,6 +131,8 @@ class SmileAPI(SmileData):
131
131
  try:
132
132
  await self.full_xml_update()
133
133
  self.get_all_gateway_entities()
134
+ # Set self._cooling_enabled -required for set_temperature,
135
+ #also, check for a failed data-retrieval
134
136
  if "heater_id" in self.gw_data:
135
137
  heat_cooler = self.gw_entities[self.gw_data["heater_id"]]
136
138
  if (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: plugwise
3
- Version: 1.6.2
3
+ Version: 1.6.3
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.6.2"
7
+ version = "1.6.3"
8
8
  license = {file = "LICENSE"}
9
9
  description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
10
10
  readme = "README.md"
@@ -320,6 +320,8 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
320
320
  assert smile._last_active["8cf650a4c10c44819e426bed406aec34"] == WERKDAG_SCHEMA
321
321
  assert smile._last_active["5cc21042f87f4b4c94ccb5537c47a53f"] == WERKDAG_SCHEMA
322
322
  assert self.entity_items == 497
323
+ assert self.cooling_present
324
+ assert self._cooling_enabled
323
325
 
324
326
  await smile.close_connection()
325
327
  await self.disconnect(server, client)
@@ -205,6 +205,7 @@ class TestPlugwiseAnna(TestPlugwise): # pylint: disable=attribute-defined-outsi
205
205
  good_schedules=[
206
206
  "standaard",
207
207
  ],
208
+ fail_cooling=True,
208
209
  )
209
210
  _LOGGER.debug(
210
211
  "ERROR raised setting good schedule standaard: %s", exc.value
@@ -261,6 +262,7 @@ class TestPlugwiseAnna(TestPlugwise): # pylint: disable=attribute-defined-outsi
261
262
  good_schedules=[
262
263
  "standaard",
263
264
  ],
265
+ fail_cooling=True,
264
266
  )
265
267
  _LOGGER.debug(
266
268
  "ERROR raised good schedule to standaard: %s", exc.value
@@ -407,6 +409,33 @@ class TestPlugwiseAnna(TestPlugwise): # pylint: disable=attribute-defined-outsi
407
409
  assert self._cooling_enabled
408
410
  assert self._cooling_active
409
411
 
412
+ result = await self.tinker_thermostat(
413
+ smile,
414
+ "d3ce834534114348be628b61b26d9220",
415
+ good_schedules=["Thermostat schedule"],
416
+ )
417
+ assert result
418
+
419
+ # Simulate a change of season: from cooling to heating after an update_interval
420
+ testdata_updated = self.load_testdata(
421
+ SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
422
+ )
423
+
424
+ self.smile_setup = "updated/anna_elga_2_switch_heating"
425
+ await self.device_test(
426
+ smile, "2020-04-05 00:00:01", testdata_updated, initialize=False
427
+ )
428
+ assert self.cooling_present
429
+ assert not self._cooling_enabled
430
+ assert not self._cooling_active
431
+
432
+ result = await self.tinker_thermostat(
433
+ smile,
434
+ "d3ce834534114348be628b61b26d9220",
435
+ good_schedules=["Thermostat schedule"],
436
+ )
437
+ assert result
438
+
410
439
  await smile.close_connection()
411
440
  await self.disconnect(server, client)
412
441
 
@@ -445,6 +474,7 @@ class TestPlugwiseAnna(TestPlugwise): # pylint: disable=attribute-defined-outsi
445
474
  good_schedules=[
446
475
  "Winter",
447
476
  ],
477
+ fail_cooling=True,
448
478
  )
449
479
  _LOGGER.debug(
450
480
  "ERROR raised setting to schedule Winter: %s", exc.value
@@ -704,14 +704,20 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
704
704
 
705
705
  @pytest.mark.asyncio
706
706
  async def tinker_thermostat_temp(
707
- self, smile, loc_id, block_cooling=False, unhappy=False
707
+ self, smile, loc_id, block_cooling=False, fail_cooling=False, unhappy=False
708
708
  ):
709
709
  """Toggle temperature to test functionality."""
710
710
  _LOGGER.info("Asserting modifying settings in location (%s):", loc_id)
711
711
  tinker_temp_passed = False
712
712
  test_temp = {"setpoint": 22.9}
713
713
  if self.cooling_present and not block_cooling:
714
- test_temp = {"setpoint_low": 19.5, "setpoint_high": 23.5}
714
+ if smile.smile_name == "Smile Anna":
715
+ if self._cooling_enabled:
716
+ test_temp = {"setpoint_low": 4.0, "setpoint_high": 23.0}
717
+ else:
718
+ test_temp = {"setpoint_low": 19.0, "setpoint_high": 30.0}
719
+ if fail_cooling:
720
+ test_temp = {"setpoint_low": 19.0, "setpoint_high": 23.0}
715
721
  _LOGGER.info("- Adjusting temperature to %s", test_temp)
716
722
  try:
717
723
  await smile.set_temperature(loc_id, test_temp)
@@ -826,6 +832,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
826
832
  good_schedules=None,
827
833
  single=False,
828
834
  block_cooling=False,
835
+ fail_cooling=False,
829
836
  unhappy=False,
830
837
  ):
831
838
  """Toggle various climate settings to test functionality."""
@@ -833,7 +840,7 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
833
840
  good_schedules = ["Weekschema"]
834
841
 
835
842
  result_1 = await self.tinker_thermostat_temp(
836
- smile, loc_id, block_cooling, unhappy
843
+ smile, loc_id, block_cooling, fail_cooling, unhappy
837
844
  )
838
845
  result_2 = await self.tinker_thermostat_preset(smile, loc_id, unhappy)
839
846
  if smile._schedule_old_states != {}:
@@ -858,11 +865,12 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
858
865
  smile,
859
866
  schedule_on=True,
860
867
  block_cooling=False,
868
+ fail_cooling=False,
861
869
  unhappy=False,
862
870
  ):
863
871
  """Toggle various climate settings to test functionality."""
864
872
  result_1 = await self.tinker_thermostat_temp(
865
- smile, "dummy", block_cooling, unhappy
873
+ smile, "dummy", block_cooling, fail_cooling, unhappy
866
874
  )
867
875
  result_2 = await self.tinker_thermostat_preset(smile, None, unhappy)
868
876
  result_3 = await self.tinker_legacy_thermostat_schedule(smile, unhappy)
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
File without changes