aiohomematic 2025.11.3__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.
Potentially problematic release.
This version of aiohomematic might be problematic. Click here for more details.
- aiohomematic/__init__.py +61 -0
- aiohomematic/async_support.py +212 -0
- aiohomematic/central/__init__.py +2309 -0
- aiohomematic/central/decorators.py +155 -0
- aiohomematic/central/rpc_server.py +295 -0
- aiohomematic/client/__init__.py +1848 -0
- aiohomematic/client/_rpc_errors.py +81 -0
- aiohomematic/client/json_rpc.py +1326 -0
- aiohomematic/client/rpc_proxy.py +311 -0
- aiohomematic/const.py +1127 -0
- aiohomematic/context.py +18 -0
- aiohomematic/converter.py +108 -0
- aiohomematic/decorators.py +302 -0
- aiohomematic/exceptions.py +164 -0
- aiohomematic/hmcli.py +186 -0
- aiohomematic/model/__init__.py +140 -0
- aiohomematic/model/calculated/__init__.py +84 -0
- aiohomematic/model/calculated/climate.py +290 -0
- aiohomematic/model/calculated/data_point.py +327 -0
- aiohomematic/model/calculated/operating_voltage_level.py +299 -0
- aiohomematic/model/calculated/support.py +234 -0
- aiohomematic/model/custom/__init__.py +177 -0
- aiohomematic/model/custom/climate.py +1532 -0
- aiohomematic/model/custom/cover.py +792 -0
- aiohomematic/model/custom/data_point.py +334 -0
- aiohomematic/model/custom/definition.py +871 -0
- aiohomematic/model/custom/light.py +1128 -0
- aiohomematic/model/custom/lock.py +394 -0
- aiohomematic/model/custom/siren.py +275 -0
- aiohomematic/model/custom/support.py +41 -0
- aiohomematic/model/custom/switch.py +175 -0
- aiohomematic/model/custom/valve.py +114 -0
- aiohomematic/model/data_point.py +1123 -0
- aiohomematic/model/device.py +1445 -0
- aiohomematic/model/event.py +208 -0
- aiohomematic/model/generic/__init__.py +217 -0
- aiohomematic/model/generic/action.py +34 -0
- aiohomematic/model/generic/binary_sensor.py +30 -0
- aiohomematic/model/generic/button.py +27 -0
- aiohomematic/model/generic/data_point.py +171 -0
- aiohomematic/model/generic/dummy.py +147 -0
- aiohomematic/model/generic/number.py +76 -0
- aiohomematic/model/generic/select.py +39 -0
- aiohomematic/model/generic/sensor.py +74 -0
- aiohomematic/model/generic/switch.py +54 -0
- aiohomematic/model/generic/text.py +29 -0
- aiohomematic/model/hub/__init__.py +333 -0
- aiohomematic/model/hub/binary_sensor.py +24 -0
- aiohomematic/model/hub/button.py +28 -0
- aiohomematic/model/hub/data_point.py +340 -0
- aiohomematic/model/hub/number.py +39 -0
- aiohomematic/model/hub/select.py +49 -0
- aiohomematic/model/hub/sensor.py +37 -0
- aiohomematic/model/hub/switch.py +44 -0
- aiohomematic/model/hub/text.py +30 -0
- aiohomematic/model/support.py +586 -0
- aiohomematic/model/update.py +143 -0
- aiohomematic/property_decorators.py +496 -0
- aiohomematic/py.typed +0 -0
- aiohomematic/rega_scripts/fetch_all_device_data.fn +92 -0
- aiohomematic/rega_scripts/get_program_descriptions.fn +30 -0
- aiohomematic/rega_scripts/get_serial.fn +44 -0
- aiohomematic/rega_scripts/get_system_variable_descriptions.fn +30 -0
- aiohomematic/rega_scripts/set_program_state.fn +12 -0
- aiohomematic/rega_scripts/set_system_variable.fn +15 -0
- aiohomematic/store/__init__.py +34 -0
- aiohomematic/store/dynamic.py +551 -0
- aiohomematic/store/persistent.py +988 -0
- aiohomematic/store/visibility.py +812 -0
- aiohomematic/support.py +664 -0
- aiohomematic/validator.py +112 -0
- aiohomematic-2025.11.3.dist-info/METADATA +144 -0
- aiohomematic-2025.11.3.dist-info/RECORD +77 -0
- aiohomematic-2025.11.3.dist-info/WHEEL +5 -0
- aiohomematic-2025.11.3.dist-info/entry_points.txt +2 -0
- aiohomematic-2025.11.3.dist-info/licenses/LICENSE +21 -0
- aiohomematic-2025.11.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for AioHomematic hub data points."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Any, Final
|
|
9
|
+
|
|
10
|
+
from slugify import slugify
|
|
11
|
+
|
|
12
|
+
from aiohomematic import central as hmcu
|
|
13
|
+
from aiohomematic.const import (
|
|
14
|
+
PROGRAM_ADDRESS,
|
|
15
|
+
SYSVAR_ADDRESS,
|
|
16
|
+
SYSVAR_TYPE,
|
|
17
|
+
HubData,
|
|
18
|
+
ProgramData,
|
|
19
|
+
SystemVariableData,
|
|
20
|
+
SysvarType,
|
|
21
|
+
)
|
|
22
|
+
from aiohomematic.decorators import inspector
|
|
23
|
+
from aiohomematic.model.data_point import CallbackDataPoint
|
|
24
|
+
from aiohomematic.model.device import Channel
|
|
25
|
+
from aiohomematic.model.support import (
|
|
26
|
+
PathData,
|
|
27
|
+
ProgramPathData,
|
|
28
|
+
SysvarPathData,
|
|
29
|
+
generate_unique_id,
|
|
30
|
+
get_hub_data_point_name_data,
|
|
31
|
+
)
|
|
32
|
+
from aiohomematic.property_decorators import config_property, state_property
|
|
33
|
+
from aiohomematic.support import PayloadMixin, parse_sys_var
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class GenericHubDataPoint(CallbackDataPoint, PayloadMixin):
|
|
37
|
+
"""Class for a Homematic system variable."""
|
|
38
|
+
|
|
39
|
+
__slots__ = (
|
|
40
|
+
"_channel",
|
|
41
|
+
"_description",
|
|
42
|
+
"_enabled_default",
|
|
43
|
+
"_legacy_name",
|
|
44
|
+
"_name_data",
|
|
45
|
+
"_state_uncertain",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
*,
|
|
51
|
+
central: hmcu.CentralUnit,
|
|
52
|
+
address: str,
|
|
53
|
+
data: HubData,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Initialize the data_point."""
|
|
56
|
+
PayloadMixin.__init__(self)
|
|
57
|
+
unique_id: Final = generate_unique_id(
|
|
58
|
+
central=central,
|
|
59
|
+
address=address,
|
|
60
|
+
parameter=slugify(data.legacy_name),
|
|
61
|
+
)
|
|
62
|
+
self._legacy_name = data.legacy_name
|
|
63
|
+
self._channel = central.identify_channel(text=data.legacy_name)
|
|
64
|
+
self._name_data: Final = get_hub_data_point_name_data(
|
|
65
|
+
channel=self._channel, legacy_name=data.legacy_name, central_name=central.name
|
|
66
|
+
)
|
|
67
|
+
self._description = data.description
|
|
68
|
+
super().__init__(central=central, unique_id=unique_id)
|
|
69
|
+
self._enabled_default: Final = data.enabled_default
|
|
70
|
+
self._state_uncertain: bool = True
|
|
71
|
+
|
|
72
|
+
@state_property
|
|
73
|
+
def available(self) -> bool:
|
|
74
|
+
"""Return the availability of the device."""
|
|
75
|
+
return self.central.available
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def legacy_name(self) -> str | None:
|
|
79
|
+
"""Return the original sysvar name."""
|
|
80
|
+
return self._legacy_name
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def channel(self) -> Channel | None:
|
|
84
|
+
"""Return the identified channel."""
|
|
85
|
+
return self._channel
|
|
86
|
+
|
|
87
|
+
@config_property
|
|
88
|
+
def description(self) -> str | None:
|
|
89
|
+
"""Return sysvar description."""
|
|
90
|
+
return self._description
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def full_name(self) -> str:
|
|
94
|
+
"""Return the fullname of the data_point."""
|
|
95
|
+
return self._name_data.full_name
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def enabled_default(self) -> bool:
|
|
99
|
+
"""Return if the data_point should be enabled."""
|
|
100
|
+
return self._enabled_default
|
|
101
|
+
|
|
102
|
+
@config_property
|
|
103
|
+
def name(self) -> str:
|
|
104
|
+
"""Return the name of the data_point."""
|
|
105
|
+
return self._name_data.name
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def state_uncertain(self) -> bool:
|
|
109
|
+
"""Return, if the state is uncertain."""
|
|
110
|
+
return self._state_uncertain
|
|
111
|
+
|
|
112
|
+
def _get_signature(self) -> str:
|
|
113
|
+
"""Return the signature of the data_point."""
|
|
114
|
+
return f"{self._category}/{self.name}"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class GenericSysvarDataPoint(GenericHubDataPoint):
|
|
118
|
+
"""Class for a Homematic system variable."""
|
|
119
|
+
|
|
120
|
+
__slots__ = (
|
|
121
|
+
"_current_value",
|
|
122
|
+
"_data_type",
|
|
123
|
+
"_max",
|
|
124
|
+
"_min",
|
|
125
|
+
"_previous_value",
|
|
126
|
+
"_temporary_value",
|
|
127
|
+
"_unit",
|
|
128
|
+
"_values",
|
|
129
|
+
"_vid",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
_is_extended = False
|
|
133
|
+
|
|
134
|
+
def __init__(
|
|
135
|
+
self,
|
|
136
|
+
*,
|
|
137
|
+
central: hmcu.CentralUnit,
|
|
138
|
+
data: SystemVariableData,
|
|
139
|
+
) -> None:
|
|
140
|
+
"""Initialize the data_point."""
|
|
141
|
+
self._vid: Final = data.vid
|
|
142
|
+
super().__init__(central=central, address=SYSVAR_ADDRESS, data=data)
|
|
143
|
+
self._data_type = data.data_type
|
|
144
|
+
self._values: Final[tuple[str, ...] | None] = tuple(data.values) if data.values else None
|
|
145
|
+
self._max: Final = data.max_value
|
|
146
|
+
self._min: Final = data.min_value
|
|
147
|
+
self._unit: Final = data.unit
|
|
148
|
+
self._current_value: SYSVAR_TYPE = data.value
|
|
149
|
+
self._previous_value: SYSVAR_TYPE = None
|
|
150
|
+
self._temporary_value: SYSVAR_TYPE = None
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def data_type(self) -> SysvarType | None:
|
|
154
|
+
"""Return the availability of the device."""
|
|
155
|
+
return self._data_type
|
|
156
|
+
|
|
157
|
+
@data_type.setter
|
|
158
|
+
def data_type(self, data_type: SysvarType) -> None:
|
|
159
|
+
"""Write data_type."""
|
|
160
|
+
self._data_type = data_type
|
|
161
|
+
|
|
162
|
+
@config_property
|
|
163
|
+
def vid(self) -> str:
|
|
164
|
+
"""Return sysvar id."""
|
|
165
|
+
return self._vid
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def previous_value(self) -> SYSVAR_TYPE:
|
|
169
|
+
"""Return the previous value."""
|
|
170
|
+
return self._previous_value
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def _value(self) -> Any | None:
|
|
174
|
+
"""Return the value."""
|
|
175
|
+
return self._temporary_value if self._temporary_refreshed_at > self._refreshed_at else self._current_value
|
|
176
|
+
|
|
177
|
+
@state_property
|
|
178
|
+
def value(self) -> Any | None:
|
|
179
|
+
"""Return the value."""
|
|
180
|
+
return self._value
|
|
181
|
+
|
|
182
|
+
@state_property
|
|
183
|
+
def values(self) -> tuple[str, ...] | None:
|
|
184
|
+
"""Return the value_list."""
|
|
185
|
+
return self._values
|
|
186
|
+
|
|
187
|
+
@config_property
|
|
188
|
+
def max(self) -> float | int | None:
|
|
189
|
+
"""Return the max value."""
|
|
190
|
+
return self._max
|
|
191
|
+
|
|
192
|
+
@config_property
|
|
193
|
+
def min(self) -> float | int | None:
|
|
194
|
+
"""Return the min value."""
|
|
195
|
+
return self._min
|
|
196
|
+
|
|
197
|
+
@config_property
|
|
198
|
+
def unit(self) -> str | None:
|
|
199
|
+
"""Return the unit of the data_point."""
|
|
200
|
+
return self._unit
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def is_extended(self) -> bool:
|
|
204
|
+
"""Return if the data_point is an extended type."""
|
|
205
|
+
return self._is_extended
|
|
206
|
+
|
|
207
|
+
def _get_path_data(self) -> PathData:
|
|
208
|
+
"""Return the path data of the data_point."""
|
|
209
|
+
return SysvarPathData(vid=self._vid)
|
|
210
|
+
|
|
211
|
+
async def event(self, *, value: Any, received_at: datetime) -> None:
|
|
212
|
+
"""Handle event for which this data_point has subscribed."""
|
|
213
|
+
self.write_value(value=value, write_at=received_at)
|
|
214
|
+
|
|
215
|
+
def _reset_temporary_value(self) -> None:
|
|
216
|
+
"""Reset the temp storage."""
|
|
217
|
+
self._temporary_value = None
|
|
218
|
+
self._reset_temporary_timestamps()
|
|
219
|
+
|
|
220
|
+
def write_value(self, *, value: Any, write_at: datetime) -> None:
|
|
221
|
+
"""Set variable value on the backend."""
|
|
222
|
+
self._reset_temporary_value()
|
|
223
|
+
|
|
224
|
+
old_value = self._current_value
|
|
225
|
+
new_value = self._convert_value(old_value=old_value, new_value=value)
|
|
226
|
+
if old_value == new_value:
|
|
227
|
+
self._set_refreshed_at(refreshed_at=write_at)
|
|
228
|
+
else:
|
|
229
|
+
self._set_modified_at(modified_at=write_at)
|
|
230
|
+
self._previous_value = old_value
|
|
231
|
+
self._current_value = new_value
|
|
232
|
+
self._state_uncertain = False
|
|
233
|
+
self.emit_data_point_updated_event()
|
|
234
|
+
|
|
235
|
+
def _write_temporary_value(self, *, value: Any, write_at: datetime) -> None:
|
|
236
|
+
"""Update the temporary value of the data_point."""
|
|
237
|
+
self._reset_temporary_value()
|
|
238
|
+
|
|
239
|
+
temp_value = self._convert_value(old_value=self._current_value, new_value=value)
|
|
240
|
+
if self._value == temp_value:
|
|
241
|
+
self._set_temporary_refreshed_at(refreshed_at=write_at)
|
|
242
|
+
else:
|
|
243
|
+
self._set_temporary_modified_at(modified_at=write_at)
|
|
244
|
+
self._temporary_value = temp_value
|
|
245
|
+
self._state_uncertain = True
|
|
246
|
+
self.emit_data_point_updated_event()
|
|
247
|
+
|
|
248
|
+
def _convert_value(self, *, old_value: Any, new_value: Any) -> Any:
|
|
249
|
+
"""Convert to value to SYSVAR_TYPE."""
|
|
250
|
+
if new_value is None:
|
|
251
|
+
return None
|
|
252
|
+
value = new_value
|
|
253
|
+
if self._data_type:
|
|
254
|
+
value = parse_sys_var(data_type=self._data_type, raw_value=new_value)
|
|
255
|
+
elif isinstance(old_value, bool):
|
|
256
|
+
value = bool(new_value)
|
|
257
|
+
elif isinstance(old_value, int):
|
|
258
|
+
value = int(new_value)
|
|
259
|
+
elif isinstance(old_value, str):
|
|
260
|
+
value = str(new_value)
|
|
261
|
+
elif isinstance(old_value, float):
|
|
262
|
+
value = float(new_value)
|
|
263
|
+
return value
|
|
264
|
+
|
|
265
|
+
@inspector
|
|
266
|
+
async def send_variable(self, *, value: Any) -> None:
|
|
267
|
+
"""Set variable value on the backend."""
|
|
268
|
+
if client := self.central.primary_client:
|
|
269
|
+
await client.set_system_variable(
|
|
270
|
+
legacy_name=self._legacy_name, value=parse_sys_var(data_type=self._data_type, raw_value=value)
|
|
271
|
+
)
|
|
272
|
+
self._write_temporary_value(value=value, write_at=datetime.now())
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class GenericProgramDataPoint(GenericHubDataPoint):
|
|
276
|
+
"""Class for a generic Homematic progran data point."""
|
|
277
|
+
|
|
278
|
+
__slots__ = (
|
|
279
|
+
"_pid",
|
|
280
|
+
"_is_active",
|
|
281
|
+
"_is_internal",
|
|
282
|
+
"_last_execute_time",
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
def __init__(
|
|
286
|
+
self,
|
|
287
|
+
*,
|
|
288
|
+
central: hmcu.CentralUnit,
|
|
289
|
+
data: ProgramData,
|
|
290
|
+
) -> None:
|
|
291
|
+
"""Initialize the data_point."""
|
|
292
|
+
self._pid: Final = data.pid
|
|
293
|
+
super().__init__(
|
|
294
|
+
central=central,
|
|
295
|
+
address=PROGRAM_ADDRESS,
|
|
296
|
+
data=data,
|
|
297
|
+
)
|
|
298
|
+
self._is_active: bool = data.is_active
|
|
299
|
+
self._is_internal: bool = data.is_internal
|
|
300
|
+
self._last_execute_time: str = data.last_execute_time
|
|
301
|
+
self._state_uncertain: bool = True
|
|
302
|
+
|
|
303
|
+
@state_property
|
|
304
|
+
def is_active(self) -> bool:
|
|
305
|
+
"""Return the program is active."""
|
|
306
|
+
return self._is_active
|
|
307
|
+
|
|
308
|
+
@config_property
|
|
309
|
+
def is_internal(self) -> bool:
|
|
310
|
+
"""Return the program is internal."""
|
|
311
|
+
return self._is_internal
|
|
312
|
+
|
|
313
|
+
@state_property
|
|
314
|
+
def last_execute_time(self) -> str:
|
|
315
|
+
"""Return the last execute time."""
|
|
316
|
+
return self._last_execute_time
|
|
317
|
+
|
|
318
|
+
@config_property
|
|
319
|
+
def pid(self) -> str:
|
|
320
|
+
"""Return the program id."""
|
|
321
|
+
return self._pid
|
|
322
|
+
|
|
323
|
+
def update_data(self, *, data: ProgramData) -> None:
|
|
324
|
+
"""Set variable value on the backend."""
|
|
325
|
+
do_update: bool = False
|
|
326
|
+
if self._is_active != data.is_active:
|
|
327
|
+
self._is_active = data.is_active
|
|
328
|
+
do_update = True
|
|
329
|
+
if self._is_internal != data.is_internal:
|
|
330
|
+
self._is_internal = data.is_internal
|
|
331
|
+
do_update = True
|
|
332
|
+
if self._last_execute_time != data.last_execute_time:
|
|
333
|
+
self._last_execute_time = data.last_execute_time
|
|
334
|
+
do_update = True
|
|
335
|
+
if do_update:
|
|
336
|
+
self.emit_data_point_updated_event()
|
|
337
|
+
|
|
338
|
+
def _get_path_data(self) -> PathData:
|
|
339
|
+
"""Return the path data of the data_point."""
|
|
340
|
+
return ProgramPathData(pid=self.pid)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for data points implemented using the number category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Final
|
|
9
|
+
|
|
10
|
+
from aiohomematic.const import DataPointCategory
|
|
11
|
+
from aiohomematic.decorators import inspector
|
|
12
|
+
from aiohomematic.model.hub.data_point import GenericSysvarDataPoint
|
|
13
|
+
|
|
14
|
+
_LOGGER: Final = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SysvarDpNumber(GenericSysvarDataPoint):
|
|
18
|
+
"""Implementation of a sysvar number."""
|
|
19
|
+
|
|
20
|
+
__slots__ = ()
|
|
21
|
+
|
|
22
|
+
_category = DataPointCategory.HUB_NUMBER
|
|
23
|
+
_is_extended = True
|
|
24
|
+
|
|
25
|
+
@inspector
|
|
26
|
+
async def send_variable(self, *, value: float) -> None:
|
|
27
|
+
"""Set the value of the data_point."""
|
|
28
|
+
if value is not None and self.max is not None and self.min is not None:
|
|
29
|
+
if self.min <= float(value) <= self.max:
|
|
30
|
+
await super().send_variable(value=value)
|
|
31
|
+
else:
|
|
32
|
+
_LOGGER.warning(
|
|
33
|
+
"SYSVAR.NUMBER failed: Invalid value: %s (min: %s, max: %s)",
|
|
34
|
+
value,
|
|
35
|
+
self.min,
|
|
36
|
+
self.max,
|
|
37
|
+
)
|
|
38
|
+
return
|
|
39
|
+
await super().send_variable(value=value)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for hub data points implemented using the select category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Final
|
|
9
|
+
|
|
10
|
+
from aiohomematic.const import DataPointCategory
|
|
11
|
+
from aiohomematic.decorators import inspector
|
|
12
|
+
from aiohomematic.model.hub.data_point import GenericSysvarDataPoint
|
|
13
|
+
from aiohomematic.model.support import get_value_from_value_list
|
|
14
|
+
from aiohomematic.property_decorators import state_property
|
|
15
|
+
|
|
16
|
+
_LOGGER: Final = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SysvarDpSelect(GenericSysvarDataPoint):
|
|
20
|
+
"""Implementation of a sysvar select data_point."""
|
|
21
|
+
|
|
22
|
+
__slots__ = ()
|
|
23
|
+
|
|
24
|
+
_category = DataPointCategory.HUB_SELECT
|
|
25
|
+
_is_extended = True
|
|
26
|
+
|
|
27
|
+
@state_property
|
|
28
|
+
def value(self) -> str | None:
|
|
29
|
+
"""Get the value of the data_point."""
|
|
30
|
+
if (value := get_value_from_value_list(value=self._value, value_list=self.values)) is not None:
|
|
31
|
+
return value
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
@inspector
|
|
35
|
+
async def send_variable(self, *, value: int | str) -> None:
|
|
36
|
+
"""Set the value of the data_point."""
|
|
37
|
+
# We allow setting the value via index as well, just in case.
|
|
38
|
+
if isinstance(value, int) and self._values:
|
|
39
|
+
if 0 <= value < len(self._values):
|
|
40
|
+
await super().send_variable(value=value)
|
|
41
|
+
elif self._values:
|
|
42
|
+
if value in self._values:
|
|
43
|
+
await super().send_variable(value=self._values.index(value))
|
|
44
|
+
else:
|
|
45
|
+
_LOGGER.warning(
|
|
46
|
+
"Value not in value_list for %s/%s",
|
|
47
|
+
self.name,
|
|
48
|
+
self.unique_id,
|
|
49
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for hub data points implemented using the sensor category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any, Final
|
|
9
|
+
|
|
10
|
+
from aiohomematic.const import DataPointCategory, SysvarType
|
|
11
|
+
from aiohomematic.model.hub.data_point import GenericSysvarDataPoint
|
|
12
|
+
from aiohomematic.model.support import check_length_and_log, get_value_from_value_list
|
|
13
|
+
from aiohomematic.property_decorators import state_property
|
|
14
|
+
|
|
15
|
+
_LOGGER: Final = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SysvarDpSensor(GenericSysvarDataPoint):
|
|
19
|
+
"""Implementation of a sysvar sensor."""
|
|
20
|
+
|
|
21
|
+
__slots__ = ()
|
|
22
|
+
|
|
23
|
+
_category = DataPointCategory.HUB_SENSOR
|
|
24
|
+
|
|
25
|
+
@state_property
|
|
26
|
+
def value(self) -> Any | None:
|
|
27
|
+
"""Return the value."""
|
|
28
|
+
if (
|
|
29
|
+
self._data_type == SysvarType.LIST
|
|
30
|
+
and (value := get_value_from_value_list(value=self._value, value_list=self.values)) is not None
|
|
31
|
+
):
|
|
32
|
+
return value
|
|
33
|
+
return (
|
|
34
|
+
check_length_and_log(name=self._legacy_name, value=self._value)
|
|
35
|
+
if self._data_type == SysvarType.STRING
|
|
36
|
+
else self._value
|
|
37
|
+
)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for hub data points implemented using the switch category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from aiohomematic.const import DataPointCategory
|
|
8
|
+
from aiohomematic.decorators import inspector
|
|
9
|
+
from aiohomematic.model.hub.data_point import GenericProgramDataPoint, GenericSysvarDataPoint
|
|
10
|
+
from aiohomematic.property_decorators import state_property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SysvarDpSwitch(GenericSysvarDataPoint):
|
|
14
|
+
"""Implementation of a sysvar switch data_point."""
|
|
15
|
+
|
|
16
|
+
__slots__ = ()
|
|
17
|
+
|
|
18
|
+
_category = DataPointCategory.HUB_SWITCH
|
|
19
|
+
_is_extended = True
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ProgramDpSwitch(GenericProgramDataPoint):
|
|
23
|
+
"""Implementation of a program switch data_point."""
|
|
24
|
+
|
|
25
|
+
__slots__ = ()
|
|
26
|
+
|
|
27
|
+
_category = DataPointCategory.HUB_SWITCH
|
|
28
|
+
|
|
29
|
+
@state_property
|
|
30
|
+
def value(self) -> bool | None:
|
|
31
|
+
"""Get the value of the data_point."""
|
|
32
|
+
return self._is_active
|
|
33
|
+
|
|
34
|
+
@inspector
|
|
35
|
+
async def turn_on(self) -> None:
|
|
36
|
+
"""Turn the program on."""
|
|
37
|
+
await self.central.set_program_state(pid=self._pid, state=True)
|
|
38
|
+
await self._central.fetch_program_data(scheduled=False)
|
|
39
|
+
|
|
40
|
+
@inspector
|
|
41
|
+
async def turn_off(self) -> None:
|
|
42
|
+
"""Turn the program off."""
|
|
43
|
+
await self.central.set_program_state(pid=self._pid, state=False)
|
|
44
|
+
await self._central.fetch_program_data(scheduled=False)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for hub data points implemented using the text category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import cast
|
|
8
|
+
|
|
9
|
+
from aiohomematic.const import DataPointCategory
|
|
10
|
+
from aiohomematic.model.hub.data_point import GenericSysvarDataPoint
|
|
11
|
+
from aiohomematic.model.support import check_length_and_log
|
|
12
|
+
from aiohomematic.property_decorators import state_property
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SysvarDpText(GenericSysvarDataPoint):
|
|
16
|
+
"""Implementation of a sysvar text data_point."""
|
|
17
|
+
|
|
18
|
+
__slots__ = ()
|
|
19
|
+
|
|
20
|
+
_category = DataPointCategory.HUB_TEXT
|
|
21
|
+
_is_extended = True
|
|
22
|
+
|
|
23
|
+
@state_property
|
|
24
|
+
def value(self) -> str | None:
|
|
25
|
+
"""Get the value of the data_point."""
|
|
26
|
+
return cast(str | None, check_length_and_log(name=self._legacy_name, value=self._value))
|
|
27
|
+
|
|
28
|
+
async def send_variable(self, *, value: str | None) -> None:
|
|
29
|
+
"""Set the value of the data_point."""
|
|
30
|
+
await super().send_variable(value=value)
|