# Mock 样例(可直接拿去打) > 六组报文全部取自 2026-11-09 20:21 的**真实一次运行**,不是手编的示例。 > 对应证据:`06_统一闭环题自测证据/05_SOS链路.json` --- ## 1. I-01 事件上报 · 请求 ```http POST /internal/iot/v1/events/batch HTTP/1.1 Content-Type: application/json X-Idempotency-Key: batch-20261109-2021-001 ``` ```json { "sourceChannel": "OWN_GW", "events": [{ "eventId": "EVT-SOS-3B9B2CDB9CD4", "sensorId": "3F7A9C23", "sourceChannel": "OWN_GW", "eventType": "SOS_PRESS", "deviceTime": null, "receivedAt": "2026-11-09T20:21:12+08:00", "tsSource": 3, "protocolVersion": "gw-1.2", "seq": 16872, "payload": {"deviceTypeRaw": 5, "rawEventCode": 1, "batteryMv": 3610}, "rawRef": "e1abbc2d6515f118ac9e7e113c68d677" }] } ``` **三个刻意的点** - `deviceTime: null` —— 433 帧没有时间字段,按 J-00 必须传 null,不许拿 `receivedAt` 顶替 - `tsSource: 3` —— 网关打戳,界面不能显示成"发生时间" - `payload.deviceTypeRaw: 5` —— 任何帧都必须带,缺了整条拒收 ## 2. I-01 响应 ```json {"code":0,"msg":"ok","data":{ "accepted":1, "rejected":0, "duplicated":0, "unregistered":0, "rejectedDetail":[]}} ``` ## 3. I-01 失败样例(四种) ```jsonc // ① 缺 deviceTypeRaw {"code":0,"data":{"accepted":0,"rejected":1,"rejectedDetail":[ {"eventId":"EVT-BAD-01","reason":"SCHEMA_INVALID"}]}} // ② SN 与通道不符(OWN_GW 传带前缀的 SN) {"code":0,"data":{"accepted":0,"rejected":1,"rejectedDetail":[ {"eventId":"EVT-BAD-02","reason":"SENSOR_ID_INVALID"}]}} // ③ tsSource 越界 {"code":0,"data":{"accepted":0,"rejected":1,"rejectedDetail":[ {"eventId":"EVT-BAD-03","reason":"SCHEMA_INVALID"}]}} // ④ 批级通道非法 → 整批 400 {"code":400,"msg":"sourceChannel 非法:H_MQTT"} ``` ## 4. I-02 设备状态快照 ```json { "sourceChannel": "OWN_GW", "items": [{ "sensorId": "3F7A9C23", "sourceChannel": "OWN_GW", "batteryMv": 3610, "csq": 22, "online": true, "reportedAt": "2026-11-09T20:21:10+08:00" }] } ``` ## 5. I-12 原始报文留档 ```json { "sourceChannel": "OWN_GW", "frames": [{ "sensorId": "3F7A9C23", "rawRef": "e1abbc2d6515f118ac9e7e113c68d677", "frameHex": "A55A213F7A9C2350100001000000E8B4", "frameLen": 17, "receivedAt": "2026-11-09T20:21:12+08:00" }] } ``` > `rawRef` 与 I-01 必须同一种算法(MD5 32 位或 SHA-256 64 位),否则回指链断。 ## 6. I-18 / I-05 下行命令 > 编号按 J-00 V1.8 §三接口表:领取是 **I-18**、回执是 **I-05**(原写 I-20/I-21,已作废)。 ```jsonc // I-18 拉取(长轮询,wait 最长 30s) GET /internal/iot/v1/commands/pending?nodeId=iot-node-1&wait=30 {"code":0,"data":{"nodeId":"iot-node-1","hasMore":false,"commands":[ {"commandId":"CMD17942268075877","gatewayId":"GW-0001","targetId":"3F7A9C23", "cmdType":"time_sync","deliveryMode":"REALTIME", "params":{"ts":"2026-11-09T20:21:12+08:00"}, "leaseExpireAt":"2026-11-09T20:22:12+08:00","expireAt":"2026-11-12T20:21:12+08:00", "retryCount":0}]}} // I-05 回执(result 五值;resultCode 是标准码,不是厂家原码) POST /internal/iot/v1/commands/result {"nodeId":"iot-node-1","results":[ {"commandId":"CMD17942268075877","result":"ACKED","resultCode":"0","resultMsg":"OK", "ackAt":"2026-11-09T20:21:14+08:00","rawResultCode":"00"}]} {"code":0,"msg":"ok"} ``` ## 7. 服务端推给家属端(SSE) ``` event: alarm data:{"type":"alarm","alarmId":2796,"alarmNo":"AL20261109202112922", "householdId":9001,"level":"S1","tier":"T1","ruleKey":"SOS", "title":"紧急呼叫","content":"老人按下紧急按钮,请立即联系", "deviceName":"床头SOS","deviceSn":"3F7A9C23", "triggerAt":"2026-11-09T20:21:12","delayed":false} ``` --- ## 8. 怎么用这些样例自测 ```bash # 登录拿 token(账号由 DemoDataInitializer 在空库首次启动时生成) curl -X POST http://127.0.0.1:8080/api/v1/auth/wx/password-login \ -H "Content-Type: application/json" \ -d '{"phone":"13800000000","password":"123456"}' # 打一条 SOS(把上面第 1 节的 body 存成 sos.json) curl -X POST http://127.0.0.1:8080/internal/iot/v1/events/batch \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: batch-local-001" \ -d @sos.json # 查告警是否生成 curl "http://127.0.0.1:8080/api/v1/alarms?size=3" -H "Authorization: Bearer " ``` 预期:1 秒内家属端 SSE 收到 `event: alarm`,列表首条是刚才那条 SOS。 > **注意**:`sensorId` 必须已经入库(后台「设备入库」录入或跑 `03` 的虚构台账数据), > 否则会返回 `unregistered`,不建档也不告警 —— 这是 A 方案的刻意设计。