Skip to content

Commit 994ebb5

Browse files
committed
feat: add EquipmentDict for dual-index equipment access
- Create EquipmentDict collection supporting lookup by name or system_id - Replace list[Equipment] with EquipmentDict in Backyard and Bow classes - Add validation for equipment identifiers and duplicate name warnings - Refactor OmniEquipment to call update() from __init__ for proper hook execution - Add _update_equipment() methods to Backyard and Bow for child equipment updates - Update items() to return (system_id, name, item) tuples This enables intuitive equipment access: backyard.bow["Pool"] or backyard.bow[3] while allowing compatibility with iteration and length operations.
1 parent e050e3e commit 994ebb5

File tree

4 files changed

+57
-41
lines changed

4 files changed

+57
-41
lines changed

pyomnilogic_local/_base.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ def __init__(self, _api: OmniLogicAPI, mspconfig: MSPConfigT, telemetry: Telemet
3737
"""
3838
self._api = _api
3939

40-
self.update_config(mspconfig)
41-
42-
if telemetry is not None:
43-
self.update_telemetry(telemetry)
40+
self.update(mspconfig, telemetry)
4441

4542
@property
4643
def bow_id(self) -> int | None:

pyomnilogic_local/backyard.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import logging
2+
13
from pyomnilogic_local.api.api import OmniLogicAPI
4+
from pyomnilogic_local.collections import EquipmentDict
25
from pyomnilogic_local.models.mspconfig import MSPBackyard
36
from pyomnilogic_local.models.telemetry import Telemetry, TelemetryBackyard
47

@@ -8,42 +11,58 @@
811
from .relay import Relay
912
from .sensor import Sensor
1013

14+
_LOGGER = logging.getLogger(__name__)
15+
1116

1217
class Backyard(OmniEquipment[MSPBackyard, TelemetryBackyard]):
1318
"""Represents the backyard equipment in the OmniLogic system."""
1419

15-
bow: list[Bow] = []
16-
lights: list[ColorLogicLight] = []
17-
relays: list[Relay] = []
18-
sensors: list[Sensor] = []
20+
bow: EquipmentDict[Bow] = EquipmentDict()
21+
lights: EquipmentDict[ColorLogicLight] = EquipmentDict()
22+
relays: EquipmentDict[Relay] = EquipmentDict()
23+
sensors: EquipmentDict[Sensor] = EquipmentDict()
1924

2025
def __init__(self, _api: OmniLogicAPI, mspconfig: MSPBackyard, telemetry: Telemetry) -> None:
2126
super().__init__(_api, mspconfig, telemetry)
2227

28+
def _update_equipment(self, mspconfig: MSPBackyard, telemetry: Telemetry | None) -> None:
29+
"""Update both the configuration and telemetry data for the equipment."""
30+
if telemetry is None:
31+
_LOGGER.warning("No telemetry provided to update Backyard equipment.")
32+
return
2333
self._update_bows(mspconfig, telemetry)
34+
self._update_lights(mspconfig, telemetry)
2435
self._update_relays(mspconfig, telemetry)
2536
self._update_sensors(mspconfig, telemetry)
2637

2738
def _update_bows(self, mspconfig: MSPBackyard, telemetry: Telemetry) -> None:
2839
"""Update the bows based on the MSP configuration."""
2940
if mspconfig.bow is None:
30-
self.bow = []
41+
self.bow = EquipmentDict()
42+
return
43+
44+
self.bow = EquipmentDict([Bow(self._api, bow, telemetry) for bow in mspconfig.bow])
45+
46+
def _update_lights(self, mspconfig: MSPBackyard, telemetry: Telemetry) -> None:
47+
"""Update the lights based on the MSP configuration."""
48+
if mspconfig.colorlogic_light is None:
49+
self.lights = EquipmentDict()
3150
return
3251

33-
self.bow = [Bow(self._api, bow, telemetry) for bow in mspconfig.bow]
52+
self.lights = EquipmentDict([ColorLogicLight(self._api, light, telemetry) for light in mspconfig.colorlogic_light])
3453

3554
def _update_relays(self, mspconfig: MSPBackyard, telemetry: Telemetry) -> None:
3655
"""Update the relays based on the MSP configuration."""
3756
if mspconfig.relay is None:
38-
self.relays = []
57+
self.relays = EquipmentDict()
3958
return
4059

41-
self.relays = [Relay(self._api, relay, telemetry) for relay in mspconfig.relay]
60+
self.relays = EquipmentDict([Relay(self._api, relay, telemetry) for relay in mspconfig.relay])
4261

4362
def _update_sensors(self, mspconfig: MSPBackyard, telemetry: Telemetry) -> None:
4463
"""Update the sensors based on the MSP configuration."""
4564
if mspconfig.sensor is None:
46-
self.sensors = []
65+
self.sensors = EquipmentDict()
4766
return
4867

49-
self.sensors = [Sensor(self._api, sensor, telemetry) for sensor in mspconfig.sensor]
68+
self.sensors = EquipmentDict([Sensor(self._api, sensor, telemetry) for sensor in mspconfig.sensor])

pyomnilogic_local/bow.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pyomnilogic_local._base import OmniEquipment
22
from pyomnilogic_local.api.api import OmniLogicAPI
33
from pyomnilogic_local.chlorinator import Chlorinator
4+
from pyomnilogic_local.collections import EquipmentDict
45
from pyomnilogic_local.colorlogiclight import _LOGGER, ColorLogicLight
56
from pyomnilogic_local.csad import CSAD
67
from pyomnilogic_local.filter import Filter
@@ -15,14 +16,14 @@
1516
class Bow(OmniEquipment[MSPBoW, TelemetryBoW]):
1617
"""Represents a bow in the OmniLogic system."""
1718

18-
filters: list[Filter] = []
19+
filters: EquipmentDict[Filter] = EquipmentDict()
1920
heater: Heater | None = None
20-
relays: list[Relay] = []
21-
sensors: list[Sensor] = []
22-
lights: list[ColorLogicLight] = []
23-
pumps: list[Pump] = []
21+
relays: EquipmentDict[Relay] = EquipmentDict()
22+
sensors: EquipmentDict[Sensor] = EquipmentDict()
23+
lights: EquipmentDict[ColorLogicLight] = EquipmentDict()
24+
pumps: EquipmentDict[Pump] = EquipmentDict()
2425
chlorinator: Chlorinator | None = None
25-
csads: list[CSAD] = []
26+
csads: EquipmentDict[CSAD] = EquipmentDict()
2627

2728
def __init__(self, _api: OmniLogicAPI, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
2829
super().__init__(_api, mspconfig, telemetry)
@@ -37,21 +38,21 @@ def _update_equipment(self, mspconfig: MSPBoW, telemetry: Telemetry | None) -> N
3738
if telemetry is None:
3839
_LOGGER.warning("No telemetry provided to update Bow equipment.")
3940
return
40-
self._update_filters(self.mspconfig, telemetry)
41-
self._update_heater(self.mspconfig, telemetry)
42-
self._update_sensors(self.mspconfig, telemetry)
43-
self._update_lights(self.mspconfig, telemetry)
44-
self._update_pumps(self.mspconfig, telemetry)
45-
self._update_chlorinators(self.mspconfig, telemetry)
46-
self._update_csads(self.mspconfig, telemetry)
41+
self._update_filters(mspconfig, telemetry)
42+
self._update_heater(mspconfig, telemetry)
43+
self._update_sensors(mspconfig, telemetry)
44+
self._update_lights(mspconfig, telemetry)
45+
self._update_pumps(mspconfig, telemetry)
46+
self._update_chlorinators(mspconfig, telemetry)
47+
self._update_csads(mspconfig, telemetry)
4748

4849
def _update_filters(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
4950
"""Update the filters based on the MSP configuration."""
5051
if mspconfig.filter is None:
51-
self.filters = []
52+
self.filters = EquipmentDict()
5253
return
5354

54-
self.filters = [Filter(self._api, filter_, telemetry) for filter_ in mspconfig.filter]
55+
self.filters = EquipmentDict([Filter(self._api, filter_, telemetry) for filter_ in mspconfig.filter])
5556

5657
def _update_heater(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
5758
"""Update the heater based on the MSP configuration."""
@@ -64,34 +65,34 @@ def _update_heater(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
6465
def _update_relays(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
6566
"""Update the relays based on the MSP configuration."""
6667
if mspconfig.relay is None:
67-
self.relays = []
68+
self.relays = EquipmentDict()
6869
return
6970

70-
self.relays = [Relay(self._api, relay, telemetry) for relay in mspconfig.relay]
71+
self.relays = EquipmentDict([Relay(self._api, relay, telemetry) for relay in mspconfig.relay])
7172

7273
def _update_sensors(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
7374
"""Update the sensors based on the MSP configuration."""
7475
if mspconfig.sensor is None:
75-
self.sensors = []
76+
self.sensors = EquipmentDict()
7677
return
7778

78-
self.sensors = [Sensor(self._api, sensor, telemetry) for sensor in mspconfig.sensor]
79+
self.sensors = EquipmentDict([Sensor(self._api, sensor, telemetry) for sensor in mspconfig.sensor])
7980

8081
def _update_lights(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
8182
"""Update the lights based on the MSP configuration."""
8283
if mspconfig.colorlogic_light is None:
83-
self.lights = []
84+
self.lights = EquipmentDict()
8485
return
8586

86-
self.lights = [ColorLogicLight(self._api, light, telemetry) for light in mspconfig.colorlogic_light]
87+
self.lights = EquipmentDict([ColorLogicLight(self._api, light, telemetry) for light in mspconfig.colorlogic_light])
8788

8889
def _update_pumps(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
8990
"""Update the pumps based on the MSP configuration."""
9091
if mspconfig.pump is None:
91-
self.pumps = []
92+
self.pumps = EquipmentDict()
9293
return
9394

94-
self.pumps = [Pump(self._api, pump, telemetry) for pump in mspconfig.pump]
95+
self.pumps = EquipmentDict([Pump(self._api, pump, telemetry) for pump in mspconfig.pump])
9596

9697
def _update_chlorinators(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
9798
"""Update the chlorinators based on the MSP configuration."""
@@ -104,7 +105,7 @@ def _update_chlorinators(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
104105
def _update_csads(self, mspconfig: MSPBoW, telemetry: Telemetry) -> None:
105106
"""Update the CSADs based on the MSP configuration."""
106107
if mspconfig.csad is None:
107-
self.csads = []
108+
self.csads = EquipmentDict()
108109
return
109110

110-
self.csads = [CSAD(self._api, csad, telemetry) for csad in mspconfig.csad]
111+
self.csads = EquipmentDict([CSAD(self._api, csad, telemetry) for csad in mspconfig.csad])

pyomnilogic_local/omnilogic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ def _update_equipment(self) -> None:
5656
self.system = System(self.mspconfig.system)
5757

5858
try:
59-
self.backyard.update_config(self.mspconfig.backyard)
60-
self.backyard.update_telemetry(self.telemetry)
59+
self.backyard.update(self.mspconfig.backyard, self.telemetry)
6160
except AttributeError:
6261
self.backyard = Backyard(self._api, self.mspconfig.backyard, self.telemetry)

0 commit comments

Comments
 (0)