aiohomematic 2025.10.0__py3-none-any.whl → 2025.10.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aiohomematic might be problematic. Click here for more details.
- aiohomematic/async_support.py +7 -7
- aiohomematic/caches/dynamic.py +31 -26
- aiohomematic/caches/persistent.py +34 -32
- aiohomematic/caches/visibility.py +19 -7
- aiohomematic/central/__init__.py +90 -74
- aiohomematic/central/decorators.py +2 -2
- aiohomematic/central/xml_rpc_server.py +27 -24
- aiohomematic/client/__init__.py +72 -56
- aiohomematic/client/_rpc_errors.py +3 -3
- aiohomematic/client/json_rpc.py +33 -25
- aiohomematic/client/xml_rpc.py +14 -9
- aiohomematic/const.py +3 -1
- aiohomematic/converter.py +19 -19
- aiohomematic/exceptions.py +2 -1
- aiohomematic/model/__init__.py +4 -3
- aiohomematic/model/calculated/__init__.py +1 -1
- aiohomematic/model/calculated/climate.py +9 -9
- aiohomematic/model/calculated/data_point.py +13 -7
- aiohomematic/model/calculated/operating_voltage_level.py +2 -2
- aiohomematic/model/calculated/support.py +7 -7
- aiohomematic/model/custom/__init__.py +3 -3
- aiohomematic/model/custom/climate.py +57 -34
- aiohomematic/model/custom/cover.py +44 -20
- aiohomematic/model/custom/data_point.py +9 -7
- aiohomematic/model/custom/definition.py +23 -17
- aiohomematic/model/custom/light.py +52 -23
- aiohomematic/model/custom/lock.py +16 -12
- aiohomematic/model/custom/siren.py +6 -3
- aiohomematic/model/custom/switch.py +3 -2
- aiohomematic/model/custom/valve.py +3 -2
- aiohomematic/model/data_point.py +62 -49
- aiohomematic/model/device.py +48 -42
- aiohomematic/model/event.py +6 -5
- aiohomematic/model/generic/__init__.py +6 -4
- aiohomematic/model/generic/action.py +1 -1
- aiohomematic/model/generic/data_point.py +7 -5
- aiohomematic/model/generic/number.py +3 -3
- aiohomematic/model/generic/select.py +1 -1
- aiohomematic/model/generic/sensor.py +2 -2
- aiohomematic/model/generic/switch.py +3 -3
- aiohomematic/model/hub/__init__.py +17 -16
- aiohomematic/model/hub/data_point.py +12 -7
- aiohomematic/model/hub/number.py +3 -3
- aiohomematic/model/hub/select.py +3 -3
- aiohomematic/model/hub/text.py +2 -2
- aiohomematic/model/support.py +8 -7
- aiohomematic/model/update.py +6 -6
- aiohomematic/support.py +44 -38
- aiohomematic/validator.py +6 -6
- {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/METADATA +1 -1
- aiohomematic-2025.10.2.dist-info/RECORD +78 -0
- aiohomematic_support/client_local.py +19 -12
- aiohomematic-2025.10.0.dist-info/RECORD +0 -78
- {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/WHEEL +0 -0
- {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/licenses/LICENSE +0 -0
- {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/top_level.txt +0 -0
aiohomematic/central/__init__.py
CHANGED
|
@@ -105,6 +105,7 @@ from aiohomematic.const import (
|
|
|
105
105
|
DEFAULT_SYSVAR_MARKERS,
|
|
106
106
|
DEFAULT_TLS,
|
|
107
107
|
DEFAULT_UN_IGNORES,
|
|
108
|
+
DEFAULT_USE_GROUP_CHANNEL_FOR_COVER_STATE,
|
|
108
109
|
DEFAULT_VERIFY_TLS,
|
|
109
110
|
DEVICE_FIRMWARE_CHECK_INTERVAL,
|
|
110
111
|
DEVICE_FIRMWARE_DELIVERING_CHECK_INTERVAL,
|
|
@@ -192,7 +193,7 @@ INTERFACE_EVENT_SCHEMA = vol.Schema(
|
|
|
192
193
|
class CentralUnit(LogContextMixin, PayloadMixin):
|
|
193
194
|
"""Central unit that collects everything to handle communication from/to the backend."""
|
|
194
195
|
|
|
195
|
-
def __init__(self, central_config: CentralConfig) -> None:
|
|
196
|
+
def __init__(self, *, central_config: CentralConfig) -> None:
|
|
196
197
|
"""Init the central unit."""
|
|
197
198
|
self._state: CentralUnitState = CentralUnitState.NEW
|
|
198
199
|
self._clients_started: bool = False
|
|
@@ -218,7 +219,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
218
219
|
# {interface_id, client}
|
|
219
220
|
self._clients: Final[dict[str, hmcl.Client]] = {}
|
|
220
221
|
self._data_point_key_event_subscriptions: Final[
|
|
221
|
-
dict[DataPointKey, list[Callable[
|
|
222
|
+
dict[DataPointKey, list[Callable[..., Coroutine[Any, Any, None]]]]
|
|
222
223
|
] = {}
|
|
223
224
|
self._data_point_path_event_subscriptions: Final[dict[str, DataPointKey]] = {}
|
|
224
225
|
self._sysvar_data_point_event_subscriptions: Final[dict[str, Callable]] = {}
|
|
@@ -228,7 +229,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
228
229
|
self._sysvar_data_points: Final[dict[str, GenericSysvarDataPoint]] = {}
|
|
229
230
|
# {sysvar_name, program_button}
|
|
230
231
|
self._program_data_points: Final[dict[str, ProgramDpType]] = {}
|
|
231
|
-
# Signature: (
|
|
232
|
+
# Signature: (system_event, new_data_points, new_channel_events, **kwargs)
|
|
232
233
|
# e.g. DEVICES_CREATED, HUB_REFRESHED
|
|
233
234
|
self._backend_system_callbacks: Final[set[Callable]] = set()
|
|
234
235
|
# Signature: (interface_id, channel_address, parameter, value)
|
|
@@ -420,14 +421,14 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
420
421
|
self._version = max(versions) if versions else None
|
|
421
422
|
return self._version
|
|
422
423
|
|
|
423
|
-
def add_sysvar_data_point(self, sysvar_data_point: GenericSysvarDataPoint) -> None:
|
|
424
|
+
def add_sysvar_data_point(self, *, sysvar_data_point: GenericSysvarDataPoint) -> None:
|
|
424
425
|
"""Add new program button."""
|
|
425
426
|
if (vid := sysvar_data_point.vid) is not None:
|
|
426
427
|
self._sysvar_data_points[vid] = sysvar_data_point
|
|
427
428
|
if sysvar_data_point.state_path not in self._sysvar_data_point_event_subscriptions:
|
|
428
429
|
self._sysvar_data_point_event_subscriptions[sysvar_data_point.state_path] = sysvar_data_point.event
|
|
429
430
|
|
|
430
|
-
def remove_sysvar_data_point(self, vid: str) -> None:
|
|
431
|
+
def remove_sysvar_data_point(self, *, vid: str) -> None:
|
|
431
432
|
"""Remove a sysvar data_point."""
|
|
432
433
|
if (sysvar_dp := self.get_sysvar_data_point(vid=vid)) is not None:
|
|
433
434
|
sysvar_dp.fire_device_removed_callback()
|
|
@@ -435,18 +436,18 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
435
436
|
if sysvar_dp.state_path in self._sysvar_data_point_event_subscriptions:
|
|
436
437
|
del self._sysvar_data_point_event_subscriptions[sysvar_dp.state_path]
|
|
437
438
|
|
|
438
|
-
def add_program_data_point(self, program_dp: ProgramDpType) -> None:
|
|
439
|
+
def add_program_data_point(self, *, program_dp: ProgramDpType) -> None:
|
|
439
440
|
"""Add new program button."""
|
|
440
441
|
self._program_data_points[program_dp.pid] = program_dp
|
|
441
442
|
|
|
442
|
-
def remove_program_button(self, pid: str) -> None:
|
|
443
|
+
def remove_program_button(self, *, pid: str) -> None:
|
|
443
444
|
"""Remove a program button."""
|
|
444
445
|
if (program_dp := self.get_program_data_point(pid=pid)) is not None:
|
|
445
446
|
program_dp.button.fire_device_removed_callback()
|
|
446
447
|
program_dp.switch.fire_device_removed_callback()
|
|
447
448
|
del self._program_data_points[pid]
|
|
448
449
|
|
|
449
|
-
def identify_channel(self, text: str) -> Channel | None:
|
|
450
|
+
def identify_channel(self, *, text: str) -> Channel | None:
|
|
450
451
|
"""Identify channel within a text."""
|
|
451
452
|
for device in self._devices.values():
|
|
452
453
|
if channel := device.identify_channel(text=text):
|
|
@@ -454,7 +455,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
454
455
|
return None
|
|
455
456
|
|
|
456
457
|
async def save_caches(
|
|
457
|
-
self, save_device_descriptions: bool = False, save_paramset_descriptions: bool = False
|
|
458
|
+
self, *, save_device_descriptions: bool = False, save_paramset_descriptions: bool = False
|
|
458
459
|
) -> None:
|
|
459
460
|
"""Save persistent caches."""
|
|
460
461
|
if save_device_descriptions:
|
|
@@ -495,7 +496,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
495
496
|
):
|
|
496
497
|
self._xml_rpc_server = xml_rpc_server
|
|
497
498
|
self._listen_port = xml_rpc_server.listen_port
|
|
498
|
-
self._xml_rpc_server.add_central(self)
|
|
499
|
+
self._xml_rpc_server.add_central(central=self)
|
|
499
500
|
except OSError as oserr:
|
|
500
501
|
self._state = CentralUnitState.STOPPED_BY_ERROR
|
|
501
502
|
raise AioHomematicException(
|
|
@@ -572,7 +573,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
572
573
|
_LOGGER.info("RESTART_CLIENTS: Central %s restarted clients", self.name)
|
|
573
574
|
|
|
574
575
|
@inspector(re_raise=False)
|
|
575
|
-
async def refresh_firmware_data(self, device_address: str | None = None) -> None:
|
|
576
|
+
async def refresh_firmware_data(self, *, device_address: str | None = None) -> None:
|
|
576
577
|
"""Refresh device firmware data."""
|
|
577
578
|
if device_address and (device := self.get_device(address=device_address)) is not None and device.is_updatable:
|
|
578
579
|
await self._refresh_device_descriptions(client=device.client, device_address=device_address)
|
|
@@ -585,7 +586,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
585
586
|
device.refresh_firmware_data()
|
|
586
587
|
|
|
587
588
|
@inspector(re_raise=False)
|
|
588
|
-
async def refresh_firmware_data_by_state(self, device_firmware_states: tuple[DeviceFirmwareState, ...]) -> None:
|
|
589
|
+
async def refresh_firmware_data_by_state(self, *, device_firmware_states: tuple[DeviceFirmwareState, ...]) -> None:
|
|
589
590
|
"""Refresh device firmware data for processing devices."""
|
|
590
591
|
for device in [
|
|
591
592
|
device_in_state
|
|
@@ -594,7 +595,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
594
595
|
]:
|
|
595
596
|
await self.refresh_firmware_data(device_address=device.address)
|
|
596
597
|
|
|
597
|
-
async def _refresh_device_descriptions(self, client: hmcl.Client, device_address: str | None = None) -> None:
|
|
598
|
+
async def _refresh_device_descriptions(self, *, client: hmcl.Client, device_address: str | None = None) -> None:
|
|
598
599
|
"""Refresh device descriptions."""
|
|
599
600
|
device_descriptions: tuple[DeviceDescription, ...] | None = None
|
|
600
601
|
if (
|
|
@@ -687,7 +688,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
687
688
|
_LOGGER.debug("CREATE_CLIENTS successful for %s", self.name)
|
|
688
689
|
return True
|
|
689
690
|
|
|
690
|
-
async def _create_client(self, interface_config: hmcl.InterfaceConfig) -> bool:
|
|
691
|
+
async def _create_client(self, *, interface_config: hmcl.InterfaceConfig) -> bool:
|
|
691
692
|
"""Create a client."""
|
|
692
693
|
try:
|
|
693
694
|
if client := await hmcl.create_client(
|
|
@@ -743,6 +744,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
743
744
|
@loop_check
|
|
744
745
|
def fire_interface_event(
|
|
745
746
|
self,
|
|
747
|
+
*,
|
|
746
748
|
interface_id: str,
|
|
747
749
|
interface_event_type: InterfaceEventType,
|
|
748
750
|
data: dict[str, Any],
|
|
@@ -760,7 +762,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
760
762
|
event_data=cast(dict[EventKey, Any], INTERFACE_EVENT_SCHEMA(event_data)),
|
|
761
763
|
)
|
|
762
764
|
|
|
763
|
-
async def _identify_ip_addr(self, port: int) -> str:
|
|
765
|
+
async def _identify_ip_addr(self, *, port: int) -> str:
|
|
764
766
|
ip_addr: str | None = None
|
|
765
767
|
while ip_addr is None:
|
|
766
768
|
try:
|
|
@@ -810,24 +812,24 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
810
812
|
system_information = client.system_information
|
|
811
813
|
return system_information
|
|
812
814
|
|
|
813
|
-
def get_client(self, interface_id: str) -> hmcl.Client:
|
|
815
|
+
def get_client(self, *, interface_id: str) -> hmcl.Client:
|
|
814
816
|
"""Return a client by interface_id."""
|
|
815
817
|
if not self.has_client(interface_id=interface_id):
|
|
816
818
|
raise AioHomematicException(f"get_client: interface_id {interface_id} does not exist on {self.name}")
|
|
817
819
|
return self._clients[interface_id]
|
|
818
820
|
|
|
819
|
-
def get_channel(self, channel_address: str) -> Channel | None:
|
|
821
|
+
def get_channel(self, *, channel_address: str) -> Channel | None:
|
|
820
822
|
"""Return Homematic channel."""
|
|
821
823
|
if device := self.get_device(address=channel_address):
|
|
822
824
|
return device.get_channel(channel_address=channel_address)
|
|
823
825
|
return None
|
|
824
826
|
|
|
825
|
-
def get_device(self, address: str) -> Device | None:
|
|
827
|
+
def get_device(self, *, address: str) -> Device | None:
|
|
826
828
|
"""Return Homematic device."""
|
|
827
829
|
d_address = get_device_address(address=address)
|
|
828
830
|
return self._devices.get(d_address)
|
|
829
831
|
|
|
830
|
-
def get_data_point_by_custom_id(self, custom_id: str) -> CallbackDataPoint | None:
|
|
832
|
+
def get_data_point_by_custom_id(self, *, custom_id: str) -> CallbackDataPoint | None:
|
|
831
833
|
"""Return Homematic data_point by custom_id."""
|
|
832
834
|
for dp in self.get_data_points(registered=True):
|
|
833
835
|
if dp.custom_id == custom_id:
|
|
@@ -836,6 +838,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
836
838
|
|
|
837
839
|
def get_data_points(
|
|
838
840
|
self,
|
|
841
|
+
*,
|
|
839
842
|
category: DataPointCategory | None = None,
|
|
840
843
|
interface: Interface | None = None,
|
|
841
844
|
exclude_no_create: bool = True,
|
|
@@ -852,7 +855,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
852
855
|
return tuple(all_data_points)
|
|
853
856
|
|
|
854
857
|
def get_readable_generic_data_points(
|
|
855
|
-
self, paramset_key: ParamsetKey | None = None, interface: Interface | None = None
|
|
858
|
+
self, *, paramset_key: ParamsetKey | None = None, interface: Interface | None = None
|
|
856
859
|
) -> tuple[GenericDataPoint, ...]:
|
|
857
860
|
"""Return the readable generic data points."""
|
|
858
861
|
return tuple(
|
|
@@ -874,7 +877,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
874
877
|
return client
|
|
875
878
|
|
|
876
879
|
def get_hub_data_points(
|
|
877
|
-
self, category: DataPointCategory | None = None, registered: bool | None = None
|
|
880
|
+
self, *, category: DataPointCategory | None = None, registered: bool | None = None
|
|
878
881
|
) -> tuple[GenericHubDataPoint, ...]:
|
|
879
882
|
"""Return the program data points."""
|
|
880
883
|
return tuple(
|
|
@@ -883,7 +886,9 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
883
886
|
if (category is None or he.category == category) and (registered is None or he.is_registered == registered)
|
|
884
887
|
)
|
|
885
888
|
|
|
886
|
-
def get_events(
|
|
889
|
+
def get_events(
|
|
890
|
+
self, *, event_type: EventType, registered: bool | None = None
|
|
891
|
+
) -> tuple[tuple[GenericEvent, ...], ...]:
|
|
887
892
|
"""Return all channel event data points."""
|
|
888
893
|
hm_channel_events: list[tuple[GenericEvent, ...]] = []
|
|
889
894
|
for device in self.devices:
|
|
@@ -901,7 +906,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
901
906
|
if cl.get_virtual_remote() is not None
|
|
902
907
|
)
|
|
903
908
|
|
|
904
|
-
def has_client(self, interface_id: str) -> bool:
|
|
909
|
+
def has_client(self, *, interface_id: str) -> bool:
|
|
905
910
|
"""Check if client exists in central."""
|
|
906
911
|
return interface_id in self._clients
|
|
907
912
|
|
|
@@ -929,7 +934,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
929
934
|
await self._data_cache.load()
|
|
930
935
|
return True
|
|
931
936
|
|
|
932
|
-
async def _create_devices(self, new_device_addresses: Mapping[str, set[str]]) -> None:
|
|
937
|
+
async def _create_devices(self, *, new_device_addresses: Mapping[str, set[str]]) -> None:
|
|
933
938
|
"""Trigger creation of the objects that expose the functionality."""
|
|
934
939
|
if not self._clients:
|
|
935
940
|
raise AioHomematicException(
|
|
@@ -985,7 +990,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
985
990
|
new_channel_events=new_channel_events,
|
|
986
991
|
)
|
|
987
992
|
|
|
988
|
-
async def delete_device(self, interface_id: str, device_address: str) -> None:
|
|
993
|
+
async def delete_device(self, *, interface_id: str, device_address: str) -> None:
|
|
989
994
|
"""Delete devices from central."""
|
|
990
995
|
_LOGGER.debug(
|
|
991
996
|
"DELETE_DEVICE: interface_id = %s, device_address = %s",
|
|
@@ -999,7 +1004,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
999
1004
|
await self.delete_devices(interface_id=interface_id, addresses=[device_address, *list(device.channels.keys())])
|
|
1000
1005
|
|
|
1001
1006
|
@callback_backend_system(system_event=BackendSystemEvent.DELETE_DEVICES)
|
|
1002
|
-
async def delete_devices(self, interface_id: str, addresses: tuple[str, ...]) -> None:
|
|
1007
|
+
async def delete_devices(self, *, interface_id: str, addresses: tuple[str, ...]) -> None:
|
|
1003
1008
|
"""Delete devices from central."""
|
|
1004
1009
|
_LOGGER.debug(
|
|
1005
1010
|
"DELETE_DEVICES: interface_id = %s, addresses = %s",
|
|
@@ -1012,12 +1017,12 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1012
1017
|
await self.save_caches()
|
|
1013
1018
|
|
|
1014
1019
|
@callback_backend_system(system_event=BackendSystemEvent.NEW_DEVICES)
|
|
1015
|
-
async def add_new_devices(self, interface_id: str, device_descriptions: tuple[DeviceDescription, ...]) -> None:
|
|
1020
|
+
async def add_new_devices(self, *, interface_id: str, device_descriptions: tuple[DeviceDescription, ...]) -> None:
|
|
1016
1021
|
"""Add new devices to central unit."""
|
|
1017
1022
|
await self._add_new_devices(interface_id=interface_id, device_descriptions=device_descriptions)
|
|
1018
1023
|
|
|
1019
1024
|
@inspector(measure_performance=True)
|
|
1020
|
-
async def _add_new_devices(self, interface_id: str, device_descriptions: tuple[DeviceDescription, ...]) -> None:
|
|
1025
|
+
async def _add_new_devices(self, *, interface_id: str, device_descriptions: tuple[DeviceDescription, ...]) -> None:
|
|
1021
1026
|
"""Add new devices to central unit."""
|
|
1022
1027
|
if not device_descriptions:
|
|
1023
1028
|
_LOGGER.debug(
|
|
@@ -1103,7 +1108,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1103
1108
|
return new_device_addresses
|
|
1104
1109
|
|
|
1105
1110
|
@callback_event
|
|
1106
|
-
async def data_point_event(self, interface_id: str, channel_address: str, parameter: str, value: Any) -> None:
|
|
1111
|
+
async def data_point_event(self, *, interface_id: str, channel_address: str, parameter: str, value: Any) -> None:
|
|
1107
1112
|
"""If a device emits some sort event, we will handle it here."""
|
|
1108
1113
|
_LOGGER_EVENT.debug(
|
|
1109
1114
|
"EVENT: interface_id = %s, channel_address = %s, parameter = %s, value = %s",
|
|
@@ -1142,7 +1147,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1142
1147
|
received_at = datetime.now()
|
|
1143
1148
|
for callback_handler in self._data_point_key_event_subscriptions[dpk]:
|
|
1144
1149
|
if callable(callback_handler):
|
|
1145
|
-
await callback_handler(value, received_at)
|
|
1150
|
+
await callback_handler(value=value, received_at=received_at)
|
|
1146
1151
|
except RuntimeError as rterr: # pragma: no cover
|
|
1147
1152
|
_LOGGER_EVENT.debug(
|
|
1148
1153
|
"EVENT: RuntimeError [%s]. Failed to call callback for: %s, %s, %s",
|
|
@@ -1160,7 +1165,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1160
1165
|
extract_exc_args(exc=exc),
|
|
1161
1166
|
)
|
|
1162
1167
|
|
|
1163
|
-
def data_point_path_event(self, state_path: str, value: str) -> None:
|
|
1168
|
+
def data_point_path_event(self, *, state_path: str, value: str) -> None:
|
|
1164
1169
|
"""If a device emits some sort event, we will handle it here."""
|
|
1165
1170
|
_LOGGER_EVENT.debug(
|
|
1166
1171
|
"DATA_POINT_PATH_EVENT: topic = %s, payload = %s",
|
|
@@ -1170,7 +1175,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1170
1175
|
|
|
1171
1176
|
if (dpk := self._data_point_path_event_subscriptions.get(state_path)) is not None:
|
|
1172
1177
|
self._looper.create_task(
|
|
1173
|
-
self.data_point_event(
|
|
1178
|
+
target=self.data_point_event(
|
|
1174
1179
|
interface_id=dpk.interface_id,
|
|
1175
1180
|
channel_address=dpk.channel_address,
|
|
1176
1181
|
parameter=dpk.parameter,
|
|
@@ -1179,7 +1184,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1179
1184
|
name=f"device-data-point-event-{dpk.interface_id}-{dpk.channel_address}-{dpk.parameter}",
|
|
1180
1185
|
)
|
|
1181
1186
|
|
|
1182
|
-
def sysvar_data_point_path_event(self, state_path: str, value: str) -> None:
|
|
1187
|
+
def sysvar_data_point_path_event(self, *, state_path: str, value: str) -> None:
|
|
1183
1188
|
"""If a device emits some sort event, we will handle it here."""
|
|
1184
1189
|
_LOGGER_EVENT.debug(
|
|
1185
1190
|
"SYSVAR_DATA_POINT_PATH_EVENT: topic = %s, payload = %s",
|
|
@@ -1193,7 +1198,8 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1193
1198
|
if callable(callback_handler):
|
|
1194
1199
|
received_at = datetime.now()
|
|
1195
1200
|
self._looper.create_task(
|
|
1196
|
-
callback_handler(value, received_at),
|
|
1201
|
+
target=callback_handler(value=value, received_at=received_at),
|
|
1202
|
+
name=f"sysvar-data-point-event-{state_path}",
|
|
1197
1203
|
)
|
|
1198
1204
|
except RuntimeError as rterr: # pragma: no cover
|
|
1199
1205
|
_LOGGER_EVENT.debug(
|
|
@@ -1209,13 +1215,13 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1209
1215
|
)
|
|
1210
1216
|
|
|
1211
1217
|
@callback_backend_system(system_event=BackendSystemEvent.LIST_DEVICES)
|
|
1212
|
-
def list_devices(self, interface_id: str) -> list[DeviceDescription]:
|
|
1218
|
+
def list_devices(self, *, interface_id: str) -> list[DeviceDescription]:
|
|
1213
1219
|
"""Return already existing devices to the backend."""
|
|
1214
1220
|
result = self._device_descriptions.get_raw_device_descriptions(interface_id=interface_id)
|
|
1215
1221
|
_LOGGER.debug("LIST_DEVICES: interface_id = %s, channel_count = %i", interface_id, len(result))
|
|
1216
1222
|
return result
|
|
1217
1223
|
|
|
1218
|
-
def add_event_subscription(self, data_point: BaseParameterDataPoint) -> None:
|
|
1224
|
+
def add_event_subscription(self, *, data_point: BaseParameterDataPoint) -> None:
|
|
1219
1225
|
"""Add data_point to central event subscription."""
|
|
1220
1226
|
if isinstance(data_point, GenericDataPoint | GenericEvent) and (
|
|
1221
1227
|
data_point.is_readable or data_point.supports_events
|
|
@@ -1241,7 +1247,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1241
1247
|
for device in self.devices:
|
|
1242
1248
|
await device.remove_central_links()
|
|
1243
1249
|
|
|
1244
|
-
def remove_device(self, device: Device) -> None:
|
|
1250
|
+
def remove_device(self, *, device: Device) -> None:
|
|
1245
1251
|
"""Remove device to central collections."""
|
|
1246
1252
|
if device.address not in self._devices:
|
|
1247
1253
|
_LOGGER.debug(
|
|
@@ -1256,7 +1262,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1256
1262
|
self._device_details.remove_device(device=device)
|
|
1257
1263
|
del self._devices[device.address]
|
|
1258
1264
|
|
|
1259
|
-
def remove_event_subscription(self, data_point: BaseParameterDataPoint) -> None:
|
|
1265
|
+
def remove_event_subscription(self, *, data_point: BaseParameterDataPoint) -> None:
|
|
1260
1266
|
"""Remove event subscription from central collections."""
|
|
1261
1267
|
if isinstance(data_point, GenericDataPoint | GenericEvent) and data_point.supports_events:
|
|
1262
1268
|
if data_point.dpk in self._data_point_key_event_subscriptions:
|
|
@@ -1264,39 +1270,40 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1264
1270
|
if data_point.state_path in self._data_point_path_event_subscriptions:
|
|
1265
1271
|
del self._data_point_path_event_subscriptions[data_point.state_path]
|
|
1266
1272
|
|
|
1267
|
-
def get_last_event_seen_for_interface(self, interface_id: str) -> datetime | None:
|
|
1273
|
+
def get_last_event_seen_for_interface(self, *, interface_id: str) -> datetime | None:
|
|
1268
1274
|
"""Return the last event seen for an interface."""
|
|
1269
1275
|
return self._last_event_seen_for_interface.get(interface_id)
|
|
1270
1276
|
|
|
1271
|
-
def set_last_event_seen_for_interface(self, interface_id: str) -> None:
|
|
1277
|
+
def set_last_event_seen_for_interface(self, *, interface_id: str) -> None:
|
|
1272
1278
|
"""Set the last event seen for an interface."""
|
|
1273
1279
|
self._last_event_seen_for_interface[interface_id] = datetime.now()
|
|
1274
1280
|
|
|
1275
|
-
async def execute_program(self, pid: str) -> bool:
|
|
1281
|
+
async def execute_program(self, *, pid: str) -> bool:
|
|
1276
1282
|
"""Execute a program on the backend."""
|
|
1277
1283
|
if client := self.primary_client:
|
|
1278
1284
|
return await client.execute_program(pid=pid)
|
|
1279
1285
|
return False
|
|
1280
1286
|
|
|
1281
|
-
async def set_program_state(self, pid: str, state: bool) -> bool:
|
|
1287
|
+
async def set_program_state(self, *, pid: str, state: bool) -> bool:
|
|
1282
1288
|
"""Execute a program on the backend."""
|
|
1283
1289
|
if client := self.primary_client:
|
|
1284
1290
|
return await client.set_program_state(pid=pid, state=state)
|
|
1285
1291
|
return False
|
|
1286
1292
|
|
|
1287
1293
|
@inspector(re_raise=False)
|
|
1288
|
-
async def fetch_sysvar_data(self, scheduled: bool) -> None:
|
|
1294
|
+
async def fetch_sysvar_data(self, *, scheduled: bool) -> None:
|
|
1289
1295
|
"""Fetch sysvar data for the hub."""
|
|
1290
1296
|
await self._hub.fetch_sysvar_data(scheduled=scheduled)
|
|
1291
1297
|
|
|
1292
1298
|
@inspector(re_raise=False)
|
|
1293
|
-
async def fetch_program_data(self, scheduled: bool) -> None:
|
|
1299
|
+
async def fetch_program_data(self, *, scheduled: bool) -> None:
|
|
1294
1300
|
"""Fetch program data for the hub."""
|
|
1295
1301
|
await self._hub.fetch_program_data(scheduled=scheduled)
|
|
1296
1302
|
|
|
1297
1303
|
@inspector(measure_performance=True)
|
|
1298
1304
|
async def load_and_refresh_data_point_data(
|
|
1299
1305
|
self,
|
|
1306
|
+
*,
|
|
1300
1307
|
interface: Interface,
|
|
1301
1308
|
paramset_key: ParamsetKey | None = None,
|
|
1302
1309
|
direct_call: bool = False,
|
|
@@ -1308,13 +1315,13 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1308
1315
|
paramset_key=paramset_key, interface=interface, direct_call=direct_call
|
|
1309
1316
|
)
|
|
1310
1317
|
|
|
1311
|
-
async def get_system_variable(self, legacy_name: str) -> Any | None:
|
|
1318
|
+
async def get_system_variable(self, *, legacy_name: str) -> Any | None:
|
|
1312
1319
|
"""Get system variable from the backend."""
|
|
1313
1320
|
if client := self.primary_client:
|
|
1314
|
-
return await client.get_system_variable(legacy_name)
|
|
1321
|
+
return await client.get_system_variable(name=legacy_name)
|
|
1315
1322
|
return None
|
|
1316
1323
|
|
|
1317
|
-
async def set_system_variable(self, legacy_name: str, value: Any) -> None:
|
|
1324
|
+
async def set_system_variable(self, *, legacy_name: str, value: Any) -> None:
|
|
1318
1325
|
"""Set variable value on the backend."""
|
|
1319
1326
|
if dp := self.get_sysvar_data_point(legacy_name=legacy_name):
|
|
1320
1327
|
await dp.send_variable(value=value)
|
|
@@ -1323,6 +1330,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1323
1330
|
|
|
1324
1331
|
def get_parameters(
|
|
1325
1332
|
self,
|
|
1333
|
+
*,
|
|
1326
1334
|
paramset_key: ParamsetKey,
|
|
1327
1335
|
operations: tuple[Operations, ...],
|
|
1328
1336
|
full_format: bool = False,
|
|
@@ -1400,7 +1408,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1400
1408
|
|
|
1401
1409
|
return tuple(parameters)
|
|
1402
1410
|
|
|
1403
|
-
def _get_virtual_remote(self, device_address: str) -> Device | None:
|
|
1411
|
+
def _get_virtual_remote(self, *, device_address: str) -> Device | None:
|
|
1404
1412
|
"""Get the virtual remote for the Client."""
|
|
1405
1413
|
for client in self._clients.values():
|
|
1406
1414
|
virtual_remote = client.get_virtual_remote()
|
|
@@ -1409,7 +1417,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1409
1417
|
return None
|
|
1410
1418
|
|
|
1411
1419
|
def get_generic_data_point(
|
|
1412
|
-
self, channel_address: str, parameter: str, paramset_key: ParamsetKey | None = None
|
|
1420
|
+
self, *, channel_address: str, parameter: str, paramset_key: ParamsetKey | None = None
|
|
1413
1421
|
) -> GenericDataPoint | None:
|
|
1414
1422
|
"""Get data_point by channel_address and parameter."""
|
|
1415
1423
|
if device := self.get_device(address=channel_address):
|
|
@@ -1418,20 +1426,20 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1418
1426
|
)
|
|
1419
1427
|
return None
|
|
1420
1428
|
|
|
1421
|
-
def get_event(self, channel_address: str, parameter: str) -> GenericEvent | None:
|
|
1429
|
+
def get_event(self, *, channel_address: str, parameter: str) -> GenericEvent | None:
|
|
1422
1430
|
"""Return the hm event."""
|
|
1423
1431
|
if device := self.get_device(address=channel_address):
|
|
1424
1432
|
return device.get_generic_event(channel_address=channel_address, parameter=parameter)
|
|
1425
1433
|
return None
|
|
1426
1434
|
|
|
1427
|
-
def get_custom_data_point(self, address: str, channel_no: int) -> CustomDataPoint | None:
|
|
1435
|
+
def get_custom_data_point(self, *, address: str, channel_no: int) -> CustomDataPoint | None:
|
|
1428
1436
|
"""Return the hm custom_data_point."""
|
|
1429
1437
|
if device := self.get_device(address=address):
|
|
1430
1438
|
return device.get_custom_data_point(channel_no=channel_no)
|
|
1431
1439
|
return None
|
|
1432
1440
|
|
|
1433
1441
|
def get_sysvar_data_point(
|
|
1434
|
-
self, vid: str | None = None, legacy_name: str | None = None
|
|
1442
|
+
self, *, vid: str | None = None, legacy_name: str | None = None
|
|
1435
1443
|
) -> GenericSysvarDataPoint | None:
|
|
1436
1444
|
"""Return the sysvar data_point."""
|
|
1437
1445
|
if vid and (sysvar := self._sysvar_data_points.get(vid)):
|
|
@@ -1442,7 +1450,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1442
1450
|
return sysvar
|
|
1443
1451
|
return None
|
|
1444
1452
|
|
|
1445
|
-
def get_program_data_point(self, pid: str | None = None, legacy_name: str | None = None) -> ProgramDpType | None:
|
|
1453
|
+
def get_program_data_point(self, *, pid: str | None = None, legacy_name: str | None = None) -> ProgramDpType | None:
|
|
1446
1454
|
"""Return the program data points."""
|
|
1447
1455
|
if pid and (program := self._program_data_points.get(pid)):
|
|
1448
1456
|
return program
|
|
@@ -1460,7 +1468,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1460
1468
|
"""Return the registered sysvar state path."""
|
|
1461
1469
|
return tuple(self._sysvar_data_point_event_subscriptions)
|
|
1462
1470
|
|
|
1463
|
-
def get_un_ignore_candidates(self, include_master: bool = False) -> list[str]:
|
|
1471
|
+
def get_un_ignore_candidates(self, *, include_master: bool = False) -> list[str]:
|
|
1464
1472
|
"""Return the candidates for un_ignore."""
|
|
1465
1473
|
candidates = sorted(
|
|
1466
1474
|
# 1. request simple parameter list for values parameters
|
|
@@ -1504,20 +1512,20 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1504
1512
|
self._device_details.clear()
|
|
1505
1513
|
self._data_cache.clear()
|
|
1506
1514
|
|
|
1507
|
-
def register_homematic_callback(self, cb: Callable) -> CALLBACK_TYPE:
|
|
1515
|
+
def register_homematic_callback(self, *, cb: Callable) -> CALLBACK_TYPE:
|
|
1508
1516
|
"""Register ha_event callback in central."""
|
|
1509
1517
|
if callable(cb) and cb not in self._homematic_callbacks:
|
|
1510
1518
|
self._homematic_callbacks.add(cb)
|
|
1511
1519
|
return partial(self._unregister_homematic_callback, cb=cb)
|
|
1512
1520
|
return None
|
|
1513
1521
|
|
|
1514
|
-
def _unregister_homematic_callback(self, cb: Callable) -> None:
|
|
1522
|
+
def _unregister_homematic_callback(self, *, cb: Callable) -> None:
|
|
1515
1523
|
"""RUn register ha_event callback in central."""
|
|
1516
1524
|
if cb in self._homematic_callbacks:
|
|
1517
1525
|
self._homematic_callbacks.remove(cb)
|
|
1518
1526
|
|
|
1519
1527
|
@loop_check
|
|
1520
|
-
def fire_homematic_callback(self, event_type: EventType, event_data: dict[EventKey, str]) -> None:
|
|
1528
|
+
def fire_homematic_callback(self, *, event_type: EventType, event_data: dict[EventKey, str]) -> None:
|
|
1521
1529
|
"""
|
|
1522
1530
|
Fire homematic_callback in central.
|
|
1523
1531
|
|
|
@@ -1525,28 +1533,28 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1525
1533
|
"""
|
|
1526
1534
|
for callback_handler in self._homematic_callbacks:
|
|
1527
1535
|
try:
|
|
1528
|
-
callback_handler(event_type, event_data)
|
|
1536
|
+
callback_handler(event_type=event_type, event_data=event_data)
|
|
1529
1537
|
except Exception as exc:
|
|
1530
1538
|
_LOGGER.error(
|
|
1531
1539
|
"FIRE_HOMEMATIC_CALLBACK: Unable to call handler: %s",
|
|
1532
1540
|
extract_exc_args(exc=exc),
|
|
1533
1541
|
)
|
|
1534
1542
|
|
|
1535
|
-
def register_backend_parameter_callback(self, cb: Callable) -> CALLBACK_TYPE:
|
|
1543
|
+
def register_backend_parameter_callback(self, *, cb: Callable) -> CALLBACK_TYPE:
|
|
1536
1544
|
"""Register backend_parameter callback in central."""
|
|
1537
1545
|
if callable(cb) and cb not in self._backend_parameter_callbacks:
|
|
1538
1546
|
self._backend_parameter_callbacks.add(cb)
|
|
1539
1547
|
return partial(self._unregister_backend_parameter_callback, cb=cb)
|
|
1540
1548
|
return None
|
|
1541
1549
|
|
|
1542
|
-
def _unregister_backend_parameter_callback(self, cb: Callable) -> None:
|
|
1550
|
+
def _unregister_backend_parameter_callback(self, *, cb: Callable) -> None:
|
|
1543
1551
|
"""Un register backend_parameter callback in central."""
|
|
1544
1552
|
if cb in self._backend_parameter_callbacks:
|
|
1545
1553
|
self._backend_parameter_callbacks.remove(cb)
|
|
1546
1554
|
|
|
1547
1555
|
@loop_check
|
|
1548
1556
|
def fire_backend_parameter_callback(
|
|
1549
|
-
self, interface_id: str, channel_address: str, parameter: str, value: Any
|
|
1557
|
+
self, *, interface_id: str, channel_address: str, parameter: str, value: Any
|
|
1550
1558
|
) -> None:
|
|
1551
1559
|
"""
|
|
1552
1560
|
Fire backend_parameter callback in central.
|
|
@@ -1555,27 +1563,29 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1555
1563
|
"""
|
|
1556
1564
|
for callback_handler in self._backend_parameter_callbacks:
|
|
1557
1565
|
try:
|
|
1558
|
-
callback_handler(
|
|
1566
|
+
callback_handler(
|
|
1567
|
+
interface_id=interface_id, channel_address=channel_address, parameter=parameter, value=value
|
|
1568
|
+
)
|
|
1559
1569
|
except Exception as exc:
|
|
1560
1570
|
_LOGGER.error(
|
|
1561
1571
|
"FIRE_BACKEND_PARAMETER_CALLBACK: Unable to call handler: %s",
|
|
1562
1572
|
extract_exc_args(exc=exc),
|
|
1563
1573
|
)
|
|
1564
1574
|
|
|
1565
|
-
def register_backend_system_callback(self, cb: Callable) -> CALLBACK_TYPE:
|
|
1575
|
+
def register_backend_system_callback(self, *, cb: Callable) -> CALLBACK_TYPE:
|
|
1566
1576
|
"""Register system_event callback in central."""
|
|
1567
1577
|
if callable(cb) and cb not in self._backend_parameter_callbacks:
|
|
1568
1578
|
self._backend_system_callbacks.add(cb)
|
|
1569
1579
|
return partial(self._unregister_backend_system_callback, cb=cb)
|
|
1570
1580
|
return None
|
|
1571
1581
|
|
|
1572
|
-
def _unregister_backend_system_callback(self, cb: Callable) -> None:
|
|
1582
|
+
def _unregister_backend_system_callback(self, *, cb: Callable) -> None:
|
|
1573
1583
|
"""Un register system_event callback in central."""
|
|
1574
1584
|
if cb in self._backend_system_callbacks:
|
|
1575
1585
|
self._backend_system_callbacks.remove(cb)
|
|
1576
1586
|
|
|
1577
1587
|
@loop_check
|
|
1578
|
-
def fire_backend_system_callback(self, system_event: BackendSystemEvent, **kwargs: Any) -> None:
|
|
1588
|
+
def fire_backend_system_callback(self, *, system_event: BackendSystemEvent, **kwargs: Any) -> None:
|
|
1579
1589
|
"""
|
|
1580
1590
|
Fire system_event callback in central.
|
|
1581
1591
|
|
|
@@ -1583,7 +1593,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1583
1593
|
"""
|
|
1584
1594
|
for callback_handler in self._backend_system_callbacks:
|
|
1585
1595
|
try:
|
|
1586
|
-
callback_handler(system_event, **kwargs)
|
|
1596
|
+
callback_handler(system_event=system_event, **kwargs)
|
|
1587
1597
|
except Exception as exc:
|
|
1588
1598
|
_LOGGER.error(
|
|
1589
1599
|
"FIRE_BACKEND_SYSTEM_CALLBACK: Unable to call handler: %s",
|
|
@@ -1598,7 +1608,7 @@ class CentralUnit(LogContextMixin, PayloadMixin):
|
|
|
1598
1608
|
class _Scheduler(threading.Thread):
|
|
1599
1609
|
"""Periodically check connection to the backend, and load data when required."""
|
|
1600
1610
|
|
|
1601
|
-
def __init__(self, central: CentralUnit) -> None:
|
|
1611
|
+
def __init__(self, *, central: CentralUnit) -> None:
|
|
1602
1612
|
"""Init the connection checker."""
|
|
1603
1613
|
threading.Thread.__init__(self, name=f"ConnectionChecker for {central.name}")
|
|
1604
1614
|
self._central: Final = central
|
|
@@ -1643,7 +1653,7 @@ class _Scheduler(threading.Thread):
|
|
|
1643
1653
|
)
|
|
1644
1654
|
|
|
1645
1655
|
self._central.looper.create_task(
|
|
1646
|
-
self._run_scheduler_tasks(),
|
|
1656
|
+
target=self._run_scheduler_tasks(),
|
|
1647
1657
|
name="run_scheduler_tasks",
|
|
1648
1658
|
)
|
|
1649
1659
|
|
|
@@ -1798,6 +1808,7 @@ class _SchedulerJob:
|
|
|
1798
1808
|
|
|
1799
1809
|
def __init__(
|
|
1800
1810
|
self,
|
|
1811
|
+
*,
|
|
1801
1812
|
task: Callable,
|
|
1802
1813
|
run_interval: int,
|
|
1803
1814
|
next_run: datetime | None = None,
|
|
@@ -1826,6 +1837,7 @@ class CentralConfig:
|
|
|
1826
1837
|
|
|
1827
1838
|
def __init__(
|
|
1828
1839
|
self,
|
|
1840
|
+
*,
|
|
1829
1841
|
central_id: str,
|
|
1830
1842
|
host: str,
|
|
1831
1843
|
interface_configs: AbstractSet[hmcl.InterfaceConfig],
|
|
@@ -1854,6 +1866,7 @@ class CentralConfig:
|
|
|
1854
1866
|
sysvar_markers: tuple[DescriptionMarker | str, ...] = DEFAULT_SYSVAR_MARKERS,
|
|
1855
1867
|
tls: bool = DEFAULT_TLS,
|
|
1856
1868
|
un_ignore_list: frozenset[str] = DEFAULT_UN_IGNORES,
|
|
1869
|
+
use_group_channel_for_cover_state: bool = DEFAULT_USE_GROUP_CHANNEL_FOR_COVER_STATE,
|
|
1857
1870
|
verify_tls: bool = DEFAULT_VERIFY_TLS,
|
|
1858
1871
|
) -> None:
|
|
1859
1872
|
"""Init the client config."""
|
|
@@ -1884,6 +1897,7 @@ class CentralConfig:
|
|
|
1884
1897
|
self.sysvar_markers: Final = sysvar_markers
|
|
1885
1898
|
self.tls: Final = tls
|
|
1886
1899
|
self.un_ignore_list: Final = un_ignore_list
|
|
1900
|
+
self.use_group_channel_for_cover_state: Final = use_group_channel_for_cover_state
|
|
1887
1901
|
self.username: Final = username
|
|
1888
1902
|
self.verify_tls: Final = verify_tls
|
|
1889
1903
|
|
|
@@ -1936,7 +1950,7 @@ class CentralConfig:
|
|
|
1936
1950
|
"""Create the central. Throws BaseHomematicException on validation failure."""
|
|
1937
1951
|
try:
|
|
1938
1952
|
self.check_config()
|
|
1939
|
-
return CentralUnit(self)
|
|
1953
|
+
return CentralUnit(central_config=self)
|
|
1940
1954
|
except BaseHomematicException as bhexc:
|
|
1941
1955
|
raise AioHomematicException(
|
|
1942
1956
|
f"CREATE_CENTRAL: Not able to create a central: : {extract_exc_args(exc=bhexc)}"
|
|
@@ -1950,7 +1964,7 @@ class CentralConfig:
|
|
|
1950
1964
|
url = f"{url}:{self.json_port}"
|
|
1951
1965
|
return f"{url}"
|
|
1952
1966
|
|
|
1953
|
-
def create_json_rpc_client(self, central: CentralUnit) -> JsonRpcAioHttpClient:
|
|
1967
|
+
def create_json_rpc_client(self, *, central: CentralUnit) -> JsonRpcAioHttpClient:
|
|
1954
1968
|
"""Create a json rpc client."""
|
|
1955
1969
|
return JsonRpcAioHttpClient(
|
|
1956
1970
|
username=self.username,
|
|
@@ -1971,7 +1985,7 @@ class CentralConnectionState:
|
|
|
1971
1985
|
self._json_issues: Final[list[str]] = []
|
|
1972
1986
|
self._xml_proxy_issues: Final[list[str]] = []
|
|
1973
1987
|
|
|
1974
|
-
def add_issue(self, issuer: ConnectionProblemIssuer, iid: str) -> bool:
|
|
1988
|
+
def add_issue(self, *, issuer: ConnectionProblemIssuer, iid: str) -> bool:
|
|
1975
1989
|
"""Add issue to collection."""
|
|
1976
1990
|
if isinstance(issuer, JsonRpcAioHttpClient) and iid not in self._json_issues:
|
|
1977
1991
|
self._json_issues.append(iid)
|
|
@@ -1983,7 +1997,7 @@ class CentralConnectionState:
|
|
|
1983
1997
|
return True
|
|
1984
1998
|
return False
|
|
1985
1999
|
|
|
1986
|
-
def remove_issue(self, issuer: ConnectionProblemIssuer, iid: str) -> bool:
|
|
2000
|
+
def remove_issue(self, *, issuer: ConnectionProblemIssuer, iid: str) -> bool:
|
|
1987
2001
|
"""Add issue to collection."""
|
|
1988
2002
|
if isinstance(issuer, JsonRpcAioHttpClient) and iid in self._json_issues:
|
|
1989
2003
|
self._json_issues.remove(iid)
|
|
@@ -1995,7 +2009,7 @@ class CentralConnectionState:
|
|
|
1995
2009
|
return True
|
|
1996
2010
|
return False
|
|
1997
2011
|
|
|
1998
|
-
def has_issue(self, issuer: ConnectionProblemIssuer, iid: str) -> bool:
|
|
2012
|
+
def has_issue(self, *, issuer: ConnectionProblemIssuer, iid: str) -> bool:
|
|
1999
2013
|
"""Add issue to collection."""
|
|
2000
2014
|
if isinstance(issuer, JsonRpcAioHttpClient):
|
|
2001
2015
|
return iid in self._json_issues
|
|
@@ -2004,6 +2018,7 @@ class CentralConnectionState:
|
|
|
2004
2018
|
|
|
2005
2019
|
def handle_exception_log(
|
|
2006
2020
|
self,
|
|
2021
|
+
*,
|
|
2007
2022
|
issuer: ConnectionProblemIssuer,
|
|
2008
2023
|
iid: str,
|
|
2009
2024
|
exception: Exception,
|
|
@@ -2035,6 +2050,7 @@ class CentralConnectionState:
|
|
|
2035
2050
|
|
|
2036
2051
|
|
|
2037
2052
|
def _get_new_data_points(
|
|
2053
|
+
*,
|
|
2038
2054
|
new_devices: set[Device],
|
|
2039
2055
|
) -> Mapping[DataPointCategory, AbstractSet[CallbackDataPoint]]:
|
|
2040
2056
|
"""Return new data points by category."""
|
|
@@ -2050,7 +2066,7 @@ def _get_new_data_points(
|
|
|
2050
2066
|
return data_points_by_category
|
|
2051
2067
|
|
|
2052
2068
|
|
|
2053
|
-
def _get_new_channel_events(new_devices: set[Device]) -> tuple[tuple[GenericEvent, ...], ...]:
|
|
2069
|
+
def _get_new_channel_events(*, new_devices: set[Device]) -> tuple[tuple[GenericEvent, ...], ...]:
|
|
2054
2070
|
"""Return new channel events by category."""
|
|
2055
2071
|
channel_events: list[tuple[GenericEvent, ...]] = []
|
|
2056
2072
|
|