python-omnilogic-local 0.15.2__py3-none-any.whl → 0.17.0__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 CHANGED
@@ -572,3 +572,44 @@ class OmniLogicAPI:
572
572
  req_body = ET.tostring(body_element, xml_declaration=True, encoding="unicode")
573
573
 
574
574
  return await self.async_send_message(MessageType.SET_SPILLOVER, req_body, False)
575
+
576
+ async def async_set_group_enable(
577
+ self,
578
+ group_id: int,
579
+ enabled: int | bool,
580
+ is_countdown_timer: bool = False,
581
+ start_time_hours: int = 0,
582
+ start_time_minutes: int = 0,
583
+ end_time_hours: int = 0,
584
+ end_time_minutes: int = 0,
585
+ days_active: int = 0,
586
+ recurring: bool = False,
587
+ ) -> None:
588
+ body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})
589
+
590
+ name_element = ET.SubElement(body_element, "Name")
591
+ name_element.text = "RunGroupCmd"
592
+
593
+ parameters_element = ET.SubElement(body_element, "Parameters")
594
+ parameter = ET.SubElement(parameters_element, "Parameter", name="GroupID", dataType="int")
595
+ parameter.text = str(group_id)
596
+ parameter = ET.SubElement(parameters_element, "Parameter", name="Data", dataType="int")
597
+ parameter.text = str(int(enabled))
598
+ parameter = ET.SubElement(parameters_element, "Parameter", name="IsCountDownTimer", dataType="bool")
599
+ parameter.text = str(int(is_countdown_timer))
600
+ parameter = ET.SubElement(parameters_element, "Parameter", name="StartTimeHours", dataType="int")
601
+ parameter.text = str(start_time_hours)
602
+ parameter = ET.SubElement(parameters_element, "Parameter", name="StartTimeMinutes", dataType="int")
603
+ parameter.text = str(start_time_minutes)
604
+ parameter = ET.SubElement(parameters_element, "Parameter", name="EndTimeHours", dataType="int")
605
+ parameter.text = str(end_time_hours)
606
+ parameter = ET.SubElement(parameters_element, "Parameter", name="EndTimeMinutes", dataType="int")
607
+ parameter.text = str(end_time_minutes)
608
+ parameter = ET.SubElement(parameters_element, "Parameter", name="DaysActive", dataType="int")
609
+ parameter.text = str(days_active)
610
+ parameter = ET.SubElement(parameters_element, "Parameter", name="Recurring", dataType="bool")
611
+ parameter.text = str(int(recurring))
612
+
613
+ req_body = ET.tostring(body_element, xml_declaration=True, encoding="unicode")
614
+
615
+ return await self.async_send_message(MessageType.RUN_GROUP_CMD, req_body, False)
File without changes
@@ -0,0 +1,25 @@
1
+ import asyncio
2
+
3
+ import click
4
+
5
+ from pyomnilogic_local.api import OmniLogicAPI
6
+ from pyomnilogic_local.cli.debug import commands as debug
7
+ from pyomnilogic_local.cli.get import commands as get
8
+
9
+
10
+ async def get_omni(host: str) -> OmniLogicAPI:
11
+ return OmniLogicAPI(host, 10444, 5.0)
12
+
13
+
14
+ @click.group()
15
+ @click.pass_context
16
+ @click.option("--host", default="127.0.0.1", help="Hostname or IP address of omnilogic system")
17
+ def entrypoint(ctx: click.Context, host: str) -> None:
18
+ ctx.ensure_object(dict)
19
+ omni = asyncio.run(get_omni(host))
20
+
21
+ ctx.obj["OMNI"] = omni
22
+
23
+
24
+ entrypoint.add_command(debug.debug)
25
+ entrypoint.add_command(get.get)
File without changes
@@ -0,0 +1,95 @@
1
+ # Need to figure out how to resolve the 'Untyped decorator makes function "..." untyped' errors in mypy when using click decorators
2
+ # mypy: disable-error-code="misc"
3
+ import asyncio
4
+ from typing import Literal, overload
5
+
6
+ import click
7
+
8
+ from pyomnilogic_local.api import OmniLogicAPI
9
+ from pyomnilogic_local.cli.utils import async_get_mspconfig, async_get_telemetry
10
+ from pyomnilogic_local.models.filter_diagnostics import FilterDiagnostics
11
+
12
+
13
+ @click.group()
14
+ @click.option("--raw/--no-raw", default=False, help="Output the raw XML from the OmniLogic, do not parse the response")
15
+ @click.pass_context
16
+ def debug(ctx: click.Context, raw: bool) -> None:
17
+ # Container for all get commands
18
+
19
+ ctx.ensure_object(dict)
20
+ ctx.obj["RAW"] = raw
21
+
22
+
23
+ @debug.command()
24
+ @click.pass_context
25
+ def get_mspconfig(ctx: click.Context) -> None:
26
+ mspconfig = asyncio.run(async_get_mspconfig(ctx.obj["OMNI"], ctx.obj["RAW"]))
27
+ click.echo(mspconfig)
28
+
29
+
30
+ @debug.command()
31
+ @click.pass_context
32
+ def get_telemetry(ctx: click.Context) -> None:
33
+ telemetry = asyncio.run(async_get_telemetry(ctx.obj["OMNI"], ctx.obj["RAW"]))
34
+ click.echo(telemetry)
35
+
36
+
37
+ @debug.command()
38
+ @click.pass_context
39
+ def get_alarm_list(ctx: click.Context) -> None:
40
+ alarm_list = asyncio.run(async_get_alarm_list(ctx.obj["OMNI"]))
41
+ click.echo(alarm_list)
42
+
43
+
44
+ async def async_get_alarm_list(omni: OmniLogicAPI) -> str:
45
+ alarm_list = await omni.async_get_alarm_list()
46
+ return alarm_list
47
+
48
+
49
+ @debug.command()
50
+ @click.option("--pool-id", help="System ID of the Body Of Water the filter is associated with")
51
+ @click.option("--filter-id", help="System ID of the filter to request diagnostics for")
52
+ @click.pass_context
53
+ def get_filter_diagnostics(ctx: click.Context, pool_id: int, filter_id: int) -> None:
54
+ filter_diags = asyncio.run(async_get_filter_diagnostics(ctx.obj["OMNI"], pool_id, filter_id, ctx.obj["RAW"]))
55
+ if ctx.obj["RAW"]:
56
+ click.echo(filter_diags)
57
+ else:
58
+ drv1 = chr(filter_diags.get_param_by_name("DriveFWRevisionB1"))
59
+ drv2 = chr(filter_diags.get_param_by_name("DriveFWRevisionB2"))
60
+ drv3 = chr(filter_diags.get_param_by_name("DriveFWRevisionB3"))
61
+ drv4 = chr(filter_diags.get_param_by_name("DriveFWRevisionB4"))
62
+ dfw1 = chr(filter_diags.get_param_by_name("DisplayFWRevisionB1"))
63
+ dfw2 = chr(filter_diags.get_param_by_name("DisplayFWRevisionB2"))
64
+ dfw3 = chr(filter_diags.get_param_by_name("DisplayFWRevisionB3"))
65
+ dfw4 = chr(filter_diags.get_param_by_name("DisplayFWRevisionB4"))
66
+ pow1 = filter_diags.get_param_by_name("PowerMSB")
67
+ pow2 = filter_diags.get_param_by_name("PowerLSB")
68
+ errs = filter_diags.get_param_by_name("ErrorStatus")
69
+ click.echo(
70
+ f"DRIVE FW REV: {drv1}{drv2}.{drv3}{drv4}\n"
71
+ f"DISPLAY FW REV: {dfw1}{dfw2}.{dfw3}.{dfw4}\n"
72
+ f"POWER: {pow1:x}{pow2:x}W\n"
73
+ f"ERROR STATUS: {errs}"
74
+ )
75
+
76
+
77
+ @overload
78
+ async def async_get_filter_diagnostics(omni: OmniLogicAPI, pool_id: int, filter_id: int, raw: Literal[True]) -> str: ...
79
+ @overload
80
+ async def async_get_filter_diagnostics(omni: OmniLogicAPI, pool_id: int, filter_id: int, raw: Literal[False]) -> FilterDiagnostics: ...
81
+ async def async_get_filter_diagnostics(omni: OmniLogicAPI, pool_id: int, filter_id: int, raw: bool) -> FilterDiagnostics | str:
82
+ filter_diags = await omni.async_get_filter_diagnostics(pool_id, filter_id, raw=raw)
83
+ return filter_diags
84
+
85
+
86
+ @debug.command()
87
+ @click.pass_context
88
+ def get_log_config(ctx: click.Context) -> None:
89
+ log_config = asyncio.run(async_get_log_config(ctx.obj["OMNI"]))
90
+ click.echo(log_config)
91
+
92
+
93
+ async def async_get_log_config(omni: OmniLogicAPI) -> str:
94
+ log_config = await omni.async_get_log_config()
95
+ return log_config
File without changes
@@ -0,0 +1,33 @@
1
+ # Need to figure out how to resolve the 'Untyped decorator makes function "..." untyped' errors in mypy when using click decorators
2
+ # mypy: disable-error-code="misc"
3
+ import asyncio
4
+
5
+ import click
6
+
7
+ from pyomnilogic_local.cli.utils import async_get_mspconfig
8
+
9
+
10
+ @click.group()
11
+ @click.pass_context
12
+ def get(ctx: click.Context) -> None:
13
+ # Container for all get commands
14
+
15
+ ctx.ensure_object(dict)
16
+
17
+
18
+ @get.command()
19
+ @click.pass_context
20
+ def lights(ctx: click.Context) -> None:
21
+ mspconfig = asyncio.run(async_get_mspconfig(ctx.obj["OMNI"]))
22
+ # Return data about lights in the backyard
23
+ if mspconfig.backyard.colorlogic_light:
24
+ for light in mspconfig.backyard.colorlogic_light:
25
+ click.echo(light)
26
+
27
+ # Return data about lights in the Body of Water
28
+ if mspconfig.backyard.bow:
29
+ for bow in mspconfig.backyard.bow:
30
+ if bow.colorlogic_light:
31
+ for cl_light in bow.colorlogic_light:
32
+ for k, v in cl_light:
33
+ click.echo(f"{k:15}\t{str(v)}")
@@ -0,0 +1,15 @@
1
+ from pyomnilogic_local.api import OmniLogicAPI
2
+ from pyomnilogic_local.models.mspconfig import MSPConfig
3
+ from pyomnilogic_local.models.telemetry import Telemetry
4
+
5
+
6
+ async def async_get_mspconfig(omni: OmniLogicAPI, raw: bool = False) -> MSPConfig:
7
+ mspconfig: MSPConfig
8
+ mspconfig = await omni.async_get_config(raw=raw)
9
+ return mspconfig
10
+
11
+
12
+ async def async_get_telemetry(omni: OmniLogicAPI, raw: bool = False) -> Telemetry:
13
+ telemetry: Telemetry
14
+ telemetry = await omni.async_get_telemetry(raw=raw)
15
+ return telemetry
@@ -23,6 +23,7 @@ class MessageType(Enum):
23
23
  GET_ALARM_LIST = 304
