python-omnilogic-local 0.15.2__tar.gz → 0.20.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.
Files changed (75) hide show
  1. python_omnilogic_local-0.20.2/PKG-INFO +372 -0
  2. python_omnilogic_local-0.20.2/README.md +355 -0
  3. python_omnilogic_local-0.20.2/pyomnilogic_local/__init__.py +22 -0
  4. python_omnilogic_local-0.20.2/pyomnilogic_local/_base.py +166 -0
  5. python_omnilogic_local-0.20.2/pyomnilogic_local/api/__init__.py +14 -0
  6. {python_omnilogic_local-0.15.2/pyomnilogic_local → python_omnilogic_local-0.20.2/pyomnilogic_local/api}/api.py +289 -93
  7. python_omnilogic_local-0.20.2/pyomnilogic_local/api/constants.py +35 -0
  8. python_omnilogic_local-0.20.2/pyomnilogic_local/api/exceptions.py +33 -0
  9. python_omnilogic_local-0.20.2/pyomnilogic_local/api/protocol.py +439 -0
  10. python_omnilogic_local-0.20.2/pyomnilogic_local/backyard.py +196 -0
  11. python_omnilogic_local-0.20.2/pyomnilogic_local/bow.py +331 -0
  12. python_omnilogic_local-0.20.2/pyomnilogic_local/chlorinator.py +430 -0
  13. python_omnilogic_local-0.20.2/pyomnilogic_local/chlorinator_equip.py +82 -0
  14. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/__init__.py +11 -0
  15. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/cli.py +45 -0
  16. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/debug/__init__.py +1 -0
  17. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/debug/commands.py +211 -0
  18. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/__init__.py +1 -0
  19. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/backyard.py +91 -0
  20. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/bows.py +104 -0
  21. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/chlorinators.py +75 -0
  22. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/commands.py +50 -0
  23. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/csads.py +69 -0
  24. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/filters.py +73 -0
  25. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/groups.py +68 -0
  26. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/heaters.py +116 -0
  27. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/lights.py +83 -0
  28. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/pumps.py +71 -0
  29. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/relays.py +79 -0
  30. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/schedules.py +65 -0
  31. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/sensors.py +72 -0
  32. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/get/valves.py +91 -0
  33. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/pcap_utils.py +164 -0
  34. python_omnilogic_local-0.20.2/pyomnilogic_local/cli/utils.py +106 -0
  35. python_omnilogic_local-0.20.2/pyomnilogic_local/collections.py +527 -0
  36. python_omnilogic_local-0.20.2/pyomnilogic_local/colorlogiclight.py +288 -0
  37. python_omnilogic_local-0.20.2/pyomnilogic_local/csad.py +328 -0
  38. python_omnilogic_local-0.20.2/pyomnilogic_local/csad_equip.py +77 -0
  39. python_omnilogic_local-0.20.2/pyomnilogic_local/decorators.py +58 -0
  40. python_omnilogic_local-0.20.2/pyomnilogic_local/filter.py +293 -0
  41. python_omnilogic_local-0.20.2/pyomnilogic_local/groups.py +114 -0
  42. python_omnilogic_local-0.20.2/pyomnilogic_local/heater.py +269 -0
  43. python_omnilogic_local-0.20.2/pyomnilogic_local/heater_equip.py +144 -0
  44. python_omnilogic_local-0.20.2/pyomnilogic_local/models/__init__.py +16 -0
  45. {python_omnilogic_local-0.15.2 → python_omnilogic_local-0.20.2}/pyomnilogic_local/models/const.py +2 -0
  46. python_omnilogic_local-0.20.2/pyomnilogic_local/models/exceptions.py +2 -0
  47. python_omnilogic_local-0.20.2/pyomnilogic_local/models/filter_diagnostics.py +67 -0
  48. python_omnilogic_local-0.20.2/pyomnilogic_local/models/leadmessage.py +43 -0
  49. python_omnilogic_local-0.20.2/pyomnilogic_local/models/mspconfig.py +467 -0
  50. python_omnilogic_local-0.20.2/pyomnilogic_local/models/telemetry.py +572 -0
  51. python_omnilogic_local-0.20.2/pyomnilogic_local/omnilogic.py +322 -0
  52. python_omnilogic_local-0.20.2/pyomnilogic_local/omnitypes.py +571 -0
  53. python_omnilogic_local-0.20.2/pyomnilogic_local/pump.py +275 -0
  54. python_omnilogic_local-0.20.2/pyomnilogic_local/relay.py +128 -0
  55. python_omnilogic_local-0.20.2/pyomnilogic_local/schedule.py +200 -0
  56. python_omnilogic_local-0.20.2/pyomnilogic_local/sensor.py +103 -0
  57. python_omnilogic_local-0.20.2/pyomnilogic_local/system.py +29 -0
  58. python_omnilogic_local-0.20.2/pyomnilogic_local/util.py +48 -0
  59. python_omnilogic_local-0.20.2/pyproject.toml +122 -0
  60. python_omnilogic_local-0.15.2/PKG-INFO +0 -58
  61. python_omnilogic_local-0.15.2/README.md +0 -39
  62. python_omnilogic_local-0.15.2/pyomnilogic_local/__init__.py +0 -0
  63. python_omnilogic_local-0.15.2/pyomnilogic_local/cli.py +0 -102
  64. python_omnilogic_local-0.15.2/pyomnilogic_local/exceptions.py +0 -10
  65. python_omnilogic_local-0.15.2/pyomnilogic_local/models/__init__.py +0 -0
  66. python_omnilogic_local-0.15.2/pyomnilogic_local/models/filter_diagnostics.py +0 -40
  67. python_omnilogic_local-0.15.2/pyomnilogic_local/models/leadmessage.py +0 -16
  68. python_omnilogic_local-0.15.2/pyomnilogic_local/models/mspconfig.py +0 -265
  69. python_omnilogic_local-0.15.2/pyomnilogic_local/models/telemetry.py +0 -264
  70. python_omnilogic_local-0.15.2/pyomnilogic_local/models/util.py +0 -47
  71. python_omnilogic_local-0.15.2/pyomnilogic_local/omnitypes.py +0 -368
  72. python_omnilogic_local-0.15.2/pyomnilogic_local/protocol.py +0 -243
  73. python_omnilogic_local-0.15.2/pyomnilogic_local/util.py +0 -16
  74. python_omnilogic_local-0.15.2/pyproject.toml +0 -133
  75. {python_omnilogic_local-0.15.2 → python_omnilogic_local-0.20.2}/LICENSE +0 -0
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-omnilogic-local
3
+ Version: 0.20.2
4
+ Summary: A library for local control of Hayward OmniHub/OmniLogic pool controllers using their local API
5
+ Author: Chris Jowett, djtimca, garionphx
6
+ Author-email: Chris Jowett <421501+cryptk@users.noreply.github.com>
7
+ License-File: LICENSE
8
+ Requires-Dist: pydantic>=2.0.0,<3.0.0
9
+ Requires-Dist: click>=8.0.0,<9.0.0
10
+ Requires-Dist: xmltodict>=1.0.1,<2.0.0
11
+ Requires-Dist: uv~=0.9.8 ; extra == 'build'
12
+ Requires-Dist: scapy>=2.6.1,<3.0.0 ; extra == 'cli'
13
+ Requires-Python: >=3.13, <4.0.0
14
+ Provides-Extra: build
15
+ Provides-Extra: cli
16
+ Description-Content-Type: text/markdown
17
+
18
+ <div align="center">
19
+
20
+ # Python OmniLogic Local
21
+
22
+ [![PyPI Version](https://img.shields.io/pypi/v/python-omnilogic-local.svg?logo=python&logoColor=fff&style=flat-square)](https://pypi.org/project/python-omnilogic-local/)
23
+ [![Python Versions](https://img.shields.io/pypi/pyversions/python-omnilogic-local.svg?style=flat-square&logo=python&logoColor=fff)](https://pypi.org/project/python-omnilogic-local/)
24
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/cryptk/python-omnilogic-local/build-test.yml?style=flat-square&label=Build)](https://github.com/cryptk/python-omnilogic-local/actions)
25
+ [![License](https://img.shields.io/pypi/l/python-omnilogic-local.svg?style=flat-square)](LICENSE)
26
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=flat-square&logo=buy-me-a-coffee&logoColor=000)](https://www.buymeacoffee.com/cryptk)
27
+
28
+ **A modern Python library for local control of Hayward OmniLogic and OmniHub pool controllers**
29
+
30
+ [Features](#features) • [Installation](#installation) • [Quick Start](#quick-start) • [Documentation](#documentation) • [CLI Tool](#cli-tool)
31
+
32
+ </div>
33
+
34
+ ---
35
+
36
+ ## Overview
37
+
38
+ Python OmniLogic Local provides complete local control over Hayward OmniLogic and OmniHub pool automation systems using their UDP-based XML protocol. Built with modern Python 3.12+, comprehensive type hints, and Pydantic validation, this library offers a async, type-safe interface for pool automation.
39
+
40
+ ## Features
41
+
42
+ ### Equipment Control
43
+ - **Heaters**: Temperature control, mode selection (heat/auto/off), solar support
44
+ - **Pumps & Filters**: Variable speed control, on/off operation, diagnostic information
45
+ - **ColorLogic Lights**: Multiple models supported (2.5, 4.0, UCL, SAM), brightness, speed, show selection
46
+ - **Relays**: Control auxiliary equipment like fountains, deck jets, blowers
47
+ - **Chlorinators**: Timed percent control, enable/disable operation
48
+ - **Groups**: Coordinated equipment control (turn multiple devices on/off together)
49
+ - **Schedules**: Enable/disable automated schedules
50
+
51
+ ### Monitoring & State Management
52
+ - **Real-time Telemetry**: Water temperature, chemical readings, equipment state
53
+ - **Configuration Discovery**: Automatic detection of all equipment and capabilities
54
+ - **Sensor Data**: pH, ORP, TDS, salt levels, flow sensors
55
+ - **Filter Diagnostics**: Last speed, valve positions, priming states
56
+ - **Equipment Hierarchy**: Automatic parent-child relationship tracking
57
+
58
+ ### Developer-Friendly Design
59
+ - **Type Safety**: Comprehensive type hints with strict mypy validation
60
+ - **Async/Await**: Non-blocking asyncio-based API
61
+ - **Pydantic Models**: Automatic validation and serialization
62
+ - **Smart State Management**: Automatic dirty tracking and efficient refreshing
63
+ - **Equipment Collections**: Dict-like and attribute access patterns
64
+ - **Generic Architecture**: Type-safe equipment hierarchy with generics
65
+
66
+ ## Installation
67
+
68
+ **Requirements**: Python 3.12 or higher
69
+
70
+ ```bash
71
+ pip install python-omnilogic-local
72
+ ```
73
+
74
+ **With CLI tools** (includes packet capture utilities):
75
+ ```bash
76
+ pip install python-omnilogic-local[cli]
77
+ ```
78
+
79
+ ## Quick Start
80
+
81
+ ### Basic Usage
82
+
83
+ ```python
84
+ import asyncio
85
+ from pyomnilogic_local import OmniLogic
86
+
87
+ async def main():
88
+ # Connect to your OmniLogic controller
89
+ omni = OmniLogic("192.168.1.100")
90
+
91
+ # Initial refresh to load configuration and state
92
+ await omni.refresh()
93
+
94
+ # Access equipment by name
95
+ pool = omni.backyard.bow["Pool"]
96
+
97
+ # Control heater
98
+ heater = pool.heater
99
+ print(f"Current temperature: {heater.current_temperature}°F")
100
+ print(f"Target temperature: {heater.current_set_point}°F")
101
+
102
+ await heater.set_temperature(85)
103
+ await heater.turn_on()
104
+
105
+ # Refresh to get updated state
106
+ await omni.refresh()
107
+
108
+ # Control lights
109
+ from pyomnilogic_local.omnitypes import ColorLogicBrightness, ColorLogicSpeed
110
+
111
+ light = pool.lights["Pool Light"]
112
+ await light.turn_on()
113
+ await light.set_show(
114
+ show=light.effects.TWILIGHT,
115
+ brightness=ColorLogicBrightness.ONE_HUNDRED_PERCENT,
116
+ speed=ColorLogicSpeed.ONE_TIMES
117
+ )
118
+
119
+ # Control pump speed
120
+ pump = pool.pumps["Pool Pump"]
121
+ await pump.set_speed(75) # Set to 75%
122
+
123
+ asyncio.run(main())
124
+ ```
125
+
126
+ ### Monitoring Equipment State
127
+
128
+ ```python
129
+ async def monitor_pool():
130
+ omni = OmniLogic("192.168.1.100")
131
+ await omni.refresh()
132
+
133
+ pool = omni.backyard.bow["Pool"]
134
+
135
+ # Check multiple equipment states
136
+ print(f"Water temperature: {pool.heater.current_temperature}°F")
137
+ print(f"Heater is {'on' if pool.heater.is_on else 'off'}")
138
+ print(f"Pump speed: {pool.pumps['Main Pump'].current_speed}%")
139
+
140
+ # Check all lights
141
+ for name, light in pool.lights.items():
142
+ if light.is_on:
143
+ print(f"{name}: {light.show.name} @ {light.brightness.name}")
144
+ else:
145
+ print(f"{name}: OFF")
146
+
147
+ # Access chemical sensors
148
+ if pool.sensors:
149
+ for name, sensor in pool.sensors.items():
150
+ print(f"{name}: {sensor.current_reading}")
151
+
152
+ asyncio.run(monitor_pool())
153
+ ```
154
+
155
+ ### Efficient State Updates
156
+
157
+ The library includes intelligent state management to minimize unnecessary API calls:
158
+
159
+ ```python
160
+ # Force immediate refresh
161
+ await omni.refresh(force=True)
162
+
163
+ # Refresh only if data is older than 30 seconds
164
+ await omni.refresh(if_older_than=30.0)
165
+
166
+ # Refresh only if equipment state changed (default after control commands)
167
+ await omni.refresh(if_dirty=True)
168
+ ```
169
+
170
+ ## Documentation
171
+
172
+ ### Equipment Hierarchy
173
+
174
+ ```
175
+ OmniLogic
176
+ ├── Backyard
177
+ │ ├── Bodies of Water (BOW)
178
+ │ │ ├── Heater (single virtual heater)
179
+ │ │ ├── Pumps
180
+ │ │ ├── Filters
181
+ │ │ ├── Chlorinator
182
+ │ │ ├── Lights (ColorLogic)
183
+ │ │ ├── Relays
184
+ │ │ ├── Sensors
185
+ │ │ └── CSAD (Chemical Sensing & Dispensing)
186
+ │ ├── Lights (ColorLogic)
187
+ │ ├── Relays
188
+ │ └── Sensors
189
+ ├── Groups
190
+ └── Schedules
191
+ ```
192
+
193
+ ### Accessing Equipment
194
+
195
+ Equipment can be accessed using dictionary-style or attribute-style syntax:
196
+
197
+ ```python
198
+ # Dictionary access (by name)
199
+ pool = omni.backyard.bow["Pool"]
200
+
201
+ # Heater is a single object (not a collection)
202
+ heater = pool.heater
203
+
204
+ # Most equipment are collections
205
+ for pump_name, pump in pool.pumps.items():
206
+ print(f"Pump: {pump_name} - Speed: {pump.current_speed}%")
207
+
208
+ # Lights, relays, and sensors can be on both BOW and backyard levels
209
+ for light_name, light in pool.lights.items():
210
+ print(f"BOW Light: {light_name}")
211
+
212
+ for light_name, light in omni.backyard.lights.items():
213
+ print(f"Backyard Light: {light_name}")
214
+
215
+ # Groups and schedules are at the OmniLogic level
216
+ for group_name, group in omni.groups.items():
217
+ print(f"Group: {group_name}")
218
+ ```
219
+
220
+ ### Equipment Properties
221
+
222
+ All equipment exposes standard properties:
223
+
224
+ ```python
225
+ equipment.name # Equipment name
226
+ equipment.system_id # Unique system identifier
227
+ equipment.bow_id # Body of water ID (if applicable)
228
+ equipment.is_ready # Whether equipment can accept commands
229
+ equipment.mspconfig # Configuration data
230
+ equipment.telemetry # Real-time state data
231
+ ```
232
+
233
+ ### Control Methods
234
+
235
+ Control methods are async and automatically handle readiness checks:
236
+
237
+ ```python
238
+ from pyomnilogic_local.omnitypes import ColorLogicBrightness, ColorLogicSpeed
239
+
240
+ # All control methods are async
241
+ await heater.turn_on()
242
+ await heater.turn_off()
243
+ await heater.set_temperature(85)
244
+
245
+ # Light show control - brightness and speed are parameters to set_show()
246
+ await light.set_show(
247
+ show=light.effects.CARIBBEAN,
248
+ brightness=ColorLogicBrightness.EIGHTY_PERCENT,
249
+ speed=ColorLogicSpeed.TWO_TIMES
250
+ )
251
+
252
+ # Pump speed control
253
+ await pump.set_speed(75)
254
+
255
+ # State is automatically marked dirty after control commands
256
+ # Refresh to get updated telemetry
257
+ await omni.refresh()
258
+ ```
259
+
260
+ ### Exception Handling
261
+
262
+ The library provides specific exception types:
263
+
264
+ ```python
265
+ from pyomnilogic_local import (
266
+ OmniLogicLocalError, # Base exception
267
+ OmniEquipmentNotReadyError, # Equipment in transitional state
268
+ OmniEquipmentNotInitializedError, # Missing required attributes
269
+ OmniConnectionError, # Network/communication errors
270
+ )
271
+
272
+ try:
273
+ await heater.set_temperature(120) # Too high
274
+ except OmniValidationException as e:
275
+ print(f"Invalid temperature: {e}")
276
+
277
+ try:
278
+ await light.turn_on()
279
+ except OmniEquipmentNotReadyError as e:
280
+ print(f"Light not ready: {e}")
281
+ ```
282
+
283
+ ## CLI Tool
284
+
285
+ The library includes a command-line tool for monitoring and debugging:
286
+
287
+ ```bash
288
+ # Get telemetry data
289
+ omnilogic --host 192.168.1.100 debug get-telemetry
290
+
291
+ # List all equipment
292
+ omnilogic get lights
293
+ omnilogic get pumps
294
+ omnilogic get heaters
295
+
296
+ # Get raw XML responses
297
+ omnilogic debug --raw get-mspconfig
298
+
299
+ # View filter diagnostics
300
+ omnilogic debug get-filter-diagnostics
301
+ ```
302
+
303
+ **Installation with CLI tools**:
304
+ ```bash
305
+ pip install python-omnilogic-local[cli]
306
+ ```
307
+
308
+ ## Supported Equipment
309
+
310
+ ### Fully Supported
311
+ - Pool/Spa Heaters (gas, heat pump, solar, hybrid)
312
+ - Variable Speed Pumps & Filters
313
+ - ColorLogic Lights (2.5, 4.0, UCL, SAM models)
314
+ - Relays (water features, auxiliary equipment)
315
+ - Chlorinators (timed percent control)
316
+ - Sensors (temperature, pH, ORP, TDS, salt, flow)
317
+ - Groups (coordinated equipment control)
318
+ - Schedules (enable/disable)
319
+ - CSAD (Chemical Sensing & Dispensing) - monitoring
320
+
321
+ ### Partial Support
322
+ - CSAD equipment control (monitoring only currently)
323
+ - Some advanced heater configurations
324
+
325
+ > [!NOTE]
326
+ > If your controller has equipment not listed here, please [open an issue](https://github.com/cryptk/python-omnilogic-local/issues) with details about your configuration.
327
+
328
+ ## Development
329
+
330
+ This project uses modern Python tooling:
331
+
332
+ - **Python**: 3.12+ with type hints
333
+ - **Type Checking**: mypy strict mode
334
+ - **Validation**: Pydantic v2
335
+ - **Testing**: pytest with async support
336
+ - **Code Quality**: black, isort, pylint, ruff
337
+ - **Package Management**: uv (optional) or pip
338
+
339
+ ### Running Tests
340
+
341
+ ```bash
342
+ # Install development dependencies
343
+ pip install -e ".[dev]"
344
+
345
+ # Run tests
346
+ pytest
347
+
348
+ # Run with coverage
349
+ pytest --cov=pyomnilogic_local --cov-report=html
350
+
351
+ # Type checking
352
+ mypy pyomnilogic_local
353
+
354
+ # Linting
355
+ pylint pyomnilogic_local
356
+ ```
357
+
358
+ ## Credits
359
+
360
+ This library was made possible by the pioneering work of:
361
+
362
+ - [djtimca](https://github.com/djtimca/) - Original protocol research and implementation
363
+ - [John Sutherland](mailto:garionphx@gmail.com) - Protocol documentation and testing
364
+
365
+ ## Related Projects
366
+
367
+ - [Home Assistant Integration](https://github.com/cryptk/haomnilogic-local) - Use this library with Home Assistant
368
+
369
+ ## Disclaimer
370
+
371
+
372
+ This is an unofficial library and is not affiliated with, endorsed by, or connected to Hayward Industries, Inc. Use at your own risk. The developers are not responsible for any damage to equipment or property resulting from the use of this software.