Skip to content

Commit b0edd9d

Browse files
committed
feat: add is_ready property to base class and expose all telemetry properties
- Implement is_ready in OmniEquipment base class to check backyard service mode state - Update all equipment classes to call super().is_ready before their own readiness checks - Add telemetry properties to Backyard - Add telemetry and config properties to Bow
1 parent 4c8b229 commit b0edd9d

File tree

8 files changed

+143
-14
lines changed

8 files changed

+143
-14
lines changed

pyomnilogic_local/_base.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pyomnilogic_local.api.api import OmniLogicAPI
55
from pyomnilogic_local.models import MSPEquipmentType, Telemetry
66
from pyomnilogic_local.models.telemetry import TelemetryType
7+
from pyomnilogic_local.omnitypes import BackyardState
78

89
if TYPE_CHECKING:
910
from pyomnilogic_local.omnilogic import OmniLogic
@@ -67,6 +68,28 @@ def omni_type(self) -> str | None:
6768
"""The OmniType of the equipment."""
6869
return self.mspconfig.omni_type
6970

71+
@property
72+
def is_ready(self) -> bool:
73+
"""Check if the equipment is ready to accept commands.
74+
75+
Equipment is not ready when the backyard is in service or configuration mode.
76+
This is the base implementation that checks backyard state.
77+
Subclasses should call super().is_ready first and add their own checks.
78+
79+
Returns:
80+
bool: False if backyard is in SERVICE_MODE, CONFIG_MODE, or TIMED_SERVICE_MODE,
81+
True otherwise (equipment-specific checks in subclasses)
82+
"""
83+
# Check if backyard state allows equipment operations
84+
backyard_state = self._omni.backyard.telemetry.state
85+
if backyard_state in (
86+
BackyardState.SERVICE_MODE,
87+
BackyardState.CONFIG_MODE,
88+
BackyardState.TIMED_SERVICE_MODE,
89+
):
90+
return False
91+
return True
92+
7093
def update(self, mspconfig: MSPConfigT, telemetry: Telemetry | None) -> None:
7194
"""Update both the configuration and telemetry data for the equipment."""
7295
self.update_config(mspconfig)

pyomnilogic_local/backyard.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pyomnilogic_local.collections import EquipmentDict
55
from pyomnilogic_local.models.mspconfig import MSPBackyard
66
from pyomnilogic_local.models.telemetry import Telemetry, TelemetryBackyard
7+
from pyomnilogic_local.omnitypes import BackyardState
78

89
from ._base import OmniEquipment
910
from .bow import Bow
@@ -30,6 +31,54 @@ class Backyard(OmniEquipment[MSPBackyard, TelemetryBackyard]):
3031
def __init__(self, omni: "OmniLogic", mspconfig: MSPBackyard, telemetry: Telemetry) -> None:
3132
super().__init__(omni, mspconfig, telemetry)
3233

34+
@property
35+
def status_version(self) -> int:
36+
"""Telemetry status version number."""
37+
return self.telemetry.status_version
38+
39+
@property
40+
def air_temp(self) -> int | None:
41+
"""Current air temperature reading from the backyard sensor.
42+
43+
Note: Temperature is in Fahrenheit. May be None if sensor is not available.
44+
"""
45+
return self.telemetry.air_temp
46+
47+
@property
48+
def state(self) -> BackyardState:
49+
"""Current backyard state (OFF, ON, SERVICE_MODE, CONFIG_MODE, TIMED_SERVICE_MODE)."""
50+
return self.telemetry.state
51+
52+
@property
53+
def config_checksum(self) -> int | None:
54+
"""Configuration checksum value.
55+
56+
Note: Only available when status_version >= 11. Returns None otherwise.
57+
"""
58+
return self.telemetry.config_checksum
59+
60+
@property
61+
def msp_version(self) -> str | None:
62+
"""MSP firmware version string.
63+
64+
Note: Only available when status_version >= 11. Returns None otherwise.
65+
Example: "R0408000"
66+
"""
67+
return self.telemetry.msp_version
68+
69+
@property
70+
def is_service_mode(self) -> bool:
71+
"""Check if the backyard is in any service mode.
72+
73+
Returns:
74+
True if in SERVICE_MODE, CONFIG_MODE, or TIMED_SERVICE_MODE, False otherwise
75+
"""
76+
return self.state in (
77+
BackyardState.SERVICE_MODE,
78+
BackyardState.CONFIG_MODE,
79+
BackyardState.TIMED_SERVICE_MODE,
80+
)
81+
3382
def _update_equipment(self, mspconfig: MSPBackyard, telemetry: Telemetry | None) -> None:
3483
"""Update both the configuration and telemetry data for the equipment."""
3584
if telemetry is None:

pyomnilogic_local/bow.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pyomnilogic_local.heater import Heater
1010
from pyomnilogic_local.models.mspconfig import MSPBoW
1111
from pyomnilogic_local.models.telemetry import Telemetry, TelemetryBoW
12+
from pyomnilogic_local.omnitypes import BodyOfWaterType
1213
from pyomnilogic_local.pump import Pump
1314
from pyomnilogic_local.relay import Relay
1415
from pyomnilogic_local.sensor import Sensor
@@ -35,10 +36,32 @@ def __init__(self, omni: "OmniLogic", mspconfig: MSPBoW, telemetry: Telemetry) -
3536
super().__init__(omni, mspconfig, telemetry)
3637

3738
@property
38-
def equip_type(self) -> str:
39-
"""The equipment type of the bow."""
39+
def equip_type(self) -> BodyOfWaterType | str:
40+
"""The equipment type of the bow (POOL or SPA)."""
4041
return self.mspconfig.equip_type
4142

