python-pooldose 0.5.0__tar.gz → 0.5.1__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 (29) hide show
  1. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/PKG-INFO +259 -7
  2. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/README.md +258 -6
  3. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/pyproject.toml +1 -1
  4. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/client.py +3 -19
  5. python_pooldose-0.5.1/src/pooldose/constants.py +29 -0
  6. python_pooldose-0.5.1/src/pooldose/mappings/model_PDPR1H1HAR1V0_FW539224.json +110 -0
  7. python_pooldose-0.5.1/src/pooldose/mock_client.py +256 -0
  8. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/python_pooldose.egg-info/PKG-INFO +259 -7
  9. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/python_pooldose.egg-info/SOURCES.txt +3 -0
  10. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/LICENSE +0 -0
  11. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/setup.cfg +0 -0
  12. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/__init__.py +0 -0
  13. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/mappings/__init__.py +0 -0
  14. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/mappings/mapping_info.py +0 -0
  15. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/mappings/model_PDPR1H1HAW100_FW539187.json +0 -0
  16. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/request_handler.py +0 -0
  17. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/request_status.py +0 -0
  18. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/values/__init__.py +0 -0
  19. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/values/instant_values.py +0 -0
  20. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/pooldose/values/static_values.py +0 -0
  21. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/python_pooldose.egg-info/dependency_links.txt +0 -0
  22. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/python_pooldose.egg-info/requires.txt +0 -0
  23. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/src/python_pooldose.egg-info/top_level.txt +0 -0
  24. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/tests/test_client.py +0 -0
  25. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/tests/test_instant_values.py +0 -0
  26. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/tests/test_mapping_info.py +0 -0
  27. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/tests/test_request_handler.py +0 -0
  28. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/tests/test_ssl_support.py +0 -0
  29. {python_pooldose-0.5.0 → python_pooldose-0.5.1}/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.5.0
3
+ Version: 0.5.1
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
@@ -17,10 +17,13 @@ Requires-Dist: pytest-asyncio; extra == "dev"
17
17
  Dynamic: license-file
18
18
 
19
19
  # python-pooldose
