Skip to content

Commit 58f684f

Browse files
committed
docs: enhance docstrings for all equipment classes
1 parent 829f105 commit 58f684f

10 files changed

Lines changed: 696 additions & 30 deletions

File tree

pyomnilogic_local/_base.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,40 @@
1818

1919

2020
class OmniEquipment(Generic[MSPConfigT, TelemetryT]):
21-
"""Base class for OmniLogic equipment.
21+
"""Base class for all OmniLogic equipment.
2222
23-
Generic parameters:
23+
This is an abstract base class that provides common functionality for all equipment
24+
types in the OmniLogic system. It handles configuration updates, telemetry updates,
25+
and provides access to the API for control operations.
26+
27+
All equipment classes inherit from this base and are strongly typed using generic
28+
parameters for their specific configuration and telemetry types.
29+
30+
Generic Parameters:
2431
MSPConfigT: The specific MSP configuration type (e.g., MSPBoW, MSPRelay)
25-
TelemetryT: The specific telemetry type (e.g., TelemetryBoW, TelemetryRelay, or None for equipment without telemetry)
32+
TelemetryT: The specific telemetry type (e.g., TelemetryBoW, TelemetryRelay, or None)
33+
34+
Attributes:
35+
mspconfig: Configuration data from the MSP XML
36+
telemetry: Live telemetry data (may be None for equipment without telemetry)
37+
child_equipment: Dictionary of child equipment indexed by system_id
38+
39+
Properties:
40+
bow_id: The body of water ID this equipment belongs to
41+
name: Equipment name from configuration
42+
system_id: Unique system identifier
43+
omni_type: OmniLogic type identifier
44+
is_ready: Whether equipment can accept commands (checks backyard state)
45+
46+
Example:
47+
Equipment classes should not be instantiated directly. Access them through
48+
the OmniLogic instance:
49+
50+
>>> omni = OmniLogic("192.168.1.100")
51+
>>> await omni.refresh()
52+
>>> # Access equipment through the backyard
53+
>>> pool = omni.backyard.bow["Pool"]
54+
>>> pump = pool.pumps["Main Pump"]
2655
"""
2756

2857
mspconfig: MSPConfigT

pyomnilogic_local/backyard.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,78 @@
1919

2020

2121
class Backyard(OmniEquipment[MSPBackyard, TelemetryBackyard]):
22-
"""Represents the backyard equipment in the OmniLogic system."""
22+
"""Represents the backyard (top-level equipment container) in the OmniLogic system.
23+
24+
The Backyard is the root equipment container that holds all pool and spa
25+
equipment. It contains:
26+
- Bodies of Water (BoW): Pools and spas
27+
- Backyard-level lights: Lights not associated with a specific body of water
28+
- Backyard-level relays: Auxiliary equipment, landscape lighting, etc.
29+
- Backyard-level sensors: Air temperature, etc.
30+
31+
The Backyard also provides system-wide status information including air
32+
temperature, service mode state, and firmware version.
33+
34+
Attributes:
35+
mspconfig: Configuration data for the backyard
36+
telemetry: Real-time system-wide telemetry
37+
bow: Collection of Bodies of Water (pools/spas)
38+
lights: Collection of backyard-level lights
39+
relays: Collection of backyard-level relays
40+
sensors: Collection of backyard-level sensors
41+
42+
Properties (Telemetry):
43+
status_version: Telemetry protocol version number
44+
air_temp: Current air temperature (Fahrenheit)
45+
state: System state (ON, OFF, SERVICE_MODE, CONFIG_MODE, etc.)
46+
config_checksum: Configuration checksum (status_version 11+)
47+
msp_version: MSP firmware version string (status_version 11+)
48+
is_service_mode: True if in any service/config mode
49+
50+
Example:
51+
>>> omni = OmniLogic("192.168.1.100")
52+
>>> await omni.refresh()
53+
>>>
54+
>>> # Access backyard
55+
>>> backyard = omni.backyard
56+
>>>
57+
>>> # Check system status
58+
>>> print(f"Air temp: {backyard.air_temp}°F")
59+
>>> print(f"System state: {backyard.state}")
60+
>>> print(f"Firmware: {backyard.msp_version}")
61+
>>>
62+
>>> # Check service mode
63+
>>> if backyard.is_service_mode:
64+
... print("System is in service mode - equipment cannot be controlled")
65+
>>>
66+
>>> # Access bodies of water
67+
>>> for bow in backyard.bow:
68+
... print(f"Body of Water: {bow.name} ({bow.equip_type})")
69+
>>>
70+
>>> # Access backyard equipment
71+
>>> for light in backyard.lights:
72+
... print(f"Backyard light: {light.name}")
73+
>>>
74+
>>> for relay in backyard.relays:
75+
... print(f"Backyard relay: {relay.name}")
76+
77+
Service Mode:
78+
When the backyard is in service mode (SERVICE_MODE, CONFIG_MODE, or
79+
TIMED_SERVICE_MODE), equipment control is disabled. This typically
80+
occurs during:
81+
- System maintenance
82+
- Configuration changes
83+
- Timed service operations
84+
85+
Always check is_service_mode or is_ready before controlling equipment.
86+
87+
Note:
88+
- The Backyard is the root of the equipment hierarchy
89+
- All equipment belongs to either the Backyard or a Body of Water
90+
- Service mode blocks all equipment control operations
91+
- Configuration changes require backyard state changes
92+
- Air temperature sensor must be configured for air_temp readings
93+
"""
2394

2495
mspconfig: MSPBackyard
2596
telemetry: TelemetryBackyard

pyomnilogic_local/bow.py

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,108 @@
2121

2222

2323
class Bow(OmniEquipment[MSPBoW, TelemetryBoW]):
24-
"""Represents a bow in the OmniLogic system."""
24+
"""Represents a Body of Water (BoW) - pool or spa - in the OmniLogic system.
25+
26+
A Body of Water (commonly abbreviated as BoW) is a pool or spa, along with
27+
all of its associated equipment. Each BoW contains:
28+
- Filtration pumps
29+
- Heating equipment
30+
- Chlorination/sanitization systems
31+
- Chemistry monitoring (CSAD)
32+
- Lighting
33+
- Auxiliary pumps (water features, etc.)
34+
- Relays (jets, blowers, etc.)
35+
- Sensors (water temperature, flow, etc.)
36+
37+
The Bow class provides access to all equipment associated with a specific
38+
pool or spa, as well as water temperature monitoring and spillover control
39+
for pool/spa combination systems.
40+
41+
Attributes:
42+
mspconfig: Configuration data for this body of water
43+
telemetry: Real-time operational data
44+
filters: Collection of filtration pumps
45+
heater: Virtual heater (if configured)
46+
relays: Collection of relays (jets, blowers, aux equipment)
47+
sensors: Collection of sensors (water temp, flow, etc.)
48+
lights: Collection of ColorLogic lights
49+
pumps: Collection of pumps (water features, etc.)
50+
chlorinator: Chlorinator system (if configured)
51+
csads: Collection of CSAD (chemistry) systems
52+
53+
Properties (Configuration):
54+
equip_type: Body of water type (BOW_POOL or BOW_SPA)
55+
supports_spillover: Whether spillover is available
56+
57+
Properties (Telemetry):
58+
water_temp: Current water temperature (Fahrenheit)
59+
flow: True if flow is detected, False otherwise
60+
61+
Control Methods:
62+
set_spillover(speed): Set spillover pump speed (0-100%)
63+
turn_on_spillover(): Turn on spillover at maximum speed
64+
turn_off_spillover(): Turn off spillover
65+
66+
Example:
67+
>>> omni = OmniLogic("192.168.1.100")
68+
>>> await omni.refresh()
69+
>>>
70+
>>> # Access pool
71+
>>> pool = omni.backyard.bow["Pool"]
72+
>>> print(f"Water temp: {pool.water_temp}°F")
73+
>>> print(f"Flow detected: {pool.flow > 0}")
74+
>>>
75+
>>> # Access pool equipment
76+
>>> if pool.heater:
77+
... await pool.heater.set_temperature(85)
78+
>>>
79+
>>> if pool.chlorinator:
80+
... print(f"Salt level: {pool.chlorinator.avg_salt_level} ppm")
81+
>>>
82+
>>> for filter in pool.filters:
83+
... print(f"Filter: {filter.name}, Speed: {filter.speed}%")
84+
>>>
85+
>>> for light in pool.lights:
86+
... await light.set_show(ColorLogicShow25.TROPICAL)
87+
>>>
88+
>>> # Spillover control (pool/spa combo systems)
89+
>>> if pool.supports_spillover:
90+
... await pool.turn_on_spillover()
91+
... await pool.set_spillover(75) # 75% speed
92+
... await pool.turn_off_spillover()
93+
94+
Pool vs Spa:
95+
Bodies of water can be either pools or spas, distinguished by the
96+
equip_type property:
97+
98+
>>> if pool.equip_type == BodyOfWaterType.POOL:
99+
... print("This is a pool")
100+
>>> elif pool.equip_type == BodyOfWaterType.SPA:
101+
... print("This is a spa")
102+
103+
Spillover Systems:
104+
Some installations have combined pool/spa systems with spillover
105+
capability that allows water to flow from spa to pool or vice versa:
106+
107+
- supports_spillover indicates if the feature is available
108+
- Spillover is controlled by a dedicated pump
109+
- Speed range is 0-100% (0 turns spillover off)
110+
- Convenience methods simplify on/off operations
111+
112+
Equipment Collections:
113+
Equipment is stored in EquipmentDict collections which allow access by:
114+
- Name (string): pool.filters["Main Filter"]
115+
- System ID (int): pool.filters[123]
116+
- Index (int): pool.filters[0]
117+
- Iteration: for filter in pool.filters: ...
118+
119+
Note:
120+
- Water temperature returns -1 if sensor not available
121+
- Flow telemetry typically reads 255 or 1 for flow, 0 for no flow, we simplify to bool
122+
- Not all bodies of water have all equipment types
123+
- Some equipment (heater, chlorinator) may be None if not configured
124+
- Spillover operations raise ValueError if not supported
125+
"""
25126

26127
mspconfig: MSPBoW
27128
telemetry: TelemetryBoW
@@ -56,13 +157,17 @@ def water_temp(self) -> int:
56157
return self.telemetry.water_temp
57158

58159
@property
59-
def flow(self) -> int:
160+
def flow(self) -> bool:
60161
"""Current flow sensor reading.
61162
62163
Returns:
63-
Flow value (255 typically indicates flow present, 0 indicates no flow)
164+
bool: True if flow is present, False otherwise.
64165
"""
65-
return self.telemetry.flow
166+
# Flow values:
167+
# 255 seems to indicate "assumed flow", for example, because a filter pump is on
168+
# 1 seems to indicate "certain flow", for example, when there is an actual flow sensor
169+
# 0 indicates no flow
170+
return self.telemetry.flow > 0
66171

67172
# Control methods
68173
@dirties_state()

pyomnilogic_local/colorlogiclight.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,90 @@
2424

2525

2626
class ColorLogicLight(OmniEquipment[MSPColorLogicLight, TelemetryColorLogicLight]):
27-
"""Represents a color logic light."""
27+
"""Represents a ColorLogic or compatible LED light in the OmniLogic system.
28+
29+
ColorLogic lights are intelligent LED pool and spa lights that can display
30+
various color shows, patterns, and effects. The OmniLogic system supports
31+
multiple light models with different capabilities:
32+
33+
Light Models:
34+
- ColorLogic 2.5: Classic model with 10 preset shows
35+
- ColorLogic 4.0: Enhanced model with 15 preset shows
36+
- ColorLogic UCL (UniversaLogic): Universal controller for various lights
37+
- ColorLogic SAM: Smart lighting system
38+
- Pentair and Zodiac compatible lights (limited functionality)
39+
40+
Each light model supports different shows, speeds, and brightness levels.
41+
The ColorLogicLight class automatically handles these differences.
42+
43+
Attributes:
44+
mspconfig: Configuration data for this light from MSP XML
45+
telemetry: Real-time operational state and settings
46+
47+
Properties (Configuration):
48+
model: Light model type (TWO_FIVE, FOUR_ZERO, UCL, SAM, etc.)
49+
v2_active: Whether V2 protocol features are active
50+
effects: List of available light shows for this model
51+
52+
Properties (Telemetry):
53+
state: Current power state (ON, OFF, transitional states)
54+
show: Currently selected light show
55+
speed: Show animation speed (1x, 2x, 4x, 8x)
56+
brightness: Light brightness (25%, 50%, 75%, 100%)
57+
special_effect: Special effect setting
58+
59+
Properties (Computed):
60+
is_on: True if light is currently on
61+
is_ready: True if light can accept commands (not in transitional state)
62+
63+
Control Methods:
64+
turn_on(): Turn on light (starts at saved show)
65+
turn_off(): Turn off light
66+
toggle(): Toggle light on/off
67+
set_show(show): Set light to specific show
68+
set_speed(speed): Set animation speed (1x-8x)
69+
set_brightness(brightness): Set brightness (25%-100%)
70+
71+
Example:
72+
>>> pool = omni.backyard.bow["Pool"]
73+
>>> pool_light = pool.lights["Pool Light"]
74+
>>>
75+
>>> # Check light capabilities
76+
>>> print(f"Light model: {pool_light.model}")
77+
>>> print(f"Available shows: {pool_light.effects}")
78+
>>>
79+
>>> # Check current state
80+
>>> if pool_light.is_on:
81+
... print(f"Show: {pool_light.show}")
82+
... print(f"Speed: {pool_light.speed}")
83+
... print(f"Brightness: {pool_light.brightness}")
84+
>>>
85+
>>> # Control light
86+
>>> await pool_light.turn_on()
87+
>>> await pool_light.set_show(ColorLogicShow25.TROPICAL)
88+
>>> await pool_light.set_speed(ColorLogicSpeed.TWO_TIMES)
89+
>>> await pool_light.set_brightness(ColorLogicBrightness.SEVENTY_FIVE_PERCENT)
90+
>>> await pool_light.turn_off()
91+
92+
Important - Light State Transitions:
93+
ColorLogic lights go through several transitional states when changing
94+
settings. During these states, the light is NOT ready to accept commands:
95+
96+
- FIFTEEN_SECONDS_WHITE: 15-second white period after power on
97+
- CHANGING_SHOW: Actively cycling through shows
98+
- POWERING_OFF: In process of turning off
99+
- COOLDOWN: Cooling down after being turned off
100+
101+
Always check is_ready before sending commands, or wait for state to
102+
stabilize after each command.
103+
104+
Note:
105+
- Different light models support different show sets
106+
- Non-ColorLogic lights (Pentair, Zodiac) have limited control
107+
- Speed and brightness may not be adjustable on all models
108+
- Some shows may require specific light hardware
109+
- V2 protocol enables enhanced features on compatible lights
110+
"""
28111

29112
mspconfig: MSPColorLogicLight
30113
telemetry: TelemetryColorLogicLight

0 commit comments

Comments
 (0)