Skip to content

Commit 75c16e6

Browse files
committed
doc: update README.md
1 parent 16ce86c commit 75c16e6

1 file changed

Lines changed: 341 additions & 26 deletions

File tree

README.md

Lines changed: 341 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,354 @@
1-
# Pyomnilogic Local
1+
<div align="center">
22

3-
<p align="center">
4-
<a href="https://pypi.org/project/python-omnilogic-local/">
5-
<img src="https://img.shields.io/pypi/v/python-omnilogic-local.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
6-
</a>
7-
<img src="https://img.shields.io/pypi/pyversions/python-omnilogic-local.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
8-
<img src="https://img.shields.io/pypi/l/python-omnilogic-local.svg?style=flat-square" alt="License">
9-
<a href="https://www.buymeacoffee.com/cryptk" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 20px !important;" ></a>
10-
</p>
3+
# Python OmniLogic Local
114

12-
A library implementing the UDP XML Local Control api for Hayward OmniLogic and OmniHub pool controllers
5+
[![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/)
6+
[![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/)
7+
[![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)
8+
[![License](https://img.shields.io/pypi/l/python-omnilogic-local.svg?style=flat-square)](LICENSE)
9+
[![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)
10+
11+
**A modern Python library for local control of Hayward OmniLogic and OmniHub pool controllers**
12+
13+
[Features](#features)[Installation](#installation)[Quick Start](#quick-start)[Documentation](#documentation)[CLI Tool](#cli-tool)
14+
15+
</div>
16+
17+
---
18+
19+
## Overview
20+
21+
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.
22+
23+
## Features
24+
25+
### Equipment Control
26+
- **Heaters**: Temperature control, mode selection (heat/auto/off), solar support
27+
- **Pumps & Filters**: Variable speed control, on/off operation, diagnostic information
28+
- **ColorLogic Lights**: Multiple models supported (2.5, 4.0, UCL, SAM), brightness, speed, show selection
29+
- **Relays**: Control auxiliary equipment like fountains, deck jets, blowers
30+
- **Chlorinators**: Timed percent control, enable/disable operation
31+
- **Groups**: Coordinated equipment control (turn multiple devices on/off together)
32+
- **Schedules**: Enable/disable automated schedules
33+
34+
### Monitoring & State Management
35+
- **Real-time Telemetry**: Water temperature, chemical readings, equipment state
36+
- **Configuration Discovery**: Automatic detection of all equipment and capabilities
37+
- **Sensor Data**: pH, ORP, TDS, salt levels, flow sensors
38+
- **Filter Diagnostics**: Last speed, valve positions, priming states
39+
- **Equipment Hierarchy**: Automatic parent-child relationship tracking
40+
41+
### Developer-Friendly Design
42+
- **Type Safety**: Comprehensive type hints with strict mypy validation
43+
- **Async/Await**: Non-blocking asyncio-based API
44+
- **Pydantic Models**: Automatic validation and serialization
45+
- **Smart State Management**: Automatic dirty tracking and efficient refreshing
46+
- **Equipment Collections**: Dict-like and attribute access patterns
47+
- **Generic Architecture**: Type-safe equipment hierarchy with generics
1348

1449
## Installation
1550

16-
This package is published to pypi at https://pypi.org/project/python-omnilogic-local/:
51+
**Requirements**: Python 3.12 or higher
52+
53+
```bash
54+
pip install python-omnilogic-local
55+
```
56+
57+
**With CLI tools** (includes packet capture utilities):
58+
```bash
59+
pip install python-omnilogic-local[cli]
60+
```
61+
62+
## Quick Start
63+
64+
### Basic Usage
65+
66+
```python
67+
import asyncio
68+
from pyomnilogic_local import OmniLogic
69+
70+
async def main():
71+
# Connect to your OmniLogic controller
72+
omni = OmniLogic("192.168.1.100")
73+
74+
# Initial refresh to load configuration and state
75+
await omni.refresh()
76+
77+
# Access equipment by name
78+
pool = omni.backyard.bow["Pool"]
79+
80+
# Control heater
81+
heater = pool.heater
82+
print(f"Current temperature: {heater.current_temperature}°F")
83+
print(f"Target temperature: {heater.current_set_point}°F")
84+
85+
await heater.set_temperature(85)
86+
await heater.turn_on()
87+
88+
# Refresh to get updated state
89+
await omni.refresh()
90+
91+
# Control lights
92+
from pyomnilogic_local.omnitypes import ColorLogicBrightness, ColorLogicSpeed
93+
94+
light = pool.lights["Pool Light"]
95+
await light.turn_on()
96+
await light.set_show(
97+
show=light.effects.TWILIGHT,
98+
brightness=ColorLogicBrightness.ONE_HUNDRED_PERCENT,
99+
speed=ColorLogicSpeed.ONE_TIMES
100+
)
101+
102+
# Control pump speed
103+
pump = pool.pumps["Pool Pump"]
104+
await pump.set_speed(75) # Set to 75%
105+
106+
asyncio.run(main())
107+
```
108+
109+
### Monitoring Equipment State
110+
111+
```python
112+
async def monitor_pool():
113+
omni = OmniLogic("192.168.1.100")
114+
await omni.refresh()
115+
116+
pool = omni.backyard.bow["Pool"]
117+
118+
# Check multiple equipment states
119+
print(f"Water temperature: {pool.heater.current_temperature}°F")
120+
print(f"Heater is {'on' if pool.heater.is_on else 'off'}")
121+
print(f"Pump speed: {pool.pumps['Main Pump'].current_speed}%")
122+
123+
# Check all lights
124+
for name, light in pool.lights.items():
125+
if light.is_on:
126+
print(f"{name}: {light.show.name} @ {light.brightness.name}")
127+
else:
128+
print(f"{name}: OFF")
129+
130+
# Access chemical sensors
131+
if pool.sensors:
132+
for name, sensor in pool.sensors.items():
133+
print(f"{name}: {sensor.current_reading}")
134+
135+
asyncio.run(monitor_pool())
136+
```
137+
138+
### Efficient State Updates
139+
140+
The library includes intelligent state management to minimize unnecessary API calls:
141+
142+
```python
143+
# Force immediate refresh
144+
await omni.refresh(force=True)
145+
146+
# Refresh only if data is older than 30 seconds
147+
await omni.refresh(if_older_than=30.0)
148+
149+
# Refresh only if equipment state changed (default after control commands)
150+
await omni.refresh(if_dirty=True)
151+
```
152+
153+
## Documentation
154+
155+
### Equipment Hierarchy
156+
157+
```
158+
OmniLogic
159+
├── Backyard
160+
│ ├── Bodies of Water (BOW)
161+
│ │ ├── Heater (single virtual heater)
162+
│ │ ├── Pumps
163+
│ │ ├── Filters
164+
│ │ ├── Chlorinator
165+
│ │ ├── Lights (ColorLogic)
166+
│ │ ├── Relays
167+
│ │ ├── Sensors
168+
│ │ └── CSAD (Chemical Sensing & Dispensing)
169+
│ ├── Lights (ColorLogic)
170+
│ ├── Relays
171+
│ └── Sensors
172+
├── Groups
173+
└── Schedules
174+
```
175+
176+
### Accessing Equipment
177+
178+
Equipment can be accessed using dictionary-style or attribute-style syntax:
17179

18-
`pip install python-omnilogic-local`
180+
```python
181+
# Dictionary access (by name)
182+
pool = omni.backyard.bow["Pool"]
19183

20-
## Functionality
184+
# Heater is a single object (not a collection)
185+
heater = pool.heater
21186

22-
This library is still under development and is not yet able to control every function of a Hayward pool controller. The implemented functionality is:
187+
# Most equipment are collections
188+
for pump_name, pump in pool.pumps.items():
189+
print(f"Pump: {pump_name} - Speed: {pump.current_speed}%")
23190

24-
- Pulling the MSP Config
25-
- Polling telemetry
26-
- Polling a list of active alarms
27-
- Polling filter/pump diagnostic information
28-
- Polling the logging configuration
29-
- Setting pool heater temperature
30-
- Turning pool heaters on/off
31-
- Turning other pool equipment on/off, including countdown timers
32-
- Setting filter/pump speed
33-
- Controlling ColorLogic lights including brightness, speed, and selected shows, with support for countdown timers
191+
# Lights, relays, and sensors can be on both BOW and backyard levels
192+
for light_name, light in pool.lights.items():
193+
print(f"BOW Light: {light_name}")
34194

35-
If your controller has functionality outside of this list, please do not hesitate to [Open an Issue](https://github.com/cryptk/python-omnilogic-local/issues)
195+
for light_name, light in omni.backyard.lights.items():
196+
print(f"Backyard Light: {light_name}")
197+
198+
# Groups and schedules are at the OmniLogic level
199+
for group_name, group in omni.groups.items():
200+
print(f"Group: {group_name}")
201+
```
202+
203+
### Equipment Properties
204+
205+
All equipment exposes standard properties:
206+
207+
```python
208+
equipment.name # Equipment name
209+
equipment.system_id # Unique system identifier
210+
equipment.bow_id # Body of water ID (if applicable)
211+
equipment.is_ready # Whether equipment can accept commands
212+
equipment.mspconfig # Configuration data
213+
equipment.telemetry # Real-time state data
214+
```
215+
216+
### Control Methods
217+
218+
Control methods are async and automatically handle readiness checks:
219+
220+
```python
221+
from pyomnilogic_local.omnitypes import ColorLogicBrightness, ColorLogicSpeed
222+
223+
# All control methods are async
224+
await heater.turn_on()
225+
await heater.turn_off()
226+
await heater.set_temperature(85)
227+
228+
# Light show control - brightness and speed are parameters to set_show()
229+
await light.set_show(
230+
show=light.effects.CARIBBEAN,
231+
brightness=ColorLogicBrightness.EIGHTY_PERCENT,
232+
speed=ColorLogicSpeed.TWO_TIMES
233+
)
234+
235+
# Pump speed control
236+
await pump.set_speed(75)
237+
238+
# State is automatically marked dirty after control commands
239+
# Refresh to get updated telemetry
240+
await omni.refresh()
241+
```
242+
243+
### Exception Handling
244+
245+
The library provides specific exception types:
246+
247+
```python
248+
from pyomnilogic_local import (
249+
OmniLogicLocalError, # Base exception
250+
OmniEquipmentNotReadyError, # Equipment in transitional state
251+
OmniEquipmentNotInitializedError, # Missing required attributes
252+
OmniConnectionError, # Network/communication errors
253+
)
254+
255+
try:
256+
await heater.set_temperature(120) # Too high
257+
except OmniValidationException as e:
258+
print(f"Invalid temperature: {e}")
259+
260+
try:
261+
await light.turn_on()
262+
except OmniEquipmentNotReadyError as e:
263+
print(f"Light not ready: {e}")
264+
```
265+
266+
## CLI Tool
267+
268+
The library includes a command-line tool for monitoring and debugging:
269+
270+
```bash
271+
# Get telemetry data
272+
omnilogic --host 192.168.1.100 debug get-telemetry
273+
274+
# List all equipment
275+
omnilogic get lights
276+
omnilogic get pumps
277+
omnilogic get heaters
278+
279+
# Get raw XML responses
280+
omnilogic debug --raw get-mspconfig
281+
282+
# View filter diagnostics
283+
omnilogic debug get-filter-diagnostics
284+
```
285+
286+
**Installation with CLI tools**:
287+
```bash
288+
pip install python-omnilogic-local[cli]
289+
```
290+
291+
## Supported Equipment
292+
293+
### Fully Supported
294+
- Pool/Spa Heaters (gas, heat pump, solar, hybrid)
295+
- Variable Speed Pumps & Filters
296+
- ColorLogic Lights (2.5, 4.0, UCL, SAM models)
297+
- Relays (water features, auxiliary equipment)
298+
- Chlorinators (timed percent control)
299+
- Sensors (temperature, pH, ORP, TDS, salt, flow)
300+
- Groups (coordinated equipment control)
301+
- Schedules (enable/disable)
302+
- CSAD (Chemical Sensing & Dispensing) - monitoring
303+
304+
### Partial Support
305+
- CSAD equipment control (monitoring only currently)
306+
- Some advanced heater configurations
307+
308+
> [!NOTE]
309+
> 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.
310+
311+
## Development
312+
313+
This project uses modern Python tooling:
314+
315+
- **Python**: 3.12+ with type hints
316+
- **Type Checking**: mypy strict mode
317+
- **Validation**: Pydantic v2
318+
- **Testing**: pytest with async support
319+
- **Code Quality**: black, isort, pylint, ruff
320+
- **Package Management**: uv (optional) or pip
321+
322+
### Running Tests
323+
324+
```bash
325+
# Install development dependencies
326+
pip install -e ".[dev]"
327+
328+
# Run tests
329+
pytest
330+
331+
# Run with coverage
332+
pytest --cov=pyomnilogic_local --cov-report=html
333+
334+
# Type checking
335+
mypy pyomnilogic_local
336+
337+
# Linting
338+
pylint pyomnilogic_local
339+
```
36340

37341
## Credits
38342

39-
The work on this library would not have been possible without the efforts of [djtimca](https://github.com/djtimca/) and [John Sutherland](garionphx@gmail.com)
343+
This library was made possible by the pioneering work of:
344+
345+
- [djtimca](https://github.com/djtimca/) - Original protocol research and implementation
346+
- [John Sutherland](mailto:garionphx@gmail.com) - Protocol documentation and testing
347+
348+
## Related Projects
349+
350+
- [Home Assistant Integration](https://github.com/cryptk/haomnilogic-local) - Use this library with Home Assistant
351+
352+
## Disclaimer
353+
354+
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.

0 commit comments

Comments
 (0)