python-pooldose 0.5.1__tar.gz → 0.6.0__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.5.1 → python_pooldose-0.6.0}/PKG-INFO +99 -34
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/README.md +98 -33
- python_pooldose-0.6.0/pyproject.toml +88 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/__init__.py +1 -0
- python_pooldose-0.6.0/src/pooldose/__main__.py +205 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/client.py +3 -3
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/constants.py +1 -1
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/mappings/mapping_info.py +4 -2
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/mock_client.py +3 -3
- python_pooldose-0.6.0/src/pooldose/py.typed +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/request_handler.py +4 -3
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/request_status.py +1 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/values/instant_values.py +1 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/python_pooldose.egg-info/PKG-INFO +99 -34
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/python_pooldose.egg-info/SOURCES.txt +3 -0
- python_pooldose-0.6.0/src/python_pooldose.egg-info/entry_points.txt +2 -0
- python_pooldose-0.5.1/pyproject.toml +0 -38
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/LICENSE +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/setup.cfg +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/mappings/__init__.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/mappings/model_PDPR1H1HAR1V0_FW539224.json +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/mappings/model_PDPR1H1HAW100_FW539187.json +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/values/__init__.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/pooldose/values/static_values.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/python_pooldose.egg-info/dependency_links.txt +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/python_pooldose.egg-info/requires.txt +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/python_pooldose.egg-info/top_level.txt +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/tests/test_client.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/tests/test_instant_values.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/tests/test_mapping_info.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/tests/test_request_handler.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/tests/test_ssl_support.py +0 -0
- {python_pooldose-0.5.1 → python_pooldose-0.6.0}/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.
|
|
3
|
+
Version: 0.6.0
|
|
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
|
|
@@ -28,6 +28,8 @@ This client uses an undocumented local HTTP API. It provides live readings for p
|
|
|
28
28
|
- **Dynamic sensor discovery** based on device model and firmware
|
|
29
29
|
- **Dictionary-style access** to instant values
|
|
30
30
|
- **Structured data API** with type-based organization
|
|
31
|
+
- **PEP-561 compliant** with full type hints for Home Assistant integrations
|
|
32
|
+
- **Command-line interface** for direct device interaction and testing
|
|
31
33
|
- **Secure by default** - WiFi passwords excluded unless explicitly requested
|
|
32
34
|
- **Comprehensive error handling** with detailed logging
|
|
33
35
|
- **SSL/HTTPS support** for secure communication
|
|
@@ -169,6 +171,45 @@ client = PooldoseClient("192.168.1.100", use_ssl=True, port=8443, ssl_verify=Fal
|
|
|
169
171
|
pip install python-pooldose
|
|
170
172
|
```
|
|
171
173
|
|
|
174
|
+
## Command Line Usage
|
|
175
|
+
|
|
176
|
+
After installation, you can use python-pooldose directly from the command line:
|
|
177
|
+
|
|
178
|
+
### Connect to Real Device
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Basic connection
|
|
182
|
+
pooldose --host 192.168.1.100
|
|
183
|
+
|
|
184
|
+
# With HTTPS
|
|
185
|
+
pooldose --host 192.168.1.100 --ssl
|
|
186
|
+
|
|
187
|
+
# Custom port
|
|
188
|
+
pooldose --host 192.168.1.100 --ssl --port 8443
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Mock Mode with JSON Files
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Use JSON file for testing
|
|
195
|
+
pooldose --mock path/to/your/data.json
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Alternative Module Execution
|
|
199
|
+
|
|
200
|
+
You can also run it as a Python module:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Real device
|
|
204
|
+
python -m pooldose --host 192.168.1.100
|
|
205
|
+
|
|
206
|
+
# Mock mode
|
|
207
|
+
python -m pooldose --mock data.json
|
|
208
|
+
|
|
209
|
+
# Show help
|
|
210
|
+
python -m pooldose --help
|
|
211
|
+
```
|
|
212
|
+
|
|
172
213
|
## Examples
|
|
173
214
|
|
|
174
215
|
The `examples/` directory contains demonstration scripts that show how to use the python-pooldose library:
|
|
@@ -189,25 +230,6 @@ python examples/demo.py
|
|
|
189
230
|
- Displays all sensor readings, alarms, setpoints, and settings
|
|
190
231
|
- Demonstrates error handling
|
|
191
232
|
|
|
192
|
-
### 2. Mock Client Demo (`examples/demo_mock.py`)
|
|
193
|
-
|
|
194
|
-
Shows how to use the mock client with JSON files for development and testing:
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
# Run with sample data
|
|
198
|
-
python examples/demo_mock.py references/testdaten/suplere/instantvalues.json
|
|
199
|
-
|
|
200
|
-
# Use custom JSON file
|
|
201
|
-
python examples/demo_mock.py path/to/your/data.json
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Features:**
|
|
205
|
-
|
|
206
|
-
- No hardware required
|
|
207
|
-
- Uses real device data from JSON files
|
|
208
|
-
- Same API as real client
|
|
209
|
-
- Perfect for development and CI/CD
|
|
210
|
-
|
|
211
233
|
### Benefits of the Examples
|
|
212
234
|
|
|
213
235
|
- **Learning**: Step-by-step progression from simple to advanced usage
|
|
@@ -266,14 +288,14 @@ asyncio.run(simple_test())
|
|
|
266
288
|
|
|
267
289
|
### Mock Client Command Line Usage
|
|
268
290
|
|
|
269
|
-
You can
|
|
291
|
+
You can use the mock client with custom JSON files via the command line:
|
|
270
292
|
|
|
271
293
|
```bash
|
|
272
|
-
#
|
|
273
|
-
|
|
294
|
+
# Use mock client with JSON file
|
|
295
|
+
pooldose --mock path/to/your/data.json
|
|
274
296
|
|
|
275
|
-
#
|
|
276
|
-
python
|
|
297
|
+
# Or as Python module
|
|
298
|
+
python -m pooldose --mock path/to/your/data.json
|
|
277
299
|
```
|
|
278
300
|
|
|
279
301
|
### JSON Data Format
|
|
@@ -344,8 +366,7 @@ success = client.reload_data()
|
|
|
344
366
|
|
|
345
367
|
The following sample JSON files are available in the repository:
|
|
346
368
|
|
|
347
|
-
- `references/testdaten/
|
|
348
|
-
- `references/testdaten/instantvalues_poolforum_1.json` - Additional sample data
|
|
369
|
+
- `references/testdaten/tscherno/instantvalues.json` - Sample device data for testing
|
|
349
370
|
|
|
350
371
|
### Mock Client Use Cases
|
|
351
372
|
|
|
@@ -741,12 +762,54 @@ The `instant_values_structured()` method returns data organized by type:
|
|
|
741
762
|
|
|
742
763
|
This client has been tested with:
|
|
743
764
|
|
|
744
|
-
- **PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
|
|
765
|
+
- **SEKO PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
|
|
766
|
+
- **VA dos BASIC Chlor - pH/ORP Wi-Fi** (Model: PDPR1H1HAR1V0, FW: 539224)
|
|
745
767
|
|
|
746
768
|
Other SEKO PoolDose models may work but are untested. The client uses JSON mapping files to adapt to different device models and firmware versions (see e.g. `src/pooldose/mappings/model_PDPR1H1HAW100_FW539187.json`).
|
|
747
769
|
|
|
748
770
|
> **Note:** The JSON files in the mappings directory define the device-specific data keys and their human-readable names for different PoolDose models and firmware versions.
|
|
749
771
|
|
|
772
|
+
## Type Hints & Home Assistant Integration
|
|
773
|
+
|
|
774
|
+
This package is **PEP-561 compliant** and fully typed for use in Home Assistant integrations:
|
|
775
|
+
|
|
776
|
+
### Type Safety Features
|
|
777
|
+
|
|
778
|
+
**PEP-561 Compliance**: Package includes `py.typed` file marking it as fully typed
|
|
779
|
+
**Comprehensive Type Annotations**: All public API methods have complete type hints
|
|
780
|
+
**mypy Support**: Built-in mypy configuration for static type checking
|
|
781
|
+
**Home Assistant Ready**: Compatible with Home Assistant's strict typing requirements
|
|
782
|
+
|
|
783
|
+
### Type-Safe Usage
|
|
784
|
+
|
|
785
|
+
```python
|
|
786
|
+
from pooldose import PooldoseClient
|
|
787
|
+
from pooldose.request_status import RequestStatus
|
|
788
|
+
|
|
789
|
+
# Type checkers will infer all types automatically
|
|
790
|
+
client: PooldoseClient = PooldoseClient("192.168.1.100")
|
|
791
|
+
status: RequestStatus = await client.connect()
|
|
792
|
+
|
|
793
|
+
# Dictionary-style access with proper typing
|
|
794
|
+
status, instant_values = await client.instant_values()
|
|
795
|
+
if status == RequestStatus.SUCCESS and instant_values:
|
|
796
|
+
temperature = instant_values["temperature"] # Typed as tuple[float, str]
|
|
797
|
+
ph_value = instant_values.get("ph", "N/A") # Safe access with default
|
|
798
|
+
|
|
799
|
+
# Structured data with full type safety
|
|
800
|
+
status, structured_data = await client.instant_values_structured()
|
|
801
|
+
sensors = structured_data.get("sensor", {}) # Type: dict[str, dict[str, Any]]
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
### Integration Benefits
|
|
805
|
+
|
|
806
|
+
- **IDE Support**: Full autocomplete and type checking in VS Code, PyCharm, etc.
|
|
807
|
+
- **Runtime Safety**: Catch type errors before deployment
|
|
808
|
+
- **Documentation**: Self-documenting code through type annotations
|
|
809
|
+
- **Maintenance**: Easier refactoring with type-guided development
|
|
810
|
+
|
|
811
|
+
For Home Assistant integrations, add this package to your integration's dependencies and enjoy full type safety throughout your integration code.
|
|
812
|
+
|
|
750
813
|
## Security
|
|
751
814
|
|
|
752
815
|
By default, the client excludes sensitive information like WiFi passwords from device info. To include sensitive data:
|
|
@@ -761,7 +824,7 @@ status = await client.connect()
|
|
|
761
824
|
|
|
762
825
|
### Security Model
|
|
763
826
|
|
|
764
|
-
```
|
|
827
|
+
```text
|
|
765
828
|
Data Classification:
|
|
766
829
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
767
830
|
│ Public Data │ │ Sensitive Data │ │ Never Exposed │
|
|
@@ -782,9 +845,11 @@ Data Classification:
|
|
|
782
845
|
|
|
783
846
|
For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
|
|
784
847
|
|
|
785
|
-
### Latest Release (0.
|
|
848
|
+
### Latest Release (0.6.0)
|
|
786
849
|
|
|
787
|
-
- **
|
|
788
|
-
- **
|
|
789
|
-
- **
|
|
790
|
-
- **
|
|
850
|
+
- **Command Line Interface**: Complete CLI with `--host`, `--mock`, `--ssl`, and `--port` options
|
|
851
|
+
- **Pip Installation**: Install as console script via `pip install python-pooldose`
|
|
852
|
+
- **PEP-561 Type Compliance**: Full typing support for Home Assistant integrations
|
|
853
|
+
- **Documentation Modernization**: Centralized CLI documentation
|
|
854
|
+
- **Code Quality**: Pylint 10.00/10 score with strict typing and enhanced error handling
|
|
855
|
+
- **Simplified Structure**: Removed deprecated demo scripts, integrated mock functionality into CLI
|
|
@@ -10,6 +10,8 @@ This client uses an undocumented local HTTP API. It provides live readings for p
|
|
|
10
10
|
- **Dynamic sensor discovery** based on device model and firmware
|
|
11
11
|
- **Dictionary-style access** to instant values
|
|
12
12
|
- **Structured data API** with type-based organization
|
|
13
|
+
- **PEP-561 compliant** with full type hints for Home Assistant integrations
|
|
14
|
+
- **Command-line interface** for direct device interaction and testing
|
|
13
15
|
- **Secure by default** - WiFi passwords excluded unless explicitly requested
|
|
14
16
|
- **Comprehensive error handling** with detailed logging
|
|
15
17
|
- **SSL/HTTPS support** for secure communication
|
|
@@ -151,6 +153,45 @@ client = PooldoseClient("192.168.1.100", use_ssl=True, port=8443, ssl_verify=Fal
|
|
|
151
153
|
pip install python-pooldose
|
|
152
154
|
```
|
|
153
155
|
|
|
156
|
+
## Command Line Usage
|
|
157
|
+
|
|
158
|
+
After installation, you can use python-pooldose directly from the command line:
|
|
159
|
+
|
|
160
|
+
### Connect to Real Device
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Basic connection
|
|
164
|
+
pooldose --host 192.168.1.100
|
|
165
|
+
|
|
166
|
+
# With HTTPS
|
|
167
|
+
pooldose --host 192.168.1.100 --ssl
|
|
168
|
+
|
|
169
|
+
# Custom port
|
|
170
|
+
pooldose --host 192.168.1.100 --ssl --port 8443
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Mock Mode with JSON Files
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Use JSON file for testing
|
|
177
|
+
pooldose --mock path/to/your/data.json
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Alternative Module Execution
|
|
181
|
+
|
|
182
|
+
You can also run it as a Python module:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Real device
|
|
186
|
+
python -m pooldose --host 192.168.1.100
|
|
187
|
+
|
|
188
|
+
# Mock mode
|
|
189
|
+
python -m pooldose --mock data.json
|
|
190
|
+
|
|
191
|
+
# Show help
|
|
192
|
+
python -m pooldose --help
|
|
193
|
+
```
|
|
194
|
+
|
|
154
195
|
## Examples
|
|
155
196
|
|
|
156
197
|
The `examples/` directory contains demonstration scripts that show how to use the python-pooldose library:
|
|
@@ -171,25 +212,6 @@ python examples/demo.py
|
|
|
171
212
|
- Displays all sensor readings, alarms, setpoints, and settings
|
|
172
213
|
- Demonstrates error handling
|
|
173
214
|
|
|
174
|
-
### 2. Mock Client Demo (`examples/demo_mock.py`)
|
|
175
|
-
|
|
176
|
-
Shows how to use the mock client with JSON files for development and testing:
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
# Run with sample data
|
|
180
|
-
python examples/demo_mock.py references/testdaten/suplere/instantvalues.json
|
|
181
|
-
|
|
182
|
-
# Use custom JSON file
|
|
183
|
-
python examples/demo_mock.py path/to/your/data.json
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**Features:**
|
|
187
|
-
|
|
188
|
-
- No hardware required
|
|
189
|
-
- Uses real device data from JSON files
|
|
190
|
-
- Same API as real client
|
|
191
|
-
- Perfect for development and CI/CD
|
|
192
|
-
|
|
193
215
|
### Benefits of the Examples
|
|
194
216
|
|
|
195
217
|
- **Learning**: Step-by-step progression from simple to advanced usage
|
|
@@ -248,14 +270,14 @@ asyncio.run(simple_test())
|
|
|
248
270
|
|
|
249
271
|
### Mock Client Command Line Usage
|
|
250
272
|
|
|
251
|
-
You can
|
|
273
|
+
You can use the mock client with custom JSON files via the command line:
|
|
252
274
|
|
|
253
275
|
```bash
|
|
254
|
-
#
|
|
255
|
-
|
|
276
|
+
# Use mock client with JSON file
|
|
277
|
+
pooldose --mock path/to/your/data.json
|
|
256
278
|
|
|
257
|
-
#
|
|
258
|
-
python
|
|
279
|
+
# Or as Python module
|
|
280
|
+
python -m pooldose --mock path/to/your/data.json
|
|
259
281
|
```
|
|
260
282
|
|
|
261
283
|
### JSON Data Format
|
|
@@ -326,8 +348,7 @@ success = client.reload_data()
|
|
|
326
348
|
|
|
327
349
|
The following sample JSON files are available in the repository:
|
|
328
350
|
|
|
329
|
-
- `references/testdaten/
|
|
330
|
-
- `references/testdaten/instantvalues_poolforum_1.json` - Additional sample data
|
|
351
|
+
- `references/testdaten/tscherno/instantvalues.json` - Sample device data for testing
|
|
331
352
|
|
|
332
353
|
### Mock Client Use Cases
|
|
333
354
|
|
|
@@ -723,12 +744,54 @@ The `instant_values_structured()` method returns data organized by type:
|
|
|
723
744
|
|
|
724
745
|
This client has been tested with:
|
|
725
746
|
|
|
726
|
-
- **PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
|
|
747
|
+
- **SEKO PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
|
|
748
|
+
- **VA dos BASIC Chlor - pH/ORP Wi-Fi** (Model: PDPR1H1HAR1V0, FW: 539224)
|
|
727
749
|
|
|
728
750
|
Other SEKO PoolDose models may work but are untested. The client uses JSON mapping files to adapt to different device models and firmware versions (see e.g. `src/pooldose/mappings/model_PDPR1H1HAW100_FW539187.json`).
|
|
729
751
|
|
|
730
752
|
> **Note:** The JSON files in the mappings directory define the device-specific data keys and their human-readable names for different PoolDose models and firmware versions.
|
|
731
753
|
|
|
754
|
+
## Type Hints & Home Assistant Integration
|
|
755
|
+
|
|
756
|
+
This package is **PEP-561 compliant** and fully typed for use in Home Assistant integrations:
|
|
757
|
+
|
|
758
|
+
### Type Safety Features
|
|
759
|
+
|
|
760
|
+
**PEP-561 Compliance**: Package includes `py.typed` file marking it as fully typed
|
|
761
|
+
**Comprehensive Type Annotations**: All public API methods have complete type hints
|
|
762
|
+
**mypy Support**: Built-in mypy configuration for static type checking
|
|
763
|
+
**Home Assistant Ready**: Compatible with Home Assistant's strict typing requirements
|
|
764
|
+
|
|
765
|
+
### Type-Safe Usage
|
|
766
|
+
|
|
767
|
+
```python
|
|
768
|
+
from pooldose import PooldoseClient
|
|
769
|
+
from pooldose.request_status import RequestStatus
|
|
770
|
+
|
|
771
|
+
# Type checkers will infer all types automatically
|
|
772
|
+
client: PooldoseClient = PooldoseClient("192.168.1.100")
|
|
773
|
+
status: RequestStatus = await client.connect()
|
|
774
|
+
|
|
775
|
+
# Dictionary-style access with proper typing
|
|
776
|
+
status, instant_values = await client.instant_values()
|
|
777
|
+
if status == RequestStatus.SUCCESS and instant_values:
|
|
778
|
+
temperature = instant_values["temperature"] # Typed as tuple[float, str]
|
|
779
|
+
ph_value = instant_values.get("ph", "N/A") # Safe access with default
|
|
780
|
+
|
|
781
|
+
# Structured data with full type safety
|
|
782
|
+
status, structured_data = await client.instant_values_structured()
|
|
783
|
+
sensors = structured_data.get("sensor", {}) # Type: dict[str, dict[str, Any]]
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
### Integration Benefits
|
|
787
|
+
|
|
788
|
+
- **IDE Support**: Full autocomplete and type checking in VS Code, PyCharm, etc.
|
|
789
|
+
- **Runtime Safety**: Catch type errors before deployment
|
|
790
|
+
- **Documentation**: Self-documenting code through type annotations
|
|
791
|
+
- **Maintenance**: Easier refactoring with type-guided development
|
|
792
|
+
|
|
793
|
+
For Home Assistant integrations, add this package to your integration's dependencies and enjoy full type safety throughout your integration code.
|
|
794
|
+
|
|
732
795
|
## Security
|
|
733
796
|
|
|
734
797
|
By default, the client excludes sensitive information like WiFi passwords from device info. To include sensitive data:
|
|
@@ -743,7 +806,7 @@ status = await client.connect()
|
|
|
743
806
|
|
|
744
807
|
### Security Model
|
|
745
808
|
|
|
746
|
-
```
|
|
809
|
+
```text
|
|
747
810
|
Data Classification:
|
|
748
811
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
749
812
|
│ Public Data │ │ Sensitive Data │ │ Never Exposed │
|
|
@@ -764,9 +827,11 @@ Data Classification:
|
|
|
764
827
|
|
|
765
828
|
For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
|
|
766
829
|
|
|
767
|
-
### Latest Release (0.
|
|
830
|
+
### Latest Release (0.6.0)
|
|
768
831
|
|
|
769
|
-
- **
|
|
770
|
-
- **
|
|
771
|
-
- **
|
|
772
|
-
- **
|
|
832
|
+
- **Command Line Interface**: Complete CLI with `--host`, `--mock`, `--ssl`, and `--port` options
|
|
833
|
+
- **Pip Installation**: Install as console script via `pip install python-pooldose`
|
|
834
|
+
- **PEP-561 Type Compliance**: Full typing support for Home Assistant integrations
|
|
835
|
+
- **Documentation Modernization**: Centralized CLI documentation
|
|
836
|
+
- **Code Quality**: Pylint 10.00/10 score with strict typing and enhanced error handling
|
|
837
|
+
- **Simplified Structure**: Removed deprecated demo scripts, integrated mock functionality into CLI
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "python-pooldose"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "Unoffical async Python client for SEKO PoolDose devices"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "Lukas Maertin", email = "pypi@lukas-maertin.de" }
|
|
7
|
+
]
|
|
8
|
+
license = "MIT"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"aiohttp",
|
|
13
|
+
"aiofiles"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://github.com/lmaertin/python-pooldose"
|
|
18
|
+
Repository = "https://github.com/lmaertin/python-pooldose"
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
pooldose = "pooldose.__main__:main"
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
25
|
+
build-backend = "setuptools.build_meta"
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
dev = ["pytest", "pytest-asyncio"]
|
|
29
|
+
|
|
30
|
+
[tool.setuptools]
|
|
31
|
+
package-dir = {"" = "src"}
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.dynamic]
|
|
34
|
+
version = {attr = "pooldose.__version__"}
|
|
35
|
+
|
|
36
|
+
[tool.setuptools.packages.find]
|
|
37
|
+
where = ["src"]
|
|
38
|
+
|
|
39
|
+
[tool.setuptools.package-data]
|
|
40
|
+
"pooldose.mappings" = ["*.json"]
|
|
41
|
+
"pooldose" = ["py.typed"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
|
45
|
+
asyncio_mode = "auto"
|
|
46
|
+
|
|
47
|
+
[tool.mypy]
|
|
48
|
+
python_version = "3.11"
|
|
49
|
+
# Home Assistant strict typing compliance
|
|
50
|
+
strict = false
|
|
51
|
+
warn_return_any = false
|
|
52
|
+
warn_unused_configs = true
|
|
53
|
+
disallow_untyped_defs = false
|
|
54
|
+
disallow_incomplete_defs = false
|
|
55
|
+
check_untyped_defs = true
|
|
56
|
+
no_implicit_optional = true
|
|
57
|
+
warn_redundant_casts = true
|
|
58
|
+
warn_unused_ignores = false
|
|
59
|
+
warn_no_return = true
|
|
60
|
+
strict_equality = true
|
|
61
|
+
ignore_missing_imports = true
|
|
62
|
+
# Focus on public API typing
|
|
63
|
+
show_error_codes = true
|
|
64
|
+
|
|
65
|
+
[[tool.mypy.overrides]]
|
|
66
|
+
module = "examples.*"
|
|
67
|
+
ignore_errors = true
|
|
68
|
+
|
|
69
|
+
[[tool.mypy.overrides]]
|
|
70
|
+
module = "tests.*"
|
|
71
|
+
ignore_errors = true
|
|
72
|
+
|
|
73
|
+
# Strict typing for core public API modules
|
|
74
|
+
[[tool.mypy.overrides]]
|
|
75
|
+
module = "pooldose.__init__"
|
|
76
|
+
disallow_untyped_defs = true
|
|
77
|
+
disallow_incomplete_defs = true
|
|
78
|
+
|
|
79
|
+
[[tool.mypy.overrides]]
|
|
80
|
+
module = "pooldose.client"
|
|
81
|
+
disallow_untyped_defs = true
|
|
82
|
+
disallow_incomplete_defs = true
|
|
83
|
+
warn_return_any = false
|
|
84
|
+
|
|
85
|
+
[[tool.mypy.overrides]]
|
|
86
|
+
module = "pooldose.request_status"
|
|
87
|
+
disallow_untyped_defs = true
|
|
88
|
+
disallow_incomplete_defs = true
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Command-line interface for python-pooldose."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import asyncio
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from pooldose import __version__
|
|
10
|
+
from pooldose.client import PooldoseClient, RequestStatus
|
|
11
|
+
from pooldose.mock_client import MockPooldoseClient
|
|
12
|
+
|
|
13
|
+
# Import demo utilities if available
|
|
14
|
+
try:
|
|
15
|
+
from examples.demo_utils import (display_static_values,
|
|
16
|
+
display_structured_data)
|
|
17
|
+
except ImportError:
|
|
18
|
+
# Fallback implementations for when installed via pip
|
|
19
|
+
def display_static_values(static_values):
|
|
20
|
+
"""Display static device values (fallback implementation)."""
|
|
21
|
+
device_info = [
|
|
22
|
+
("Name", static_values.sensor_name),
|
|
23
|
+
("Serial", static_values.sensor_serial_number),
|
|
24
|
+
("Model", static_values.sensor_model),
|
|
25
|
+
("Firmware", static_values.sensor_fw_version),
|
|
26
|
+
]
|
|
27
|
+
print("\nDevice Information:")
|
|
28
|
+
for label, value in device_info:
|
|
29
|
+
print(f" {label}: {value}")
|
|
30
|
+
|
|
31
|
+
def display_structured_data(structured_data):
|
|
32
|
+
"""Display structured data in a simple format."""
|
|
33
|
+
for data_type, items in structured_data.items():
|
|
34
|
+
if not items:
|
|
35
|
+
continue
|
|
36
|
+
print(f"\n{data_type.title()}:")
|
|
37
|
+
for key, data in items.items():
|
|
38
|
+
value = data.get("value")
|
|
39
|
+
unit = data.get("unit", "")
|
|
40
|
+
if unit:
|
|
41
|
+
print(f" {key}: {value} {unit}")
|
|
42
|
+
else:
|
|
43
|
+
print(f" {key}: {value}")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def run_real_client(host: str, use_ssl: bool, port: int) -> None:
|
|
47
|
+
"""Run the real PooldoseClient."""
|
|
48
|
+
print(f"Connecting to PoolDose device at {host}")
|
|
49
|
+
if use_ssl:
|
|
50
|
+
print(f"Using HTTPS on port {port}")
|
|
51
|
+
else:
|
|
52
|
+
print(f"Using HTTP on port {port}")
|
|
53
|
+
|
|
54
|
+
client = PooldoseClient(
|
|
55
|
+
host=host,
|
|
56
|
+
use_ssl=use_ssl,
|
|
57
|
+
port=port if port != 0 else None,
|
|
58
|
+
timeout=30
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
# Connect
|
|
63
|
+
status = await client.connect()
|
|
64
|
+
if status != RequestStatus.SUCCESS:
|
|
65
|
+
print(f"Error connecting to device: {status}")
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
print("Connected successfully!")
|
|
69
|
+
|
|
70
|
+
# Get static values
|
|
71
|
+
static_status, static_values = client.static_values()
|
|
72
|
+
if static_status == RequestStatus.SUCCESS:
|
|
73
|
+
display_static_values(static_values)
|
|
74
|
+
|
|
75
|
+
# Get instant values
|
|
76
|
+
instant_status, instant_data = await client.instant_values_structured()
|
|
77
|
+
if instant_status == RequestStatus.SUCCESS:
|
|
78
|
+
display_structured_data(instant_data)
|
|
79
|
+
|
|
80
|
+
print("\nConnection completed successfully!")
|
|
81
|
+
|
|
82
|
+
except (ConnectionError, TimeoutError, OSError) as e:
|
|
83
|
+
print(f"Network error: {e}")
|
|
84
|
+
except Exception as e: # pylint: disable=broad-except
|
|
85
|
+
print(f"Error during connection: {e}")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
async def run_mock_client(json_file: str) -> None:
|
|
89
|
+
"""Run the MockPooldoseClient."""
|
|
90
|
+
json_path = Path(json_file)
|
|
91
|
+
if not json_path.exists():
|
|
92
|
+
print(f"Error: JSON file not found: {json_file}")
|
|
93
|
+
return
|
|
94
|
+
|
|
95
|
+
print(f"Loading mock data from: {json_file}")
|
|
96
|
+
|
|
97
|
+
client = MockPooldoseClient(
|
|
98
|
+
json_file_path=json_path,
|
|
99
|
+
include_sensitive_data=True
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
# Connect
|
|
104
|
+
status = await client.connect()
|
|
105
|
+
if status.name != "SUCCESS":
|
|
106
|
+
print(f"Error connecting to mock device: {status}")
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
print("Connected to mock device successfully!")
|
|
110
|
+
|
|
111
|
+
# Get static values
|
|
112
|
+
static_status, static_values = client.static_values()
|
|
113
|
+
if static_status.name == "SUCCESS":
|
|
114
|
+
display_static_values(static_values)
|
|
115
|
+
|
|
116
|
+
# Get instant values
|
|
117
|
+
instant_status, instant_data = await client.instant_values_structured()
|
|
118
|
+
if instant_status.name == "SUCCESS":
|
|
119
|
+
display_structured_data(instant_data)
|
|
120
|
+
|
|
121
|
+
print("\nMock demo completed successfully!")
|
|
122
|
+
|
|
123
|
+
except (FileNotFoundError, ValueError, OSError) as e:
|
|
124
|
+
print(f"File or data error: {e}")
|
|
125
|
+
except Exception as e: # pylint: disable=broad-except
|
|
126
|
+
print(f"Error during mock demo: {e}")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def main() -> None:
|
|
130
|
+
"""Main entry point for command-line interface."""
|
|
131
|
+
parser = argparse.ArgumentParser(
|
|
132
|
+
description="Python PoolDose Client - Connect to SEKO PoolDose devices",
|
|
133
|
+
epilog="""
|
|
134
|
+
Examples:
|
|
135
|
+
# Connect to real device
|
|
136
|
+
python -m pooldose --host 192.168.1.100
|
|
137
|
+
|
|
138
|
+
# Connect with HTTPS
|
|
139
|
+
python -m pooldose --host 192.168.1.100 --ssl --port 443
|
|
140
|
+
|
|
141
|
+
# Use mock client with JSON file
|
|
142
|
+
python -m pooldose --mock path/to/your/data.json
|
|
143
|
+
""",
|
|
144
|
+
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Mode selection
|
|
148
|
+
mode_group = parser.add_mutually_exclusive_group(required=True)
|
|
149
|
+
mode_group.add_argument(
|
|
150
|
+
"--host",
|
|
151
|
+
type=str,
|
|
152
|
+
help="IP address or hostname of PoolDose device"
|
|
153
|
+
)
|
|
154
|
+
mode_group.add_argument(
|
|
155
|
+
"--mock",
|
|
156
|
+
type=str,
|
|
157
|
+
metavar="JSON_FILE",
|
|
158
|
+
help="Path to JSON file for mock mode"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Connection options
|
|
162
|
+
parser.add_argument(
|
|
163
|
+
"--ssl",
|
|
164
|
+
action="store_true",
|
|
165
|
+
help="Use HTTPS instead of HTTP"
|
|
166
|
+
)
|
|
167
|
+
parser.add_argument(
|
|
168
|
+
"--port",
|
|
169
|
+
type=int,
|
|
170
|
+
default=0,
|
|
171
|
+
help="Custom port (default: 80 for HTTP, 443 for HTTPS)"
|
|
172
|
+
)
|
|
173
|
+
parser.add_argument(
|
|
174
|
+
"--version",
|
|
175
|
+
action="version",
|
|
176
|
+
version=f"python-pooldose {__version__}"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
args = parser.parse_args()
|
|
180
|
+
|
|
181
|
+
# Set UTF-8 encoding for output
|
|
182
|
+
if sys.stdout.encoding != 'utf-8':
|
|
183
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
184
|
+
|
|
185
|
+
print("Python PoolDose Client")
|
|
186
|
+
print("=" * 40)
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
if args.host:
|
|
190
|
+
# Real device mode
|
|
191
|
+
port = args.port if args.port != 0 else (443 if args.ssl else 80)
|
|
192
|
+
asyncio.run(run_real_client(args.host, args.ssl, port))
|
|
193
|
+
elif args.mock:
|
|
194
|
+
# Mock mode
|
|
195
|
+
asyncio.run(run_mock_client(args.mock))
|
|
196
|
+
|
|
197
|
+
except KeyboardInterrupt:
|
|
198
|
+
print("\nOperation cancelled by user.")
|
|
199
|
+
except Exception as e: # pylint: disable=broad-except
|
|
200
|
+
print(f"\nUnexpected error: {e}")
|
|
201
|
+
sys.exit(1)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
if __name__ == "__main__":
|
|
205
|
+
main()
|
|
@@ -4,14 +4,14 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import logging
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import Any, Dict, Optional, Tuple
|
|
8
8
|
|
|
9
9
|
from pooldose.constants import get_default_device_info
|
|
10
|
-
from pooldose.
|
|
10
|
+
from pooldose.mappings.mapping_info import MappingInfo
|
|
11
11
|
from pooldose.request_handler import RequestHandler
|
|
12
12
|
from pooldose.request_status import RequestStatus
|
|
13
|
+
from pooldose.values.instant_values import InstantValues
|
|
13
14
|
from pooldose.values.static_values import StaticValues
|
|
14
|
-
from pooldose.mappings.mapping_info import MappingInfo
|
|
15
15
|
|
|
16
16
|
# pylint: disable=line-too-long,too-many-instance-attributes
|
|
17
17
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"""Mapping Parser for async API client for SEKO Pooldose."""
|
|
2
2
|
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from typing import Any, Dict, Optional
|
|
5
3
|
import importlib.resources
|
|
6
4
|
import json
|
|
7
5
|
import logging
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Any, Dict, Optional
|
|
8
|
+
|
|
8
9
|
import aiofiles
|
|
10
|
+
|
|
9
11
|
from pooldose.request_handler import RequestStatus
|
|
10
12
|
|
|
11
13
|
# pylint: disable=line-too-long
|
|
@@ -5,13 +5,13 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
|
9
9
|
|
|
10
10
|
from pooldose.constants import get_default_device_info
|
|
11
|
-
from pooldose.
|
|
11
|
+
from pooldose.mappings.mapping_info import MappingInfo
|
|
12
12
|
from pooldose.request_status import RequestStatus
|
|
13
|
+
from pooldose.values.instant_values import InstantValues
|
|
13
14
|
from pooldose.values.static_values import StaticValues
|
|
14
|
-
from pooldose.mappings.mapping_info import MappingInfo
|
|
15
15
|
|
|
16
16
|
_LOGGER = logging.getLogger(__name__)
|
|
17
17
|
|
|
File without changes
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"""Request Handler for async API client for SEKO Pooldose."""
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import asyncio
|
|
4
4
|
import json
|
|
5
|
+
import logging
|
|
5
6
|
import re
|
|
6
7
|
import socket
|
|
7
8
|
import ssl
|
|
8
9
|
from typing import Any, Optional
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
import aiohttp
|
|
11
12
|
|
|
12
13
|
from pooldose.request_status import RequestStatus
|
|
@@ -93,7 +94,7 @@ class RequestHandler: # pylint: disable=too-many-instance-attributes
|
|
|
93
94
|
else:
|
|
94
95
|
return f"{scheme}://{self.host}{path}"
|
|
95
96
|
|
|
96
|
-
async def _get_core_params(self) -> dict | None:
|
|
97
|
+
async def _get_core_params(self) -> dict[str, Any] | None:
|
|
97
98
|
"""
|
|
98
99
|
Fetch and extract softwareVersion and apiversion from params.js.
|
|
99
100
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Any, Dict, Tuple, Union
|
|
5
|
+
|
|
5
6
|
from pooldose.request_handler import RequestHandler
|
|
6
7
|
|
|
7
8
|
# pylint: disable=line-too-long,too-many-arguments,too-many-positional-arguments,too-many-locals,too-many-return-statements,too-many-branches,no-else-return,too-many-public-methods
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-pooldose
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
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
|
|
@@ -28,6 +28,8 @@ This client uses an undocumented local HTTP API. It provides live readings for p
|
|
|
28
28
|
- **Dynamic sensor discovery** based on device model and firmware
|
|
29
29
|
- **Dictionary-style access** to instant values
|
|
30
30
|
- **Structured data API** with type-based organization
|
|
31
|
+
- **PEP-561 compliant** with full type hints for Home Assistant integrations
|
|
32
|
+
- **Command-line interface** for direct device interaction and testing
|
|
31
33
|
- **Secure by default** - WiFi passwords excluded unless explicitly requested
|
|
32
34
|
- **Comprehensive error handling** with detailed logging
|
|
33
35
|
- **SSL/HTTPS support** for secure communication
|
|
@@ -169,6 +171,45 @@ client = PooldoseClient("192.168.1.100", use_ssl=True, port=8443, ssl_verify=Fal
|
|
|
169
171
|
pip install python-pooldose
|
|
170
172
|
```
|
|
171
173
|
|
|
174
|
+
## Command Line Usage
|
|
175
|
+
|
|
176
|
+
After installation, you can use python-pooldose directly from the command line:
|
|
177
|
+
|
|
178
|
+
### Connect to Real Device
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Basic connection
|
|
182
|
+
pooldose --host 192.168.1.100
|
|
183
|
+
|
|
184
|
+
# With HTTPS
|
|
185
|
+
pooldose --host 192.168.1.100 --ssl
|
|
186
|
+
|
|
187
|
+
# Custom port
|
|
188
|
+
pooldose --host 192.168.1.100 --ssl --port 8443
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Mock Mode with JSON Files
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Use JSON file for testing
|
|
195
|
+
pooldose --mock path/to/your/data.json
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Alternative Module Execution
|
|
199
|
+
|
|
200
|
+
You can also run it as a Python module:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Real device
|
|
204
|
+
python -m pooldose --host 192.168.1.100
|
|
205
|
+
|
|
206
|
+
# Mock mode
|
|
207
|
+
python -m pooldose --mock data.json
|
|
208
|
+
|
|
209
|
+
# Show help
|
|
210
|
+
python -m pooldose --help
|
|
211
|
+
```
|
|
212
|
+
|
|
172
213
|
## Examples
|
|
173
214
|
|
|
174
215
|
The `examples/` directory contains demonstration scripts that show how to use the python-pooldose library:
|
|
@@ -189,25 +230,6 @@ python examples/demo.py
|
|
|
189
230
|
- Displays all sensor readings, alarms, setpoints, and settings
|
|
190
231
|
- Demonstrates error handling
|
|
191
232
|
|
|
192
|
-
### 2. Mock Client Demo (`examples/demo_mock.py`)
|
|
193
|
-
|
|
194
|
-
Shows how to use the mock client with JSON files for development and testing:
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
# Run with sample data
|
|
198
|
-
python examples/demo_mock.py references/testdaten/suplere/instantvalues.json
|
|
199
|
-
|
|
200
|
-
# Use custom JSON file
|
|
201
|
-
python examples/demo_mock.py path/to/your/data.json
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Features:**
|
|
205
|
-
|
|
206
|
-
- No hardware required
|
|
207
|
-
- Uses real device data from JSON files
|
|
208
|
-
- Same API as real client
|
|
209
|
-
- Perfect for development and CI/CD
|
|
210
|
-
|
|
211
233
|
### Benefits of the Examples
|
|
212
234
|
|
|
213
235
|
- **Learning**: Step-by-step progression from simple to advanced usage
|
|
@@ -266,14 +288,14 @@ asyncio.run(simple_test())
|
|
|
266
288
|
|
|
267
289
|
### Mock Client Command Line Usage
|
|
268
290
|
|
|
269
|
-
You can
|
|
291
|
+
You can use the mock client with custom JSON files via the command line:
|
|
270
292
|
|
|
271
293
|
```bash
|
|
272
|
-
#
|
|
273
|
-
|
|
294
|
+
# Use mock client with JSON file
|
|
295
|
+
pooldose --mock path/to/your/data.json
|
|
274
296
|
|
|
275
|
-
#
|
|
276
|
-
python
|
|
297
|
+
# Or as Python module
|
|
298
|
+
python -m pooldose --mock path/to/your/data.json
|
|
277
299
|
```
|
|
278
300
|
|
|
279
301
|
### JSON Data Format
|
|
@@ -344,8 +366,7 @@ success = client.reload_data()
|
|
|
344
366
|
|
|
345
367
|
The following sample JSON files are available in the repository:
|
|
346
368
|
|
|
347
|
-
- `references/testdaten/
|
|
348
|
-
- `references/testdaten/instantvalues_poolforum_1.json` - Additional sample data
|
|
369
|
+
- `references/testdaten/tscherno/instantvalues.json` - Sample device data for testing
|
|
349
370
|
|
|
350
371
|
### Mock Client Use Cases
|
|
351
372
|
|
|
@@ -741,12 +762,54 @@ The `instant_values_structured()` method returns data organized by type:
|
|
|
741
762
|
|
|
742
763
|
This client has been tested with:
|
|
743
764
|
|
|
744
|
-
- **PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
|
|
765
|
+
- **SEKO PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
|
|
766
|
+
- **VA dos BASIC Chlor - pH/ORP Wi-Fi** (Model: PDPR1H1HAR1V0, FW: 539224)
|
|
745
767
|
|
|
746
768
|
Other SEKO PoolDose models may work but are untested. The client uses JSON mapping files to adapt to different device models and firmware versions (see e.g. `src/pooldose/mappings/model_PDPR1H1HAW100_FW539187.json`).
|
|
747
769
|
|
|
748
770
|
> **Note:** The JSON files in the mappings directory define the device-specific data keys and their human-readable names for different PoolDose models and firmware versions.
|
|
749
771
|
|
|
772
|
+
## Type Hints & Home Assistant Integration
|
|
773
|
+
|
|
774
|
+
This package is **PEP-561 compliant** and fully typed for use in Home Assistant integrations:
|
|
775
|
+
|
|
776
|
+
### Type Safety Features
|
|
777
|
+
|
|
778
|
+
**PEP-561 Compliance**: Package includes `py.typed` file marking it as fully typed
|
|
779
|
+
**Comprehensive Type Annotations**: All public API methods have complete type hints
|
|
780
|
+
**mypy Support**: Built-in mypy configuration for static type checking
|
|
781
|
+
**Home Assistant Ready**: Compatible with Home Assistant's strict typing requirements
|
|
782
|
+
|
|
783
|
+
### Type-Safe Usage
|
|
784
|
+
|
|
785
|
+
```python
|
|
786
|
+
from pooldose import PooldoseClient
|
|
787
|
+
from pooldose.request_status import RequestStatus
|
|
788
|
+
|
|
789
|
+
# Type checkers will infer all types automatically
|
|
790
|
+
client: PooldoseClient = PooldoseClient("192.168.1.100")
|
|
791
|
+
status: RequestStatus = await client.connect()
|
|
792
|
+
|
|
793
|
+
# Dictionary-style access with proper typing
|
|
794
|
+
status, instant_values = await client.instant_values()
|
|
795
|
+
if status == RequestStatus.SUCCESS and instant_values:
|
|
796
|
+
temperature = instant_values["temperature"] # Typed as tuple[float, str]
|
|
797
|
+
ph_value = instant_values.get("ph", "N/A") # Safe access with default
|
|
798
|
+
|
|
799
|
+
# Structured data with full type safety
|
|
800
|
+
status, structured_data = await client.instant_values_structured()
|
|
801
|
+
sensors = structured_data.get("sensor", {}) # Type: dict[str, dict[str, Any]]
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
### Integration Benefits
|
|
805
|
+
|
|
806
|
+
- **IDE Support**: Full autocomplete and type checking in VS Code, PyCharm, etc.
|
|
807
|
+
- **Runtime Safety**: Catch type errors before deployment
|
|
808
|
+
- **Documentation**: Self-documenting code through type annotations
|
|
809
|
+
- **Maintenance**: Easier refactoring with type-guided development
|
|
810
|
+
|
|
811
|
+
For Home Assistant integrations, add this package to your integration's dependencies and enjoy full type safety throughout your integration code.
|
|
812
|
+
|
|
750
813
|
## Security
|
|
751
814
|
|
|
752
815
|
By default, the client excludes sensitive information like WiFi passwords from device info. To include sensitive data:
|
|
@@ -761,7 +824,7 @@ status = await client.connect()
|
|
|
761
824
|
|
|
762
825
|
### Security Model
|
|
763
826
|
|
|
764
|
-
```
|
|
827
|
+
```text
|
|
765
828
|
Data Classification:
|
|
766
829
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
767
830
|
│ Public Data │ │ Sensitive Data │ │ Never Exposed │
|
|
@@ -782,9 +845,11 @@ Data Classification:
|
|
|
782
845
|
|
|
783
846
|
For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
|
|
784
847
|
|
|
785
|
-
### Latest Release (0.
|
|
848
|
+
### Latest Release (0.6.0)
|
|
786
849
|
|
|
787
|
-
- **
|
|
788
|
-
- **
|
|
789
|
-
- **
|
|
790
|
-
- **
|
|
850
|
+
- **Command Line Interface**: Complete CLI with `--host`, `--mock`, `--ssl`, and `--port` options
|
|
851
|
+
- **Pip Installation**: Install as console script via `pip install python-pooldose`
|
|
852
|
+
- **PEP-561 Type Compliance**: Full typing support for Home Assistant integrations
|
|
853
|
+
- **Documentation Modernization**: Centralized CLI documentation
|
|
854
|
+
- **Code Quality**: Pylint 10.00/10 score with strict typing and enhanced error handling
|
|
855
|
+
- **Simplified Structure**: Removed deprecated demo scripts, integrated mock functionality into CLI
|
|
@@ -2,9 +2,11 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
4
|
src/pooldose/__init__.py
|
|
5
|
+
src/pooldose/__main__.py
|
|
5
6
|
src/pooldose/client.py
|
|
6
7
|
src/pooldose/constants.py
|
|
7
8
|
src/pooldose/mock_client.py
|
|
9
|
+
src/pooldose/py.typed
|
|
8
10
|
src/pooldose/request_handler.py
|
|
9
11
|
src/pooldose/request_status.py
|
|
10
12
|
src/pooldose/mappings/__init__.py
|
|
@@ -17,6 +19,7 @@ src/pooldose/values/static_values.py
|
|
|
17
19
|
src/python_pooldose.egg-info/PKG-INFO
|
|
18
20
|
src/python_pooldose.egg-info/SOURCES.txt
|
|
19
21
|
src/python_pooldose.egg-info/dependency_links.txt
|
|
22
|
+
src/python_pooldose.egg-info/entry_points.txt
|
|
20
23
|
src/python_pooldose.egg-info/requires.txt
|
|
21
24
|
src/python_pooldose.egg-info/top_level.txt
|
|
22
25
|
tests/test_client.py
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "python-pooldose"
|
|
3
|
-
version = "0.5.1"
|
|
4
|
-
description = "Unoffical async Python client for SEKO PoolDose devices"
|
|
5
|
-
authors = [
|
|
6
|
-
{ name = "Lukas Maertin", email = "pypi@lukas-maertin.de" }
|
|
7
|
-
]
|
|
8
|
-
license = "MIT"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.11"
|
|
11
|
-
dependencies = [
|
|
12
|
-
"aiohttp",
|
|
13
|
-
"aiofiles"
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
[project.urls]
|
|
17
|
-
Homepage = "https://github.com/lmaertin/python-pooldose"
|
|
18
|
-
Repository = "https://github.com/lmaertin/python-pooldose"
|
|
19
|
-
|
|
20
|
-
[build-system]
|
|
21
|
-
requires = ["setuptools>=61.0", "wheel"]
|
|
22
|
-
build-backend = "setuptools.build_meta"
|
|
23
|
-
|
|
24
|
-
[project.optional-dependencies]
|
|
25
|
-
dev = ["pytest", "pytest-asyncio"]
|
|
26
|
-
|
|
27
|
-
[tool.setuptools]
|
|
28
|
-
package-dir = {"" = "src"}
|
|
29
|
-
|
|
30
|
-
[tool.setuptools.packages.find]
|
|
31
|
-
where = ["src"]
|
|
32
|
-
|
|
33
|
-
[tool.setuptools.package-data]
|
|
34
|
-
"pooldose.mappings" = ["*.json"]
|
|
35
|
-
|
|
36
|
-
[tool.pytest.ini_options]
|
|
37
|
-
testpaths = ["tests"]
|
|
38
|
-
asyncio_mode = "auto"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_pooldose-0.5.1 → python_pooldose-0.6.0}/src/python_pooldose.egg-info/dependency_links.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
|
|
File without changes
|