PyPlumIO 0.6.0__py3-none-any.whl → 0.6.2__py3-none-any.whl

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.
Files changed (49) hide show
  1. pyplumio/__init__.py +3 -1
  2. pyplumio/_version.py +2 -2
  3. pyplumio/connection.py +0 -36
  4. pyplumio/const.py +0 -5
  5. pyplumio/data_types.py +2 -2
  6. pyplumio/devices/__init__.py +23 -5
  7. pyplumio/devices/ecomax.py +30 -53
  8. pyplumio/devices/ecoster.py +2 -3
  9. pyplumio/filters.py +199 -136
  10. pyplumio/frames/__init__.py +101 -15
  11. pyplumio/frames/messages.py +8 -65
  12. pyplumio/frames/requests.py +38 -38
  13. pyplumio/frames/responses.py +30 -86
  14. pyplumio/helpers/async_cache.py +13 -8
  15. pyplumio/helpers/event_manager.py +24 -18
  16. pyplumio/helpers/factory.py +0 -3
  17. pyplumio/parameters/__init__.py +38 -35
  18. pyplumio/protocol.py +63 -47
  19. pyplumio/structures/alerts.py +2 -2
  20. pyplumio/structures/ecomax_parameters.py +1 -1
  21. pyplumio/structures/frame_versions.py +3 -2
  22. pyplumio/structures/mixer_parameters.py +5 -3
  23. pyplumio/structures/network_info.py +1 -0
  24. pyplumio/structures/product_info.py +1 -1
  25. pyplumio/structures/program_version.py +2 -2
  26. pyplumio/structures/schedules.py +8 -40
  27. pyplumio/structures/sensor_data.py +498 -0
  28. pyplumio/structures/thermostat_parameters.py +7 -4
  29. pyplumio/utils.py +41 -4
  30. {pyplumio-0.6.0.dist-info → pyplumio-0.6.2.dist-info}/METADATA +7 -8
  31. pyplumio-0.6.2.dist-info/RECORD +50 -0
  32. pyplumio/structures/boiler_load.py +0 -32
  33. pyplumio/structures/boiler_power.py +0 -33
  34. pyplumio/structures/fan_power.py +0 -33
  35. pyplumio/structures/fuel_consumption.py +0 -36
  36. pyplumio/structures/fuel_level.py +0 -39
  37. pyplumio/structures/lambda_sensor.py +0 -57
  38. pyplumio/structures/mixer_sensors.py +0 -80
  39. pyplumio/structures/modules.py +0 -102
  40. pyplumio/structures/output_flags.py +0 -47
  41. pyplumio/structures/outputs.py +0 -88
  42. pyplumio/structures/pending_alerts.py +0 -28
  43. pyplumio/structures/statuses.py +0 -52
  44. pyplumio/structures/temperatures.py +0 -94
  45. pyplumio/structures/thermostat_sensors.py +0 -106
  46. pyplumio-0.6.0.dist-info/RECORD +0 -63
  47. {pyplumio-0.6.0.dist-info → pyplumio-0.6.2.dist-info}/WHEEL +0 -0
  48. {pyplumio-0.6.0.dist-info → pyplumio-0.6.2.dist-info}/licenses/LICENSE +0 -0
  49. {pyplumio-0.6.0.dist-info → pyplumio-0.6.2.dist-info}/top_level.txt +0 -0
