feat(vd960Air): 4G 特有字段 link 注入 + 用户决策落地

用户决策(2026-08-31):
1. 波特率默认 115200,后续再调
2. dev_serial 与有线通道同一序列号;4G 上报附加 IMEI/流量卡ICCID/IMSI/MSISDN/CSQ
3. 4G 适配并入《DLD960_IoT_MQTT协议》主协议,4G 特有部分单独标注

实现:
- link_info.lua: 采集 mobile.imei()/iccid()/imsi()/msisdn()/csq()
- uart_app.lua: 上行 json.decode → 注入顶层 link 对象 → encode(解析失败原样转发)
- config.lua: CFG_LINK_ENABLE 开关
- readme: §2.1 link 字段定义 + 决策记录/待确认清单更新
This commit is contained in:
wangfq
2026-08-31 11:54:34 +08:00
parent 8911b04df2
commit d994013517
4 changed files with 109 additions and 7 deletions
@@ -37,3 +37,8 @@ CFG_UART_BAUD = 115200
-- 帧 = [0x7D] [LEN_H] [LEN_L] [PAYLOAD...] [SUM], 详见 uart_app.lua 头注释
CFG_FRAME_HEAD = 0x7D
CFG_FRAME_MAXLEN = 2048 -- PAYLOAD 最大字节数(防御: 超长判非法帧)
-- ==================== 4G 特有字段注入 ====================
-- 用户决策 2026-08-31: 4G 上报附加 IMEI/流量卡ICCID/IMSI/MSISDN/CSQ 字段
-- true = 上行 JSON 顶层注入 link 对象(见 link_info.lua)
CFG_LINK_ENABLE = true
@@ -0,0 +1,35 @@
--[[
@module link_info
@summary 4G 链路信息采集: IMEI / 流量卡ICCID / IMSI / 手机号 / CSQ 信号
@date 2026.08.31
@usage
4G 通道特有字段,随上行 JSON 注入(顶层 link 对象,平台可选解析,不破坏主协议结构)。
字段说明(接入《DLD960_IoT_MQTT协议》4G 通道适配章节时一并标注):
- imei: 4G 模块 IMEI(mobile.imei())
- iccid: 流量卡 ICCID(mobile.iccid();卡商未写入返回 nil → 置空串)
- imsi: IMSI(mobile.imsi();部分运营商/测试卡返回 nil)
- msisdn: 手机号(mobile.msisdn();物联网卡通常拿不到 → 置空串)
- csq: 信号强度 0-31(mobile.csq();越大越好,31=最强,99/255=无信号)
- net: 网络制式(当前 4G 通道固定 "4G";后续若支持 5G 或以太网备份可扩展)
]]
local link_info = {}
-- 实时采集(CSQ 每次调用现读;若需降低开销,可改为定时缓存刷新)
function link_info.get()
local csq = mobile.csq() or 0
-- mobile.csq() 在某些固件返回 table(如 {csq=xx, ber=xx});此处兼容
if type(csq) == "table" then
csq = csq.csq or 0
end
return {
imei = mobile.imei() or "",
iccid = mobile.iccid() or "",
imsi = mobile.imsi() or "",
msisdn = mobile.msisdn() or "",
csq = csq,
net = "4G",
}
end
return link_info
@@ -29,12 +29,47 @@
| 4G 特有状态(SIM/信号/注册/IMEI/固件版本/链路状态) | **新增命令(4G 侧自答,不进 UART)** | 平台需要区分"有线通/4G 通/都不通",4G 状态是兜底通道健康度关键 |
| 通道切换策略 | **新增** | 有线优先 / 4G 兜底 / 心跳超时切换,由 vd960DBN 侧决策(4G 上报自身可用性) |
**落地方式**: 建议产出《DLD960_IoT_MQTT协议》 **"4G 通道适配"章节(或独立附录)**,标注:
**落地方式**: 并入《DLD960_IoT_MQTT协议》主协议(用户决策 2026-08-31),新增 **"4G 通道适配"章节**,标注:
- 不支持的命令清单(ssc_net_* / iot_net_* / iot_topic_* 等,4G 通道返回 `code=4`)
- 新增 4G 特有命令(如 `4g_status_query` / `link_status_report`)
- **4G 特有字段(link 对象)**: 上行 JSON 顶层附加 `link` 字段,老平台忽略、新平台可管理 4G 通道
- UART 链路帧格式(本工程 §3)
- 与主协议共享的 JSON 结构,平台侧零改动
### 2.1 4G 特有字段: link 对象(用户决策 2026-08-31)
上行 JSON(initialize / loop_data / event_report / heartbeat / 命令响应)注入:
```json
{
"msg_id": 1,
"cmd": "loop_data",
"ts": 1719000000,
"data": { "...": "主协议原样" },
"link": {
"imei": "860012345678901",
"iccid": "89860012345678901234",
"imsi": "460001234567890",
"msisdn": "",
"csq": 23,
"net": "4G"
}
}
```
| 字段 | 来源 | 说明 |
|------|------|------|
| `imei` | mobile.imei() | 4G 模块 IMEI,设备唯一标识 |
| `iccid` | mobile.iccid() | **流量卡卡号**,物联网卡管理识别用(卡商未写入 → 空串) |
| `imsi` | mobile.imsi() | IMSI(部分卡返回空) |
| `msisdn` | mobile.msisdn() | 手机号(物联网卡通常拿不到 → 空串) |
| `csq` | mobile.csq() | 信号强度 0-31(31 最强,99/255 无信号) |
| `net` | 固定 "4G" | 网络制式(预留扩展) |
- 实现: `link_info.lua` 采集 + `uart_app.lua` 上行 json.decode → 注入 `link` → encode
- JSON 解析失败时原样转发,不阻塞上行
- 开关: `config.lua` `CFG_LINK_ENABLE`
## 3 UART 链路帧协议(设计稿 v0.1)
```
@@ -54,8 +89,9 @@
```
vd960Air/
├── main.lua # 入口: 加载 config/看门狗/4G网卡/uart_app/mqtt_main
├── config.lua # 配置: MQTT 服务器/序列号/主题/UART/帧参数
├── uart_app.lua # UART1 <-> vd960DBN 帧协议(接收状态机 + 下行组帧)
├── config.lua # 配置: MQTT 服务器/序列号/主题/UART/帧参数/link 注入开关
├── uart_app.lua # UART1 <-> vd960DBN 帧协议(接收状态机 + 下行组帧 + link 注入)
├── link_info.lua # 4G 链路信息采集(IMEI/ICCID/IMSI/MSISDN/CSQ)
├── netdrv_device.lua # 网卡: 仅 4G(官方 netdrv_4g)
├── network_watchdog.lua # 网络看门狗(官方原样)
└── mqtt/
@@ -71,12 +107,21 @@ vd960Air/
- vd960DBN 侧需要新增: UART1 帧收发 + JSON 组包/解析的"4G 通道"适配(与现有 TCP/MQTT 双栈并列的第三通道,见《DLD960_IoT_MQTT协议》4G 适配章节)
- 8N1,无流控(帧协议自带长度+校验,无需硬件流控)
## 6 待确认清单(等开发文档/板级验证)
## 6 决策记录 & 待确认清单
- [ ] vd960DBN UART1 波特率、帧格式是否按 §3 设计稿(或用户文档另有规定)
- [ ] 设备序列号 dev_serial 来源: config.lua 写死 vs UART 握手动态下发
### 已决策(用户 2026-08-31)
- [x] **波特率**: UART1 默认 **115200**,后续如需再调(config.lua)
- [x] **dev_serial**: 采用与有线通道**同一序列号**(Topic 族一致,平台认同一台设备);config.lua 配置,部署时与 vd960DBN 保持一致
- [x] **4G 特有字段**: 上行注入 `link` 对象(IMEI/ICCID/IMSI/MSISDN/CSQ),平台按 §2.1 解析
- [x] **协议并入主协议**: 4G 适配作为《DLD960_IoT_MQTT协议》章节,4G 特有部分(link 字段/不支持命令/4G 状态命令)单独标注
### 待确认(等开发文档/板级验证)
- [ ] vd960DBN UART1 帧格式是否按 §3 设计稿(0x7D 帧),或用户文档另有规定
- [ ] dev_serial 获取方式: config 写死 vs UART 握手动态下发(当前 config 写死)
- [ ] MQTT 服务器地址/端口/TLS、鉴权方式(平台为准)
- [ ] 4G 特有命令清单与"不支持命令返回 code=4"是否纳入主协议文档
- [ ] 4G 特有命令清单(如 `4g_status_query` / `link_status_report`)是否纳入主协议 4G 章节
- [ ] 通道切换策略: 有线失效判定、4G 启用条件、回切策略
- [ ] 心跳: 4G 通道 heartbeat 间隔/内容是否与有线一致
- [ ] OTA: 4G 通道是否需要支持 Loop/DBN OTA(4G 下行分片经 UART 转发可行性)
@@ -27,6 +27,8 @@ UART 链路帧格式(设计稿 v0.1,待与 vd960DBN 侧联调确认):
-- 加载配置
local CFG = require "config"
-- 4G 链路信息采集(IMEI/ICCID/CSQ)
local link_info = require "link_info"
local UART_ID = CFG.CFG_UART_ID
local MAX_LEN = CFG.CFG_FRAME_MAXLEN
@@ -48,6 +50,21 @@ end
-- 一帧完整且校验通过 → 发布到 MQTT 发送队列
local function on_frame_ok(payload)
log.info("uart_app.frame", "len", payload:len())
-- 4G 特有字段注入(用户决策 2026-08-31):
-- 上行 JSON 顶层附加 link 对象 {imei, iccid, imsi, msisdn, csq, net},
-- 方便平台管理 4G 通道设备(流量卡识别/信号监控)。不破坏主协议结构,老平台忽略即可。
if CFG.CFG_LINK_ENABLE then
local ok, obj = pcall(json.decode, payload)
if ok and type(obj) == "table" then
obj.link = link_info.get()
payload = json.encode(obj)
else
-- JSON 解析失败: 原样转发,不阻塞上行
log.warn("uart_app.frame", "json decode fail, forward raw")
end
end
-- SEND_DATA_REQ(tag, topic, payload, qos)
-- 上行统一发布到 dev 主题(平台侧与有线通道无差别)
sys.publish("SEND_DATA_REQ", "vd960DBN", CFG.CFG_TOPIC_UP, payload, 1)