设备影子、命令状态与跨语言契约局部实验(U89)
公开入口,仓库根目录,JDK 21 / Maven 3.9 / Python 3;不依赖 MySQL、Redis 或任何外部服务:
python3 labs/iot-command/run.py入口记录 JDK/Maven、执行 clean test、核对两份 Surefire 计数(合计 15)、解析依赖版本、校验 15 条 U89 观察行,写入 evidence/u89-2026-10-28.json。每个测试在 127.0.0.1 的随机端口启动一个真实的嵌入式 HiveMQ Community Edition 2026.5 broker(真实 Netty TCP 监听器、独立临时数据目录、file 持久化、与 U88 同款的设备身份/ACL 扩展),测试结束 stop+close 并删除临时目录;入口创建的进程组由 runner 回收。
教材:设备影子与命令状态。协议层连接/QoS/遗嘱见 U88 设备身份与 MQTT 会话,通用幂等见重复消费、幂等与顺序消息。
公开工程:POM、runner、影子文档、命令记录、命令状态机与幂等表、跨语言契约、效果日志、Python 客户端、broker 装配、身份扩展、状态机测试、端到端测试、契约 fixture、运行证据。
| 测试类 | 真实运行入口 | 实际观察 |
|---|---|---|
CommandShadowTest(13) | 嵌入式 broker + 真实 Java 状态机 + Python 子进程 | 生命周期到 SUCCEEDED 且效果一条;重复投递/重复回执效果仍一条;在途重复 DUPLICATE_IN_FLIGHT;可控时钟制造过期:发布前 EXPIRED、迟到 ACK 被拒且无效果;影子版本冲突被拒、部分更新合并、删除终态、JSON 往返一致;离线队列补发;契约摘要 Java=Python、Python ack 被 Java 解析、缺字段两端拒绝 |
EndToEndCommandTest(2) | 嵌入式 broker + 真实双客户端 | 正常闭环:云端下发 → 设备经真实 MQTT 收到 → 回执 → 影子 delta 收敛 → 重复投递效果仍一条;离线恢复:设备离线两条命令入队,重连后旧命令 EXPIRED、新命令 SUCCEEDED,效果只有新命令 |
15 个测试都通过真实 socket 与真实 broker 观察行为:没有 listener mock,没有断言内部字段。命令状态机、影子、幂等表是真实 Java 实现(单进程教学实现,效果写本地文件);跨语言客户端是独立进程的 Python 脚本,不是同一进程假装跨语言。
本机环境(一次运行的实际值)
BellSoft Liberica JDK 21.0.11+11-LTS、Maven 3.9.9、macOS 27.2 arm64、Python 3.9.6;HiveMQ Community Edition 2026.5(嵌入式)、HiveMQ Extension SDK 4.52.0、HiveMQ MQTT Client 1.4.1、Jackson 2.21.7、JUnit Jupiter 6.0.3。实际解析版本、退出码、观察行与文件 SHA-256 见入口生成的 evidence/u89-*.json。
边界
- 影子与命令状态机是单进程 Java 教学实现,效果写本地文件;未接入生产数据库事务、多节点命令服务或真实云 IoT 平台影子(AWS IoT / 阿里云 IoT)。
- 跨语言客户端为 Python 标准库实现,只覆盖契约编解码与摘要一致性,不含固件 C/C++、C# 或 Go 实现。
- TLS/mTLS、增强认证、WebSocket、外部凭据源与 broker 集群/桥接未运行(沿用 U88 边界)。
- 时间过期用可控 Clock 制造,不是真实等待;"设备时钟不准"只做推演,未实跑时钟漂移。
- 断线恢复是正常 disconnect 后重连,不是 kill -9/断电/网络分区。
- 未做容量与并发压测;两路并发更新影子按顺序模拟,不是真实多线程争用。
- 只使用合成设备 id、127.0.0.1 随机端口与临时目录;不写用户数据,不触碰本机其他服务。
已知未运行
真实云 IoT 影子服务、生产数据库事务与多节点命令服务、时钟漂移、kill -9/断电恢复、容量与并发压测、多语言 SDK 一致性矩阵均未在本实验运行;对应结论在正文与账本中按机制推演或明确未运行标注。