python-omnilogic-local 0.26.0__tar.gz → 0.27.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/PKG-INFO +1 -1
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/mock_api.py +8 -2
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/filter_diagnostics.py +12 -2
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/leadmessage.py +1 -1
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/mspconfig.py +6 -1
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/telemetry.py +7 -3
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyproject.toml +3 -8
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/LICENSE +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/README.md +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/__init__.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/_base.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/__init__.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/api.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/constants.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/exceptions.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/protocol.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/backyard.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/bow.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/chlorinator.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/chlorinator_equip.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/__init__.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/cli.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/debug/__init__.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/debug/commands.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/__init__.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/backyard.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/bows.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/chlorinators.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/commands.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/csads.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/filters.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/groups.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/heaters.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/lights.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/pumps.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/relays.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/schedules.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/sensors.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/valves.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/pcap_utils.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/utils.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/collections.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/colorlogiclight.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/csad.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/csad_equip.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/decorators.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/filter.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/groups.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/heater.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/heater_equip.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/__init__.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/const.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/exceptions.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/omnilogic.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/omnitypes.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/pump.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/py.typed +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/relay.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/schedule.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/sensor.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/system.py +0 -0
- {python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-omnilogic-local
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.27.0
|
|
4
4
|
Summary: A library for local control of Hayward OmniHub/OmniLogic pool controllers using their local API
|
|
5
5
|
Author: Chris Jowett, djtimca, garionphx
|
|
6
6
|
Author-email: Chris Jowett <421501+cryptk@users.noreply.github.com>
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/mock_api.py
RENAMED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any, Literal, overload
|
|
8
|
+
from typing import Any, Literal, TypedDict, overload
|
|
9
9
|
|
|
10
10
|
from pyomnilogic_local.models.mspconfig import MSPConfig
|
|
11
11
|
from pyomnilogic_local.models.telemetry import Telemetry
|
|
@@ -13,6 +13,12 @@ from pyomnilogic_local.models.telemetry import Telemetry
|
|
|
13
13
|
_LOGGER = logging.getLogger(__name__)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
class SimData(TypedDict):
|
|
17
|
+
telemetry: str
|
|
18
|
+
msp_config: str
|
|
19
|
+
filepath: str
|
|
20
|
+
|
|
21
|
+
|
|
16
22
|
class OmniLogicMockAPI:
|
|
17
23
|
"""Drop-in replacement for OmniLogicAPI that serves pre-recorded data from one or more JSON files.
|
|
18
24
|
|
|
@@ -43,7 +49,7 @@ class OmniLogicMockAPI:
|
|
|
43
49
|
"""
|
|
44
50
|
paths = filepath.split(",")
|
|
45
51
|
|
|
46
|
-
self._sim_data: list[
|
|
52
|
+
self._sim_data: list[SimData] = []
|
|
47
53
|
for fp in paths:
|
|
48
54
|
path = Path(fp)
|
|
49
55
|
if not path.exists():
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, ValidationError
|
|
4
4
|
from xmltodict import parse as xml_parse
|
|
5
5
|
|
|
6
|
+
from pyomnilogic_local.models.exceptions import OmniParsingError
|
|
7
|
+
|
|
6
8
|
# Example Filter Diagnostics XML:
|
|
7
9
|
#
|
|
8
10
|
# <?xml version="1.0" encoding="UTF-8" ?>
|
|
@@ -46,6 +48,7 @@ class FilterDiagnosticsParameters(BaseModel):
|
|
|
46
48
|
|
|
47
49
|
class FilterDiagnostics(BaseModel):
|
|
48
50
|
model_config = ConfigDict(from_attributes=True)
|
|
51
|
+
_raw: str = PrivateAttr(default="")
|
|
49
52
|
|
|
50
53
|
name: str = Field(alias="Name")
|
|
51
54
|
parameters: list[FilterDiagnosticsParameter] = Field(alias="Parameters")
|
|
@@ -64,4 +67,11 @@ class FilterDiagnostics(BaseModel):
|
|
|
64
67
|
# The XML nests the Parameter entries under a Parameters entry, this is annoying to work with. Here we are adjusting the data to
|
|
65
68
|
# remove that extra level in the data
|
|
66
69
|
data["Response"]["Parameters"] = data["Response"]["Parameters"]["Parameter"]
|
|
67
|
-
|
|
70
|
+
try:
|
|
71
|
+
instance = FilterDiagnostics.model_validate(data["Response"])
|
|
72
|
+
instance._raw = xml
|
|
73
|
+
except ValidationError as exc:
|
|
74
|
+
msg = f"Failed to parse Filter Diagnostics: {exc}"
|
|
75
|
+
raise OmniParsingError(msg) from exc
|
|
76
|
+
else:
|
|
77
|
+
return instance
|
|
@@ -9,6 +9,7 @@ from pydantic import (
|
|
|
9
9
|
BaseModel,
|
|
10
10
|
ConfigDict,
|
|
11
11
|
Field,
|
|
12
|
+
PrivateAttr,
|
|
12
13
|
ValidationError,
|
|
13
14
|
computed_field,
|
|
14
15
|
model_validator,
|
|
@@ -410,6 +411,7 @@ type MSPConfigType = MSPSystem | MSPEquipmentType
|
|
|
410
411
|
|
|
411
412
|
class MSPConfig(BaseModel):
|
|
412
413
|
model_config = ConfigDict(from_attributes=True)
|
|
414
|
+
_raw: str = PrivateAttr(default="")
|
|
413
415
|
|
|
414
416
|
system: MSPSystem = Field(alias="System")
|
|
415
417
|
backyard: MSPBackyard = Field(alias="Backyard")
|
|
@@ -459,7 +461,10 @@ class MSPConfig(BaseModel):
|
|
|
459
461
|
),
|
|
460
462
|
)
|
|
461
463
|
try:
|
|
462
|
-
|
|
464
|
+
instance = MSPConfig.model_validate(data["MSPConfig"], from_attributes=True)
|
|
465
|
+
instance._raw = xml
|
|
463
466
|
except ValidationError as exc:
|
|
464
467
|
msg = f"Failed to parse MSP Configuration: {exc}"
|
|
465
468
|
raise OmniParsingError(msg) from exc
|
|
469
|
+
else:
|
|
470
|
+
return instance
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
from typing import Any, SupportsInt, cast, overload
|
|
5
5
|
|
|
6
|
-
from pydantic import BaseModel, ConfigDict, Field, ValidationError, computed_field
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, ValidationError, computed_field
|
|
7
7
|
from xmltodict import parse as xml_parse
|
|
8
8
|
|
|
9
9
|
from pyomnilogic_local.omnitypes import (
|
|
@@ -492,6 +492,7 @@ class Telemetry(BaseModel):
|
|
|
492
492
|
"""
|
|
493
493
|
|
|
494
494
|
model_config = ConfigDict(from_attributes=True)
|
|
495
|
+
_raw: str = PrivateAttr(default="")
|
|
495
496
|
|
|
496
497
|
version: str = Field(alias="@version")
|
|
497
498
|
backyard: TelemetryBackyard = Field(alias="Backyard")
|
|
@@ -525,7 +526,7 @@ class Telemetry(BaseModel):
|
|
|
525
526
|
|
|
526
527
|
try:
|
|
527
528
|
newvalue = int(value)
|
|
528
|
-
except
|
|
529
|
+
except ValueError, TypeError:
|
|
529
530
|
newvalue = value
|
|
530
531
|
|
|
531
532
|
return key, newvalue
|
|
@@ -552,10 +553,13 @@ class Telemetry(BaseModel):
|
|
|
552
553
|
),
|
|
553
554
|
)
|
|
554
555
|
try:
|
|
555
|
-
|
|
556
|
+
instance = Telemetry.model_validate(data["STATUS"])
|
|
557
|
+
instance._raw = xml
|
|
556
558
|
except ValidationError as exc:
|
|
557
559
|
msg = f"Failed to parse Telemetry: {exc}"
|
|
558
560
|
raise OmniParsingError(msg) from exc
|
|
561
|
+
else:
|
|
562
|
+
return instance
|
|
559
563
|
|
|
560
564
|
def get_telem_by_systemid(self, system_id: int) -> TelemetryType | None:
|
|
561
565
|
for field_name, value in self:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-omnilogic-local"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.27.0"
|
|
4
4
|
description = "A library for local control of Hayward OmniHub/OmniLogic pool controllers using their local API"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14.2"
|
|
@@ -43,14 +43,9 @@ dev = [
|
|
|
43
43
|
|
|
44
44
|
[tool.mypy]
|
|
45
45
|
python_version = "3.14"
|
|
46
|
-
plugins = [
|
|
47
|
-
|
|
48
|
-
]
|
|
49
|
-
# follow_imports = "silent"
|
|
46
|
+
plugins = ["pydantic.mypy"]
|
|
47
|
+
follow_imports = "normal"
|
|
50
48
|
strict = true
|
|
51
|
-
ignore_missing_imports = true
|
|
52
|
-
disallow_subclassing_any = false
|
|
53
|
-
warn_return_any = false
|
|
54
49
|
|
|
55
50
|
[tool.ruff]
|
|
56
51
|
line-length = 140
|
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/__init__.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/api.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/constants.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/exceptions.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/api/protocol.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/backyard.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/chlorinator.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/__init__.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/bows.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/csads.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/filters.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/groups.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/heaters.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/lights.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/pumps.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/relays.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/sensors.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/get/valves.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/pcap_utils.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/cli/utils.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/collections.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/colorlogiclight.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/csad_equip.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/decorators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/heater_equip.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/__init__.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/models/const.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/omnilogic.py
RENAMED
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/omnitypes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_omnilogic_local-0.26.0 → python_omnilogic_local-0.27.0}/pyomnilogic_local/schedule.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|