Skip to content

Commit 2727db9

Browse files
committed
Add turn_on/turn_off methods and is_on/is_ready properties to Filter and Pump
- Filter includes run_preset_speed method for LOW/MEDIUM/HIGH presets - All MSPConfig and Telemetry attributes exposed as properties
1 parent 68da82d commit 2727db9

File tree

7 files changed

+659
-1
lines changed

7 files changed

+659
-1
lines changed

pyomnilogic_local/filter.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,179 @@
11
from pyomnilogic_local._base import OmniEquipment
2+
from pyomnilogic_local.decorators import dirties_state
23
from pyomnilogic_local.models.mspconfig import MSPFilter
34
from pyomnilogic_local.models.telemetry import TelemetryFilter
5+
from pyomnilogic_local.omnitypes import FilterSpeedPresets, FilterState
46

57

68
class Filter(OmniEquipment[MSPFilter, TelemetryFilter]):
79
"""Represents a filter in the OmniLogic system."""
10+
11+
# Expose MSPConfig attributes
12+
@property
13+
def equip_type(self) -> str:
14+
"""The filter type (e.g., FMT_VARIABLE_SPEED_PUMP)."""
15+
return self.mspconfig.equip_type
16+
17+
@property
18+
def max_percent(self) -> int:
19+
"""Maximum pump speed percentage."""
20+
return self.mspconfig.max_percent
21+
22+
@property
23+
def min_percent(self) -> int:
24+
"""Minimum pump speed percentage."""
25+
return self.mspconfig.min_percent
26+
27+
@property
28+
def max_rpm(self) -> int:
29+
"""Maximum pump speed in RPM."""
30+
return self.mspconfig.max_rpm
31+
32+
@property
33+
def min_rpm(self) -> int:
34+
"""Minimum pump speed in RPM."""
35+
return self.mspconfig.min_rpm
36+
37+
@property
38+
def priming_enabled(self) -> bool:
39+
"""Whether priming is enabled for this filter."""
40+
return self.mspconfig.priming_enabled
41+
42+
@property
43+
def low_speed(self) -> int:
44+
"""Low speed preset value."""
45+
return self.mspconfig.low_speed
46+
47+
@property
48+
def medium_speed(self) -> int:
49+
"""Medium speed preset value."""
50+
return self.mspconfig.medium_speed
51+
52+
@property
53+
def high_speed(self) -> int:
54+
"""High speed preset value."""
55+
return self.mspconfig.high_speed
56+
57+
# Expose Telemetry attributes
58+
@property
59+
def state(self) -> FilterState | int:
60+
"""Current filter state."""
61+
return self.telemetry.state
62+
63+
@property
64+
def speed(self) -> int:
65+
"""Current filter speed."""
66+
return self.telemetry.speed
67+
68+
@property
69+
def valve_position(self) -> int:
70+
"""Current valve position."""
71+
return self.telemetry.valve_position
72+
73+
@property
74+
def why_on(self) -> int:
75+
"""Reason why the filter is on."""
76+
return self.telemetry.why_on
77+
78+
@property
79+
def reported_speed(self) -> int:
80+
"""Reported filter speed."""
81+
return self.telemetry.reported_speed
82+
83+
@property
84+
def power(self) -> int:
85+
"""Current power consumption."""
86+
return self.telemetry.power
87+
88+
@property
89+
def last_speed(self) -> int:
90+
"""Last speed setting."""
91+
return self.telemetry.last_speed
92+
93+
# Computed properties
94+
@property
95+
def is_on(self) -> bool:
96+
"""Check if the filter is currently on.
97+
98+
Returns:
99+
True if filter state is ON (1), False otherwise
100+
"""
101+
return self.state in (
102+
FilterState.ON,
103+
FilterState.PRIMING,
104+
FilterState.HEATER_EXTEND,
105+
FilterState.CSAD_EXTEND,
106+
FilterState.FILTER_FORCE_PRIMING,
107+
FilterState.FILTER_SUPERCHLORINATE,
108+
)
109+
110+
@property
111+
def is_ready(self) -> bool:
112+
"""Check if the filter is ready to receive commands.
113+
114+
A filter is considered ready if it's not in a transitional state like
115+
priming, waiting to turn off, or cooling down.
116+
117+
Returns:
118+
True if filter can accept commands, False otherwise
119+
"""
120+
return self.state in (FilterState.OFF, FilterState.ON)
121+
122+
# Control methods
123+
@dirties_state()
124+
async def turn_on(self) -> None:
125+
"""Turn the filter on.
126+
127+
This will turn on the filter at its last used speed setting.
128+
"""
129+
if self.bow_id is None or self.system_id is None:
130+
msg = "Filter bow_id and system_id must be set"
131+
raise ValueError(msg)
132+
133+
await self._api.async_set_equipment(
134+
pool_id=self.bow_id,
135+
equipment_id=self.system_id,
136+
is_on=self.last_speed,
137+
)
138+
139+
@dirties_state()
140+
async def turn_off(self) -> None:
141+
"""Turn the filter off."""
142+
if self.bow_id is None or self.system_id is None:
143+
msg = "Filter bow_id and system_id must be set"
144+
raise ValueError(msg)
145+
146+
await self._api.async_set_equipment(
147+
pool_id=self.bow_id,
148+
equipment_id=self.system_id,
149+
is_on=False,
150+
)
151+
152+
@dirties_state()
153+
async def run_preset_speed(self, speed: FilterSpeedPresets) -> None:
154+
"""Run the filter at a preset speed.
155+
156+
Args:
157+
speed: The preset speed to use (LOW, MEDIUM, or HIGH)
158+
"""
159+
if self.bow_id is None or self.system_id is None:
160+
msg = "Filter bow_id and system_id must be set"
161+
raise ValueError(msg)
162+
163+
speed_value: int
164+
match speed:
165+
case FilterSpeedPresets.LOW:
166+
speed_value = self.low_speed
167+
case FilterSpeedPresets.MEDIUM:
168+
speed_value = self.medium_speed
169+
case FilterSpeedPresets.HIGH:
170+
speed_value = self.high_speed
171+
case _:
172+
msg = f"Invalid speed preset: {speed}"
173+
raise ValueError(msg)
174+
175+
await self._api.async_set_equipment(
176+
pool_id=self.bow_id,
177+
equipment_id=self.system_id,
178+
is_on=speed_value,
179+
)

