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.

Files changed (56) hide show
  1. aiohomematic/async_support.py +7 -7
  2. aiohomematic/caches/dynamic.py +31 -26
  3. aiohomematic/caches/persistent.py +34 -32
  4. aiohomematic/caches/visibility.py +19 -7
  5. aiohomematic/central/__init__.py +90 -74
  6. aiohomematic/central/decorators.py +2 -2
  7. aiohomematic/central/xml_rpc_server.py +27 -24
  8. aiohomematic/client/__init__.py +72 -56
  9. aiohomematic/client/_rpc_errors.py +3 -3
  10. aiohomematic/client/json_rpc.py +33 -25
  11. aiohomematic/client/xml_rpc.py +14 -9
  12. aiohomematic/const.py +3 -1
  13. aiohomematic/converter.py +19 -19
  14. aiohomematic/exceptions.py +2 -1
  15. aiohomematic/model/__init__.py +4 -3
  16. aiohomematic/model/calculated/__init__.py +1 -1
  17. aiohomematic/model/calculated/climate.py +9 -9
  18. aiohomematic/model/calculated/data_point.py +13 -7
  19. aiohomematic/model/calculated/operating_voltage_level.py +2 -2
  20. aiohomematic/model/calculated/support.py +7 -7
  21. aiohomematic/model/custom/__init__.py +3 -3
  22. aiohomematic/model/custom/climate.py +57 -34
  23. aiohomematic/model/custom/cover.py +44 -20
  24. aiohomematic/model/custom/data_point.py +9 -7
  25. aiohomematic/model/custom/definition.py +23 -17
  26. aiohomematic/model/custom/light.py +52 -23
  27. aiohomematic/model/custom/lock.py +16 -12
  28. aiohomematic/model/custom/siren.py +6 -3
  29. aiohomematic/model/custom/switch.py +3 -2
  30. aiohomematic/model/custom/valve.py +3 -2
  31. aiohomematic/model/data_point.py +62 -49
  32. aiohomematic/model/device.py +48 -42
  33. aiohomematic/model/event.py +6 -5
  34. aiohomematic/model/generic/__init__.py +6 -4
  35. aiohomematic/model/generic/action.py +1 -1
  36. aiohomematic/model/generic/data_point.py +7 -5
  37. aiohomematic/model/generic/number.py +3 -3
  38. aiohomematic/model/generic/select.py +1 -1
  39. aiohomematic/model/generic/sensor.py +2 -2
  40. aiohomematic/model/generic/switch.py +3 -3
  41. aiohomematic/model/hub/__init__.py +17 -16
  42. aiohomematic/model/hub/data_point.py +12 -7
  43. aiohomematic/model/hub/number.py +3 -3
  44. aiohomematic/model/hub/select.py +3 -3
  45. aiohomematic/model/hub/text.py +2 -2
  46. aiohomematic/model/support.py +8 -7
  47. aiohomematic/model/update.py +6 -6
  48. aiohomematic/support.py +44 -38
  49. aiohomematic/validator.py +6 -6
  50. {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/METADATA +1 -1
  51. aiohomematic-2025.10.2.dist-info/RECORD +78 -0
  52. aiohomematic_support/client_local.py +19 -12
  53. aiohomematic-2025.10.0.dist-info/RECORD +0 -78
  54. {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/WHEEL +0 -0
  55. {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/licenses/LICENSE +0 -0
  56. {aiohomematic-2025.10.0.dist-info → aiohomematic-2025.10.2.dist-info}/top_level.txt +0 -0
@@ -52,7 +52,7 @@ def callback_backend_system(system_event: BackendSystemEvent) -> Callable:
52
52
  central = unit.get_central(interface_id=str(args[1]))
53
53
  if central:
54
54
  central.looper.create_task(
55
- _exec_backend_system_callback(*args, **kwargs),
55
+ target=_exec_backend_system_callback(*args, **kwargs),
56
56
  name="wrapper_backend_system_callback",
57
57
  )
58
58
  except Exception as exc:
@@ -123,7 +123,7 @@ def callback_event[**P, R](func: Callable[P, R]) -> Callable:
123
123
  unit = args[0]
124
124
  if isinstance(unit, hmcu.CentralUnit):
125
125
  unit.looper.create_task(
126
- _async_wrap_sync(_exec_event_callback, *args, **kwargs),
126
+ target=_async_wrap_sync(_exec_event_callback, *args, **kwargs),
127
127
  name="wrapper_event_callback",
128
128
  )
129
129
  return
@@ -27,15 +27,15 @@ _LOGGER: Final = logging.getLogger(__name__)
27
27
  class RPCFunctions:
28
28
  """The XML-RPC functions the backend will expect."""
29
29
 
30
- def __init__(self, xml_rpc_server: XmlRpcServer) -> None:
30
+ def __init__(self, *, xml_rpc_server: XmlRpcServer) -> None:
31
31
  """Init RPCFunctions."""
32
32
  self._xml_rpc_server: Final = xml_rpc_server
33
33
 
34
- def event(self, interface_id: str, channel_address: str, parameter: str, value: Any) -> None:
34
+ def event(self, interface_id: str, channel_address: str, parameter: str, value: Any, /) -> None:
35
35
  """If a device emits some sort event, we will handle it here."""
36
- if central := self.get_central(interface_id):
36
+ if central := self.get_central(interface_id=interface_id):
37
37
  central.looper.create_task(
38
- central.data_point_event(
38
+ target=central.data_point_event(
39
39
  interface_id=interface_id,
40
40
  channel_address=channel_address,
41
41
  parameter=parameter,
@@ -45,7 +45,7 @@ class RPCFunctions:
45
45
  )
46
46
 
47
47
  @callback_backend_system(system_event=BackendSystemEvent.ERROR)
48
- def error(self, interface_id: str, error_code: str, msg: str) -> None:
48
+ def error(self, interface_id: str, error_code: str, msg: str, /) -> None:
49
49
  """When some error occurs the backend will send its error message here."""
50
50
  # Structured boundary log (warning level). XML-RPC server received error notification.
51
51
  try:
@@ -66,32 +66,34 @@ class RPCFunctions:
66
66
  str(msg),
67
67
  )
68
68
 
69
- def listDevices(self, interface_id: str) -> list[dict[str, Any]]:
69
+ def listDevices(self, interface_id: str, /) -> list[dict[str, Any]]:
70
70
  """Return already existing devices to the backend."""
71
- if central := self.get_central(interface_id):
71
+ if central := self.get_central(interface_id=interface_id):
72
72
  return [dict(device_description) for device_description in central.list_devices(interface_id=interface_id)]
73
73
  return []
74
74
 
75
- def newDevices(self, interface_id: str, device_descriptions: list[dict[str, Any]]) -> None:
75
+ def newDevices(self, interface_id: str, device_descriptions: list[dict[str, Any]], /) -> None:
76
76
  """Add new devices send from the backend."""
77
77
  central: hmcu.CentralUnit | None
78
- if central := self.get_central(interface_id):
78
+ if central := self.get_central(interface_id=interface_id):
79
79
  central.looper.create_task(
80
- central.add_new_devices(interface_id=interface_id, device_descriptions=tuple(device_descriptions)),
80
+ target=central.add_new_devices(
81
+ interface_id=interface_id, device_descriptions=tuple(device_descriptions)
82
+ ),
81
83
  name=f"newDevices-{interface_id}",
82
84
  )
83
85
 
84
- def deleteDevices(self, interface_id: str, addresses: list[str]) -> None:
86
+ def deleteDevices(self, interface_id: str, addresses: list[str], /) -> None:
85
87
  """Delete devices send from the backend."""
86
88
  central: hmcu.CentralUnit | None
87
- if central := self.get_central(interface_id):
89
+ if central := self.get_central(interface_id=interface_id):
88
90
  central.looper.create_task(
89
- central.delete_devices(interface_id=interface_id, addresses=tuple(addresses)),
91
+ target=central.delete_devices(interface_id=interface_id, addresses=tuple(addresses)),
90
92
  name=f"deleteDevices-{interface_id}",
91
93
  )
92
94
 
93
95
  @callback_backend_system(system_event=BackendSystemEvent.UPDATE_DEVICE)
94
- def updateDevice(self, interface_id: str, address: str, hint: int) -> None:
96
+ def updateDevice(self, interface_id: str, address: str, hint: int, /) -> None:
95
97
  """
96
98
  Update a device.
97
99
 
@@ -106,7 +108,7 @@ class RPCFunctions:
106
108
  )
107
109
 
108
110
  @callback_backend_system(system_event=BackendSystemEvent.REPLACE_DEVICE)
109
- def replaceDevice(self, interface_id: str, old_device_address: str, new_device_address: str) -> None:
111
+ def replaceDevice(self, interface_id: str, old_device_address: str, new_device_address: str, /) -> None:
110
112
  """Replace a device. Probably irrelevant for us."""
111
113
  _LOGGER.debug(
112
114
  "REPLACEDEVICE: interface_id = %s, oldDeviceAddress = %s, newDeviceAddress = %s",
@@ -116,7 +118,7 @@ class RPCFunctions:
116
118
  )
117
119
 
118
120
  @callback_backend_system(system_event=BackendSystemEvent.RE_ADDED_DEVICE)
119
- def readdedDevice(self, interface_id: str, addresses: list[str]) -> None:
121
+ def readdedDevice(self, interface_id: str, addresses: list[str], /) -> None:
120
122
  """
121
123
  Re-Add device from the backend.
122
124
 
@@ -130,9 +132,9 @@ class RPCFunctions:
130
132
  str(addresses),
131
133
  )
132
134
 
133
- def get_central(self, interface_id: str) -> hmcu.CentralUnit | None:
135
+ def get_central(self, *, interface_id: str) -> hmcu.CentralUnit | None:
134
136
  """Return the central by interface_id."""
135
- return self._xml_rpc_server.get_central(interface_id)
137
+ return self._xml_rpc_server.get_central(interface_id=interface_id)
136
138
 
137
139
 
138
140
  # Restrict to specific paths.
@@ -159,7 +161,7 @@ class AioHomematicXMLRPCServer(SimpleXMLRPCServer):
159
161
  system_listMethods(self, interface_id: str.
160
162
  """
161
163
 
162
- def system_listMethods(self, interface_id: str | None = None) -> list[str]:
164
+ def system_listMethods(self, interface_id: str | None = None, /) -> list[str]:
163
165
  """Return a list of the methods supported by the server."""
164
166
  return SimpleXMLRPCServer.system_listMethods(self)
165
167
 
@@ -172,6 +174,7 @@ class XmlRpcServer(threading.Thread):
172
174
 
173
175
  def __init__(
174
176
  self,
177
+ *,
175
178
  ip_addr: str,
176
179
  port: int,
177
180
  ) -> None:
@@ -192,7 +195,7 @@ class XmlRpcServer(threading.Thread):
192
195
  )
193
196
  self._simple_xml_rpc_server.register_introspection_functions()
194
197
  self._simple_xml_rpc_server.register_multicall_functions()
195
- self._simple_xml_rpc_server.register_instance(RPCFunctions(self), allow_dotted_names=True)
198
+ self._simple_xml_rpc_server.register_instance(RPCFunctions(xml_rpc_server=self), allow_dotted_names=True)
196
199
  self._centrals: Final[dict[str, hmcu.CentralUnit]] = {}
197
200
 
198
201
  def __new__(cls, ip_addr: str, port: int) -> XmlRpcServer: # noqa: PYI034
@@ -240,17 +243,17 @@ class XmlRpcServer(threading.Thread):
240
243
  """Return if thread is active."""
241
244
  return self._started.is_set() is True # type: ignore[attr-defined]
242
245
 
243
- def add_central(self, central: hmcu.CentralUnit) -> None:
246
+ def add_central(self, *, central: hmcu.CentralUnit) -> None:
244
247
  """Register a central in the XmlRPC-Server."""
245
248
  if not self._centrals.get(central.name):
246
249
  self._centrals[central.name] = central
247
250
 
248
- def remove_central(self, central: hmcu.CentralUnit) -> None:
251
+ def remove_central(self, *, central: hmcu.CentralUnit) -> None:
249
252
  """Unregister a central from XmlRPC-Server."""
250
253
  if self._centrals.get(central.name):
251
254
  del self._centrals[central.name]
252
255
 
253
- def get_central(self, interface_id: str) -> hmcu.CentralUnit | None:
256
+ def get_central(self, *, interface_id: str) -> hmcu.CentralUnit | None:
254
257
  """Return a central by interface_id."""
255
258
  for central in self._centrals.values():
256
259
  if central.has_client(interface_id=interface_id):
@@ -263,7 +266,7 @@ class XmlRpcServer(threading.Thread):
263
266
  return len(self._centrals) == 0
264
267
 
265
268
 
266
- def create_xml_rpc_server(ip_addr: str = IP_ANY_V4, port: int = PORT_ANY) -> XmlRpcServer:
269
+ def create_xml_rpc_server(*, ip_addr: str = IP_ANY_V4, port: int = PORT_ANY) -> XmlRpcServer:
267
270
  """Register the xml rpc server."""
268
271
  xml_rpc = XmlRpcServer(ip_addr=ip_addr, port=port)
269
272
  if not xml_rpc.started: