conson-xp 1.49.0__py3-none-any.whl → 1.50.1__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.
- {conson_xp-1.49.0.dist-info → conson_xp-1.50.1.dist-info}/METADATA +2 -1
- {conson_xp-1.49.0.dist-info → conson_xp-1.50.1.dist-info}/RECORD +14 -16
- xp/__init__.py +1 -1
- xp/cli/commands/conbus/conbus_actiontable_commands.py +4 -13
- xp/cli/commands/conbus/conbus_export_commands.py +86 -0
- xp/cli/commands/conbus/conbus_msactiontable_commands.py +56 -13
- xp/models/actiontable/actiontable_type.py +13 -0
- xp/services/conbus/actiontable/actiontable_upload_service.py +99 -19
- xp/services/conbus/conbus_export_actiontable_service.py +308 -0
- xp/services/conbus/conbus_export_service.py +5 -2
- xp/utils/dependencies.py +5 -35
- xp/cli/utils/xp_module_type.py +0 -55
- xp/services/conbus/msactiontable/__init__.py +0 -1
- xp/services/conbus/msactiontable/msactiontable_upload_service.py +0 -332
- {conson_xp-1.49.0.dist-info → conson_xp-1.50.1.dist-info}/WHEEL +0 -0
- {conson_xp-1.49.0.dist-info → conson_xp-1.50.1.dist-info}/entry_points.txt +0 -0
- {conson_xp-1.49.0.dist-info → conson_xp-1.50.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: conson-xp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.50.1
|
|
4
4
|
Summary: XP Protocol Communication Tools
|
|
5
5
|
Author-Email: ldvchosal <ldvchosal@github.com>
|
|
6
6
|
License: MIT License
|
|
@@ -353,6 +353,7 @@ xp conbus event raw
|
|
|
353
353
|
|
|
354
354
|
|
|
355
355
|
xp conbus export
|
|
356
|
+
xp conbus export actiontable
|
|
356
357
|
xp conbus export config
|
|
357
358
|
|
|
358
359
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
conson_xp-1.
|
|
2
|
-
conson_xp-1.
|
|
3
|
-
conson_xp-1.
|
|
4
|
-
conson_xp-1.
|
|
5
|
-
xp/__init__.py,sha256=
|
|
1
|
+
conson_xp-1.50.1.dist-info/METADATA,sha256=bCbYqnE9XZK73a4laFt68XxyWDTPC-MlmxJa99Y7JTc,11432
|
|
2
|
+
conson_xp-1.50.1.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
|
|
3
|
+
conson_xp-1.50.1.dist-info/entry_points.txt,sha256=1OcdIcDM1hz3ljCXgybaPUh1IOFEwkaTgLIW9u9zGeg,50
|
|
4
|
+
conson_xp-1.50.1.dist-info/licenses/LICENSE,sha256=rxj6woMM-r3YCyGq_UHFtbh7kHTAJgrccH6O-33IDE4,1419
|
|
5
|
+
xp/__init__.py,sha256=hEOsOLZ2VP2s9c4Fqe0rpmfu56_wnujnc7Wf3f0xDGI,182
|
|
6
6
|
xp/cli/__init__.py,sha256=QjnKB1KaI2aIyKlzrnvCwfbBuUj8HNgwNMvNJVQofbI,81
|
|
7
7
|
xp/cli/__main__.py,sha256=l2iKwMdat5rTGd3JWs-uGksnYYDDffp_Npz05QdKEeU,117
|
|
8
8
|
xp/cli/commands/__init__.py,sha256=G7A1KFRSV0CEeDTqr_khu-K9_sc01CTI2KSfkFcaBRM,4949
|
|
9
9
|
xp/cli/commands/conbus/__init__.py,sha256=HYaX2__XxwD3Xaw4CzflvL8CwoUa4yR6wOyH8wwyofM,535
|
|
10
10
|
xp/cli/commands/conbus/conbus.py,sha256=GpWq1QS3mKfQFG77nTED-_hsvcnXb3ZIrC6DhfyhzBE,3538
|
|
11
|
-
xp/cli/commands/conbus/conbus_actiontable_commands.py,sha256=
|
|
11
|
+
xp/cli/commands/conbus/conbus_actiontable_commands.py,sha256=EpyLG_6RxhIQY4BWxDXTyo8yzpBwbHfZDOgmRl--R5w,7378
|
|
12
12
|
xp/cli/commands/conbus/conbus_autoreport_commands.py,sha256=dO3rxgII_xZVhbkxlMqTJCarrUveQCs_7-qf4li0UkQ,3962
|
|
13
13
|
xp/cli/commands/conbus/conbus_blink_commands.py,sha256=1zLiXV8Nn4XSDI-z7F3f2RN2IO-yxeMkGQ1PCknAkWY,5398
|
|
14
14
|
xp/cli/commands/conbus/conbus_config_commands.py,sha256=jeZi7J973DrDCyP59Qrvk6tonduj97KnV4fq9zbei2k,721
|
|
@@ -16,11 +16,11 @@ xp/cli/commands/conbus/conbus_custom_commands.py,sha256=TqWo45yqEp_ezmKZ0tymQ0C4
|
|
|
16
16
|
xp/cli/commands/conbus/conbus_datapoint_commands.py,sha256=uYsvi37vl2od2XJB0semAF0sH3UrRWTt_qHnBmUBR-w,3788
|
|
17
17
|
xp/cli/commands/conbus/conbus_discover_commands.py,sha256=gSK5Y4lespNKFNgGtp7VkqStGe4fWxDNNfyPPuJiwXQ,1931
|
|
18
18
|
xp/cli/commands/conbus/conbus_event_commands.py,sha256=faaSGRNtJCttk-0VO5Z4m4Zz37aOsSgmbuzWbTOUZIQ,3103
|
|
19
|
-
xp/cli/commands/conbus/conbus_export_commands.py,sha256
|
|
19
|
+
xp/cli/commands/conbus/conbus_export_commands.py,sha256=epfoIC1C32IT7SMVxolUDm1xm2q7hz_kvs7Jct4W9FQ,5819
|
|
20
20
|
xp/cli/commands/conbus/conbus_lightlevel_commands.py,sha256=WH4ZQHxSbquPlAqd0uRxq8VR-sO4_AnfseMqaoPoGoA,7092
|
|
21
21
|
xp/cli/commands/conbus/conbus_linknumber_commands.py,sha256=3bkik8nHXY89XfzeUnKWmvKA70r4qJJ79j8FfLL4sL0,3556
|
|
22
22
|
xp/cli/commands/conbus/conbus_modulenumber_commands.py,sha256=fOIO0f85iDJBfGnRCEN8zK6j4i43uuF_9YKQc_nQ39A,3628
|
|
23
|
-
xp/cli/commands/conbus/conbus_msactiontable_commands.py,sha256=
|
|
23
|
+
xp/cli/commands/conbus/conbus_msactiontable_commands.py,sha256=oMHfrxDR9yj0Pvx92ZHnwYU3CZqwNNvfAfEoLuo_jhQ,11585
|
|
24
24
|
xp/cli/commands/conbus/conbus_output_commands.py,sha256=XMEMb5tM0ul7lwhwoo4QRgWprXZ31qswXBno8KCeFMo,5342
|
|
25
25
|
xp/cli/commands/conbus/conbus_raw_commands.py,sha256=o1dVZqiRw7J3_8Bge7DJucFyAqt7GNP-Azf-f3ir3SU,2019
|
|
26
26
|
xp/cli/commands/conbus/conbus_receive_commands.py,sha256=LdxoOUdM5atkC8fFlp-GK7HQ7oxTnjrSFDx-lQ3nme0,1925
|
|
@@ -54,11 +54,10 @@ xp/cli/utils/formatters.py,sha256=SN_kUkL4M7csay8eftnxoIPS_VvQDlqZueARNElyZZs,98
|
|
|
54
54
|
xp/cli/utils/module_type_choice.py,sha256=Hs0VFrssKWWGqfqBtSJPP7DDCzLyv-BfyeNIPC1WxyU,1672
|
|
55
55
|
xp/cli/utils/serial_number_type.py,sha256=-6MlAAPbpqaGx1Ds3vPPT3PU9hYJG4_C2SmytXV3VyI,1480
|
|
56
56
|
xp/cli/utils/system_function_choice.py,sha256=3YZrTtBHCw_f6KqqT41wJUiiPBVLAQufyPnrMkesdd0,1637
|
|
57
|
-
xp/cli/utils/xp_module_type.py,sha256=rCafAi8k0BNRqtQryoai2WW4zr51lCEY-VRS7asW7VA,1485
|
|
58
57
|
xp/models/__init__.py,sha256=lROqr559DGd8WpJJUtfPT95VERCwMZHpBDEc96QSxQ0,1312
|
|
59
58
|
xp/models/actiontable/__init__.py,sha256=6kVq1rTOlpc24sZxGGVWkY48tqR42YWHLQHqakWqlPc,43
|
|
60
59
|
xp/models/actiontable/actiontable.py,sha256=IAV3KhA5B4jNOHFvVQmhJQV3vbX7EOug2UNAJuTslvk,1258
|
|
61
|
-
xp/models/actiontable/actiontable_type.py,sha256=
|
|
60
|
+
xp/models/actiontable/actiontable_type.py,sha256=HjQ9Z-akdhMJaVx6fgyjqqFCAdFwQp0vO1YmSznlW1M,887
|
|
62
61
|
xp/models/actiontable/msactiontable_xp20.py,sha256=E2JQpZzWuAb_ZdFApzx80tqfF1qFjiO4zp-PtrRBYeQ,5034
|
|
63
62
|
xp/models/actiontable/msactiontable_xp24.py,sha256=WNtUmJVizyUs0RmG9EQW21tgiUB9ofqVQxrzEVpOjdk,9423
|
|
64
63
|
xp/models/actiontable/msactiontable_xp33.py,sha256=nM4v7jICY3woXV50ji02rBbMxAu6CNjydoh9QNAMsF4,11859
|
|
@@ -127,7 +126,7 @@ xp/services/conbus/actiontable/__init__.py,sha256=oD6vRk_Ye-eZ9s_hldAgtRJFu4mfAn
|
|
|
127
126
|
xp/services/conbus/actiontable/actiontable_download_service.py,sha256=ZTQCC1D9TLmyDu3b5GAO4VxUVGSr6HuqZI9fxHB1qW8,14992
|
|
128
127
|
xp/services/conbus/actiontable/actiontable_list_service.py,sha256=oTDSpBkp-MJeaF5bhRnwkSy3na55xqQ4e2ykJzbMCUo,3236
|
|
129
128
|
xp/services/conbus/actiontable/actiontable_show_service.py,sha256=WISY2VsmSlceGa5_9lpFO-gs5TnTjv6YidQksUjCapk,3058
|
|
130
|
-
xp/services/conbus/actiontable/actiontable_upload_service.py,sha256=
|
|
129
|
+
xp/services/conbus/actiontable/actiontable_upload_service.py,sha256=FaQzOSg8s2zUL5xz9qZY9fvzrdDosc3CoxkVDvNg2SU,13252
|
|
131
130
|
xp/services/conbus/conbus_blink_all_service.py,sha256=toDIZDXBGBYnEishcdnJrVzkmfPi7g5nCDXuyA_wFCs,8536
|
|
132
131
|
xp/services/conbus/conbus_blink_service.py,sha256=ggLuzeq_UsgCoxRxg2bsNs9p8Lw_shjsj-niRzb5dKk,7953
|
|
133
132
|
xp/services/conbus/conbus_custom_service.py,sha256=9OIRC2CG_rN96vbv_EZXf7BrX_abhqi5MZx0Se8fEhU,7826
|
|
@@ -136,13 +135,12 @@ xp/services/conbus/conbus_datapoint_service.py,sha256=WBQC42-6xuPWhMKKRtHtRzwEmV
|
|
|
136
135
|
xp/services/conbus/conbus_discover_service.py,sha256=mvqjHFMmEkQjHD9YDIk9gE8MowPMkOIJRmyjX96G5pw,12868
|
|
137
136
|
xp/services/conbus/conbus_event_list_service.py,sha256=-jl3WHpyidbh-h4NMK2gERqu48mTNFD6rpPo2EyGxeg,3641
|
|
138
137
|
xp/services/conbus/conbus_event_raw_service.py,sha256=viXuEXw165-RytdqC76wQShJLD7Yd0rtURxWZZ8hyKA,7060
|
|
139
|
-
xp/services/conbus/
|
|
138
|
+
xp/services/conbus/conbus_export_actiontable_service.py,sha256=_2bxmDVSpkGtepuQVbdYX2nwEnSm91GX9P9UzB_INDQ,11043
|
|
139
|
+
xp/services/conbus/conbus_export_service.py,sha256=RP8nADTIs4FGUf_BFLRZMtEJZdXV94zg3QrlWaDnhKA,17536
|
|
140
140
|
xp/services/conbus/conbus_output_service.py,sha256=e57bRkLgPnJuB8hkllNh0kgGkjPt9IK75tuBxd_bOkE,9361
|
|
141
141
|
xp/services/conbus/conbus_raw_service.py,sha256=OQuV521VOQraf2PGF2B9868vh7sDgmfc19YebrkZnyw,5844
|
|
142
142
|
xp/services/conbus/conbus_receive_service.py,sha256=TFf3W65brGsy6QZICpIs0Xy9bgqyL1vgQuhS_eHuIZs,5416
|
|
143
143
|
xp/services/conbus/conbus_scan_service.py,sha256=_Ka0OUDNYhDgZIR49Q0P5GTxJq6RcAAX2DVqEDdtb5U,6888
|
|
144
|
-
xp/services/conbus/msactiontable/__init__.py,sha256=rDYzumPSfcTjDADHxjE7bXQoeWtZTDGaYzFTYdVl_9g,42
|
|
145
|
-
xp/services/conbus/msactiontable/msactiontable_upload_service.py,sha256=LB9pv0VOUDmyTHKUcY894fmBAqINO7qpM8mW1E3s8aU,12423
|
|
146
144
|
xp/services/conbus/write_config_service.py,sha256=BCfmLNPRDpwSwRMRYJvx2FXA8IZsdgmyeTXIYvmb4ys,9004
|
|
147
145
|
xp/services/homekit/__init__.py,sha256=xAMKmln_AmEFdOOJGKWYi96seRlKDQpKx3-hm7XbdIo,36
|
|
148
146
|
xp/services/homekit/homekit_cache_service.py,sha256=z1TB6icEqd1paoilVTewuFL0lXVCQbvrOJkJvvQECJY,11060
|
|
@@ -200,10 +198,10 @@ xp/term/widgets/protocol_log.py,sha256=E68QmSMpOFrvrPTo_gOQVfyiDqY5c_y8fkNKnQw6V
|
|
|
200
198
|
xp/term/widgets/status_footer.py,sha256=YYAT0431p6jmrzzpVgaPhu7yGkRroWGv4e99t2XlkHI,3297
|
|
201
199
|
xp/utils/__init__.py,sha256=_avMF_UOkfR3tNeDIPqQ5odmbq5raKkaq1rZ9Cn1CJs,332
|
|
202
200
|
xp/utils/checksum.py,sha256=Px1S3dFGA-_plavBxrq3IqmprNlgtNDunE3whg6Otwg,1722
|
|
203
|
-
xp/utils/dependencies.py,sha256=
|
|
201
|
+
xp/utils/dependencies.py,sha256=dlSuKVmuA7AZlqINrQkZxfHuU8mzSHDZnMRRDzqjRAI,24067
|
|
204
202
|
xp/utils/event_helper.py,sha256=zD0K3TPfGEThU9vUNlDtglTai3Cmm30727iwjDZy6Dk,1007
|
|
205
203
|
xp/utils/logging.py,sha256=wJ1d-yg97NiZUrt2F8iDMcmnHVwC-PErcI-7dpyiRDc,3777
|
|
206
204
|
xp/utils/serialization.py,sha256=TS1OwpTOemSvXsCGw3js4JkYYFEqkzrPe8V9QYQefdw,4684
|
|
207
205
|
xp/utils/state_machine.py,sha256=W9AY4ntRZnFeHAa5d43hm37j53uJPlqkRvWTPiBhJ_0,2464
|
|
208
206
|
xp/utils/time_utils.py,sha256=K17godWpL18VEypbTlvNOEDG6R3huYnf29yjkcnwRpU,3796
|
|
209
|
-
conson_xp-1.
|
|
207
|
+
conson_xp-1.50.1.dist-info/RECORD,,
|
xp/__init__.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"""ActionTable CLI commands."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from contextlib import suppress
|
|
5
|
-
from pathlib import Path
|
|
6
4
|
|
|
7
5
|
import click
|
|
8
6
|
from click import Context
|
|
@@ -13,10 +11,9 @@ from xp.cli.utils.decorators import (
|
|
|
13
11
|
)
|
|
14
12
|
from xp.cli.utils.serial_number_type import SERIAL
|
|
15
13
|
from xp.models.actiontable.actiontable import ActionTable
|
|
16
|
-
from xp.models.actiontable.actiontable_type import ActionTableType
|
|
14
|
+
from xp.models.actiontable.actiontable_type import ActionTableType, ActionTableType2
|
|
17
15
|
from xp.models.config.conson_module_config import (
|
|
18
16
|
ConsonModuleConfig,
|
|
19
|
-
ConsonModuleListConfig,
|
|
20
17
|
)
|
|
21
18
|
from xp.services.conbus.actiontable.actiontable_download_service import (
|
|
22
19
|
ActionTableDownloadService,
|
|
@@ -164,18 +161,12 @@ def conbus_upload_actiontable(ctx: Context, serial_number: str) -> None:
|
|
|
164
161
|
|
|
165
162
|
with service:
|
|
166
163
|
# Load config to get entry count for success message
|
|
167
|
-
config_path = Path.cwd() / "conson.yml"
|
|
168
|
-
if config_path.exists():
|
|
169
|
-
with suppress(Exception):
|
|
170
|
-
config = ConsonModuleListConfig.from_yaml(str(config_path))
|
|
171
|
-
module = config.find_module(serial_number)
|
|
172
|
-
if module and module.action_table:
|
|
173
|
-
entries_count = len(module.action_table)
|
|
174
|
-
|
|
175
164
|
service.on_progress.connect(progress_callback)
|
|
176
165
|
service.on_finish.connect(on_finish)
|
|
177
166
|
service.on_error.connect(on_error)
|
|
178
|
-
service.start(
|
|
167
|
+
service.start(
|
|
168
|
+
serial_number=serial_number, actiontable_type=ActionTableType2.ACTIONTABLE
|
|
169
|
+
)
|
|
179
170
|
service.start_reactor()
|
|
180
171
|
|
|
181
172
|
|
|
@@ -6,8 +6,12 @@ import click
|
|
|
6
6
|
|
|
7
7
|
from xp.cli.commands.conbus.conbus import conbus_export
|
|
8
8
|
from xp.cli.utils.decorators import connection_command
|
|
9
|
+
from xp.models.actiontable.actiontable_type import ActionTableType
|
|
9
10
|
from xp.models.conbus.conbus_export import ConbusExportResponse
|
|
10
11
|
from xp.models.config.conson_module_config import ConsonModuleConfig
|
|
12
|
+
from xp.services.conbus.conbus_export_actiontable_service import (
|
|
13
|
+
ConbusActiontableExportService,
|
|
14
|
+
)
|
|
11
15
|
from xp.services.conbus.conbus_export_service import ConbusExportService
|
|
12
16
|
|
|
13
17
|
|
|
@@ -91,3 +95,85 @@ def export_conbus_config(ctx: click.Context) -> None:
|
|
|
91
95
|
service.on_finish.connect(on_finish)
|
|
92
96
|
service.set_timeout(5)
|
|
93
97
|
service.start_reactor()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@conbus_export.command("actiontable")
|
|
101
|
+
@click.pass_context
|
|
102
|
+
@connection_command()
|
|
103
|
+
def export_conbus_actiontable(ctx: click.Context) -> None:
|
|
104
|
+
r"""
|
|
105
|
+
Export Conbus device actiontable to YAML file.
|
|
106
|
+
|
|
107
|
+
Read device list from conson.yml
|
|
108
|
+
Export export.yml file in conson.yml format.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
ctx: Click context object.
|
|
112
|
+
|
|
113
|
+
Examples:
|
|
114
|
+
\b
|
|
115
|
+
# Export device metadata to export.yml
|
|
116
|
+
xp conbus export
|
|
117
|
+
xp conbus export actiontable
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
def on_progress(serial_number: str, current: int, total: int) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Handle progress updates during export.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
serial_number: Serial number of discovered device.
|
|
126
|
+
current: Current device number.
|
|
127
|
+
total: Total devices discovered.
|
|
128
|
+
"""
|
|
129
|
+
click.echo(f"Querying device {current}/{total}: {serial_number}...")
|
|
130
|
+
|
|
131
|
+
def on_device_actiontable_exported(
|
|
132
|
+
module: ConsonModuleConfig,
|
|
133
|
+
actiontable_type: ActionTableType,
|
|
134
|
+
actiontable_short: str,
|
|
135
|
+
) -> None:
|
|
136
|
+
"""
|
|
137
|
+
Handle device export completion.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
module: Exported module configuration.
|
|
141
|
+
actiontable_type: Type of action table exported.
|
|
142
|
+
actiontable_short: Short representation of the action table.
|
|
143
|
+
"""
|
|
144
|
+
serial_number = module.serial_number or "UNKNOWN"
|
|
145
|
+
click.echo(f" ✓ Module: {serial_number})")
|
|
146
|
+
click.echo(f" ✓ Action type: {actiontable_type}")
|
|
147
|
+
click.echo(f" ✓ Action table: {actiontable_short}")
|
|
148
|
+
|
|
149
|
+
def on_finish(result: ConbusExportResponse) -> None:
|
|
150
|
+
"""
|
|
151
|
+
Handle export completion.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
result: Export result.
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
ClickException: When export fails with error message from result.
|
|
158
|
+
"""
|
|
159
|
+
# Try to stop reactor (may already be stopped)
|
|
160
|
+
with suppress(Exception):
|
|
161
|
+
service.stop_reactor()
|
|
162
|
+
|
|
163
|
+
if result.success:
|
|
164
|
+
click.echo(
|
|
165
|
+
f"\nExport complete: {result.output_file} ({result.device_count} devices)"
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
click.echo(f"Error: {result.error}", err=True)
|
|
169
|
+
raise click.ClickException(result.error or "Export failed")
|
|
170
|
+
|
|
171
|
+
service: ConbusActiontableExportService = (
|
|
172
|
+
ctx.obj.get("container").get_container().resolve(ConbusActiontableExportService)
|
|
173
|
+
)
|
|
174
|
+
with service:
|
|
175
|
+
service.on_progress.connect(on_progress)
|
|
176
|
+
service.on_device_actiontable_exported.connect(on_device_actiontable_exported)
|
|
177
|
+
service.on_finish.connect(on_finish)
|
|
178
|
+
service.set_timeout(5)
|
|
179
|
+
service.start_reactor()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""XP24 Action Table CLI commands."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from typing import Any, Union
|
|
4
|
+
from typing import Any, Optional, Union
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
from click import Context
|
|
@@ -11,8 +11,7 @@ from xp.cli.utils.decorators import (
|
|
|
11
11
|
connection_command,
|
|
12
12
|
)
|
|
13
13
|
from xp.cli.utils.serial_number_type import SERIAL
|
|
14
|
-
from xp.
|
|
15
|
-
from xp.models.actiontable.actiontable_type import ActionTableType
|
|
14
|
+
from xp.models.actiontable.actiontable_type import ActionTableType, ActionTableType2
|
|
16
15
|
from xp.models.config.conson_module_config import ConsonModuleConfig
|
|
17
16
|
from xp.services.conbus.actiontable.actiontable_download_service import (
|
|
18
17
|
ActionTableDownloadService,
|
|
@@ -23,11 +22,59 @@ from xp.services.conbus.actiontable.actiontable_list_service import (
|
|
|
23
22
|
from xp.services.conbus.actiontable.actiontable_show_service import (
|
|
24
23
|
ActionTableShowService,
|
|
25
24
|
)
|
|
26
|
-
from xp.services.conbus.
|
|
27
|
-
|
|
25
|
+
from xp.services.conbus.actiontable.actiontable_upload_service import (
|
|
26
|
+
ActionTableUploadService,
|
|
28
27
|
)
|
|
29
28
|
|
|
30
29
|
|
|
30
|
+
class XpModuleTypeChoice(click.ParamType):
|
|
31
|
+
"""
|
|
32
|
+
Click parameter type for validating XP module types.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
name: The parameter type name.
|
|
36
|
+
choices: List of valid module type strings.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
name = "xpmoduletype"
|
|
40
|
+
|
|
41
|
+
def __init__(self) -> None:
|
|
42
|
+
"""Initialize the XpModuleTypeChoice parameter type."""
|
|
43
|
+
self.choices = ["xp20", "xp24", "xp31", "xp33"]
|
|
44
|
+
|
|
45
|
+
def convert(
|
|
46
|
+
self,
|
|
47
|
+
value: Any,
|
|
48
|
+
param: Optional[click.Parameter],
|
|
49
|
+
ctx: Optional[click.Context],
|
|
50
|
+
) -> Any:
|
|
51
|
+
"""
|
|
52
|
+
Convert and validate XP module type input.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
value: The input value to convert.
|
|
56
|
+
param: The Click parameter.
|
|
57
|
+
ctx: The Click context.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Lowercase module type string if valid, None if input is None.
|
|
61
|
+
"""
|
|
62
|
+
if value is None:
|
|
63
|
+
return value
|
|
64
|
+
normalized_value = value.lower()
|
|
65
|
+
if normalized_value in self.choices:
|
|
66
|
+
return normalized_value
|
|
67
|
+
choices_list = "\n".join(f" - {choice}" for choice in sorted(self.choices))
|
|
68
|
+
self.fail(
|
|
69
|
+
f"{value!r} is not a valid choice. Choose from:\n{choices_list}",
|
|
70
|
+
param,
|
|
71
|
+
ctx,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
XP_MODULE_TYPE = XpModuleTypeChoice()
|
|
76
|
+
|
|
77
|
+
|
|
31
78
|
def _get_actiontable_type(xpmoduletype: str) -> ActionTableType:
|
|
32
79
|
"""
|
|
33
80
|
Map xpmoduletype string to ActionTableType enum.
|
|
@@ -244,22 +291,18 @@ def conbus_show_msactiontable(ctx: Context, serial_number: str) -> None:
|
|
|
244
291
|
|
|
245
292
|
@conbus_msactiontable.command("upload", short_help="Upload MSActionTable")
|
|
246
293
|
@click.argument("serial_number", type=SERIAL)
|
|
247
|
-
@click.argument("xpmoduletype", type=XP_MODULE_TYPE)
|
|
248
294
|
@click.pass_context
|
|
249
295
|
@connection_command()
|
|
250
|
-
def conbus_upload_msactiontable(
|
|
251
|
-
ctx: Context, serial_number: str, xpmoduletype: str
|
|
252
|
-
) -> None:
|
|
296
|
+
def conbus_upload_msactiontable(ctx: Context, serial_number: str) -> None:
|
|
253
297
|
"""
|
|
254
298
|
Upload MS action table from conson.yml to XP module.
|
|
255
299
|
|
|
256
300
|
Args:
|
|
257
301
|
ctx: Click context object.
|
|
258
302
|
serial_number: 10-digit module serial number.
|
|
259
|
-
xpmoduletype: XP module type.
|
|
260
303
|
"""
|
|
261
|
-
service:
|
|
262
|
-
ctx.obj.get("container").get_container().resolve(
|
|
304
|
+
service: ActionTableUploadService = (
|
|
305
|
+
ctx.obj.get("container").get_container().resolve(ActionTableUploadService)
|
|
263
306
|
)
|
|
264
307
|
|
|
265
308
|
def on_progress(progress: str) -> None:
|
|
@@ -300,7 +343,7 @@ def conbus_upload_msactiontable(
|
|
|
300
343
|
service.on_finish.connect(on_finish)
|
|
301
344
|
service.start(
|
|
302
345
|
serial_number=serial_number,
|
|
303
|
-
|
|
346
|
+
actiontable_type=ActionTableType2.MSACTIONTABLE,
|
|
304
347
|
)
|
|
305
348
|
service.start_reactor()
|
|
306
349
|
|
|
@@ -18,3 +18,16 @@ class ActionTableType(str, Enum):
|
|
|
18
18
|
MSACTIONTABLE_XP20 = "msactiontable_xp20"
|
|
19
19
|
MSACTIONTABLE_XP24 = "msactiontable_xp24"
|
|
20
20
|
MSACTIONTABLE_XP33 = "msactiontable_xp33"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ActionTableType2(str, Enum):
|
|
24
|
+
"""
|
|
25
|
+
ActionTable types for download/upload operations.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
ACTIONTABLE: Standard action table.
|
|
29
|
+
MSACTIONTABLE: MS action table.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
ACTIONTABLE = "actiontable"
|
|
33
|
+
MSACTIONTABLE = "msactiontable"
|
|
@@ -5,18 +5,32 @@ from typing import Any, Optional
|
|
|
5
5
|
|
|
6
6
|
from psygnal import Signal
|
|
7
7
|
|
|
8
|
-
from xp.models.
|
|
8
|
+
from xp.models.actiontable.actiontable_type import ActionTableType2
|
|
9
|
+
from xp.models.config.conson_module_config import (
|
|
10
|
+
ConsonModuleConfig,
|
|
11
|
+
ConsonModuleListConfig,
|
|
12
|
+
)
|
|
9
13
|
from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
|
|
10
14
|
from xp.models.telegram.system_function import SystemFunction
|
|
11
15
|
from xp.models.telegram.telegram_type import TelegramType
|
|
12
16
|
from xp.services.actiontable.actiontable_serializer import ActionTableSerializer
|
|
17
|
+
from xp.services.actiontable.msactiontable_xp20_serializer import (
|
|
18
|
+
Xp20MsActionTableSerializer,
|
|
19
|
+
)
|
|
20
|
+
from xp.services.actiontable.msactiontable_xp24_serializer import (
|
|
21
|
+
Xp24MsActionTableSerializer,
|
|
22
|
+
)
|
|
23
|
+
from xp.services.actiontable.msactiontable_xp33_serializer import (
|
|
24
|
+
Xp33MsActionTableSerializer,
|
|
25
|
+
)
|
|
13
26
|
from xp.services.protocol.conbus_event_protocol import ConbusEventProtocol
|
|
14
27
|
from xp.services.telegram.telegram_service import TelegramService
|
|
15
28
|
|
|
16
29
|
|
|
17
30
|
class ActionTableUploadService:
|
|
18
31
|
"""
|
|
19
|
-
TCP client service for uploading action tables to Conbus
|
|
32
|
+
TCP client service for uploading action tables and MS action tables to Conbus
|
|
33
|
+
modules.
|
|
20
34
|
|
|
21
35
|
Manages TCP socket connections, handles telegram generation and transmission,
|
|
22
36
|
and processes server responses for action table uploads.
|
|
@@ -35,6 +49,9 @@ class ActionTableUploadService:
|
|
|
35
49
|
self,
|
|
36
50
|
conbus_protocol: ConbusEventProtocol,
|
|
37
51
|
actiontable_serializer: ActionTableSerializer,
|
|
52
|
+
xp20ms_serializer: Xp20MsActionTableSerializer,
|
|
53
|
+
xp24ms_serializer: Xp24MsActionTableSerializer,
|
|
54
|
+
xp33ms_serializer: Xp33MsActionTableSerializer,
|
|
38
55
|
telegram_service: TelegramService,
|
|
39
56
|
conson_config: ConsonModuleListConfig,
|
|
40
57
|
) -> None:
|
|
@@ -44,14 +61,22 @@ class ActionTableUploadService:
|
|
|
44
61
|
Args:
|
|
45
62
|
conbus_protocol: ConbusEventProtocol for communication.
|
|
46
63
|
actiontable_serializer: Action table serializer.
|
|
64
|
+
xp20ms_serializer: XP20 MS action table serializer.
|
|
65
|
+
xp24ms_serializer: XP24 MS action table serializer.
|
|
66
|
+
xp33ms_serializer: XP33 MS action table serializer.
|
|
47
67
|
telegram_service: Telegram service for parsing.
|
|
48
68
|
conson_config: Conson module list configuration.
|
|
49
69
|
"""
|
|
50
70
|
self.conbus_protocol = conbus_protocol
|
|
51
|
-
self.
|
|
71
|
+
self.actiontable_serializer = actiontable_serializer
|
|
72
|
+
self.xp20ms_serializer = xp20ms_serializer
|
|
73
|
+
self.xp24ms_serializer = xp24ms_serializer
|
|
74
|
+
self.xp33ms_serializer = xp33ms_serializer
|
|
52
75
|
self.telegram_service = telegram_service
|
|
53
76
|
self.conson_config = conson_config
|
|
54
77
|
self.serial_number: str = ""
|
|
78
|
+
self.xpmoduletype: str = ""
|
|
79
|
+
self.actiontable_type: ActionTableType2 = ActionTableType2.ACTIONTABLE
|
|
55
80
|
|
|
56
81
|
# Upload state
|
|
57
82
|
self.upload_data_chunks: list[str] = []
|
|
@@ -70,10 +95,17 @@ class ActionTableUploadService:
|
|
|
70
95
|
def connection_made(self) -> None:
|
|
71
96
|
"""Handle connection established event."""
|
|
72
97
|
self.logger.debug("Connection established, sending upload actiontable telegram")
|
|
98
|
+
|
|
99
|
+
system_function = (
|
|
100
|
+
SystemFunction.UPLOAD_ACTIONTABLE
|
|
101
|
+
if self.actiontable_type == ActionTableType2.ACTIONTABLE
|
|
102
|
+
else SystemFunction.UPLOAD_MSACTIONTABLE
|
|
103
|
+
)
|
|
104
|
+
|
|
73
105
|
self.conbus_protocol.send_telegram(
|
|
74
106
|
telegram_type=TelegramType.SYSTEM,
|
|
75
107
|
serial_number=self.serial_number,
|
|
76
|
-
system_function=
|
|
108
|
+
system_function=system_function,
|
|
77
109
|
data_value="00",
|
|
78
110
|
)
|
|
79
111
|
|
|
@@ -127,10 +159,16 @@ class ActionTableUploadService:
|
|
|
127
159
|
# Second character: 'A' + chunk_index (sequential counter A-O for 15 chunks)
|
|
128
160
|
prefix_hex = f"AAA{ord('A') + self.current_chunk_index:c}"
|
|
129
161
|
|
|
162
|
+
system_function = (
|
|
163
|
+
SystemFunction.ACTIONTABLE
|
|
164
|
+
if self.actiontable_type == ActionTableType2.ACTIONTABLE
|
|
165
|
+
else SystemFunction.MSACTIONTABLE
|
|
166
|
+
)
|
|
167
|
+
|
|
130
168
|
self.conbus_protocol.send_telegram(
|
|
131
169
|
telegram_type=TelegramType.SYSTEM,
|
|
132
170
|
serial_number=self.serial_number,
|
|
133
|
-
system_function=
|
|
171
|
+
system_function=system_function,
|
|
134
172
|
data_value=f"{prefix_hex}{chunk}",
|
|
135
173
|
)
|
|
136
174
|
self.current_chunk_index += 1
|
|
@@ -169,19 +207,24 @@ class ActionTableUploadService:
|
|
|
169
207
|
def start(
|
|
170
208
|
self,
|
|
171
209
|
serial_number: str,
|
|
210
|
+
actiontable_type: ActionTableType2,
|
|
172
211
|
timeout_seconds: Optional[float] = None,
|
|
173
212
|
) -> None:
|
|
174
213
|
"""
|
|
175
|
-
Upload action table to module.
|
|
214
|
+
Upload action table or MS action table to module.
|
|
176
215
|
|
|
177
216
|
Uploads the action table configuration to the specified module.
|
|
217
|
+
Module type will decide which actiontable to use.
|
|
178
218
|
|
|
179
219
|
Args:
|
|
180
220
|
serial_number: Module serial number.
|
|
221
|
+
actiontable_type: True if actionTable false for MS action table.
|
|
181
222
|
timeout_seconds: Optional timeout in seconds.
|
|
182
223
|
"""
|
|
183
224
|
self.logger.info("Starting actiontable upload")
|
|
184
225
|
self.serial_number = serial_number
|
|
226
|
+
self.actiontable_type = actiontable_type
|
|
227
|
+
|
|
185
228
|
if timeout_seconds:
|
|
186
229
|
self.conbus_protocol.timeout_seconds = timeout_seconds
|
|
187
230
|
|
|
@@ -193,29 +236,65 @@ class ActionTableUploadService:
|
|
|
193
236
|
|
|
194
237
|
# Parse action table strings to ActionTable object
|
|
195
238
|
try:
|
|
196
|
-
|
|
197
|
-
|
|
239
|
+
encoded_data = self.get_encoded_action_table(module)
|
|
240
|
+
# Chunk the data into 64 byte chunks
|
|
241
|
+
chunk_size = 64
|
|
242
|
+
self.upload_data_chunks = [
|
|
243
|
+
encoded_data[i : i + chunk_size]
|
|
244
|
+
for i in range(0, len(encoded_data), chunk_size)
|
|
245
|
+
]
|
|
246
|
+
self.current_chunk_index = 0
|
|
247
|
+
|
|
198
248
|
except ValueError as e:
|
|
199
249
|
self.logger.error(f"Invalid action table format: {e}")
|
|
200
250
|
self.failed(f"Invalid action table format: {e}")
|
|
201
251
|
return
|
|
202
252
|
|
|
203
|
-
# Encode action table to hex string
|
|
204
|
-
encoded_data = self.serializer.to_encoded_string(action_table)
|
|
205
|
-
|
|
206
|
-
# Chunk the data into 64 byte chunks
|
|
207
|
-
chunk_size = 64
|
|
208
|
-
self.upload_data_chunks = [
|
|
209
|
-
encoded_data[i : i + chunk_size]
|
|
210
|
-
for i in range(0, len(encoded_data), chunk_size)
|
|
211
|
-
]
|
|
212
|
-
self.current_chunk_index = 0
|
|
213
|
-
|
|
214
253
|
self.logger.debug(
|
|
215
254
|
f"Upload data encoded: {len(encoded_data)} chars, "
|
|
216
255
|
f"{len(self.upload_data_chunks)} chunks"
|
|
217
256
|
)
|
|
218
257
|
|
|
258
|
+
def get_encoded_action_table(self, module: ConsonModuleConfig) -> str:
|
|
259
|
+
"""
|
|
260
|
+
Get encoded action table string for upload.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
module: Module configuration containing action table data.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Hex-encoded action table string ready for transmission.
|
|
267
|
+
"""
|
|
268
|
+
msactiontable = (
|
|
269
|
+
True if self.actiontable_type == ActionTableType2.MSACTIONTABLE else False
|
|
270
|
+
)
|
|
271
|
+
# Parse MS action table from short format (first element)
|
|
272
|
+
if msactiontable and module.module_type.lower() == "xp20":
|
|
273
|
+
xp20_short_table = module.xp20_msaction_table or []
|
|
274
|
+
xp20_actiontable = self.xp20ms_serializer.from_short_string(
|
|
275
|
+
xp20_short_table
|
|
276
|
+
)
|
|
277
|
+
encoded_string = self.xp20ms_serializer.to_encoded_string(xp20_actiontable)
|
|
278
|
+
elif msactiontable and module.module_type.lower() == "xp24":
|
|
279
|
+
xp24_short_table = module.xp24_msaction_table or []
|
|
280
|
+
xp24_actiontable = self.xp24ms_serializer.from_short_string(
|
|
281
|
+
xp24_short_table
|
|
282
|
+
)
|
|
283
|
+
encoded_string = self.xp24ms_serializer.to_encoded_string(xp24_actiontable)
|
|
284
|
+
elif msactiontable and module.module_type.lower() == "xp33":
|
|
285
|
+
xp33_short_table = module.xp33_msaction_table or []
|
|
286
|
+
xp33_actiontable = self.xp33ms_serializer.from_short_string(
|
|
287
|
+
xp33_short_table
|
|
288
|
+
)
|
|
289
|
+
encoded_string = self.xp33ms_serializer.to_encoded_string(xp33_actiontable)
|
|
290
|
+
else:
|
|
291
|
+
short_table = module.action_table or []
|
|
292
|
+
actiontable = self.actiontable_serializer.from_short_string(short_table)
|
|
293
|
+
encoded_string = self.actiontable_serializer.to_encoded_string(actiontable)
|
|
294
|
+
|
|
295
|
+
# Serialize to telegram data (64 characters: AAAA + 64 data chars)
|
|
296
|
+
return encoded_string
|
|
297
|
+
|
|
219
298
|
def set_timeout(self, timeout_seconds: float) -> None:
|
|
220
299
|
"""
|
|
221
300
|
Set operation timeout.
|
|
@@ -243,6 +322,7 @@ class ActionTableUploadService:
|
|
|
243
322
|
self.upload_data_chunks = []
|
|
244
323
|
self.current_chunk_index = 0
|
|
245
324
|
self.serial_number = ""
|
|
325
|
+
self.xpmoduletype = ""
|
|
246
326
|
return self
|
|
247
327
|
|
|
248
328
|
def __exit__(self, _exc_type: Any, _exc_val: Any, _exc_tb: Any) -> None:
|