Skip to content

Commit

Permalink
feat: more csad (#62)
Browse files Browse the repository at this point in the history
* feat: add more CSAD data

* ci: update pre-commit repos

* chore: update pyproject.toml

* chore: more testing/linting updates

* chore: adjust formatting more

* chore: adjust formatting more
  • Loading branch information
cryptk committed Jan 9, 2025
1 parent 3781902 commit c3e39df
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 213 deletions.
16 changes: 8 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ default_stages: [ commit ]

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v5.0.0
hooks:
- id: debug-statements
- id: check-builtin-literals
Expand All @@ -18,35 +18,35 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/python-poetry/poetry
rev: 1.7.0
rev: 2.0.0
hooks:
- id: poetry-check
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 23.11.0
rev: 24.10.0
hooks:
- id: black
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
rev: v2.3.0
hooks:
- id: codespell
exclude: poetry.lock
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.1.6
rev: v0.9.0
hooks:
- id: ruff
args:
- --fix
- repo: https://github.com/pylint-dev/pylint
rev: v3.2.3
rev: v3.3.3
hooks:
- id: pylint
additional_dependencies: [ "pydantic>=1.10.17", "xmltodict" ]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.0
rev: v1.14.1
hooks:
- id: mypy
exclude: cli.py
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"--cov-report=xml:coverage.xml",
"tests"
],
"mypy-type-checker.importStrategy": "fromEnvironment",
"python.analysis.typeCheckingMode": "basic",
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
Expand Down
81 changes: 4 additions & 77 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 43 additions & 13 deletions pyomnilogic_local/api.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# pylint: disable=too-many-positional-arguments
from __future__ import annotations

import asyncio
import logging
from typing import Literal, overload
import xml.etree.ElementTree as ET
from typing import Literal, overload

