conson-xp 0.11.16__py3-none-any.whl → 0.11.21__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: conson-xp
3
- Version: 0.11.16
3
+ Version: 0.11.21
4
4
  Summary: XP Protocol Communication Tools
5
5
  Author-Email: ldvchosal <ldvchosal@github.com>
6
6
  License: MIT License
@@ -1,8 +1,8 @@
1
- conson_xp-0.11.16.dist-info/METADATA,sha256=8ERF_5ZRjF38qTZxaozeb8ujHtlg4Nkl2i3Qee4bh6Y,9298
2
- conson_xp-0.11.16.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- conson_xp-0.11.16.dist-info/entry_points.txt,sha256=1OcdIcDM1hz3ljCXgybaPUh1IOFEwkaTgLIW9u9zGeg,50
4
- conson_xp-0.11.16.dist-info/licenses/LICENSE,sha256=rxj6woMM-r3YCyGq_UHFtbh7kHTAJgrccH6O-33IDE4,1419
5
- xp/__init__.py,sha256=BjREecd5tmeQ3KDa23xjW_YpWm394_yXdoLcIruGLIE,177
1
+ conson_xp-0.11.21.dist-info/METADATA,sha256=HwBfLHuKhBtOi-5wmg081HGTAng6BXa2E8W-hkfzkXU,9298
2
+ conson_xp-0.11.21.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
+ conson_xp-0.11.21.dist-info/entry_points.txt,sha256=1OcdIcDM1hz3ljCXgybaPUh1IOFEwkaTgLIW9u9zGeg,50
4
+ conson_xp-0.11.21.dist-info/licenses/LICENSE,sha256=rxj6woMM-r3YCyGq_UHFtbh7kHTAJgrccH6O-33IDE4,1419
5
+ xp/__init__.py,sha256=Yo_o4SM3_458AZhuCwUhwwY3C5xsGcGv2-pF3Z-8Fhs,177
6
6
  xp/api/__init__.py,sha256=fCWjkuTzDlyJ8hIpU_QEBNcah3BB2bqVSfZwmP4ee5k,51
7
7
  xp/api/main.py,sha256=8OMXUYKnpsqjjnLChokC_M0DXZy-whrxY2dU4QTvr8A,3389
8
8
  xp/api/models/__init__.py,sha256=Xl8j2qiHc-Vb8b1ZmNZaMj7RtMvk0G_2SOvMgQumYzs,54
@@ -17,23 +17,23 @@ xp/api/routers/conbus_output.py,sha256=U-i7kjZv7H6aE0O_8AcZIKZDJuYwU8XostEWoNccn
17
17
  xp/api/routers/errors.py,sha256=5vzpeTt0cPQZDHL5YgrYJUxMh4uI7IgUNFAvL0NpLKM,1267
18
18
  xp/cli/__init__.py,sha256=KWYwhOU46dNEerlc2i4FHsVR4Fxmt90Pw5L5i2v1Jqc,80
19
19
  xp/cli/__main__.py,sha256=l2iKwMdat5rTGd3JWs-uGksnYYDDffp_Npz05QdKEeU,117
20
- xp/cli/commands/__init__.py,sha256=_Ia9P0gK7tCeiWbuU7p8RPgvBhQx1kFC6i3b1g1UuOo,4482
20
+ xp/cli/commands/__init__.py,sha256=dJ_VaOojg14vdx4OwxbDH-egJd16h3uT7f5DSQX4ZB0,4459
21
21
  xp/cli/commands/api.py,sha256=d9uD5NnDV807suEK6eLzJSl62TGTtFSwIA_foPc6wtg,340
22
22
  xp/cli/commands/api_start_commands.py,sha256=q9yOkiIY-NmRD04pq3N6rRe-BjnrcMRZmai8Jg5TKhA,3116
23
23
  xp/cli/commands/conbus/__init__.py,sha256=gE3K5OEoXkkZX8UOc2v3nreQQzwkOQi7n0VZ-Z2juXA,495
24
24
  xp/cli/commands/conbus/conbus.py,sha256=fVLbAg0kuodUdx9RfE4vVR3L_bc8liDP2cOEyup7ud0,2973
25
25
  xp/cli/commands/conbus/conbus_actiontable_commands.py,sha256=CjJKFTB_oHENKY165j0lQBBndf9S36K-ykogv7kSppQ,1436
26
26
  xp/cli/commands/conbus/conbus_autoreport_commands.py,sha256=EfCLZhuDu8uXDVGKE1eJ5Ji9mUauJLoGXqP4zFn2LhA,2501
27
- xp/cli/commands/conbus/conbus_blink_commands.py,sha256=gu8usX3_zdCKWXGvIH22yvlelWdtcGTQtbDY5pLIV9c,3061
27
+ xp/cli/commands/conbus/conbus_blink_commands.py,sha256=g2zGEXce2aTReCCNp7ph0-uI7YhWEgz_Z048-3YC36w,3696
28
28
  xp/cli/commands/conbus/conbus_config_commands.py,sha256=MBLt7Z95-v2Drvr80r4HQxx8PMmq9rA5odl60IF3j7A,897
29
29
  xp/cli/commands/conbus/conbus_custom_commands.py,sha256=NH8WDm31-7tb-KYH8nZprEXgo8a4asLWmNd0EgJVSHQ,1336
30
30
  xp/cli/commands/conbus/conbus_datapoint_commands.py,sha256=Ozc36DFKVfzDZyWU9xVdhebiYy8yodb_DgVKEpzK9Jg,2842
31
31
  xp/cli/commands/conbus/conbus_discover_commands.py,sha256=5HwuhlC3qyYJqLBuqQVyu5kr493BJOZ281V2pXtfoCY,961
32
- xp/cli/commands/conbus/conbus_lightlevel_commands.py,sha256=-0rkE6Y5XForr3WRYSuBT02JO2rXuXLYHkEwbMVNF14,3744
32
+ xp/cli/commands/conbus/conbus_lightlevel_commands.py,sha256=hMzQewTgqGNB6s_Pag2HNfImhpgXnitwUVgMM6XXJv8,4161
33
33
  xp/cli/commands/conbus/conbus_linknumber_commands.py,sha256=Q8hh222Gq7xDD-dRvwS4tiLQj3l913n-Vk1J73QxGGc,1954
34
34
  xp/cli/commands/conbus/conbus_msactiontable_commands.py,sha256=n1g-ZKjjjbCQqTPGCrcCB595QoRClv0DGvGEx8y7BAY,1728
35
35
  xp/cli/commands/conbus/conbus_output_commands.py,sha256=B_N31H4uBjahBxr6VNsj_bnsJsqkQc4CTIofDBKY4v8,2885
36
- xp/cli/commands/conbus/conbus_raw_commands.py,sha256=i9Ab_r7-iH6faaFesXV23PBBVRunC06pjTTTd6ufM3E,1858
36
+ xp/cli/commands/conbus/conbus_raw_commands.py,sha256=NRST1cg9tO7zVUwiTKqCBpwfwP1-yvnKTDrwwIMaz68,1572
37
37
  xp/cli/commands/conbus/conbus_receive_commands.py,sha256=jV5zAmiIKK3_oDpTs9yF1YklIRcJNvOrkI6O2deb1eQ,1380
38
38
  xp/cli/commands/conbus/conbus_scan_commands.py,sha256=HjZMhU1hPRuUSWMURB9UUeZt8aNMDlBYCktwrXUgsCY,4190
39
39
  xp/cli/commands/file_commands.py,sha256=YEkho5HU5-SEVqTKKWoYPYXI0qWDr9PZaAuEt8fIXak,4855
@@ -73,7 +73,7 @@ xp/models/actiontable/msactiontable_xp33.py,sha256=vYXJnyqnazUQ_6lkoDnDVh31bo-Mq
73
73
  xp/models/conbus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
74
  xp/models/conbus/conbus.py,sha256=Su2NKXizapeN3-mEMpCXDNii7TfZB3p3cAfWSmPpSC4,1763
75
75
  xp/models/conbus/conbus_autoreport.py,sha256=dx9CzlDwDWrLkyvfVsz4dKFouiCl4YcQ80rue97Zfbk,1652
76
- xp/models/conbus/conbus_blink.py,sha256=b1VpRS5cyYamrIdgu5af8UivUhh3Gx-duuuUx1OHgZg,1377
76
+ xp/models/conbus/conbus_blink.py,sha256=xwe8A-C1ywbLKYARRUwUEX0sq6QALQiv1C8R3RyQOSM,2196
77
77
  xp/models/conbus/conbus_client_config.py,sha256=HVaGZkhZI6cBpJaEgybq8TFARyrI9-dM6U6IPc2hOKQ,940
78
78
  xp/models/conbus/conbus_connection_status.py,sha256=YGrusHpc7cHEG4zU6j0yU-BTICqm0tyymQnblDO4C0Q,706
79
79
  xp/models/conbus/conbus_custom.py,sha256=hjzL7n5eIWfascyWNA2F6L3W5nnG4JgzAz2wL_chCyI,1322
@@ -118,18 +118,20 @@ xp/services/conbus/actiontable/msactiontable_service.py,sha256=89pxbUVlKd6mplpIe
118
118
  xp/services/conbus/actiontable/msactiontable_xp20_serializer.py,sha256=EYspooOdi0Z8oaXGxpazwnUoTmh-d7U9auhu11iBgmU,6527
