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,333 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""
|
|
4
|
+
Hub (backend) data points for AioHomematic.
|
|
5
|
+
|
|
6
|
+
Overview
|
|
7
|
+
- This module reflects the state and capabilities of the backend
|
|
8
|
+
at the hub level. It exposes backend programs and system variables as data
|
|
9
|
+
points that can be observed and acted upon by higher layers (e.g.,
|
|
10
|
+
integrations).
|
|
11
|
+
|
|
12
|
+
Responsibilities
|
|
13
|
+
- Fetch current lists of programs and system variables from the central unit.
|
|
14
|
+
- Create and maintain concrete hub data point instances for those items.
|
|
15
|
+
- Keep hub data points in sync with the backend (update values, add/remove).
|
|
16
|
+
- Notify the system about newly created hub data points via backend events.
|
|
17
|
+
|
|
18
|
+
Public API (selected)
|
|
19
|
+
- Hub: Orchestrates scanning and synchronization of hub-level data points.
|
|
20
|
+
- ProgramDpButton / ProgramDpSwitch: Represent a backend program as an
|
|
21
|
+
invocable button or a switch-like control, respectively.
|
|
22
|
+
- Sysvar data points: Map system variables to appropriate types:
|
|
23
|
+
- SysvarDpSensor, SysvarDpBinarySensor, SysvarDpSelect, SysvarDpNumber,
|
|
24
|
+
SysvarDpSwitch, SysvarDpText.
|
|
25
|
+
- __all__: Exposes the classes and types intended for external consumption.
|
|
26
|
+
|
|
27
|
+
Lifecycle and Flow
|
|
28
|
+
1. fetch_program_data / fetch_sysvar_data (async) are scheduled or triggered
|
|
29
|
+
manually depending on configuration and availability of the central unit.
|
|
30
|
+
2. On fetch:
|
|
31
|
+
- The module retrieves program/sysvar lists from the primary client.
|
|
32
|
+
- It identifies removed items and cleans up corresponding data points.
|
|
33
|
+
- It updates existing data points or creates new ones as needed.
|
|
34
|
+
3. For newly created hub data points, a BackendSystemEvent.HUB_REFRESHED event
|
|
35
|
+
is emitted with a categorized mapping of the new points for consumers.
|
|
36
|
+
|
|
37
|
+
Type Mapping for System Variables
|
|
38
|
+
- Based on SysvarType and the extended_sysvar flag, system variables are
|
|
39
|
+
represented by the most suitable hub data point class. For example:
|
|
40
|
+
- ALARM/LOGIC → binary_sensor or switch (if extended)
|
|
41
|
+
- LIST (extended) → select
|
|
42
|
+
- FLOAT/INTEGER (extended) → number
|
|
43
|
+
- STRING (extended) → text
|
|
44
|
+
- Any other case → generic sensor
|
|
45
|
+
|
|
46
|
+
Concurrency and Reliability
|
|
47
|
+
- Fetch operations are protected by semaphores to avoid concurrent updates of
|
|
48
|
+
the same kind (programs or sysvars).
|
|
49
|
+
- The inspector decorator helps ensure exceptions do not propagate unexpectedly
|
|
50
|
+
when fetching; errors are logged and the system continues operating.
|
|
51
|
+
|
|
52
|
+
Backend Specifics and Cleanup
|
|
53
|
+
- For CCU backends, certain internal variables (e.g., legacy "OldVal*",
|
|
54
|
+
"pcCCUID") are filtered out to avoid exposing irrelevant state.
|
|
55
|
+
|
|
56
|
+
Categories and New Data Point Discovery
|
|
57
|
+
- Newly created hub data points are grouped into HUB_CATEGORIES and returned as
|
|
58
|
+
a mapping, so subscribers can register and present them appropriately.
|
|
59
|
+
|
|
60
|
+
Related Modules
|
|
61
|
+
- aiohomematic.model.hub.data_point: Base types for hub-level data points.
|
|
62
|
+
- aiohomematic.central: Central unit coordination and backend communication.
|
|
63
|
+
- aiohomematic.const: Shared constants, enums, and data structures.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
- Typical usage occurs inside the central unit scheduling:
|
|
67
|
+
hub = Hub(central)
|
|
68
|
+
await hub.fetch_program_data(scheduled=True)
|
|
69
|
+
await hub.fetch_sysvar_data(scheduled=True)
|
|
70
|
+
|
|
71
|
+
This module complements device/channel data points by reflecting control center
|
|
72
|
+
state and enabling automations at the backend level.
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
from __future__ import annotations
|
|
77
|
+
|
|
78
|
+
import asyncio
|
|
79
|
+
from collections.abc import Collection, Mapping, Set as AbstractSet
|
|
80
|
+
from datetime import datetime
|
|
81
|
+
import logging
|
|
82
|
+
from typing import Final, NamedTuple
|
|
83
|
+
|
|
84
|
+
from aiohomematic import central as hmcu
|
|
85
|
+
from aiohomematic.const import (
|
|
86
|
+
HUB_CATEGORIES,
|
|
87
|
+
Backend,
|
|
88
|
+
BackendSystemEvent,
|
|
89
|
+
DataPointCategory,
|
|
90
|
+
ProgramData,
|
|
91
|
+
SystemVariableData,
|
|
92
|
+
SysvarType,
|
|
93
|
+
)
|
|
94
|
+
from aiohomematic.decorators import inspector
|
|
95
|
+
from aiohomematic.model.hub.binary_sensor import SysvarDpBinarySensor
|
|
96
|
+
from aiohomematic.model.hub.button import ProgramDpButton
|
|
97
|
+
from aiohomematic.model.hub.data_point import GenericHubDataPoint, GenericProgramDataPoint, GenericSysvarDataPoint
|
|
98
|
+
from aiohomematic.model.hub.number import SysvarDpNumber
|
|
99
|
+
from aiohomematic.model.hub.select import SysvarDpSelect
|
|
100
|
+
from aiohomematic.model.hub.sensor import SysvarDpSensor
|
|
101
|
+
from aiohomematic.model.hub.switch import ProgramDpSwitch, SysvarDpSwitch
|
|
102
|
+
from aiohomematic.model.hub.text import SysvarDpText
|
|
103
|
+
|
|
104
|
+
__all__ = [
|
|
105
|
+
"GenericProgramDataPoint",
|
|
106
|
+
"GenericSysvarDataPoint",
|
|
107
|
+
"Hub",
|
|
108
|
+
"ProgramDpButton",
|
|
109
|
+
"ProgramDpSwitch",
|
|
110
|
+
"ProgramDpType",
|
|
111
|
+
"SysvarDpBinarySensor",
|
|
112
|
+
"SysvarDpNumber",
|
|
113
|
+
"SysvarDpSelect",
|
|
114
|
+
"SysvarDpSensor",
|
|
115
|
+
"SysvarDpSwitch",
|
|
116
|
+
"SysvarDpText",
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
_LOGGER: Final = logging.getLogger(__name__)
|
|
120
|
+
|
|
121
|
+
_EXCLUDED: Final = [
|
|
122
|
+
"OldVal",
|
|
123
|
+
"pcCCUID",
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class ProgramDpType(NamedTuple):
|
|
128
|
+
"""Key for data points."""
|
|
129
|
+
|
|
130
|
+
pid: str
|
|
131
|
+
button: ProgramDpButton
|
|
132
|
+
switch: ProgramDpSwitch
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class Hub:
|
|
136
|
+
"""The Homematic hub."""
|
|
137
|
+
|
|
138
|
+
__slots__ = (
|
|
139
|
+
"_sema_fetch_sysvars",
|
|
140
|
+
"_sema_fetch_programs",
|
|
141
|
+
"_central",
|
|
142
|
+
"_config",
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def __init__(self, *, central: hmcu.CentralUnit) -> None:
|
|
146
|
+
"""Initialize Homematic hub."""
|
|
147
|
+
self._sema_fetch_sysvars: Final = asyncio.Semaphore()
|
|
148
|
+
self._sema_fetch_programs: Final = asyncio.Semaphore()
|
|
149
|
+
self._central: Final = central
|
|
150
|
+
self._config: Final = central.config
|
|
151
|
+
|
|
152
|
+
@inspector(re_raise=False)
|
|
153
|
+
async def fetch_sysvar_data(self, *, scheduled: bool) -> None:
|
|
154
|
+
"""Fetch sysvar data for the hub."""
|
|
155
|
+
if self._config.enable_sysvar_scan:
|
|
156
|
+
_LOGGER.debug(
|
|
157
|
+
"FETCH_SYSVAR_DATA: %s fetching of system variables for %s",
|
|
158
|
+
"Scheduled" if scheduled else "Manual",
|
|
159
|
+
self._central.name,
|
|
160
|
+
)
|
|
161
|
+
async with self._sema_fetch_sysvars:
|
|
162
|
+
if self._central.available:
|
|
163
|
+
await self._update_sysvar_data_points()
|
|
164
|
+
|
|
165
|
+
@inspector(re_raise=False)
|
|
166
|
+
async def fetch_program_data(self, *, scheduled: bool) -> None:
|
|
167
|
+
"""Fetch program data for the hub."""
|
|
168
|
+
if self._config.enable_program_scan:
|
|
169
|
+
_LOGGER.debug(
|
|
170
|
+
"FETCH_PROGRAM_DATA: %s fetching of programs for %s",
|
|
171
|
+
"Scheduled" if scheduled else "Manual",
|
|
172
|
+
self._central.name,
|
|
173
|
+
)
|
|
174
|
+
async with self._sema_fetch_programs:
|
|
175
|
+
if self._central.available:
|
|
176
|
+
await self._update_program_data_points()
|
|
177
|
+
|
|
178
|
+
async def _update_program_data_points(self) -> None:
|
|
179
|
+
"""Retrieve all program data and update program values."""
|
|
180
|
+
if not (client := self._central.primary_client):
|
|
181
|
+
return
|
|
182
|
+
if (programs := await client.get_all_programs(markers=self._config.program_markers)) is None:
|
|
183
|
+
_LOGGER.debug("UPDATE_PROGRAM_DATA_POINTS: Unable to retrieve programs for %s", self._central.name)
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
_LOGGER.debug(
|
|
187
|
+
"UPDATE_PROGRAM_DATA_POINTS: %i programs received for %s",
|
|
188
|
+
len(programs),
|
|
189
|
+
self._central.name,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if missing_program_ids := self._identify_missing_program_ids(programs=programs):
|
|
193
|
+
self._remove_program_data_point(ids=missing_program_ids)
|
|
194
|
+
|
|
195
|
+
new_programs: list[GenericProgramDataPoint] = []
|
|
196
|
+
|
|
197
|
+
for program_data in programs:
|
|
198
|
+
if program_dp := self._central.get_program_data_point(pid=program_data.pid):
|
|
199
|
+
program_dp.button.update_data(data=program_data)
|
|
200
|
+
program_dp.switch.update_data(data=program_data)
|
|
201
|
+
else:
|
|
202
|
+
program_dp = self._create_program_dp(data=program_data)
|
|
203
|
+
new_programs.append(program_dp.button)
|
|
204
|
+
new_programs.append(program_dp.switch)
|
|
205
|
+
|
|
206
|
+
if new_programs:
|
|
207
|
+
self._central.emit_backend_system_callback(
|
|
208
|
+
system_event=BackendSystemEvent.HUB_REFRESHED,
|
|
209
|
+
new_data_points=_get_new_hub_data_points(data_points=new_programs),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
async def _update_sysvar_data_points(self) -> None:
|
|
213
|
+
"""Retrieve all variable data and update hmvariable values."""
|
|
214
|
+
if not (client := self._central.primary_client):
|
|
215
|
+
return
|
|
216
|
+
if (variables := await client.get_all_system_variables(markers=self._config.sysvar_markers)) is None:
|
|
217
|
+
_LOGGER.debug("UPDATE_SYSVAR_DATA_POINTS: Unable to retrieve sysvars for %s", self._central.name)
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
_LOGGER.debug(
|
|
221
|
+
"UPDATE_SYSVAR_DATA_POINTS: %i sysvars received for %s",
|
|
222
|
+
len(variables),
|
|
223
|
+
self._central.name,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# remove some variables in case of CCU backend
|
|
227
|
+
# - OldValue(s) are for internal calculations
|
|
228
|
+
if self._central.model is Backend.CCU:
|
|
229
|
+
variables = _clean_variables(variables=variables)
|
|
230
|
+
|
|
231
|
+
if missing_variable_ids := self._identify_missing_variable_ids(variables=variables):
|
|
232
|
+
self._remove_sysvar_data_point(del_data_point_ids=missing_variable_ids)
|
|
233
|
+
|
|
234
|
+
new_sysvars: list[GenericSysvarDataPoint] = []
|
|
235
|
+
|
|
236
|
+
for sysvar in variables:
|
|
237
|
+
if dp := self._central.get_sysvar_data_point(vid=sysvar.vid):
|
|
238
|
+
dp.write_value(value=sysvar.value, write_at=datetime.now())
|
|
239
|
+
else:
|
|
240
|
+
new_sysvars.append(self._create_system_variable(data=sysvar))
|
|
241
|
+
|
|
242
|
+
if new_sysvars:
|
|
243
|
+
self._central.emit_backend_system_callback(
|
|
244
|
+
system_event=BackendSystemEvent.HUB_REFRESHED,
|
|
245
|
+
new_data_points=_get_new_hub_data_points(data_points=new_sysvars),
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def _create_program_dp(self, *, data: ProgramData) -> ProgramDpType:
|
|
249
|
+
"""Create program as data_point."""
|
|
250
|
+
program_dp = ProgramDpType(
|
|
251
|
+
pid=data.pid,
|
|
252
|
+
button=ProgramDpButton(central=self._central, data=data),
|
|
253
|
+
switch=ProgramDpSwitch(central=self._central, data=data),
|
|
254
|
+
)
|
|
255
|
+
self._central.add_program_data_point(program_dp=program_dp)
|
|
256
|
+
return program_dp
|
|
257
|
+
|
|
258
|
+
def _create_system_variable(self, *, data: SystemVariableData) -> GenericSysvarDataPoint:
|
|
259
|
+
"""Create system variable as data_point."""
|
|
260
|
+
sysvar_dp = self._create_sysvar_data_point(data=data)
|
|
261
|
+
self._central.add_sysvar_data_point(sysvar_data_point=sysvar_dp)
|
|
262
|
+
return sysvar_dp
|
|
263
|
+
|
|
264
|
+
def _create_sysvar_data_point(self, *, data: SystemVariableData) -> GenericSysvarDataPoint:
|
|
265
|
+
"""Create sysvar data_point."""
|
|
266
|
+
data_type = data.data_type
|
|
267
|
+
extended_sysvar = data.extended_sysvar
|
|
268
|
+
if data_type:
|
|
269
|
+
if data_type in (SysvarType.ALARM, SysvarType.LOGIC):
|
|
270
|
+
if extended_sysvar:
|
|
271
|
+
return SysvarDpSwitch(central=self._central, data=data)
|
|
272
|
+
return SysvarDpBinarySensor(central=self._central, data=data)
|
|
273
|
+
if data_type == SysvarType.LIST and extended_sysvar:
|
|
274
|
+
return SysvarDpSelect(central=self._central, data=data)
|
|
275
|
+
if data_type in (SysvarType.FLOAT, SysvarType.INTEGER) and extended_sysvar:
|
|
276
|
+
return SysvarDpNumber(central=self._central, data=data)
|
|
277
|
+
if data_type == SysvarType.STRING and extended_sysvar:
|
|
278
|
+
return SysvarDpText(central=self._central, data=data)
|
|
279
|
+
|
|
280
|
+
return SysvarDpSensor(central=self._central, data=data)
|
|
281
|
+
|
|
282
|
+
def _remove_program_data_point(self, *, ids: set[str]) -> None:
|
|
283
|
+
"""Remove sysvar data_point from hub."""
|
|
284
|
+
for pid in ids:
|
|
285
|
+
self._central.remove_program_button(pid=pid)
|
|
286
|
+
|
|
287
|
+
def _remove_sysvar_data_point(self, *, del_data_point_ids: set[str]) -> None:
|
|
288
|
+
"""Remove sysvar data_point from hub."""
|
|
289
|
+
for vid in del_data_point_ids:
|
|
290
|
+
self._central.remove_sysvar_data_point(vid=vid)
|
|
291
|
+
|
|
292
|
+
def _identify_missing_program_ids(self, *, programs: tuple[ProgramData, ...]) -> set[str]:
|
|
293
|
+
"""Identify missing programs."""
|
|
294
|
+
return {dp.pid for dp in self._central.program_data_points if dp.pid not in [x.pid for x in programs]}
|
|
295
|
+
|
|
296
|
+
def _identify_missing_variable_ids(self, *, variables: tuple[SystemVariableData, ...]) -> set[str]:
|
|
297
|
+
"""Identify missing variables."""
|
|
298
|
+
variable_ids: dict[str, bool] = {x.vid: x.extended_sysvar for x in variables}
|
|
299
|
+
missing_variable_ids: list[str] = []
|
|
300
|
+
for dp in self._central.sysvar_data_points:
|
|
301
|
+
if dp.data_type == SysvarType.STRING:
|
|
302
|
+
continue
|
|
303
|
+
if (vid := dp.vid) is not None and (
|
|
304
|
+
vid not in variable_ids or (dp.is_extended is not variable_ids.get(vid))
|
|
305
|
+
):
|
|
306
|
+
missing_variable_ids.append(vid)
|
|
307
|
+
return set(missing_variable_ids)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def _is_excluded(*, variable: str, excludes: list[str]) -> bool:
|
|
311
|
+
"""Check if variable is excluded by exclude_list."""
|
|
312
|
+
return any(marker in variable for marker in excludes)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _clean_variables(*, variables: tuple[SystemVariableData, ...]) -> tuple[SystemVariableData, ...]:
|
|
316
|
+
"""Clean variables by removing excluded."""
|
|
317
|
+
return tuple(sv for sv in variables if not _is_excluded(variable=sv.legacy_name, excludes=_EXCLUDED))
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _get_new_hub_data_points(
|
|
321
|
+
*,
|
|
322
|
+
data_points: Collection[GenericHubDataPoint],
|
|
323
|
+
) -> Mapping[DataPointCategory, AbstractSet[GenericHubDataPoint]]:
|
|
324
|
+
"""Return data points as category dict."""
|
|
325
|
+
hub_data_points: dict[DataPointCategory, set[GenericHubDataPoint]] = {}
|
|
326
|
+
for hub_category in HUB_CATEGORIES:
|
|
327
|
+
hub_data_points[hub_category] = set()
|
|
328
|
+
|
|
329
|
+
for dp in data_points:
|
|
330
|
+
if dp.is_registered is False:
|
|
331
|
+
hub_data_points[dp.category].add(dp)
|
|
332
|
+
|
|
333
|
+
return hub_data_points
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for hub data points implemented using the binary_sensor category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from aiohomematic.const import DataPointCategory
|
|
8
|
+
from aiohomematic.model.hub.data_point import GenericSysvarDataPoint
|
|
9
|
+
from aiohomematic.property_decorators import state_property
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SysvarDpBinarySensor(GenericSysvarDataPoint):
|
|
13
|
+
"""Implementation of a sysvar binary_sensor."""
|
|
14
|
+
|
|
15
|
+
__slots__ = ()
|
|
16
|
+
|
|
17
|
+
_category = DataPointCategory.HUB_BINARY_SENSOR
|
|
18
|
+
|
|
19
|
+
@state_property
|
|
20
|
+
def value(self) -> bool | None:
|
|
21
|
+
"""Return the value of the data_point."""
|
|
22
|
+
if self._value is not None:
|
|
23
|
+
return bool(self._value)
|
|
24
|
+
return None
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2025
|
|
3
|
+
"""Module for hub data points implemented using the button 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
|
|
10
|
+
from aiohomematic.property_decorators import state_property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProgramDpButton(GenericProgramDataPoint):
|
|
14
|
+
"""Class for a Homematic program button."""
|
|
15
|
+
|
|
16
|
+
__slots__ = ()
|
|
17
|
+
|
|
18
|
+
_category = DataPointCategory.HUB_BUTTON
|
|
19
|
+
|
|
20
|
+
@state_property
|
|
21
|
+
def available(self) -> bool:
|
|
22
|
+
"""Return the availability of the device."""
|
|
23
|
+
return self._is_active and self._central.available
|
|
24
|
+
|
|
25
|
+
@inspector
|
|
26
|
+
async def press(self) -> None:
|
|
27
|
+
"""Handle the button press."""
|
|
28
|
+
await self.central.execute_program(pid=self.pid)
|