24
24
  SET_STANDALONE_LIGHT_SHOW = 308
25
25
  SET_SPILLOVER = 311
26
+ RUN_GROUP_CMD = 317
26
27
  RESTORE_IDLE_STATE = 340
27
28
  GET_FILTER_DIAGNOSTIC_INFO = 386
28
29
  HANDSHAKE = 1000
@@ -63,6 +64,9 @@ class OmniType(str, Enum):
63
64
  VALVE_ACTUATOR = "ValveActuator"
64
65
  VIRT_HEATER = "VirtualHeater"
65
66
 
67
+ def __str__(self) -> str:
68
+ return OmniType[self.name].value
69
+
66
70
 
67
71
  # Backyard/BoW
68
72
  class BackyardState(PrettyEnum):
@@ -172,6 +176,9 @@ class ColorLogicShow(PrettyEnum):
172
176
  WARM_WHITE = 25
173
177
  BRIGHT_YELLOW = 26
174
178
 
179
+ def __str__(self) -> str:
180
+ return self.name
181
+
175
182
 
176
183
  class ColorLogicPowerState(PrettyEnum):
177
184
  OFF = 0
@@ -187,6 +194,9 @@ class ColorLogicLightType(str, PrettyEnum):
187
194
  FOUR_ZERO = "COLOR_LOGIC_4_0"