119
119
  xp/services/conbus/actiontable/msactiontable_xp24_serializer.py,sha256=J_ve6uyMmsb_QT2Py1ciZngf4C0pfHpkbWFc8OL2QEk,3752
120
120
  xp/services/conbus/actiontable/msactiontable_xp33_serializer.py,sha256=AeGBbum5eIqlgVm9t4igfF6vyl-ACVpuzSUQm4TYfUQ,7962
121
- xp/services/conbus/conbus_autoreport_get_service.py,sha256=d97x_2AMq9BZsRS8ZvwN-LgdyNPzdDiyqjSqvWDqYjQ,4949
121
+ xp/services/conbus/conbus_autoreport_get_service.py,sha256=mNWFOt0-Ahx5N_Ayyq4oa-rdf2Xcu4rwz7erIjfdNBg,5206
122
122
  xp/services/conbus/conbus_autoreport_set_service.py,sha256=0fa2xGVE1GSoBvEcOH8cnjAdhvEoamvHE27t40f7lUk,4937
123
- xp/services/conbus/conbus_blink_service.py,sha256=fpNwy8FcE6Ve8SvHzV3JmBUrGoOUbieaNNVPDGzpoj4,7385
123
+ xp/services/conbus/conbus_blink_all_service.py,sha256=t_oaztEFRirjS3nL50AEBrKKpNXYssWwSBwWjWhhKqU,5959
124
+ xp/services/conbus/conbus_blink_service.py,sha256=mHaD-84RCmEGqD2cD4Ve85A36D08tMBPwMgDEyAEMCc,5031
124
125
  xp/services/conbus/conbus_connection_pool.py,sha256=uiuuZ1S2_BBg6sTWqWIStCPFnWJjsfi2PuD53DalPv8,5616
125
126
  xp/services/conbus/conbus_custom_service.py,sha256=jM6B085GTT8epCE9EqVTT8mZLPMXM3tVwvO-yJulJ5s,5290
126
127
  xp/services/conbus/conbus_datapoint_queryall_service.py,sha256=FBpFmwXVKoTiqMwQW-z2eYbamKL_ZGlTI86720ZcGt8,6095
127
128
  xp/services/conbus/conbus_datapoint_service.py,sha256=CspxjhEi8awX_dv6EpJpYjTtCsfLgjJ4ROl6jD1TOiY,5289
128
- xp/services/conbus/conbus_discover_service.py,sha256=j3WpzKxNMo971dEqZw4sg505gMdD_jPgpeRfurzd4_g,4281
129
- xp/services/conbus/conbus_lightlevel_service.py,sha256=Lfa1ruDDA4_M1103Ha-wSlGSjZmsGDpXuF22RfGBYDQ,7243
129
+ xp/services/conbus/conbus_discover_service.py,sha256=kA_ewxXgbqXng0cXBjSgQSGYesyesbN2wK0tMp1fgfc,4281
130
+ xp/services/conbus/conbus_lightlevel_get_service.py,sha256=vrr5HhR5l58oOezTz2rorO-RHoyGbVuHrx2rGfKvH20,5739
131
+ xp/services/conbus/conbus_lightlevel_set_service.py,sha256=6Mhq9xjWx-ixGVfcWBcJSnuYT256m8Lps1g8Tg-1nkM,7483
130
132
  xp/services/conbus/conbus_linknumber_service.py,sha256=r3Lyb7IV4i5kRY6zTnRK9jmC1vo8dpyHwh4WwdwrlL4,7703
131
133
  xp/services/conbus/conbus_output_service.py,sha256=_sHGF6AWadhT_CNSnRPaXwQLaNEwQHSVuyKtyZ9jgFc,5115
132
- xp/services/conbus/conbus_raw_service.py,sha256=ja0IMw1KN4JtOKqIkMZtH3vjBp1CYJ_prj1uthmzp7Q,2283
134
+ xp/services/conbus/conbus_raw_service.py,sha256=riANTAiXTdSzOWbp_g-IQjdRhAf8CzZnNJtlT-aDvRs,3746
133
135
  xp/services/conbus/conbus_receive_service.py,sha256=k6hzxh-D4piizb3e5Vsz-2Mfft_5KnAXoov4xk9wVY0,3123
134
136
  xp/services/conbus/conbus_scan_service.py,sha256=uDI4rRAeBMg4Z5gdO0Evn-ejEoPpB5X4FTxMpfKTw78,4025
135
137
  xp/services/conbus/conbus_service.py,sha256=MdT01cE_KjAqx6gZOiL0k6z9dPBd-CG19wiKrK8GqB4,10873
@@ -173,8 +175,8 @@ xp/services/telegram/telegram_service.py,sha256=Mp20QB50WDp43QBl8TzsR9BKV_hHP53R
173
175
  xp/services/telegram/telegram_version_service.py,sha256=21v256THg0lidTyUtp2i8r6TAl8J0CTaZo4bZw59nFk,10479
