Skip to main content

A library for local control of Hayward OmniHub/OmniLogic pool controllers using their local API

Project description

Python OmniLogic Local

PyPI Version Python Version Tests License Buy Me A Coffee

A modern Python library for local control of Hayward OmniLogic and OmniHub pool controllers

FeaturesInstallationQuick StartDocumentationCLI Tool


Overview

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.14+, comprehensive type hints, and Pydantic validation, this library offers a async, type-safe interface for pool automation.

Features

Equipment Control

  • Heaters: Temperature control, mode selection (heat/auto/off), solar support
  • Pumps & Filters: Variable speed control, on/off operation, diagnostic information
  • ColorLogic Lights: Multiple models supported (2.5, 4.0, UCL, SAM), brightness, speed, show selection
  • Relays: Control auxiliary equipment like fountains, deck jets, blowers
  • Chlorinators: Timed percent control, enable/disable operation
  • Groups: Coordinated equipment control (turn multiple devices on/off together)
  • Schedules: Enable/disable automated schedules

Monitoring & State Management

  • Real-time Telemetry: Water temperature, chemical readings, equipment state
  • Configuration Discovery: Automatic detection of all equipment and capabilities
  • Sensor Data: pH, ORP, TDS, salt levels, flow sensors
  • Filter Diagnostics: Last speed, valve positions, priming states
  • Equipment Hierarchy: Automatic parent-child relationship tracking

Developer-Friendly Design

  • Type Safety: Comprehensive type hints with strict mypy validation
  • Async/Await: Non-blocking asyncio-based API
  • Pydantic Models: Automatic validation and serialization
  • Smart State Management: Automatic dirty tracking and efficient refreshing
  • Equipment Collections: Dict-like and attribute access patterns
  • Generic Architecture: Type-safe equipment hierarchy with generics

Installation

Requirements: Python 3.14 or higher

pip install python-omnilogic-local

With CLI tools (includes packet capture utilities):

pip install python-omnilogic-local[cli]

Quick Start

Basic Usage

import asyncio
from pyomnilogic_local import OmniLogic

async def main():
    # Connect to your OmniLogic controller
    omni = OmniLogic("192.168.1.100")

    # Initial refresh to load configuration and state
    await omni.refresh()

    # Access equipment by name
    pool = omni.backyard.bow["Pool"]

    # Control heater
    heater = pool.heater
    print(f"Current temperature: {heater.current_temperature}°F")
    print(f"Target temperature: {heater.current_set_point}°F")

    await heater.set_temperature(85)
    await heater.turn_on()

    # Refresh to get updated state
    await omni.refresh()

    # Control lights
    from pyomnilogic_local.omnitypes import ColorLogicBrightness, ColorLogicSpeed

    light = pool.lights["Pool Light"]
    await light.turn_on()
    await light.set_show(
        show=light.effects.TWILIGHT,
        brightness=ColorLogicBrightness.ONE_HUNDRED_PERCENT,
        speed=ColorLogicSpeed.ONE_TIMES
    )

    # Control pump speed
    pump = pool.pumps["Pool Pump"]
    await pump.set_speed(75)  # Set to 75%

asyncio.run(main())

Monitoring Equipment State

async def monitor_pool():
    omni = OmniLogic("192.168.1.100")
    await omni.refresh()

    pool = omni.backyard.bow["Pool"]

    # Check multiple equipment states
    print(f"Water temperature: {pool.heater.current_temperature}°F")
    print(f"Heater is {'on' if pool.heater.is_on else 'off'}")
    print(f"Pump speed: {pool.pumps['Main Pump'].current_speed}%")

    # Check all lights
    for name, light in pool.lights.items():
        if light.is_on:
            print(f"{name}: {light.show.name} @ {light.brightness.name}")
        else:
            print(f"{name}: OFF")

    # Access chemical sensors
    if pool.sensors:
        for name, sensor in pool.sensors.items():
            print(f"{name}: {sensor.current_reading}")

asyncio.run(monitor_pool())

Efficient State Updates

The library includes intelligent state management to minimize unnecessary API calls:

# Force immediate refresh
await omni.refresh(force=True)

# Refresh only if data is older than 30 seconds
await omni.refresh(if_older_than=30.0)

# Refresh only if equipment state changed (default after control commands)
await omni.refresh(if_dirty=True)

Documentation

Equipment Hierarchy

OmniLogic
├── Backyard
│   ├── Bodies of Water (BOW)
│   │   ├── Heater (single virtual heater)
│   │   ├── Pumps
│   │   ├── Filters
│   │   ├── Chlorinator
│   │   ├── Lights (ColorLogic)
│   │   ├── Relays
│   │   ├── Sensors
│   │   └── CSAD (Chemical Sensing & Dispensing)
│   ├── Lights (ColorLogic)
│   ├── Relays
│   └── Sensors
├── Groups
└── Schedules

Accessing Equipment

Equipment can be accessed using dictionary-style or attribute-style syntax:

# Dictionary access (by name)
pool = omni.backyard.bow["Pool"]

# Heater is a single object (not a collection)
heater = pool.heater

# Most equipment are collections
for pump_name, pump in pool.pumps.items():
    print(f"Pump: {pump_name} - Speed: {pump.current_speed}%")

