From f71ac09a0bfadaef4d80c4ba49357f45512c15ac Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 22 Jun 2026 18:30:36 +0800 Subject: [PATCH] =?UTF-8?q?docs(M06-C):=20=E8=AE=B0=E5=BD=95=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E5=B9=82=E7=AD=89=E9=AA=8C=E6=94=B6=E5=B9=B6=E6=8E=A8?= =?UTF-8?q?=E8=BF=9B=E6=8E=A7=E5=88=B6=E7=AE=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++-- docs/current-baseline.md | 4 +-- .../2026-06-22-M06-C-iot-messages.md | 16 +++++++++ .../2026-06-22-M06-C-协议适配与消息幂等.md | 34 +++++++++++++++++++ docs/feature-status.md | 2 ++ docs/hardware-vendor.md | 6 ++-- docs/module-status.md | 12 +++---- docs/mqtt-protocol-mapping.md | 17 +++++++--- docs/unresolved-issues.md | 1 + 9 files changed, 80 insertions(+), 18 deletions(-) create mode 100644 docs/db-changelog/2026-06-22-M06-C-iot-messages.md create mode 100644 docs/devlogs/2026-06-22-M06-C-协议适配与消息幂等.md diff --git a/README.md b/README.md index 5c704aa..6dff530 100644 --- a/README.md +++ b/README.md @@ -120,9 +120,9 @@ WSL 已验证:EMQX `5.8.9`、MQTTX CLI `1.13.0`、EMQX 服务 `active (running 项目已开发部分模块。具体完成度不得从 README 猜测,必须以现有代码、测试、数据库迁移、Git 历史以及 `docs/current-baseline.md`、`docs/module-status.md`、`docs/feature-status.md` 为准。 -- 当前执行游标:`M06-C` -- 最近工程提交:`74a67ac`,完成 M06-B 设备资产、控制通道、Sub-1G 拓扑、状态快照、告警/维护结构与门店权限。 -- 下一工程目标:M06-C 协议适配器和消息幂等。 +- 当前执行游标:`M06-D` +- 最近工程提交:`e795cdb`,完成 M06-C 三类协议适配器、13 位命令状态机、ACK 关联、QoS 1 去重与死信。 +- 下一工程目标:M06-D 控制箱和门锁业务能力。 ## 版本递进 diff --git a/docs/current-baseline.md b/docs/current-baseline.md index 6baa1dd..863da81 100644 --- a/docs/current-baseline.md +++ b/docs/current-baseline.md @@ -1,8 +1,8 @@ # 当前开发成果基线 > V5.0 首次核验日期:2026-06-16 -> audited_commit: `74a67ac` -> next_engineering_target: M06-C 协议适配器和消息幂等 +> audited_commit: `e795cdb` +> next_engineering_target: M06-D 控制箱和门锁业务能力 > 事实源:当前工作区、Git 历史、状态文档、Windows/WSL 检查脚本。 ## 总体结论 diff --git a/docs/db-changelog/2026-06-22-M06-C-iot-messages.md b/docs/db-changelog/2026-06-22-M06-C-iot-messages.md new file mode 100644 index 0000000..d50e1fd --- /dev/null +++ b/docs/db-changelog/2026-06-22-M06-C-iot-messages.md @@ -0,0 +1,16 @@ +# M06-C IoT 消息数据库变更 + +- 迁移版本:`2026062220` +- 名称:`m06c_iot_messages` + +## 新增 + +- `qipai_iot_commands`:13 位命令 ID、状态、请求/回包、发布/ACK/超时和失败原因。 +- `qipai_iot_device_events`:原始/标准化消息、Topic、事件类型、payload 哈希、接收次数。 +- `qipai_iot_dead_letters`:非法 Topic、未知设备和解析失败消息。 + +## 幂等与回滚 + +- 设备事件按租户、设备、Topic 和 payload 哈希唯一;重复消息只增加计数。 +- 死信按 Topic 和 payload 哈希唯一。 +- down 迁移仅删除 M06-C 三张表,不影响设备资产和拓扑。 diff --git a/docs/devlogs/2026-06-22-M06-C-协议适配与消息幂等.md b/docs/devlogs/2026-06-22-M06-C-协议适配与消息幂等.md new file mode 100644 index 0000000..5397c59 --- /dev/null +++ b/docs/devlogs/2026-06-22-M06-C-协议适配与消息幂等.md @@ -0,0 +1,34 @@ +# M06-C 协议适配器和消息幂等 + +- 日期:2026-06-22 +- 起始 commit:`c96045f` +- 工程 commit:`e795cdb` +- ENGINEERING_DELTA=YES +- 子阶段状态:DONE(可独立工程范围);PDF 原件复核为外部阻塞 + +## 工程增量 + +- 实现 `MqttTransport`、`JilianControlBoxAdapter`、`JilianSub1GLockAdapter`、`JilianSmartSocketAdapter`。 +- 严格保留 `ConctolPower`、`Crldoor`、`CrlLED`、`PlayTTS`、`CtrlDevice` 等厂商拼写。 +- Zod 校验控制箱读取/控电/门锁/TTS/LED/任务、Sub-1G 配对控制、插座读取/开关/本地任务。 +- 建立 13 位命令 ID、命令持久化、发布状态、ACK/失败/超时状态推进。 +- MQTT 消费校验 Topic、DeviceID 和 JSON;原始/标准化 payload 分开保存。 +- QoS 1 重复消息只增加接收次数,不重复推进命令或设备状态。 +- 非法 Topic、未知设备、非法 JSON/字段进入可去重死信表,消费循环不崩溃。 + +## 验证 + +- Windows `npm test` 与 `scripts/dev/windows/test-all.ps1`:退出码 0。 +- WSL MySQL 8.4.9 原生临时副本:`up → verify → down → up → verify` 通过。 +- 迁移语句:up 102、verify 74、down 96。 +- 实测同一 ACK 投递两次:事件行 1 条、`receive_count=2`、命令只推进一次至 `ACKED`。 +- 非法 Topic 实测进入 `qipai_iot_dead_letters`。 +- 工程 commit 已 push,`HEAD == origin/main == e795cdb6935568611a5d27d78991bf9e7ee2f7df`。 + +## 资料边界 + +当前工作区与现有压缩包未找到 V5.4 点名的两份协议 PDF。实现依据为 V5.4 已固化的协议章节;PDF 页码级复核登记为 `ISSUE-013/BLOCKED_EXTERNAL`。 + +## 后续 + +执行游标进入 M06-D:控制箱和门锁业务能力。 diff --git a/docs/feature-status.md b/docs/feature-status.md index 104359e..906d553 100644 --- a/docs/feature-status.md +++ b/docs/feature-status.md @@ -40,3 +40,5 @@ | BKG-007 | 后台微信支付配置 | M05-D/M08 | PARTIAL | `1680d73` | 已提供收款账户、分账接收方、门店/全局比例策略和授权状态 API;私钥、APIv3 Key 和接收方真实标识只使用环境引用,查询仅返回脱敏信息。 | Vue 后台页面待 M08;真实商户与服务商授权未提供。 | M08 接入响应式配置页面;授权后完成生产验收。 | | DEV-003 | 设备管理 | M06-B/M08 | PARTIAL | `74a67ac` | 已实现 DeviceID/IMEI/ICCID/型号/固件/信号/能力资产,控制箱通道、智慧插座负载、Sub-1G 父子拓扑、状态快照、开放告警和维护记录查询;门店数据范围生效。 | 尚无后台/手机页面,在线状态仍需 M06-C/G 由真实消息更新。 | M06-C 接入协议消息与幂等;M08 实现响应式界面。 | | BKG-004 | 后台设备管理 | M06-B/M08 | PARTIAL | `74a67ac` | 已提供设备入库、列表、拓扑、通道绑定、Sub-1G 绑定、状态和维护 API;同一房间控制目标唯一,控制箱与智慧插座重复负载被数据库拒绝。 | Vue 后台页面和真实设备扫码入库待 M08/M06-G。 | M06-C/D/E 接入协议后补真实状态;M08 实现管理页面。 | +| IOT-006 | MQTT 消息幂等 | M01/M06-C | DONE | `e795cdb` | 上行按租户、设备、Topic 和 payload SHA-256 唯一;QoS 1 重复消息只增加 `receive_count`,不重复更新命令或设备副作用;WSL MySQL 8.4.9 实测两次 ACK 仅一条事件。 | - | M06-D/E 继续复用同一消费链路。 | +| IOT-007 | 命令状态机 | M01/M06-C | DONE | `e795cdb` | 已实现 `PENDING/PUBLISHED/ACKED/FAILED/TIMEOUT/UNKNOWN/CANCELLED` 数据模型,发布失败、ACK 结果、超时和 13 位命令 ID 均有测试;发布成功不等于 ACK。 | - | M06-D/F 接入业务权限、补偿与过期取消。 | diff --git a/docs/hardware-vendor.md b/docs/hardware-vendor.md index 8865b93..ade60fb 100644 --- a/docs/hardware-vendor.md +++ b/docs/hardware-vendor.md @@ -2,7 +2,7 @@ | 设备 | 当前资料 | 状态 | 下一步 | |---|---|---|---| -| 4G 智能门禁控电箱 | 待在参考资料中定位正式协议 | TODO | M06 前完成协议录入。 | -| Sub-1G 智能门锁 | 待在参考资料中定位正式协议 | TODO | M06 前完成绑定和控制模型。 | -| 4G 智慧插座 | 待在参考资料中定位正式协议 | TODO | M06 前完成型号能力识别。 | +| 4G 智能门禁控电箱 | V5.4 已固化命令与字段;PDF 原件未在当前仓库找到 | PARTIAL | M06-D 完成业务权限和控制;取得 PDF 后逐页复核。 | +| Sub-1G 智能门锁 | V5.4 已固化 `AddDevice/CtrlDevice`、subID/subtype 和结果码;PDF 原件缺失 | PARTIAL | M06-D 完成绑定、控制、安全门禁与事件。 | +| 4G 智慧插座 | V5.4 已固化查询、开关、本地任务和事件;PDF 原件缺失 | PARTIAL | M06-E 完成能力识别、计量和保护事件。 | | EMQX Broker | 固定主机 `101.42.38.246`;已生成安装说明、ACL 模板和菜单检查 | PARTIAL | 生产 Ubuntu 安装、端口限制和 ACL 应用后复验。 | diff --git a/docs/module-status.md b/docs/module-status.md index 395a6da..be19cca 100644 --- a/docs/module-status.md +++ b/docs/module-status.md @@ -3,15 +3,15 @@ ```yaml execution_cursor: current_module: M06 - current_stage: M06-C + current_stage: M06-D stage_status: TODO - last_completed_stage: M06-B - next_stage: M06-C - last_engineering_commit: 74a67ac + last_completed_stage: M06-C + next_stage: M06-D + last_engineering_commit: e795cdb last_push_verified: true base_branch: main blocked_reason: "" - updated_at: 2026-06-22T21:05:00+08:00 + updated_at: 2026-06-22T22:10:00+08:00 ``` | 模块 | 状态 | 最近提交 | 最近开发日志 | 备注 | @@ -22,7 +22,7 @@ execution_cursor: | M03 门店、房间、价格、营业时间 | DONE | `d563078` | docs/devlogs/2026-06-18-M03-D-场景码NFC与WiFi.md | M03-A/B/C/D 已完成门店房间、装修广告、媒体、地图选店、场景码/NFC 页面导航和受控 Wi-Fi;真实微信小程序码图片生成留待 M08 真机联调。 | | M04 订单、时段锁定、支付闭环 | DONE | `91801fe` | docs/devlogs/2026-06-20-M04-D-订单分享.md | M04-A/B/C/D 已完成可信定价、并发预占、订单状态机、续费取消换房、管理员调整、代下单和最小权限分享;Windows 全量回归与 WSL MySQL 8.4.9 模块回归通过。 | | M05 会员、余额、套餐、优惠券 | PARTIAL | `1680d73` | docs/devlogs/2026-06-22-M05-D-分账与收款配置.md | M05-A/B/C/D 工程闭环已完成:统一支付、微信支付退款、团购直订、门店收款账户、分账接收方、比例策略、授权门禁、幂等分账和对账查询均通过 Windows 与 WSL MySQL 回归;真实微信/团购/分账权限未提供,模块保持 PARTIAL/BLOCKED_EXTERNAL。 | -| M06 设备、MQTT 与真实硬件联动 | PARTIAL | `74a67ac` | docs/devlogs/2026-06-22-M06-B-设备资产与拓扑.md | M06-A/B 已完成 MQTT 基础、设备资产、能力、控制通道、Sub-1G 父子拓扑、状态快照、告警/维护结构和门店权限;生产 Broker 与真实硬件仍待联调,继续 M06-C。 | +| M06 设备、MQTT 与真实硬件联动 | PARTIAL | `e795cdb` | docs/devlogs/2026-06-22-M06-C-协议适配与消息幂等.md | M06-A/B/C 已完成 MQTT 基础、设备拓扑、三类协议适配器、命令状态、ACK 关联、QoS 1 去重和死信;协议 PDF 原件未在仓库找到,当前严格按 V5.4 已固化字段实现,继续 M06-D。 | | M07 保洁、通知、任务和语音播报 | TODO | - | - | - | | M08 微信原生小程序完整业务 | TODO | - | - | - | | M09 后台管理端完整业务 | TODO | - | - | - | diff --git a/docs/mqtt-protocol-mapping.md b/docs/mqtt-protocol-mapping.md index 882d282..30785c5 100644 --- a/docs/mqtt-protocol-mapping.md +++ b/docs/mqtt-protocol-mapping.md @@ -1,12 +1,12 @@ # MQTT 协议映射 -M06-A 已按正式协议固定 MQTT Topic、QoS 和客户端权限;具体命令字段、回包、超时和重试在 M06-C/D/E 继续录入。 +M06-C 已按 V5.4 中固化的厂商协议字段实现适配器、上行解析、命令关联、消息幂等与死信。仓库当前未找到总纲点名的两份 PDF 原件,因此尚不能完成 PDF 页码级复核;不得把此状态写成“PDF 已阅读”。 | 设备 | Topic/命令 | 方向 | 字段 | 状态 | |---|---|---|---|---| -| 4G 智能门禁控电箱 | `/devicesend/{DeviceID}`、`/devicewill/{DeviceID}`、`/deviceaccept/{DeviceID}` | 双向 | M06-C/D 补命令字段 | PARTIAL | -| Sub-1G 智能门锁 | 经父控制箱使用相同三个 Topic | 双向 | M06-C/D 补 `subID/subtype` 与命令字段 | PARTIAL | -| 4G 智慧插座 | `/devicesend/{DeviceID}`、`/devicewill/{DeviceID}`、`/deviceaccept/{DeviceID}` | 双向 | M06-C/E 补命令字段 | PARTIAL | +| 4G 智能门禁控电箱 | `/devicesend/{DeviceID}`、`/devicewill/{DeviceID}`、`/deviceaccept/{DeviceID}` | 双向 | `basicInfo/mqttConfig/startVoice/task/taskconfig`、`ConctolPower`、`Crldoor`、`PlayTTS/stopTTS`、`CrlLED`、`task/addtask/canceltask` | PARTIAL | +| Sub-1G 智能门锁 | 经父控制箱使用相同三个 Topic | 双向 | `AddDevice`、`CtrlDevice`;`open/close/setkey/delkey/setcard/delcard/factoryreset` | PARTIAL | +| 4G 智慧插座 | `/devicesend/{DeviceID}`、`/devicewill/{DeviceID}`、`/deviceaccept/{DeviceID}` | 双向 | `basicInfo/workInfo`、`on/off`、`localtask`、`clearTask` | PARTIAL | ## M06-A ACL 基线 @@ -17,3 +17,12 @@ M06-A 已按正式协议固定 MQTT Topic、QoS 和客户端权限;具体命 | 普通客户端 | 禁止 `$SYS/#`、`#`、`+/#` | 禁止未显式允许主题 | 模板已生成 | 后端 MQTT.js 固定使用 MQTT 3.1(`protocolVersion: 3`)、QoS 1、持久会话、自动重连,并在每次连接成功后显式恢复两个上行订阅。单条应用消息默认限制为 64 KiB。 + +## M06-C 消息规则 + +- 命令 ID 只允许 1-13 位数字,默认生成 10 位秒时间戳加 3 位滚动序号。 +- 下发先写 `qipai_iot_commands=PENDING`,MQTT 发布成功后转 `PUBLISHED`,有效 ACK 才转 `ACKED`。 +- `fail/busy/unconfirm/timeout/full` 统一转 `FAILED` 并保留厂商结果码;超时扫描可把未回包命令转 `TIMEOUT`。 +- 上行先校验 Topic、资产 DeviceID 和 JSON;异常 Topic、未知设备、非法 JSON/字段进入 `qipai_iot_dead_letters`。 +- QoS 1 重复消息命中唯一键后只增加 `receive_count`,不重复执行 ACK、状态快照或后续业务副作用。 +- 原始 JSON 与标准化 JSON 分开保存;协议字段大小写和拼写不得在适配器外重新拼装。 diff --git a/docs/unresolved-issues.md b/docs/unresolved-issues.md index a03bcf2..8fcce28 100644 --- a/docs/unresolved-issues.md +++ b/docs/unresolved-issues.md @@ -14,3 +14,4 @@ | ISSUE-010 | 2026-06-22 | M05-C/GRP-001/GRP-002 | 美团/点评、抖音等团购核销与直订未完成真实平台联调。 | 高 | 已完成统一适配器、人工/Mock/API 核销、券码哈希、重复核销幂等、HMAC 回调、映射、人工队列和认领成单;后台配置与记录 API 已具备。 | 缺平台商家授权、Token、正式签名协议和回调测试环境。 | 获取授权后新增厂商专用适配器并执行验券、重复推送、取消和异常重试验收。 | BLOCKED_EXTERNAL | | ISSUE-011 | 2026-06-22 | M05-D/FRN-001 | 微信支付真实分账尚未联调。 | 高 | 已完成收款账户、接收方、比例策略、授权门禁、成功支付校验、API 请求签名、幂等批次、失败人工处理和查询;Mock 仅限非生产。 | 缺微信支付服务商/分账权限、已授权接收方和生产商户凭据。 | 取得权限后登记环境接收方映射,执行小额支付后多接收方分账、重复请求和失败对账验收。 | BLOCKED_EXTERNAL | | ISSUE-012 | 2026-06-22 | M06-A/IOT-001 | 生产 EMQX、正式 MQTT 客户端账号和 ACL 尚未现场验收。 | 高 | 已完成菜单 3 安装/更新、正式 Topic ACL、后端 MQTT 3.1/QoS 1、重连、订阅恢复、健康检查、消息限制和 Mock 客户端测试;WSL EMQX 服务级检查通过。 | Codex 不自动操作生产 Ubuntu,且尚无生产 MQTT 账号;WSL 本地最小权限账号也未配置。 | 管理员在 `101.42.38.246` 执行菜单 3 并建立账号/ACL;提供 Git 忽略的本地账号后执行错误密码、越权、TLS、遗嘱和三个 Topic 冒烟。 | BLOCKED_EXTERNAL | +| ISSUE-013 | 2026-06-22 | M06-C/协议资料 | V5.4 点名的控制箱与智慧插座协议 PDF 原件未在 `参考/`、现有压缩包或仓库其他路径找到。 | 中 | M06-C 严格按 V5.4 已固化的 Topic、命令拼写、字段约束和结果枚举实现,并用 Mock/MySQL 验证;未伪称 PDF 已阅读。 | 协议原件未随当前工作区提供。 | 用户补充两份 PDF 后按页码复核字段、范围和完整枚举;若有差异,以 PDF 和实机结果修正适配器并记录迁移。 | BLOCKED_EXTERNAL |