aiohomematic 2026.1.29__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.
Files changed (188) hide show
  1. aiohomematic/__init__.py +110 -0
  2. aiohomematic/_log_context_protocol.py +29 -0
  3. aiohomematic/api.py +410 -0
  4. aiohomematic/async_support.py +250 -0
  5. aiohomematic/backend_detection.py +462 -0
  6. aiohomematic/central/__init__.py +103 -0
  7. aiohomematic/central/async_rpc_server.py +760 -0
  8. aiohomematic/central/central_unit.py +1152 -0
  9. aiohomematic/central/config.py +463 -0
  10. aiohomematic/central/config_builder.py +772 -0
  11. aiohomematic/central/connection_state.py +160 -0
  12. aiohomematic/central/coordinators/__init__.py +38 -0
  13. aiohomematic/central/coordinators/cache.py +414 -0
  14. aiohomematic/central/coordinators/client.py +480 -0
  15. aiohomematic/central/coordinators/connection_recovery.py +1141 -0
  16. aiohomematic/central/coordinators/device.py +1166 -0
  17. aiohomematic/central/coordinators/event.py +514 -0
  18. aiohomematic/central/coordinators/hub.py +532 -0
  19. aiohomematic/central/decorators.py +184 -0
  20. aiohomematic/central/device_registry.py +229 -0
  21. aiohomematic/central/events/__init__.py +104 -0
  22. aiohomematic/central/events/bus.py +1392 -0
  23. aiohomematic/central/events/integration.py +424 -0
  24. aiohomematic/central/events/types.py +194 -0
  25. aiohomematic/central/health.py +762 -0
  26. aiohomematic/central/rpc_server.py +353 -0
  27. aiohomematic/central/scheduler.py +794 -0
  28. aiohomematic/central/state_machine.py +391 -0
  29. aiohomematic/client/__init__.py +203 -0
  30. aiohomematic/client/_rpc_errors.py +187 -0
  31. aiohomematic/client/backends/__init__.py +48 -0
  32. aiohomematic/client/backends/base.py +335 -0
  33. aiohomematic/client/backends/capabilities.py +138 -0
  34. aiohomematic/client/backends/ccu.py +487 -0
  35. aiohomematic/client/backends/factory.py +116 -0
  36. aiohomematic/client/backends/homegear.py +294 -0
  37. aiohomematic/client/backends/json_ccu.py +252 -0
  38. aiohomematic/client/backends/protocol.py +316 -0
  39. aiohomematic/client/ccu.py +1857 -0
  40. aiohomematic/client/circuit_breaker.py +459 -0
  41. aiohomematic/client/config.py +64 -0
  42. aiohomematic/client/handlers/__init__.py +40 -0
  43. aiohomematic/client/handlers/backup.py +157 -0
  44. aiohomematic/client/handlers/base.py +79 -0
  45. aiohomematic/client/handlers/device_ops.py +1085 -0
  46. aiohomematic/client/handlers/firmware.py +144 -0
  47. aiohomematic/client/handlers/link_mgmt.py +199 -0
  48. aiohomematic/client/handlers/metadata.py +436 -0
  49. aiohomematic/client/handlers/programs.py +144 -0
  50. aiohomematic/client/handlers/sysvars.py +100 -0
  51. aiohomematic/client/interface_client.py +1304 -0
  52. aiohomematic/client/json_rpc.py +2068 -0
  53. aiohomematic/client/request_coalescer.py +282 -0
  54. aiohomematic/client/rpc_proxy.py +629 -0
  55. aiohomematic/client/state_machine.py +324 -0
  56. aiohomematic/const.py +2207 -0
  57. aiohomematic/context.py +275 -0
  58. aiohomematic/converter.py +270 -0
  59. aiohomematic/decorators.py +390 -0
  60. aiohomematic/exceptions.py +185 -0
  61. aiohomematic/hmcli.py +997 -0
  62. aiohomematic/i18n.py +193 -0
  63. aiohomematic/interfaces/__init__.py +407 -0
  64. aiohomematic/interfaces/central.py +1067 -0
  65. aiohomematic/interfaces/client.py +1096 -0
  66. aiohomematic/interfaces/coordinators.py +63 -0
  67. aiohomematic/interfaces/model.py +1921 -0
  68. aiohomematic/interfaces/operations.py +217 -0
  69. aiohomematic/logging_context.py +134 -0
  70. aiohomematic/metrics/__init__.py +125 -0
  71. aiohomematic/metrics/_protocols.py +140 -0
  72. aiohomematic/metrics/aggregator.py +534 -0
  73. aiohomematic/metrics/dataclasses.py +489 -0
  74. aiohomematic/metrics/emitter.py +292 -0
  75. aiohomematic/metrics/events.py +183 -0
  76. aiohomematic/metrics/keys.py +300 -0
  77. aiohomematic/metrics/observer.py +563 -0
  78. aiohomematic/metrics/stats.py +172 -0
  79. aiohomematic/model/__init__.py +189 -0
  80. aiohomematic/model/availability.py +65 -0
  81. aiohomematic/model/calculated/__init__.py +89 -0
  82. aiohomematic/model/calculated/climate.py +276 -0
  83. aiohomematic/model/calculated/data_point.py +315 -0
  84. aiohomematic/model/calculated/field.py +147 -0
  85. aiohomematic/model/calculated/operating_voltage_level.py +286 -0
  86. aiohomematic/model/calculated/support.py +232 -0
  87. aiohomematic/model/custom/__init__.py +214 -0
  88. aiohomematic/model/custom/capabilities/__init__.py +67 -0
  89. aiohomematic/model/custom/capabilities/climate.py +41 -0
  90. aiohomematic/model/custom/capabilities/light.py +87 -0
  91. aiohomematic/model/custom/capabilities/lock.py +44 -0
  92. aiohomematic/model/custom/capabilities/siren.py +63 -0
  93. aiohomematic/model/custom/climate.py +1130 -0
  94. aiohomematic/model/custom/cover.py +722 -0
  95. aiohomematic/model/custom/data_point.py +360 -0
  96. aiohomematic/model/custom/definition.py +300 -0
  97. aiohomematic/model/custom/field.py +89 -0
  98. aiohomematic/model/custom/light.py +1174 -0
  99. aiohomematic/model/custom/lock.py +322 -0
  100. aiohomematic/model/custom/mixins.py +445 -0
  101. aiohomematic/model/custom/profile.py +945 -0
  102. aiohomematic/model/custom/registry.py +251 -0
  103. aiohomematic/model/custom/siren.py +462 -0
  104. aiohomematic/model/custom/switch.py +195 -0
  105. aiohomematic/model/custom/text_display.py +289 -0
  106. aiohomematic/model/custom/valve.py +78 -0
  107. aiohomematic/model/data_point.py +1416 -0
  108. aiohomematic/model/device.py +1840 -0
  109. aiohomematic/model/event.py +216 -0
  110. aiohomematic/model/generic/__init__.py +327 -0
  111. aiohomematic/model/generic/action.py +40 -0
  112. aiohomematic/model/generic/action_select.py +62 -0
  113. aiohomematic/model/generic/binary_sensor.py +30 -0
  114. aiohomematic/model/generic/button.py +31 -0
  115. aiohomematic/model/generic/data_point.py +177 -0
  116. aiohomematic/model/generic/dummy.py +150 -0
  117. aiohomematic/model/generic/number.py +76 -0
  118. aiohomematic/model/generic/select.py +56 -0
  119. aiohomematic/model/generic/sensor.py +76 -0
  120. aiohomematic/model/generic/switch.py +54 -0
  121. aiohomematic/model/generic/text.py +33 -0
  122. aiohomematic/model/hub/__init__.py +100 -0
  123. aiohomematic/model/hub/binary_sensor.py +24 -0
  124. aiohomematic/model/hub/button.py +28 -0
  125. aiohomematic/model/hub/connectivity.py +190 -0
  126. aiohomematic/model/hub/data_point.py +342 -0
  127. aiohomematic/model/hub/hub.py +864 -0
  128. aiohomematic/model/hub/inbox.py +135 -0
  129. aiohomematic/model/hub/install_mode.py +393 -0
  130. aiohomematic/model/hub/metrics.py +208 -0
  131. aiohomematic/model/hub/number.py +42 -0
  132. aiohomematic/model/hub/select.py +52 -0
  133. aiohomematic/model/hub/sensor.py +37 -0
  134. aiohomematic/model/hub/switch.py +43 -0
  135. aiohomematic/model/hub/text.py +30 -0
  136. aiohomematic/model/hub/update.py +221 -0
  137. aiohomematic/model/support.py +592 -0
  138. aiohomematic/model/update.py +140 -0
  139. aiohomematic/model/week_profile.py +1827 -0
  140. aiohomematic/property_decorators.py +719 -0
  141. aiohomematic/py.typed +0 -0
  142. aiohomematic/rega_scripts/accept_device_in_inbox.fn +51 -0
  143. aiohomematic/rega_scripts/create_backup_start.fn +28 -0
  144. aiohomematic/rega_scripts/create_backup_status.fn +89 -0
  145. aiohomematic/rega_scripts/fetch_all_device_data.fn +97 -0
  146. aiohomematic/rega_scripts/get_backend_info.fn +25 -0
  147. aiohomematic/rega_scripts/get_inbox_devices.fn +61 -0
  148. aiohomematic/rega_scripts/get_program_descriptions.fn +31 -0
  149. aiohomematic/rega_scripts/get_serial.fn +44 -0
  150. aiohomematic/rega_scripts/get_service_messages.fn +83 -0
  151. aiohomematic/rega_scripts/get_system_update_info.fn +39 -0
  152. aiohomematic/rega_scripts/get_system_variable_descriptions.fn +31 -0
  153. aiohomematic/rega_scripts/set_program_state.fn +17 -0
  154. aiohomematic/rega_scripts/set_system_variable.fn +19 -0
  155. aiohomematic/rega_scripts/trigger_firmware_update.fn +67 -0
  156. aiohomematic/schemas.py +256 -0
  157. aiohomematic/store/__init__.py +55 -0
  158. aiohomematic/store/dynamic/__init__.py +43 -0
  159. aiohomematic/store/dynamic/command.py +250 -0
  160. aiohomematic/store/dynamic/data.py +175 -0
  161. aiohomematic/store/dynamic/details.py +187 -0
  162. aiohomematic/store/dynamic/ping_pong.py +416 -0
  163. aiohomematic/store/persistent/__init__.py +71 -0
  164. aiohomematic/store/persistent/base.py +285 -0
  165. aiohomematic/store/persistent/device.py +233 -0
  166. aiohomematic/store/persistent/incident.py +380 -0
  167. aiohomematic/store/persistent/paramset.py +241 -0
  168. aiohomematic/store/persistent/session.py +556 -0
  169. aiohomematic/store/serialization.py +150 -0
  170. aiohomematic/store/storage.py +689 -0
  171. aiohomematic/store/types.py +526 -0
  172. aiohomematic/store/visibility/__init__.py +40 -0
  173. aiohomematic/store/visibility/parser.py +141 -0
  174. aiohomematic/store/visibility/registry.py +722 -0
  175. aiohomematic/store/visibility/rules.py +307 -0
  176. aiohomematic/strings.json +237 -0
  177. aiohomematic/support.py +706 -0
  178. aiohomematic/tracing.py +236 -0
  179. aiohomematic/translations/de.json +237 -0
  180. aiohomematic/translations/en.json +237 -0
  181. aiohomematic/type_aliases.py +51 -0
  182. aiohomematic/validator.py +128 -0
  183. aiohomematic-2026.1.29.dist-info/METADATA +296 -0
  184. aiohomematic-2026.1.29.dist-info/RECORD +188 -0
  185. aiohomematic-2026.1.29.dist-info/WHEEL +5 -0
  186. aiohomematic-2026.1.29.dist-info/entry_points.txt +2 -0
  187. aiohomematic-2026.1.29.dist-info/licenses/LICENSE +21 -0
  188. aiohomematic-2026.1.29.dist-info/top_level.txt +1 -0