174
176
  xp/utils/__init__.py,sha256=clisBctja_VwtkAM9wnbOGDRPfbKHlCUqq4Sa4Z6zng,331
175
177
  xp/utils/checksum.py,sha256=HDpiQxmdIedbCbZ4o_Box0i_Zig417BtCV_46ZyhiTk,1711
176
- xp/utils/dependencies.py,sha256=KEbdfQIsB6cl6CYRacu72IF4LlNhDNPTuQF_FJlz0ME,20172
178
+ xp/utils/dependencies.py,sha256=VztcJM27MA6mykoVuX84zXMRsmKYuSGsVOKu5Gaw0b4,20490
177
179
  xp/utils/event_helper.py,sha256=W-A_xmoXlpWZBbJH6qdaN50o3-XrwFsDgvAGMJDiAgo,1001
178
180
  xp/utils/serialization.py,sha256=hZcrpzaBOe3a2wS_RFCIRs9PvnYsrbK7Ulq6s1rU0q4,4456
179
181
  xp/utils/time_utils.py,sha256=Yi3JxHrHsd9ZZxTBRIqlTOz1FYTCeE1IZbefDaXIop8,3800
180
- conson_xp-0.11.16.dist-info/RECORD,,
182
+ conson_xp-0.11.21.dist-info/RECORD,,
xp/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """conson-xp"""
4
4
 
5
- __version__ = "0.11.16"
5
+ __version__ = "0.11.21"
6
6
  __manufacturer__ = "salchichon"
7
7
  __model__ = "xp.cli"
8
8
  __serial__ = "2025.09.23.000"
@@ -38,7 +38,6 @@ from xp.cli.commands.conbus.conbus_datapoint_commands import (
38
38
  )
39
39
  from xp.cli.commands.conbus.conbus_discover_commands import send_discover_telegram
