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
@@ -0,0 +1,62 @@
1
+ """Conbus raw telegram CLI commands."""
2
+
3
+ import json
4
+
5
+ import click
6
+ from click import Context
7
+
8
+ from xp.cli.commands.conbus.conbus import conbus
9
+ from xp.cli.utils.decorators import (
10
+ connection_command,
11
+ )
12
+ from xp.models.conbus.conbus_raw import ConbusRawResponse
13
+ from xp.services.conbus.conbus_raw_service import ConbusRawService
14
+
15
+
16
+ @conbus.command("raw")
17
+ @click.argument("raw_telegrams")
18
+ @click.pass_context
19
+ @connection_command()
20
+ def send_raw_telegrams(ctx: Context, raw_telegrams: str) -> None:
21
+ r"""Send raw telegram sequence to Conbus server.
22
+
23
+ Accepts a string containing one or more telegrams in format <...>.
24
+ Multiple telegrams should be concatenated without separators.
25
+
26
+ Args:
27
+ ctx: Click context object.
28
+ raw_telegrams: Raw telegram string(s).
29
+
30
+ Examples:
31
+ \b
32
+ xp conbus raw '<S2113010000F02D12>'
33
+ xp conbus raw '<S2113010000F02D12><S2113010001F02D12><S2113010002F02D12>'
34
+ xp conbus raw '<S0012345003F02D12FM>...<S0012345009F02D12FF>'
35
+ """
36
+ service: ConbusRawService = (
37
+ ctx.obj.get("container").get_container().resolve(ConbusRawService)
38
+ )
39
+
40
+ def on_progress(message: str) -> None:
41
+ """Handle progress updates during raw telegram sending.
42
+
43
+ Args:
44
+ message: Progress message string.
45
+ """
46
+ click.echo(message)
47
+
48
+ def on_finish(service_response: ConbusRawResponse) -> None:
49
+ """Handle successful completion of raw telegram sending.
50
+
51
+ Args:
52
+ service_response: Raw response object.
53
+ """
54
+ click.echo(json.dumps(service_response.to_dict(), indent=2))
55
+
56
+ with service:
57
+ service.send_raw_telegram(
58
+ raw_input=raw_telegrams,
59
+ progress_callback=on_progress,
60
+ finish_callback=on_finish,
61
+ timeout_seconds=5.0,
62
+ )
@@ -0,0 +1,59 @@
1
+ """Conbus receive telegrams CLI commands."""
2
+
3
+ import json
4
+
5
+ import click
6
+ from click import Context
7
+
8
+ from xp.cli.commands.conbus.conbus import conbus
9
+ from xp.cli.utils.decorators import (
10
+ connection_command,
11
+ )
12
+ from xp.models.conbus.conbus_receive import ConbusReceiveResponse
13
+ from xp.services.conbus.conbus_receive_service import (
14
+ ConbusReceiveService,
15
+ )
16
+
17
+
18
+ @conbus.command("receive")
19
+ @click.argument("timeout", type=click.FLOAT, default=2.0)
20
+ @connection_command()
21
+ @click.pass_context
22
+ def receive_telegrams(ctx: Context, timeout: float) -> None:
23
+ r"""Receive waiting event telegrams from Conbus server.
24
+
25
+ Connects to the Conbus server and receives any waiting event telegrams
26
+ without sending any data first. Useful for collecting pending notifications
27
+ or events from the server.
28
+
29
+ Args:
30
+ ctx: Click context object.
31
+ timeout: Timeout in seconds for receiving telegrams (default: 2.0).
32
+
33
+ Examples:
34
+ \b
35
+ xp conbus receive
36
+ xp conbus receive 5.0
37
+ """
38
+
39
+ def on_finish(response_received: ConbusReceiveResponse) -> None:
40
+ """Handle successful completion of telegram receive operation.
41
+
42
+ Args:
43
+ response_received: Receive response object with telegrams.
44
+ """
45
+ click.echo(json.dumps(response_received.to_dict(), indent=2))
46
+
47
+ def progress(telegram_received: str) -> None:
48
+ """Handle progress updates during telegram receive operation.
49
+
50
+ Args:
51
+ telegram_received: Received telegram string.
52
+ """
53
+ click.echo(telegram_received)
54
+
55
+ service: ConbusReceiveService = (
56
+ ctx.obj.get("container").get_container().resolve(ConbusReceiveService)
57
+ )
58
+ with service:
59
+ service.start(progress, on_finish, timeout)
@@ -0,0 +1,58 @@
1
+ """Conbus client operations CLI commands."""
2
+
3
+ import json
4
+
5
+ import click
6
+ from click import Context
7
+
8
+ from xp.cli.commands.conbus.conbus import conbus
9
+ from xp.cli.utils.decorators import connection_command
10
+ from xp.cli.utils.serial_number_type import SERIAL
11
+ from xp.models import ConbusResponse
12
+ from xp.services.conbus.conbus_scan_service import ConbusScanService
13
+
14
+
15
+ @conbus.command("scan")
16
+ @click.argument("serial_number", type=SERIAL)
17
+ @click.argument("function_code", type=str)
18
+ @click.pass_context
19
+ @connection_command()
20
+ def scan_module(ctx: Context, serial_number: str, function_code: str) -> None:
21
+ r"""Scan all datapoints of a function_code for a module.
22
+
23
+ Args:
24
+ ctx: Click context object.
25
+ serial_number: 10-digit module serial number.
26
+ function_code: Function code.
27
+
28
+ Examples:
29
+ \b
30
+ xp conbus scan 0012345011 02 # Scan all datapoints of function Read data points (02)
31
+ """
32
+ service: ConbusScanService = (
33
+ ctx.obj.get("container").get_container().resolve(ConbusScanService)
34
+ )
35
+
36
+ def on_progress(progress: str) -> None:
37
+ """Handle progress updates during module scan.
38
+
39
+ Args:
40
+ progress: Progress message string.
41
+ """
42
+ click.echo(progress)
43
+
44
+ def on_finish(service_response: ConbusResponse) -> None:
45
+ """Handle successful completion of module scan.
46
+
47
+ Args:
48
+ service_response: Scan response object.
49
+ """
50
+ click.echo(json.dumps(service_response.to_dict(), indent=2))
51
+
52
+ with service:
53
+ service.scan_module(
54
+ serial_number=serial_number,
55
+ function_code=function_code,
56
+ progress_callback=on_progress,
57
+ finish_callback=on_finish,
58
+ )
@@ -0,0 +1,186 @@
1
+ """File operations CLI commands for console bus logs."""
2
+
3
+ import json
4
+
5
+ import click
6
+ from click import Context
7
+ from click_help_colors import HelpColorsGroup
8
+
9
+ from xp.cli.utils.decorators import (
10
+ file_operation_command,
11
+ handle_service_errors,
12
+ )
13
+ from xp.cli.utils.error_handlers import CLIErrorHandler
14
+ from xp.cli.utils.formatters import OutputFormatter, StatisticsFormatter
15
+
16
+
17
+ @click.group(
18
+ cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
19
+ )
20
+ def file() -> None:
21
+ """Perform file operations for console bus logs."""
22
+ pass
23
+
24
+
25
+ @file.command("decode")
26
+ @click.argument("log_file_path")
27
+ @click.option("--summary", is_flag=True, help="Show summary statistics only")
28
+ @click.pass_context
29
+ @file_operation_command()
30
+ @handle_service_errors(Exception)
31
+ def decode_log_file(
32
+ ctx: Context,
33
+ log_file_path: str,
34
+ filter_type: str,
35
+ filter_direction: str,
36
+ time_range: str,
37
+ summary: bool,
38
+ ) -> None:
39
+ r"""Decode and parse console bus log file.
40
+
41
+ Args:
42
+ ctx: Click context object.
43
+ log_file_path: Path to the log file to decode.
44
+ filter_type: Filter by telegram type.
45
+ filter_direction: Filter by telegram direction.
46
+ time_range: Filter by time range.
47
+ summary: Show summary statistics only.
48
+
49
+ Examples:
50
+ \b
51
+ xp file decode conbus.log
52
+
53
+ Raises:
54
+ SystemExit: If time range is invalid or log file cannot be parsed.
55
+ """
56
+ from xp.services.log_file_service import LogFileService
57
+ from xp.utils.time_utils import TimeParsingError, parse_time_range
58
+
59
+ service: LogFileService = (
60
+ ctx.obj.get("container").get_container().resolve(LogFileService)
61
+ )
62
+ StatisticsFormatter(True)
63
+
64
+ try:
65
+ # Parse the log file
66
+ entries = service.parse_log_file(log_file_path)
67
+
68
+ # Apply filters
69
+ if filter_type or filter_direction or time_range:
70
+ start_time = None
71
+ end_time = None
72
+
73
+ if time_range:
74
+ try:
75
+ start_time, end_time = parse_time_range(time_range)
76
+ except TimeParsingError as e:
77
+ error_response = OutputFormatter(True).error_response(
78
+ f"Invalid time range: {e}"
79
+ )
80
+ click.echo(error_response)
81
+ raise SystemExit(1)
82
+
83
+ entries = service.filter_entries(
84
+ entries,
85
+ telegram_type=filter_type,
86
+ direction=filter_direction,
87
+ start_time=start_time,
88
+ end_time=end_time,
89
+ )
90
+
91
+ # Generate statistics
92
+ stats = service.get_file_statistics(entries)
93
+
94
+ if summary:
95
+ # Show summary only
96
+ click.echo(
97
+ json.dumps({"statistics": stats, "entry_count": len(entries)}, indent=2)
98
+ )
99
+ else:
100
+ # Show full results
101
+ output = {
102
+ "file_path": log_file_path,
103
+ "statistics": stats,
104
+ "entries": [entry.to_dict() for entry in entries],
105
+ }
106
+ click.echo(json.dumps(output, indent=2))
107
+
108
+ except Exception as e:
109
+ CLIErrorHandler.handle_file_error(e, log_file_path, "log file parsing")
110
+
111
+
112
+ @file.command("analyze")
113
+ @click.argument("log_file_path")
114
+ @click.pass_context
115
+ @handle_service_errors(Exception)
116
+ def analyze_log_file(ctx: Context, log_file_path: str) -> None:
117
+ r"""Analyze console bus log file for patterns and statistics.
118
+
119
+ Args:
120
+ ctx: Click context object.
121
+ log_file_path: Path to the log file to analyze.
122
+
123
+ Examples:
124
+ \b
125
+ xp file analyze conbus.log
126
+ """
127
+ from xp.services.log_file_service import LogFileService
128
+
129
+ service: LogFileService = (
130
+ ctx.obj.get("container").get_container().resolve(LogFileService)
131
+ )
132
+ StatisticsFormatter(True)
133
+
134
+ try:
135
+ entries = service.parse_log_file(log_file_path)
136
+ stats = service.get_file_statistics(entries)
137
+
138
+ click.echo(
139
+ json.dumps({"file_path": log_file_path, "analysis": stats}, indent=2)
140
+ )
141
+
142
+ except Exception as e:
143
+ CLIErrorHandler.handle_file_error(e, log_file_path, "log file analysis")
144
+
145
+
146
+ @file.command("validate")
147
+ @click.argument("log_file_path")
148
+ @click.pass_context
149
+ @handle_service_errors(Exception)
150
+ def validate_log_file(ctx: Context, log_file_path: str) -> None:
151
+ r"""Validate console bus log file format and telegram checksums.
152
+
153
+ Args:
154
+ ctx: Click context object.
155
+ log_file_path: Path to the log file to validate.
156
+
157
+ Examples:
158
+ \b
159
+ xp file validate conbus.log
160
+ """
161
+ from xp.services.log_file_service import LogFileService
162
+
163
+ service: LogFileService = (
164
+ ctx.obj.get("container").get_container().resolve(LogFileService)
165
+ )
166
+ OutputFormatter(True)
167
+
168
+ try:
169
+ entries = service.parse_log_file(log_file_path)
170
+ stats = service.get_file_statistics(entries)
171
+
172
+ is_valid = stats["parse_errors"] == 0
173
+ checksum_issues = stats["checksum_validation"]["invalid_checksums"]
174
+
175
+ result = {
176
+ "file_path": log_file_path,
177
+ "valid_format": is_valid,
178
+ "parse_errors": stats["parse_errors"],
179
+ "checksum_issues": checksum_issues,
180
+ "statistics": stats,
181
+ "success": is_valid and checksum_issues == 0,
182
+ }
183
+ click.echo(json.dumps(result, indent=2))
184
+
185
+ except Exception as e:
186
+ CLIErrorHandler.handle_file_error(e, log_file_path, "log file validation")
@@ -0,0 +1,3 @@
1
+ """HomeKit CLI commands package."""
2
+
3
+ __all__ = []
@@ -0,0 +1,118 @@
1
+ """HomeKit management CLI commands."""
2
+
3
+ import click
4
+ from click_help_colors import HelpColorsGroup
5
+
6
+ from xp.cli.utils.decorators import service_command
7
+
8
+
9
+ @click.group(
10
+ cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
11
+ )
12
+ def homekit() -> None:
13
+ """Manage the HomeKit server for XP Protocol operations."""
14
+ pass
15
+
16
+
17
+ @homekit.group(
18
+ cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
19
+ )
20
+ def config() -> None:
21
+ """Manage HomeKit configuration."""
22
+ pass
23
+
24
+
25
+ @config.command()
26
+ @click.option(
27
+ "--conson-config",
28
+ default="conson.yml",
29
+ help="Path to conson.yml configuration file",
30
+ )
31
+ @click.option(
32
+ "--homekit-config",
33
+ default="homekit.yml",
34
+ help="Path to homekit.yml configuration file",
35
+ )
36
+ @service_command()
37
+ def validate(conson_config: str, homekit_config: str) -> None:
38
+ """Validate homekit.yml and conson.yml coherence.
39
+
40
+ Args:
41
+ conson_config: Path to conson.yml configuration file.
42
+ homekit_config: Path to homekit.yml configuration file.
43
+ """
44
+ from xp.services.homekit.homekit_config_validator import ConfigValidationService
45
+
46
+ try:
47
+ validator = ConfigValidationService(conson_config, homekit_config)
48
+ results = validator.validate_all()
49
+
50
+ if results["is_valid"]:
51
+ click.echo(click.style("✓ Configuration validation passed", fg="green"))
52
+ else:
53
+ click.echo(
54
+ click.style(
55
+ f"✗ Configuration validation failed with {results['total_errors']} errors",
56
+ fg="red",
57
+ )
58
+ )
59
+
60
+ if results["conson_errors"]:
61
+ click.echo(
62
+ click.style("\nConson Configuration Errors:", fg="red", bold=True)
63
+ )
64
+ for error in results["conson_errors"]:
65
+ click.echo(f" - {error}")
66
+
67
+ if results["homekit_errors"]:
68
+ click.echo(
69
+ click.style("\nHomeKit Configuration Errors:", fg="red", bold=True)
70
+ )
71
+ for error in results["homekit_errors"]:
72
+ click.echo(f" - {error}")
73
+
74
+ if results["cross_reference_errors"]:
75
+ click.echo(
76
+ click.style("\nCross-Reference Errors:", fg="red", bold=True)
77
+ )
78
+ for error in results["cross_reference_errors"]:
79
+ click.echo(f" - {error}")
80
+
81
+ exit(1)
82
+
83
+ except Exception as e:
84
+ click.echo(click.style(f"✗ Validation failed: {e}", fg="red"))
85
+ exit(1)
86
+
87
+
88
+ @config.command("show")
89
+ @click.option(
90
+ "--conson-config",
91
+ default="conson.yml",
92
+ help="Path to conson.yml configuration file",
93
+ )
94
+ @click.option(
95
+ "--homekit-config",
96
+ default="homekit.yml",
97
+ help="Path to homekit.yml configuration file",
98
+ )
99
+ @service_command()
100
+ def show_config(conson_config: str, homekit_config: str) -> None:
101
+ """Display parsed configuration summary.
102
+
103
+ Args:
104
+ conson_config: Path to conson.yml configuration file.
105
+ homekit_config: Path to homekit.yml configuration file.
106
+ """
107
+ from xp.services.homekit.homekit_config_validator import ConfigValidationService
108
+
109
+ try:
110
+ validator = ConfigValidationService(conson_config, homekit_config)
111
+ summary = validator.print_config_summary()
112
+
113
+ click.echo(click.style("Configuration Summary:", fg="blue", bold=True))
114
+ click.echo(summary)
115
+
116
+ except Exception as e:
117
+ click.echo(click.style(f"✗ Failed to load configuration: {e}", fg="red"))
118
+ exit(1)
@@ -0,0 +1,43 @@
1
+ """API server start command."""
2
+
3
+ import sys
4
+
5
+ import click
6
+ from click import Context
7
+
8
+ from xp.cli.commands.homekit.homekit import homekit
9
+ from xp.services.homekit.homekit_service import HomeKitService
10
+
11
+
12
+ @homekit.command("start")
13
+ @click.pass_context
14
+ def homekit_start(ctx: Context) -> None:
15
+ r"""Start the HomeKit server.
16
+
17
+ This command starts the XP Protocol HomeKit server using HAP-python.
18
+ The server provides HomeKit endpoints for Conbus operations.
19
+
20
+ Args:
21
+ ctx: Click context object.
22
+
23
+ Examples:
24
+ \b
25
+ # Start server on default host and port
26
+ xp homekit start
27
+ """
28
+ click.echo("Starting XP Protocol HomeKit server...")
29
+
30
+ try:
31
+ service: HomeKitService = (
32
+ ctx.obj.get("container").get_container().resolve(HomeKitService)
33
+ )
34
+ service.start() # Blocking call - reactor.run() never returns
35
+
36
+ except KeyboardInterrupt:
37
+ click.echo("\nShutting down server...")
38
+ except Exception as e:
39
+ click.echo(
40
+ click.style(f"Error starting server: {e}", fg="red"),
41
+ err=True,
42
+ )
43
+ sys.exit(1)