Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use slugified status and error codes for display code and error status #15

Merged
merged 9 commits into from
Jun 9, 2024
145 changes: 90 additions & 55 deletions incomfortclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from __future__ import annotations

import logging
from enum import IntEnum
from typing import Any

import aiohttp

Expand All @@ -29,45 +31,54 @@
BITMASK_PUMP = 0x02 # pump state: on / off
BITMASK_TAP = 0x04 # tap (DHW) state: function on / off

# key label: displ_code
DISPLAY_CODES: dict[int, str] = {
0: "opentherm",
15: "boiler ext.",
24: "frost",
37: "central heating rf",
51: "tapwater int.",
85: "sensortest",
102: "central heating",
126: "standby",
153: "postrun boiler",
170: "service",
204: "tapwater",
231: "postrun ch",
240: "boiler int.",
255: "buffer",
}
FAULT_CODES: dict[int, str] = {
0: "Sensor fault after self check",
1: "Temperature too high",
2: "S1 and S2 interchanged",
4: "No flame signal",
5: "Poor flame signal",
6: "Flame detection fault",
8: "Incorrect fan speed",
10: "Sensor fault S1",
11: "Sensor fault S1",
12: "Sensor fault S1",
13: "Sensor fault S1",
14: "Sensor fault S1",
20: "Sensor fault S2",
21: "Sensor fault S2",
22: "Sensor fault S2",
23: "Sensor fault S2",
24: "Sensor fault S2",
27: "Shortcut outside sensor temperature",
29: "Gas valve relay faulty",
30: "Gas valve relay faulty",
} # "0.0": "Low system pressure"
ISSUE_URL = "https://github.com/jbouwh/incomfort-client/issues"


class DiplayCode(IntEnum):
"""Label to display code."""

UNKNOWN = -1
OPENTHERM = 0
BOILET_EXT = 15
FROST = 24
CENNTRAL_HEATING_RF = 37
TAPWATER_INT = 51
SENSOR_TEST = 85
CENNTRAL_HEATING = 102
STANDBY = 126
POSTRUN_BOYLER = 153
SERVICE = 170
TAPWATER = 204
POSTRUN_CH = 231
BOILER_INT = 240
BUFFER = 255


class FaultCode(IntEnum):
"""Label to fault code."""

UNKNOWN = -1
SENSOR_FAULT_AFTER_SELF_CHECK_E0: 0
CV_TEMPERATURE_TOO_HIGH_E1: 1
S1_AND_S2_INTERCHANGED_E2: 2
NO_FLAME_SIGNAL_E4: 4
POOR_FLAME_SIGNAL_E5: 5
FLAME_DETECTION_FAULT_E6: 6
INCORRECT_FAN_SPEED_E8: 8
SENSOR_FAULT_S1_E10: 10
SENSOR_FAULT_S1_E11: 11
SENSOR_FAULT_S1_E12: 12
SENSOR_FAULT_S1_E13: 13
SENSOR_FAULT_S1_E14: 14
SENSOR_FAULT_S2_E20: 20
SENSOR_FAULT_S2_E21: 21
SENSOR_FAULT_S2_E22: 22
SENSOR_FAULT_S2_E23: 23
SENSOR_FAULT_S2_E24: 24
SHORTCUT_OUTSIDE_SENSOR_TEMPERATURE_E27: 27
GAS_VALVE_RELAY_FAULTY_E29: 29
GAS_VALVE_RELAY_FAULTY_E30: 30


HEATER_ATTRS: tuple[str, ...] = (
"display_code",
Expand Down Expand Up @@ -221,11 +232,45 @@ def __init__(self, serial_no: str, idx: int, gateway: Gateway) -> None:
self._data: dict = {}
self._status: dict = {}
self._rooms: list[Room] = None
self.display_code: DiplayCode | None = None
self.fault_code: FaultCode | None = None
self._last_display_code: int | None = None

async def update(self) -> None:
"""Retrieve the Heater's latest status from the Gateway."""
self._data = await self._get(f"data.json?heater={self._heater_idx}")

code: int = self._data["displ_code"]
if self.is_failed:
self.display_code = None
try:
self.fault_code = FaultCode(code)
except ValueError:
self.fault_code = FaultCode.UNKNOWN
if self._last_display_code != code:
_LOGGER.warning(
"Unknown fault code %s reported by heater %s. "
"Log an issue at %s to report the unknown fault code",
code,
self._serial_no,
ISSUE_URL,
)
else:
self.fault_code = None
try:
self.display_code = DiplayCode(code)
except ValueError:
self.display_code = DiplayCode.UNKNOWN
if self._last_display_code != code:
_LOGGER.warning(
"Unknown operation code %s reported by heater %s"
"Log an issue at %s to report the unknown display code",
code,
self._serial_no,
ISSUE_URL,
)
self._last_display_code = code

self._status = {}

for attr in HEATER_ATTRS:
Expand All @@ -237,26 +282,16 @@ async def update(self) -> None:
_LOGGER.debug("Heater(%s).status() = %s", self._serial_no, self._status)

@property
def status(self) -> dict:
def status(self) -> dict[str, Any]:
"""Return the current state of the heater."""
return self._status

@property
def display_code(self) -> int:
"""Return the display code, 'displ_code'."""
return self._data["displ_code"]

@property
def display_text(self) -> None | str:
"""Return the display code as text rather than a code."""
code = self.display_code
code_map = FAULT_CODES if self.is_failed else DISPLAY_CODES
return code_map.get(code, f"unknown/other, code = '{code}'")

@property
def fault_code(self) -> None | int:
"""Return the fault code when the heater is in a failed state."""
return self._data["displ_code"] if self.is_failed else None
def display_text(self) -> str | None:
"""Return the display or fault code as text label rather than a code."""
if self.is_failed:
return self.fault_code.name.lower() if self.fault_code else None
return self.display_code.name.lower() if self.display_code else None

@property
def is_burning(self) -> bool:
Expand Down
Loading