# Lights, relays, and sensors can be on both BOW and backyard levels
for light_name, light in pool.lights.items():
    print(f"BOW Light: {light_name}")

for light_name, light in omni.backyard.lights.items():
    print(f"Backyard Light: {light_name}")

# Groups and schedules are at the OmniLogic level
for group_name, group in omni.groups.items():
    print(f"Group: {group_name}")

Equipment Properties

All equipment exposes standard properties:

equipment.name           # Equipment name
equipment.system_id      # Unique system identifier
equipment.bow_id         # Body of water ID (if applicable)
equipment.is_ready       # Whether equipment can accept commands
equipment.mspconfig      # Configuration data
equipment.telemetry      # Real-time state data

Control Methods

Control methods are async and automatically handle readiness checks:

from pyomnilogic_local.omnitypes import ColorLogicBrightness, ColorLogicSpeed

# All control methods are async
await heater.turn_on()
await heater.turn_off()
await heater.set_temperature(85)

# Light show control - brightness and speed are parameters to set_show()
await light.set_show(
    show=light.effects.CARIBBEAN,
    brightness=ColorLogicBrightness.EIGHTY_PERCENT,
    speed=ColorLogicSpeed.TWO_TIMES
)

# Pump speed control
await pump.set_speed(75)

# State is automatically marked dirty after control commands
# Refresh to get updated telemetry
await omni.refresh()

Exception Handling

The library provides specific exception types:

from pyomnilogic_local import (
    OmniLogicLocalError,          # Base exception
    OmniEquipmentNotReadyError,   # Equipment in transitional state
    OmniEquipmentNotInitializedError,  # Missing required attributes
    OmniConnectionError,          # Network/communication errors
)

try:
    await heater.set_temperature(120)  # Too high
except OmniValidationException as e:
    print(f"Invalid temperature: {e}")

try:
    await light.turn_on()
except OmniEquipmentNotReadyError as e:
    print(f"Light not ready: {e}")

CLI Tool

The library includes a command-line tool for monitoring and debugging:

# Get telemetry data
omnilogic --host 192.168.1.100 debug get-telemetry

# List all equipment
omnilogic get lights
omnilogic get pumps
omnilogic get heaters

# Get raw XML responses
omnilogic debug --raw get-mspconfig

# View filter diagnostics
omnilogic debug get-filter-diagnostics

Installation with CLI tools:

pip install python-omnilogic-local[cli]

Supported Equipment

Fully Supported

  • Pool/Spa Heaters (gas, heat pump, solar, hybrid)
  • Variable Speed Pumps & Filters
  • ColorLogic Lights (2.5, 4.0, UCL, SAM models)
  • Relays (water features, auxiliary equipment)
  • Chlorinators (timed percent control)
  • Sensors (temperature, pH, ORP, TDS, salt, flow)
  • Groups (coordinated equipment control)
  • Schedules (enable/disable)
  • CSAD (Chemical Sensing & Dispensing) - monitoring

Partial Support

  • CSAD equipment control (monitoring only currently)
  • Some advanced heater configurations

[!NOTE] If your controller has equipment not listed here, please open an issue with details about your configuration.

Development

This project uses modern Python tooling:

  • Python: 3.14+ with type hints
  • Type Checking: mypy strict mode
  • Validation: Pydantic v2
  • Testing: pytest with async support
  • Code Quality: black, isort, pylint, ruff
  • Package Management: uv (optional) or pip

Running Tests

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=pyomnilogic_local --cov-report=html

# Type checking
mypy pyomnilogic_local

# Linting
pylint pyomnilogic_local

Credits

This library was made possible by the pioneering work of:

  • djtimca - Original protocol research and implementation
  • John Sutherland - Protocol documentation and testing

Related Projects

Disclaimer

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.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_omnilogic_local-0.27.1.tar.gz (83.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_omnilogic_local-0.27.1-py3-none-any.whl (117.7 kB view details)

Uploaded Python 3

File details

Details for the file python_omnilogic_local-0.27.1.tar.gz.

File metadata

  • Download URL: python_omnilogic_local-0.27.1.tar.gz
  • Upload date:
  • Size: 83.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for python_omnilogic_local-0.27.1.tar.gz
Algorithm Hash digest
SHA256 3b62b93a6c53a95a0ed65d981560813279d50638abf4c89f646b1cb0bb71cca9
MD5 0dbadc5f1d259e86f96a0f84a2d03931
BLAKE2b-256 ecd49dd2c11e2c9b475c7b579094f70bb8cb0300ae57cfde71f19bc862240b11

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_omnilogic_local-0.27.1.tar.gz:

Publisher: cd-release.yaml on cryptk/python-omnilogic-local

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_omnilogic_local-0.27.1-py3-none-any.whl.

File metadata

File hashes

Hashes for python_omnilogic_local-0.27.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e1e20c26d2cf5bf2c020bba8835048b97217abc5edd6a7f8d9eee38952dd0549
MD5 5d94e04ff41504bbe34f2014566e45af
BLAKE2b-256 bfc7052b8ac183b9dc26b21f5a6e21d03cd56c6d11732263e3e0e702d3d1bd78

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_omnilogic_local-0.27.1-py3-none-any.whl:

Publisher: cd-release.yaml on cryptk/python-omnilogic-local

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page