from .models.filter_diagnostics import FilterDiagnostics
from .models.mspconfig import MSPConfig
from .models.telemetry import Telemetry
from .models.util import to_pydantic
from .protocol import OmniLogicProtocol
from .types import (
from .omnitypes import (
ColorLogicBrightness,
ColorLogicShow,
ColorLogicSpeed,
HeaterMode,
MessageType,
)
from .protocol import OmniLogicProtocol

_LOGGER = logging.getLogger(__name__)

Expand All @@ -30,12 +31,10 @@ def __init__(self, controller_ip: str, controller_port: int, response_timeout: f
self._protocol_factory = OmniLogicProtocol

@overload
async def async_send_message(self, message_type: MessageType, message: str | None, need_response: Literal[True]) -> str:
...
async def async_send_message(self, message_type: MessageType, message: str | None, need_response: Literal[True]) -> str: ...

@overload
async def async_send_message(self, message_type: MessageType, message: str | None, need_response: Literal[False]) -> None:
...
async def async_send_message(self, message_type: MessageType, message: str | None, need_response: Literal[False]) -> None: ...

async def async_send_message(self, message_type: MessageType, message: str | None, need_response: bool = False) -> str | None:
"""Send a message via the Hayward Omni UDP protocol along with properly handling timeouts and responses.
Expand Down Expand Up @@ -97,7 +96,11 @@ async def async_get_config(self) -> str:
return await self.async_send_message(MessageType.REQUEST_CONFIGURATION, req_body, True)

@to_pydantic(pydantic_type=FilterDiagnostics)
async def async_get_filter_diagnostics(self, pool_id: int, equipment_id: int) -> str:
async def async_get_filter_diagnostics(
self,
pool_id: int,
equipment_id: int,
) -> str:
"""Retrieve filter diagnostics from the Omni, optionally parse it into a pydantic model.
Args:
Expand Down Expand Up @@ -146,7 +149,13 @@ async def async_get_telemetry(self) -> str:

return await self.async_send_message(MessageType.GET_TELEMETRY, req_body, True)

async def async_set_heater(self, pool_id: int, equipment_id: int, temperature: int, unit: str) -> None:
async def async_set_heater(
self,
pool_id: int,
equipment_id: int,
temperature: int,
unit: str,
) -> None:
"""Set the temperature for a heater on the Omni
Args:
Expand Down Expand Up @@ -175,7 +184,13 @@ async def async_set_heater(self, pool_id: int, equipment_id: int, temperature: i

return await self.async_send_message(MessageType.SET_HEATER_COMMAND, req_body, False)

async def async_set_solar_heater(self, pool_id: int, equipment_id: int, temperature: int, unit: str) -> None:
async def async_set_solar_heater(
self,
pool_id: int,
equipment_id: int,
temperature: int,
unit: str,
) -> None:
"""Set the solar set point for a heater on the Omni.
Args:
Expand Down Expand Up @@ -204,7 +219,12 @@ async def async_set_solar_heater(self, pool_id: int, equipment_id: int, temperat

return await self.async_send_message(MessageType.SET_SOLAR_SET_POINT_COMMAND, req_body, False)

async def async_set_heater_mode(self, pool_id: int, equipment_id: int, mode: HeaterMode) -> None:
async def async_set_heater_mode(
self,
pool_id: int,
equipment_id: int,
mode: HeaterMode,
) -> None:
"""Set what mode (Heat/Cool/Auto) the heater should use.
Args:
Expand Down Expand Up @@ -232,7 +252,12 @@ async def async_set_heater_mode(self, pool_id: int, equipment_id: int, mode: Hea

return await self.async_send_message(MessageType.SET_HEATER_MODE_COMMAND, req_body, False)

async def async_set_heater_enable(self, pool_id: int, equipment_id: int, enabled: int | bool) -> None:
async def async_set_heater_enable(
self,
pool_id: int,
equipment_id: int,
enabled: int | bool,
) -> None:
"""async_set_heater_enable handles sending a SetHeaterEnable XML API call to the Hayward Omni pool controller
Args:
Expand Down Expand Up @@ -472,7 +497,12 @@ async def async_set_chlorinator_params(

return await self.async_send_message(MessageType.SET_CHLOR_PARAMS, req_body, False)

async def async_set_chlorinator_superchlorinate(self, pool_id: int, equipment_id: int, enabled: int | bool) -> None:
async def async_set_chlorinator_superchlorinate(
self,
pool_id: int,
equipment_id: int,
enabled: int | bool,
) -> None:
body_element = ET.Element("Request", {"xmlns": "http://nextgen.hayward.com/api"})

name_element = ET.SubElement(body_element, "Name")
Expand Down
1 change: 0 additions & 1 deletion pyomnilogic_local/cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python3

import asyncio
import logging
import os
Expand Down
1 change: 1 addition & 0 deletions pyomnilogic_local/models/filter_diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Config:
orm_mode = True

def get_param_by_name(self, name: str) -> int:
# pylint: disable=not-an-iterable
return [param.value for param in self.parameters if param.name == name][0]

@staticmethod
Expand Down
4 changes: 2 additions & 2 deletions pyomnilogic_local/models/mspconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from xmltodict import parse as xml_parse

from ..exceptions import OmniParsingException
from ..types import (
from ..omnitypes import (
BodyOfWaterType,
ChlorinatorCellType,
ChlorinatorDispenserType,
Expand Down Expand Up @@ -219,7 +219,7 @@ class MSPBackyard(OmniBase):
colorlogic_light: list[MSPColorLogicLight] | None = Field(alias="ColorLogic-Light")


class MSPSchedule(OmniBase):
class MSPSchedule(OmniBase): # type: ignore[override]
omni_type: OmniType = OmniType.SCHEDULE
system_id: int = Field(alias="schedule-system-id")
bow_id: int = Field(alias="bow-system-id")
Expand Down
10 changes: 4 additions & 6 deletions pyomnilogic_local/models/telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from xmltodict import parse as xml_parse

from ..exceptions import OmniParsingException
from ..types import (
from ..omnitypes import (
BackyardState,
ChlorinatorOperatingMode,
ColorLogicBrightness,
Expand Down Expand Up @@ -71,7 +71,7 @@ class TelemetryChlorinator(BaseModel):
sc_mode: int = Field(alias="@scMode")
operating_state: int = Field(alias="@operatingState")
timed_percent: int | None = Field(alias="@Timed-Percent")
operating_mode: ChlorinatorOperatingMode = Field(alias="@operatingMode")
operating_mode: ChlorinatorOperatingMode | int = Field(alias="@operatingMode")
enable: bool = Field(alias="@enable")

# Still need to do a bit more work to determine if a chlorinator is actively chlorinating
Expand Down Expand Up @@ -200,12 +200,10 @@ def load_xml(xml: str) -> Telemetry:
TypeVar("VT", SupportsInt, Any)

@overload
def xml_postprocessor(path: Any, key: Any, value: SupportsInt) -> tuple[Any, SupportsInt]:
...
def xml_postprocessor(path: Any, key: Any, value: SupportsInt) -> tuple[Any, SupportsInt]: ...

@overload
def xml_postprocessor(path: Any, key: Any, value: Any) -> tuple[Any, Any]:
...
def xml_postprocessor(path: Any, key: Any, value: Any) -> tuple[Any, Any]: ...

def xml_postprocessor(path: Any, key: Any, value: SupportsInt | Any) -> tuple[Any, SupportsInt | Any]:
"""Post process XML to attempt to convert values to int.
Expand Down
Loading

0 comments on commit c3e39df

Please sign in to comment.