conson-xp 1.18.0__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 (176) hide show
  1. conson_xp-1.18.0.dist-info/METADATA +412 -0
  2. conson_xp-1.18.0.dist-info/RECORD +176 -0
  3. conson_xp-1.18.0.dist-info/WHEEL +4 -0
  4. conson_xp-1.18.0.dist-info/entry_points.txt +5 -0
  5. conson_xp-1.18.0.dist-info/licenses/LICENSE +29 -0
  6. xp/__init__.py +9 -0
  7. xp/cli/__init__.py +5 -0
  8. xp/cli/__main__.py +6 -0
  9. xp/cli/commands/__init__.py +153 -0
  10. xp/cli/commands/conbus/__init__.py +25 -0
  11. xp/cli/commands/conbus/conbus.py +128 -0
  12. xp/cli/commands/conbus/conbus_actiontable_commands.py +233 -0
  13. xp/cli/commands/conbus/conbus_autoreport_commands.py +108 -0
  14. xp/cli/commands/conbus/conbus_blink_commands.py +163 -0
  15. xp/cli/commands/conbus/conbus_config_commands.py +29 -0
  16. xp/cli/commands/conbus/conbus_custom_commands.py +57 -0
  17. xp/cli/commands/conbus/conbus_datapoint_commands.py +113 -0
  18. xp/cli/commands/conbus/conbus_discover_commands.py +61 -0
  19. xp/cli/commands/conbus/conbus_event_commands.py +81 -0
  20. xp/cli/commands/conbus/conbus_lightlevel_commands.py +207 -0
  21. xp/cli/commands/conbus/conbus_linknumber_commands.py +102 -0
  22. xp/cli/commands/conbus/conbus_modulenumber_commands.py +104 -0
  23. xp/cli/commands/conbus/conbus_msactiontable_commands.py +94 -0
  24. xp/cli/commands/conbus/conbus_output_commands.py +163 -0
  25. xp/cli/commands/conbus/conbus_raw_commands.py +62 -0
  26. xp/cli/commands/conbus/conbus_receive_commands.py +59 -0
  27. xp/cli/commands/conbus/conbus_scan_commands.py +58 -0
  28. xp/cli/commands/file_commands.py +186 -0
  29. xp/cli/commands/homekit/__init__.py +3 -0
  30. xp/cli/commands/homekit/homekit.py +118 -0
  31. xp/cli/commands/homekit/homekit_start_commands.py +43 -0
  32. xp/cli/commands/module_commands.py +187 -0
  33. xp/cli/commands/reverse_proxy_commands.py +178 -0
  34. xp/cli/commands/server/__init__.py +3 -0
  35. xp/cli/commands/server/server_commands.py +135 -0
  36. xp/cli/commands/telegram/__init__.py +5 -0
  37. xp/cli/commands/telegram/telegram.py +41 -0
  38. xp/cli/commands/telegram/telegram_blink_commands.py +79 -0
  39. xp/cli/commands/telegram/telegram_checksum_commands.py +112 -0
  40. xp/cli/commands/telegram/telegram_discover_commands.py +41 -0
  41. xp/cli/commands/telegram/telegram_linknumber_commands.py +86 -0
  42. xp/cli/commands/telegram/telegram_parse_commands.py +75 -0
  43. xp/cli/commands/telegram/telegram_version_commands.py +52 -0
  44. xp/cli/main.py +87 -0
  45. xp/cli/utils/__init__.py +1 -0
  46. xp/cli/utils/click_tree.py +57 -0
  47. xp/cli/utils/datapoint_type_choice.py +57 -0
  48. xp/cli/utils/decorators.py +351 -0
  49. xp/cli/utils/error_handlers.py +201 -0
  50. xp/cli/utils/formatters.py +312 -0
  51. xp/cli/utils/module_type_choice.py +56 -0
  52. xp/cli/utils/serial_number_type.py +52 -0
  53. xp/cli/utils/system_function_choice.py +57 -0
  54. xp/cli/utils/xp_module_type.py +53 -0
  55. xp/connection/__init__.py +13 -0
  56. xp/connection/exceptions.py +22 -0
  57. xp/models/__init__.py +36 -0
  58. xp/models/actiontable/__init__.py +1 -0
  59. xp/models/actiontable/actiontable.py +43 -0
  60. xp/models/actiontable/msactiontable_xp20.py +53 -0
  61. xp/models/actiontable/msactiontable_xp24.py +58 -0
  62. xp/models/actiontable/msactiontable_xp33.py +65 -0
  63. xp/models/conbus/__init__.py +1 -0
  64. xp/models/conbus/conbus.py +87 -0
  65. xp/models/conbus/conbus_autoreport.py +67 -0
  66. xp/models/conbus/conbus_blink.py +80 -0
  67. xp/models/conbus/conbus_client_config.py +55 -0
  68. xp/models/conbus/conbus_connection_status.py +40 -0
  69. xp/models/conbus/conbus_custom.py +58 -0
  70. xp/models/conbus/conbus_datapoint.py +89 -0
  71. xp/models/conbus/conbus_discover.py +64 -0
  72. xp/models/conbus/conbus_event_raw.py +47 -0
  73. xp/models/conbus/conbus_lightlevel.py +52 -0
  74. xp/models/conbus/conbus_linknumber.py +54 -0
  75. xp/models/conbus/conbus_output.py +57 -0
  76. xp/models/conbus/conbus_raw.py +45 -0
  77. xp/models/conbus/conbus_receive.py +42 -0
  78. xp/models/conbus/conbus_writeconfig.py +60 -0
  79. xp/models/homekit/__init__.py +1 -0
  80. xp/models/homekit/homekit_accessory.py +35 -0
  81. xp/models/homekit/homekit_config.py +106 -0
  82. xp/models/homekit/homekit_conson_config.py +86 -0
  83. xp/models/log_entry.py +130 -0
  84. xp/models/protocol/__init__.py +1 -0
  85. xp/models/protocol/conbus_protocol.py +312 -0
  86. xp/models/response.py +42 -0
  87. xp/models/telegram/__init__.py +1 -0
  88. xp/models/telegram/action_type.py +31 -0
  89. xp/models/telegram/datapoint_type.py +82 -0
  90. xp/models/telegram/event_telegram.py +140 -0
  91. xp/models/telegram/event_type.py +15 -0
  92. xp/models/telegram/input_action_type.py +69 -0
  93. xp/models/telegram/input_type.py +17 -0
  94. xp/models/telegram/module_type.py +188 -0
  95. xp/models/telegram/module_type_code.py +205 -0
  96. xp/models/telegram/output_telegram.py +103 -0
  97. xp/models/telegram/reply_telegram.py +297 -0
  98. xp/models/telegram/system_function.py +116 -0
  99. xp/models/telegram/system_telegram.py +94 -0
  100. xp/models/telegram/telegram.py +28 -0
  101. xp/models/telegram/telegram_type.py +19 -0
  102. xp/models/telegram/timeparam_type.py +51 -0
  103. xp/models/write_config_type.py +33 -0
  104. xp/services/__init__.py +26 -0
  105. xp/services/actiontable/__init__.py +1 -0
  106. xp/services/actiontable/actiontable_serializer.py +273 -0
  107. xp/services/actiontable/msactiontable_serializer.py +7 -0
  108. xp/services/actiontable/msactiontable_xp20_serializer.py +169 -0
  109. xp/services/actiontable/msactiontable_xp24_serializer.py +120 -0
  110. xp/services/actiontable/msactiontable_xp33_serializer.py +239 -0
  111. xp/services/conbus/__init__.py +1 -0
  112. xp/services/conbus/actiontable/__init__.py +1 -0
  113. xp/services/conbus/actiontable/actiontable_download_service.py +158 -0
  114. xp/services/conbus/actiontable/actiontable_list_service.py +91 -0
  115. xp/services/conbus/actiontable/actiontable_show_service.py +89 -0
  116. xp/services/conbus/actiontable/actiontable_upload_service.py +211 -0
  117. xp/services/conbus/actiontable/msactiontable_service.py +232 -0
  118. xp/services/conbus/conbus_blink_all_service.py +181 -0
  119. xp/services/conbus/conbus_blink_service.py +158 -0
  120. xp/services/conbus/conbus_custom_service.py +156 -0
  121. xp/services/conbus/conbus_datapoint_queryall_service.py +182 -0
  122. xp/services/conbus/conbus_datapoint_service.py +170 -0
  123. xp/services/conbus/conbus_discover_service.py +312 -0
  124. xp/services/conbus/conbus_event_raw_service.py +181 -0
  125. xp/services/conbus/conbus_output_service.py +194 -0
  126. xp/services/conbus/conbus_raw_service.py +122 -0
  127. xp/services/conbus/conbus_receive_service.py +115 -0
  128. xp/services/conbus/conbus_scan_service.py +150 -0
  129. xp/services/conbus/write_config_service.py +194 -0
  130. xp/services/homekit/__init__.py +1 -0
  131. xp/services/homekit/homekit_cache_service.py +307 -0
  132. xp/services/homekit/homekit_conbus_service.py +93 -0
  133. xp/services/homekit/homekit_config_validator.py +310 -0
  134. xp/services/homekit/homekit_conson_validator.py +121 -0
  135. xp/services/homekit/homekit_dimminglight.py +182 -0
  136. xp/services/homekit/homekit_dimminglight_service.py +148 -0
  137. xp/services/homekit/homekit_hap_service.py +342 -0
  138. xp/services/homekit/homekit_lightbulb.py +120 -0
  139. xp/services/homekit/homekit_lightbulb_service.py +86 -0
  140. xp/services/homekit/homekit_module_service.py +56 -0
  141. xp/services/homekit/homekit_outlet.py +168 -0
  142. xp/services/homekit/homekit_outlet_service.py +121 -0
  143. xp/services/homekit/homekit_service.py +359 -0
  144. xp/services/log_file_service.py +309 -0
  145. xp/services/module_type_service.py +257 -0
  146. xp/services/protocol/__init__.py +21 -0
  147. xp/services/protocol/conbus_event_protocol.py +360 -0
  148. xp/services/protocol/conbus_protocol.py +318 -0
  149. xp/services/protocol/protocol_factory.py +78 -0
  150. xp/services/protocol/telegram_protocol.py +264 -0
  151. xp/services/reverse_proxy_service.py +435 -0
  152. xp/services/server/__init__.py +1 -0
  153. xp/services/server/base_server_service.py +366 -0
  154. xp/services/server/cp20_server_service.py +65 -0
  155. xp/services/server/device_service_factory.py +94 -0
  156. xp/services/server/server_service.py +428 -0
  157. xp/services/server/xp130_server_service.py +67 -0
  158. xp/services/server/xp20_server_service.py +92 -0
  159. xp/services/server/xp230_server_service.py +58 -0
  160. xp/services/server/xp24_server_service.py +245 -0
  161. xp/services/server/xp33_server_service.py +535 -0
  162. xp/services/telegram/__init__.py +1 -0
  163. xp/services/telegram/telegram_blink_service.py +138 -0
  164. xp/services/telegram/telegram_checksum_service.py +149 -0
  165. xp/services/telegram/telegram_datapoint_service.py +82 -0
  166. xp/services/telegram/telegram_discover_service.py +277 -0
  167. xp/services/telegram/telegram_link_number_service.py +216 -0
  168. xp/services/telegram/telegram_output_service.py +322 -0
  169. xp/services/telegram/telegram_service.py +380 -0
  170. xp/services/telegram/telegram_version_service.py +288 -0
  171. xp/utils/__init__.py +12 -0
  172. xp/utils/checksum.py +61 -0
  173. xp/utils/dependencies.py +531 -0
  174. xp/utils/event_helper.py +31 -0
  175. xp/utils/serialization.py +205 -0
  176. xp/utils/time_utils.py +134 -0
