plugwise 1.6.0__tar.gz → 1.6.2__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.
- {plugwise-1.6.0 → plugwise-1.6.2}/PKG-INFO +3 -2
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/__init__.py +1 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/constants.py +2 -1
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/data.py +10 -3
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/helper.py +18 -4
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/smile.py +2 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise.egg-info/PKG-INFO +3 -2
- {plugwise-1.6.0 → plugwise-1.6.2}/pyproject.toml +6 -5
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_adam.py +18 -4
- {plugwise-1.6.0 → plugwise-1.6.2}/LICENSE +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/README.md +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/common.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/exceptions.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/legacy/data.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/legacy/helper.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/legacy/smile.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/py.typed +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise/util.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise.egg-info/SOURCES.txt +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise.egg-info/dependency_links.txt +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise.egg-info/requires.txt +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/plugwise.egg-info/top_level.txt +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/setup.cfg +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/setup.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_anna.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_generic.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_init.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_legacy_anna.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_legacy_generic.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_legacy_p1.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_legacy_stretch.py +0 -0
- {plugwise-1.6.0 → plugwise-1.6.2}/tests/test_p1.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plugwise
|
3
|
-
Version: 1.6.
|
3
|
+
Version: 1.6.2
|
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
|
@@ -36,8 +36,9 @@ Classifier: Intended Audience :: Developers
|
|
36
36
|
Classifier: License :: OSI Approved :: MIT License
|
37
37
|
Classifier: Operating System :: OS Independent
|
38
38
|
Classifier: Programming Language :: Python :: 3.12
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
39
40
|
Classifier: Topic :: Home Automation
|
40
|
-
Requires-Python: >=3.
|
41
|
+
Requires-Python: >=3.12.0
|
41
42
|
Description-Content-Type: text/markdown
|
42
43
|
License-File: LICENSE
|
43
44
|
Requires-Dist: aiohttp
|
@@ -196,6 +196,7 @@ ZONE_MEASUREMENTS: Final[dict[str, DATA | UOM]] = {
|
|
196
196
|
"electricity_produced": UOM(POWER_WATT),
|
197
197
|
"relay": UOM(NONE),
|
198
198
|
"temperature": UOM(TEMP_CELSIUS), # HA Core thermostat current_temperature
|
199
|
+
"thermostat": DATA("setpoint", TEMP_CELSIUS), # HA Core thermostat setpoint
|
199
200
|
}
|
200
201
|
|
201
202
|
# Literals
|
@@ -566,7 +567,7 @@ class GwEntityData(TypedDict, total=False):
|
|
566
567
|
|
567
568
|
climate_mode: str
|
568
569
|
# Extra for Adam Master Thermostats
|
569
|
-
control_state: str
|
570
|
+
control_state: str
|
570
571
|
|
571
572
|
# Dict-types
|
572
573
|
binary_sensors: SmileBinarySensors
|
@@ -160,9 +160,16 @@ class SmileData(SmileHelper):
|
|
160
160
|
"""
|
161
161
|
zone = self._zones[loc_id]
|
162
162
|
data = self._get_zone_data(loc_id)
|
163
|
-
if ctrl_state := self._control_state(loc_id):
|
164
|
-
|
165
|
-
|
163
|
+
if ctrl_state := self._control_state(data, loc_id):
|
164
|
+
if str(ctrl_state) in ("cooling", "heating", "preheating"):
|
165
|
+
data["control_state"] = str(ctrl_state)
|
166
|
+
self._count += 1
|
167
|
+
if str(ctrl_state) == "off":
|
168
|
+
data["control_state"] = "idle"
|
169
|
+
self._count += 1
|
170
|
+
|
171
|
+
data["sensors"].pop("setpoint") # remove, only used in _control_state()
|
172
|
+
self._count -= 1
|
166
173
|
|
167
174
|
# Thermostat data (presets, temperatures etc)
|
168
175
|
self._climate_data(loc_id, zone, data)
|
@@ -64,7 +64,7 @@ from dateutil import tz
|
|
64
64
|
from dateutil.parser import parse
|
65
65
|
from defusedxml import ElementTree as etree
|
66
66
|
from munch import Munch
|
67
|
-
from packaging
|
67
|
+
from packaging import version
|
68
68
|
|
69
69
|
|
70
70
|
class SmileComm:
|
@@ -252,13 +252,14 @@ class SmileHelper(SmileCommon):
|
|
252
252
|
self.gateway_id: str
|
253
253
|
self.gw_data: GatewayData = {}
|
254
254
|
self.gw_entities: dict[str, GwEntityData] = {}
|
255
|
-
self.smile_fw_version: Version | None
|
255
|
+
self.smile_fw_version: version.Version | None
|
256
256
|
self.smile_hw_version: str | None
|
257
257
|
self.smile_mac_address: str | None
|
258
258
|
self.smile_model: str
|
259
259
|
self.smile_model_id: str | None
|
260
260
|
self.smile_name: str
|
261
261
|
self.smile_type: str
|
262
|
+
self.smile_version: version.Version | None
|
262
263
|
self.smile_zigbee_mac_address: str | None
|
263
264
|
self.therms_with_offset_func: list[str] = []
|
264
265
|
self._zones: dict[str, GwEntityData] = {}
|
@@ -917,7 +918,7 @@ class SmileHelper(SmileCommon):
|
|
917
918
|
else:
|
918
919
|
thermo_loc["secondary"].append(appliance_id)
|
919
920
|
|
920
|
-
def _control_state(self, loc_id: str) -> str | bool:
|
921
|
+
def _control_state(self, data: GwEntityData, loc_id: str) -> str | bool:
|
921
922
|
"""Helper-function for _get_adam_data().
|
922
923
|
|
923
924
|
Adam: find the thermostat control_state of a location, from DOMAIN_OBJECTS.
|
@@ -930,7 +931,20 @@ class SmileHelper(SmileCommon):
|
|
930
931
|
if (ctrl_state := location.find(locator)) is not None:
|
931
932
|
return str(ctrl_state.text)
|
932
933
|
|
933
|
-
|
934
|
+
# Handle missing control_state in regulation_mode off for firmware >= 3.2.0 (issue #776)
|
935
|
+
# In newer firmware versions, default to "off" when control_state is not present
|
936
|
+
if self.smile_version is not None:
|
937
|
+
if self.smile_version >= version.parse("3.2.0"):
|
938
|
+
return "off"
|
939
|
+
|
940
|
+
# Older Adam firmware does not have the control_state xml-key
|
941
|
+
# Work around this by comparing the reported temperature and setpoint for a location
|
942
|
+
setpoint = data["sensors"]["setpoint"]
|
943
|
+
temperature = data["sensors"]["temperature"]
|
944
|
+
# No cooling available in older firmware
|
945
|
+
return "heating" if temperature < setpoint else "off"
|
946
|
+
|
947
|
+
return False # pragma: no cover
|
934
948
|
|
935
949
|
def _heating_valves(self) -> int | bool:
|
936
950
|
"""Helper-function for smile.py: _get_adam_data().
|
@@ -66,6 +66,7 @@ class SmileAPI(SmileData):
|
|
66
66
|
smile_model_id: str | None,
|
67
67
|
smile_name: str,
|
68
68
|
smile_type: str,
|
69
|
+
smile_version: Version | None,
|
69
70
|
port: int = DEFAULT_PORT,
|
70
71
|
username: str = DEFAULT_USERNAME,
|
71
72
|
) -> None:
|
@@ -90,6 +91,7 @@ class SmileAPI(SmileData):
|
|
90
91
|
self.smile_model_id = smile_model_id
|
91
92
|
self.smile_name = smile_name
|
92
93
|
self.smile_type = smile_type
|
94
|
+
self.smile_version = smile_version
|
93
95
|
SmileData.__init__(self)
|
94
96
|
|
95
97
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plugwise
|
3
|
-
Version: 1.6.
|
3
|
+
Version: 1.6.2
|
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
|
@@ -36,8 +36,9 @@ Classifier: Intended Audience :: Developers
|
|
36
36
|
Classifier: License :: OSI Approved :: MIT License
|
37
37
|
Classifier: Operating System :: OS Independent
|
38
38
|
Classifier: Programming Language :: Python :: 3.12
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
39
40
|
Classifier: Topic :: Home Automation
|
40
|
-
Requires-Python: >=3.
|
41
|
+
Requires-Python: >=3.12.0
|
41
42
|
Description-Content-Type: text/markdown
|
42
43
|
License-File: LICENSE
|
43
44
|
Requires-Dist: aiohttp
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "plugwise"
|
7
|
-
version = "1.6.
|
7
|
+
version = "1.6.2"
|
8
8
|
license = {file = "LICENSE"}
|
9
9
|
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
|
10
10
|
readme = "README.md"
|
@@ -15,6 +15,7 @@ classifiers = [
|
|
15
15
|
"License :: OSI Approved :: MIT License",
|
16
16
|
"Operating System :: OS Independent",
|
17
17
|
"Programming Language :: Python :: 3.12",
|
18
|
+
"Programming Language :: Python :: 3.13",
|
18
19
|
"Topic :: Home Automation",
|
19
20
|
]
|
20
21
|
authors = [
|
@@ -24,7 +25,7 @@ maintainers = [
|
|
24
25
|
{ name = "bouwew"},
|
25
26
|
{ name = "CoMPaTech" }
|
26
27
|
]
|
27
|
-
requires-python = ">=3.
|
28
|
+
requires-python = ">=3.12.0"
|
28
29
|
dependencies = [
|
29
30
|
"aiohttp",
|
30
31
|
"defusedxml",
|
@@ -47,7 +48,7 @@ include-package-data = true
|
|
47
48
|
include = ["plugwise*"]
|
48
49
|
|
49
50
|
[tool.black]
|
50
|
-
target-version = ["
|
51
|
+
target-version = ["py313"]
|
51
52
|
exclude = 'generated'
|
52
53
|
|
53
54
|
[tool.isort]
|
@@ -185,7 +186,7 @@ norecursedirs = [
|
|
185
186
|
]
|
186
187
|
|
187
188
|
[tool.mypy]
|
188
|
-
python_version = "3.
|
189
|
+
python_version = "3.13"
|
189
190
|
show_error_codes = true
|
190
191
|
follow_imports = "silent"
|
191
192
|
ignore_missing_imports = true
|
@@ -215,7 +216,7 @@ omit= [
|
|
215
216
|
]
|
216
217
|
|
217
218
|
[tool.ruff]
|
218
|
-
target-version = "
|
219
|
+
target-version = "py313"
|
219
220
|
|
220
221
|
lint.select = [
|
221
222
|
"B002", # Python does not support the unary prefix increment
|
@@ -18,7 +18,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
18
18
|
|
19
19
|
@pytest.mark.asyncio
|
20
20
|
async def test_connect_adam_plus_anna_new(self):
|
21
|
-
"""Test extended Adam (firmware 3.
|
21
|
+
"""Test extended Adam (firmware 3.7) with Anna and a switch-group setup."""
|
22
22
|
self.smile_setup = "adam_plus_anna_new"
|
23
23
|
|
24
24
|
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
|
@@ -167,6 +167,20 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
167
167
|
await smile.close_connection()
|
168
168
|
await self.disconnect(server, client)
|
169
169
|
|
170
|
+
@pytest.mark.asyncio
|
171
|
+
async def test_connect_adam_plus_anna_new_regulation_off(self):
|
172
|
+
"""Test regultaion_mode off with control_state key missing for Adam."""
|
173
|
+
self.smile_setup = "adam_plus_anna_new_regulation_off"
|
174
|
+
|
175
|
+
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
|
176
|
+
server, smile, client = await self.connect_wrapper()
|
177
|
+
assert smile.smile_hostname == "smile000000"
|
178
|
+
|
179
|
+
await self.device_test(smile, "2023-12-17 00:00:01", testdata)
|
180
|
+
|
181
|
+
await smile.close_connection()
|
182
|
+
await self.disconnect(server, client)
|
183
|
+
|
170
184
|
@pytest.mark.asyncio
|
171
185
|
async def test_connect_adam_zone_per_device(self):
|
172
186
|
"""Test an extensive setup of Adam with a zone per device."""
|
@@ -189,7 +203,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
189
203
|
assert smile._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE
|
190
204
|
assert smile._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA
|
191
205
|
assert smile._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA
|
192
|
-
assert self.entity_items ==
|
206
|
+
assert self.entity_items == 369
|
193
207
|
|
194
208
|
assert "af82e4ccf9c548528166d38e560662a4" in self.notifications
|
195
209
|
await smile.delete_notification()
|
@@ -267,7 +281,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
267
281
|
assert smile._last_active["82fa13f017d240daa0d0ea1775420f24"] == CV_JESSIE
|
268
282
|
assert smile._last_active["08963fec7c53423ca5680aa4cb502c63"] == BADKAMER_SCHEMA
|
269
283
|
assert smile._last_active["446ac08dd04d4eff8ac57489757b7314"] == BADKAMER_SCHEMA
|
270
|
-
assert self.entity_items ==
|
284
|
+
assert self.entity_items == 369
|
271
285
|
|
272
286
|
assert "af82e4ccf9c548528166d38e560662a4" in self.notifications
|
273
287
|
|
@@ -351,7 +365,7 @@ class TestPlugwiseAdam(TestPlugwise): # pylint: disable=attribute-defined-outsi
|
|
351
365
|
await self.device_test(smile, "2020-03-22 00:00:01", testdata)
|
352
366
|
assert smile.gateway_id == "b128b4bbbd1f47e9bf4d756e8fb5ee94"
|
353
367
|
assert smile._last_active["009490cc2f674ce6b576863fbb64f867"] == "Weekschema"
|
354
|
-
assert self.entity_items ==
|
368
|
+
assert self.entity_items == 80
|
355
369
|
assert "6fb89e35caeb4b1cb275184895202d84" in self.notifications
|
356
370
|
|
357
371
|
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
|
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
|
File without changes
|
File without changes
|