40
40
  from xp.cli.commands.conbus.conbus_lightlevel_commands import (
41
- xp_lightlevel_get,
42
41
  xp_lightlevel_off,
43
42
  xp_lightlevel_on,
44
43
  xp_lightlevel_set,
@@ -11,6 +11,8 @@ from xp.cli.utils.decorators import (
11
11
  handle_service_errors,
12
12
  )
13
13
  from xp.cli.utils.serial_number_type import SERIAL
14
+ from xp.models.conbus.conbus_blink import ConbusBlinkResponse
15
+ from xp.services.conbus.conbus_blink_all_service import ConbusBlinkAllService
14
16
  from xp.services.conbus.conbus_blink_service import ConbusBlinkService
15
17
  from xp.services.telegram.telegram_blink_service import BlinkError
16
18
 
@@ -29,12 +31,15 @@ def send_blink_on_telegram(ctx: Context, serial_number: str) -> None:
29
31
  \b
30
32
  xp conbus blink on 0012345008
31
33
  """
32
- service = ctx.obj.get("container").get_container().resolve(ConbusBlinkService)
33
34
 
34
- with service:
35
+ def finish(service_response: ConbusBlinkResponse) -> None:
36
+ click.echo(json.dumps(service_response.to_dict(), indent=2))
35
37
 
36
- response = service.send_blink_telegram(serial_number, "on")
37
- click.echo(json.dumps(response.to_dict(), indent=2))
38
+ service: ConbusBlinkService = (
39
+ ctx.obj.get("container").get_container().resolve(ConbusBlinkService)
40
+ )
41
+ with service:
42
+ service.send_blink_telegram(serial_number, "on", finish, 0.5)
38
43
 
39
44
 
40
45
  @conbus_blink.command("off")
@@ -51,12 +56,15 @@ def send_blink_off_telegram(ctx: Context, serial_number: str) -> None:
51
56
  \b
52
57
  xp conbus blink off 0012345008
53
58
  """
54
- service = ctx.obj.get("container").get_container().resolve(ConbusBlinkService)
55
59
 
56
- with service:
60
+ def finish(service_response: ConbusBlinkResponse) -> None:
61
+ click.echo(json.dumps(service_response.to_dict(), indent=2))
57
62
 
58
- response = service.send_blink_telegram(serial_number, "off")
59
- click.echo(json.dumps(response.to_dict(), indent=2))
63
+ service: ConbusBlinkService = (
64
+ ctx.obj.get("container").get_container().resolve(ConbusBlinkService)
65
+ )
66
+ with service:
67
+ service.send_blink_telegram(serial_number, "off", finish, 0.5)
60
68
 
61
69
 
62
70
  @conbus_blink.group("all", short_help="Control blink state for all devices")
@@ -80,14 +88,19 @@ def blink_all_off(ctx: Context) -> None:
80
88
  \b
81
89
  xp conbus blink all off
82
90
  """
83
- service = ctx.obj.get("container").get_container().resolve(ConbusBlinkService)
84
91
 
92
+ def finish(discovered_devices: ConbusBlinkResponse) -> None:
93
+ click.echo(json.dumps(discovered_devices.to_dict(), indent=2))
94
+
95
+ def progress(message: str) -> None:
96
+ click.echo(message)
97
+ pass
98
+
99
+ service: ConbusBlinkAllService = (
100
+ ctx.obj.get("container").get_container().resolve(ConbusBlinkAllService)
101
+ )
85
102
  with service:
86
- response = service.blink_all("off")
87
- if response.success:
88
- click.echo("All devices blink turned off")
89
- else:
90
- click.echo(f"Error: {response.error}")
103
+ service.send_blink_all_telegram("off", progress, finish, 0.5)
91
104
 
92
105
 
93
106
  @conbus_blink_all.command("on", short_help="Turn on blinking for all devices")
@@ -103,11 +116,16 @@ def blink_all_on(ctx: Context) -> None:
103
116
  \b
104
117
  xp conbus blink all on
105
118
  """
106
- service = ctx.obj.get("container").get_container().resolve(ConbusBlinkService)
107
119
 
120
+ def finish(discovered_devices: ConbusBlinkResponse) -> None:
121
+ click.echo(json.dumps(discovered_devices.to_dict(), indent=2))
122
+
123
+ def progress(message: str) -> None:
124
+ click.echo(message)
125
+ pass
126
+
127
+ service: ConbusBlinkAllService = (
128
+ ctx.obj.get("container").get_container().resolve(ConbusBlinkAllService)
129
+ )
108
130
  with service:
109
- response = service.blink_all("on")
110
- if response.success:
111
- click.echo("All devices blink turned on")
112
- else:
113
- click.echo(f"Error: {response.error}")
131
+ service.send_blink_all_telegram("on", progress, finish, 0.5)
@@ -10,9 +10,10 @@ from xp.cli.utils.decorators import (
10
10
  handle_service_errors,
11
11
  )
12
12
  from xp.cli.utils.serial_number_type import SERIAL
13
- from xp.services.conbus.conbus_lightlevel_service import (
13
+ from xp.models.conbus.conbus_lightlevel import ConbusLightlevelResponse
14
+ from xp.services.conbus.conbus_lightlevel_set_service import (
14
15
  ConbusLightlevelError,
15
- ConbusLightlevelService,
16
+ ConbusLightlevelSetService,
16
17
  )
17
18
 
18
19
 
@@ -34,12 +35,17 @@ def xp_lightlevel_set(
34
35
  xp conbus lightlevel set 0123450001 2 50 # Set output 2 to 50%
35
36
  xp conbus lightlevel set 0011223344 0 100 # Set output 0 to 100%
36
37
  """
37
- service = ctx.obj.get("container").get_container().resolve(ConbusLightlevelService)
38
38
 
39
- with service:
40
- response = service.set_lightlevel(serial_number, output_number, level)
39
+ def finish(response: "ConbusLightlevelResponse") -> None:
41
40
  click.echo(json.dumps(response.to_dict(), indent=2))
42
41
 
42
+ service = (
43
+ ctx.obj.get("container").get_container().resolve(ConbusLightlevelSetService)
44
+ )
45
+
46
+ with service:
47
+ service.set_lightlevel(serial_number, output_number, level, finish, 0.5)
48
+
43
49
 
44
50
  @conbus_lightlevel.command("off")
45
51
  @click.argument("serial_number", type=SERIAL)
@@ -58,12 +64,17 @@ def xp_lightlevel_off(
58
64
  xp conbus lightlevel off 0123450001 2 # Turn off output 2
59
65
  xp conbus lightlevel off 0011223344 0 # Turn off output 0
60
66
  """
61
- service = ctx.obj.get("container").get_container().resolve(ConbusLightlevelService)
62
67
 
63
- with service:
64
- response = service.turn_off(serial_number, output_number)
68
+ def finish(response: "ConbusLightlevelResponse") -> None:
65
69
  click.echo(json.dumps(response.to_dict(), indent=2))
66
70
 
71
+ service = (
72
+ ctx.obj.get("container").get_container().resolve(ConbusLightlevelSetService)
73
+ )
74
+
75
+ with service:
76
+ service.turn_off(serial_number, output_number, finish, 0.5)
77
+
67
78
 
68
79
  @conbus_lightlevel.command("on")
69
80
  @click.argument("serial_number", type=SERIAL)
@@ -82,12 +93,17 @@ def xp_lightlevel_on(
82
93
  xp conbus lightlevel on 0123450001 2 # Turn on output 2 (80%)
83
94
  xp conbus lightlevel on 0011223344 0 # Turn on output 0 (80%)
84
95
  """
85
- service = ctx.obj.get("container").get_container().resolve(ConbusLightlevelService)
86
96
 
87
- with service:
88
- response = service.turn_on(serial_number, output_number)
97
+ def finish(response: "ConbusLightlevelResponse") -> None:
89
98
  click.echo(json.dumps(response.to_dict(), indent=2))
90
99
 
100
+ service = (
101
+ ctx.obj.get("container").get_container().resolve(ConbusLightlevelSetService)
102
+ )
103
+
104
+ with service:
105
+ service.turn_on(serial_number, output_number, finish, 0.5)
106
+
91
107
 
92
108
  @conbus_lightlevel.command("get")
93
109
  @click.argument("serial_number", type=SERIAL)
@@ -99,15 +115,18 @@ def xp_lightlevel_get(
99
115
  ctx: click.Context, serial_number: str, output_number: int
100
116
  ) -> None:
101
117
  """Get current light level for output_number on XP module serial_number
102
-
103
118
  Examples:
104
-
105
119
  \b
106
120
  xp conbus lightlevel get 0123450001 2 # Get light level for output 2
107
121
  xp conbus lightlevel get 0011223344 0 # Get light level for output 0
108
122
  """
109
- service = ctx.obj.get("container").get_container().resolve(ConbusLightlevelService)
110
123
 
111
- with service:
112
- response = service.get_lightlevel(serial_number, output_number)
124
+ def finish(response: "ConbusLightlevelResponse") -> None:
113
125
  click.echo(json.dumps(response.to_dict(), indent=2))
126
+
127
+ service = (
128
+ ctx.obj.get("container").get_container().resolve(ConbusLightlevelSetService)
129
+ )
130
+
131
+ with service:
132
+ service.get_lightlevel(serial_number, output_number, finish, 0.5)
@@ -1,22 +1,22 @@
1
1
  """Conbus raw telegram CLI commands."""
2
2
 
3
+ import json
4
+
3
5
  import click
4
6
  from click import Context
5
7
 
6
8
  from xp.cli.commands.conbus.conbus import conbus
7
9
  from xp.cli.utils.decorators import (
8
10
  connection_command,
9
- handle_service_errors,
10
11
  )
11
- from xp.cli.utils.error_handlers import CLIErrorHandler
12
- from xp.services.conbus.conbus_raw_service import ConbusRawError, ConbusRawService
12
+ from xp.models.conbus.conbus_raw import ConbusRawResponse
13
+ from xp.services.conbus.conbus_raw_service import ConbusRawService
13
14
 
14
15
 
15
16
  @conbus.command("raw")
16
17
  @click.argument("raw_telegrams")
17
18
  @click.pass_context
18
19
  @connection_command()
19
- @handle_service_errors(ConbusRawError)
20
20
  def send_raw_telegrams(ctx: Context, raw_telegrams: str) -> None:
21
21
  """
22
22
  Send raw telegram sequence to Conbus server.
@@ -31,26 +31,21 @@ def send_raw_telegrams(ctx: Context, raw_telegrams: str) -> None:
31
31
  xp conbus raw '<S2113010000F02D12><S2113010001F02D12><S2113010002F02D12>'
32
32
  xp conbus raw '<S0012345003F02D12FM><S0012345004F02D12FD><S0012345005F02D12FI><S0012345006F02D12FL><S0012345007F02D12FK><S0012345008F02D12FJ><S0012345009F02D12FF>'
33
33
  """
34
- service = ctx.obj.get("container").get_container().resolve(ConbusRawService)
35
-
36
- try:
37
- with service:
38
- response = service.send_raw_telegrams(raw_telegrams)
39
-
40
- # Format output to match expected format from documentation
41
- if response.success and response.received_telegrams:
42
- for telegram in response.received_telegrams:
43
- click.echo(telegram)
44
- elif response.success:
45
- click.echo("No response received")
46
- else:
47
- click.echo(f"Error: {response.error}", err=True)
48
-
49
- except ConbusRawError as e:
50
- CLIErrorHandler.handle_service_error(
51
- e,
52
- "raw telegram send",
53
- {
54
- "raw_telegrams": raw_telegrams,
55
- },
34
+ service: ConbusRawService = (
35
+ ctx.obj.get("container").get_container().resolve(ConbusRawService)
36
+ )
37
+
38
+ def on_progress(message: str) -> None:
39
+ click.echo(message)
40
+ pass
41
+
42
+ def on_finish(service_response: ConbusRawResponse) -> None:
43
+ click.echo(json.dumps(service_response.to_dict(), indent=2))
44
+
45
+ with service:
46
+ service.send_raw_telegram(
47
+ raw_input=raw_telegrams,
48
+ progress_callback=on_progress,
49
+ finish_callback=on_finish,
50
+ timeout_seconds=5.0,
56
51
  )
@@ -31,10 +31,30 @@ class ConbusBlinkResponse:
31
31
 
32
32
  def to_dict(self) -> Dict[str, Any]:
33
33
  """Convert to dictionary for JSON serialization"""
34
- return {
34
+ result = {
35
35
  "success": self.success,
36
- "sent_telegram": self.sent_telegram,
37
- "received_telegrams": self.received_telegrams,
38
- "error": self.error,
36
+ "serial_number": self.serial_number,
37
+ "operation": self.operation,
38
+ "system_function": (
39
+ self.system_function.name if self.system_function else None
40
+ ),
41
+ "sent_telegram": (
42
+ self.sent_telegram.to_dict()
43
+ if self.sent_telegram and hasattr(self.sent_telegram, "to_dict")
44
+ else str(self.sent_telegram) if self.sent_telegram else None
45
+ ),
46
+ "reply_telegram": (
47
+ self.reply_telegram.to_dict()
48
+ if self.reply_telegram and hasattr(self.reply_telegram, "to_dict")
49
+ else str(self.reply_telegram) if self.reply_telegram else None
50
+ ),
39
51
  "timestamp": self.timestamp.isoformat() if self.timestamp else None,
40
52
  }
53
+
54
+ # Only include these if they have values
55
+ if self.received_telegrams:
56
+ result["received_telegrams"] = self.received_telegrams
57
+ if self.error:
58
+ result["error"] = self.error
59
+
60
+ return result
@@ -79,22 +79,29 @@ class ConbusAutoreportGetService(ConbusProtocol):
79
79
  telegram_received.frame
80
80
  )
81
81
  if (
82
- reply_telegram is not None
83
- and reply_telegram.system_function == SystemFunction.READ_DATAPOINT
84
- and reply_telegram.datapoint_type == DataPointType.AUTO_REPORT_STATUS
82
+ not reply_telegram
83
+ or reply_telegram.system_function != SystemFunction.READ_DATAPOINT
84
+ or reply_telegram.datapoint_type != DataPointType.AUTO_REPORT_STATUS
85
85
  ):
86
- self.logger.debug("Received autoreport status telegram")
87
- self.service_response.success = True
88
- self.service_response.timestamp = datetime.now()
89
- self.service_response.serial_number = self.serial_number
90
- self.service_response.auto_report_status = reply_telegram.data_value
86
+ self.logger.debug("Not an autoreport reply")
87
+ return
88
+
89
+ autoreport_status = reply_telegram.data_value
90
+ self.succeed(autoreport_status)
91
91
 
92
- if self.finish_callback:
93
- self.finish_callback(self.service_response)
92
+ def succeed(self, autoreport_status: str) -> None:
93
+ self.logger.debug("Received autoreport status: {autoreport_status}")
94
+ self.service_response.success = True
95
+ self.service_response.serial_number = self.serial_number
96
+ self.service_response.timestamp = datetime.now()
97
+ self.service_response.auto_report_status = autoreport_status
98
+ if self.finish_callback:
99
+ self.finish_callback(self.service_response)
94
100
 
95
101
  def failed(self, message: str) -> None:
96
102
  self.logger.debug(f"Failed with message: {message}")
97
103
  self.service_response.success = False
104
+ self.service_response.serial_number = self.serial_number
98
105
  self.service_response.timestamp = datetime.now()
99
106
  self.service_response.error = message
100
107
  if self.finish_callback:
@@ -0,0 +1,162 @@
1
+ """Conbus Client Send Service for TCP communication with Conbus servers.
2
+
3
+ This service implements a TCP client that connects to Conbus servers and sends
4
+ various types of telegrams including discover, version, and sensor data requests.
5
+ """
6
+
7
+ import logging
8
+ from datetime import datetime
9
+ from typing import Callable, Optional
10
+
11
+ from twisted.internet.posixbase import PosixReactorBase
12
+
13
+ from xp.models import ConbusClientConfig
14
+ from xp.models.conbus.conbus_blink import ConbusBlinkResponse
15
+ from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
16
+ from xp.models.telegram.system_function import SystemFunction
17
+ from xp.models.telegram.telegram_type import TelegramType
18
+ from xp.services.protocol import ConbusProtocol
19
+ from xp.services.telegram.telegram_service import TelegramService
20
+
21
+
22
+ class ConbusBlinkAllService(ConbusProtocol):
23
+ """
24
+ Service for receiving telegrams from Conbus servers.
25
+
26
+ Uses composition with ConbusService to provide receive-only functionality
27
+ for collecting waiting event telegrams from the server.
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ telegram_service: TelegramService,
33
+ cli_config: ConbusClientConfig,
34
+ reactor: PosixReactorBase,
35
+ ) -> None:
36
+ """Initialize the Conbus client send service"""
37
+ super().__init__(cli_config, reactor)
38
+ self.telegram_service = telegram_service
39
+ self.serial_number: str = ""
40
+ self.on_or_off = "none"
41
+ self.progress_callback: Optional[Callable[[str], None]] = None
42
+ self.finish_callback: Optional[Callable[[ConbusBlinkResponse], None]] = None
43
+ self.service_response: ConbusBlinkResponse = ConbusBlinkResponse(
44
+ success=False,
45
+ serial_number=self.serial_number,
46
+ system_function=SystemFunction.NONE,
47
+ operation=self.on_or_off,
48
+ )
49
+
50
+ # Set up logging
51
+ self.logger = logging.getLogger(__name__)
52
+
53
+ def connection_established(self) -> None:
54
+ self.logger.debug("Connection established, send discover telegram...")
55
+ self.send_telegram(
56
+ telegram_type=TelegramType.SYSTEM,
57
+ serial_number="0000000000",
58
+ system_function=SystemFunction.DISCOVERY,
59
+ data_value="00",
60
+ )
61
+ if self.progress_callback:
62
+ self.progress_callback(".")
63
+
64
+ def send_blink(self, serial_number: str) -> None:
65
+ self.logger.debug("Device discovered, send blink...")
66
+
67
+ # Blink is 05, Unblink is 06
68
+ system_function = SystemFunction.UNBLINK
69
+ if self.on_or_off.lower() == "on":
70
+ system_function = SystemFunction.BLINK
71
+
72
+ self.send_telegram(
73
+ telegram_type=TelegramType.SYSTEM,
74
+ serial_number=serial_number,
75
+ system_function=system_function,
76
+ data_value="00",
77
+ )
78
+ self.service_response.system_function = system_function
79
+ self.service_response.operation = self.on_or_off
80
+
81
+ if self.progress_callback:
82
+ self.progress_callback(".")
83
+
84
+ def telegram_sent(self, telegram_sent: str) -> None:
85
+ system_telegram = self.telegram_service.parse_system_telegram(telegram_sent)
86
+ self.service_response.sent_telegram = system_telegram
87
+
88
+ def telegram_received(self, telegram_received: TelegramReceivedEvent) -> None:
89
+
90
+ self.logger.debug(f"Telegram received: {telegram_received}")
91
+ if not self.service_response.received_telegrams:
92
+ self.service_response.received_telegrams = []
93
+ self.service_response.received_telegrams.append(telegram_received.frame)
94
+
95
+ if (
96
+ not telegram_received.checksum_valid
97
+ or telegram_received.telegram_type != TelegramType.REPLY
98
+ ):
99
+ self.logger.debug("Not a reply")
100
+ return
101
+
102
+ reply_telegram = self.telegram_service.parse_reply_telegram(
103
+ telegram_received.frame
104
+ )
105
+ if (
106
+ reply_telegram
107
+ and reply_telegram.system_function == SystemFunction.DISCOVERY
108
+ ):
109
+ self.logger.debug("Received discovery response")
110
+ self.send_blink(reply_telegram.serial_number)
111
+ if self.progress_callback:
112
+ self.progress_callback(".")
113
+ return
114
+
115
+ if reply_telegram and reply_telegram.system_function in (
116
+ SystemFunction.BLINK,
117
+ SystemFunction.UNBLINK,
118
+ ):
119
+ self.logger.debug("Received blink response")
120
+ if self.progress_callback:
121
+ self.progress_callback(".")
122
+ return
123
+
124
+ self.logger.debug("Received unexpected response")
125
+
126
+ def failed(self, message: str) -> None:
127
+ self.logger.debug(f"Failed with message: {message}")
128
+ self.service_response.success = False
129
+ self.service_response.timestamp = datetime.now()
130
+ self.service_response.error = message
131
+ if self.finish_callback:
132
+ self.finish_callback(self.service_response)
133
+
134
+ def send_blink_all_telegram(
135
+ self,
136
+ on_or_off: str,
137
+ progress_callback: Callable[[str], None],
138
+ finish_callback: Callable[[ConbusBlinkResponse], None],
139
+ timeout_seconds: Optional[float] = None,
140
+ ) -> None:
141
+ """
142
+ Get the current auto report status for a specific module.
143
+
144
+ Args:
145
+ on_or_off: blink or unblink device
146
+ finish_callback: callback function to call when the autoreport status is
147
+ timeout_seconds: timeout in seconds
148
+
149
+ Returns:
150
+ ConbusAutoreportResponse with operation result and auto report status
151
+
152
+ Raises:
153
+ ConbusAutoreportError: If the operation fails
154
+ """
155
+
156
+ self.logger.info("Starting get_autoreport_status")
157
+ if timeout_seconds:
158
+ self.timeout_seconds = timeout_seconds
159
+ self.progress_callback = progress_callback
160
+ self.finish_callback = finish_callback
161
+ self.on_or_off = on_or_off
162
+ self.start_reactor()