188
195
  TWO_FIVE = "COLOR_LOGIC_2_5"
189
196
 
197
+ def __str__(self) -> str:
198
+ return ColorLogicLightType[self.name].value
199
+
190
200
 
191
201
  class CSADType(str, PrettyEnum):
192
202
  ACID = "ACID"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: python-omnilogic-local
3
- Version: 0.15.2
3
+ Version: 0.17.0
4
4
  Summary: A library for local control of Hayward OmniHub/OmniLogic pool controllers using their local API
5
5
  License: Apache-2.0
6
6
  Author: Chris Jowett
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Dist: click (>=8.0.0,<8.1.0)
15
16
  Requires-Dist: pydantic (>=1.10.17)
16
17
  Requires-Dist: xmltodict (>=0.13.0,<0.14.0)
17
18
  Description-Content-Type: text/markdown
@@ -0,0 +1,26 @@
1
+ pyomnilogic_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ pyomnilogic_local/api.py,sha256=0yC7OMBUZfzBkBiLHT3QBA-B9m30conKzO9TDYruXLw,30540
3
+ pyomnilogic_local/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ pyomnilogic_local/cli/cli.py,sha256=JP3IIwMlV0CtJXa-Zr5Kp_HfzTG-N-B-TADDjPzErNY,633
5
+ pyomnilogic_local/cli/debug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ pyomnilogic_local/cli/debug/commands.py,sha256=1G3I_qJzwby0zYnjofr_tCrT7D4XSw4TZK_ujX9ifkI,3747
7
+ pyomnilogic_local/cli/get/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ pyomnilogic_local/cli/get/commands.py,sha256=EE0WjN3sd9-bslothw4pMs7fi0czk1ACb4ZBSE5A1WQ,1034
9
+ pyomnilogic_local/cli/utils.py,sha256=b485Pe33bumwIOg4v_fmylZ6LN8Vh9cS6SRNaNpL5IE,532
10
+ pyomnilogic_local/cli_legacy.py,sha256=YsLPDuBUM9hDmSiYVfz0H346OtPUgRwiLHfKWUKbD7Q,3930
11
+ pyomnilogic_local/exceptions.py,sha256=7-EYTP-_VgGrA8WWGwQPUE1NGjJEDWB-ovyvSM2iaNY,164
12
+ pyomnilogic_local/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ pyomnilogic_local/models/const.py,sha256=j4HSiPJW5If296yJ-AiIsBI9EdlckF4QkVFIpTLb5C4,51
14
+ pyomnilogic_local/models/filter_diagnostics.py,sha256=74-VjHB-Rf6imeJTYawybA40_m_wb1Dww-Eu4ucGBdo,1577
15
+ pyomnilogic_local/models/leadmessage.py,sha256=XnzXTpLLQzhLQR1OgfAjKmW5N8BBgM7OrntUi1I2VRY,410
16
+ pyomnilogic_local/models/mspconfig.py,sha256=6YUz5e1V25KX0VynT6iwyZyzi8cPUvZwwLSY0M2bTV0,10594
17
+ pyomnilogic_local/models/telemetry.py,sha256=8ncC-10SRQneFmrH-LrnlVTS3Q-oqeXS_EtYKiIfDks,10612
18
+ pyomnilogic_local/models/util.py,sha256=X9jCiU3hFbI0Nc6NSCnvwyVK9XyA3BsiA9W7JYCJmKs,1462
19
+ pyomnilogic_local/omnitypes.py,sha256=31CvXH4FmyelTdZA7NAJQvkilho9qbIPwnymEEQ8d5Y,8067
20
+ pyomnilogic_local/protocol.py,sha256=M2vyj8o_PCKyLEswb6JGpUIdyj_swEJC18KrqcQV4kI,10356
21
+ pyomnilogic_local/util.py,sha256=sLkCn2eWbwP4FRiEgYlfmNxiHPeiWYjeUyvRRhWuNYE,359
22
+ python_omnilogic_local-0.17.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
23
+ python_omnilogic_local-0.17.0.dist-info/METADATA,sha256=bWu4U75I6FIZUh26EHazG8vpTxZUXGtIeyFcxgiRxio,2672
24
+ python_omnilogic_local-0.17.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
25
+ python_omnilogic_local-0.17.0.dist-info/entry_points.txt,sha256=We3r6ccF9wjWKBBSywFoYUJyL1TdGI1Pjw8-0L44kvw,66
26
+ python_omnilogic_local-0.17.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.0
2
+ Generator: poetry-core 2.0.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ omnilogic=pyomnilogic_local.cli.cli:entrypoint
3
+
@@ -1,19 +0,0 @@
1
- pyomnilogic_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- pyomnilogic_local/api.py,sha256=G991ro3UM-ksVg9gGjTArOvZe41MWsSopbcyqPwwdsU,28390
3
- pyomnilogic_local/cli.py,sha256=YsLPDuBUM9hDmSiYVfz0H346OtPUgRwiLHfKWUKbD7Q,3930
4
- pyomnilogic_local/exceptions.py,sha256=7-EYTP-_VgGrA8WWGwQPUE1NGjJEDWB-ovyvSM2iaNY,164
5
- pyomnilogic_local/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- pyomnilogic_local/models/const.py,sha256=j4HSiPJW5If296yJ-AiIsBI9EdlckF4QkVFIpTLb5C4,51
7
- pyomnilogic_local/models/filter_diagnostics.py,sha256=74-VjHB-Rf6imeJTYawybA40_m_wb1Dww-Eu4ucGBdo,1577
8
- pyomnilogic_local/models/leadmessage.py,sha256=XnzXTpLLQzhLQR1OgfAjKmW5N8BBgM7OrntUi1I2VRY,410
9
- pyomnilogic_local/models/mspconfig.py,sha256=6YUz5e1V25KX0VynT6iwyZyzi8cPUvZwwLSY0M2bTV0,10594
10
- pyomnilogic_local/models/telemetry.py,sha256=8ncC-10SRQneFmrH-LrnlVTS3Q-oqeXS_EtYKiIfDks,10612
11
- pyomnilogic_local/models/util.py,sha256=X9jCiU3hFbI0Nc6NSCnvwyVK9XyA3BsiA9W7JYCJmKs,1462
12
- pyomnilogic_local/omnitypes.py,sha256=rmmBo1xKgsHsX9bjbBh-0YPv4lID1jGrNNU1W1m6zBo,7832
13
- pyomnilogic_local/protocol.py,sha256=M2vyj8o_PCKyLEswb6JGpUIdyj_swEJC18KrqcQV4kI,10356
14
- pyomnilogic_local/util.py,sha256=sLkCn2eWbwP4FRiEgYlfmNxiHPeiWYjeUyvRRhWuNYE,359
15
- python_omnilogic_local-0.15.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
16
- python_omnilogic_local-0.15.2.dist-info/METADATA,sha256=JnhXfISXcBHkTvEJjHfYPvhQcc_F2Nx1FvxZvaSqyfo,2634
17
- python_omnilogic_local-0.15.2.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
18
- python_omnilogic_local-0.15.2.dist-info/entry_points.txt,sha256=PUvdumqSijeB0dHH_s5oE2TnWtPWdJSNpSOsn8yTtOo,56
19
- python_omnilogic_local-0.15.2.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- omnilogic=pyomnilogic_local.cli:main
3
-
File without changes