20
- Unofficial async Python client for [SEKO](https://www.seko.com/) Pooldosing systems. SEKO is a manufacturer of various monitoring and control devices for Pools and Spas.
20
+
21
+ Unofficial async Python client for [SEKO](https://www.seko.com/) Pooldosing systems. SEKO is a manufacturer of various monitoring and control devices for pools and spas.
22
+
21
23
  This client uses an undocumented local HTTP API. It provides live readings for pool sensors such as temperature, pH, ORP/Redox, as well as status information and control over the dosing logic.
22
24
 
23
25
  ## Features
26
+
24
27
  - **Async/await support** for non-blocking operations
25
28
  - **Dynamic sensor discovery** based on device model and firmware
26
29
  - **Dictionary-style access** to instant values
@@ -95,6 +98,7 @@ This client uses an undocumented local HTTP API. It provides live readings for p
95
98
  ```
96
99
 
97
100
  ## Prerequisites
101
+
98
102
  1. Install and set-up the PoolDose devices according to the user manual.
99
103
  1. In particular, connect the device to your WiFi network.
100
104
  2. Identify the IP address or hostname of the device.
@@ -165,9 +169,246 @@ client = PooldoseClient("192.168.1.100", use_ssl=True, port=8443, ssl_verify=Fal
165
169
  pip install python-pooldose
166
170
  ```
167
171
 
172
+ ## Examples
173
+
174
+ The `examples/` directory contains demonstration scripts that show how to use the python-pooldose library:
175
+
176
+ ### 1. Real Device Demo (`examples/demo.py`)
177
+
178
+ Demonstrates connecting to a real PoolDose device and accessing all types of data:
179
+
180
+ ```bash
181
+ # Edit the HOST variable in the file first
182
+ python examples/demo.py
183
+ ```
184
+
185
+ **Features:**
186
+
187
+ - Connects to actual hardware
188
+ - Shows device information and static values
189
+ - Displays all sensor readings, alarms, setpoints, and settings
190
+ - Demonstrates error handling
191
+
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
+ ### Benefits of the Examples
212
+
213
+ - **Learning**: Step-by-step progression from simple to advanced usage
214
+ - **Development**: Mock client allows development without hardware
215
+ - **Testing**: JSON-based testing for CI/CD pipelines
216
+ - **Reference**: Real-world code patterns and best practices
217
+
218
+ ## Mock Client System
219
+
220
+ The **MockPooldoseClient** system allows using JSON files instead of real Pooldose hardware for testing and development. This is particularly useful for:
221
+
222
+ - **Development without hardware**
223
+ - **Unit tests**
224
+ - **Data analysis with real device data**
225
+ - **CI/CD pipeline tests**
226
+
227
+ ### Mock Client Quick Start
228
+
229
+ ```python
230
+ import asyncio
231
+ from pathlib import Path
232
+ from pooldose.mock_client import MockPooldoseClient
233
+
234
+ async def simple_test():
235
+ # Load data file
236
+ json_file = Path("path/to/your/data.json")
237
+
238
+ # Create mock client
239
+ client = MockPooldoseClient(json_file_path=json_file)
240
+
241
+ # Connect (loads mapping data)
242
+ status = await client.connect()
243
+ if status.name != "SUCCESS":
244
+ print(f"Connection failed: {status}")
245
+ return
246
+
247
+ # Get sensor values
248
+ status, instant_values = await client.instant_values()
249
+ if status.name == "SUCCESS" and instant_values:
250
+ print(f"Temperature: {instant_values['temperature']}")
251
+ print(f"pH Value: {instant_values['ph']}")
252
+ print(f"ORP: {instant_values['orp']}")
253
+
254
+ # Get structured data
255
+ status, data = await client.instant_values_structured()
256
+ if status.name == "SUCCESS":
257
+ sensors = data.get('sensor', {})
258
+ for name, info in sensors.items():
259
+ value = info.get('value', 'N/A')
260
+ unit = info.get('unit', '')
261
+ print(f"{name}: {value} {unit}")
262
+
263
+ # Run demo
264
+ asyncio.run(simple_test())
265
+ ```
266
+
267
+ ### Mock Client Command Line Usage
268
+
269
+ You can run the demo script with custom JSON files:
270
+
271
+ ```bash
272
+ # Run with sample data
273
+ python examples/demo_mock.py references/testdaten/suplere/instantvalues.json
274
+
275
+ # Use custom JSON file
276
+ python examples/demo_mock.py path/to/your/data.json
277
+ ```
278
+
279
+ ### JSON Data Format
280
+
281
+ The JSON file must have the following structure:
282
+
283
+ ```json
284
+ {
285
+ "devicedata": {
286
+ "SERIALNUMBER_DEVICE": {
287
+ "MODEL_FW_w_key1": {
288
+ "current": 25.5,
289
+ "magnitude": ["°C"]
290
+ },
291
+ "MODEL_FW_w_key2": {
292
+ "current": 7.2,
293
+ "magnitude": ["pH"]
294
+ }
295
+ }
296
+ }
297
+ }
298
+ ```
299
+
300
+ ### Mock Client API Methods
301
+
302
+ #### Initialization
303
+
304
+ ```python
305
+ client = MockPooldoseClient(
306
+ json_file_path="path/to/data.json",
307
+ timeout=30, # Ignored (compatibility)
308
+ include_sensitive_data=True # Include WiFi keys etc.
309
+ )
310
+ ```
311
+
312
+ #### Connection
313
+
314
+ ```python
315
+ status = await client.connect() # Loads mapping configuration
316
+ is_connected = client.is_connected # Check status
317
+ ```
318
+
319
+ #### Data Retrieval
320
+
321
+ ```python
322
+ # Static device information
323
+ status, static_values = client.static_values()
324
+
325
+ # Live sensor values
326
+ status, instant_values = await client.instant_values()
327
+
328
+ # Structured data (grouped by types)
329
+ status, structured_data = await client.instant_values_structured()
330
+ ```
331
+
332
+ #### Utility Methods
333
+
334
+ ```python
335
+ # Get raw data
336
+ raw_data = client.get_raw_data()
337
+ device_data = client.get_device_data()
338
+
339
+ # Reload JSON file
340
+ success = client.reload_data()
341
+ ```
342
+
343
+ ### Available Sample Files
344
+
345
+ The following sample JSON files are available in the repository:
346
+
347
+ - `references/testdaten/suplere/instantvalues.json` - PDPR1H1HAR1V0_FW539224 device
348
+ - `references/testdaten/instantvalues_poolforum_1.json` - Additional sample data
349
+
350
+ ### Mock Client Use Cases
351
+
352
+ #### Unit Tests
353
+
354
+ ```python
355
+ def test_temperature_reading():
356
+ client = MockPooldoseClient("sample_data.json")
357
+ asyncio.run(client.connect())
358
+
359
+ status, values = asyncio.run(client.instant_values())
360
+ assert status.name == "SUCCESS"
361
+ assert values['temperature'][0] == 23.0 # Expected value
362
+ ```
363
+
364
+ #### Data Analysis
365
+
366
+ ```python
367
+ # Analyze all sensor values
368
+ client = MockPooldoseClient("production_data.json")
369
+ await client.connect()
370
+
371
+ status, data = await client.instant_values_structured()
372
+ sensors = data.get('sensor', {})
373
+
374
+ for sensor_name, sensor_data in sensors.items():
375
+ value = sensor_data.get('value')
376
+ unit = sensor_data.get('unit', '')
377
+ print(f"{sensor_name}: {value} {unit}")
378
+ ```
379
+
380
+ #### Integration Tests
381
+
382
+ ```python
383
+ async def test_full_integration():
384
+ client = MockPooldoseClient("integration_sample_data.json")
385
+
386
+ # Test connection
387
+ assert await client.connect() == RequestStatus.SUCCESS
388
+
389
+ # Test static values
390
+ status, static = client.static_values()
391
+ assert status == RequestStatus.SUCCESS
392
+ assert static.sensor_name is not None
393
+
394
+ # Test live values
395
+ status, instant = await client.instant_values()
396
+ assert status == RequestStatus.SUCCESS
397
+ assert 'temperature' in instant
398
+ ```
399
+
400
+ ### Benefits of the Mock System
401
+
402
+ - **Fast**: No network latency
403
+ - **Reliable**: No hardware dependencies
404
+ - **Flexible**: Different scenarios testable
405
+ - **Realistic**: Real device data structures
406
+ - **Compatible**: Same API as real client
407
+
168
408
  ## Example Usage
169
409
 
170
410
  ### Basic Example
411
+
171
412
  ```python
172
413
  import asyncio
173
414
  import json
@@ -292,6 +533,7 @@ if __name__ == "__main__":
292
533
  ### Advanced Usage
293
534
 
294
535
  #### Connection Management
536
+
295
537
  ```python
296
538
  from pooldose.client import PooldoseClient
297
539
  from pooldose.request_status import RequestStatus
@@ -316,6 +558,7 @@ else:
316
558
  ```
317
559
 
318
560
  #### Error Handling
561
+
319
562
  ```python
320
563
  from pooldose.client import PooldoseClient
321
564
 
@@ -335,6 +578,7 @@ else:
335
578
  ```
336
579
 
337
580
  #### Working with Structured Data
581
+
338
582
  ```python
339
583
  # Get all data types at once
340
584
  status, structured_data = await client.instant_values_structured()
@@ -364,6 +608,7 @@ if status == RequestStatus.SUCCESS:
364
608
  ```
365
609
 
366
610
  #### Working with Mappings
611
+
367
612
  ```
368
613
  Mapping Discovery Process:
369
614
  ┌─────────────────┐
@@ -399,11 +644,13 @@ Mapping Discovery Process:
399
644
  ### PooldoseClient Class
400
645
 
401
646
  #### Constructor
647
+
402
648
  ```python
403
649
  PooldoseClient(host, timeout=30, include_sensitive_data=False, use_ssl=False, port=None, ssl_verify=True)
404
650
  ```
405
651
 
406
652
  **Parameters:**
653
+
407
654
  - `host` (str): The hostname or IP address of the device
408
655
  - `timeout` (int): Request timeout in seconds (default: 30)
409
656
  - `include_sensitive_data` (bool): Whether to include sensitive data like WiFi passwords (default: False)
@@ -412,6 +659,7 @@ PooldoseClient(host, timeout=30, include_sensitive_data=False, use_ssl=False, po
412
659
  - `ssl_verify` (bool): Whether to verify SSL certificates when using HTTPS (default: True)
413
660
 
414
661
  #### Methods
662
+
415
663
  - `async connect()` → `RequestStatus` - Connect to device and initialize all components
416
664
  - `static_values()` → `tuple[RequestStatus, StaticValues | None]` - Get static device information
417
665
  - `async instant_values()` → `tuple[RequestStatus, InstantValues | None]` - Get current sensor readings and device state
@@ -419,6 +667,7 @@ PooldoseClient(host, timeout=30, include_sensitive_data=False, use_ssl=False, po
419
667
  - `check_apiversion_supported()` → `tuple[RequestStatus, dict]` - Check API version compatibility
420
668
 
421
669
  #### Properties
670
+
422
671
  - `is_connected: bool` - Check if client is connected to device
423
672
  - `device_info: dict` - Dictionary containing device information
424
673
 
@@ -491,6 +740,7 @@ The `instant_values_structured()` method returns data organized by type:
491
740
  ## Supported Devices
492
741
 
493
742
  This client has been tested with:
743
+
494
744
  - **PoolDose Double/Dual WiFi** (Model: PDPR1H1HAW100, FW: 539187)
495
745
 
496
746
  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`).
@@ -510,6 +760,7 @@ status = await client.connect()
510
760
  ```
511
761
 
512
762
  ### Security Model
763
+
513
764
  ```
514
765
  Data Classification:
515
766
  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
@@ -531,8 +782,9 @@ Data Classification:
531
782
 
532
783
  For detailed release notes and version history, please see [CHANGELOG.md](CHANGELOG.md).
533
784
 
534
- ### Latest Release (0.5.0)
535
- - **BREAKING**: Redesigned API with dictionary-style access (`instant_values["key"]`)
536
- - New structured data method `instant_values_structured()` grouped by type
537
- - Removed deprecated getter methods, enhanced validation, improved error handling
538
- - Complete code modernization and comprehensive test
785
+ ### Latest Release (0.5.1)
786
+
787
+ - **Examples**: Demo scripts for real and mock clients (`examples/` directory)
788
+ - **Device Support**: Added mapping for model `PDPR1H1HAR1V0_FW539224`
789
+ - **Mock Client**: JSON-based testing framework for development without hardware
790
+ - **Fixed**: Removed deprecated references and improved consistency