# Logger01 **Repository Path**: weekend/logger01 ## Basic Information - **Project Name**: Logger01 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-12 - **Last Updated**: 2026-09-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Logger01 采集设备调试工具(Qt5 Widgets):通过 TCP 或串口连接 M20x 系列采集设备(支持主机模块串接多台从机),下发采集参数、控制推流启停、查询设备信息,并实时打印解析后的数据帧与原始收发报文。 ## 功能 - **多设备管理**:网格卡片视图,勾选设备后对其执行批量操作;设备列表持久化(config.json) - **TCP / 串口 / HU(USB) 三传输**:TCP 自动绕过系统代理;串口自动枚举可用端口,参数可配置;HU 设备经 CH375DLL 访问 USB 批量端点(需厂商驱动,运行时自动探测 DLL) - **参数下发**(异步队列,不阻塞界面):采集速度(1s/100ms/10ms/1ms)、通道类型(协议类型表 29 种,统一应用到 8 通道),等待设备 `set ok` 应答,超时可配置 - **推流控制**:启动/停止命令按链路自动选择(网口 `00 02` / 串口 `00 01` 变体) - **设备信息查询**:解析从机信息帧(设备号/型号/协议版本/通道数/通道类型/采样周期) - **数据帧解析**:流式扫描(处理粘包/半包/坏帧重同步),解码设备号/包计数/传输参数/时间戳/数值(float 等常见类型) - **日志**:界面实时展示 + 按天分文件双写;原始收发全量 hex + 解析摘要每包必记;区分协议应答与坏数据 ## 协议要点(M20x数据传输协议V2) - 设备为 **TCP 服务端**(默认端口 **8655**),连接后不主动推流,必须下发启动命令 - modbus 格式,广播地址 FF,CRC16-MODBUS 低字节在前 - 关键命令:启动推流 `FF 10 00 32 ... 00 02`(串口变体 `... 00 01`)、停止 `... 00 00`、速度 `00 17`、通道类型 `00 11`、设备信息 `00 35` - 设备应答:参数设置回 `set ok %02d`,设备信息回文本行 + N×32 字节二进制帧 - 串接从机共用一条主机链路,靠数据帧内设备号区分 ## 构建 - Qt 5.15.x(msvc2022_64)+ CMake ≥3.16 + VS2022 - `CMakeLists.txt` 中 `STATIC_QT` 开关(默认 ON):ON 使用静态 Qt(`msvc2022_64-static` 前缀,静态 CRT + 平台插件内链),OFF 使用动态 Qt - 静态 Qt 自建脚本:`build-qt-static.bat`(qtbase + qtserialport,安装到 `F:\Qt\Qt5.15.17\5.15.17\msvc2022_64-static`) ## 打包 ``` package.bat # 缺省静态: 产出 package\Logger01_<日期>__static\ 单文件 exe(零依赖) package.bat dynamic # 动态: windeployqt 收集依赖的目录版 ``` ## 使用 1. 点"添加"输入 `ip:端口`(如 `192.168.0.123:8655`)或选择串口及参数;地址自动去重 2. 勾选设备(勾选 = 参与批量操作),点"连接";双击卡片可编辑地址 3. (可选)在"采集配置"区选好速度/通道类型,点"下发配置",等待设备回 `set ok` 4. 点"启动"开始推流,"停止"结束;点"查询设备"查看串接的从机信息 5. 命令超时可在操作区调整(默认 5000ms,修改立即生效) 注意:设备推流状态会跨连接保持——程序异常退出后重连,数据会自动恢复(无需再点启动);主动停止即可关闭推流。 ## 代码结构 ``` src/ ├── main.cpp # 装配: 初始化日志 → 读配置 → 创建主窗口 ├── mainwindow.h/.cpp # 界面布局、设备列表、批量操作(信号槽均为成员函数) ├── commclient.h/.cpp # 传输无关的设备客户端: 异步命令队列 + 应答解析 + CRC16-MODBUS ├── deviceinfo.h/.cpp # 从机信息帧解析(设备/通道/采样周期) ├── dataframe.h/.cpp # 推流数据帧流式解析(校验/坏帧重同步/数值解码) ├── appconfig.h/.cpp # config.json 读写(设备列表 + 命令超时 + 采集配置) ├── gatherconfig.h/.cpp # 采集配置(速度/通道类型, 仅协议可下发的设备侧参数) ├── logger.h/.cpp # 日志双写单例(界面文本框 + 按天分文件) ├── devicecarddelegate.h/.cpp # 设备网格卡片自绘 ├── deviceaddressdialog.h/.cpp # 添加/编辑设备对话框(TCP/串口单选) ├── protocol.h # 协议常量唯一来源(命令帧/类型表/档位) ├── app.rc / resources.qrc # exe 图标与窗口图标资源 └── shiliu.ico ``` ## 外部控制 RPC 程序启动后监听所有网卡的 `7777` 端口(`config.json` 的 `rpcPort` 可改,0 = 禁用),局域网内其它机器可通过 `<本机IP>:7777` 访问(无鉴权,仅限内部工具使用),每行一个 JSON 命令: | 命令 | 参数 | 说明 | |---|---|---| | `status` | - | 设备列表及状态 | | `start` / `stop` | - | 启动/停止推流(勾选且已连接的设备) | | `apply_config` | `speed`(0~3), `channelType` | 下发采集配置 | | `query_devices` | - | 查询从机信息(结果看日志) | | `connect` / `disconnect` | `addr` | 连接/断开指定设备 | 服务端同时兼容裸 TCP 行 JSON 和 HTTP 两种方式,`GET /状态命令` 可直接查询: ``` curl http://127.0.0.1:7777/status ``` curl 测试示例(全部命令): ```bat rem 查询设备列表及状态 curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"status\"}" rem 启动 / 停止推流 curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"start\"}" curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"stop\"}" rem 下发采集配置 (speed: 0=1s 1=100ms 2=10ms 3=1ms; channelType: 如 15=0x0F K型) curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"apply_config\",\"speed\":0,\"channelType\":15}" rem 查询从机信息 (结果看 Logger01 日志) curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"query_devices\"}" rem 连接 / 断开指定设备 curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"connect\",\"addr\":\"192.168.0.123:8655\"}" curl -s http://127.0.0.1:7777 -d "{\"cmd\":\"disconnect\",\"addr\":\"192.168.0.123:8655\"}" ``` Python 示例: ```python import socket, json s = socket.create_connection(("127.0.0.1", 7777)) s.sendall(b'{"cmd":"status"} ') print(s.recv(65536).decode()) ``` ## MCP 接入(AI 控制) `tools/mcp_server.py` 把上述 RPC 暴露为 MCP 工具,AI 助手(Claude Desktop/Cursor 等)可直接控制 Logger01: 1. `pip install mcp` 2. 在 AI 客户端的 MCP 配置(如 `claude_desktop_config.json`)中加入: ```json { "mcpServers": { "logger01": { "command": "python", "args": ["F:/git/Hello/Logger01/tools/mcp_server.py"] } } } ``` 3. 重启 AI 客户端后即可对话控制:"启动采集" / "把采样速度调成 10ms" / "现在设备什么状态" 工具清单:`get_status` / `start_gather` / `stop_gather` / `apply_config(speed, channel_type)` / `query_devices` / `connect_device(addr)` / `disconnect_device(addr)` ### 只有 AI API 地址时(无 MCP 客户端) 用 `tools/ai_agent.py` 走 function calling 循环(OpenAI 兼容接口),填好 `API_URL/API_KEY/MODEL` 后: ``` python tools/ai_agent.py "启动采集并告诉我设备状态" ``` ## 对象结构 单线程事件循环(GUI 线程)承载全部对象,并发靠 Qt 事件驱动 + 每连接异步命令队列,无锁。 ``` QApplication ├─ Logger (单例) 日志双写: 界面文本框 + 按天分文件 │ └─ logView_ ────(引用)────▶ MainWindow::logView_ │ ├─ RpcServer (QTcpServer, 监听所有网卡:7777) │ ├─ 裸 TCP 行 JSON / HTTP POST(GET /命令) 双协议 │ ├─ 防火墙降级: 用户拒绝弹窗 → netsh 检测阻止规则 → 降级 127.0.0.1 │ └─ dispatch ──调用──▶ MainWindow 公有控制接口 │ deviceStatusList / startGatherAll / stopGatherAll / │ applyConfigAll / queryDevicesAll / connectDevice / disconnectDevice │ └─ MainWindow (QMainWindow) ├─ deviceModel_ (QStandardItemModel, 网格卡片数据源) │ └─ item×N: IpPortRole/SerialRole/CheckState/StatusText ── ClientRole ──▶ CommClient ├─ deviceList_ (QListView) ── DeviceCardDelegate (自绘卡片) ├─ clients: CommClient ×N (parent=MainWindow) │ ├─ TCP: tcpSocket_ (NoProxy) 串口: serialPort_ │ ├─ pendingCmds_ + cmdTimer_ 异步命令队列 (set ok 应答/超时推进, 不阻塞 UI) │ ├─ infoBuffer_/awaitingInfo_ 查询设备信息应答 │ ├─ streamBuffer_ 推流帧扫描 (DataFrame::tryExtract) │ └─ 静态 crc16()/withCrc() CRC16-MODBUS ├─ config_ (AppConfig) │ ├─ devices_: {addr, serial, checked} ×N ◀─▶ config.json │ ├─ commandTimeoutMs_ 操作区 SpinBox 即时应用 │ ├─ rpcPort_ RPC 端口 (0=禁用) │ └─ gather_ (GatherConfig): speed + channelType ├─ dataLogCount_: QHash<(连接,从机设备号), 收包数> └─ 信号连接 (每个 CommClient 一套, 同线程直连, 槽内 sender() 取来源) connected/disconnected/errorOccurred(msg,transient) ─▶ 卡片状态+按钮(勾选驱动) deviceInfoReceived ─▶ 从机概要日志 gatherDataReceived ─▶ 每包必记日志 外部 (可选): tools/mcp_server.py ──TCP JSON──▶ RpcServer AI MCP 工具桥 ``` 数据流(以串口设备为例): ``` 设备推流 ─▶ readyRead ─▶ onReadyRead ─┬─ cmdBusy_? ▶ cmdReplyBuffer_ (等 set ok) ▶ 队列推进 ├─ awaitingInfo_? ▶ infoBuffer_ ▶ DeviceInfo 解析 └─ 否则 ▶ streamBuffer_ ▶ DataFrame 解析 ▶ 日志/信号 ``` ## AI 助手(程序内) 右侧"AI 助手"面板:对话方式直接操作设备。AI 通过本机 RPC 执行工具(status/start/stop/apply_config/query_devices),调用过程在面板中透明可见(⚙ 行)。 配置 `config.json` 的 `ai` 节后重启程序: ```json { "ai": { "apiUrl": "https://你的API地址/v1/chat/completions", "apiKey": "你的KEY", "model": "模型名", "tools": [ ... ] // 工具表(function calling schema), 首次运行自动生成默认值, 可编辑 } } ``` 首次运行时若 config.json 不存在会自动生成包含全部默认项(含 5 个默认工具)的配置文件;`ai.tools` 即发送给 AI 的工具说明书,可自行增删改(改坏可删除该字段恢复默认)。 要求 OpenAI 兼容接口(chat/completions + tools)。面板可停靠/浮动/关闭,通过菜单"查看"可重新打开。 ## 日志字体 `config.json` 的 `log.fonts` 为字体回退链(按顺序取第一个系统可用的字体,类似 Chrome 的 font stack,全部缺失则用 Qt 默认): ```json { "log": { "fonts": ["Cascadia Mono", "Consolas", "Menlo", "SF Mono", "Ubuntu Mono", "Ubuntu Sans Mono", "Courier New", "Microsoft YaHei"] } } ``` 首次启动会自动写入默认值;中英混排建议最后一个放中文字体(如 Microsoft YaHei)。 ## 注意 - Qt 静态链接为 LGPL 授权,对外分发闭源软件时需遵守相应义务;自用/内部工具无碍 - 运行依赖:静态版单 exe 即可;动态版需 Qt DLL 与 VC 运行库