@@ -1,32 +0,0 @@
1
- """Contains a boiler load structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Final
6
-
7
- from pyplumio.const import BYTE_UNDEFINED
8
- from pyplumio.structures import StructureDecoder
9
- from pyplumio.utils import ensure_dict
10
-
11
- ATTR_BOILER_LOAD: Final = "boiler_load"
12
-
13
-
14
- class BoilerLoadStructure(StructureDecoder):
15
- """Represents a boiler load sensor data structure."""
16
-
17
- __slots__ = ()
18
-
19
- def decode(
20
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
21
- ) -> tuple[dict[str, Any], int]:
22
- """Decode bytes and return message data and offset."""
23
- boiler_load = message[offset]
24
- offset += 1
25
-
26
- if boiler_load == BYTE_UNDEFINED:
27
- return ensure_dict(data), offset
28
-
29
- return (ensure_dict(data, {ATTR_BOILER_LOAD: boiler_load}), offset)
30
-
31
-
32
- __all__ = ["ATTR_BOILER_LOAD", "BoilerLoadStructure"]
@@ -1,33 +0,0 @@
1
- """Contains a boiler power structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- import math
6
- from typing import Any, Final
7
-
8
- from pyplumio.data_types import Float
9
- from pyplumio.structures import StructureDecoder
10
- from pyplumio.utils import ensure_dict
11
-
12
- ATTR_BOILER_POWER: Final = "boiler_power"
13
-
14
-
15
- class BoilerPowerStructure(StructureDecoder):
16
- """Represents a boiler power sensor data structure."""
17
-
18
- __slots__ = ()
19
-
20
- def decode(
21
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
22
- ) -> tuple[dict[str, Any], int]:
23
- """Decode bytes and return message data and offset."""
24
- boiler_power = Float.from_bytes(message, offset)
25
- offset += boiler_power.size
26
-
27
- if math.isnan(boiler_power.value):
28
- return ensure_dict(data), offset
29
-
30
- return ensure_dict(data, {ATTR_BOILER_POWER: boiler_power.value}), offset
31
-
32
-
33
- __all__ = ["ATTR_BOILER_POWER", "BoilerPowerStructure"]
@@ -1,33 +0,0 @@
1
- """Contains a fan power structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- import math
6
- from typing import Any, Final
7
-
8
- from pyplumio.data_types import Float
9
- from pyplumio.structures import StructureDecoder
10
- from pyplumio.utils import ensure_dict
11
-
12
- ATTR_FAN_POWER: Final = "fan_power"
13
-
14
-
15
- class FanPowerStructure(StructureDecoder):
16
- """Represents a fan power sensor data structure."""
17
-
18
- __slots__ = ()
19
-
20
- def decode(
21
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
22
- ) -> tuple[dict[str, Any], int]:
23
- """Decode bytes and return message data and offset."""
24
- fan_power = Float.from_bytes(message, offset)
25
- offset += fan_power.size
26
-
27
- if math.isnan(fan_power.value):
28
- return ensure_dict(data), offset
29
-
30
- return ensure_dict(data, {ATTR_FAN_POWER: fan_power.value}), offset
31
-
32
-
33
- __all__ = ["ATTR_FAN_POWER", "FanPowerStructure"]
@@ -1,36 +0,0 @@
1
- """Contains fuel consumption structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- import math
6
- from typing import Any, Final
7
-
8
- from pyplumio.data_types import Float
9
- from pyplumio.structures import StructureDecoder
10
- from pyplumio.utils import ensure_dict
11
-
12
- ATTR_FUEL_CONSUMPTION: Final = "fuel_consumption"
13
-
14
-
15
- class FuelConsumptionStructure(StructureDecoder):
16
- """Represents a fuel consumption sensor data structure."""
17
-
18
- __slots__ = ()
19
-
20
- def decode(
21
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
22
- ) -> tuple[dict[str, Any], int]:
23
- """Decode bytes and return message data and offset."""
24
- fuel_consumption = Float.from_bytes(message, offset)
25
- offset += fuel_consumption.size
26
-
27
- if math.isnan(fuel_consumption.value):
28
- return ensure_dict(data), offset
29
-
30
- return (
31
- ensure_dict(data, {ATTR_FUEL_CONSUMPTION: fuel_consumption.value}),
32
- offset,
33
- )
34
-
35
-
36
- __all__ = ["ATTR_FUEL_CONSUMPTION", "FuelConsumptionStructure"]
@@ -1,39 +0,0 @@
1
- """Contains a fuel level structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Final
6
-
7
- from pyplumio.const import BYTE_UNDEFINED
8
- from pyplumio.structures import StructureDecoder
9
- from pyplumio.utils import ensure_dict
10
-
11
- ATTR_FUEL_LEVEL: Final = "fuel_level"
12
-
13
- FUEL_LEVEL_OFFSET: Final = 101
14
-
15
-
16
- class FuelLevelStructure(StructureDecoder):
17
- """Represents a fuel level sensor data structure."""
18
-
19
- __slots__ = ()
20
-
21
- def decode(
22
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
23
- ) -> tuple[dict[str, Any], int]:
24
- """Decode bytes and return message data and offset."""
25
- fuel_level = message[offset]
26
- offset += 1
27
-
28
- if fuel_level == BYTE_UNDEFINED:
29
- return ensure_dict(data), offset
30
-
31
- if fuel_level >= FUEL_LEVEL_OFFSET:
32
- # Observed on at least ecoMAX 860P6-O.
33
- # See: https://github.com/denpamusic/PyPlumIO/issues/19
34
- fuel_level -= FUEL_LEVEL_OFFSET
35
-
36
- return (ensure_dict(data, {ATTR_FUEL_LEVEL: fuel_level}), offset)
37
-
38
-
39
- __all__ = ["ATTR_FUEL_LEVEL", "FuelLevelStructure"]
@@ -1,57 +0,0 @@
1
- """Contains a lambda sensor structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from contextlib import suppress
6
- from typing import Any, Final
7
-
8
- from pyplumio.const import BYTE_UNDEFINED, LambdaState
9
- from pyplumio.data_types import UnsignedShort
10
- from pyplumio.structures import StructureDecoder
11
- from pyplumio.utils import ensure_dict
12
-
13
- ATTR_LAMBDA_STATE: Final = "lambda_state"
14
- ATTR_LAMBDA_TARGET: Final = "lambda_target"
15
- ATTR_LAMBDA_LEVEL: Final = "lambda_level"
16
-
17
-
18
- class LambdaSensorStructure(StructureDecoder):
19
- """Represents a lambda sensor data structure."""
20
-
21
- __slots__ = ()
22
-
23
- def decode(
24
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
25
- ) -> tuple[dict[str, Any], int]:
26
- """Decode bytes and return message data and offset."""
27
- lambda_state = message[offset]
28
- offset += 1
29
- if lambda_state == BYTE_UNDEFINED:
30
- return ensure_dict(data), offset
31
-
32
- lambda_target = message[offset]
33
- offset += 1
34
- level = UnsignedShort.from_bytes(message, offset)
35
- offset += level.size
36
- with suppress(ValueError):
37
- lambda_state = LambdaState(lambda_state)
38
-
39
- return (
40
- ensure_dict(
41
- data,
42
- {
43
- ATTR_LAMBDA_STATE: lambda_state,
44
- ATTR_LAMBDA_TARGET: lambda_target,
45
- ATTR_LAMBDA_LEVEL: level.value / 10,
46
- },
47
- ),
48
- offset,
49
- )
50
-
51
-
52
- __all__ = [
53
- "ATTR_LAMBDA_STATE",
54
- "ATTR_LAMBDA_TARGET",
55
- "ATTR_LAMBDA_LEVEL",
56
- "LambdaSensorStructure",
57
- ]
@@ -1,80 +0,0 @@
1
- """Contains a mixer sensors structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from collections.abc import Generator
6
- import math
7
- from typing import Any, Final
8
-
9
- from pyplumio.const import ATTR_CURRENT_TEMP, ATTR_TARGET_TEMP
10
- from pyplumio.data_types import Float
11
- from pyplumio.structures import StructureDecoder
12
- from pyplumio.utils import ensure_dict
13
-
14
- ATTR_PUMP: Final = "pump"
15
- ATTR_MIXERS_AVAILABLE: Final = "mixers_available"
16
- ATTR_MIXERS_CONNECTED: Final = "mixers_connected"
17
- ATTR_MIXER_SENSORS: Final = "mixer_sensors"
18
-
19
- MIXER_SENSOR_SIZE: Final = 8
20
-
21
-
22
- class MixerSensorsStructure(StructureDecoder):
23
- """Represents a mixer sensors data structure."""
24
-
25
- __slots__ = ("_offset",)
26
-
27
- _offset: int
28
-
29
- def _unpack_mixer_sensors(self, message: bytearray) -> dict[str, Any] | None:
30
- """Unpack sensors for a mixer."""
31
- offset = self._offset
32
- current_temp = Float.from_bytes(message, offset)
33
- try:
34
- return (
35
- {
36
- ATTR_CURRENT_TEMP: current_temp.value,
37
- ATTR_TARGET_TEMP: message[offset + 4],
38
- ATTR_PUMP: bool(message[offset + 6] & 0x01),
39
- }
40
- if not math.isnan(current_temp.value)
41
- else None
42
- )
43
- finally:
44
- self._offset = offset + MIXER_SENSOR_SIZE
45
-
46
- def _mixer_sensors(
47
- self, message: bytearray, mixers: int
48
- ) -> Generator[tuple[int, dict[str, Any]], None, None]:
49
- """Get sensors for a mixer."""
50
- for index in range(mixers):
51
- if sensors := self._unpack_mixer_sensors(message):
52
- yield (index, sensors)
53
-
54
- def decode(
55
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
56
- ) -> tuple[dict[str, Any], int]:
57
- """Decode bytes and return message data and offset."""
58
- mixers = message[offset]
59
- self._offset = offset + 1
60
- mixer_sensors = dict(self._mixer_sensors(message, mixers))
61
- return (
62
- ensure_dict(
63
- data,
64
- {
65
- ATTR_MIXER_SENSORS: mixer_sensors,
66
- ATTR_MIXERS_AVAILABLE: mixers,
67
- ATTR_MIXERS_CONNECTED: len(mixer_sensors),
68
- },
69
- ),
70
- self._offset,
71
- )
72
-
73
-
74
- __all__ = [
75
- "ATTR_PUMP",
76
- "ATTR_MIXERS_AVAILABLE",
77
- "ATTR_MIXERS_CONNECTED",
78
- "ATTR_MIXER_SENSORS",
79
- "MixerSensorsStructure",
80
- ]
@@ -1,102 +0,0 @@
1
- """Contains a modules structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from dataclasses import dataclass
6
- import struct
7
- from typing import Any, Final
8
-
9
- from pyplumio.const import BYTE_UNDEFINED
10
- from pyplumio.structures import StructureDecoder
11
- from pyplumio.utils import ensure_dict
12
-
13
- ATTR_MODULES: Final = "modules"
14
- ATTR_MODULE_A: Final = "module_a"
15
- ATTR_MODULE_B: Final = "module_b"
16
- ATTR_MODULE_C: Final = "module_c"
17
- ATTR_ECOLAMBDA: Final = "ecolambda"
18
- ATTR_ECOSTER: Final = "ecoster"
19
- ATTR_PANEL: Final = "panel"
20
- MODULES: tuple[str, ...] = (
21
- ATTR_MODULE_A,
22
- ATTR_MODULE_B,
23
- ATTR_MODULE_C,
24
- ATTR_ECOLAMBDA,
25
- ATTR_ECOSTER,
26
- ATTR_PANEL,
27
- )
28
-
29
- struct_version = struct.Struct("<BBB")
30
- struct_vendor = struct.Struct("<BB")
31
-
32
-
33
- @dataclass(slots=True)
34
- class ConnectedModules:
35
- """Represents a firmware version info for connected module."""
36
-
37
- module_a: str | None = None
38
- module_b: str | None = None
39
- module_c: str | None = None
40
- ecolambda: str | None = None
41
- ecoster: str | None = None
42
- panel: str | None = None
43
-
44
-
45
- class ModulesStructure(StructureDecoder):
46
- """Represents a modules data structure."""
47
-
48
- __slots__ = ("_offset",)
49
-
50
- _offset: int
51
-
52
- def _unpack_module_version(self, module: str, message: bytearray) -> str | None:
53
- """Unpack a module version."""
54
- if message[self._offset] == BYTE_UNDEFINED:
55
- self._offset += 1
56
- return None
57
-
58
- offset = self._offset
59
- version_data = struct_version.unpack_from(message, offset)
60
- version = ".".join(str(i) for i in version_data)
61
- offset += struct_version.size
62
- if module == ATTR_MODULE_A:
63
- vendor_code, vendor_version = struct_vendor.unpack_from(message, offset)
64
- version += f".{chr(vendor_code) + str(vendor_version)}"
65
- offset += struct_vendor.size
66
-
67
- self._offset = offset
68
- return version
69
-
70
- def decode(
71
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
72
- ) -> tuple[dict[str, Any], int]:
73
- """Decode bytes and return message data and offset."""
74
- self._offset = offset
75
- return (
76
- ensure_dict(
77
- data,
78
- {
79
- ATTR_MODULES: ConnectedModules(
80
- **{
81
- module: self._unpack_module_version(module, message)
82
- for module in MODULES
83
- }
84
- )
85
- },
86
- ),
87
- self._offset,
88
- )
89
-
90
-
91
- __all__ = [
92
- "ATTR_MODULES",
93
- "ATTR_MODULE_A",
94
- "ATTR_MODULE_B",
95
- "ATTR_MODULE_C",
96
- "ATTR_ECOLAMBDA",
97
- "ATTR_ECOSTER",
98
- "ATTR_PANEL",
99
- "MODULES",
100
- "ConnectedModules",
101
- "ModulesStructure",
102
- ]
@@ -1,47 +0,0 @@
1
- """Contains an output flags structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Final
6
-
7
- from pyplumio.data_types import UnsignedInt
8
- from pyplumio.structures import StructureDecoder
9
- from pyplumio.utils import ensure_dict
10
-
11
- ATTR_HEATING_PUMP_FLAG: Final = "heating_pump_flag"
12
- ATTR_WATER_HEATER_PUMP_FLAG: Final = "water_heater_pump_flag"
13
- ATTR_CIRCULATION_PUMP_FLAG: Final = "circulation_pump_flag"
14
- ATTR_SOLAR_PUMP_FLAG: Final = "solar_pump_flag"
15
-
16
-
17
- class OutputFlagsStructure(StructureDecoder):
18
- """Represents an output flags structure."""
19
-
20
- __slots__ = ()
21
-
22
- def decode(
23
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
24
- ) -> tuple[dict[str, Any], int]:
25
- """Decode bytes and return message data and offset."""
26
- output_flags = UnsignedInt.from_bytes(message, offset)
27
- return (
28
- ensure_dict(
29
- data,
30
- {
31
- ATTR_HEATING_PUMP_FLAG: bool(output_flags.value & 0x04),
32
- ATTR_WATER_HEATER_PUMP_FLAG: bool(output_flags.value & 0x08),
33
- ATTR_CIRCULATION_PUMP_FLAG: bool(output_flags.value & 0x10),
34
- ATTR_SOLAR_PUMP_FLAG: bool(output_flags.value & 0x800),
35
- },
36
- ),
37
- offset + output_flags.size,
38
- )
39
-
40
-
41
- __all__ = [
42
- "ATTR_HEATING_PUMP_FLAG",
43
- "ATTR_WATER_HEATER_PUMP_FLAG",
44
- "ATTR_CIRCULATION_PUMP_FLAG",
45
- "ATTR_SOLAR_PUMP_FLAG",
46
- "OutputFlagsStructure",
47
- ]
@@ -1,88 +0,0 @@
1
- """Contains an outputs structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Final
6
-
7
- from pyplumio.data_types import UnsignedInt
8
- from pyplumio.structures import StructureDecoder
9
- from pyplumio.utils import ensure_dict
10
-
11
- ATTR_FAN: Final = "fan"
12
- ATTR_FEEDER: Final = "feeder"
13
- ATTR_HEATING_PUMP: Final = "heating_pump"
14
- ATTR_WATER_HEATER_PUMP: Final = "water_heater_pump"
15
- ATTR_CIRCULATION_PUMP: Final = "circulation_pump"
16
- ATTR_LIGHTER: Final = "lighter"
17
- ATTR_ALARM: Final = "alarm"
18
- ATTR_OUTER_BOILER: Final = "outer_boiler"
19
- ATTR_FAN2_EXHAUST: Final = "fan2_exhaust"
20
- ATTR_FEEDER2: Final = "feeder2"
21
- ATTR_OUTER_FEEDER: Final = "outer_feeder"
22
- ATTR_SOLAR_PUMP: Final = "solar_pump"
23
- ATTR_FIREPLACE_PUMP: Final = "fireplace_pump"
24
- ATTR_GCZ_CONTACT: Final = "gcz_contact"
25
- ATTR_BLOW_FAN1: Final = "blow_fan1"
26
- ATTR_BLOW_FAN2: Final = "blow_fan2"
27
-
28
- OUTPUTS: tuple[str, ...] = (
29
- ATTR_FAN,
30
- ATTR_FEEDER,
31
- ATTR_HEATING_PUMP,
32
- ATTR_WATER_HEATER_PUMP,
33
- ATTR_CIRCULATION_PUMP,
34
- ATTR_LIGHTER,
35
- ATTR_ALARM,
36
- ATTR_OUTER_BOILER,
37
- ATTR_FAN2_EXHAUST,
38
- ATTR_FEEDER2,
39
- ATTR_OUTER_FEEDER,
40
- ATTR_SOLAR_PUMP,
41
- ATTR_FIREPLACE_PUMP,
42
- ATTR_GCZ_CONTACT,
43
- ATTR_BLOW_FAN1,
44
- ATTR_BLOW_FAN2,
45
- )
46
-
47
-
48
- class OutputsStructure(StructureDecoder):
49
- """Represents an outputs data structure."""
50
-
51
- __slots__ = ()
52
-
53
- def decode(
54
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
55
- ) -> tuple[dict[str, Any], int]:
56
- """Decode bytes and return message data and offset."""
57
- outputs = UnsignedInt.from_bytes(message, offset)
58
- return (
59
- ensure_dict(
60
- data,
61
- {
62
- output: bool(outputs.value & 2**index)
63
- for index, output in enumerate(OUTPUTS)
64
- },
65
- ),
66
- offset + outputs.size,
67
- )
68
-
69
-
70
- __all__ = [
71
- "ATTR_FAN",
72
- "ATTR_FEEDER",
73
- "ATTR_HEATING_PUMP",
74
- "ATTR_WATER_HEATER_PUMP",
75
- "ATTR_CIRCULATION_PUMP",
76
- "ATTR_LIGHTER",
77
- "ATTR_ALARM",
78
- "ATTR_OUTER_BOILER",
79
- "ATTR_FAN2_EXHAUST",
80
- "ATTR_FEEDER2",
81
- "ATTR_OUTER_FEEDER",
82
- "ATTR_SOLAR_PUMP",
83
- "ATTR_FIREPLACE_PUMP",
84
- "ATTR_GCZ_CONTACT",
85
- "ATTR_BLOW_FAN1",
86
- "ATTR_BLOW_FAN2",
87
- "OutputsStructure",
88
- ]
@@ -1,28 +0,0 @@
1
- """Contains a pending alerts structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Final
6
-
7
- from pyplumio.structures import StructureDecoder
8
- from pyplumio.utils import ensure_dict
9
-
10
- ATTR_PENDING_ALERTS: Final = "pending_alerts"
11
-
12
-
13
- class PendingAlertsStructure(StructureDecoder):
14
- """Represents a pending alerts structure."""
15
-
16
- __slots__ = ()
17
-
18
- def decode(
19
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
20
- ) -> tuple[dict[str, Any], int]:
21
- """Decode bytes and return message data and offset."""
22
- alerts_number = message[offset]
23
- return ensure_dict(data, {ATTR_PENDING_ALERTS: alerts_number}), (
24
- offset + alerts_number + 1
25
- )
26
-
27
-
28
- __all__ = ["ATTR_PENDING_ALERTS", "PendingAlertsStructure"]
@@ -1,52 +0,0 @@
1
- """Contains a statuses structure decoder."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Final
6
-
7
- from pyplumio.structures import StructureDecoder
8
- from pyplumio.utils import ensure_dict
9
-
10
- ATTR_HEATING_TARGET: Final = "heating_target"
11
- ATTR_HEATING_STATUS: Final = "heating_status"
12
- ATTR_WATER_HEATER_TARGET: Final = "water_heater_target"
13
- ATTR_WATER_HEATER_STATUS: Final = "water_heater_status"
14
-
15
- STATUSES: tuple[str, ...] = (
16
- ATTR_HEATING_TARGET,
17
- ATTR_HEATING_STATUS,
18
- ATTR_WATER_HEATER_TARGET,
19
- ATTR_WATER_HEATER_STATUS,
20
- )
21
-
22
- STATUSES_SIZE: Final = 4
23
-
24
-
25
- class StatusesStructure(StructureDecoder):
26
- """Represents a statuses data structure."""
27
-
28
- __slots__ = ()
29
-
30
- def decode(
31
- self, message: bytearray, offset: int = 0, data: dict[str, Any] | None = None
32
- ) -> tuple[dict[str, Any], int]:
33
- """Decode bytes and return message data and offset."""
34
- return (
35
- ensure_dict(
36
- data,
37
- {
38
- status: message[offset + index]
39
- for index, status in enumerate(STATUSES)
40
- },
41
- ),
42
- offset + STATUSES_SIZE,
43
- )
44
-
45
-
46
- __all__ = [
47
- "ATTR_HEATING_TARGET",
48
- "ATTR_HEATING_STATUS",
49
- "ATTR_WATER_HEATER_TARGET",
50
- "ATTR_WATER_HEATER_STATUS",
51
- "StatusesStructure",
52
- ]