python-pooldose 0.6.6__tar.gz → 0.6.8__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.
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/PKG-INFO +6 -3
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/README.md +4 -2
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/pyproject.toml +6 -11
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/__init__.py +1 -1
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/__main__.py +4 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/client.py +11 -2
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/device_analyzer.py +4 -3
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/mappings/model_PDPR1H1HAR1V0_FW539224.json +12 -4
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/mock_client.py +5 -2
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/values/instant_values.py +9 -5
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/PKG-INFO +6 -3
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/requires.txt +1 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_client.py +1 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_instant_values.py +2 -1
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/LICENSE +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/setup.cfg +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/constants.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/mappings/__init__.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/mappings/mapping_info.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/mappings/model_PDPR1H1HAW100_FW539187.json +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/py.typed +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/request_handler.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/request_status.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/values/__init__.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/pooldose/values/static_values.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/SOURCES.txt +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/dependency_links.txt +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/entry_points.txt +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/top_level.txt +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_device_analyzer.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_device_analyzer_integration.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_mapping_info.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_request_handler.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_ssl_support.py +0 -0
- {python_pooldose-0.6.6 → python_pooldose-0.6.8}/tests/test_static_values.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-pooldose
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
4
4
|
Summary: Unoffical async Python client for SEKO PoolDose devices
|
|
5
5
|
Author-email: Lukas Maertin <pypi@lukas-maertin.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -11,6 +11,7 @@ Description-Content-Type: text/markdown
|
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Requires-Dist: aiohttp
|
|
13
13
|
Requires-Dist: aiofiles
|
|
14
|
+
Requires-Dist: getmac
|
|
14
15
|
Provides-Extra: dev
|
|
15
16
|
Requires-Dist: pytest; extra == "dev"
|
|
16
17
|
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
@@ -942,6 +943,8 @@ Data Classification:
|
|
|
942
943
|
|
|
943
944
|
For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
|
|
944
945
|
|
|
945
|
-
### Latest Release (0.6.
|
|
946
|
+
### Latest Release (0.6.8)
|
|
946
947
|
|
|
947
|
-
- **
|
|
948
|
+
- **Client**: Implemented alternate method to retrieve MAC address of device
|
|
949
|
+
- **Mapping**: Further fixes for PDPR1H1HAR1V0_FW539224
|
|
950
|
+
- **Values**: Added conversion for binary sensors
|
|
@@ -924,6 +924,8 @@ Data Classification:
|
|
|
924
924
|
|
|
925
925
|
For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
|
|
926
926
|
|
|
927
|
-
### Latest Release (0.6.
|
|
927
|
+
### Latest Release (0.6.8)
|
|
928
928
|
|
|
929
|
-
- **
|
|
929
|
+
- **Client**: Implemented alternate method to retrieve MAC address of device
|
|
930
|
+
- **Mapping**: Further fixes for PDPR1H1HAR1V0_FW539224
|
|
931
|
+
- **Values**: Added conversion for binary sensors
|
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
name = "python-pooldose"
|
|
3
3
|
dynamic = ["version"]
|
|
4
4
|
description = "Unoffical async Python client for SEKO PoolDose devices"
|
|
5
|
-
authors = [
|
|
6
|
-
{ name = "Lukas Maertin", email = "pypi@lukas-maertin.de" }
|
|
7
|
-
]
|
|
5
|
+
authors = [{ name = "Lukas Maertin", email = "pypi@lukas-maertin.de" }]
|
|
8
6
|
license = "MIT"
|
|
9
7
|
readme = "README.md"
|
|
10
8
|
requires-python = ">=3.11"
|
|
11
|
-
dependencies = [
|
|
12
|
-
"aiohttp",
|
|
13
|
-
"aiofiles"
|
|
14
|
-
]
|
|
9
|
+
dependencies = ["aiohttp", "aiofiles", "getmac"]
|
|
15
10
|
|
|
16
11
|
[project.urls]
|
|
17
12
|
Homepage = "https://github.com/lmaertin/python-pooldose"
|
|
@@ -28,10 +23,10 @@ build-backend = "setuptools.build_meta"
|
|
|
28
23
|
dev = ["pytest", "pytest-asyncio"]
|
|
29
24
|
|
|
30
25
|
[tool.setuptools]
|
|
31
|
-
package-dir = {"" = "src"}
|
|
26
|
+
package-dir = { "" = "src" }
|
|
32
27
|
|
|
33
28
|
[tool.setuptools.dynamic]
|
|
34
|
-
version = {attr = "pooldose.__version__"}
|
|
29
|
+
version = { attr = "pooldose.__version__" }
|
|
35
30
|
|
|
36
31
|
[tool.setuptools.packages.find]
|
|
37
32
|
where = ["src"]
|
|
@@ -67,7 +62,7 @@ module = "examples.*"
|
|
|
67
62
|
ignore_errors = true
|
|
68
63
|
|
|
69
64
|
[[tool.mypy.overrides]]
|
|
70
|
-
module = "tests.*"
|
|
65
|
+
module = "tests.*"
|
|
71
66
|
ignore_errors = true
|
|
72
67
|
|
|
73
68
|
# Strict typing for core public API modules
|
|
@@ -85,4 +80,4 @@ warn_return_any = false
|
|
|
85
80
|
[[tool.mypy.overrides]]
|
|
86
81
|
module = "pooldose.request_status"
|
|
87
82
|
disallow_untyped_defs = true
|
|
88
|
-
disallow_incomplete_defs = true
|
|
83
|
+
disallow_incomplete_defs = true
|
|
@@ -12,6 +12,8 @@ from pooldose.device_analyzer import DeviceAnalyzer
|
|
|
12
12
|
from pooldose.mock_client import MockPooldoseClient
|
|
13
13
|
from pooldose.request_handler import RequestHandler
|
|
14
14
|
|
|
15
|
+
# pylint: disable=line-too-long
|
|
16
|
+
|
|
15
17
|
# Import demo utilities if available
|
|
16
18
|
try:
|
|
17
19
|
from examples.demo_utils import (display_static_values,
|
|
@@ -25,6 +27,8 @@ except ImportError:
|
|
|
25
27
|
("Serial", static_values.sensor_serial_number),
|
|
26
28
|
("Model", static_values.sensor_model),
|
|
27
29
|
("Firmware", static_values.sensor_fw_version),
|
|
30
|
+
("IP", static_values.sensor_ip),
|
|
31
|
+
("MAC", static_values.sensor_mac)
|
|
28
32
|
]
|
|
29
33
|
print("\nDevice Information:")
|
|
30
34
|
for label, value in device_info:
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import logging
|
|
7
7
|
from typing import Any, Dict, Optional, Tuple
|
|
8
|
+
from getmac import get_mac_address
|
|
8
9
|
|
|
9
10
|
from pooldose.constants import get_default_device_info
|
|
10
11
|
from pooldose.mappings.mapping_info import MappingInfo
|
|
@@ -121,7 +122,7 @@ class PooldoseClient:
|
|
|
121
122
|
|
|
122
123
|
return RequestStatus.SUCCESS, result
|
|
123
124
|
|
|
124
|
-
async def _load_device_info(self) -> RequestStatus: # pylint: disable=too-many-branches
|
|
125
|
+
async def _load_device_info(self) -> RequestStatus: # pylint: disable=too-many-branches, too-many-statements
|
|
125
126
|
"""
|
|
126
127
|
Load device information from the request handler.
|
|
127
128
|
This method should be called after a successful connection.
|
|
@@ -164,7 +165,6 @@ class PooldoseClient:
|
|
|
164
165
|
_LOGGER.warning("Failed to fetch WiFi station info: %s", status)
|
|
165
166
|
else:
|
|
166
167
|
self.device_info["WIFI_SSID"] = wifi_station.get("SSID")
|
|
167
|
-
self.device_info["MAC"] = wifi_station.get("MAC")
|
|
168
168
|
self.device_info["IP"] = wifi_station.get("IP")
|
|
169
169
|
# Only include WiFi key if explicitly requested
|
|
170
170
|
if self._include_sensitive_data:
|
|
@@ -193,6 +193,15 @@ class PooldoseClient:
|
|
|
193
193
|
if self._include_sensitive_data:
|
|
194
194
|
_LOGGER.info("Included WiFi and AP keys (use include_sensitive_data=False to exclude)")
|
|
195
195
|
|
|
196
|
+
# MAC address via getmac library
|
|
197
|
+
if self.device_info["IP"]:
|
|
198
|
+
self.device_info["MAC"] = get_mac_address(ip=self.device_info["IP"])
|
|
199
|
+
if not self.device_info["MAC"]:
|
|
200
|
+
_LOGGER.warning("Failed to fetch MAC address via getmac library for IP: %s", self.device_info["IP"])
|
|
201
|
+
else:
|
|
202
|
+
_LOGGER.warning("IP address not set, cannot fetch MAC address via getmac library")
|
|
203
|
+
self.device_info["MAC"] = None
|
|
204
|
+
|
|
196
205
|
return RequestStatus.SUCCESS
|
|
197
206
|
|
|
198
207
|
@property
|
|
@@ -67,7 +67,7 @@ class DeviceAnalyzer:
|
|
|
67
67
|
if key in SKIP_KEYS:
|
|
68
68
|
continue
|
|
69
69
|
|
|
70
|
-
# Pattern: {MODEL}_{FW_CODE}_w_{SHORT_ID}
|
|
70
|
+
# Pattern: {MODEL}_{FW_CODE}_w_{SHORT_ID}
|
|
71
71
|
match = re.match(r"^([A-Z0-9]+)_(FW[A-Z0-9]+)_", key)
|
|
72
72
|
if match:
|
|
73
73
|
model = match.group(1)
|
|
@@ -390,8 +390,9 @@ class DeviceAnalyzer:
|
|
|
390
390
|
|
|
391
391
|
return detail_strings
|
|
392
392
|
|
|
393
|
-
def _print_footer(self, widgets: List[WidgetInfo],
|
|
394
|
-
|
|
393
|
+
def _print_footer(self, widgets: List[WidgetInfo],
|
|
394
|
+
filtered_widgets: List[WidgetInfo],
|
|
395
|
+
show_all: bool) -> None:
|
|
395
396
|
"""Print analysis footer."""
|
|
396
397
|
print(f"\n{'='*SEPARATOR_LENGTH}")
|
|
397
398
|
print("ANALYSIS COMPLETE")
|
|
@@ -60,8 +60,12 @@
|
|
|
60
60
|
"type": "sensor"
|
|
61
61
|
},
|
|
62
62
|
"pump_running": {
|
|
63
|
-
"key": "
|
|
64
|
-
"type": "binary_sensor"
|
|
63
|
+
"key": "w_1f1fng00q",
|
|
64
|
+
"type": "binary_sensor",
|
|
65
|
+
"conversion": {
|
|
66
|
+
"|PDPR1H1HAR1V0_FW539224_LABEL_w_1f1fng00q_OFF|": "F",
|
|
67
|
+
"|PDPR1H1HAR1V0_FW539224_LABEL_w_1f1fng00q_ON|": "O"
|
|
68
|
+
}
|
|
65
69
|
},
|
|
66
70
|
"ph_level_ok": {
|
|
67
71
|
"key": "w_1f0ioo093",
|
|
@@ -100,8 +104,12 @@
|
|
|
100
104
|
"type": "switch"
|
|
101
105
|
},
|
|
102
106
|
"pump_detection": {
|
|
103
|
-
"key": "
|
|
104
|
-
"type": "
|
|
107
|
+
"key": "w_1hn0vte5j",
|
|
108
|
+
"type": "binary_sensor",
|
|
109
|
+
"conversion": {
|
|
110
|
+
"|PDPR1H1HAR1V0_FW539224_LABEL_w_1hn0vte5j_DISABLED|": "F",
|
|
111
|
+
"|PDPR1H1HAR1V0_FW539224_LABEL_w_1hn0vte5j_ENABLED|": "O"
|
|
112
|
+
}
|
|
105
113
|
},
|
|
106
114
|
"water_meter_unit": {
|
|
107
115
|
"key": "w_1f3dfp59r",
|
|
@@ -109,8 +109,11 @@ class MockPooldoseClient:
|
|
|
109
109
|
"DEVICE_ID": self._device_key,
|
|
110
110
|
"MODEL": model or "MOCK_MODEL",
|
|
111
111
|
"MODEL_ID": model or "MOCK_MODEL",
|
|
112
|
-
"FW_CODE": (
|
|
113
|
-
|
|
112
|
+
"FW_CODE": (
|
|
113
|
+
fw_code.replace('FW', '')
|
|
114
|
+
if fw_code and fw_code.startswith('FW')
|
|
115
|
+
else fw_code or "MOCK_FW"
|
|
116
|
+
),
|
|
114
117
|
"API_VERSION": API_VERSION_SUPPORTED,
|
|
115
118
|
"IP": "127.0.0.1", # Mock IP
|
|
116
119
|
})
|
|
@@ -189,7 +189,7 @@ class InstantValues:
|
|
|
189
189
|
if entry_type == "sensor":
|
|
190
190
|
return self._process_sensor_value(raw_entry, attributes, name)
|
|
191
191
|
elif entry_type == "binary_sensor":
|
|
192
|
-
return self._process_binary_sensor_value(raw_entry, name)
|
|
192
|
+
return self._process_binary_sensor_value(raw_entry, attributes, name)
|
|
193
193
|
elif entry_type == "switch":
|
|
194
194
|
return self._process_switch_value(raw_entry, name)
|
|
195
195
|
elif entry_type == "number":
|
|
@@ -224,15 +224,19 @@ class InstantValues:
|
|
|
224
224
|
|
|
225
225
|
return (value, unit)
|
|
226
226
|
|
|
227
|
-
def _process_binary_sensor_value(self, raw_entry: Dict[str, Any], name: str) -> Union[bool, None]:
|
|
228
|
-
"""Process binary sensor value and return bool."""
|
|
227
|
+
def _process_binary_sensor_value(self, raw_entry: Dict[str, Any], attributes: Dict[str, Any], name: str) -> Union[bool, None]:
|
|
228
|
+
"""Process binary sensor value and return bool, with optional conversion mapping."""
|
|
229
229
|
if not isinstance(raw_entry, dict):
|
|
230
230
|
_LOGGER.warning("Invalid raw entry type for binary sensor '%s': expected dict, got %s", name, type(raw_entry))
|
|
231
231
|
return None
|
|
232
232
|
|
|
233
233
|
value = raw_entry.get("current")
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
|
|
235
|
+
# Apply conversion mapping if defined in mapping
|
|
236
|
+
if value is not None and "conversion" in attributes:
|
|
237
|
+
conversion = attributes["conversion"]
|
|
238
|
+
if isinstance(conversion, dict) and str(value) in conversion:
|
|
239
|
+
value = conversion[str(value)]
|
|
236
240
|
|
|
237
241
|
# Convert string values to boolean
|
|
238
242
|
if isinstance(value, str):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-pooldose
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
4
4
|
Summary: Unoffical async Python client for SEKO PoolDose devices
|
|
5
5
|
Author-email: Lukas Maertin <pypi@lukas-maertin.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -11,6 +11,7 @@ Description-Content-Type: text/markdown
|
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Requires-Dist: aiohttp
|
|
13
13
|
Requires-Dist: aiofiles
|
|
14
|
+
Requires-Dist: getmac
|
|
14
15
|
Provides-Extra: dev
|
|
15
16
|
Requires-Dist: pytest; extra == "dev"
|
|
16
17
|
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
@@ -942,6 +943,8 @@ Data Classification:
|
|
|
942
943
|
|
|
943
944
|
For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
|
|
944
945
|
|
|
945
|
-
### Latest Release (0.6.
|
|
946
|
+
### Latest Release (0.6.8)
|
|
946
947
|
|
|
947
|
-
- **
|
|
948
|
+
- **Client**: Implemented alternate method to retrieve MAC address of device
|
|
949
|
+
- **Mapping**: Further fixes for PDPR1H1HAR1V0_FW539224
|
|
950
|
+
- **Values**: Added conversion for binary sensors
|
|
@@ -8,6 +8,7 @@ from pooldose.request_status import RequestStatus
|
|
|
8
8
|
from pooldose.values.instant_values import InstantValues
|
|
9
9
|
from pooldose.values.static_values import StaticValues
|
|
10
10
|
|
|
11
|
+
# pylint: disable=line-too-long
|
|
11
12
|
|
|
12
13
|
class TestPooldoseClient:
|
|
13
14
|
"""Test PooldoseClient functionality."""
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
+
# pylint: disable=line-too-long
|
|
5
6
|
|
|
6
7
|
class TestInstantValues: # pylint: disable=too-many-public-methods
|
|
7
8
|
"""Test InstantValues functionality."""
|
|
@@ -158,7 +159,7 @@ class TestInstantValues: # pylint: disable=too-many-public-methods
|
|
|
158
159
|
def test_process_binary_sensor_value_invalid_entry(self, instant_values_fixture):
|
|
159
160
|
"""Test processing binary sensor value with invalid entry."""
|
|
160
161
|
# pylint: disable=protected-access
|
|
161
|
-
value = instant_values_fixture._process_binary_sensor_value("invalid", "test")
|
|
162
|
+
value = instant_values_fixture._process_binary_sensor_value("invalid", {}, "test")
|
|
162
163
|
assert value is None
|
|
163
164
|
|
|
164
165
|
def test_process_switch_value_bool(self, instant_values_fixture):
|
|
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
|
{python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{python_pooldose-0.6.6 → python_pooldose-0.6.8}/src/python_pooldose.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|