From 28418dab66999738ecc5107f8993d867dc215ab7 Mon Sep 17 00:00:00 2001 From: wangfq Date: Thu, 10 Sep 2026 21:46:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(vd960Air):=20=E9=85=8D=E7=BD=AE=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=94=B9=E7=94=A8=200x8F=20=E6=9C=AC=E6=9C=BA?= =?UTF-8?q?=E4=BE=A7=E7=A7=81=E6=9C=89=E5=B8=A7=EF=BC=9BMQTT=20=E5=87=AD?= =?UTF-8?q?=E6=8D=AE=E5=A4=96=E7=BD=AE=E5=88=B0=E9=9D=9E=E8=B7=9F=E8=B8=AA?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - readme §2.2/§3:0x7D 帧设计稿 v0.2 作废,改写为「0x7F 业务帧字节流 + 0x8F 本机侧私有帧」 (权威源规则 / 拉取为主+推送为辅 / 帧长上限 260B / 两侧缓冲需同步扩容),依据协议 §6.9 - readme §3.1:对比表由 0x7D 改为 0x8F,保留 0x7F 帧布局参考 - config.lua / uart_app.lua:注释中的 0x7D 计划改为 0x8F 配置同步;协议版本引用 V1.13 → V1.14 - config.lua:MQTT 账号密码不再明文入库,改从 cred.lua 读取;缺失时降级为空串(匿名连接) - 新增 .gitignore(忽略 cred.lua)+ cred.lua.example(填写模板) ⚠ 原明文凭据已存在于 git 历史,商用前必须更换服务器密码 - 语法:luac5.3 -p config.lua / cred.lua / uart_app.lua 全部通过 --- .../module/Air780EPM/demo/vd960Air/.gitignore | 2 + .../module/Air780EPM/demo/vd960Air/config.lua | 28 ++++--- .../Air780EPM/demo/vd960Air/cred.lua.example | 12 +++ .../module/Air780EPM/demo/vd960Air/readme.md | 73 ++++++++++++------- .../Air780EPM/demo/vd960Air/uart_app.lua | 2 +- 5 files changed, 79 insertions(+), 38 deletions(-) create mode 100644 luatos/air780epm/module/Air780EPM/demo/vd960Air/.gitignore create mode 100644 luatos/air780epm/module/Air780EPM/demo/vd960Air/cred.lua.example diff --git a/luatos/air780epm/module/Air780EPM/demo/vd960Air/.gitignore b/luatos/air780epm/module/Air780EPM/demo/vd960Air/.gitignore new file mode 100644 index 0000000..f7edd56 --- /dev/null +++ b/luatos/air780epm/module/Air780EPM/demo/vd960Air/.gitignore @@ -0,0 +1,2 @@ +# 敏感凭据(不入库) —— 见 cred.lua.example +cred.lua diff --git a/luatos/air780epm/module/Air780EPM/demo/vd960Air/config.lua b/luatos/air780epm/module/Air780EPM/demo/vd960Air/config.lua index 1905846..aa0742c 100644 --- a/luatos/air780epm/module/Air780EPM/demo/vd960Air/config.lua +++ b/luatos/air780epm/module/Air780EPM/demo/vd960Air/config.lua @@ -6,19 +6,29 @@ vd960Air 是 Air8781P 整板(Air780EPM 核心模组)上的 LuatOS 应用, 作为 vd960DBN 车检器在有线网络失效时的 4G 兜底通道(方案 C: Air780 协议转换)。 -协议依据:《DLD960_IoT_MQTT协议》V1.13(4G 通道适配方案 C,标准 JSON 命令面) +协议依据:《DLD960_IoT_MQTT协议》V1.14(4G 通道适配方案 C,标准 JSON 命令面) ]] -- ==================== MQTT 服务器 ==================== --- 测试服务器(2026-09-10 用户提供): 110.41.131.144:1883, admin/password --- 注: 后续 vd960DBN 更新版本后,经 BLE 设置的服务器参数会同步下发覆盖此处(配置同步, P1) --- ⚠ 商用环境须替换为平台实际地址; 密码不应长期写死在代码里(应走 §2.2 配置同步链路) -CFG_MQTT_HOST = "110.41.131.144" -CFG_MQTT_PORT = 1883 +-- 测试服务器(2026-09-10 用户提供): host/port 见下(出厂默认值) +-- 注: 后续 vd960DBN 更新版本后,经 BLE 设置的服务器参数会同步下发覆盖此处(配置同步, 协议 §6.9) +-- ⚠ 商用环境须替换为平台实际地址 +-- +-- 敏感凭据从非跟踪文件 cred.lua 读取(不入版本库; 模板见 cred.lua.example) +-- 缺失时为空串 -> 匿名连接(不崩, 仅 broker 侧鉴权失败后按重连逻辑重试) +-- ⚠ 2026-09-10 之前凭据曾明文写在 config.lua 并已入库(git 历史), 商用前必须更换服务器密码 +local _cred_ok, _cred = pcall(require, "cred") +if not _cred_ok or type(_cred) ~= "table" then + _cred = {} + if log then log.warn("config", "cred.lua 缺失或非法 -> 凭据为空(匿名), 请复制 cred.lua.example") end +end + +CFG_MQTT_HOST = _cred.mqtt_host or "110.41.131.144" +CFG_MQTT_PORT = _cred.mqtt_port or 1883 -- MQTT 鉴权(mqtt_main 调用 mqtt_client:auth; 空串表示匿名) -CFG_MQTT_USER = "admin" -CFG_MQTT_PASS = "password" +CFG_MQTT_USER = _cred.mqtt_user or "" +CFG_MQTT_PASS = _cred.mqtt_pass or "" -- ==================== 设备标识 ==================== -- 设备序列码: 6 字节十六进制字符串(与 vd960DBN dev_serial 一致,有线/4G 同一设备) @@ -45,7 +55,7 @@ CFG_UART_ID = 1 CFG_UART_BAUD = 115200 -- 链路帧: 0x7F 帧字节流(方案 C,数据面透传 Loop 地感协议) --- 0x7D 帧仅用于 DBN↔Air780 配置同步/握手(P1) +-- 0x8F 本机侧私有帧用于 DBN↔Air780 配置同步(拉取+推送,协议 §6.9)(P1) -- ==================== 上报节奏 ==================== CFG_HEARTBEAT_INTERVAL = 60 -- 心跳周期(秒,协议 §5.4 默认 60) diff --git a/luatos/air780epm/module/Air780EPM/demo/vd960Air/cred.lua.example b/luatos/air780epm/module/Air780EPM/demo/vd960Air/cred.lua.example new file mode 100644 index 0000000..9b7f4ae --- /dev/null +++ b/luatos/air780epm/module/Air780EPM/demo/vd960Air/cred.lua.example @@ -0,0 +1,12 @@ +--[[ +@module cred +@summary vd960Air 敏感凭据模板 —— 复制为同目录 cred.lua 并填写实际值 +@usage cp cred.lua.example cred.lua && 编辑 cred.lua +]]-- +-- ⚠ cred.lua 已列入 .gitignore, 不会入库。切勿把真实凭据写回 config.lua 或任何跟踪文件。 +return { + mqtt_host = "MQTT_服务器_IP或域名", + mqtt_port = 1883, + mqtt_user = "MQTT_用户名", + mqtt_pass = "MQTT_密码", +} diff --git a/luatos/air780epm/module/Air780EPM/demo/vd960Air/readme.md b/luatos/air780epm/module/Air780EPM/demo/vd960Air/readme.md index b87506d..6113df5 100644 --- a/luatos/air780epm/module/Air780EPM/demo/vd960Air/readme.md +++ b/luatos/air780epm/module/Air780EPM/demo/vd960Air/readme.md @@ -53,7 +53,7 @@ **已定稿(用户决策 2026-08-31):** - ✅ **方案 B(原始帧透传)正式采用** - ✅ **4G 上报格式 = hex 封装**(平台友好,参照 log_query records hex 风格) -- ✅ **0x7D 帧去留**: 数据面走 0x7F 帧字节流透传(不需要 0x7D);0x7D 帧仅保留给"配置同步下发/握手" +- ✅ **0x7D 帧作废(2026-09-10 用户决策)**: 数据面走 0x7F 帧字节流透传;配置同步改用 **0x8F 本机侧私有帧**(与 BLE 同魔数,两端各自本地消费、不转发,见 §2.2) **待确认(影响定稿):** - [ ] 上行双通道策略: 默认 4G / 有线失效才走 4G / 双通道并存(呼应 §6 通道切换讨论) @@ -95,7 +95,7 @@ 1. 新增上行 `frame_report` + 下行 `frame_cmd` 两个命令(4G 通道专用) 2. **平台双通道格式差异说明**: 有线通道 = 标准 JSON 业务命令(loop_data/event_report);4G 通道 = frame_report/frame_cmd(hex 帧透传)——平台须按通道区分解析 3. 4G 通道网络配置类命令不适用(ssc_net_* / iot_net_* / iot_topic_*,返回 code=4 或文档标注) -4. 链路层: 数据面 0x7F 帧字节流;0x7D 帧仅 DBN↔Air780 配置同步/握手(§2.2) +4. 链路层: 数据面 0x7F 帧字节流;**0x8F 本机侧私有帧**用于 DBN↔Air780 配置同步(§2.2) 5. 平台侧新增《DLD960Loop_串口通信协议》解析依赖(hex → 帧) **与方案 A(JSON 桥)对比:** @@ -106,19 +106,28 @@ | Air780 侧职责 | MQTT 壳 + JSON 透传 | 0x7F 帧切包 + MQTT + 封装 | | 平台侧 | 收标准 JSON(与有线一致) | 收 0x7F 帧/hex 封装(需解析《DLD960Loop_串口通信协议》) | | 地感指令下行 | 经 JSON 命令中转 | **原样透传,零改造** | -| 链路帧 | 0x7D 帧(2B LEN 装 JSON) | 0x7F 帧字节流(不需要 0x7D,或仅配置用) | +| 链路帧 | 0x7D 帧(2B LEN 装 JSON) — **已作废** | 0x7F 帧字节流 + 0x8F 配置同步帧(§3) | ### 2.2 服务器参数配置链路(用户决策 2026-08-31,列入 vd960DBN 开发计划) -**服务器参数(地址/端口/ClientID/账号密码/Topic)当前由小程序 BLE 蓝牙设置。** 规划: +**服务器参数(地址/端口/ClientID/账号密码/Topic)由小程序 BLE 蓝牙设置,经 UART1 同步到 Air780。**(2026-09-10 定稿) ``` -小程序 → BLE → vd960DBN(CH32V208) → UART1(0x7D 帧) → Air780 存储(LuatOS fskv/luadb) +小程序 → BLE → vd960DBN(CH32V208) → UART1(0x8F 本机侧私有帧) → Air780 fskv 缓存 ``` -- **vd960DBN 更新版本(列入计划)**: 小程序设置服务器/topic 相关参数(BLE 0x13/0x15 等)时,同步经 UART1 组帧下发 Air780 -- **Air780 侧**: 新增"配置下发"UART 命令处理——收到后更新本地配置存储;`config.lua` 值降级为**出厂默认**(运行时优先读存储) -- 协议面: 在《DLD960_IoT_MQTT协议》4G 适配章节新增"配置同步下发"命令(方向 srv 语义,经 DBN 透传或 DBN 主动下发) +**权威源规则**: 配置权威源 = **DBN 侧 flash**(`IOT_NET_INFO`/`IOT_Topic`)。Air780 的 fskv **仅作启动缓存**, +唯一合法写入者 = **收到的 DBN 配置帧**;平台经 4G 下发配置一律拒绝(《DLD960_IoT_MQTT协议》§6.6 回 `code=4`)。 + +- **vd960DBN 侧**: BLE 写 `0x13`(SET_IOT_NET)/`0x15`(SET_IOT_TOPIC)/`0x09`(UPDATE_DEV_SERIAL) 成功后, + ① 应答 Air780 的配置请求(拉取);② 链路可用时主动推送。命令复用 `0x14`(GET_IOT_NET)/`0x16`(GET_IOT_TOPIC), + 载荷复用 `set_response_iot_net/topic()` 构造器 → **与 BLE 读响应逐字节同源**(零新增序列化) +- **Air780 侧**: `config.lua` 值降级为**出厂默认**;上电先读 fskv 缓存立即连接,再拉权威值校准; + 配置变化 → 断开重连重订阅。`frame_parser.lua` 增 `0x8F` 分支(本地消费,不转发); + 配置读取从 require 期 `local` 改为**重连时重读**;fskv **仅在值变化时写入**(littlefs 擦写磨损) +- **DBN 不维护"待同步"标志位**: 推送时链路不可用则等 Air780 下次拉取(无状态,天然自愈) +- **帧长上限**: `0x8F` 独立上限 **260B**(LEN 1B ≤255);`0x7F` 业务帧维持 70B —— **两侧帧缓冲需同步扩容** +- 协议面: 《DLD960_IoT_MQTT协议》**§6.9 4G 配置同步** - 好处: 现场换 4G 模块/重新配对时,参数随 BLE 一次配好,不依赖 Air780 单独刷脚本 ### 2.3 4G 特有字段: link 对象(用户决策 2026-08-31) @@ -155,17 +164,24 @@ - JSON 解析失败时原样转发,不阻塞上行 - 开关: `config.lua` `CFG_LINK_ENABLE` -## 3 UART 链路帧协议(设计稿 v0.2,校验已定稿) +## 3 UART 链路帧协议(定稿: 0x7F 业务帧 + 0x8F 本机侧私有帧) + +> **原"设计稿 v0.2"(0x7D 帧 / 2B 大端 LEN / PAYLOAD 装 JSON ≤2048)已作废**(2026-09-10 用户决策)。 +> 实际采用 vd960DBN 侧既有帧布局的**双魔数分流**,不再自造第二套帧协议。 ``` -帧 = [HEAD 0x7D] [LEN_H] [LEN_L] [PAYLOAD...] [XOR] [SUM] -- HEAD: 0x7D(避开 0x7F DBN↔Loop / 0x8F DBN 专有 / 0x9F OTA 已占用魔数) -- LEN: uint16 大端, PAYLOAD(JSON) 字节数, ≤2048 -- XOR: XOR 校验,从 LEN_H 起到 PAYLOAD 末字节(不含 HEAD) -- SUM: 累加和校验,范围同上 -- 双向对称 +[0]=MAGIC [1]=Addr [2]=LEN(1B, =1+data) [3]=CMD [4..]=DATA [-2]=XOR [-1]=SUM +帧总长 = LEN + 5; 校验范围 = 从 Addr 起 2+LEN 字节(不含 MAGIC); 双向对称 ``` +| 魔数 | 用途 | 帧长上限 | +|---|---|---| +| `0x7F` | 业务帧: 转发 UART2(Loop),字节流透传 | 70B(Loop 协议) | +| `0x8F` | **本机侧私有帧**: 链路两端各自本地消费,**不转发**(DBN 私有指令 / 4G 配置同步) | **260B** | +| `0x9F` | OTA(既有) | 既有 | + +其他魔数: 丢弃 + 回找最近魔数 resync。 + ### 3.1 与 DBN↔Loop 0x7F 帧的对比(2026-08-31 代码核实) vd960DBN 与地感 MCU 的串口逻辑(loop_uart_proto.c,UART2,0x7F 帧): @@ -177,17 +193,18 @@ vd960DBN 与地感 MCU 的串口逻辑(loop_uart_proto.c,UART2,0x7F 帧): 校验: XOR+SUM,从 Addr 起(不含 magic) ``` -| 对比项 | DBN↔Loop (0x7F) | Air780↔DBN (0x7D 本工程) | +| 对比项 | DBN↔Loop (0x7F) | DBN↔Air780 (0x8F 配置同步) | |---|---|---| -| LEN 字段 | **1B**,Value 0~64B(协议明确上限) | **2B**,≤2048B | -| 魔数 | 0x7F | 0x7D | -| 校验 | XOR + SUM(从 Addr 起) | **XOR + SUM(从 LEN_H 起,用户决策 2026-08-31)** | +| LEN 字段 | **1B**,Value 0~64B(协议明确上限) | **1B**,LEN=1+data,**帧 ≤260B**(数据 ≤254B) | +| 魔数 | 0x7F | 0x8F | +| 校验 | XOR + SUM(从 Addr 起) | **XOR + SUM(从 Addr 起,不含魔数)** —— 与 0x7F 完全一致 | | 状态机 | IDLE→HEADER→VALUE→CHECK | 同构(IDLE→HEAD→LEN→DATA→XOR→SUM) | -| 用途 | 命令-响应短帧 | JSON 报文流(loop_data 数百字节) | +| 用途 | 命令-响应短帧 | **本机侧配置同步**(net 229B / topic 129B) | -- 为什么不用 0x7F 帧: LEN 1B 上限 64B,装不下 MQTT JSON -- 状态机同构 + 校验统一 → vd960DBN 侧 UART1 通道可直接复用 `lup_feed_byte` 解析骨架 -- ✅ **校验已定稿为 XOR+SUM**(2026-08-31 用户确认),与 0x7F 完全一致 +- 为什么配置同步不用 0x7F 帧: 其 LEN 1B 且 Loop 协议上限 70B,装不下 ClientID/密码/Topic 等长字段 + → `0x8F` 独立放宽到 260B;`0x7F` 纪律不变 +- 状态机同构 + 校验统一 → 解析骨架可复用(注: UART1 用**独立装配器实例**,不可与全局 `g_lup_parser` 共用) +- ✅ **校验定稿为 XOR+SUM**(2026-08-31 用户确认),与 0x7F 完全一致 ## 4 文件结构 @@ -243,7 +260,7 @@ vd960Air/ ### 待确认(等开发文档/板级验证) -- [ ] vd960DBN UART1 帧格式是否按 §3 设计稿(0x7D 帧),或用户文档另有规定 +- [x] **vd960DBN UART1 帧格式(2026-09-10 定稿)**: 按 §3 —— 0x7F 业务帧字节流 + 0x8F 本机侧私有帧(原 0x7D 设计稿作废) - [ ] dev_serial 获取方式: config 写死 vs UART 握手动态下发(当前 config 写死) - [x] **MQTT 服务器(2026-09-10 定)**: 测试服 `110.41.131.144:1883`,明文(非 TLS),鉴权 `admin/****` —— 实现: `config.lua` `CFG_MQTT_HOST/PORT/USER/PASS`,`mqtt_main` 取配置传入 `mqtt:auth()` @@ -260,14 +277,14 @@ vd960Air/ | P0 | 工程骨架 + 帧协议 + MQTT 桥接 + link 注入 | ✅ 完成 | | **P0.5** | **方案 C MVP: 0x7F 帧解析 + 0xC0→loop_data + 沿检测→event_report + ACK 状态机 + initialize/heartbeat + 时钟校准**(2026-08-31) | ✅ 代码完成,待板级 | | **P0.5-fix** | **上电复位修复: config.lua 漏 return + mstick 时基 + MQTT 服务器/鉴权配置**(2026-09-10) | ✅ 已修,待板级复测 | -| P1 | 下行命令转换(loop_param_*/log_*/ota_* 转 0x7F)+ 0x7D 配置同步下发 + vd960DBN UART1 通道联调 | ⏳ 待板/待 vd960DBN 版本 | +| P1 | 下行命令转换(loop_param_*/log_*/ota_* 转 0x7F)+ **0x8F 配置同步(拉取+推送)** + vd960DBN UART1 通道联调 | ⏳ 待板/待 vd960DBN 版本 | | P2 | 板级联调: 帧校验、背压、掉线重连、看门狗 | ⏳ 待板 | | P3 | 通道切换(策略待讨论)+ 脱机日志/OTA 走 4G | ⏳ 规划 | **vd960DBN 侧开发计划(2026-08-31 用户确认列入):** -- [ ] UART1(PB6/PB7)通道: 帧收发 + 0x7F 帧魔数分流(0x7F → UART2 透传 / 0x8F → 本地) -- [ ] **UART2↔UART1 双向透传(方案 B)**: Loop 传感数据(0xC0)转发 Air780;4G 下行地感指令转发 Loop(复用 manage_dbn_ble_transparent 模式) -- [ ] BLE 设置服务器/topic 参数时(0x13/0x15 等),同步经 UART1 下发 Air780 配置 +- [x] UART1(PB6/PB7)通道: 帧收发 + 魔数分流(0x7F → UART2 透传 / 0x8F → 本地) —— **已实现**(`d4d57f6` + `c879ed0`, 2026-09-10) +- [x] **UART2↔UART1 双向透传(方案 B)**: Loop 传感数据(0xC0)转发 Air780;4G 下行地感指令转发 Loop(复用 manage_dbn_ble_transparent 模式) —— **已实现**(`d4d57f6`, 2026-09-10) +- [ ] BLE 设置服务器/topic 参数时(0x13/0x15/0x09 等),同步经 UART1 下发 Air780 配置 —— **协议已定稿**(《DLD960_IoT_MQTT协议》§6.9),待两侧实现 - [ ] 通道切换策略(待讨论: 动态自动 vs 人工设置;暂定默认 4G) ## 8 板级问题修复记录 diff --git a/luatos/air780epm/module/Air780EPM/demo/vd960Air/uart_app.lua b/luatos/air780epm/module/Air780EPM/demo/vd960Air/uart_app.lua index fd845b5..fc75441 100644 --- a/luatos/air780epm/module/Air780EPM/demo/vd960Air/uart_app.lua +++ b/luatos/air780epm/module/Air780EPM/demo/vd960Air/uart_app.lua @@ -12,7 +12,7 @@ 下行链路: MQTT 标准 JSON 命令 → (P1: 转 0x7F 帧) → UART1 → vd960DBN → vd960Loop MVP 范围: 上行(initialize/loop_data/event_report/heartbeat)+ report_config 时钟校准; - 下行命令转换与 0x7D 配置同步列入 P1。 + 下行命令转换与 0x8F 配置同步(拉取+推送)列入 P1。 ]] -- 依赖