compit-inext-api-beta 0.4.0b13__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.
@@ -0,0 +1,44 @@
1
+ from importlib import resources
2
+ import json
3
+ import logging
4
+ import aiofiles
5
+
6
+ from .types.DeviceDefinitions import DeviceDefinitions, Device
7
+
8
+ _LOGGER: logging.Logger = logging.getLogger(__package__)
9
+
10
+ class DeviceDefinitionsLoader:
11
+ """Class to load the device definitions from file."""
12
+
13
+ cache: dict[str, DeviceDefinitions] = {}
14
+
15
+ @staticmethod
16
+ async def get_device_definitions(lang: str) -> DeviceDefinitions:
17
+ """Get the device definitions from file."""
18
+ file_name = f"devices_{lang}.json"
19
+
20
+ if lang in DeviceDefinitionsLoader.cache:
21
+ return DeviceDefinitionsLoader.cache[lang]
22
+
23
+ config_path = resources.files('compit_inext_api.definitions').joinpath(file_name)
24
+ try:
25
+ async with aiofiles.open(config_path, encoding="utf-8", mode='r') as file:
26
+ content = await file.read()
27
+ definitions = DeviceDefinitions.from_json(json.loads(content))
28
+ DeviceDefinitionsLoader.cache[lang] = definitions
29
+ return definitions
30
+ except FileNotFoundError:
31
+ _LOGGER.warning("File %s not found", file_name)
32
+ if lang != "en":
33
+ _LOGGER.debug("Trying to load English definitions")
34
+ return await DeviceDefinitionsLoader.get_device_definitions("en")
35
+ raise ValueError("No definitions found") from None
36
+
37
+ @staticmethod
38
+ async def get_device_definition(code: int, lang: str = "en") -> Device:
39
+ """Get the device definition for a specific device type."""
40
+ definitions = await DeviceDefinitionsLoader.get_device_definitions(lang)
41
+ for device in definitions.devices:
42
+ if device.code == code:
43
+ return device
44
+ raise ValueError(f"No definition found for device with code {code}")
@@ -0,0 +1,369 @@
1
+ from .consts import CompitParameter
2
+
3
+ PARAMS = {
4
+ CompitParameter.AEROKONFBYPASS: {
5
+ "off": 0,
6
+ "auto": 1,
7
+ "on": 2,
8
+ },
9
+ CompitParameter.ADDITIONAL_VENTILATION_ZONE: {
10
+ "gear_0": 0,
11
+ "gear_1": 1,
12
+ "gear_2": 2,
13
+ "gear_3": 3,
14
+ "gear_4": 4,
15
+ },
16
+ CompitParameter.LANGUAGE: {
17
+ "polish": 0,
18
+ "english": 1,
19
+ },
20
+ CompitParameter.NANO_MODE: {
21
+ "manual_3": 0,
22
+ "manual_2": 1,
23
+ "manual_1": 2,
24
+ "manual_0": 3,
25
+ "schedule": 4,
26
+ "christmas": 5,
27
+ "out_of_home": 6,
28
+ },
29
+ CompitParameter.VENTILATION_COMFORT_ZONE: {
30
+ "gear_0": 0,
31
+ "gear_1": 1,
32
+ "gear_2": 2,
33
+ "gear_3": 3,
34
+ },
35
+ CompitParameter.VENTILATION_ECO_ZONE: {
36
+ "gear_0": 0,
37
+ "gear_1": 1,
38
+ "gear_2": 2,
39
+ "gear_3": 3,
40
+ },
41
+ CompitParameter.VENTILATION_HOLIDAY_MODE: {
42
+ "gear_0": 0,
43
+ "gear_1": 1,
44
+ "gear_2": 2,
45
+ "gear_3": 3,
46
+ },
47
+ CompitParameter.AIRING_PROGRAM_ZONE_3: {
48
+ "no_exclusions": 0,
49
+ "30m_work30m_stop": 1,
50
+ "20m_work40m_stop": 2,
51
+ "20m_work100m_stop": 3,
52
+ },
53
+ CompitParameter.PRE_HEATER_ZONE_3: {
54
+ "disabled": 0,
55
+ "onoff": 1,
56
+ "pwm": 2,
57
+ },
58
+ CompitParameter.SECONDARY_HEATER_ZONE_3: {
59
+ "disabled": 0,
60
+ "onoff_room_temp": 1,
61
+ "onoff_outside_temp": 2,
62
+ "onoff": 3,
63
+ "pwm_room_temp": 4,
64
+ "pwm_outside_temp": 5,
65
+ },
66
+ CompitParameter.AIRING_PROGRAM_ZONE_4: {
67
+ "no_exclusions": 0,
68
+ "30m_work30m_stop": 1,
69
+ "20m_work40m_stop": 2,
70
+ "20m_work100m_stop": 3,
71
+ },
72
+ CompitParameter.AIRING_PROGRAM_ZONE_5: {
73
+ "no_exclusions": 0,
74
+ "30m_work30m_stop": 1,
75
+ "20m_work40m_stop": 2,
76
+ "20m_work100m_stop": 3,
77
+ },
78
+ CompitParameter.PRE_HEATER_ZONE_5: {
79
+ "disabled": 0,
80
+ "onoff": 1,
81
+ "pwm": 2,
82
+ },
83
+ CompitParameter.SECONDARY_HEATER_ZONE_5: {
84
+ "disabled": 0,
85
+ "pwm": 1,
86
+ },
87
+ CompitParameter.CIRCUIT_MODE_HEATING_ZONE_1: {
88
+ "pump": 0,
89
+ "mixer": 1,
90
+ },
91
+ CompitParameter.CIRCUIT_MODE_HEATING_ZONE_2: {
92
+ "pump": 0,
93
+ "mixer": 1,
94
+ },
95
+ CompitParameter.CIRCUIT_MODE_HEATING_ZONE_3: {
96
+ "pump": 0,
97
+ "mixer": 1,
98
+ },
99
+ CompitParameter.CIRCUIT_MODE_HEATING_ZONE_4: {
100
+ "pump": 0,
101
+ "mixer": 1,
102
+ },
103
+ CompitParameter.DHWC_CIRCULATION: {
104
+ "disabled": 0,
105
+ "schedule": 1,
106
+ "constant": 2,
107
+ },
108
+ CompitParameter.OPERATING_MODE: {
109
+ "disabled": 0,
110
+ "eco": 1,
111
+ "hybrid": 2,
112
+ },
113
+ CompitParameter.HEATING_MODE_ZONE_1: {
114
+ "disabled": 0,
115
+ "schedule": 1,
116
+ "manual": 2,
117
+ },
118
+ CompitParameter.HEATING_MODE_ZONE_2: {
119
+ "disabled": 0,
120
+ "schedule": 1,
121
+ "manual": 2,
122
+ },
123
+ CompitParameter.HEATING_MODE_ZONE_3: {
124
+ "disabled": 0,
125
+ "schedule": 1,
126
+ "manual": 2,
127
+ },
128
+ CompitParameter.HEATING_MODE_ZONE_4: {
129
+ "disabled": 0,
130
+ "schedule": 1,
131
+ "manual": 2,
132
+ },
133
+ CompitParameter.MIXER_MODE: {
134
+ "disabled": 0,
135
+ "no_corrections": 1,
136
+ "with_a_schedule": 2,
137
+ "with_thermostat": 3,
138
+ "nano_nr_1": 4,
139
+ "nano_nr_2": 5,
140
+ "nano_nr_3": 6,
141
+ "nano_nr_4": 7,
142
+ "nano_nr_5": 8,
143
+ },
144
+ CompitParameter.SOLAR_COMP_OPERATING_MODE: {
145
+ "auto": 1,
146
+ "de_icing": 2,
147
+ "holiday": 3,
148
+ "disabled": 4,
149
+ },
150
+ CompitParameter.HEATING_SOURCE_OF_CORRECTION_ZONE_1: {
151
+ "no_corrections": 0,
152
+ "schedule": 1,
153
+ "thermostat": 2,
154
+ "nano_nr_1": 3,
155
+ "nano_nr_2": 4,
156
+ "nano_nr_3": 5,
157
+ "nano_nr_4": 6,
158
+ "nano_nr_5": 7,
159
+ },
160
+ CompitParameter.HEATING_SOURCE_OF_CORRECTION_ZONE_2: {
161
+ "no_corrections": 0,
162
+ "schedule": 1,
163
+ "thermostat": 2,
164
+ "nano_nr_1": 3,
165
+ "nano_nr_2": 4,
166
+ "nano_nr_3": 5,
167
+ "nano_nr_4": 6,
168
+ "nano_nr_5": 7,
169
+ },
170
+ CompitParameter.HEATING_SOURCE_OF_CORRECTION_ZONE_3: {
171
+ "no_corrections": 0,
172
+ "schedule": 1,
173
+ "thermostat": 2,
174
+ "nano_nr_1": 3,
175
+ "nano_nr_2": 4,
176
+ "nano_nr_3": 5,
177
+ "nano_nr_4": 6,
178
+ "nano_nr_5": 7,
179
+ },
180
+ CompitParameter.HEATING_SOURCE_OF_CORRECTION_ZONE_4: {
181
+ "no_corrections": 0,
182
+ "schedule": 1,
183
+ "thermostat": 2,
184
+ "nano_nr_1": 3,
185
+ "nano_nr_2": 4,
186
+ "nano_nr_3": 5,
187
+ "nano_nr_4": 6,
188
+ "nano_nr_5": 7,
189
+ },
190
+ CompitParameter.R490_OPERATING_MODE: {
191
+ "disabled": 0,
192
+ "eco": 1,
193
+ "hybrid": 2,
194
+ },
195
+ CompitParameter.DHW_OPERATING_MODE: {
196
+ "schedule": 1,
197
+ "manual": 2,
198
+ },
199
+ CompitParameter.HEATING_OPERATING_MODE_ZONE_1: {
200
+ "disabled": 0,
201
+ "schedule": 1,
202
+ "manual": 2,
203
+ },
204
+ CompitParameter.HEATING_OPERATING_MODE_ZONE_2: {
205
+ "disabled": 0,
206
+ "schedule": 1,
207
+ "manual": 2,
208
+ },
209
+ CompitParameter.HEATING_OPERATING_MODE_ZONE_3: {
210
+ "disabled": 0,
211
+ "schedule": 1,
212
+ "manual": 2,
213
+ },
214
+ CompitParameter.HEATING_OPERATING_MODE_ZONE_4: {
215
+ "disabled": 0,
216
+ "schedule": 1,
217
+ "manual": 2,
218
+ },
219
+ CompitParameter.BUFFER_MODE: {
220
+ "disabled": 0,
221
+ "schedule": 1,
222
+ "manual": 2,
223
+ },
224
+ CompitParameter.R470_OPERATING_MODE: {
225
+ "disabled": 1,
226
+ "auto": 2,
227
+ "eco": 3,
228
+ },
229
+ CompitParameter.HEATING_SOURCE_OF_CORRECTION: {
230
+ "no_corrections": 1,
231
+ "schedule": 2,
232
+ "thermostat": 3,
233
+ "nano_nr_1": 4,
234
+ "nano_nr_2": 5,
235
+ "nano_nr_3": 6,
236
+ "nano_nr_4": 7,
237
+ "nano_nr_5": 8,
238
+ },
239
+ CompitParameter.MIXERMODE_ZONE_1: {
240
+ "no_corrections": 1,
241
+ "clock": 2,
242
+ "thermostat": 3,
243
+ "nano_nr_1": 4,
244
+ "nano_nr_2": 5,
245
+ "nano_nr_3": 6,
246
+ "nano_nr_4": 7,
247
+ "nano_nr_5": 8,
248
+ },
249
+ CompitParameter.DHW_MODE: {
250
+ "disabled": 0,
251
+ "constant": 1,
252
+ "schedule": 2,
253
+ },
254
+ CompitParameter.DHW_CIRCULATION_MODE: {
255
+ "disabled": 0,
256
+ "constant": 1,
257
+ "schedule": 2,
258
+ },
259
+ CompitParameter.R770_MIXER_MODE_ZONE_1: {
260
+ "disabled": 0,
261
+ "schedule": 1,
262
+ "thermostat": 2,
263
+ "nano_nr_1": 3,
264
+ "nano_nr_2": 4,
265
+ "nano_nr_3": 5,
266
+ "nano_nr_4": 6,
267
+ "nano_nr_5": 7,
268
+ },
269
+ CompitParameter.R770_MIXER_MODE_ZONE_2: {
270
+ "disabled": 0,
271
+ "schedule": 1,
272
+ "thermostat": 2,
273
+ "nano_nr_1": 3,
274
+ "nano_nr_2": 4,
275
+ "nano_nr_3": 5,
276
+ "nano_nr_4": 6,
277
+ "nano_nr_5": 7,
278
+ },
279
+ CompitParameter.R770_DHW_OPERATING_MODE: {
280
+ "disabled": 0,
281
+ "constant": 1,
282
+ "schedule": 2,
283
+ },
284
+ CompitParameter.R770_DHW_CIRCULATION_MODE: {
285
+ "disabled": 0,
286
+ "constant": 1,
287
+ "schedule": 2,
288
+ },
289
+ CompitParameter.BIOMAX_HEATING_SOURCE_OF_CORRECTION: {
290
+ "disabled": 0,
291
+ "no_corrections": 1,
292
+ "schedule": 2,
293
+ "thermostat": 3,
294
+ "nano_nr_1": 4,
295
+ "nano_nr_2": 5,
296
+ "nano_nr_3": 6,
297
+ "nano_nr_4": 7,
298
+ "nano_nr_5": 8,
299
+ },
300
+ CompitParameter.BIOMAX_MIXER_MODE_ZONE_1: {
301
+ "disabled": 0,
302
+ "without_thermostat": 1,
303
+ "no_corrections": 1,
304
+ "schedule": 2,
305
+ "thermostat": 3,
306
+ "nano_nr_1": 4,
307
+ "nano_nr_2": 5,
308
+ "nano_nr_3": 6,
309
+ "nano_nr_4": 7,
310
+ "nano_nr_5": 8,
311
+ },
312
+ CompitParameter.BIOMAX_MIXER_MODE_ZONE_2: {
313
+ "disabled": 0,
314
+ "without_thermostat": 1,
315
+ "no_corrections": 1,
316
+ "schedule": 2,
317
+ "thermostat": 3,
318
+ "nano_nr_1": 4,
319
+ "nano_nr_2": 5,
320
+ "nano_nr_3": 6,
321
+ "nano_nr_4": 7,
322
+ "nano_nr_5": 8,
323
+ },
324
+ CompitParameter.BIOMAX_DHW_MODE: {
325
+ "disabled": 0,
326
+ "constant": 1,
327
+ "schedule": 2,
328
+ },
329
+ CompitParameter.BIOMAX_DHW_CIRCULATION_MODE: {
330
+ "disabled": 0,
331
+ "constant": 1,
332
+ "schedule": 2,
333
+ },
334
+ CompitParameter.BIOMAX_DHW_CIRCULATION_MODE: {
335
+ "disabled": 0,
336
+ "constant": 1,
337
+ "schedule": 2,
338
+ },
339
+ CompitParameter.R350_HEATING_SOURCE_OF_CORRECTION: {
340
+ "no_corrections": 1,
341
+ "schedule": 2,
342
+ "thermostat": 3,
343
+ "nano_nr_1": 4,
344
+ "nano_nr_2": 5,
345
+ "nano_nr_3": 6,
346
+ "nano_nr_4": 7,
347
+ "nano_nr_5": 8,
348
+ },
349
+ CompitParameter.R480_DHW_CIRCULATION: {
350
+ "disabled": 0,
351
+ "schedule": 1,
352
+ "constant": 2,
353
+ },
354
+ CompitParameter.R480_OPERATING_MODE: {
355
+ "disabled": 0,
356
+ "eco": 1,
357
+ "hybrid": 2,
358
+ },
359
+ CompitParameter.R480_DHW_MODE: {
360
+ "disabled": 0,
361
+ "schedule": 1,
362
+ "manual": 2,
363
+ },
364
+ CompitParameter.R480_BUFFER_MODE: {
365
+ "disabled": 0,
366
+ "schedule": 1,
367
+ "manual": 2,
368
+ },
369
+ }
File without changes
@@ -0,0 +1,126 @@
1
+ """Module containing device definitions for compit which are deserialized from json.""" # noqa: INP001
2
+
3
+ from typing import Any
4
+
5
+
6
+ class ParameterDetails:
7
+ """Class representing the details of a parameter."""
8
+
9
+ def __init__(self, State: int, Description: str, Param: str) -> None:
10
+ """Initialize the ParameterDetails class.
11
+
12
+ Args:
13
+ State (int): The state of the parameter.
14
+ Description (str): The description of the parameter.
15
+ Param (str): The parameter value.
16
+
17
+ """
18
+ self.state = State
19
+ self.description = Description
20
+ self.param = Param
21
+
22
+
23
+ class Parameter:
24
+ """Class representing a parameter."""
25
+
26
+ def __init__(
27
+ self,
28
+ ParameterCode: str,
29
+ Label: str,
30
+ ReadWrite: str = "R",
31
+ Details: list[dict[str, Any]] | None = None,
32
+ MinValue: float | None = None,
33
+ MaxValue: float | None = None,
34
+ Unit: str | None = None,
35
+ Type: str | None = None,
36
+ ) -> None:
37
+ """Initialize the DeviceDefinitions class."""
38
+
39
+ self.parameter_code = ParameterCode
40
+ self.label = Label
41
+ self.ReadOnly = ReadWrite == "R"
42
+ self.details = (
43
+ [ParameterDetails(**detail) if Details else None for detail in Details]
44
+ if Details
45
+ else None
46
+ )
47
+ self.min_value = MinValue
48
+ self.max_value = MaxValue
49
+ self.unit = Unit
50
+ self.type = Type
51
+
52
+
53
+ class Device:
54
+ """Class representing a device."""
55
+
56
+ def __init__(
57
+ self,
58
+ name: str,
59
+ parameters: list[Parameter],
60
+ code: int,
61
+ device_class: int,
62
+ id: int | None,
63
+ ) -> None:
64
+ """Initialize the Device class.
65
+
66
+ Args:
67
+ name (str): The name of the device.
68
+ parameters (list[Parameter]): The list of parameters for the device.
69
+ code (int): The code of the device.
70
+ device_class (int): The class of the device.
71
+ id (int | None): The ID of the device.
72
+
73
+ """
74
+ self.name = name
75
+ self.parameters = parameters
76
+ self.code = code
77
+ self.device_class = device_class
78
+ self.id = id
79
+ self.type = type
80
+
81
+ @classmethod
82
+ def from_json(cls, data: dict[str, Any]):
83
+ """Create a DeviceDefinitions instance from JSON data.
84
+
85
+ Args:
86
+ data (dict[str, Any]): The JSON data representing the device definitions.
87
+
88
+ Returns:
89
+ DeviceDefinitions: The created DeviceDefinitions instance.
90
+
91
+ """
92
+ parameters = [Parameter(**param) for param in data.get("Parameters", [])]
93
+ return cls(
94
+ name=data["Name"],
95
+ parameters=parameters,
96
+ code=data["Code"],
97
+ device_class=data["Class"],
98
+ id=data.get("ID"),
99
+ )
100
+
101
+
102
+ class DeviceDefinitions:
103
+ """Class representing device definitions."""
104
+
105
+ def __init__(self, devices: list[Device]) -> None:
106
+ """Initialize the DeviceDefinitions class.
107
+
108
+ Args:
109
+ devices (list[Device]): The list of devices.
110
+
111
+ """
112
+ self.devices = devices
113
+
114
+ @classmethod
115
+ def from_json(cls, data: Any):
116
+ """Create a DeviceDefinitions instance from JSON data.
117
+
118
+ Args:
119
+ data (Any): The JSON data representing the device definitions.
120
+
121
+ Returns:
122
+ DeviceDefinitions: The created DeviceDefinitions instance.
123
+
124
+ """
125
+ devices = [Device.from_json(device_data) for device_data in data]
126
+ return cls(devices=devices)
@@ -0,0 +1,137 @@
1
+ """Module containing params definitions.""" # noqa: INP001
2
+
3
+ from typing import Any
4
+
5
+ from .DeviceDefinitions import Device, Parameter
6
+
7
+
8
+ class Param:
9
+ """Class representing a parameter."""
10
+
11
+ def __init__(
12
+ self,
13
+ code: str,
14
+ hidden: bool,
15
+ max: float | None,
16
+ min: float | None,
17
+ value: Any,
18
+ value_code: str | None,
19
+ value_label: str | None,
20
+ write: bool,
21
+ ext_info: dict | None = None,
22
+ ) -> None:
23
+ """Initialize the Param object."""
24
+ self.code = code
25
+ self.hidden = hidden
26
+ self.max = max
27
+ self.min = min
28
+ self.value = value
29
+ self.value_code = value_code
30
+ self.value_label = value_label
31
+ self.write = write
32
+ self.ext_info = ext_info
33
+
34
+
35
+ class DeviceState:
36
+ """Class representing the state of a device."""
37
+
38
+ def __init__(
39
+ self, errors: list[Any], last_connected_at: str, params: list[Param]
40
+ ) -> None:
41
+ """Initialize the DeviceState object."""
42
+ self.errors = errors
43
+ self.last_connected_at = last_connected_at
44
+ self.params = params
45
+
46
+ def get_parameter_value(self, param: str | Parameter) -> Param | None:
47
+ """Get the value of a parameter by its code or parameter object.
48
+
49
+ Args:
50
+ param (str | Parameter): The code or parameter object.
51
+
52
+ Returns:
53
+ Param: The parameter object.
54
+
55
+ """
56
+
57
+ if isinstance(param, str):
58
+ return next(
59
+ (item for item in self.params if item and item.code == param), None
60
+ )
61
+ return next(
62
+ (
63
+ item
64
+ for item in self.params
65
+ if item and item.code == param.parameter_code
66
+ ),
67
+ None,
68
+ )
69
+
70
+ def set_parameter_value(self, param: str | Parameter, value: Any) -> bool:
71
+ """Set the value of a parameter by its code or parameter object.
72
+
73
+ Args:
74
+ param (str | Parameter): The code or parameter object.
75
+ value (Any): The new value of the parameter.
76
+ """
77
+ if isinstance(param, str):
78
+ parameter = next(
79
+ (item for item in self.params if item and item.code == param), None
80
+ )
81
+ if parameter:
82
+ parameter.value = value
83
+ return parameter is not None
84
+ else:
85
+ parameter = next(
86
+ (
87
+ item
88
+ for item in self.params
89
+ if item and item.code == param.parameter_code
90
+ ),
91
+ None,
92
+ )
93
+ if parameter:
94
+ parameter.value = value
95
+ return parameter is not None
96
+
97
+ @classmethod
98
+ def from_json(cls, data: dict):
99
+ """Create a DeviceState object from JSON data."""
100
+ params = [
101
+ Param(
102
+ code=p["code"],
103
+ hidden=p["hidden"],
104
+ max=p.get("max"),
105
+ min=p.get("min"),
106
+ value=p["value"],
107
+ value_code=p.get("value_code"),
108
+ value_label=p.get("value_label"),
109
+ write=p["write"],
110
+ ext_info=p.get("ext_info"),
111
+ )
112
+ for p in data["params"]
113
+ ]
114
+ return cls(
115
+ errors=data["errors"],
116
+ last_connected_at=data["last_connected_at"],
117
+ params=params,
118
+ )
119
+
120
+
121
+ class DeviceInstance:
122
+ """Class representing a device instance."""
123
+
124
+ def __init__(self, label: str, definition: Device | None) -> None:
125
+ """Initialize the DeviceInstance object."""
126
+ self.label = label
127
+ self.definition = definition
128
+ self.state: DeviceState
129
+
130
+ class GateInstance:
131
+ """Class representing a gate instance."""
132
+
133
+ def __init__(self, id: int, label: str) -> None:
134
+ """Initialize the GateInstance object."""
135
+ self.id = id
136
+ self.label = label
137
+ self.devices: dict[int, DeviceInstance] = {}