xp/models/log_entry.py ADDED
@@ -0,0 +1,130 @@
1
+ """Log entry model for console bus communication logs."""
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Any, Optional, Union
6
+
7
+ from xp.models.telegram.event_telegram import EventTelegram
8
+ from xp.models.telegram.reply_telegram import ReplyTelegram
9
+ from xp.models.telegram.system_telegram import SystemTelegram
10
+
11
+
12
+ @dataclass
13
+ class LogEntry:
14
+ """Represents a single entry in a console bus log file.
15
+
16
+ Format: HH:MM:SS,mmm [TX/RX] <telegram>
17
+ Examples: 22:44:20,352 [TX] <S0012345008F27D00AAFN>
18
+
19
+ Attributes:
20
+ timestamp: Timestamp of the log entry.
21
+ direction: Direction of telegram ("TX" or "RX").
22
+ raw_telegram: Raw telegram string.
23
+ parsed_telegram: Parsed telegram object if successfully parsed.
24
+ parse_error: Error message if parsing failed.
25
+ line_number: Line number in the log file.
26
+ is_transmitted: True if this is a transmitted telegram.
27
+ is_received: True if this is a received telegram.
28
+ telegram_type: Telegram type (event, system, reply, unknown).
29
+ is_valid_parse: True if the telegram was successfully parsed.
30
+ checksum_validated: Checksum validation status if available.
31
+ """
32
+
33
+ timestamp: datetime
34
+ direction: str # "TX" or "RX"
35
+ raw_telegram: str
36
+ parsed_telegram: Optional[Union[EventTelegram, SystemTelegram, ReplyTelegram]] = (
37
+ None
38
+ )
39
+ parse_error: Optional[str] = None
40
+ line_number: int = 0
41
+
42
+ @property
43
+ def is_transmitted(self) -> bool:
44
+ """True if this is a transmitted telegram.
45
+
46
+ Returns:
47
+ True if direction is TX, False otherwise.
48
+ """
49
+ return self.direction == "TX"
50
+
51
+ @property
52
+ def is_received(self) -> bool:
53
+ """True if this is a received telegram.
54
+
55
+ Returns:
56
+ True if direction is RX, False otherwise.
57
+ """
58
+ return self.direction == "RX"
59
+
60
+ @property
61
+ def telegram_type(self) -> str:
62
+ """Get the telegram type (event, system, reply, unknown).
63
+
64
+ Returns:
65
+ Telegram type string.
66
+ """
67
+ if self.parsed_telegram is None:
68
+ return "unknown"
69
+
70
+ return self.parsed_telegram.telegram_type.value.lower()
71
+
72
+ @property
73
+ def is_valid_parse(self) -> bool:
74
+ """True if the telegram was successfully parsed.
75
+
76
+ Returns:
77
+ True if parsed without errors, False otherwise.
78
+ """
79
+ return self.parsed_telegram is not None and self.parse_error is None
80
+
81
+ @property
82
+ def checksum_validated(self) -> Optional[bool]:
83
+ """Get checksum validation status if available.
84
+
85
+ Returns:
86
+ Checksum validation status or None if not available.
87
+ """
88
+ if self.parsed_telegram and hasattr(self.parsed_telegram, "checksum_validated"):
89
+ return self.parsed_telegram.checksum_validated
90
+ return None
91
+
92
+ def to_dict(self) -> dict[str, Any]:
93
+ """Convert to dictionary for JSON serialization.
94
+
95
+ Returns:
96
+ Dictionary representation of the log entry.
97
+ """
98
+ result: dict[str, Any] = {
99
+ "line_number": self.line_number,
100
+ "timestamp": self.timestamp.strftime("%H:%M:%S.%f")[
101
+ :-3
102
+ ], # HH:MM:SS,mmm format
103
+ "direction": self.direction,
104
+ "raw_telegram": self.raw_telegram,
105
+ "telegram_type": self.telegram_type,
106
+ "is_valid_parse": self.is_valid_parse,
107
+ "parse_error": self.parse_error,
108
+ }
109
+
110
+ # Add parsed telegram data if available
111
+ if self.parsed_telegram:
112
+ result["parsed"] = self.parsed_telegram.to_dict()
113
+ result["checksum_validated"] = self.checksum_validated
114
+
115
+ return result
116
+
117
+ def __str__(self) -> str:
118
+ """Human-readable string representation.
119
+
120
+ Returns:
121
+ Formatted string representation of the log entry.
122
+ """
123
+ timestamp_str = self.timestamp.strftime("%H:%M:%S,%f")[:-3] # HH:MM:SS,mmm
124
+ status = "✓" if self.is_valid_parse else "✗"
125
+ checksum_status = ""
126
+
127
+ if self.checksum_validated is not None:
128
+ checksum_status = f" ({('✓' if self.checksum_validated else '✗')})"
129
+
130
+ return f"[{self.line_number:3d}] {timestamp_str} [{self.direction}] {self.raw_telegram} {status}{checksum_status}"
@@ -0,0 +1 @@
1
+ """Protocol models and interfaces."""
@@ -0,0 +1,312 @@
1
+ """Conbus protocol event models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Union
6
+
7
+ from bubus import BaseEvent
8
+ from pydantic import Field
9
+
10
+ from xp.models.homekit.homekit_config import HomekitAccessoryConfig
11
+ from xp.models.homekit.homekit_conson_config import ConsonModuleConfig
12
+ from xp.models.telegram.datapoint_type import DataPointType
13
+
14
+ if TYPE_CHECKING:
15
+ from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
16
+ from xp.services.protocol.conbus_protocol import ConbusProtocol
17
+ from xp.services.protocol.telegram_protocol import TelegramProtocol
18
+
19
+
20
+ class ConnectionMadeEvent(BaseEvent):
21
+ """Event dispatched when TCP connection is established.
22
+
23
+ Attributes:
24
+ protocol: Reference to the TelegramProtocol instance.
25
+ """
26
+
27
+ protocol: TelegramProtocol = Field(
28
+ description="Reference to the TelegramProtocol instance"
29
+ )
30
+
31
+
32
+ class ConnectionFailedEvent(BaseEvent):
33
+ """Event dispatched when TCP connection fails.
34
+
35
+ Attributes:
36
+ reason: Failure reason.
37
+ """
38
+
39
+ reason: str = Field(description="Failure reason")
40
+
41
+
42
+ class SendWriteConfigEvent(BaseEvent):
43
+ """Event for sending write config commands.
44
+
45
+ Attributes:
46
+ serial_number: Serial number.
47
+ output_number: Output number.
48
+ datapoint_type: Datapoint type.
49
+ value: Set brightness value.
50
+ """
51
+
52
+ serial_number: str = Field(description="Serial number")
53
+ output_number: int = Field(description="Output number")
54
+ datapoint_type: DataPointType = Field(description="Datapoint type")
55
+ value: int = Field(description="Set brightness value")
56
+
57
+
58
+ class SendActionEvent(BaseEvent):
59
+ """Event for sending action commands.
60
+
61
+ Attributes:
62
+ serial_number: Serial number of the light bulb set.
63
+ output_number: Output number of the light bulb set.
64
+ value: Set light bulb On or Off (True/False).
65
+ on_action: On action E00L00I00.
66
+ off_action: On action E00L00I04.
67
+ """
68
+
69
+ serial_number: str = Field(description="Serial number of the light bulb set")
70
+ output_number: int = Field(description="Output number of the light bulb set")
71
+ value: bool = Field(description="Set light bulb On or Off (True/False)")
72
+ on_action: str = Field(description="on action")
73
+ off_action: str = Field(description="off action")
74
+
75
+
76
+ class DatapointEvent(BaseEvent):
77
+ """Base event for datapoint operations.
78
+
79
+ Attributes:
80
+ serial_number: Serial number of the light bulb set.
81
+ datapoint_type: Datapoint type.
82
+ """
83
+
84
+ serial_number: str = Field(description="Serial number of the light bulb set")
85
+ datapoint_type: DataPointType = Field(description="Datapoint type")
86
+
87
+
88
+ class OutputStateReceivedEvent(DatapointEvent):
89
+ """Event when output state is received.
90
+
91
+ Attributes:
92
+ data_value: Data value.
93
+ """
94
+
95
+ data_value: str = Field(description="Data value")
96
+
97
+
98
+ class LightLevelReceivedEvent(DatapointEvent):
99
+ """Event when light level is received.
100
+
101
+ Attributes:
102
+ data_value: Data value.
103
+ """
104
+
105
+ data_value: str = Field(description="Data value")
106
+
107
+
108
+ class ReadDatapointEvent(DatapointEvent):
109
+ """Event to read datapoint.
110
+
111
+ Attributes:
112
+ refresh_cache: If True, force cache invalidation and fresh protocol query.
113
+ """
114
+
115
+ refresh_cache: bool = Field(
116
+ default=False,
117
+ description="If True, force cache invalidation and fresh protocol query",
118
+ )
119
+
120
+
121
+ class ReadDatapointFromProtocolEvent(DatapointEvent):
122
+ """Internal event for cache service to forward to protocol when cache misses."""
123
+
124
+ pass
125
+
126
+
127
+ class ModuleEvent(BaseEvent):
128
+ """Event dispatched when light bulb set is on.
129
+
130
+ Attributes:
131
+ serial_number: Serial number of the light bulb set.
132
+ output_number: Output number of the light bulb set.
133
+ module: ConsonModuleConfig of the light bulb set.
134
+ accessory: HomekitAccessoryConfig of the light bulb set.
135
+ """
136
+
137
+ serial_number: str = Field(description="Serial number of the light bulb set")
138
+ output_number: int = Field(description="Output number of the light bulb set")
139
+ module: ConsonModuleConfig = Field(
140
+ description="ConsonModuleConfig of the light bulb set"
141
+ )
142
+ accessory: HomekitAccessoryConfig = Field(
143
+ description="HomekitAccessoryConfig of the light bulb set"
144
+ )
145
+
146
+
147
+ class LightBulbSetOnEvent(ModuleEvent):
148
+ """Event dispatched when light bulb set is on.
149
+
150
+ Attributes:
151
+ value: On or Off the light bulb set.
152
+ """
153
+
154
+ value: bool = Field(description="On or Off the light bulb set")
155
+
156
+
157
+ class LightBulbGetOnEvent(ModuleEvent, BaseEvent[bool]):
158
+ """Event dispatched when getting light bulb on state."""
159
+
160
+ pass
161
+
162
+
163
+ class OutletSetOnEvent(ModuleEvent):
164
+ """Event dispatched when outlet set is on.
165
+
166
+ Attributes:
167
+ value: On or Off the light bulb set.
168
+ """
169
+
170
+ value: bool = Field(description="On or Off the light bulb set")
171
+
172
+
173
+ class OutletGetOnEvent(ModuleEvent):
174
+ """Event dispatched when getting outlet on state."""
175
+
176
+ pass
177
+
178
+
179
+ class OutletGetInUseEvent(ModuleEvent):
180
+ """Event dispatched when getting outlet in-use state."""
181
+
182
+ pass
183
+
184
+
185
+ class OutletSetInUseEvent(ModuleEvent, BaseEvent[bool]):
186
+ """Event dispatched when outlet set is on.
187
+
188
+ Attributes:
189
+ value: On or Off the light bulb set.
190
+ """
191
+
192
+ value: bool = Field(description="On or Off the light bulb set")
193
+
194
+
195
+ class DimmingLightSetOnEvent(ModuleEvent):
196
+ """Event dispatched when dimming light set is on.
197
+
198
+ Attributes:
199
+ value: On or Off the light bulb set.
200
+ brightness: Brightness of the light bulb set.
201
+ """
202
+
203
+ value: bool = Field(description="On or Off the light bulb set")
204
+ brightness: int = Field(description="Brightness of the light bulb set")
205
+
206
+
207
+ class DimmingLightGetOnEvent(ModuleEvent):
208
+ """Event dispatched when getting dimming light on state."""
209
+
210
+ pass
211
+
212
+
213
+ class DimmingLightSetBrightnessEvent(ModuleEvent):
214
+ """Event dispatched when dimming light set is on.
215
+
216
+ Attributes:
217
+ brightness: Level of brightness of the dimming light.
218
+ """
219
+
220
+ brightness: int = Field(description="Level of brightness of the dimming light")
221
+
222
+
223
+ class DimmingLightGetBrightnessEvent(ModuleEvent):
224
+ """Event dispatched when getting dimming light brightness."""
225
+
226
+ pass
227
+
228
+
229
+ class ConnectionLostEvent(BaseEvent):
230
+ """Event dispatched when TCP connection is lost.
231
+
232
+ Attributes:
233
+ reason: Disconnection reason.
234
+ """
235
+
236
+ reason: str = Field(description="Disconnection reason")
237
+
238
+
239
+ class TelegramEvent(BaseEvent):
240
+ """Event for telegram operations.
241
+
242
+ Attributes:
243
+ protocol: TelegramProtocol instance.
244
+ frame: Frame <S0123450001F02D12FK>.
245
+ telegram: Telegram S0123450001F02D12FK.
246
+ payload: Payload S0123450001F02D12.
247
+ telegram_type: Telegram type S.
248
+ serial_number: Serial number 0123450001 or empty.
249
+ checksum: Checksum FK.
250
+ checksum_valid: Checksum valid true or false.
251
+ """
252
+
253
+ protocol: Union[TelegramProtocol, ConbusProtocol, ConbusEventProtocol] = Field(
254
+ description="TelegramProtocol instance"
255
+ )
256
+ frame: str = Field(description="Frame <S0123450001F02D12FK>")
257
+ telegram: str = Field(description="Telegram: S0123450001F02D12FK")
258
+ payload: str = Field(description="Payload: S0123450001F02D12")
259
+ telegram_type: str = Field(description="Telegram type: S")
260
+ serial_number: str = Field(description="Serial number: 0123450001 or empty")
261
+ checksum: str = Field(description="Checksum: FK")
262
+ checksum_valid: bool = Field(
263
+ default=True, description="Checksum valid: true, or false"
264
+ )
265
+
266
+
267
+ class ModuleStateChangedEvent(BaseEvent):
268
+ """Event dispatched when a module's state changes (from event telegram).
269
+
270
+ Attributes:
271
+ module_type_code: Module type code from event telegram.
272
+ link_number: Link number from event telegram.
273
+ input_number: Input number that triggered the event.
274
+ telegram_event_type: Event type (M=press, B=release).
275
+ """
276
+
277
+ module_type_code: int = Field(description="Module type code from event telegram")
278
+ link_number: int = Field(description="Link number from event telegram")
279
+ input_number: int = Field(description="Input number that triggered the event")
280
+ telegram_event_type: str = Field(description="Event type (M=press, B=release)")
281
+
282
+
283
+ class EventTelegramReceivedEvent(TelegramEvent):
284
+ """Event telegram received."""
285
+
286
+ pass
287
+
288
+
289
+ class ModuleDiscoveredEvent(TelegramEvent):
290
+ """Event dispatched when module is discovered."""
291
+
292
+ pass
293
+
294
+
295
+ class TelegramReceivedEvent(TelegramEvent):
296
+ """Event dispatched when a telegram frame is received."""
297
+
298
+ pass
299
+
300
+
301
+ class InvalidTelegramReceivedEvent(BaseEvent):
302
+ """Event dispatched when an invalid telegram frame is received.
303
+
304
+ Attributes:
305
+ protocol: TelegramProtocol instance.
306
+ frame: Frame <S0123450001F02D12FK>.
307
+ error: Error with the received telegram.
308
+ """
309
+
310
+ protocol: TelegramProtocol = Field(description="TelegramProtocol instance")
311
+ frame: str = Field(description="Frame <S0123450001F02D12FK>")
312
+ error: str = Field(description="Error with the received telegram")
xp/models/response.py ADDED
@@ -0,0 +1,42 @@
1
+ """Response model for structured service responses.
2
+
3
+ This module provides the Response class used throughout the application
4
+ for consistent service response formatting.
5
+ """
6
+
7
+ from datetime import datetime
8
+ from typing import Any, Optional
9
+
10
+
11
+ class Response:
12
+ """Standard response model for service operations.
13
+
14
+ Provides consistent structure for all service responses including
15
+ success status, data payload, error messages, and timestamp.
16
+ """
17
+
18
+ def __init__(self, success: bool, data: Any, error: Optional[str] = None):
19
+ """Initialize response.
20
+
21
+ Args:
22
+ success: Whether the operation was successful
23
+ data: Response data payload
24
+ error: Error message if operation failed
25
+ """
26
+ self.success = success
27
+ self.data = data
28
+ self.error = error
29
+ self.timestamp = datetime.now()
30
+
31
+ def to_dict(self) -> dict:
32
+ """Convert response to dictionary for JSON serialization.
33
+
34
+ Returns:
35
+ Dictionary representation of the response
36
+ """
37
+ return {
38
+ "success": self.success,
39
+ "data": self.data,
40
+ "error": self.error,
41
+ "timestamp": self.timestamp.isoformat(),
42
+ }
@@ -0,0 +1 @@
1
+ """Telegram models for console bus communication."""
@@ -0,0 +1,31 @@
1
+ """Action type enumeration for XP24 telegrams."""
2
+
3
+ from enum import Enum
4
+ from typing import Optional
5
+
6
+
7
+ class ActionType(Enum):
8
+ """Action types for XP24 telegrams.
9
+
10
+ Attributes:
11
+ OFF_PRESS: Make action (activate relay).
12
+ ON_RELEASE: Break action (deactivate relay).
13
+ """
14
+
15
+ OFF_PRESS = "AA" # Make action (activate relay)
16
+ ON_RELEASE = "AB" # Break action (deactivate relay)
17
+
18
+ @classmethod
19
+ def from_code(cls, code: str) -> Optional["ActionType"]:
20
+ """Get ActionType from code string.
21
+
22
+ Args:
23
+ code: Action code string.
24
+
25
+ Returns:
26
+ ActionType instance if found, None otherwise.
27
+ """
28
+ for action in cls:
29
+ if action.value == code:
30
+ return action
31
+ return None
@@ -0,0 +1,82 @@
1
+ """Datapoint type enumeration for system telegrams."""
2
+
3
+ from enum import Enum
4
+ from typing import Optional
5
+
6
+
7
+ class DataPointType(str, Enum):
8
+ """Data point types for system telegrams.
9
+
10
+ Attributes:
11
+ MODULE_TYPE: Module type (XP24, XP33, etc).
12
+ HW_VERSION: Hardware version information.
13
+ SW_VERSION: Software version information.
14
+ SERIAL_NUMBER: Serial number.
15
+ LINK_NUMBER: Link number.
16
+ MODULE_NUMBER: Module number.
17
+ SYSTEM_TYPE: System type.
18
+ MODULE_TYPE_CODE: Module type code.
19
+ MODULE_TYPE_ID: Module type ID.
20
+ MODULE_STATE: Module state.
21
+ MODULE_ERROR_CODE: Status query data point.
22
+ MODULE_INPUT_STATE: Module input state.
23
+ MODULE_OUTPUT_STATE: Channel states (XP33).
24
+ MODULE_FW_CRC: Module firmware CRC.
25
+ MODULE_ACTION_TABLE_CRC: Module action table CRC.
26
+ MODULE_LIGHT_LEVEL: Module light level.
27
+ MODULE_OPERATING_HOURS: Module operating hours.
28
+ MODULE_ENERGY_LEVEL: Current data point.
29
+ TEMPERATURE: Temperature data point.
30
+ SW_TOP_VERSION: Software top version.
31
+ VOLTAGE: Voltage data point.
32
+ AUTO_REPORT_STATUS: Auto report status.
33
+ """
34
+
35
+ MODULE_TYPE = "00" # Module type (XP24, XP33, ..)
36
+ HW_VERSION = "01" # Hardware version information
37
+ SW_VERSION = "02" # Software version information
38
+ SERIAL_NUMBER = "03" # Serial number
39
+ LINK_NUMBER = "04" # Link number
40
+ MODULE_NUMBER = "05" # Module number
41
+ SYSTEM_TYPE = "06" # System type
42
+ MODULE_TYPE_CODE = "07" # Module type code
43
+ MODULE_TYPE_ID = "08" # Module type id
44
+ MODULE_STATE = "09" # Module state
45
+ MODULE_ERROR_CODE = "10" # Status query data point
46
+ MODULE_INPUT_STATE = "11" # Module input state
47
+ MODULE_OUTPUT_STATE = "12" # Channel states (XP33)
48
+ MODULE_FW_CRC = "13" # Module Firmware CRC
49
+ MODULE_ACTION_TABLE_CRC = "14" # Module Action Table CRC
50
+
51
+ # XP24 00:000[%],01:000[%],02:000[%],03:000[%]
52
+ # XP33 00:000[%],01:000[%],02:000[%]
53
+ MODULE_LIGHT_LEVEL = "15" # Module Light Level
54
+
55
+ # XP24 00:000[H],01:000[H],02:000[H],03:000[H]
56
+ MODULE_OPERATING_HOURS = "16" # Module Operating Hours
57
+
58
+ # XP24 00:00000[NA],01:00000[NA],02:00000[NA],03:00000[NA]
59
+ MODULE_ENERGY_LEVEL = "17" # Current data point
60
+
61
+ # XP24 +34,0C
62
+ # XP33 -20,0C
63
+ TEMPERATURE = "18" # Temperature data point
64
+
65
+ SW_TOP_VERSION = "19" # Software Top Version
66
+ VOLTAGE = "20" # VOLTAGE data point
67
+ AUTO_REPORT_STATUS = "21" # Auto Report Status
68
+
69
+ @classmethod
70
+ def from_code(cls, code: str) -> Optional["DataPointType"]:
71
+ """Get DataPointType from code string.
72
+
73
+ Args:
74
+ code: Datapoint type code string.
75
+
76
+ Returns:
77
+ DataPointType instance if found, None otherwise.
78
+ """
79
+ for dp_type in cls:
80
+ if dp_type.value == code:
81
+ return dp_type
82
+ return None