conson-xp 1.20.0__py3-none-any.whl → 1.22.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: conson-xp
3
- Version: 1.20.0
3
+ Version: 1.22.0
4
4
  Summary: XP Protocol Communication Tools
5
5
  Author-Email: ldvchosal <ldvchosal@github.com>
6
6
  License: MIT License
@@ -60,7 +60,7 @@ Description-Content-Type: text/markdown
60
60
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
61
61
  [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
62
62
 
63
- > **A powerful Python CLI and API toolkit for CONSON XP Protocol operations**
63
+ > **A powerful Python CLI toolkit for CONSON XP Protocol operations**
64
64
 
65
65
  Control and communicate with XP devices through console bus (Conbus), parse telegrams in real-time, and integrate with smart home systems like Apple HomeKit.
66
66
 
@@ -81,7 +81,7 @@ Bridge XP devices to Apple HomeKit for seamless smart home control
81
81
  Automatically discover XP servers and scan connected modules on your network
82
82
 
83
83
  ⚡ **Modern Architecture**
84
- FastAPI REST endpoints and comprehensive type safety
84
+ Comprehensive type safety and robust error handling
85
85
 
86
86
  ---
87
87
 
@@ -96,9 +96,6 @@ xp telegram parse "<E14L00I02MAK>"
96
96
 
97
97
  # Discover XP servers on your network
98
98
  xp conbus discover
99
-
100
- # Start the REST API server
101
- xp api start
102
99
  ```
103
100
 
104
101
  ## 📦 Installation
@@ -167,7 +164,32 @@ xp module search "push button"
167
164
  xp module list --group-by-category
168
165
  ```
169
166
 
167
+ ### 🖥️ Terminal UI (TUI)
168
+
169
+ **Real-time Protocol Monitor**
170
+
171
+ Launch an interactive terminal interface for live protocol monitoring and control:
170
172
 
173
+ ```bash
174
+ # Start the protocol monitor TUI
175
+ xp term protocol
176
+ ```
177
+
178
+ **Features:**
179
+ - 📊 **Live Telegram Stream**: Real-time RX/TX telegram monitoring from Conbus server
180
+ - ⌨️ **Keyboard Shortcuts**: Quick access controls for common operations
181
+ - `Q` - Quit application
182
+ - `C` - Toggle connection (connect/disconnect)
183
+ - `R` - Reset and clear log
184
+ - `0-9, a-q` - Send predefined protocol telegrams
185
+ - 🎨 **Visual Status Indicators**: Color-coded connection states
186
+ - 🟢 Green - Connected
187
+ - 🟡 Yellow - Connecting/Disconnecting
188
+ - 🔴 Red - Failed
189
+ - ⚪ White - Disconnected
190
+ - 📝 **Interactive Display**: Scrollable telegram log with detailed parsing information
191
+
192
+ The TUI provides a convenient way to monitor and interact with XP devices without juggling multiple terminal commands.
171
193
 
172
194
  ### 🔧 Advanced Features
173
195
 
@@ -201,13 +223,7 @@ xp checksum calculate "E14L00I02M" --algorithm crc32
201
223
  ```
202
224
  </details>
203
225
 
204
- ### 🌐 API & Integration
205
-
206
- **REST API Server**
207
- ```bash
208
- # Start API server with interactive docs at /docs
209
- xp api start
210
- ```
226
+ ### 🌐 Integration
211
227
 
212
228
  **HomeKit Smart Home Bridge**
213
229
  ```bash
@@ -232,7 +248,7 @@ xp reverse-proxy start
232
248
 
233
249
  **Layered Design**
234
250
  ```
235
- CLI Layer → API Layer → Services → Models → Connection Layer
251
+ CLI Layer → Services → Models → Connection Layer
236
252
  ```
237
253
 
238
254
  **Key Components**: Telegram processing • Real-time Conbus communication • HomeKit bridge • Multiple XP server support • Configuration management
@@ -256,9 +272,8 @@ pdm run check
256
272
  <details>
257
273
  <summary><b>Project Structure</b></summary>
258
274
 
259
- ```
275
+ ```
260
276
  src/xp/
261
- ├── api/ # FastAPI REST endpoints
262
277
  ├── cli/ # Command-line interface
263
278
  ├── models/ # Core data models
264
279
  ├── services/ # Business logic
@@ -407,7 +422,7 @@ xp term protocol
407
422
  ```
408
423
  </details>
409
424
 
410
- **Requirements**: Python 3.10+ • FastAPI • Pydantic • Click • HAP-python
425
+ **Requirements**: Python 3.10+ • Pydantic • Click • HAP-python
411
426
 
412
427
  ## License
413
428
 
@@ -1,8 +1,8 @@
1
- conson_xp-1.20.0.dist-info/METADATA,sha256=vAvQzvNII8d7oxEEbo1rSLyswX3lROWxh7cERQ-y3_Y,9584
2
- conson_xp-1.20.0.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
3
- conson_xp-1.20.0.dist-info/entry_points.txt,sha256=1OcdIcDM1hz3ljCXgybaPUh1IOFEwkaTgLIW9u9zGeg,50
4
- conson_xp-1.20.0.dist-info/licenses/LICENSE,sha256=rxj6woMM-r3YCyGq_UHFtbh7kHTAJgrccH6O-33IDE4,1419
5
- xp/__init__.py,sha256=T304nC2FLiJmOCyBS3xq0x0Bb4Nv_XAMMRN4xZtqUec,181
1
+ conson_xp-1.22.0.dist-info/METADATA,sha256=SHz732F4Z0CbbWIukCpttstkgiNLFBgqYAZQg94OkEk,10298
2
+ conson_xp-1.22.0.dist-info/WHEEL,sha256=tsUv_t7BDeJeRHaSrczbGeuK-TtDpGsWi_JfpzD255I,90
3
+ conson_xp-1.22.0.dist-info/entry_points.txt,sha256=1OcdIcDM1hz3ljCXgybaPUh1IOFEwkaTgLIW9u9zGeg,50
4
+ conson_xp-1.22.0.dist-info/licenses/LICENSE,sha256=rxj6woMM-r3YCyGq_UHFtbh7kHTAJgrccH6O-33IDE4,1419
5
+ xp/__init__.py,sha256=cGDFz-p2G9nzESEviCX7b8voSRj-fYSsRjnhBPsDwSE,181
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=noh8fdZAWq-ihJEboP8WugbIgq4LJ3jUWMRA7720xWE,4909
@@ -42,7 +42,7 @@ xp/cli/commands/telegram/telegram_parse_commands.py,sha256=_OYOso1hS4f_ox96qlkYL
42
42
  xp/cli/commands/telegram/telegram_version_commands.py,sha256=WQyx1-B9yJ8V9WrFyBpOvULJ-jq12GoZZDDoRbM7eyw,1553
43
43
  xp/cli/commands/term/__init__.py,sha256=1NNST_8YJfj5LCujQISwQflK6LyEn7mDmZpMpvI9d-o,116
44
44
  xp/cli/commands/term/term.py,sha256=gjvsv2OE-F_KNWQrWi04fXQ5cGo0l8P-Ortbb5KTA-A,309
45
- xp/cli/commands/term/term_commands.py,sha256=3qwiGlEEgMIz5AG7fq5U_9SZSWSDfrKwYggHbiv5kRk,738
45
+ xp/cli/commands/term/term_commands.py,sha256=ccBdvvyxjh2-cptmI9ohVIa02OOfG0dzO1JFb4KTowQ,744
46
46
  xp/cli/main.py,sha256=ap5jU0DrSnrCKDKqGXcz9N-sngZodyyN-5ReWE8Fh1s,1817
47
47
  xp/cli/utils/__init__.py,sha256=gTGIj60Uai0iE7sr9_TtEpl04fD7krtTzbbigXUsUVU,46
48
48
  xp/cli/utils/click_tree.py,sha256=ilmM2IMa_c-TqUMsv2alrZXuS0BNhvVlrBlSfyN8lzM,1670
@@ -104,6 +104,8 @@ xp/models/telegram/system_telegram.py,sha256=9FNQ4Mf47mRK7wGrTg2GzziVsrEWCE5ZkZp
104
104
  xp/models/telegram/telegram.py,sha256=IJUxHX6ftLcET9C1pjvLhUO5Db5JO6W7rUItzdEW30I,842
105
105
  xp/models/telegram/telegram_type.py,sha256=GhqKP63oNMyh2tIvCPcsC5RFp4s4JjhmEqCLCC-8XMk,423
106
106
  xp/models/telegram/timeparam_type.py,sha256=Ar8xvSfPmOAgR2g2Je0FgvP01SL7bPvZn5_HrVDpmJM,1137
107
+ xp/models/term/__init__.py,sha256=c1AMtVitYk80o9K_zWjYNzZYpFDASqM8S1Djm1PD4Qo,192
108
+ xp/models/term/protocol_keys_config.py,sha256=CTujcfI2_NOeltjvHy_cnsHzxLSVsGFXieMZlD-zj0Q,1204
107
109
  xp/models/write_config_type.py,sha256=T2RaO52RpzoJ4782uMHE-fX7Ymx3CaIQAEwByydXq1M,881
108
110
  xp/services/__init__.py,sha256=W9YZyrkh7vm--ZHhAXNQiOYQs5yhhmUHXP5I0Lf1XBg,782
109
111
  xp/services/actiontable/__init__.py,sha256=z6js4EuJ6xKHaseTEhuEvKo1tr9K1XyQiruReJtBiPY,26
@@ -149,7 +151,7 @@ xp/services/homekit/homekit_service.py,sha256=0lW-hg40ETco3gDBEYkR_sX-UIYsLSKCD4
149
151
  xp/services/log_file_service.py,sha256=fvPcZQj8XOKUA-4ep5R8n0PelvwvRlTLlVxvIWM5KR4,10506
150
152
  xp/services/module_type_service.py,sha256=xWhr1EAZMykL5uNWHWdpa5T8yNruGKH43XRTOS8GwZg,7477
151
153
  xp/services/protocol/__init__.py,sha256=qRufBmqRKGzpuzZ5bxBbmwf510TT00Ke8s5HcWGnqRY,818
152
- xp/services/protocol/conbus_event_protocol.py,sha256=48KCTkJLDHV1ijVXHf0TraY663Nk3_dEV3lkZpvduDo,13671
154
+ xp/services/protocol/conbus_event_protocol.py,sha256=t_ovcLbwXays-y8u-EqFpDSfo2Xc_BNl3jAj9PqxRwg,13885
153
155
  xp/services/protocol/conbus_protocol.py,sha256=JO7yLkD_ohPT0ETjnAIx4CGpZyobf4LdbuozM_43btE,10276
154
156
  xp/services/protocol/protocol_factory.py,sha256=PmjN9AtW9sxNo3voqUiNgQA-pTvX1RW4XXFlHKfFr5Q,2470
155
157
  xp/services/protocol/telegram_protocol.py,sha256=Ki5DrXsKxiaqLcdP9WWUuhUI7cPu2DfwyZkh-Gv9Lb8,9496
@@ -173,16 +175,20 @@ xp/services/telegram/telegram_link_number_service.py,sha256=1_c-_QCRPTHYn3BmMElr
173
175
  xp/services/telegram/telegram_output_service.py,sha256=UaUv_14fR8o5K2PxQBXrCzx-Hohnk-gzbev_oLw_Clc,10799
174
176
  xp/services/telegram/telegram_service.py,sha256=XrP1CPi0ckxoKBaNwLA6lo-TogWxXgmXDOsU4Xl8BlY,13237
175
177
  xp/services/telegram/telegram_version_service.py,sha256=M5HdOTsLdcwo122FP-jW6R740ktLrtKf2TiMDVz23h8,10528
176
- xp/tui/__init__.py,sha256=Xg2DhBeI3xQJLfc7_BPWI1por-rUXemyer5OtOt9Cus,51
177
- xp/tui/app.py,sha256=NBCdFCgftckey5TgxDFn-SeOLSFggapshIwKDcLM5QY,2227
178
- xp/tui/protocol.tcss,sha256=njMgFgz4oD4Qjw3dyoX1SfCuvlfGg6QrrkZ2COFZ0yM,768
179
- xp/tui/widgets/__init__.py,sha256=Ewiza9u6k5K50zZRIMD7jjOHY1IvGhoX1ViwlqhdGms,27
180
- xp/tui/widgets/protocol_log.py,sha256=0twJHiOTNcOOw3eQtYkjb1x37adecypPPPT1fuWb2q4,11541
178
+ xp/term/__init__.py,sha256=Xg2DhBeI3xQJLfc7_BPWI1por-rUXemyer5OtOt9Cus,51
179
+ xp/term/protocol.py,sha256=ERntzYvNMyI-VDCYW7EnhpPu-V6WPmyEk0xcQfm7LFM,4399
180
+ xp/term/protocol.tcss,sha256=biaIv6X-bmD1tbXENFUNsXOF8ABkuoRAUgeSDqwudtQ,2126
181
+ xp/term/protocol.yml,sha256=kiTe_QSMPmLvLA0ZyIhNaDPwBdi6khh5C1NSR7I9TN0,2124
182
+ xp/term/widgets/__init__.py,sha256=ftWmN_fmjxy2E8Qfm-YSRmzKfgL0KTBCTpgvYWCPbUY,274
183
+ xp/term/widgets/help_menu.py,sha256=bdT5AYRdtKt_tvZTVbG7-DPMb1mj78kggtjjsa-95BA,1780
184
+ xp/term/widgets/protocol_log.py,sha256=yuSfc61azgQmWQxLvBcmVik3cJAW1Hocj2Sk8qr3hSg,14343
185
+ xp/term/widgets/status_footer.py,sha256=VTN5owCprMbYmNiEbNWS_4CE8yxysDi8IBCECuU9EQY,1663
181
186
  xp/utils/__init__.py,sha256=_avMF_UOkfR3tNeDIPqQ5odmbq5raKkaq1rZ9Cn1CJs,332
182
187
  xp/utils/checksum.py,sha256=HDpiQxmdIedbCbZ4o_Box0i_Zig417BtCV_46ZyhiTk,1711
183
188
  xp/utils/dependencies.py,sha256=ECS6p0eXzocM5INLwJeckHXn_Dim18uOjXTJ29qQvkQ,22001
184
189
  xp/utils/event_helper.py,sha256=W-A_xmoXlpWZBbJH6qdaN50o3-XrwFsDgvAGMJDiAgo,1001
185
- xp/utils/logging.py,sha256=5ol2JrnFtjs9QtBYW4KeKYzcFzCxbCn8BsIq3aIF4H4,3395
190
+ xp/utils/logging.py,sha256=rZDXwlBrYK8A6MPq5StsMNpgsRowzJXM6fvROPwJdGM,3750
186
191
  xp/utils/serialization.py,sha256=RWHHk86feaB4ZP7rjE4qOWK0900yg2joUBDkP76gfOY,4618
192
+ xp/utils/state_machine.py,sha256=Oe2sLwCh9z_vr1tF6X0ZRGTeuckRQAGzmef7xc9CNdc,2413
187
193
  xp/utils/time_utils.py,sha256=dEyViDlAG9GWU-J3D_YVa-sGma6yiyyMTgN4h2x3PY4,3781
188
- conson_xp-1.20.0.dist-info/RECORD,,
194
+ conson_xp-1.22.0.dist-info/RECORD,,
xp/__init__.py CHANGED
@@ -3,7 +3,7 @@
3
3
  conson-xp package.
4
4
  """
5
5
 
6
- __version__ = "1.20.0"
6
+ __version__ = "1.22.0"
7
7
  __manufacturer__ = "salchichon"
8
8
  __model__ = "xp.cli"
9
9
  __serial__ = "2025.09.23.000"
@@ -21,7 +21,7 @@ def protocol_monitor(ctx: Context) -> None:
21
21
  \b
22
22
  xp term protocol
23
23
  """
24
- from xp.tui.app import ProtocolMonitorApp
24
+ from xp.term.protocol import ProtocolMonitorApp
25
25
 
26
26
  # Resolve ServiceContainer from context
27
27
  container = ctx.obj.get("container").get_container()
@@ -0,0 +1,11 @@
1
+ """Terminal UI models."""
2
+
3
+ from xp.models.term.protocol_keys_config import (
4
+ ProtocolKeyConfig,
5
+ ProtocolKeysConfig,
6
+ )
7
+
8
+ __all__ = [
9
+ "ProtocolKeyConfig",
10
+ "ProtocolKeysConfig",
11
+ ]
@@ -0,0 +1,45 @@
1
+ """Protocol keys configuration model."""
2
+
3
+ from pathlib import Path
4
+ from typing import Dict
5
+
6
+ import yaml
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class ProtocolKeyConfig(BaseModel):
11
+ """Configuration for a single protocol key.
12
+
13
+ Attributes:
14
+ name: Human-readable command name.
15
+ telegrams: List of raw telegram strings to send (without angle brackets).
16
+ """
17
+
18
+ name: str = Field(..., description="Human-readable command name")
19
+ telegrams: list[str] = Field(..., description="List of raw telegram strings")
20
+
21
+
22
+ class ProtocolKeysConfig(BaseModel):
23
+ """Protocol keys configuration.
24
+
25
+ Attributes:
26
+ protocol: Dictionary mapping key to protocol configuration.
27
+ """
28
+
29
+ protocol: Dict[str, ProtocolKeyConfig] = Field(
30
+ default_factory=dict, description="Protocol key mappings"
31
+ )
32
+
33
+ @classmethod
34
+ def from_yaml(cls, config_path: Path) -> "ProtocolKeysConfig":
35
+ """Load protocol keys from YAML file.
36
+
37
+ Args:
38
+ config_path: Path to YAML configuration file.
39
+
40
+ Returns:
41
+ ProtocolKeysConfig instance.
42
+ """
43
+ with config_path.open("r") as f:
44
+ data = yaml.safe_load(f)
45
+ return cls(**data)
@@ -209,6 +209,14 @@ class ConbusEventProtocol(protocol.Protocol, protocol.ClientFactory):
209
209
  f"F{system_function.value}"
210
210
  f"D{data_value}"
211
211
  )
212
+ self.send_raw_telegram(payload)
213
+
214
+ def send_raw_telegram(self, payload: str) -> None:
215
+ """Send telegram with specified parameters.
216
+
217
+ Args:
218
+ payload: Telegram to send.
219
+ """
212
220
  self.telegram_queue.put_nowait(payload.encode())
213
221
  self.call_later(0.0, self.start_queue_manager)
214
222
 
xp/term/protocol.py ADDED
@@ -0,0 +1,127 @@
1
+ """Protocol Monitor TUI Application."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Optional
5
+
6
+ from textual.app import App, ComposeResult
7
+ from textual.containers import Horizontal
8
+
9
+ from xp.models.term import ProtocolKeysConfig
10
+ from xp.term.widgets.help_menu import HelpMenuWidget
11
+ from xp.term.widgets.protocol_log import ProtocolLogWidget
12
+ from xp.term.widgets.status_footer import StatusFooterWidget
13
+
14
+
15
+ class ProtocolMonitorApp(App[None]):
16
+ """Textual app for real-time protocol monitoring.
17
+
18
+ Displays live RX/TX telegram stream from Conbus server in an interactive
19
+ terminal interface with keyboard shortcuts for control.
20
+
21
+ Attributes:
22
+ container: ServiceContainer for dependency injection.
23
+ CSS_PATH: Path to CSS stylesheet file.
24
+ BINDINGS: Keyboard bindings for app actions.
25
+ TITLE: Application title displayed in header.
26
+ ENABLE_COMMAND_PALETTE: Disable Textual's command palette feature.
27
+ """
28
+
29
+ CSS_PATH = Path(__file__).parent / "protocol.tcss"
30
+ TITLE = "Protocol Monitor"
31
+ ENABLE_COMMAND_PALETTE = False
32
+
33
+ BINDINGS = [
34
+ ("Q", "quit", "Quit"),
35
+ ("C", "toggle_connection", "Connect"),
36
+ ("R", "reset", "Reset"),
37
+ ("0-9,a-q", "protocol_keys", "Keys"),
38
+ ]
39
+
40
+ def __init__(self, container: Any) -> None:
41
+ """Initialize the Protocol Monitor app.
42
+
43
+ Args:
44
+ container: ServiceContainer for resolving services.
45
+ """
46
+ super().__init__()
47
+ self.container = container
48
+ self.protocol_widget: Optional[ProtocolLogWidget] = None
49
+ self.help_menu: Optional[HelpMenuWidget] = None
50
+ self.footer_widget: Optional[StatusFooterWidget] = None
51
+ self.protocol_keys = self._load_protocol_keys()
52
+
53
+ def _load_protocol_keys(self) -> ProtocolKeysConfig:
54
+ """Load protocol keys from YAML config file.
55
+
56
+ Returns:
57
+ ProtocolKeysConfig instance.
58
+ """
59
+ config_path = Path(__file__).parent / "protocol.yml"
60
+ return ProtocolKeysConfig.from_yaml(config_path)
61
+
62
+ def compose(self) -> ComposeResult:
63
+ """Compose the app layout with widgets.
64
+
65
+ Yields:
66
+ ProtocolLogWidget and Footer widgets.
67
+ """
68
+ with Horizontal(id="main-container"):
69
+ self.protocol_widget = ProtocolLogWidget(container=self.container)
70
+ yield self.protocol_widget
71
+
72
+ # Help menu (hidden by default)
73
+ self.help_menu = HelpMenuWidget(
74
+ protocol_keys=self.protocol_keys, id="help-menu"
75
+ )
76
+ yield self.help_menu
77
+
78
+ self.footer_widget = StatusFooterWidget(id="footer-container")
79
+ yield self.footer_widget
80
+
81
+ def action_toggle_connection(self) -> None:
82
+ """Toggle connection on 'c' key press.
83
+
84
+ Connects if disconnected/failed, disconnects if connected/connecting.
85
+ """
86
+ if self.protocol_widget:
87
+ from xp.term.widgets.protocol_log import ConnectionState
88
+
89
+ state = self.protocol_widget.connection_state
90
+ if state in (ConnectionState.CONNECTED, ConnectionState.CONNECTING):
91
+ self.protocol_widget.disconnect()
92
+ else:
93
+ self.protocol_widget.connect()
94
+
95
+ def action_reset(self) -> None:
96
+ """Reset and clear protocol widget on 'r' key press."""
97
+ if self.protocol_widget:
98
+ self.protocol_widget.clear_log()
99
+
100
+ def on_key(self, event: Any) -> None:
101
+ """Handle key press events for protocol keys.
102
+
103
+ Args:
104
+ event: Key press event from Textual.
105
+ """
106
+ if event.key in self.protocol_keys.protocol and self.protocol_widget:
107
+ key_config = self.protocol_keys.protocol[event.key]
108
+ for telegram in key_config.telegrams:
109
+ self.protocol_widget.send_telegram(key_config.name, telegram)
110
+
111
+ def on_mount(self) -> None:
112
+ """Set up status line updates when app mounts."""
113
+ if self.protocol_widget:
114
+ self.protocol_widget.watch(
115
+ self.protocol_widget,
116
+ "connection_state",
117
+ self._update_status,
118
+ )
119
+
120
+ def _update_status(self, state: Any) -> None:
121
+ """Update status line with connection state.
122
+
123
+ Args:
124
+ state: Current connection state.
125
+ """
126
+ if self.footer_widget:
127
+ self.footer_widget.update_status(state)
xp/term/protocol.tcss ADDED
@@ -0,0 +1,135 @@
1
+ /* Protocol Monitor TUI Styling */
2
+
3
+ /* App-level styling */
4
+ Screen {
5
+ background: $background;
6
+ }
7
+
8
+ /* Protocol Log Widget */
9
+ ProtocolLogWidget {
10
+ border: solid $success;
11
+ width: 1fr;
12
+ height: 1fr;
13
+ background: $background;
14
+ padding: 1;
15
+ }
16
+
17
+ ProtocolLogWidget > RichLog {
18
+ background: $background !important;
19
+ scrollbar-background: $background;
20
+ }
21
+
22
+ ProtocolLogWidget > RichLog:focus {
23
+ background: $background !important;
24
+ background-tint: transparent;
25
+ }
26
+
27
+ ProtocolLogWidget > .connection-status {
28
+ color: $text;
29
+ text-align: center;
30
+ padding: 1;
31
+ }
32
+
33
+ ProtocolLogWidget > .connection-status.connecting {
34
+ color: $warning;
35
+ }
36
+
37
+ ProtocolLogWidget > .connection-status.connected {
38
+ color: $success;
39
+ }
40
+
41
+ ProtocolLogWidget > .connection-status.failed {
42
+ color: $error;
43
+ }
44
+
45
+ /* Message display styling */
46
+ .message-tx {
47
+ color: $success;
48
+ }
49
+
50
+ .message-rx {
51
+ color: $success;
52
+ }
53
+
54
+ .message-frame {
55
+ color: $text-muted;
56
+ }
57
+
58
+ /* Main container */
59
+ #main-container {
60
+ height: 1fr;
61
+ }
62
+
63
+ /* Help menu styling */
64
+ #help-menu {
65
+ width: 35;
66
+ height: 1fr;
67
+ background: $background;
68
+ border: solid $success;
69
+ padding: 1;
70
+ }
71
+
72
+ #help-menu:focus {
73
+ border: solid $success;
74
+ }
75
+
76
+ #help-title {
77
+ color: $success;
78
+ text-align: center;
79
+ text-style: bold;
80
+ margin-bottom: 1;
81
+ }
82
+
83
+ #help-table {
84
+ background: $background;
85
+ height: auto;
86
+ color: $success;
87
+ }
88
+
89
+ DataTable {
90
+ background: $background;
91
+ }
92
+
93
+ DataTable > .datatable--header {
94
+ background: $background;
95
+ color: $success;
96
+ }
97
+
98
+ DataTable > .datatable--cursor {
99
+ background: $background;
100
+ }
101
+
102
+ DataTable:focus > .datatable--cursor {
103
+ background: $background;
104
+ }
105
+
106
+ /* Footer styling */
107
+ #footer-container {
108
+ dock: bottom;
109
+ height: 1;
110
+ background: $background;
111
+ }
112
+
113
+ Footer {
114
+ width: auto;
115
+ background: $background;
116
+ color: $text;
117
+ }
118
+
119
+ #status-text {
120
+ dock: right;
121
+ width: auto;
122
+ padding: 0 1;
123
+ background: $background;
124
+ color: $text;
125
+ text-align: right;
126
+ }
127
+
128
+ #status-line {
129
+ dock: right;
130
+ width: auto;
131
+ padding: 0 1;
132
+ background: $background;
133
+ color: $text;
134
+ text-align: right;
135
+ }
xp/term/protocol.yml ADDED
@@ -0,0 +1,139 @@
1
+ protocol:
2
+ "1":
3
+ name: "Discover"
4
+ telegrams:
5
+ - S0000000000F01D00
6
+ "2":
7
+ name: "Error Code"
8
+ telegrams:
9
+ - S0020044966F02D10
10
+ "3":
11
+ name: "Module Type"
12
+ telegrams:
13
+ - S0020044966F02D00
14
+ "4":
15
+ name: "Auto Report"
16
+ telegrams:
17
+ - S0020044966F02D21
18
+ "5":
19
+ name: "Link Number"
20
+ telegrams:
21
+ - S0020044966F02D04
22
+ "6":
23
+ name: "Blink On"
24
+ telegrams:
25
+ - S0020044966F01D01
26
+ "7":
27
+ name: "Blink Off"
28
+ telegrams:
29
+ - S0020044966F01D00
30
+ "8":
31
+ name: "Output 1 On"
32
+ telegrams:
33
+ - S0020044966F02101
34
+ "9":
35
+ name: "Output 1 Off"
36
+ telegrams:
37
+ - S0020044966F02100
38
+ "0":
39
+ name: "Output State"
40
+ telegrams:
41
+ - S0020044966F02D09
42
+ "a":
43
+ name: "Module State"
44
+ telegrams:
45
+ - S0020044966F02D09
46
+ "b":
47
+ name: "All Off"
48
+ telegrams:
49
+ - E02L00I00M
50
+ - E02L00I00B
51
+ "c":
52
+ name: "All On"
53
+ telegrams:
54
+ - E02L00I08M
55
+ - E02L00I08B
56
+
57
+ "d":
58
+ name: "Link 1 On"
59
+ telegrams:
60
+ - E02L01I08M
61
+ - E02L01I08B
62
+
63
+ "e":
64
+ name: "Link 1 Off"
65
+ telegrams:
66
+ - E02L01I00M
67
+ - E02L01I00B
68
+
69
+ "f":
70
+ name: "Link 2 On"
71
+ telegrams:
72
+ - E02L02I08M
73
+ - E02L02I08B
74
+
75
+ "g":
76
+ name: "Link 2 Off"
77
+ telegrams:
78
+ - E02L02I00M
79
+ - E02L02I00B
80
+
81
+ "h":
82
+ name: "Link 3 On"
83
+ telegrams:
84
+ - E02L03I08M
85
+ - E02L03I08B
86
+
87
+ "i":
88
+ name: "Link 3 Off"
89
+ telegrams:
90
+ - E02L03I00M
91
+ - E02L03I00B
92
+
93
+ "j":
94
+ name: "Link 4 On"
95
+ telegrams:
96
+ - E02L04I08M
97
+ - E02L04I08B
98
+
99
+ "k":
100
+ name: "Link 4 Off"
101
+ telegrams:
102
+ - E02L04I00M
103
+ - E02L04I00B
104
+
105
+ "l":
106
+ name: "Link 5 On"
107
+ telegrams:
108
+ - E02L05I08M
109
+ - E02L05I08B
110
+
111
+ "m":
112
+ name: "Link 5 Off"
113
+ telegrams:
114
+ - E02L05I00M
115
+ - E02L05I00B
116
+
117
+ "n":
118
+ name: "Link 6 On"
119
+ telegrams:
120
+ - E02L06I08M
121
+ - E02L06I08B
122
+
123
+ "o":
124
+ name: "Link 6 Off"
125
+ telegrams:
126
+ - E02L06I00M
127
+ - E02L06I00B
128
+
129
+ "p":
130
+ name: "Link 7 On"
131
+ telegrams:
132
+ - E02L07I08M
133
+ - E02L07I08B
134
+
135
+ "q":
136
+ name: "Link 7 Off"
137
+ telegrams:
138
+ - E02L07I00M
139
+ - E02L07I00B
@@ -0,0 +1,7 @@
1
+ """TUI widgets package."""
2
+
3
+ from xp.term.widgets.help_menu import HelpMenuWidget
4
+ from xp.term.widgets.protocol_log import ProtocolLogWidget
5
+ from xp.term.widgets.status_footer import StatusFooterWidget
6
+
7
+ __all__ = ["HelpMenuWidget", "ProtocolLogWidget", "StatusFooterWidget"]