termora 0.80.0__tar.gz
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.
- termora-0.80.0/LICENSE +21 -0
- termora-0.80.0/MANIFEST.in +3 -0
- termora-0.80.0/PKG-INFO +201 -0
- termora-0.80.0/README.md +170 -0
- termora-0.80.0/pyproject.toml +72 -0
- termora-0.80.0/requirements.txt +5 -0
- termora-0.80.0/setup.cfg +4 -0
- termora-0.80.0/src/__init__.py +11 -0
- termora-0.80.0/src/__main__.py +6 -0
- termora-0.80.0/src/app.py +151 -0
- termora-0.80.0/src/can/__init__.py +24 -0
- termora-0.80.0/src/can/backend.py +542 -0
- termora-0.80.0/src/can/dbc_support.py +132 -0
- termora-0.80.0/src/core/__init__.py +1 -0
- termora-0.80.0/src/core/filter_rules.py +55 -0
- termora-0.80.0/src/core/i18n.py +61 -0
- termora-0.80.0/src/core/modbus.py +374 -0
- termora-0.80.0/src/core/paths.py +123 -0
- termora-0.80.0/src/core/platformutil.py +116 -0
- termora-0.80.0/src/core/settings.py +518 -0
- termora-0.80.0/src/core/theme.py +778 -0
- termora-0.80.0/src/plugins/__init__.py +1 -0
- termora-0.80.0/src/plugins/autoreply.py +143 -0
- termora-0.80.0/src/plugins/counter.py +125 -0
- termora-0.80.0/src/plugins/host.py +414 -0
- termora-0.80.0/src/plugins/macros.py +1234 -0
- termora-0.80.0/src/plugins/manager.py +121 -0
- termora-0.80.0/src/plugins/modbus_assistant.py +327 -0
- termora-0.80.0/src/plugins/netproxy.py +299 -0
- termora-0.80.0/src/plugins/send_queue.py +122 -0
- termora-0.80.0/src/plugins/serial_bridge.py +225 -0
- termora-0.80.0/src/resources/i18n/en.json +655 -0
- termora-0.80.0/src/resources/i18n/zh_CN.json +655 -0
- termora-0.80.0/src/resources/icons/app.ico +0 -0
- termora-0.80.0/src/resources/icons/app.png +0 -0
- termora-0.80.0/src/resources/icons/app.svg +26 -0
- termora-0.80.0/src/resources/icons/break.svg +5 -0
- termora-0.80.0/src/resources/icons/check_off.svg +3 -0
- termora-0.80.0/src/resources/icons/check_off_light.svg +3 -0
- termora-0.80.0/src/resources/icons/check_on.svg +4 -0
- termora-0.80.0/src/resources/icons/chevron_down.svg +3 -0
- termora-0.80.0/src/resources/icons/chevron_up.svg +3 -0
- termora-0.80.0/src/resources/icons/clear.svg +5 -0
- termora-0.80.0/src/resources/icons/close.svg +4 -0
- termora-0.80.0/src/resources/icons/crc.svg +6 -0
- termora-0.80.0/src/resources/icons/export.svg +5 -0
- termora-0.80.0/src/resources/icons/find.svg +4 -0
- termora-0.80.0/src/resources/icons/freeze.svg +5 -0
- termora-0.80.0/src/resources/icons/hex.svg +4 -0
- termora-0.80.0/src/resources/icons/log.svg +5 -0
- termora-0.80.0/src/resources/icons/open.svg +4 -0
- termora-0.80.0/src/resources/icons/scope.svg +4 -0
- termora-0.80.0/src/resources/icons/send_file.svg +5 -0
- termora-0.80.0/src/resources/icons/session.svg +4 -0
- termora-0.80.0/src/resources/icons/settings.svg +4 -0
- termora-0.80.0/src/resources/icons/tab_close.svg +3 -0
- termora-0.80.0/src/resources/icons/tab_close_light.svg +3 -0
- termora-0.80.0/src/resources/macros/arduino_cli.json +162 -0
- termora-0.80.0/src/resources/macros/bluetooth_hc05.json +162 -0
- termora-0.80.0/src/resources/macros/common_debug.json +162 -0
- termora-0.80.0/src/resources/macros/esp32_at.json +162 -0
- termora-0.80.0/src/resources/macros/gnss.json +162 -0
- termora-0.80.0/src/resources/macros/gps_ublox.json +162 -0
- termora-0.80.0/src/resources/macros/grbl.json +162 -0
- termora-0.80.0/src/resources/macros/lora_at.json +162 -0
- termora-0.80.0/src/resources/macros/marlin_gcode.json +162 -0
- termora-0.80.0/src/resources/macros/modbus.json +162 -0
- termora-0.80.0/src/resources/macros/modem_4g.json +162 -0
- termora-0.80.0/src/resources/macros/serial_hmi.json +162 -0
- termora-0.80.0/src/resources/terminal.svg +500 -0
- termora-0.80.0/src/resources/themes/dark.qss +219 -0
- termora-0.80.0/src/resources/themes/light.qss +178 -0
- termora-0.80.0/src/resources/themes/nord.qss +179 -0
- termora-0.80.0/src/resources/themes/terminal.qss +179 -0
- termora-0.80.0/src/ui/__init__.py +1 -0
- termora-0.80.0/src/ui/can_analyzer.py +1368 -0
- termora-0.80.0/src/ui/can_config_dialog.py +279 -0
- termora-0.80.0/src/ui/can_scope.py +619 -0
- termora-0.80.0/src/ui/collapsible.py +95 -0
- termora-0.80.0/src/ui/control_panel.py +589 -0
- termora-0.80.0/src/ui/ctrl_popup.py +77 -0
- termora-0.80.0/src/ui/data_display.py +626 -0
- termora-0.80.0/src/ui/disk_log_dialog.py +75 -0
- termora-0.80.0/src/ui/display_perf_dialog.py +80 -0
- termora-0.80.0/src/ui/filter_rules_dialog.py +218 -0
- termora-0.80.0/src/ui/flow_layout.py +128 -0
- termora-0.80.0/src/ui/font_dialog.py +193 -0
- termora-0.80.0/src/ui/highlighter.py +124 -0
- termora-0.80.0/src/ui/icons.py +62 -0
- termora-0.80.0/src/ui/log_viewer_dialog.py +133 -0
- termora-0.80.0/src/ui/main_window.py +2173 -0
- termora-0.80.0/src/ui/protocol_panel.py +164 -0
- termora-0.80.0/src/ui/search_bar.py +87 -0
- termora-0.80.0/src/ui/session_dialog.py +173 -0
- termora-0.80.0/src/ui/signal_scope.py +328 -0
- termora-0.80.0/src/ui/status_widget.py +87 -0
- termora-0.80.0/src/ui/tools_dialog.py +118 -0
- termora-0.80.0/src/ui/windowing.py +193 -0
- termora-0.80.0/termora.egg-info/PKG-INFO +201 -0
- termora-0.80.0/termora.egg-info/SOURCES.txt +102 -0
- termora-0.80.0/termora.egg-info/dependency_links.txt +1 -0
- termora-0.80.0/termora.egg-info/entry_points.txt +3 -0
- termora-0.80.0/termora.egg-info/requires.txt +4 -0
- termora-0.80.0/termora.egg-info/top_level.txt +1 -0
termora-0.80.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sunyd168
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
termora-0.80.0/PKG-INFO
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: termora
|
|
3
|
+
Version: 0.80.0
|
|
4
|
+
Summary: Desktop workbench for serial, CAN, and protocol debugging
|
|
5
|
+
Author-email: sunyd168 <sunyd168@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/syd168/Termora
|
|
8
|
+
Project-URL: Repository, https://github.com/syd168/Termora
|
|
9
|
+
Project-URL: Issues, https://github.com/syd168/Termora/issues
|
|
10
|
+
Keywords: serial,uart,can,modbus,terminal,pyside6,protocol
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: System :: Hardware
|
|
22
|
+
Classifier: Topic :: Terminals :: Serial
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: PySide6>=6.6
|
|
27
|
+
Requires-Dist: PySide6-Addons>=6.6
|
|
28
|
+
Requires-Dist: python-can>=4.3
|
|
29
|
+
Requires-Dist: cantools>=39.0
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# Termora
|
|
33
|
+
|
|
34
|
+
[](https://pypi.org/project/termora/)
|
|
35
|
+
[](https://pypi.org/project/termora/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
|
|
38
|
+
Desktop workbench for **serial**, **CAN**, and **protocol** debugging. Built with PySide6, laid out for wide / 2K / 4K screens, with skins and English / 简体中文. Inspired by classic [CuteCom](https://gitlab.com/cutecom/cutecom).
|
|
39
|
+
|
|
40
|
+
The product name is **Termora**. The Python import package stays `cutecom` so existing macros and scripts keep working.
|
|
41
|
+
|
|
42
|
+
面向串口、CAN 与协议调试的桌面工作台。基于 PySide6,界面按大屏设计,支持皮肤与多语言。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install termora
|
|
50
|
+
termora
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or from this repository:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/syd168/Termora.git
|
|
57
|
+
cd Termora
|
|
58
|
+
python3 -m venv .venv
|
|
59
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
60
|
+
pip install -e .
|
|
61
|
+
termora
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Use a **dedicated venv**. Mixing conda `pyside6` with pip `PySide6-Addons` leads to
|
|
65
|
+
`libshiboken6.abi3.so` import errors.
|
|
66
|
+
|
|
67
|
+
### Platform notes
|
|
68
|
+
|
|
69
|
+
| Capability | Linux | macOS | Windows |
|
|
70
|
+
|------------|:-----:|:-----:|:-------:|
|
|
71
|
+
| Serial I/O, sessions, macros, plugins | ✓ | ✓ | ✓ |
|
|
72
|
+
| CAN (virtual / PCAN / Kvaser / Vector / SLCAN, …) | ✓ | ✓* | ✓* |
|
|
73
|
+
| Native SocketCAN | ✓ | — | — |
|
|
74
|
+
| X/Y/Zmodem (`sz` / lrzsz) | ✓ | ✓* | — |
|
|
75
|
+
|
|
76
|
+
\* Needs the matching driver or Homebrew tool. Use the `virtual` CAN backend without hardware.
|
|
77
|
+
|
|
78
|
+
- **Linux**: `sudo usermod -aG dialout $USER` then log in again.
|
|
79
|
+
- **macOS**: ports look like `/dev/cu.*`. Zmodem: `brew install lrzsz`.
|
|
80
|
+
- **Windows**: `COMx` in Device Manager. No X/Y/Zmodem (`sz` + POSIX redirection).
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
termora # GUI
|
|
88
|
+
termora -s Default # named session
|
|
89
|
+
python -m cutecom # same entry point
|
|
90
|
+
python run.py # from a source checkout
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Headless serial (no window; RX on stdout):
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
termora --headless --port /dev/ttyUSB0 --baud 115200 --send "AT" --timeout 2
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| Flag | Meaning |
|
|
100
|
+
|------|---------|
|
|
101
|
+
| `-s`, `--session` | Open a named session |
|
|
102
|
+
| `--port` | Serial device |
|
|
103
|
+
| `--baud` | Baud rate (default `115200`) |
|
|
104
|
+
| `--send` | String to write after open |
|
|
105
|
+
| `--send-file` | File bytes to write after open |
|
|
106
|
+
| `--line-end` | `none` / `lf` / `cr` / `crlf` (headless `--send`) |
|
|
107
|
+
| `--timeout` | Headless read duration in seconds |
|
|
108
|
+
| `--headless` | No GUI; requires `--port` |
|
|
109
|
+
|
|
110
|
+
Logs: repo runs write `logs/` in the project; a pip-installed run uses the OS app-data directory.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Interface
|
|
115
|
+
|
|
116
|
+
Connection settings on the left, a large output pane in the middle, command history above, input bar at the bottom.
|
|
117
|
+
|
|
118
|
+
- **View → Skin**: Light / Dark / Nord / Terminal green
|
|
119
|
+
- **View → Language**: English / 简体中文
|
|
120
|
+
- **View → Connection settings** (`Alt+S`): reopen the sidebar
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Features
|
|
125
|
+
|
|
126
|
+
Aligned with classic CuteCom:
|
|
127
|
+
|
|
128
|
+
- Open/close, baud, data bits, parity, stop bits, flow control, RTS/DTR
|
|
129
|
+
- Read-write / read-only / write-only, auto-reconnect
|
|
130
|
+
- Line endings LF / CR / CRLF / none / Hex, character delay
|
|
131
|
+
- Command history, completion, Ctrl control characters
|
|
132
|
+
- Text / HEX display, control characters, timestamps, find (`F3`)
|
|
133
|
+
- Session manager; disk logs (per session and window)
|
|
134
|
+
- Send file as text or script; X/Y/Zmodem on Linux/macOS (`sz`)
|
|
135
|
+
- Plugins: macro packs (JSON, hand-editable; legacy `.tmf` supported), UDP/TCP proxy, byte counter, Modbus assistant
|
|
136
|
+
|
|
137
|
+
Termora extras:
|
|
138
|
+
|
|
139
|
+
- Skins and language switch
|
|
140
|
+
- Local echo (TX in green)
|
|
141
|
+
- Leave port settings unchanged on open
|
|
142
|
+
- Break, repeat send
|
|
143
|
+
- Freeze scroll / export output (`Ctrl+E`)
|
|
144
|
+
- Live RX/TX B/s, recent devices
|
|
145
|
+
- CRC / checksum tools, protocol pane (NMEA / AT / Modbus)
|
|
146
|
+
- CAN analyzer (multiple backends, DBC, sequenced send)
|
|
147
|
+
- Widescreen sidebar layout
|
|
148
|
+
- Multiple windows (each with its own port and log file)
|
|
149
|
+
|
|
150
|
+
### Macro packs
|
|
151
|
+
|
|
152
|
+
JSON files. Built-in examples live in the package (`cutecom/resources/macros/`). When you run from the repo, user copies go under `config/macros/`.
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"format": "cutecom-macros",
|
|
157
|
+
"version": 2,
|
|
158
|
+
"name": { "en": "ESP32 / ESP-AT", "zh_CN": "ESP32 / ESP-AT" },
|
|
159
|
+
"macros": [
|
|
160
|
+
{ "name": { "en": "Reset", "zh_CN": "复位" }, "command": "AT+RST" }
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Escapes in commands: `\n` `\r` `\t` `\0` `\xFF`. In JSON write `\\`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 中文
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
pip install termora
|
|
173
|
+
termora
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
从源码:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
git clone https://github.com/syd168/Termora.git
|
|
180
|
+
cd Termora
|
|
181
|
+
python3 -m venv .venv
|
|
182
|
+
source .venv/bin/activate
|
|
183
|
+
pip install -e .
|
|
184
|
+
termora
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
请使用项目自己的虚拟环境。不要用混装了 conda `pyside6` 与 pip `PySide6-Addons` 的解释器,否则会报找不到 `libshiboken6.abi3.so`。
|
|
188
|
+
|
|
189
|
+
无界面发串口:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
termora --headless --port /dev/ttyUSB0 --baud 115200 --send "AT" --timeout 2
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Linux 串口权限:`sudo usermod -aG dialout $USER`,重新登录后生效。开发态日志在项目 `logs/`;`pip install` 后使用系统 AppData / Application Support。
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
[MIT](LICENSE). Inspired by [CuteCom](https://gitlab.com/cutecom/cutecom); this is an independent Python implementation.
|
termora-0.80.0/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Termora
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/termora/)
|
|
4
|
+
[](https://pypi.org/project/termora/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
Desktop workbench for **serial**, **CAN**, and **protocol** debugging. Built with PySide6, laid out for wide / 2K / 4K screens, with skins and English / 简体中文. Inspired by classic [CuteCom](https://gitlab.com/cutecom/cutecom).
|
|
8
|
+
|
|
9
|
+
The product name is **Termora**. The Python import package stays `cutecom` so existing macros and scripts keep working.
|
|
10
|
+
|
|
11
|
+
面向串口、CAN 与协议调试的桌面工作台。基于 PySide6,界面按大屏设计,支持皮肤与多语言。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install termora
|
|
19
|
+
termora
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or from this repository:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git clone https://github.com/syd168/Termora.git
|
|
26
|
+
cd Termora
|
|
27
|
+
python3 -m venv .venv
|
|
28
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
29
|
+
pip install -e .
|
|
30
|
+
termora
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Use a **dedicated venv**. Mixing conda `pyside6` with pip `PySide6-Addons` leads to
|
|
34
|
+
`libshiboken6.abi3.so` import errors.
|
|
35
|
+
|
|
36
|
+
### Platform notes
|
|
37
|
+
|
|
38
|
+
| Capability | Linux | macOS | Windows |
|
|
39
|
+
|------------|:-----:|:-----:|:-------:|
|
|
40
|
+
| Serial I/O, sessions, macros, plugins | ✓ | ✓ | ✓ |
|
|
41
|
+
| CAN (virtual / PCAN / Kvaser / Vector / SLCAN, …) | ✓ | ✓* | ✓* |
|
|
42
|
+
| Native SocketCAN | ✓ | — | — |
|
|
43
|
+
| X/Y/Zmodem (`sz` / lrzsz) | ✓ | ✓* | — |
|
|
44
|
+
|
|
45
|
+
\* Needs the matching driver or Homebrew tool. Use the `virtual` CAN backend without hardware.
|
|
46
|
+
|
|
47
|
+
- **Linux**: `sudo usermod -aG dialout $USER` then log in again.
|
|
48
|
+
- **macOS**: ports look like `/dev/cu.*`. Zmodem: `brew install lrzsz`.
|
|
49
|
+
- **Windows**: `COMx` in Device Manager. No X/Y/Zmodem (`sz` + POSIX redirection).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
termora # GUI
|
|
57
|
+
termora -s Default # named session
|
|
58
|
+
python -m cutecom # same entry point
|
|
59
|
+
python run.py # from a source checkout
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Headless serial (no window; RX on stdout):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
termora --headless --port /dev/ttyUSB0 --baud 115200 --send "AT" --timeout 2
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| Flag | Meaning |
|
|
69
|
+
|------|---------|
|
|
70
|
+
| `-s`, `--session` | Open a named session |
|
|
71
|
+
| `--port` | Serial device |
|
|
72
|
+
| `--baud` | Baud rate (default `115200`) |
|
|
73
|
+
| `--send` | String to write after open |
|
|
74
|
+
| `--send-file` | File bytes to write after open |
|
|
75
|
+
| `--line-end` | `none` / `lf` / `cr` / `crlf` (headless `--send`) |
|
|
76
|
+
| `--timeout` | Headless read duration in seconds |
|
|
77
|
+
| `--headless` | No GUI; requires `--port` |
|
|
78
|
+
|
|
79
|
+
Logs: repo runs write `logs/` in the project; a pip-installed run uses the OS app-data directory.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Interface
|
|
84
|
+
|
|
85
|
+
Connection settings on the left, a large output pane in the middle, command history above, input bar at the bottom.
|
|
86
|
+
|
|
87
|
+
- **View → Skin**: Light / Dark / Nord / Terminal green
|
|
88
|
+
- **View → Language**: English / 简体中文
|
|
89
|
+
- **View → Connection settings** (`Alt+S`): reopen the sidebar
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
Aligned with classic CuteCom:
|
|
96
|
+
|
|
97
|
+
- Open/close, baud, data bits, parity, stop bits, flow control, RTS/DTR
|
|
98
|
+
- Read-write / read-only / write-only, auto-reconnect
|
|
99
|
+
- Line endings LF / CR / CRLF / none / Hex, character delay
|
|
100
|
+
- Command history, completion, Ctrl control characters
|
|
101
|
+
- Text / HEX display, control characters, timestamps, find (`F3`)
|
|
102
|
+
- Session manager; disk logs (per session and window)
|
|
103
|
+
- Send file as text or script; X/Y/Zmodem on Linux/macOS (`sz`)
|
|
104
|
+
- Plugins: macro packs (JSON, hand-editable; legacy `.tmf` supported), UDP/TCP proxy, byte counter, Modbus assistant
|
|
105
|
+
|
|
106
|
+
Termora extras:
|
|
107
|
+
|
|
108
|
+
- Skins and language switch
|
|
109
|
+
- Local echo (TX in green)
|
|
110
|
+
- Leave port settings unchanged on open
|
|
111
|
+
- Break, repeat send
|
|
112
|
+
- Freeze scroll / export output (`Ctrl+E`)
|
|
113
|
+
- Live RX/TX B/s, recent devices
|
|
114
|
+
- CRC / checksum tools, protocol pane (NMEA / AT / Modbus)
|
|
115
|
+
- CAN analyzer (multiple backends, DBC, sequenced send)
|
|
116
|
+
- Widescreen sidebar layout
|
|
117
|
+
- Multiple windows (each with its own port and log file)
|
|
118
|
+
|
|
119
|
+
### Macro packs
|
|
120
|
+
|
|
121
|
+
JSON files. Built-in examples live in the package (`cutecom/resources/macros/`). When you run from the repo, user copies go under `config/macros/`.
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"format": "cutecom-macros",
|
|
126
|
+
"version": 2,
|
|
127
|
+
"name": { "en": "ESP32 / ESP-AT", "zh_CN": "ESP32 / ESP-AT" },
|
|
128
|
+
"macros": [
|
|
129
|
+
{ "name": { "en": "Reset", "zh_CN": "复位" }, "command": "AT+RST" }
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Escapes in commands: `\n` `\r` `\t` `\0` `\xFF`. In JSON write `\\`.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 中文
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pip install termora
|
|
142
|
+
termora
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
从源码:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
git clone https://github.com/syd168/Termora.git
|
|
149
|
+
cd Termora
|
|
150
|
+
python3 -m venv .venv
|
|
151
|
+
source .venv/bin/activate
|
|
152
|
+
pip install -e .
|
|
153
|
+
termora
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
请使用项目自己的虚拟环境。不要用混装了 conda `pyside6` 与 pip `PySide6-Addons` 的解释器,否则会报找不到 `libshiboken6.abi3.so`。
|
|
157
|
+
|
|
158
|
+
无界面发串口:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
termora --headless --port /dev/ttyUSB0 --baud 115200 --send "AT" --timeout 2
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Linux 串口权限:`sudo usermod -aG dialout $USER`,重新登录后生效。开发态日志在项目 `logs/`;`pip install` 后使用系统 AppData / Application Support。
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
[MIT](LICENSE). Inspired by [CuteCom](https://gitlab.com/cutecom/cutecom); this is an independent Python implementation.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "termora"
|
|
7
|
+
version = "0.80.0"
|
|
8
|
+
description = "Desktop workbench for serial, CAN, and protocol debugging"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "sunyd168", email = "sunyd168@gmail.com" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"serial",
|
|
15
|
+
"uart",
|
|
16
|
+
"can",
|
|
17
|
+
"modbus",
|
|
18
|
+
"terminal",
|
|
19
|
+
"pyside6",
|
|
20
|
+
"protocol",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Environment :: X11 Applications :: Qt",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"Intended Audience :: End Users/Desktop",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Programming Language :: Python :: 3.10",
|
|
30
|
+
"Programming Language :: Python :: 3.11",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Topic :: System :: Hardware",
|
|
34
|
+
"Topic :: Terminals :: Serial",
|
|
35
|
+
]
|
|
36
|
+
dependencies = [
|
|
37
|
+
"PySide6>=6.6",
|
|
38
|
+
"PySide6-Addons>=6.6",
|
|
39
|
+
"python-can>=4.3",
|
|
40
|
+
"cantools>=39.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/syd168/Termora"
|
|
45
|
+
Repository = "https://github.com/syd168/Termora"
|
|
46
|
+
Issues = "https://github.com/syd168/Termora/issues"
|
|
47
|
+
|
|
48
|
+
[project.scripts]
|
|
49
|
+
termora = "cutecom.app:main"
|
|
50
|
+
cutecom = "cutecom.app:main"
|
|
51
|
+
|
|
52
|
+
[tool.setuptools]
|
|
53
|
+
package-dir = { cutecom = "src" }
|
|
54
|
+
packages = [
|
|
55
|
+
"cutecom",
|
|
56
|
+
"cutecom.core",
|
|
57
|
+
"cutecom.ui",
|
|
58
|
+
"cutecom.plugins",
|
|
59
|
+
"cutecom.can",
|
|
60
|
+
"cutecom.resources",
|
|
61
|
+
"cutecom.resources.i18n",
|
|
62
|
+
"cutecom.resources.icons",
|
|
63
|
+
"cutecom.resources.macros",
|
|
64
|
+
"cutecom.resources.themes",
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[tool.setuptools.package-data]
|
|
68
|
+
cutecom = [
|
|
69
|
+
"resources/**/*.json",
|
|
70
|
+
"resources/**/*.qss",
|
|
71
|
+
"resources/**/*.svg",
|
|
72
|
+
]
|
termora-0.80.0/setup.cfg
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Termora 主入口:解析命令行,在 GUI 与无界面串口模式之间分发。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
import time
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from PySide6.QtCore import QCoreApplication, QIODevice, QTimer
|
|
11
|
+
from PySide6.QtSerialPort import QSerialPort
|
|
12
|
+
from PySide6.QtWidgets import QApplication
|
|
13
|
+
|
|
14
|
+
from cutecom import APP_ID, APP_NAME, APP_ORG, VERSION
|
|
15
|
+
from cutecom.core.settings import AppSettings
|
|
16
|
+
from cutecom.core.theme import ui_font
|
|
17
|
+
from cutecom.ui.icons import app_icon
|
|
18
|
+
from cutecom.ui.main_window import MainWindow
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _run_headless(args: argparse.Namespace) -> int:
|
|
22
|
+
"""无界面模式:打开串口,可选发送字符串或文件,将 RX 写入 stdout 后按超时退出。"""
|
|
23
|
+
app = QCoreApplication([APP_NAME])
|
|
24
|
+
app.setOrganizationName(APP_ORG)
|
|
25
|
+
app.setApplicationName(APP_ID)
|
|
26
|
+
app.setApplicationVersion(VERSION)
|
|
27
|
+
|
|
28
|
+
port = QSerialPort()
|
|
29
|
+
port.setPortName(args.port)
|
|
30
|
+
port.setBaudRate(args.baud)
|
|
31
|
+
port.setDataBits(QSerialPort.DataBits.Data8)
|
|
32
|
+
port.setParity(QSerialPort.Parity.NoParity)
|
|
33
|
+
port.setStopBits(QSerialPort.StopBits.OneStop)
|
|
34
|
+
if not port.open(QIODevice.OpenModeFlag.ReadWrite):
|
|
35
|
+
print(f"termora: cannot open {args.port}: {port.errorString()}", file=sys.stderr)
|
|
36
|
+
return 1
|
|
37
|
+
|
|
38
|
+
def on_ready() -> None:
|
|
39
|
+
data = bytes(port.readAll())
|
|
40
|
+
if data:
|
|
41
|
+
sys.stdout.buffer.write(data)
|
|
42
|
+
sys.stdout.buffer.flush()
|
|
43
|
+
|
|
44
|
+
port.readyRead.connect(on_ready)
|
|
45
|
+
|
|
46
|
+
if args.send:
|
|
47
|
+
payload = args.send.encode("utf-8", errors="replace")
|
|
48
|
+
if args.line_end == "crlf":
|
|
49
|
+
payload += b"\r\n"
|
|
50
|
+
elif args.line_end == "cr":
|
|
51
|
+
payload += b"\r"
|
|
52
|
+
elif args.line_end == "lf":
|
|
53
|
+
payload += b"\n"
|
|
54
|
+
port.write(payload)
|
|
55
|
+
port.flush()
|
|
56
|
+
|
|
57
|
+
if args.send_file:
|
|
58
|
+
path = Path(args.send_file)
|
|
59
|
+
if not path.is_file():
|
|
60
|
+
print(f"termora: file not found: {path}", file=sys.stderr)
|
|
61
|
+
port.close()
|
|
62
|
+
return 1
|
|
63
|
+
port.write(path.read_bytes())
|
|
64
|
+
port.flush()
|
|
65
|
+
|
|
66
|
+
deadline = time.monotonic() + max(0.0, args.timeout)
|
|
67
|
+
timer = QTimer()
|
|
68
|
+
timer.setInterval(50)
|
|
69
|
+
|
|
70
|
+
def tick() -> None:
|
|
71
|
+
if time.monotonic() >= deadline:
|
|
72
|
+
port.close()
|
|
73
|
+
app.quit()
|
|
74
|
+
|
|
75
|
+
timer.timeout.connect(tick)
|
|
76
|
+
timer.start()
|
|
77
|
+
return app.exec()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def main(argv: list[str] | None = None) -> int:
|
|
81
|
+
parser = argparse.ArgumentParser(description=f"{APP_NAME} {VERSION}")
|
|
82
|
+
parser.add_argument("-s", "--session", default="", help="Open a named session")
|
|
83
|
+
parser.add_argument("--port", default="", help="Serial device (CLI)")
|
|
84
|
+
parser.add_argument("--baud", type=int, default=115200, help="Baud rate for --port")
|
|
85
|
+
parser.add_argument("--send", default="", help="Send a string after open")
|
|
86
|
+
parser.add_argument("--send-file", default="", help="Send a file after open")
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
"--line-end",
|
|
89
|
+
choices=("none", "lf", "cr", "crlf"),
|
|
90
|
+
default="lf",
|
|
91
|
+
help="Line ending appended to --send (headless)",
|
|
92
|
+
)
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
"--timeout",
|
|
95
|
+
type=float,
|
|
96
|
+
default=2.0,
|
|
97
|
+
help="Seconds to keep reading in headless mode before exit",
|
|
98
|
+
)
|
|
99
|
+
parser.add_argument(
|
|
100
|
+
"--headless",
|
|
101
|
+
action="store_true",
|
|
102
|
+
help="No GUI: open --port, send, print RX to stdout",
|
|
103
|
+
)
|
|
104
|
+
args = parser.parse_args(argv)
|
|
105
|
+
|
|
106
|
+
if args.headless:
|
|
107
|
+
if not args.port:
|
|
108
|
+
parser.error("--headless requires --port")
|
|
109
|
+
# 使用 QCoreApplication,不实例化 QWidget,适合脚本与管道场景。
|
|
110
|
+
return _run_headless(args)
|
|
111
|
+
|
|
112
|
+
app = QApplication(sys.argv if argv is None else [APP_NAME, *argv])
|
|
113
|
+
app.setOrganizationName(APP_ORG)
|
|
114
|
+
app.setApplicationName(APP_ID)
|
|
115
|
+
app.setApplicationDisplayName(APP_NAME)
|
|
116
|
+
app.setApplicationVersion(VERSION)
|
|
117
|
+
# 资源图标缺失时 isNull(),跳过 setWindowIcon 以免占位空图标。
|
|
118
|
+
icon = app_icon()
|
|
119
|
+
if not icon.isNull():
|
|
120
|
+
app.setWindowIcon(icon)
|
|
121
|
+
|
|
122
|
+
settings = AppSettings()
|
|
123
|
+
settings.read(args.session)
|
|
124
|
+
if args.port:
|
|
125
|
+
settings.update_session(device=args.port, baud_rate=args.baud)
|
|
126
|
+
app.setFont(ui_font(settings.language))
|
|
127
|
+
window = MainWindow(settings, args.session)
|
|
128
|
+
if args.port:
|
|
129
|
+
window.control.apply_session(settings.current_session())
|
|
130
|
+
window.show()
|
|
131
|
+
if args.port:
|
|
132
|
+
QTimer.singleShot(0, window.open_device)
|
|
133
|
+
# 延迟发送,等待 open_device 完成后再写串口。
|
|
134
|
+
if args.send_file:
|
|
135
|
+
def _send_file_later() -> None:
|
|
136
|
+
path = Path(args.send_file)
|
|
137
|
+
if path.is_file() and window.device.isOpen():
|
|
138
|
+
window._write_bytes(path.read_bytes())
|
|
139
|
+
|
|
140
|
+
QTimer.singleShot(400, _send_file_later)
|
|
141
|
+
if args.send:
|
|
142
|
+
def _send_later() -> None:
|
|
143
|
+
if window.device.isOpen():
|
|
144
|
+
window.input.setText(args.send)
|
|
145
|
+
window.exec_cmd(clear_input=False)
|
|
146
|
+
|
|
147
|
+
QTimer.singleShot(400, _send_later)
|
|
148
|
+
return app.exec()
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""CAN 分析器公共导出:帧/过滤器类型与可选 python-can 后端封装。"""
|
|
2
|
+
|
|
3
|
+
from cutecom.can.backend import (
|
|
4
|
+
BusStats,
|
|
5
|
+
CanBackendKind,
|
|
6
|
+
CanBusBackend,
|
|
7
|
+
CanConnectionConfig,
|
|
8
|
+
CanFilter,
|
|
9
|
+
CanFrame,
|
|
10
|
+
list_interfaces,
|
|
11
|
+
)
|
|
12
|
+
from cutecom.can.dbc_support import DbcDatabase, DecodedSignal
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"BusStats",
|
|
16
|
+
"CanBackendKind",
|
|
17
|
+
"CanBusBackend",
|
|
18
|
+
"CanConnectionConfig",
|
|
19
|
+
"CanFilter",
|
|
20
|
+
"CanFrame",
|
|
21
|
+
"DbcDatabase",
|
|
22
|
+
"DecodedSignal",
|
|
23
|
+
"list_interfaces",
|
|
24
|
+
]
|