pyomnilogic_local/omnitypes.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from enum import Enum, Flag, IntEnum, StrEnum
1+
from enum import Enum, Flag, IntEnum, StrEnum, auto
22

33
from .util import PrettyEnum
44

@@ -416,6 +416,12 @@ class FilterWhyOn(IntEnum, PrettyEnum):
416416
UNKNOWN_18 = 18
417417

418418

419+
class FilterSpeedPresets(StrEnum, PrettyEnum):
420+
LOW = auto()
421+
MEDIUM = auto()
422+
HIGH = auto()
423+
424+
419425
# Heaters
420426
class HeaterState(IntEnum, PrettyEnum):
421427
OFF = 0

pyomnilogic_local/pump.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,132 @@
11
from pyomnilogic_local._base import OmniEquipment
2+
from pyomnilogic_local.decorators import dirties_state
23
from pyomnilogic_local.models.mspconfig import MSPPump
34
from pyomnilogic_local.models.telemetry import TelemetryPump
5+
from pyomnilogic_local.omnitypes import PumpState
46

57

68
class Pump(OmniEquipment[MSPPump, TelemetryPump]):
79
"""Represents a pump in the OmniLogic system."""
10+
11+
# Expose MSPConfig attributes
12+
@property
13+
def equip_type(self) -> str:
14+
"""The pump type (e.g., PMP_VARIABLE_SPEED_PUMP)."""
15+
return self.mspconfig.equip_type
16+
17+
@property
18+
def function(self) -> str:
19+
"""The pump function (e.g., PMP_PUMP, PMP_WATER_FEATURE)."""
20+
return self.mspconfig.function
21+
22+
@property
23+
def max_percent(self) -> int:
24+
"""Maximum pump speed percentage."""
25+
return self.mspconfig.max_percent
26+
27+
@property
28+
def min_percent(self) -> int:
29+
"""Minimum pump speed percentage."""
30+
return self.mspconfig.min_percent
31+
32+
@property
33+
def max_rpm(self) -> int:
34+
"""Maximum pump speed in RPM."""
35+
return self.mspconfig.max_rpm
36+
37+
@property
38+
def min_rpm(self) -> int:
39+
"""Minimum pump speed in RPM."""
40+
return self.mspconfig.min_rpm
41+
42+
@property
43+
def priming_enabled(self) -> bool:
44+
"""Whether priming is enabled for this pump."""
45+
return self.mspconfig.priming_enabled
46+
47+
@property
48+
def low_speed(self) -> int:
49+
"""Low speed preset value."""
50+
return self.mspconfig.low_speed
51+
52+
@property
53+
def medium_speed(self) -> int:
54+
"""Medium speed preset value."""
55+
return self.mspconfig.medium_speed
56+
57+
@property
58+
def high_speed(self) -> int:
59+
"""High speed preset value."""
60+
return self.mspconfig.high_speed
61+
62+
# Expose Telemetry attributes
63+
@property
64+
def state(self) -> PumpState | int:
65+
"""Current pump state."""
66+
return self.telemetry.state
67+
68+
@property
69+
def speed(self) -> int:
70+
"""Current pump speed."""
71+
return self.telemetry.speed
72+
73+
@property
74+
def last_speed(self) -> int:
75+
"""Last speed setting."""
76+
return self.telemetry.last_speed
77+
78+
@property
79+
def why_on(self) -> int:
80+
"""Reason why the pump is on."""
81+
return self.telemetry.why_on
82+
83+
# Computed properties
84+
@property
85+
def is_on(self) -> bool:
86+
"""Check if the pump is currently on.
87+
88+
Returns:
89+
True if pump state is ON (1), False otherwise
90+
"""
91+
return self.state == PumpState.ON
92+
93+
@property
94+
def is_ready(self) -> bool:
95+
"""Check if the pump is ready to receive commands.
96+
97+
A pump is considered ready if it's in a stable state (ON or OFF).
98+
99+
Returns:
100+
True if pump can accept commands, False otherwise
101+
"""
102+
return self.state in (PumpState.OFF, PumpState.ON)
103+
104+
# Control methods
105+
@dirties_state()
106+
async def turn_on(self) -> None:
107+
"""Turn the pump on.
108+
109+
This will turn on the pump at its last used speed setting.
110+
"""
111+
if self.bow_id is None or self.system_id is None:
112+
msg = "Pump bow_id and system_id must be set"
113+
raise ValueError(msg)
114+
115+
await self._api.async_set_equipment(
116+
pool_id=self.bow_id,
117+
equipment_id=self.system_id,
118+
is_on=True,
119+
)
120+
121+
@dirties_state()
122+
async def turn_off(self) -> None:
123+
"""Turn the pump off."""
124+
if self.bow_id is None or self.system_id is None:
125+
msg = "Pump bow_id and system_id must be set"
126+
raise ValueError(msg)
127+
128+
await self._api.async_set_equipment(
129+
pool_id=self.bow_id,
130+
equipment_id=self.system_id,
131+
is_on=False,
132+
)

tests/test_chlorinator_bitmask.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Tests for chlorinator bitmask decoding."""
22

3+
# pylint: skip-file
4+
35
from pyomnilogic_local.models.telemetry import TelemetryChlorinator
46

57

tests/test_chlorinator_multibit.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Tests for chlorinator multi-bit field special case handling."""
22

3+
# pylint: skip-file
4+
35
from pyomnilogic_local.models.telemetry import TelemetryChlorinator
46

57

0 commit comments

Comments
 (0)