43+
@property
44+
def supports_spillover(self) -> bool:
45+
"""Whether this body of water supports spillover functionality."""
46+
return self.mspconfig.supports_spillover
47+
48+
@property
49+
def water_temp(self) -> int:
50+
"""Current water temperature reading from the bow sensor.
51+
52+
Note: Temperature is in Fahrenheit. Returns -1 if sensor is not available.
53+
"""
54+
return self.telemetry.water_temp
55+
56+
@property
57+
def flow(self) -> int:
58+
"""Current flow sensor reading.
59+
60+
Returns:
61+
Flow value (255 typically indicates flow present, 0 indicates no flow)
62+
"""
63+
return self.telemetry.flow
64+
4265
def _update_equipment(self, mspconfig: MSPBoW, telemetry: Telemetry | None) -> None:
4366
"""Update both the configuration and telemetry data for the equipment."""
4467
if telemetry is None:

pyomnilogic_local/chlorinator.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,10 @@ def salt_level_status(self) -> str:
303303
def is_ready(self) -> bool:
304304
"""Check if the chlorinator is ready to accept commands.
305305
306-
A chlorinator is considered ready if it is authenticated and has no
307-
critical errors that would prevent it from operating.
306+
A chlorinator is considered ready if:
307+
- The backyard is not in service/config mode (checked by parent class)
308+
- It is authenticated
309+
- It has no critical errors that would prevent it from operating
308310
309311
Returns:
310312
True if chlorinator can accept commands, False otherwise
@@ -313,4 +315,9 @@ def is_ready(self) -> bool:
313315
>>> if chlorinator.is_ready:
314316
... await chlorinator.set_chlorine_level(75)
315317
"""
318+
# First check if backyard is ready
319+
if not super().is_ready:
320+
return False
321+
322+
# Then check chlorinator-specific readiness
316323
return self.is_authenticated and not self.has_error

pyomnilogic_local/colorlogiclight.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,22 @@ def is_ready(self) -> bool:
8383
"""
8484
Returns whether the light is ready to accept commands.
8585
86-
The light is not ready when it is in a transitional state:
87-
- FIFTEEN_SECONDS_WHITE: Light is in the 15-second white period after power on
88-
- CHANGING_SHOW: Light is actively changing between shows
89-
- POWERING_OFF: Light is in the process of turning off
90-
- COOLDOWN: Light is in cooldown period after being turned off
86+
The light is not ready when:
87+
- The backyard is in service/config mode (checked by parent class)
88+
- The light is in a transitional state:
89+
- FIFTEEN_SECONDS_WHITE: Light is in the 15-second white period after power on
90+
- CHANGING_SHOW: Light is actively changing between shows
91+
- POWERING_OFF: Light is in the process of turning off
92+
- COOLDOWN: Light is in cooldown period after being turned off
9193
9294
Returns:
9395
bool: True if the light can accept commands, False otherwise.
9496
"""
97+
# First check if backyard is ready
98+
if not super().is_ready:
99+
return False
100+
101+
# Then check light-specific readiness
95102
return self.state not in [
96103
ColorLogicPowerState.FIFTEEN_SECONDS_WHITE,
97104
ColorLogicPowerState.CHANGING_SHOW,

pyomnilogic_local/csad.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,10 @@ def ph_offset(self) -> float:
278278
def is_ready(self) -> bool:
279279
"""Check if the CSAD is ready to accept commands.
280280
281-
A CSAD is considered ready if it is enabled and in a stable operating mode
282-
(AUTO or MONITORING), not in a transitional or error state.
281+
A CSAD is considered ready if:
282+
- The backyard is not in service/config mode (checked by parent class)
283+
- It is enabled and in a stable operating mode (AUTO, MONITORING, or FORCE_ON)
284+
- Not in a transitional or error state
283285
284286
Returns:
285287
True if CSAD can accept commands, False otherwise
@@ -288,4 +290,9 @@ def is_ready(self) -> bool:
288290
>>> if csad.is_ready:
289291
... await csad.set_mode(CSADMode.AUTO)
290292
"""
293+
# First check if backyard is ready
294+
if not super().is_ready:
295+
return False
296+
297+
# Then check CSAD-specific readiness
291298
return self.is_on and self.mode in (CSADMode.AUTO, CSADMode.MONITORING, CSADMode.FORCE_ON)

pyomnilogic_local/filter.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,18 @@ def is_on(self) -> bool:
115115
def is_ready(self) -> bool:
116116
"""Check if the filter is ready to receive commands.
117117
118-
A filter is considered ready if it's not in a transitional state like
119-
priming, waiting to turn off, or cooling down.
118+
A filter is considered ready if:
119+
- The backyard is not in service/config mode (checked by parent class)
120+
- It's not in a transitional state like priming, waiting to turn off, or cooling down
120121
121122
Returns:
122123
True if filter can accept commands, False otherwise
123124
"""
125+
# First check if backyard is ready
126+
if not super().is_ready:
127+
return False
128+
129+
# Then check filter-specific readiness
124130
return self.state in (FilterState.OFF, FilterState.ON)
125131

126132
# Control methods

pyomnilogic_local/pump.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,18 @@ def is_on(self) -> bool:
9898
def is_ready(self) -> bool:
9999
"""Check if the pump is ready to receive commands.
100100
101-
A pump is considered ready if it's in a stable state (ON or OFF).
101+
A pump is considered ready if:
102+
- The backyard is not in service/config mode (checked by parent class)
103+
- It's in a stable state (ON or OFF)
102104
103105
Returns:
104106
True if pump can accept commands, False otherwise
105107
"""
108+
# First check if backyard is ready
109+
if not super().is_ready:
110+
return False
111+
112+
# Then check pump-specific readiness
106113
return self.state in (PumpState.OFF, PumpState.ON)
107114

108115
# Control methods

0 commit comments

Comments
 (0)