@@ -0,0 +1,307 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2021-2026
3
+ """
4
+ Static visibility rules for Homematic parameters.
5
+
6
+ This module contains all static mappings and constants that determine parameter
7
+ visibility, including:
8
+
9
+ - MASTER paramset relevance by channel and device
10
+ - Parameters to ignore/un-ignore per device model
11
+ - Hidden parameters that are created but not displayed by default
12
+ - Event suppression rules for specific devices
13
+
14
+ These rules are used by ParameterVisibilityRegistry to make visibility decisions.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from collections.abc import Mapping
20
+ import re
21
+ from typing import Final, TypeAlias
22
+
23
+ from aiohomematic.const import CLICK_EVENTS, Parameter
24
+
25
+ # =============================================================================
26
+ # Type Aliases
27
+ # =============================================================================
28
+
29
+ ModelName: TypeAlias = str
30
+ ChannelNo: TypeAlias = int | None
31
+ ParameterName: TypeAlias = str
32
+
33
+ # =============================================================================
34
+ # MASTER Paramset Relevance Rules
35
+ # =============================================================================
36
+ # Define which additional parameters from MASTER paramset should be created as
37
+ # data points. By default these are also in HIDDEN_PARAMETERS, which prevents
38
+ # them from being displayed. Usually these entities are used within custom data
39
+ # points, not for general display.
40
+
41
+ RELEVANT_MASTER_PARAMSETS_BY_CHANNEL: Final[Mapping[ChannelNo, frozenset[Parameter]]] = {
42
+ None: frozenset({Parameter.GLOBAL_BUTTON_LOCK, Parameter.LOW_BAT_LIMIT}),
43
+ 0: frozenset({Parameter.GLOBAL_BUTTON_LOCK, Parameter.LOW_BAT_LIMIT}),
44
+ }
45
+
46
+ CLIMATE_MASTER_PARAMETERS: Final[frozenset[Parameter]] = frozenset(
47
+ {
48
+ Parameter.HEATING_VALVE_TYPE,
49
+ Parameter.MIN_MAX_VALUE_NOT_RELEVANT_FOR_MANU_MODE,
50
+ Parameter.OPTIMUM_START_STOP,
51
+ Parameter.TEMPERATURE_MAXIMUM,
52
+ Parameter.TEMPERATURE_MINIMUM,
53
+ Parameter.TEMPERATURE_OFFSET,
54
+ Parameter.WEEK_PROGRAM_POINTER,
55
+ }
56
+ )
57
+
58
+ # {model: (channel_numbers, parameters)}
59
+ RELEVANT_MASTER_PARAMSETS_BY_DEVICE: Final[Mapping[ModelName, tuple[frozenset[ChannelNo], frozenset[Parameter]]]] = {
60
+ "ALPHA-IP-RBG": (frozenset({1}), CLIMATE_MASTER_PARAMETERS),
61
+ "ELV-SH-TACO": (frozenset({2}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
62
+ "HM-CC-RT-DN": (frozenset({None}), CLIMATE_MASTER_PARAMETERS),
63
+ "HM-CC-VG-1": (frozenset({None}), CLIMATE_MASTER_PARAMETERS),
64
+ "HM-TC-IT-WM-W-EU": (frozenset({None}), CLIMATE_MASTER_PARAMETERS),
65
+ "HmIP-BWTH": (frozenset({1, 8}), CLIMATE_MASTER_PARAMETERS),
66
+ "HmIP-DRBLI4": (
67
+ frozenset({1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 17, 21}),
68
+ frozenset({Parameter.CHANNEL_OPERATION_MODE}),
69
+ ),
70
+ "HmIP-DRDI3": (frozenset({1, 2, 3}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
71
+ "HmIP-DRSI1": (frozenset({1}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
72
+ "HmIP-DRSI4": (frozenset({1, 2, 3, 4}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
73
+ "HmIP-DSD-PCB": (frozenset({1}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
74
+ "HmIP-FCI1": (frozenset({1}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
75
+ "HmIP-FCI6": (frozenset(range(1, 7)), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
76
+ "HmIP-FSI16": (frozenset({1}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
77
+ "HmIP-HEATING": (frozenset({1}), CLIMATE_MASTER_PARAMETERS),
78
+ "HmIP-MIO16-PCB": (frozenset({13, 14, 15, 16}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
79
+ "HmIP-MOD-RC8": (frozenset(range(1, 9)), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
80
+ "HmIP-RGBW": (frozenset({0}), frozenset({Parameter.DEVICE_OPERATION_MODE})),
81
+ "HmIP-STH": (frozenset({1}), CLIMATE_MASTER_PARAMETERS),
82
+ "HmIP-WGT": (frozenset({8, 14}), CLIMATE_MASTER_PARAMETERS),
83
+ "HmIP-WTH": (frozenset({1}), CLIMATE_MASTER_PARAMETERS),
84
+ "HmIP-eTRV": (frozenset({1}), CLIMATE_MASTER_PARAMETERS),
85
+ "HmIPW-DRBL4": (frozenset({1, 5, 9, 13}), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
86
+ "HmIPW-DRI16": (frozenset(range(1, 17)), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
87
+ "HmIPW-DRI32": (frozenset(range(1, 33)), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
88
+ "HmIPW-FIO6": (frozenset(range(1, 7)), frozenset({Parameter.CHANNEL_OPERATION_MODE})),
89
+ "HmIPW-STH": (frozenset({1}), CLIMATE_MASTER_PARAMETERS),
90
+ }
91
+
92
+ # =============================================================================
93
+ # Event Suppression Rules
94
+ # =============================================================================
95
+ # Ignore events for some devices to reduce noise in event streams.
96
+
97
+ IGNORE_DEVICES_FOR_DATA_POINT_EVENTS: Final[Mapping[ModelName, frozenset[Parameter]]] = {
98
+ "HmIP-PS": CLICK_EVENTS,
99
+ }
100
+
101
+ IGNORE_DEVICES_FOR_DATA_POINT_EVENTS_LOWER: Final[Mapping[ModelName, frozenset[Parameter]]] = {
102
+ model.lower(): frozenset(events) for model, events in IGNORE_DEVICES_FOR_DATA_POINT_EVENTS.items()
103
+ }
104
+
105
+ # =============================================================================
106
+ # Hidden Parameters
107
+ # =============================================================================
108
+ # Data points that will be created but should be hidden from UI by default.
109
+
110
+ HIDDEN_PARAMETERS: Final[frozenset[Parameter]] = frozenset(
111
+ {
112
+ Parameter.ACTIVITY_STATE,
113
+ Parameter.CHANNEL_OPERATION_MODE,
114
+ Parameter.CONFIG_PENDING,
115
+ Parameter.DIRECTION,
116
+ Parameter.ERROR,
117
+ Parameter.HEATING_VALVE_TYPE,
118
+ Parameter.LOW_BAT_LIMIT,
119
+ Parameter.MIN_MAX_VALUE_NOT_RELEVANT_FOR_MANU_MODE,
120
+ Parameter.OPTIMUM_START_STOP,
121
+ Parameter.SECTION,
122
+ Parameter.STICKY_UN_REACH,
123
+ Parameter.TEMPERATURE_MAXIMUM,
124
+ Parameter.TEMPERATURE_MINIMUM,
125
+ Parameter.TEMPERATURE_OFFSET,
126
+ Parameter.UN_REACH,
127
+ Parameter.UPDATE_PENDING,
128
+ Parameter.WORKING,
129
+ }
130
+ )
131
+
132
+ # =============================================================================
133
+ # Ignored Parameters
134
+ # =============================================================================
135
+ # Parameters within the VALUES paramset for which we don't create data points.
136
+
137
+ IGNORED_PARAMETERS: Final[frozenset[ParameterName]] = frozenset(
138
+ {
139
+ "ACCESS_AUTHORIZATION",
140
+ "ADAPTION_DRIVE",
141
+ "AES_KEY",
142
+ "ALARM_COUNT",
143
+ "ALL_LEDS",
144
+ "ARROW_DOWN",
145
+ "ARROW_UP",
146
+ "BACKLIGHT",
147
+ "BEEP",
148
+ "BELL",
149
+ "BLIND",
150
+ "BOOST_STATE",
151
+ "BOOST_TIME",
152
+ "BOOT",
153
+ "BULB",
154
+ "CLEAR_ERROR",
155
+ "CLEAR_WINDOW_OPEN_SYMBOL",
156
+ "CLOCK",
157
+ "CMD_RETL", # CUxD
158
+ "CMD_RETS", # CUxD
159
+ "CONTROL_DIFFERENTIAL_TEMPERATURE",
160
+ "DATE_TIME_UNKNOWN",
161
+ "DECISION_VALUE",
162
+ "DEVICE_IN_BOOTLOADER",
163
+ "DOOR",
164
+ "EXTERNAL_CLOCK",
165
+ "FROST_PROTECTION",
166
+ "HUMIDITY_LIMITER",
167
+ "IDENTIFICATION_MODE_KEY_VISUAL",
168
+ "IDENTIFICATION_MODE_LCD_BACKLIGHT",
169
+ "INCLUSION_UNSUPPORTED_DEVICE",
170
+ "INHIBIT",
171
+ "INSTALL_MODE",
172
+ "LEVEL_REAL",
173
+ "OLD_LEVEL",
174
+ "OVERFLOW",
175
+ "OVERRUN",
176
+ "PARTY_SET_POINT_TEMPERATURE",
177
+ "PARTY_TEMPERATURE",
178
+ "PARTY_TIME_END",
179
+ "PARTY_TIME_START",
180
+ "PHONE",
181
+ "PROCESS",
182
+ "QUICK_VETO_TIME",
183
+ "RAMP_STOP",
184
+ "RELOCK_DELAY",
185
+ "SCENE",
186
+ "SELF_CALIBRATION",
187
+ "SERVICE_COUNT",
188
+ "SET_SYMBOL_FOR_HEATING_PHASE",
189
+ "SHADING_SPEED",
190
+ "SHEV_POS",
191
+ "SPEED",
192
+ "STATE_UNCERTAIN",
193
+ "SUBMIT",
194
+ "SWITCH_POINT_OCCURED",
195
+ "TEMPERATURE_LIMITER",
196
+ "TEMPERATURE_OUT_OF_RANGE",
197
+ "TEXT",
198
+ "USER_COLOR",
199
+ "USER_PROGRAM",
200
+ "VALVE_ADAPTION",
201
+ "WINDOW",
202
+ "WIN_RELEASE",
203
+ "WIN_RELEASE_ACT",
204
+ }
205
+ )
206
+
207
+ # Precompiled regex patterns for wildcard parameter checks
208
+ IGNORED_PARAMETERS_END_PATTERN: Final = re.compile(r".*(_OVERFLOW|_OVERRUN|_REPORTING|_RESULT|_STATUS|_SUBMIT)$")
209
+ IGNORED_PARAMETERS_START_PATTERN: Final = re.compile(
210
+ r"^(ADJUSTING_|ERR_TTM_|HANDLE_|IDENTIFY_|PARTY_START_|PARTY_STOP_|STATUS_FLAG_|WEEK_PROGRAM_)"
211
+ )
212
+
213
+
214
+ def parameter_is_wildcard_ignored(*, parameter: ParameterName) -> bool:
215
+ """Check if a parameter matches common wildcard patterns."""
216
+ return bool(IGNORED_PARAMETERS_END_PATTERN.match(parameter) or IGNORED_PARAMETERS_START_PATTERN.match(parameter))
217
+
218
+
219
+ # =============================================================================
220
+ # Un-Ignore Rules by Device
221
+ # =============================================================================
222
+ # Parameters that are normally ignored but should be created for specific devices.
223
+
224
+ UN_IGNORE_PARAMETERS_BY_DEVICE: Final[Mapping[ModelName, frozenset[Parameter]]] = {
225
+ "HmIP-DLD": frozenset({Parameter.ERROR_JAMMED}),
226
+ "HmIP-SWSD": frozenset({Parameter.DIRT_LEVEL, Parameter.SMOKE_LEVEL, Parameter.SMOKE_DETECTOR_ALARM_STATUS}),
227
+ # Text display parameters for HmIP-WRCD
228
+ "HmIP-WRCD": frozenset(
229
+ {Parameter.DISPLAY_DATA_COMMIT, Parameter.DISPLAY_DATA_ID, Parameter.DISPLAY_DATA_STRING, Parameter.INTERVAL}
230
+ ),
231
+ "HM-OU-LED16": frozenset({Parameter.LED_STATUS}),
232
+ "HM-Sec-Win": frozenset({Parameter.DIRECTION, Parameter.WORKING, Parameter.ERROR, Parameter.STATUS}),
233
+ "HM-Sec-Key": frozenset({Parameter.DIRECTION, Parameter.ERROR}),
234
+ "HmIP-PCBS-BAT": frozenset({Parameter.OPERATING_VOLTAGE, Parameter.LOW_BAT}), # Override HmIP-PCBS
235
+ # RF thermostats need WEEK_PROGRAM_POINTER for climate presets
236
+ "BC-RT-TRX-CyG": frozenset({Parameter.WEEK_PROGRAM_POINTER}),
237
+ "BC-RT-TRX-CyN": frozenset({Parameter.WEEK_PROGRAM_POINTER}),
238
+ "BC-TC-C-WM": frozenset({Parameter.WEEK_PROGRAM_POINTER}),
239
+ "HM-CC-RT-DN": frozenset({Parameter.WEEK_PROGRAM_POINTER}),
240
+ "HM-CC-VG-1": frozenset({Parameter.WEEK_PROGRAM_POINTER}),
241
+ "HM-TC-IT-WM-W-EU": frozenset({Parameter.WEEK_PROGRAM_POINTER}),
242
+ }
243
+
244
+ UN_IGNORE_PARAMETERS_BY_MODEL_LOWER: Final[dict[ModelName, frozenset[Parameter]]] = {
245
+ model.lower(): frozenset(parameters) for model, parameters in UN_IGNORE_PARAMETERS_BY_DEVICE.items()
246
+ }
247
+
248
+ # =============================================================================
249
+ # Ignore Rules by Device
250
+ # =============================================================================
251
+ # Parameters to ignore for specific device models.
252
+
253
+ IGNORE_PARAMETERS_BY_DEVICE: Final[Mapping[Parameter, frozenset[ModelName]]] = {
254
+ Parameter.CURRENT_ILLUMINATION: frozenset({"HmIP-SMI", "HmIP-SMO", "HmIP-SPI"}),
255
+ Parameter.LOWBAT: frozenset(
256
+ {
257
+ "HM-LC-Sw1-DR",
258
+ "HM-LC-Sw1-FM",
259
+ "HM-LC-Sw1-PCB",
260
+ "HM-LC-Sw1-Pl",
261
+ "HM-LC-Sw1-Pl-DN-R1",
262
+ "HM-LC-Sw1PBU-FM",
263
+ "HM-LC-Sw2-FM",
264
+ "HM-LC-Sw4-DR",
265
+ "HM-SwI-3-FM",
266
+ }
267
+ ),
268
+ Parameter.LOW_BAT: frozenset({"HmIP-BWTH", "HmIP-PCBS"}),
269
+ Parameter.OPERATING_VOLTAGE: frozenset(
270
+ {
271
+ "ELV-SH-BS2",
272
+ "HmIP-BDT",
273
+ "HmIP-BROLL",
274
+ "HmIP-BS2",
275
+ "HmIP-BSL",
276
+ "HmIP-BSM",
277
+ "HmIP-BWTH",
278
+ "HmIP-DR",
279
+ "HmIP-FDT",
280
+ "HmIP-FROLL",
281
+ "HmIP-FSM",
282
+ "HmIP-MOD-OC8",
283
+ "HmIP-PCBS",
284
+ "HmIP-PDT",
285
+ "HmIP-PMFS",
286
+ "HmIP-PS",
287
+ "HmIP-SFD",
288
+ "HmIP-SMO230",
289
+ "HmIP-WGT",
290
+ }
291
+ ),
292
+ Parameter.VALVE_STATE: frozenset({"HmIP-FALMOT-C8", "HmIPW-FALMOT-C12", "HmIP-FALMOT-C12"}),
293
+ }
294
+
295
+ IGNORE_PARAMETERS_BY_DEVICE_LOWER: Final[dict[ParameterName, frozenset[ModelName]]] = {
296
+ parameter: frozenset(model.lower() for model in s) for parameter, s in IGNORE_PARAMETERS_BY_DEVICE.items()
297
+ }
298
+
299
+ # =============================================================================
300
+ # Channel-Specific Parameter Rules
301
+ # =============================================================================
302
+ # Some devices have parameters on multiple channels, but we want to use it only
303
+ # from a certain channel.
304
+
305
+ ACCEPT_PARAMETER_ONLY_ON_CHANNEL: Final[Mapping[ParameterName, int]] = {
306
+ Parameter.LOWBAT: 0,
307
+ }
@@ -0,0 +1,237 @@
1
+ {
2
+ "exception.central.create_devices.no_clients": "CREATE_DEVICES failed: No clients initialized. Not starting central {name}.",
3
+ "exception.central.decorators.backend_system_handler.args_exception": "ARGS-EXCEPTION backend_system_handler [{reason}]",
4
+ "exception.central.decorators.backend_system_handler.identify_central_failed": "EXEC_BACKEND_SYSTEM_CALLBACK failed: Problem with identifying central: {reason}",
5
+ "exception.central.decorators.event_handler.args_exception": "ARGS-EXCEPTION event_handler [{reason}]",
6
+ "exception.central.get_client.interface_missing": "GET_CLIENT failed: Missing client for interface_id {interface_id} on central {name}",
7
+ "exception.central.get_client.interface_type_missing": "GET_CLIENT failed: Missing client for interface {interface} on central {name}",
8
+ "exception.central.get_client.no_parameter": "GET_CLIENT failed: Either interface_id or interface must be provided on central {name}",
9
+ "exception.central.rpc_server.invalid_xml": "Invalid XML: {error}",
10
+ "exception.central.rpc_server.parse_error": "Parse error: {error}",
11
+ "exception.central.start.failed": "Failed to start central unit {name}: {reason}",
12
+ "exception.central.validate_config.no_clients": "VALIDATE_CONFIG: No clients defined.",
13
+ "exception.client.add_link.failed": "ADD_LINK failed for {sender}/{receiver}/{name}/{description}: {reason}",
14
+ "exception.client.client_config.no_connection": "No connection to {interface_id}",
15
+ "exception.client.client_config.unable_to_connect": "Unable to connect {reason}",
16
+ "exception.client.get_all_device_data.failed": "GET_ALL_DEVICE_DATA failed: Unable to fetch device data for interface {interface}",
17
+ "exception.client.get_install_mode.failed": "GET_INSTALL_MODE failed for {interface_id}: {reason}",
18
+ "exception.client.get_link_peers.failed": "GET_LINK_PEERS failed for {address}: {reason}",
19
+ "exception.client.get_links.failed": "GET_LINKS failed for {address}: {reason}",
20
+ "exception.client.get_metadata.failed": "GET_METADATA failed for {address}/{data_id}: {reason}",
21
+ "exception.client.get_paramset.failed": "GET_PARAMSET failed for {address}/{paramset_key}: {reason}",
22
+ "exception.client.get_value.failed": "GET_VALUE failed for {channel_address}/{parameter}/{paramset_key}: {reason}",
23
+ "exception.client.interface_config.port_required": "VALIDATE interface config failed: Port must defined for interface {interface}",
24
+ "exception.client.json_ccu.get_paramset.failed": "GET_PARAMSET failed for {address}/{paramset_key}: {reason}",
25
+ "exception.client.json_ccu.get_value.failed": "GET_VALUE failed for: {channel_address}/{parameter}/{paramset_key}: {reason}",
26
+ "exception.client.json_ccu.set_value.unknown_type": "SET_VALUE failed: Unable to identify parameter type {channel_address}/{paramset_key}/{parameter}",
27
+ "exception.client.json_post.connector_certificate_error": "Connector certificate error: {reason}",
28
+ "exception.client.json_post.connector_error": "Connector error: {reason}",
29
+ "exception.client.json_post.http_status": "HTTP status: {status}",
30
+ "exception.client.json_post.login_failed": "Error while logging in",
31
+ "exception.client.json_post.method_unsupported": "POST: method '{method} not supported by the backend.",
32
+ "exception.client.json_post.no_credentials": "No credentials set",
33
+ "exception.client.json_post.no_response": "POST method failed with no response",
34
+ "exception.client.json_post.no_session": "ClientSession not initialized",
35
+ "exception.client.json_rpc.circuit_open": "Circuit breaker is open for {url} - requests temporarily blocked",
36
+ "exception.client.parameter.not_found": "Parameter {parameter} could not be found: {interface_id}/{channel_address}/{paramset_key}",
37
+ "exception.client.parameter.operation_unsupported": "Parameter {parameter} does not support the requested operation {operation}",
38
+ "exception.client.parameter.value_above_max": "Value {value} for parameter {parameter} exceeds maximum {max_value}",
39
+ "exception.client.parameter.value_below_min": "Value {value} for parameter {parameter} is below minimum {min_value}",
40
+ "exception.client.paramset_key.invalid": "Parameter paramset_key is neither a valid ParamsetKey nor a channel address.",
41
+ "exception.client.put_paramset.failed": "PUT_PARAMSET failed for {channel_address}/{paramset_key}/{values}: {reason}",
42
+ "exception.client.remove_link.failed": "REMOVE_LINK failed for {sender}/{receiver}: {reason}",
43
+ "exception.client.report_value_usage.failed": "REPORT_VALUE_USAGE failed: {address}/{value_id}/{ref_counter}: {reason}",
44
+ "exception.client.rx_mode.unsupported": "Unsupported rx_mode: {rx_mode}",
45
+ "exception.client.script.missing": "Script file for {script} does not exist",
46
+ "exception.client.set_install_mode.failed": "SET_INSTALL_MODE failed for {interface_id}: {reason}",
47
+ "exception.client.set_metadata.failed": "SET_METADATA failed for {address}/{data_id}/{value}: {reason}",
48
+ "exception.client.set_value.failed": "SET_VALUE failed for {channel_address}/{parameter}={value}: {reason}",
49
+ "exception.client.update_device_firmware.failed": "UPDATE_DEVICE_FIRMWARE failed: {reason}",
50
+ "exception.client.xmlrpc.circuit_open": "Circuit breaker is open for {interface_id} - requests temporarily blocked",
51
+ "exception.client.xmlrpc.http_connection_state_error": "HTTP connection state error on {interface_id}: {reason}",
52
+ "exception.client.xmlrpc.method_unsupported": "XmlRPC.__ASYNC_REQUEST: method '{method} not supported by the backend.",
53
+ "exception.client.xmlrpc.no_connection": "No connection to {interface_id}",
54
+ "exception.client.xmlrpc.no_connection_with_reason": "No connection to {context}: {reason}",
55
+ "exception.client.xmlrpc.null_proxy_unsupported": "XML-RPC not supported on {interface_id} - use JSON-RPC methods instead",
56
+ "exception.client.xmlrpc.os_error": "OSError on {interface_id}: {reason}",
57
+ "exception.client.xmlrpc.ssl_error": "SSLError on {interface_id}: {reason}",
58
+ "exception.config.check.callback_host.invalid": "Invalid callback hostname or ipv4 address",
59
+ "exception.config.check.callback_port_xml_rpc.invalid": "Invalid xml rpc callback port",
60
+ "exception.config.check.host.invalid": "Invalid hostname or ipv4 address",
61
+ "exception.config.check.instance_name.separator": "Instance name must not contain {sep}",
62
+ "exception.config.check.json_port.invalid": "Invalid json port",
63
+ "exception.config.check.password.invalid": "Password is not valid",
64
+ "exception.config.check.password.required": "Password is required",
65
+ "exception.config.check.primary_interface.missing": "No primary interface ({interfaces}) defined",
66
+ "exception.config.check.username.empty": "Username must not be empty",
67
+ "exception.config.invalid": "Invalid configuration: {failures}",
68
+ "exception.create_central.failed": "Not able to create a central: {reason}",
69
+ "exception.model.action_select.value_not_in_value_list": "ACTION_SELECT {name} (unique_id={unique_id}): Value not in value list",
70
+ "exception.model.custom.climate.set_temperature.invalid": "SET_TEMPERATURE failed: Invalid temperature: {temperature} (min: {min}, max: {max})",
71
+ "exception.model.custom.definition.create_custom_data_point.failed": "_CREATE_CUSTOM_DATA_POINT: unable to create custom data point: {reason}",
72
+ "exception.model.custom.light.invalid_brightness": "Invalid brightness specified for data_point {full_name}: {value}. Must be 0.0-1.0.",
73
+ "exception.model.custom.light.invalid_color": "Invalid color specified for data_point {full_name}: {value}",
74
+ "exception.model.custom.light.invalid_duration_unit": "Invalid duration unit specified for data_point {full_name}: {value}",
75
+ "exception.model.custom.light.invalid_on_time": "Invalid on time specified for data_point {full_name}: {value}",
76
+ "exception.model.custom.light.invalid_repetitions": "Invalid repetitions specified for data_point {full_name}: {value}",
77
+ "exception.model.custom.siren.invalid_duration_unit": "Invalid duration unit specified for data_point {full_name}: {value}",
78
+ "exception.model.custom.siren.invalid_light": "Invalid light specified for data_point {full_name}: {value}",
79
+ "exception.model.custom.siren.invalid_repetitions": "Invalid repetitions specified for data_point {full_name}: {value}",
80
+ "exception.model.custom.siren.invalid_soundfile": "Invalid soundfile specified for data_point {full_name}: {value}",
81
+ "exception.model.custom.siren.invalid_soundfile_index": "Soundfile index must be 1-189, got {index}",
82
+ "exception.model.custom.siren.invalid_tone": "Invalid tone specified for data_point {full_name}: {value}",
83
+ "exception.model.custom.siren.invalid_volume": "Invalid volume specified for data_point {full_name}: {value}. Must be 0.0-1.0.",
84
+ "exception.model.custom.text_display.invalid_alignment": "Invalid alignment specified for data_point {full_name}: {value}",
85
+ "exception.model.custom.text_display.invalid_background_color": "Invalid background color specified for data_point {full_name}: {value}",
86
+ "exception.model.custom.text_display.invalid_display_id": "Invalid display ID specified for data_point {full_name}: {value}. Must be 1-5.",
87
+ "exception.model.custom.text_display.invalid_icon": "Invalid icon specified for data_point {full_name}: {value}",
88
+ "exception.model.custom.text_display.invalid_interval": "Invalid interval specified for data_point {full_name}: {value}. Must be 1-15.",
89
+ "exception.model.custom.text_display.invalid_repeat": "Invalid repeat count specified for data_point {full_name}: {value}. Must be 0-15.",
90
+ "exception.model.custom.text_display.invalid_sound": "Invalid sound specified for data_point {full_name}: {value}",
91
+ "exception.model.custom.text_display.invalid_text_color": "Invalid text color specified for data_point {full_name}: {value}",
92
+ "exception.model.data_point.subscribe_handler.already_registered": "REGISTER_DATA_POINT_UPDATED_CALLBACK failed: hm_data_point: {full_name} is already registered by {custom_id}",
93
+ "exception.model.device.export_device_definition.failed": "EXPORT_DEVICE_DEFINITION failed: {reason}",
94
+ "exception.model.event.create_event.failed": "CREATE_EVENT_AND_APPEND_TO_CHANNEL: Unable to create event: {reason}",
95
+ "exception.model.generic.create_data_point.failed": "CREATE_DATA_POINT_AND_APPEND_TO_CHANNEL: Unable to create data_point: {reason}",
96
+ "exception.model.hub.number.invalid_value": "SYSVAR.NUMBER failed: Invalid value: {value} (min: {min}, max: {max})",
97
+ "exception.model.number.invalid_value": "NUMBER failed: Invalid value: {value} (min: {min}, max: {max}, special:{special})",
98
+ "exception.model.select.value_not_in_value_list": "Value not in value_list for {name}/{unique_id}",
99
+ "exception.model.week_profile.copy_schedule.profile_count_mismatch": "Copy schedule profile is only: No of schedule profile must be identical",
100
+ "exception.model.week_profile.copy_schedule.same_device_invalid": "Copy schedule profile on same device is only possible with defined and different source/target profiles",
101
+ "exception.model.week_profile.schedule.unsupported": "Schedule is not supported by device {name}",
102
+ "exception.model.week_profile.source_profile.not_loaded": "Source profile {source_profile} could not be loaded.",
103
+ "exception.model.week_profile.validate.base_temperature_out_of_range": "VALIDATE_PROFILE: Base temperature {base_temperature} not in valid range (min: {min}, max: {max})",
104
+ "exception.model.week_profile.validate.endtime_missing": "VALIDATE_PROFILE: ENDTIME is missing.",
105
+ "exception.model.week_profile.validate.overlap": "VALIDATE_PROFILE: Timespans are overlapping with a previous slot for start time: {start} / end time: {end}",
106
+ "exception.model.week_profile.validate.profile_name_invalid": "Not a valid profile name: {profile_name}",
107
+ "exception.model.week_profile.validate.sequence_rising": "VALIDATE_PROFILE: Time sequence must be rising. {time} is lower than the previous value {previous} for profile: {profile} / week day: {weekday} / slot no: {no}",
108
+ "exception.model.week_profile.validate.slot_missing": "VALIDATE_PROFILE: slot no {no} is missing in profile: {profile} / week day: {weekday}",
109
+ "exception.model.week_profile.validate.slot_type_missing": "VALIDATE_PROFILE: slot type {slot_type} is missing in profile: {profile} / week day: {weekday} / slot no: {no}",
110
+ "exception.model.week_profile.validate.start_before_end": "VALIDATE_PROFILE: Start time {start} must be lower than end time {end}",
111
+ "exception.model.week_profile.validate.starttime_missing": "VALIDATE_PROFILE: STARTTIME is missing.",
112
+ "exception.model.week_profile.validate.temperature_missing": "VALIDATE_PROFILE: TEMPERATURE is missing.",
113
+ "exception.model.week_profile.validate.temperature_out_of_range_for_profile_slot": "VALIDATE_PROFILE: Temperature {temperature} not in valid range (min: {min}, max: {max}) for profile: {profile} / week day: {weekday} / slot no: {no}",
114
+ "exception.model.week_profile.validate.temperature_out_of_range_for_times": "VALIDATE_PROFILE: Temperature {temperature} not in valid range (min: {min}, max: {max}) for start time: {start} / end time: {end}",
115
+ "exception.model.week_profile.validate.time_convert_failed": "Failed to convert time {time}. Format must be hh:mm.",
116
+ "exception.model.week_profile.validate.time_invalid_format": "Time {time} is not valid. Format must be hh:mm with min: {min} and max: {max}",
117
+ "exception.model.week_profile.validate.time_out_of_bounds_profile_slot": "VALIDATE_PROFILE: Time {time} must be between {min_time} and {max_time} for profile: {profile} / week day: {weekday} / slot no: {no}",
118
+ "exception.model.week_profile.validate.too_few_slots": "VALIDATE_PROFILE: Too few slots in profile: {profile} / week day: {weekday}",
119
+ "exception.model.week_profile.validate.too_many_slots": "VALIDATE_PROFILE: Too many slots in profile: {profile} / week day: {weekday}",
120
+ "exception.startup.validation_failed": "AioHomematic startup validation failed: {reason}",
121
+ "exception.store.device_description.not_found": "Description not found for {address} on interface {interface_id}",
122
+ "exception.store.session_recorder.ttl_positive": "default_ttl_seconds must be positive",
123
+ "exception.support.boolean.invalid_type": "Invalid literal for boolean. Not a string.",
124
+ "exception.support.check_or_create_directory.failed": "Unable to create directory {directory}: {reason}",
125
+ "exception.support.get_local_ip.resolve_failed": "Can't resolve host for {host}:{port}: {reason}",
126
+ "exception.support.host_empty": "Host cannot be empty",
127
+ "exception.support.host_invalid": "Invalid host format: {host}. Must be a valid hostname or IP address",
128
+ "exception.validator.categories.not_exhaustive": "BLOCKED_CATEGORIES/CATEGORIES/HUB_CATEGORIES are not exhaustive. Missing categories: {missing}",
129
+ "exception.validator.channel_address.invalid": "CHANNEL_ADDRESS is invalid",
130
+ "exception.validator.custom_definition.invalid": "Custom data point definition schema is invalid",
131
+ "exception.validator.device_address.invalid": "DEVICE_ADDRESS is invalid",
132
+ "exception.validator.hostname.invalid": "Hostname is invalid",
133
+ "exception.validator.ipv4_address.invalid": "IPv4_address is invalid",
134
+ "exception.validator.paramset_key.invalid": "PARAMSET_KEY is invalid",
135
+ "exception.validator.password.invalid": "Password is invalid",
136
+ "exception.validator.undefined_in_lists": "DataPointCategory.UNDEFINED must not be present in BLOCKED_CATEGORIES/CATEGORIES/HUB_CATEGORIES",
137
+ "issue.fetch_data_failed": "Failed to fetch device data from interface {interface_id}",
138
+ "issue.ping_pong_mismatch": "Ping-pong mismatch detected on {interface_id} ({mismatch_type}: {mismatch_count} mismatches)",
139
+ "log.backend_detection.detect_backend.backend_type": "DETECT_BACKEND: Detected backend type: {backend}",
140
+ "log.backend_detection.detect_backend.found_interfaces": "DETECT_BACKEND: Found interfaces via JSON-RPC: {interfaces}",
141
+ "log.backend_detection.detect_backend.found_version": "DETECT_BACKEND: Found version '{version}' on port {port}",
142
+ "log.backend_detection.detect_backend.json_rpc_fallback": "DETECT_BACKEND: JSON-RPC query failed, using detected interface",
143
+ "log.backend_detection.detect_backend.no_backend_found": "DETECT_BACKEND: No backend found on host {host}",
144
+ "log.backend_detection.detect_backend.probing": "DETECT_BACKEND: Probing {host}:{port} (TLS={tls}, interface={interface})",
145
+ "log.backend_detection.detect_backend.starting": "DETECT_BACKEND: Starting detection for host {host} (timeout={total_timeout}s)",
146
+ "log.backend_detection.detect_backend.total_timeout": "DETECT_BACKEND: Detection timed out after {total_timeout}s for host {host}",
147
+ "log.backend_detection.json_rpc.auth_failed": "DETECT_BACKEND: Authentication failed at {url}",
148
+ "log.backend_detection.json_rpc.connection_failed": "DETECT_BACKEND: Connection failed at {url}",
149
+ "log.backend_detection.json_rpc.interface_not_present": "DETECT_BACKEND: Interface '{interface}' is installed but not running - skipping",
150
+ "log.backend_detection.json_rpc.interface_present": "DETECT_BACKEND: Interface '{interface}' is present and running",
151
+ "log.backend_detection.json_rpc.is_present_failed": "DETECT_BACKEND: Failed to check if interface '{interface}' is present: {reason}",
152
+ "log.backend_detection.json_rpc.query_failed": "DETECT_BACKEND: JSON-RPC query failed at {url} - {exc_type}: {reason}",
153
+ "log.backend_detection.json_rpc.querying": "DETECT_BACKEND: Querying JSON-RPC at {url}",
154
+ "log.backend_detection.json_rpc.unknown_interface": "DETECT_BACKEND: Unknown interface '{interface}', skipping",
155
+ "log.backend_detection.xml_rpc.probe_error": "DETECT_BACKEND: XML-RPC probe error for {host}:{port} - {exc_type}: {reason}",
156
+ "log.backend_detection.xml_rpc.probe_failed": "DETECT_BACKEND: XML-RPC probe failed for {host}:{port} - {exc_type}: {reason}",
157
+ "log.backend_detection.xml_rpc.probe_timeout": "DETECT_BACKEND: XML-RPC probe timeout for {host}:{port}",
158
+ "log.central.accept_device_in_inbox.no_client": "ACCEPT_DEVICE_IN_INBOX failed: No primary client available for {device_address} on {name}",
159
+ "log.central.create_client.no_connection": "CREATE_CLIENT failed: No connection to interface {interface_id} [{reason}]",
160
+ "log.central.create_clients.already_created": "CREATE_CLIENTS: Clients for {name} are already created",
161
+ "log.central.create_clients.created_count_failed": "CREATE_CLIENTS failed: Created {created} of {total} clients",
162
+ "log.central.create_clients.interface_not_available": "CREATE_CLIENTS failed: Interface: {interface} is not available for the backend {name}",
163
+ "log.central.create_clients.no_interfaces": "CREATE_CLIENTS failed: No interfaces for {name} defined",
164
+ "log.central.create_clients.no_primary_identified": "CREATE_CLIENTS failed: No primary client identified for {name}",
165
+ "log.central.rename_device.not_found": "RENAME_DEVICE failed: Device {device_address} not found on {name}",
166
+ "log.central.restart_clients.restarted": "RESTART_CLIENTS: Central {name} restarted clients",
167
+ "log.central.rpc_server.background_task_failed": "Background task {task_name} failed: {error}",
168
+ "log.central.rpc_server.error": "ERROR failed: interface_id = {interface_id}, error_code = {error_code}, message = {msg}",
169
+ "log.central.rpc_server.method_failed": "XML-RPC method {method_name} failed",
170
+ "log.central.rpc_server.protocol_error": "XML-RPC protocol error: {error}",
171
+ "log.central.rpc_server.unexpected_error": "Unexpected error handling XML-RPC request",
172
+ "log.central.scheduler.check_connection.attempting_reconnect": "CHECK_CONNECTION: RPC stable for {name} - attempting full reconnection",
173
+ "log.central.scheduler.check_connection.connection_loss_detected": "CHECK_CONNECTION: Connection loss detected for {name} - starting staged reconnection",
174
+ "log.central.scheduler.check_connection.failed": "CHECK_CONNECTION failed: {exc_type} [{reason}]",
175
+ "log.central.scheduler.check_connection.no_clients": "CHECK_CONNECTION failed: No clients exist. Trying to create clients for server {name}",
176
+ "log.central.scheduler.check_connection.no_connection": "CHECK_CONNECTION failed: no connection: {reason}",
177
+ "log.central.scheduler.check_connection.reconnect_failed": "CHECK_CONNECTION: Reconnection failed for {name} - will retry",
178
+ "log.central.scheduler.check_connection.reconnect_success": "CHECK_CONNECTION: Reconnection successful for {name} - interfaces: {interfaces}",
179
+ "log.central.scheduler.check_connection.rpc_check_passed": "CHECK_CONNECTION: First RPC check passed for {name} - starting warmup",
180
+ "log.central.scheduler.check_connection.rpc_stable": "CHECK_CONNECTION: Second RPC check passed for {name} - services stable",
181
+ "log.central.scheduler.check_connection.rpc_unstable": "CHECK_CONNECTION: RPC became unavailable during warmup for {name} - retrying",
182
+ "log.central.scheduler.check_connection.tcp_check_timeout": "CHECK_CONNECTION: TCP port check timeout ({timeout}s) for {name} - restarting check",
183
+ "log.central.scheduler.check_connection.tcp_port_available": "CHECK_CONNECTION: TCP port {host}:{port} available for {name}",
184
+ "log.central.set_system_variable.not_found": "SET_SYSTEM_VARIABLE failed: Variable {legacy_name} not found on {name}",
185
+ "log.central.validate_config_and_get_system_information.client_failed": "VALIDATE_CONFIG_AND_GET_SYSTEM_INFORMATION failed for client {interface}: {reason}",
186
+ "log.client.circuit_breaker.state_transition": "CIRCUIT_BREAKER: {old_state} → {new_state} for {interface_id} (failures={failure_count}, successes={success_count})",
187
+ "log.client.create_backup_and_download.completed": "CREATE_BACKUP_AND_DOWNLOAD: Backup completed: {filename} ({size} bytes)",
188
+ "log.client.create_backup_and_download.failed": "CREATE_BACKUP_AND_DOWNLOAD: Backup creation failed",
189
+ "log.client.create_backup_and_download.idle": "CREATE_BACKUP_AND_DOWNLOAD: Unexpected idle status during backup",
190
+ "log.client.create_backup_and_download.running": "CREATE_BACKUP_AND_DOWNLOAD: Backup still running ({elapsed:.1f}s elapsed)",
191
+ "log.client.create_backup_and_download.timeout": "CREATE_BACKUP_AND_DOWNLOAD: Backup timed out after {max_wait_time:.1f}s",
192
+ "log.client.is_callback_alive.no_events": "IS_CALLBACK_ALIVE: Callback for {interface_id} has not received events for {seconds}s",
193
+ "log.client.json_rpc.accept_device_in_inbox.failed": "ACCEPT_DEVICE_IN_INBOX for {device_address} failed: Unable to decode json: {reason}",
194
+ "log.client.json_rpc.create_backup_start.failed": "CREATE_BACKUP_START failed: Unable to decode json: {reason}",
195
+ "log.client.json_rpc.create_backup_status.failed": "CREATE_BACKUP_STATUS failed: Unable to decode json: {reason}",
196
+ "log.client.json_rpc.do_login.max_attempts_reached": "DO_LOGIN failed: Max failed login attempts ({max_attempts}) reached. Consider checking credentials.",
197
+ "log.client.json_rpc.do_login.no_credentials": "DO_LOGIN failed: No credentials set",
198
+ "log.client.json_rpc.do_login.rate_limited": "DO_LOGIN: Rate limited after {attempts} failed attempts. Waiting {wait_time:.1f} seconds.",
199
+ "log.client.json_rpc.download_backup.error": "DOWNLOAD_BACKUP failed: {reason}",
200
+ "log.client.json_rpc.download_backup.failed": "DOWNLOAD_BACKUP failed: HTTP status {status}",
201
+ "log.client.json_rpc.download_backup.no_session": "DOWNLOAD_BACKUP failed: No session ID available",
202
+ "log.client.json_rpc.download_firmware.error": "DOWNLOAD_FIRMWARE failed: {reason}",
203
+ "log.client.json_rpc.download_firmware.failed": "DOWNLOAD_FIRMWARE failed: HTTP status {status}",
204
+ "log.client.json_rpc.download_firmware.no_session": "DOWNLOAD_FIRMWARE failed: No session ID available",
205
+ "log.client.json_rpc.get_all_system_variables.parse_failed": "GET_ALL_SYSTEM_VARIABLES failed: {exc_type} [{reason}] Failed to parse SysVar {legacy_name}",
206
+ "log.client.json_rpc.get_backend_info.failed": "GET_BACKEND_INFO failed: Unable to decode json: {reason}",
207
+ "log.client.json_rpc.get_inbox_devices.decode_failed": "GET_INBOX_DEVICES failed: Unable to decode json: {reason}",
208
+ "log.client.json_rpc.get_program_descriptions.decode_failed": "GET_PROGRAM_DESCRIPTIONS failed: Unable to decode json: {reason}",
209
+ "log.client.json_rpc.get_service_messages.decode_failed": "GET_SERVICE_MESSAGES failed: Unable to decode json: {reason}",
210
+ "log.client.json_rpc.get_system_update_info.decode_failed": "GET_SYSTEM_UPDATE_INFO failed: Unable to decode json: {reason}",
211
+ "log.client.json_rpc.get_system_variable_descriptions.decode_failed": "GET_SYSTEM_VARIABLE_DESCRIPTIONS failed: Unable to decode json: {reason}",
212
+ "log.client.json_rpc.rename_channel.failed": "RENAME_CHANNEL for {channel_address} failed: Unable to decode json: {reason}",
213
+ "log.client.json_rpc.rename_device.failed": "RENAME_DEVICE for {device_address} failed: Unable to decode json: {reason}",
214
+ "log.client.json_rpc.set_system_variable.value_contains_html": "SET_SYSTEM_VARIABLE: Value ({value}) contains html tags. These are filtered out when writing.",
215
+ "log.client.json_rpc.trigger_firmware_update.failed": "TRIGGER_FIRMWARE_UPDATE failed: Unable to decode json: {reason}",
216
+ "log.client.json_rpc.trigger_firmware_update.not_triggered": "TRIGGER_FIRMWARE_UPDATE: {message}",
217
+ "log.client.json_rpc.trigger_firmware_update.success": "TRIGGER_FIRMWARE_UPDATE: {message}",
218
+ "log.client.reconnect.reconnected": "RECONNECT: re-connected client {interface_id}",
219
+ "log.client.update_device_firmware.result": "UPDATE_DEVICE_FIRMWARE: Executed firmware update for {device_address} with result '{result}'",
220
+ "log.client.update_device_firmware.try": "UPDATE_DEVICE_FIRMWARE: Trying firmware update for {device_address}",
221
+ "log.core.signal.shutdown": "Got signal: {sig}. Shutting down central",
222
+ "log.metrics.observer.counter_key_limit": "METRICS OBSERVER: Counter key limit reached, dropping: {metric_key}",
223
+ "log.metrics.observer.gauge_key_limit": "METRICS OBSERVER: Gauge key limit reached, dropping: {metric_key}",
224
+ "log.metrics.observer.latency_key_limit": "METRICS OBSERVER: Latency key limit reached, dropping: {metric_key}",
225
+ "log.model.custom.definition.validate_failed": "The custom data point definition could not be validated. {path}, {msg}",
226
+ "log.model.custom.text_display.send_text.burst_limit_warning": "SEND_TEXT: {full_name}: Burst limit warning active - command may be rate-limited",
227
+ "log.model.device.channel_description_not_found": "INIT_DEVICE: Skipping channel {address} - description could not be retrieved from CCU",
228
+ "log.model.generic_data_point.send_value.not_writable": "SEND_VALUE: writing to non-writable data_point {full_name} is not possible",
229
+ "log.model.hub.update.progress_completed": "Hub firmware update completed: {old_version} -> {new_version}",
230
+ "log.model.hub.update.progress_poll_error": "Error polling update status (CCU may be rebooting): {error}",
231
+ "log.model.hub.update.progress_timeout": "Hub firmware update monitoring timed out after {timeout}s",
232
+ "log.store.dynamic.pending_pong_mismatch": "Pending PONG mismatch: There is a mismatch between send ping events and received pong events for instance {interface_id}. Possible reason 1: You are running multiple instances with the same instance name configured for this integration. Re-add one instance! Otherwise this instance will not receive update events from your CCU. Possible reason 2: Something is stuck on the CCU or hasn't been cleaned up. Therefore, try a CCU restart. Possible reason 3: Your setup is misconfigured and this instance is not able to receive events from the CCU.",
233
+ "log.store.dynamic.unknown_pong_mismatch": "Unknown PONG Mismatch: Your instance {interface_id} receives PONG events, that it hasn't send. Possible reason 1: You are running multiple instances with the same instance name configured for this integration. Re-add one instance! Otherwise the other instance will not receive update events from your CCU. Possible reason 2: Something is stuck on the CCU or hasn't been cleaned up. Therefore, try a CCU restart.",
234
+ "log.store.session_recorder.activate.already_running": "ACTIVATE: Recording session is already running.",
235
+ "log.store.session_recorder.deactivate.already_running": "DEACTIVATE: Recording session is already running.",
236
+ "log.support.check_password.invalid_chars": "CHECK_CONFIG: password contains not allowed characters. Use only allowed characters. See password regex: {pattern}"
237
+ }