python-omnilogic-local 0.4.1__py3-none-any.whl → 0.4.2__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- pyomnilogic_local/api.py +47 -13
- pyomnilogic_local/cli.py +5 -5
- pyomnilogic_local/models/mspconfig.py +1 -1
- {python_omnilogic_local-0.4.1.dist-info → python_omnilogic_local-0.4.2.dist-info}/METADATA +1 -1
- {python_omnilogic_local-0.4.1.dist-info → python_omnilogic_local-0.4.2.dist-info}/RECORD +7 -7
- {python_omnilogic_local-0.4.1.dist-info → python_omnilogic_local-0.4.2.dist-info}/WHEEL +1 -1
- {python_omnilogic_local-0.4.1.dist-info → python_omnilogic_local-0.4.2.dist-info}/entry_points.txt +0 -0
pyomnilogic_local/api.py
CHANGED
@@ -38,6 +38,16 @@ class OmniLogicAPI:
|
|
38
38
|
...
|
39
39
|
|
40
40
|
async def async_send_message(self, message_type: MessageType, message: str | None, need_response: bool = False) -> str | None:
|
41
|
+
"""Send a message via the Hayward Omni UDP protocol along with properly handling timeouts and responses.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
message_type (MessageType): A selection from MessageType indicating what type of communication you are sending
|
45
|
+
message (str | None): The XML body of the message to deliver
|
46
|
+
need_response (bool, optional): Should a response be received and returned to the caller. Defaults to False.
|
47
|
+
|
48
|
+
Returns:
|
49
|
+
str | None: The response body sent from the Omni if need_response indicates that a response will be sent
|
50
|
+
"""
|
41
51
|
loop = asyncio.get_running_loop()
|
42
52
|
transport, protocol = await loop.create_datagram_endpoint(OmniLogicProtocol, remote_addr=(self.controller_ip, self.controller_port))
|
43
53
|
|
@@ -53,6 +63,11 @@ class OmniLogicAPI:
|
|
53
63
|
return resp
|
54
64
|
|
55
65
|
async def async_get_alarm_list(self) -> str:
|
66
|
+
"""Retrieve a list of alarms from the Omni.
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
str: An XML body indicating any alarms that are present
|
70
|
+
"""
|
56
71
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
57
72
|
|
58
73
|
name_element = ET.SubElement(body_element, "Name")
|
@@ -64,6 +79,14 @@ class OmniLogicAPI:
|
|
64
79
|
|
65
80
|
@to_pydantic(pydantic_type=MSPConfig)
|
66
81
|
async def async_get_config(self) -> str:
|
82
|
+
"""Retrieve the MSPConfig from the Omni, optionally parse it into a pydantic model.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
raw (bool): Do not parse the response into a Pydantic model, just return the raw XML. Defaults to False.
|
86
|
+
|
87
|
+
Returns:
|
88
|
+
MSPConfig|str: Either a parsed .models.mspconfig.MSPConfig object or a str depending on arg raw
|
89
|
+
"""
|
67
90
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
68
91
|
|
69
92
|
name_element = ET.SubElement(body_element, "Name")
|
@@ -75,14 +98,14 @@ class OmniLogicAPI:
|
|
75
98
|
|
76
99
|
@to_pydantic(pydantic_type=FilterDiagnostics)
|
77
100
|
async def async_get_filter_diagnostics(self, pool_id: int, equipment_id: int) -> str:
|
78
|
-
"""
|
101
|
+
"""Retrieve filter diagnostics from the Omni, optionally parse it into a pydantic model.
|
79
102
|
|
80
103
|
Args:
|
81
104
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
82
105
|
equipment_id (int): Which equipment_id within that Pool to address
|
83
106
|
|
84
107
|
Returns:
|
85
|
-
|
108
|
+
FilterDiagnostics|str: Either a parsed .models.mspconfig.FilterDiagnostics object or a str depending on arg raw
|
86
109
|
"""
|
87
110
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
88
111
|
|
@@ -100,10 +123,20 @@ class OmniLogicAPI:
|
|
100
123
|
return await self.async_send_message(MessageType.GET_FILTER_DIAGNOSTIC_INFO, req_body, True)
|
101
124
|
|
102
125
|
async def async_get_log_config(self) -> str:
|
126
|
+
"""Retrieve the logging configuration from the Omni.
|
127
|
+
|
128
|
+
Returns:
|
129
|
+
str: An XML body describing the logging configuration
|
130
|
+
"""
|
103
131
|
return await self.async_send_message(MessageType.REQUEST_LOG_CONFIG, None, True)
|
104
132
|
|
105
133
|
@to_pydantic(pydantic_type=Telemetry)
|
106
134
|
async def async_get_telemetry(self) -> str:
|
135
|
+
"""Retrieve the current telemetry data from the Omni, optionally parse it into a pydantic model.
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
Telemetry|str: Either a parsed .models.telemetry.Telemetry object or a str depending on arg raw
|
139
|
+
"""
|
107
140
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
108
141
|
|
109
142
|
name_element = ET.SubElement(body_element, "Name")
|
@@ -114,7 +147,7 @@ class OmniLogicAPI:
|
|
114
147
|
return await self.async_send_message(MessageType.GET_TELEMETRY, req_body, True)
|
115
148
|
|
116
149
|
async def async_set_heater(self, pool_id: int, equipment_id: int, temperature: int, unit: str) -> None:
|
117
|
-
"""
|
150
|
+
"""Set the temperature for a heater on the Omni
|
118
151
|
|
119
152
|
Args:
|
120
153
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
@@ -123,7 +156,7 @@ class OmniLogicAPI:
|
|
123
156
|
unit (str): The temperature unit to use (either F or C)
|
124
157
|
|
125
158
|
Returns:
|
126
|
-
|
159
|
+
None
|
127
160
|
"""
|
128
161
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
129
162
|
|
@@ -143,7 +176,7 @@ class OmniLogicAPI:
|
|
143
176
|
return await self.async_send_message(MessageType.SET_HEATER_COMMAND, req_body, False)
|
144
177
|
|
145
178
|
async def async_set_solar_heater(self, pool_id: int, equipment_id: int, temperature: int, unit: str) -> None:
|
146
|
-
"""
|
179
|
+
"""Set the solar set point for a heater on the Omni.
|
147
180
|
|
148
181
|
Args:
|
149
182
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
@@ -152,7 +185,7 @@ class OmniLogicAPI:
|
|
152
185
|
unit (str): The temperature unit to use (either F or C)
|
153
186
|
|
154
187
|
Returns:
|
155
|
-
|
188
|
+
None
|
156
189
|
"""
|
157
190
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
158
191
|
|
@@ -172,15 +205,15 @@ class OmniLogicAPI:
|
|
172
205
|
return await self.async_send_message(MessageType.SET_SOLAR_SET_POINT_COMMAND, req_body, False)
|
173
206
|
|
174
207
|
async def async_set_heater_mode(self, pool_id: int, equipment_id: int, mode: HeaterMode) -> None:
|
175
|
-
"""
|
208
|
+
"""Set what mode (Heat/Cool/Auto) the heater should use.
|
176
209
|
|
177
210
|
Args:
|
178
211
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
179
212
|
equipment_id (int): Which equipment_id within that Pool to address
|
180
|
-
|
213
|
+
mode (HeaterMode): What mode should the heater operate under
|
181
214
|
|
182
215
|
Returns:
|
183
|
-
|
216
|
+
None
|
184
217
|
"""
|
185
218
|
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
|
186
219
|
|
@@ -240,13 +273,14 @@ class OmniLogicAPI:
|
|
240
273
|
days_active: int = 0,
|
241
274
|
recurring: bool = False,
|
242
275
|
) -> None:
|
243
|
-
"""
|
276
|
+
"""Control a piece of equipment, turning it on/off or setting a value (E.g.: filter speed), optionally scheduling it.
|
244
277
|
|
245
278
|
Args:
|
246
279
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
247
280
|
equipment_id (int): Which equipment_id within that Pool to address
|
248
281
|
is_on (Union[int,bool]): For most equipment items, True/False to turn on/off.
|
249
282
|
For Variable Speed Pumps, you can optionally provide an int from 0-100 to set the speed percentage with 0 being Off.
|
283
|
+
The interpretation of value depends on the piece of equipment being targeted.
|
250
284
|
is_countdown_timer (bool, optional): For potential future use, included to be "API complete". Defaults to False.
|
251
285
|
startTimeHours (int, optional): For potential future use, included to be "API complete". Defaults to 0.
|
252
286
|
startTimeMinutes (int, optional): For potential future use, included to be "API complete". Defaults to 0.
|
@@ -265,7 +299,7 @@ class OmniLogicAPI:
|
|
265
299
|
parameter.text = str(pool_id)
|
266
300
|
parameter = ET.SubElement(parameters_element, "Parameter", name="equipmentId", dataType="int")
|
267
301
|
parameter.text = str(equipment_id)
|
268
|
-
parameter = ET.SubElement(parameters_element, "Parameter", name="isOn", dataType="int")
|
302
|
+
parameter = ET.SubElement(parameters_element, "Parameter", name="isOn", dataType="int", alias="Data")
|
269
303
|
parameter.text = str(int(is_on))
|
270
304
|
parameter = ET.SubElement(parameters_element, "Parameter", name="IsCountDownTimer", dataType="bool")
|
271
305
|
parameter.text = str(int(is_countdown_timer))
|
@@ -287,7 +321,7 @@ class OmniLogicAPI:
|
|
287
321
|
return await self.async_send_message(MessageType.SET_EQUIPMENT, req_body, False)
|
288
322
|
|
289
323
|
async def async_set_filter_speed(self, pool_id: int, equipment_id: int, speed: int) -> None:
|
290
|
-
"""
|
324
|
+
"""Set the speed for a variable speed filter/pump.
|
291
325
|
|
292
326
|
Args:
|
293
327
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
@@ -328,7 +362,7 @@ class OmniLogicAPI:
|
|
328
362
|
days_active: int = 0,
|
329
363
|
recurring: bool = False,
|
330
364
|
) -> None:
|
331
|
-
"""
|
365
|
+
"""Set the desired light show/speed/brightness for a ColorLogic light.
|
332
366
|
|
333
367
|
Args:
|
334
368
|
pool_id (int): The Pool/BodyOfWater ID that you want to address
|
pyomnilogic_local/cli.py
CHANGED
@@ -49,14 +49,14 @@ async def async_main() -> None:
|
|
49
49
|
# b2=chr(diags.get_param_by_name("DisplayFWRevisionB2"))
|
50
50
|
# b3=chr(diags.get_param_by_name("DisplayFWRevisionB3"))
|
51
51
|
# b4=chr(diags.get_param_by_name("DisplayFWRevisionB4"))
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
52
|
+
# b5 and b6 are whitespace and a null terminator
|
53
|
+
# b5=chr(diags.get_param_by_name("DisplayFWRevisionB5"))
|
54
|
+
# b6=chr(diags.get_param_by_name("DisplayFWRevisionB6"))
|
55
55
|
# print(f"{b1}{b2}.{b3}.{b4}")
|
56
|
-
#
|
56
|
+
# Decode the filter power consumption (don't do this, it's returned already decoded in the telemetry)
|
57
57
|
# p1=diags.get_param_by_name("PowerMSB")
|
58
58
|
# p2=diags.get_param_by_name("PowerLSB")
|
59
|
-
#
|
59
|
+
# The f-string below converts the bytes to hex and displays them. Just get this value from the telemetry, it's easier
|
60
60
|
# print(f"{p1:x}{p2:x}")
|
61
61
|
|
62
62
|
# Fetch logging configuration
|
@@ -140,7 +140,7 @@ class MSPVirtualHeater(OmniBase):
|
|
140
140
|
class MSPColorLogicLight(OmniBase):
|
141
141
|
omni_type: OmniType = OmniType.CL_LIGHT
|
142
142
|
type: ColorLogicLightType | str = Field(alias="Type")
|
143
|
-
v2_active: Literal["yes", "no"] = Field(alias="V2-Active")
|
143
|
+
v2_active: Literal["yes", "no"] | None = Field(alias="V2-Active")
|
144
144
|
|
145
145
|
|
146
146
|
class MSPBoW(OmniBase):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: python-omnilogic-local
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.2
|
4
4
|
Summary: A library for local control of Hayward OmniHub/OmniLogic pool controllers using their local API
|
5
5
|
Home-page: https://github.com/cryptk/python-omnilogic-local
|
6
6
|
License: Apache-2.0
|
@@ -1,17 +1,17 @@
|
|
1
1
|
pyomnilogic_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
pyomnilogic_local/api.py,sha256=
|
3
|
-
pyomnilogic_local/cli.py,sha256=
|
2
|
+
pyomnilogic_local/api.py,sha256=j65JAwp6p2Z4jUt2-0wG2-EYiO_IVZrnuB4G29Jj1qg,21535
|
3
|
+
pyomnilogic_local/cli.py,sha256=jHAhN_VfjgEVbXlvLsPdgNSab-jY8XntpXoek0I1Vfc,3921
|
4
4
|
pyomnilogic_local/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
pyomnilogic_local/models/const.py,sha256=j4HSiPJW5If296yJ-AiIsBI9EdlckF4QkVFIpTLb5C4,51
|
6
6
|
pyomnilogic_local/models/filter_diagnostics.py,sha256=N4YWl9aEMKcWZ4QOlqR68WV9H1WjTtxjs0wHrNojAaU,1532
|
7
7
|
pyomnilogic_local/models/leadmessage.py,sha256=9r6PbIHHzD0tyeKiFUve3WLcjS8uL2Gj6r_96X7l5H8,407
|
8
|
-
pyomnilogic_local/models/mspconfig.py,sha256=
|
8
|
+
pyomnilogic_local/models/mspconfig.py,sha256=fpEAVKoRijZHV_KxdCCnVxNvdhekvkCpiggd8CiOpU8,7871
|
9
9
|
pyomnilogic_local/models/telemetry.py,sha256=jqvNQcBxTsDrPfzSYuev5y4ujVVfGKB7319D_WEX8Tg,9619
|
10
10
|
pyomnilogic_local/models/util.py,sha256=3Qch98NOl5eO-KIOUBnE9ar86MlzbZ0g2LRApMgj-co,1476
|
11
11
|
pyomnilogic_local/protocol.py,sha256=oO05ZPXJWCi3NzJJqfOqegMkkntQbhbDWkOjsPcleLw,9040
|
12
12
|
pyomnilogic_local/types.py,sha256=DcrOtDcPH6i0fsdULcFIAGqr2-YL_GzICJ-4KErTYj0,6304
|
13
13
|
pyomnilogic_local/util.py,sha256=agbRBKnecrYycC9iUmo1aJDjbVg9VxHyq4QY0D8-bfA,359
|
14
|
-
python_omnilogic_local-0.4.
|
15
|
-
python_omnilogic_local-0.4.
|
16
|
-
python_omnilogic_local-0.4.
|
17
|
-
python_omnilogic_local-0.4.
|
14
|
+
python_omnilogic_local-0.4.2.dist-info/METADATA,sha256=df-i2dL7x9NAHXs3myeD-VdqfxdvxmKH47Jo8TwuM_E,2727
|
15
|
+
python_omnilogic_local-0.4.2.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
16
|
+
python_omnilogic_local-0.4.2.dist-info/entry_points.txt,sha256=PUvdumqSijeB0dHH_s5oE2TnWtPWdJSNpSOsn8yTtOo,56
|
17
|
+
python_omnilogic_local-0.4.2.dist-info/RECORD,,
|
{python_omnilogic_local-0.4.1.dist-info → python_omnilogic_local-0.4.2.dist-info}/entry_points.txt
RENAMED
File without changes
|