# serial2tcp-pro **Repository Path**: outa/serial2tcp-pro ## Basic Information - **Project Name**: serial2tcp-pro - **Description**: 串口转网络转发管理系统,支持 TCP / UDP / HTTP 协议,带 Web 管理界面。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-13 - **Last Updated**: 2026-07-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Serial2TCP Pro 串口转网络转发管理系统,支持 TCP / UDP / HTTP 协议,带 Web 管理界面。 ![image-20260713144506088](images/image-20260713144506088.png) ## 功能 - **协议支持**:TCP (Server/Client)、UDP (Server/Client)、HTTP Server (GET) - **串口参数**:波特率、数据位、停止位、校验位、流控均可配置 - **Web 管理**:Flask + Bootstrap 5 纯本地资源,无 CDN 依赖 - **实时监控**:WebSocket 推送状态更新,数据展示 Hex + ASCII - **数据方向筛选**:详情面板支持按「全部 / 串口→网络 / 网络→串口」筛选,最近 50 条记录 - **共享串口池** ⭐:多个服务可绑定到同一物理串口(如 TCP+UDP+HTTP 同时订阅 COM3),由 `SerialHub` 统一调度;一个串口只打开一次,避开 Windows/Linux 串口独占冲突 - **串口断开自动重连**:物理断线时所有相关服务自动进入"重连中"状态,恢复后自动继续 - **错误实时上抛**:服务启动失败、绑定失败、读写异常会立即通过 WebSocket 推送到前端,弹窗 + 横幅提示 - **Web 日志查看器**:内置 SSE 流式日志面板,支持级别过滤、实时跟踪、清空视图 - **持久化**:SQLite 存储配置,重启自动恢复已启用的服务 - **跨平台**:Windows / Linux / 树莓派 - **systemd 自启**:提供安装/卸载脚本,树莓派开机自动运行 - **USB 串口固定映射**:udev 规则按物理端口绑定 `/dev/ttyCOM1`-`/dev/ttyCOM4`,插拔顺序不影响设备名 - **IP 白名单** ⭐:每个服务可配置允许访问的 IP/CIDR 白名单,阻挡无关设备(如 BlueOS)扫描干扰 ## 安装 ### Windows / Linux ```bash cd serial2tcp-pro pip install -r requirements.txt python app.py ``` 浏览器访问 http://127.0.0.1:11000 ### 树莓派一键部署 ```bash # 1. 固定 USB 串口映射(按物理端口绑定 /dev/ttyCOM1-4) sudo bash scripts/install_udev.sh # 2. 开机自启(自动装依赖、配串口权限、注册 systemd 服务) sudo bash scripts/install_systemd.sh ``` 安装完成后访问 http://<树莓派IP>:11000 ## 树莓派部署 ### 快速安装 ```bash # 固定串口映射 sudo bash scripts/install_udev.sh # 开机自启 sudo bash scripts/install_systemd.sh ``` ### 卸载 ```bash sudo bash scripts/uninstall_systemd.sh # 卸载开机自启 sudo bash scripts/uninstall_udev.sh # 卸载串口映射 ``` ### 常用管理命令 ```bash systemctl status serial2tcp-pro # 查看状态 sudo systemctl restart serial2tcp-pro # 重启 journalctl -u serial2tcp-pro -f # 实时日志 ``` ### USB 串口固定映射 树莓派多个 USB 串口设备插拔顺序不同会导致设备名变化,通过 udev 规则按物理端口固定映射: ```bash sudo bash scripts/install_udev.sh # 安装 ls -la /dev/ttyCOM* # 验证 sudo bash scripts/uninstall_udev.sh # 卸载 ``` 映射关系: | 物理端口 | 固定设备名 | |---------|-----------| | USB 1-1.1 | `/dev/ttyCOM1` | | USB 1-1.2 | `/dev/ttyCOM2` | | USB 1-1.3 | `/dev/ttyCOM3` | | USB 1-1.4 | `/dev/ttyCOM4` | 查看 USB 设备物理位置:`lsusb -t` 或 `udevadm info -a /dev/ttyUSB0` ## 项目结构 ``` serial2tcp-pro/ ├── app.py # Flask 主程序 + WebSocket + SSE ├── engine.py # SerialHub (串口池) + ForwardService (网络端) ├── db.py # SQLite 数据层(部分更新) ├── serialutil.py # 跨平台串口枚举 ├── logutil.py # 日志配置(5MB 轮转 × 5 份) ├── requirements.txt ├── scripts/ │ ├── install_systemd.sh # systemd 服务安装脚本 │ ├── uninstall_systemd.sh # systemd 卸载脚本 │ ├── install_udev.sh # udev 串口固定映射安装脚本 │ └── uninstall_udev.sh # udev 卸载脚本 ├── templates/ │ └── index.html # Web UI └── static/ ├── css/ (bootstrap / icons / style — 全部本地) └── js/ (bootstrap / socket.io / app.js — 全部本地,纯原生 JS) ``` ## 共享串口原理 传统实现下,两个服务都创建 `serial.Serial("COM3")` 会因设备独占而失败。本项目通过 `SerialHub` 解决这个问题: ``` [COM3 物理口] ── SerialHub (持有唯一 serial.Serial 实例) ──┐ ├─ TCP 服务 A ├─ UDP 服务 B └─ HTTP 服务 C ``` - 第一个绑定到 COM3 的服务触发 `hub._open()`:打开底层串口 - 后续服务 `subscribe()` 到现有 hub,不重复打开 - 最后一个服务 `unsubscribe()` 时自动 `close()` 串口 - 串口读取错误(如拔线)→ hub 进入 `reconnecting` → 定时重试 → 成功后所有订阅者自动恢复 - `net→serial` 写入由 hub 内置锁保护(同一时刻只有一个网络帧写入串口) > ⚠️ 同一 hub 下的服务必须使用相同的串口参数(波特率/校验位等)。如果不同,第一个服务生效,后续服务会在日志中收到 warning,仍可继续工作但可能产生乱码。 ## 数据转发记录 详情面板(点击服务卡片 ℹ️ 按钮)展示最近 50 条数据转发记录: - **方向筛选**:全部 / 串口→网络 / 网络→串口 - 每条记录包含:时间、方向 badge、字节数、HEX、ASCII - 面板每 2 秒自动刷新 ## HTTP GET 接口 HTTP 模式下,通过 GET 请求获取串口最新数据: ``` GET http://:/ ``` 返回 JSON: ```json { "service": "服务名", "serial_port": "COM3", "serial_open": true, "buffer_size": 128, "data_hex": "48 65 6c 6c 6f", "data_ascii": "Hello", "timestamp": "2026-07-13 10:30:00" } ``` ## API 端点 | 方法 | 路径 | 说明 | | --- | --- | --- | | GET | `/api/ports` | 枚举本机串口 | | GET | `/api/services` | 列出所有服务 | | POST | `/api/services` | 创建服务 | | GET | `/api/services/` | 获取单个服务配置 | | PUT | `/api/services/` | 更新服务(运行中则自动重启) | | DELETE | `/api/services/` | 删除服务 | | POST | `/api/services//start` | 启动服务(返回 `{ok, error?}`) | | POST | `/api/services//stop` | 停用服务 | | GET | `/api/services//status` | 获取运行时状态(含 data_log、last_error) | | GET | `/api/hubs` | 列出当前所有 SerialHub 状态 | | GET | `/api/logs?lines=200&level=ERROR` | 获取最近日志 | | GET | `/api/logs/stream` | SSE 实时日志流 | ## WebSocket 事件 - `status_update`:每 2s 推送所有服务的状态数组 - `service_error`:运行时错误(新出现)触发,包含 `{id, name, error}` ## 错误提示 任何后端异常(端口占用、串口打不开、参数冲突、读写失败)都会: 1. 写入 `logs/serial2tcp.log`(带 ERROR 级别) 2. 通过 WebSocket `service_error` 事件推送 3. 前端 toast 弹窗 + 顶部红色横幅 4. 卡片上显示具体错误信息 ## 日志 - 文件位置:`logs/serial2tcp.log`(单文件 5MB,最多保留 5 份) - Web 端:点击导航栏"查看日志"打开实时跟踪面板 - 支持级别过滤(INFO/WARNING/ERROR/DEBUG) ## 跨平台 - **Windows**:`COM1`-`COM256`,通过 `serial.tools.list_ports` 枚举 - **Linux / 树莓派**:`/dev/ttyUSB0`、`/dev/ttyACM0` 等,通过 `serial.tools.list_ports` 枚举 - 自动重连逻辑在两边都生效 ## 默认串口参数 ``` baudrate=115200, bytesize=8, stopbits=1, parity=N, flow_control=none ``` 可在创建/编辑服务时修改。 ## IP 白名单 每个服务可独立配置 IP 白名单,阻挡无关设备扫描干扰(如树莓派上的 BlueOS): - **留空**:允许所有 IP 访问(默认) - **单个 IP**:`192.168.1.100` - **CIDR 网段**:`192.168.1.0/24` - **混合**:`192.168.1.100,10.0.0.0/24`(逗号分隔) TCP、UDP、HTTP 三种协议均生效:不在白名单的连接/请求会被直接拒绝并记录日志。 在创建/编辑服务时的「IP 白名单」栏填写,服务卡片上会显示 🛡️ 标识。