aiohomematic 2025.8.7__tar.gz → 2025.8.8__tar.gz
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-2025.8.7 → aiohomematic-2025.8.8}/PKG-INFO +1 -1
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/caches/dynamic.py +8 -12
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/const.py +1 -1
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/calculated/__init__.py +3 -3
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/data_point.py +1 -3
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/device.py +28 -59
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/__init__.py +5 -9
- aiohomematic-2025.8.8/aiohomematic/rega_scripts/fetch_all_device_data.fn +92 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic.egg-info/PKG-INFO +1 -1
- aiohomematic-2025.8.7/aiohomematic/rega_scripts/fetch_all_device_data.fn +0 -75
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/LICENSE +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/README.md +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/async_support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/caches/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/caches/persistent.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/caches/visibility.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/central/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/central/decorators.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/central/xml_rpc_server.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/client/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/client/json_rpc.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/client/xml_rpc.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/context.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/converter.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/decorators.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/exceptions.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/hmcli.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/calculated/climate.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/calculated/data_point.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/calculated/operating_voltage_level.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/calculated/support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/climate.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/const.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/cover.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/data_point.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/definition.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/light.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/lock.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/siren.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/switch.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/custom/valve.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/decorators.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/event.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/action.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/binary_sensor.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/button.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/data_point.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/number.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/select.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/sensor.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/switch.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/generic/text.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/binary_sensor.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/button.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/data_point.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/number.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/select.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/sensor.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/switch.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/hub/text.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/model/update.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/py.typed +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/get_program_descriptions.fn +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/get_serial.fn +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/get_system_variable_descriptions.fn +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/set_program_state.fn +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/set_system_variable.fn +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/validator.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic.egg-info/SOURCES.txt +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic.egg-info/dependency_links.txt +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic.egg-info/requires.txt +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic.egg-info/top_level.txt +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic_support/__init__.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic_support/client_local.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/pyproject.toml +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/setup.cfg +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_action.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_binary_sensor.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_button.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_calculated_support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_central.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_central_pydevccu.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_climate.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_cover.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_decorator.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_device.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_entity.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_event.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_json_rpc.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_light.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_lock.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_number.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_select.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_sensor.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_siren.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_support.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_switch.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_text.py +0 -0
- {aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/tests/test_valve.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiohomematic
|
|
3
|
-
Version: 2025.8.
|
|
3
|
+
Version: 2025.8.8
|
|
4
4
|
Summary: Homematic interface for Home Assistant running on Python 3.
|
|
5
5
|
Home-page: https://github.com/sukramj/aiohomematic
|
|
6
6
|
Author-email: SukramJ <sukramj@icloud.com>, Daniel Perna <danielperna84@gmail.com>
|
|
@@ -25,11 +25,13 @@ from collections.abc import Mapping
|
|
|
25
25
|
from datetime import datetime
|
|
26
26
|
import logging
|
|
27
27
|
from typing import Any, Final, cast
|
|
28
|
+
from urllib.parse import unquote
|
|
28
29
|
|
|
29
30
|
from aiohomematic import central as hmcu
|
|
30
31
|
from aiohomematic.const import (
|
|
31
32
|
DP_KEY_VALUE,
|
|
32
33
|
INIT_DATETIME,
|
|
34
|
+
ISO_8859_1,
|
|
33
35
|
LAST_COMMAND_SEND_STORE_TIMEOUT,
|
|
34
36
|
MAX_CACHE_AGE,
|
|
35
37
|
NO_CACHE_ENTRY,
|
|
@@ -272,7 +274,6 @@ class CentralDataCache:
|
|
|
272
274
|
|
|
273
275
|
__slots__ = (
|
|
274
276
|
"_central",
|
|
275
|
-
"_escaped_channel_cache",
|
|
276
277
|
"_refreshed_at",
|
|
277
278
|
"_value_cache",
|
|
278
279
|
)
|
|
@@ -283,7 +284,6 @@ class CentralDataCache:
|
|
|
283
284
|
# { key, value}
|
|
284
285
|
self._value_cache: Final[dict[Interface, Mapping[str, Any]]] = {}
|
|
285
286
|
self._refreshed_at: Final[dict[Interface, datetime]] = {}
|
|
286
|
-
self._escaped_channel_cache: Final[dict[str, str]] = {}
|
|
287
287
|
|
|
288
288
|
async def load(self, direct_call: bool = False, interface: Interface | None = None) -> None:
|
|
289
289
|
"""Fetch data from backend."""
|
|
@@ -310,7 +310,10 @@ class CentralDataCache:
|
|
|
310
310
|
|
|
311
311
|
def add_data(self, interface: Interface, all_device_data: Mapping[str, Any]) -> None:
|
|
312
312
|
"""Add data to cache."""
|
|
313
|
-
self._value_cache[interface] =
|
|
313
|
+
self._value_cache[interface] = {
|
|
314
|
+
unquote(string=k, encoding=ISO_8859_1): unquote(string=v, encoding=ISO_8859_1) if isinstance(v, str) else v
|
|
315
|
+
for k, v in all_device_data.items()
|
|
316
|
+
}
|
|
314
317
|
self._refreshed_at[interface] = datetime.now()
|
|
315
318
|
|
|
316
319
|
def get_data(
|
|
@@ -320,14 +323,8 @@ class CentralDataCache:
|
|
|
320
323
|
parameter: str,
|
|
321
324
|
) -> Any:
|
|
322
325
|
"""Get data from cache."""
|
|
323
|
-
if not self._is_empty(interface=interface):
|
|
324
|
-
|
|
325
|
-
if (escaped := self._escaped_channel_cache.get(channel_address)) is None:
|
|
326
|
-
escaped = channel_address.replace(":", "%3A") if ":" in channel_address else channel_address
|
|
327
|
-
self._escaped_channel_cache[channel_address] = escaped
|
|
328
|
-
key = f"{interface}.{escaped}.{parameter}"
|
|
329
|
-
if (iface_cache := self._value_cache.get(interface)) is not None:
|
|
330
|
-
return iface_cache.get(key, NO_CACHE_ENTRY)
|
|
326
|
+
if not self._is_empty(interface=interface) and (iface_cache := self._value_cache.get(interface)) is not None:
|
|
327
|
+
return iface_cache.get(f"{interface}.{channel_address}.{parameter}", NO_CACHE_ENTRY)
|
|
331
328
|
return NO_CACHE_ENTRY
|
|
332
329
|
|
|
333
330
|
def clear(self, interface: Interface | None = None) -> None:
|
|
@@ -335,7 +332,6 @@ class CentralDataCache:
|
|
|
335
332
|
if interface:
|
|
336
333
|
self._value_cache[interface] = {}
|
|
337
334
|
self._refreshed_at[interface] = INIT_DATETIME
|
|
338
|
-
self._escaped_channel_cache.clear()
|
|
339
335
|
else:
|
|
340
336
|
for _interface in self._central.interfaces:
|
|
341
337
|
self.clear(interface=_interface)
|
|
@@ -60,6 +60,6 @@ _LOGGER: Final = logging.getLogger(__name__)
|
|
|
60
60
|
@inspector()
|
|
61
61
|
def create_calculated_data_points(channel: hmd.Channel) -> None:
|
|
62
62
|
"""Decides which data point category should be used, and creates the required data points."""
|
|
63
|
-
for
|
|
64
|
-
if
|
|
65
|
-
channel.add_data_point(data_point=
|
|
63
|
+
for dp in _CALCULATED_DATA_POINTS:
|
|
64
|
+
if dp.is_relevant_for_model(channel=channel):
|
|
65
|
+
channel.add_data_point(data_point=dp(channel=channel))
|
|
@@ -861,9 +861,7 @@ class BaseParameterDataPoint[
|
|
|
861
861
|
|
|
862
862
|
self.write_value(
|
|
863
863
|
value=await self._device.value_cache.get_value(
|
|
864
|
-
|
|
865
|
-
paramset_key=self._paramset_key,
|
|
866
|
-
parameter=self._parameter,
|
|
864
|
+
dpk=self.dpk,
|
|
867
865
|
call_source=call_source,
|
|
868
866
|
direct_call=direct_call,
|
|
869
867
|
),
|
|
@@ -1146,121 +1146,90 @@ class _ValueCache:
|
|
|
1146
1146
|
|
|
1147
1147
|
async def get_value(
|
|
1148
1148
|
self,
|
|
1149
|
-
|
|
1150
|
-
paramset_key: ParamsetKey,
|
|
1151
|
-
parameter: str,
|
|
1149
|
+
dpk: DataPointKey,
|
|
1152
1150
|
call_source: CallSource,
|
|
1153
1151
|
direct_call: bool = False,
|
|
1154
1152
|
) -> Any:
|
|
1155
1153
|
"""Load data."""
|
|
1154
|
+
|
|
1156
1155
|
async with self._sema_get_or_load_value:
|
|
1157
|
-
if (
|
|
1158
|
-
direct_call is False
|
|
1159
|
-
and (
|
|
1160
|
-
cached_value := self._get_value_from_cache(
|
|
1161
|
-
channel_address=channel_address,
|
|
1162
|
-
paramset_key=paramset_key,
|
|
1163
|
-
parameter=parameter,
|
|
1164
|
-
)
|
|
1165
|
-
)
|
|
1166
|
-
!= NO_CACHE_ENTRY
|
|
1167
|
-
):
|
|
1156
|
+
if direct_call is False and (cached_value := self._get_value_from_cache(dpk=dpk)) != NO_CACHE_ENTRY:
|
|
1168
1157
|
return NO_CACHE_ENTRY if cached_value == self._NO_VALUE_CACHE_ENTRY else cached_value
|
|
1169
1158
|
|
|
1170
|
-
value_dict: dict[str, Any] = {parameter: self._NO_VALUE_CACHE_ENTRY}
|
|
1159
|
+
value_dict: dict[str, Any] = {dpk.parameter: self._NO_VALUE_CACHE_ENTRY}
|
|
1171
1160
|
try:
|
|
1172
|
-
value_dict = await self._get_values_for_cache(
|
|
1173
|
-
channel_address=channel_address,
|
|
1174
|
-
paramset_key=paramset_key,
|
|
1175
|
-
parameter=parameter,
|
|
1176
|
-
)
|
|
1161
|
+
value_dict = await self._get_values_for_cache(dpk=dpk)
|
|
1177
1162
|
except BaseHomematicException as bhexc:
|
|
1178
1163
|
_LOGGER.debug(
|
|
1179
1164
|
"GET_OR_LOAD_VALUE: Failed to get data for %s, %s, %s, %s: %s",
|
|
1180
1165
|
self._device.model,
|
|
1181
|
-
channel_address,
|
|
1182
|
-
parameter,
|
|
1166
|
+
dpk.channel_address,
|
|
1167
|
+
dpk.parameter,
|
|
1183
1168
|
call_source,
|
|
1184
1169
|
extract_exc_args(exc=bhexc),
|
|
1185
1170
|
)
|
|
1186
1171
|
for d_parameter, d_value in value_dict.items():
|
|
1187
1172
|
self._add_entry_to_device_cache(
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1173
|
+
dpk=DataPointKey(
|
|
1174
|
+
interface_id=dpk.interface_id,
|
|
1175
|
+
channel_address=dpk.channel_address,
|
|
1176
|
+
paramset_key=dpk.paramset_key,
|
|
1177
|
+
parameter=d_parameter,
|
|
1178
|
+
),
|
|
1191
1179
|
value=d_value,
|
|
1192
1180
|
)
|
|
1193
1181
|
return (
|
|
1194
1182
|
NO_CACHE_ENTRY
|
|
1195
|
-
if (value := value_dict.get(parameter)) and value == self._NO_VALUE_CACHE_ENTRY
|
|
1183
|
+
if (value := value_dict.get(dpk.parameter)) and value == self._NO_VALUE_CACHE_ENTRY
|
|
1196
1184
|
else value
|
|
1197
1185
|
)
|
|
1198
1186
|
|
|
1199
|
-
async def _get_values_for_cache(
|
|
1200
|
-
self, channel_address: str, paramset_key: ParamsetKey, parameter: str
|
|
1201
|
-
) -> dict[str, Any]:
|
|
1187
|
+
async def _get_values_for_cache(self, dpk: DataPointKey) -> dict[str, Any]:
|
|
1202
1188
|
"""Return a value from CCU to store in cache."""
|
|
1203
1189
|
if not self._device.available:
|
|
1204
1190
|
_LOGGER.debug(
|
|
1205
1191
|
"GET_VALUES_FOR_CACHE failed: device %s (%s) is not available", self._device.name, self._device.address
|
|
1206
1192
|
)
|
|
1207
1193
|
return {}
|
|
1208
|
-
if paramset_key == ParamsetKey.VALUES:
|
|
1194
|
+
if dpk.paramset_key == ParamsetKey.VALUES:
|
|
1209
1195
|
return {
|
|
1210
|
-
parameter: await self._device.client.get_value(
|
|
1211
|
-
channel_address=channel_address,
|
|
1212
|
-
paramset_key=paramset_key,
|
|
1213
|
-
parameter=parameter,
|
|
1196
|
+
dpk.parameter: await self._device.client.get_value(
|
|
1197
|
+
channel_address=dpk.channel_address,
|
|
1198
|
+
paramset_key=dpk.paramset_key,
|
|
1199
|
+
parameter=dpk.parameter,
|
|
1214
1200
|
call_source=CallSource.HM_INIT,
|
|
1215
1201
|
)
|
|
1216
1202
|
}
|
|
1217
1203
|
return await self._device.client.get_paramset(
|
|
1218
|
-
address=channel_address, paramset_key=paramset_key, call_source=CallSource.HM_INIT
|
|
1204
|
+
address=dpk.channel_address, paramset_key=dpk.paramset_key, call_source=CallSource.HM_INIT
|
|
1219
1205
|
)
|
|
1220
1206
|
|
|
1221
|
-
def _add_entry_to_device_cache(
|
|
1222
|
-
self, channel_address: str, paramset_key: ParamsetKey, parameter: str, value: Any
|
|
1223
|
-
) -> None:
|
|
1207
|
+
def _add_entry_to_device_cache(self, dpk: DataPointKey, value: Any) -> None:
|
|
1224
1208
|
"""Add value to cache."""
|
|
1225
|
-
key = DataPointKey(
|
|
1226
|
-
interface_id=self._device.interface_id,
|
|
1227
|
-
channel_address=channel_address,
|
|
1228
|
-
paramset_key=paramset_key,
|
|
1229
|
-
parameter=parameter,
|
|
1230
|
-
)
|
|
1231
1209
|
# write value to cache even if an exception has occurred
|
|
1232
1210
|
# to avoid repetitive calls to CCU within max_age
|
|
1233
|
-
self._device_cache[
|
|
1211
|
+
self._device_cache[dpk] = CacheEntry(value=value, refresh_at=datetime.now())
|
|
1234
1212
|
|
|
1235
1213
|
def _get_value_from_cache(
|
|
1236
1214
|
self,
|
|
1237
|
-
|
|
1238
|
-
paramset_key: ParamsetKey,
|
|
1239
|
-
parameter: str,
|
|
1215
|
+
dpk: DataPointKey,
|
|
1240
1216
|
) -> Any:
|
|
1241
1217
|
"""Load data from caches."""
|
|
1242
1218
|
# Try to get data from central cache
|
|
1243
1219
|
if (
|
|
1244
|
-
paramset_key == ParamsetKey.VALUES
|
|
1220
|
+
dpk.paramset_key == ParamsetKey.VALUES
|
|
1245
1221
|
and (
|
|
1246
1222
|
global_value := self._device.central.data_cache.get_data(
|
|
1247
1223
|
interface=self._device.interface,
|
|
1248
|
-
channel_address=channel_address,
|
|
1249
|
-
parameter=parameter,
|
|
1224
|
+
channel_address=dpk.channel_address,
|
|
1225
|
+
parameter=dpk.parameter,
|
|
1250
1226
|
)
|
|
1251
1227
|
)
|
|
1252
1228
|
!= NO_CACHE_ENTRY
|
|
1253
1229
|
):
|
|
1254
1230
|
return global_value
|
|
1255
1231
|
|
|
1256
|
-
|
|
1257
|
-
key = DataPointKey(
|
|
1258
|
-
interface_id=self._device.interface_id,
|
|
1259
|
-
channel_address=channel_address,
|
|
1260
|
-
paramset_key=paramset_key,
|
|
1261
|
-
parameter=parameter,
|
|
1262
|
-
)
|
|
1263
|
-
if (cache_entry := self._device_cache.get(key, CacheEntry.empty())) and cache_entry.is_valid:
|
|
1232
|
+
if (cache_entry := self._device_cache.get(dpk, CacheEntry.empty())) and cache_entry.is_valid:
|
|
1264
1233
|
return cache_entry.value
|
|
1265
1234
|
return NO_CACHE_ENTRY
|
|
1266
1235
|
|
|
@@ -289,21 +289,17 @@ class Hub:
|
|
|
289
289
|
|
|
290
290
|
def _identify_missing_program_ids(self, programs: tuple[ProgramData, ...]) -> set[str]:
|
|
291
291
|
"""Identify missing programs."""
|
|
292
|
-
return {
|
|
293
|
-
program_dp.pid
|
|
294
|
-
for program_dp in self._central.program_data_points
|
|
295
|
-
if program_dp.pid not in [x.pid for x in programs]
|
|
296
|
-
}
|
|
292
|
+
return {dp.pid for dp in self._central.program_data_points if dp.pid not in [x.pid for x in programs]}
|
|
297
293
|
|
|
298
294
|
def _identify_missing_variable_ids(self, variables: tuple[SystemVariableData, ...]) -> set[str]:
|
|
299
295
|
"""Identify missing variables."""
|
|
300
296
|
variable_ids: dict[str, bool] = {x.vid: x.extended_sysvar for x in variables}
|
|
301
297
|
missing_variable_ids: list[str] = []
|
|
302
|
-
for
|
|
303
|
-
if
|
|
298
|
+
for dp in self._central.sysvar_data_points:
|
|
299
|
+
if dp.data_type == SysvarType.STRING:
|
|
304
300
|
continue
|
|
305
|
-
if (vid :=
|
|
306
|
-
vid not in variable_ids or (
|
|
301
|
+
if (vid := dp.vid) is not None and (
|
|
302
|
+
vid not in variable_ids or (dp.is_extended is not variable_ids.get(vid))
|
|
307
303
|
):
|
|
308
304
|
missing_variable_ids.append(vid)
|
|
309
305
|
return set(missing_variable_ids)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
!# fetch_all_device_data.fn v2.2
|
|
2
|
+
!# This script fetches all device data required to initialize the entities without affecting the duty cycle.
|
|
3
|
+
!#
|
|
4
|
+
!# Original script: https://github.com/ioBroker/ioBroker.hm-rega/blob/master/regascripts/datapoints.fn
|
|
5
|
+
!# datapoints.fn 1.9
|
|
6
|
+
!# 3'2013-9'2014 hobbyquaker https://github.com/hobbyquaker
|
|
7
|
+
!#
|
|
8
|
+
!# Dieses Homematic-Script gibt eine Liste aller Datenpunkte, die zur Laufzeit einen validen Zeitstempel haben, als JSON String aus.
|
|
9
|
+
!#
|
|
10
|
+
!# modified by: SukramJ https://github.com/SukramJ && Baxxy13 https://github.com/Baxxy13
|
|
11
|
+
!# v2.2 - 09/2023
|
|
12
|
+
!#
|
|
13
|
+
!# Das Interface wird durch die Integration an 'sUse_Interface' übergeben.
|
|
14
|
+
!# Nutzbare Interfaces: BidCos-RF, BidCos-Wired, HmIP-RF, VirtualDevices
|
|
15
|
+
!# Zum Testen direkt auf der Homematic-Zentrale muss das Interface wie folgt eingetragen werden: sUse_Interface = "HmIP-RF";
|
|
16
|
+
|
|
17
|
+
string sUse_Interface = "##interface##";
|
|
18
|
+
string sDevId;
|
|
19
|
+
string sChnId;
|
|
20
|
+
string sDPId;
|
|
21
|
+
var vDPValue;
|
|
22
|
+
boolean bDPFirst = true;
|
|
23
|
+
object oInterface = interfaces.Get(sUse_Interface);
|
|
24
|
+
|
|
25
|
+
Write('{');
|
|
26
|
+
if (oInterface) {
|
|
27
|
+
integer iInterface_ID = interfaces.Get(sUse_Interface).ID();
|
|
28
|
+
string sAllDevices = dom.GetObject(ID_DEVICES).EnumUsedIDs();
|
|
29
|
+
foreach (sDevId, sAllDevices) {
|
|
30
|
+
object oDevice = dom.GetObject(sDevId);
|
|
31
|
+
if ((oDevice) && (oDevice.ReadyConfig()) && (oDevice.Interface() == iInterface_ID)) {
|
|
32
|
+
foreach (sChnId, oDevice.Channels()) {
|
|
33
|
+
object oChannel = dom.GetObject(sChnId);
|
|
34
|
+
if (oChannel) {
|
|
35
|
+
var oDPs = oChannel.DPs();
|
|
36
|
+
if (oDPs) {
|
|
37
|
+
foreach(sDPId, oDPs.EnumUsedIDs()) {
|
|
38
|
+
object oDP = dom.GetObject(sDPId);
|
|
39
|
+
if (oDP && oDP.Timestamp()) {
|
|
40
|
+
if (oDP.TypeName() != "VARDP") {
|
|
41
|
+
integer sValueType = oDP.ValueType();
|
|
42
|
+
boolean bHasValue = false;
|
|
43
|
+
string sValue;
|
|
44
|
+
string sID = oDP.Name().UriEncode();
|
|
45
|
+
if (sValueType == 20) {
|
|
46
|
+
sValue = oDP.Value().UriEncode();
|
|
47
|
+
bHasValue = true;
|
|
48
|
+
} else {
|
|
49
|
+
vDPValue = oDP.Value();
|
|
50
|
+
if (sValueType == 2) {
|
|
51
|
+
if (vDPValue) {
|
|
52
|
+
sValue = "true";
|
|
53
|
+
} else {
|
|
54
|
+
sValue = "false";
|
|
55
|
+
}
|
|
56
|
+
bHasValue = true;
|
|
57
|
+
} else {
|
|
58
|
+
if (vDPValue == "") {
|
|
59
|
+
sValue = "0";
|
|
60
|
+
} else {
|
|
61
|
+
sValue = vDPValue;
|
|
62
|
+
}
|
|
63
|
+
bHasValue = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (bHasValue) {
|
|
67
|
+
if (bDPFirst) {
|
|
68
|
+
bDPFirst = false;
|
|
69
|
+
} else {
|
|
70
|
+
WriteLine(',');
|
|
71
|
+
}
|
|
72
|
+
Write('"');
|
|
73
|
+
Write(sID);
|
|
74
|
+
Write('":');
|
|
75
|
+
if (sValueType == 20) {
|
|
76
|
+
Write('"');
|
|
77
|
+
Write(sValue);
|
|
78
|
+
Write('"');
|
|
79
|
+
} else {
|
|
80
|
+
Write(sValue);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
Write('}');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiohomematic
|
|
3
|
-
Version: 2025.8.
|
|
3
|
+
Version: 2025.8.8
|
|
4
4
|
Summary: Homematic interface for Home Assistant running on Python 3.
|
|
5
5
|
Home-page: https://github.com/sukramj/aiohomematic
|
|
6
6
|
Author-email: SukramJ <sukramj@icloud.com>, Daniel Perna <danielperna84@gmail.com>
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
!# fetch_all_device_data.fn v2.2
|
|
2
|
-
!# This script fetches all device data required to initialize the entities without affecting the duty cycle.
|
|
3
|
-
!#
|
|
4
|
-
!# Original script: https://github.com/ioBroker/ioBroker.hm-rega/blob/master/regascripts/datapoints.fn
|
|
5
|
-
!# datapoints.fn 1.9
|
|
6
|
-
!# 3'2013-9'2014 hobbyquaker https://github.com/hobbyquaker
|
|
7
|
-
!#
|
|
8
|
-
!# Dieses Homematic-Script gibt eine Liste aller Datenpunkte, die zur Laufzeit einen validen Zeitstempel haben, als JSON String aus.
|
|
9
|
-
!#
|
|
10
|
-
!# modified by: SukramJ https://github.com/SukramJ && Baxxy13 https://github.com/Baxxy13
|
|
11
|
-
!# v2.2 - 09/2023
|
|
12
|
-
!#
|
|
13
|
-
!# Das Interface wird durch die Integration an 'sUse_Interface' übergeben.
|
|
14
|
-
!# Nutzbare Interfaces: BidCos-RF, BidCos-Wired, HmIP-RF, VirtualDevices
|
|
15
|
-
!# Zum Testen direkt auf der Homematic-Zentrale muss das Interface wie folgt eingetragen werden: sUse_Interface = "HmIP-RF";
|
|
16
|
-
|
|
17
|
-
string sUse_Interface = "##interface##";
|
|
18
|
-
string sDevId;
|
|
19
|
-
string sChnId;
|
|
20
|
-
string sDPId;
|
|
21
|
-
string sDPId;
|
|
22
|
-
var vDPValue;
|
|
23
|
-
boolean bDPFirst = true;
|
|
24
|
-
object oInterface = interfaces.Get(sUse_Interface);
|
|
25
|
-
|
|
26
|
-
Write('{');
|
|
27
|
-
if (oInterface) {
|
|
28
|
-
integer iInterface_ID = interfaces.Get(sUse_Interface).ID();
|
|
29
|
-
string sAllDevices = dom.GetObject(ID_DEVICES).EnumUsedIDs();
|
|
30
|
-
foreach (sDevId, sAllDevices) {
|
|
31
|
-
object oDevice = dom.GetObject(sDevId);
|
|
32
|
-
if ((oDevice) && (oDevice.ReadyConfig()) && (oDevice.Interface() == iInterface_ID)) {
|
|
33
|
-
foreach (sChnId, oDevice.Channels()) {
|
|
34
|
-
object oChannel = dom.GetObject(sChnId);
|
|
35
|
-
foreach(sDPId, oChannel.DPs().EnumUsedIDs()) {
|
|
36
|
-
object oDP = dom.GetObject(sDPId);
|
|
37
|
-
if (oDP && oDP.Timestamp()) {
|
|
38
|
-
if (oDP.TypeName() != "VARDP") {
|
|
39
|
-
if (bDPFirst) {
|
|
40
|
-
bDPFirst = false;
|
|
41
|
-
} else {
|
|
42
|
-
WriteLine(',');
|
|
43
|
-
}
|
|
44
|
-
integer sValueType = oDP.ValueType();
|
|
45
|
-
Write('"');
|
|
46
|
-
WriteURL(oDP.Name());
|
|
47
|
-
Write('":');
|
|
48
|
-
if (sValueType == 20) {
|
|
49
|
-
Write('"');
|
|
50
|
-
WriteURL(oDP.Value());
|
|
51
|
-
Write('"');
|
|
52
|
-
} else {
|
|
53
|
-
vDPValue = oDP.Value();
|
|
54
|
-
if (sValueType == 2) {
|
|
55
|
-
if (vDPValue) {
|
|
56
|
-
Write("true");
|
|
57
|
-
} else {
|
|
58
|
-
Write("false");
|
|
59
|
-
}
|
|
60
|
-
} else {
|
|
61
|
-
if (vDPValue == "") {
|
|
62
|
-
Write("0");
|
|
63
|
-
} else {
|
|
64
|
-
Write(vDPValue);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
Write('}');
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/set_program_state.fn
RENAMED
|
File without changes
|
{aiohomematic-2025.8.7 → aiohomematic-2025.8.8}/aiohomematic/rega_scripts/set_system_variable.fn
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|