设备端对接文档.md 14 KB

智慧停车系统 · 设备端对接文档

版本:v1.0 适用对象:硬件端(车牌识别相机 / LPR 相机、UHF 读写器、道闸控制器)工程师 配套文档:doc/设备接入层设计.mddoc/多岗亭改造方案.md


1. 通信架构概述

系统与硬件设备之间采用 MQTT 消息总线 + HTTP 图片传输 两种通道:

┌─────────────┐  MQTT 发布(识别事件/状态/回执)  ┌──────────────────┐
│  硬件设备     │ ─────────────────────────────▶ │  智慧停车系统      │
│ (相机/道闸)  │                                │  (内嵌 MQTT Broker)│
│             │ ◀───────────────────────────── │                  │
└─────────────┘  MQTT 订阅(道闸指令)            └──────────────────┘
      │
      │ HTTP(抓拍图片,图片不进 MQTT)
      ▼
  图片存储/URL 引用

核心原则:

  • MQTT 只传「元数据」(车牌、RFID、状态、指令、回执),数据量小、实时性高。
  • 图片走 HTTP,绝不塞进 MQTT,避免撑爆 broker。
  • 系统内嵌了一个 MQTT Broker(mochi-mqtt),设备主动连接它,而不是系统连接设备。

2. MQTT 连接规范

参数 说明
协议 MQTT 3.1.1 标准 MQTT
Broker 地址 tcp://<系统主机IP>:1883 系统内嵌 broker,默认端口 1883
ClientID 设备编码(device_code) 必须全局唯一,建议用系统里配置的设备编码
用户名 / 密码 留空 当前版本匿名接入(allow-all-auth
QoS 1(至少一次) 所有消息统一 QoS 1
Keep Alive 30 秒 建议 30s,超时 broker 会判定离线
遗嘱(LWT) 必须配置 见 §2.1,用于系统感知设备离线

2.1 遗嘱(Last Will)配置(必配)

设备连接时必须设置 LWT 遗嘱消息,否则设备断电/断网后系统无法感知离线。

遗嘱参数
Topic parking/lot/{lot}/booth/{booth}/channel/{ch}/gate/lwt
Payload {"schema":"gate.lwt.v1","device_code":"<设备编码>"}
QoS 1
Retained true

2.2 心跳 / 在线状态(必发)

设备连接成功后,立即发布一条 retained 的状态消息,让系统知道设备上线:

  • Topic:parking/lot/{lot}/booth/{booth}/channel/{ch}/gate/state
  • Retained:true
  • Payload:见 §4.2 gate.state.v1

3. Topic 规范

3.1 命名规则

统一前缀 parking/,中间为「停车场 → 岗亭 → 通道」三级坐标,末尾为消息类型:

parking/lot/{lot_id}/booth/{booth_id}/channel/{channel_id}/{类型}

{lot_id}{booth_id}{channel_id}系统分配的数字 ID,不是编码(code)。设备端需从系统获取这三元组并配置到设备(见 §7)。

3.2 Topic 总览

方向 Topic QoS Retained 说明
设备 → 系统 .../channel/{ch}/camera/event 1 车牌/RFID 识别事件
设备 → 系统 .../channel/{ch}/gate/state 1 道闸状态/在线心跳
系统 → 设备 .../channel/{ch}/gate/cmd 1 开/关闸指令
设备 → 系统 .../channel/{ch}/gate/cmd/ack 1 指令执行回执
设备 → 系统 .../channel/{ch}/gate/lwt 1 遗嘱消息(离线通知)

3.3 设备需要订阅的 Topic

设备只需订阅自己坐标下的指令

parking/lot/{lot}/booth/{booth}/channel/{ch}/gate/cmd

4. 消息格式定义(JSON)

所有消息为 JSON 文本,UTF-8 编码。每个消息都含 schema 字段用于区分类型。

4.1 识别事件 camera.event.v1(设备 → 系统)

车牌识别(或 RFID 读取)成功后上报,触发系统执行进场/出场流程。

{
  "schema": "camera.event.v1",
  "device_code": "CAM-A01",
  "plate_number": "粤A12345",
  "rfid_tag": "E28068940000500ABCDEF",
  "direction": "in",
  "ts": 1730000000,
  "image_path": "http://192.168.1.50/capture/20240814_001.jpg",
  "confidence": 0.98
}
字段 类型 必填 说明
schema string 固定 camera.event.v1
device_code string 设备编码,必须与系统设备管理中配置的一致
plate_number string 否* 车牌号(无牌车可空)
rfid_tag string 否* RFID 标签 EPC(无 RFID 可空)
direction string 通行方向 in(进场)/ out(出场)
ts int64 事件时间戳,Unix 秒
image_path string 抓拍图 URL 或路径(图片不走 MQTT)
confidence float 识别置信度,0~1

* plate_numberrfid_tag 至少一个非空。

4.2 道闸状态 gate.state.v1(设备 → 系统,retained)

道闸状态变化或上线时上报,系统据此维护设备在线状态。

{
  "schema": "gate.state.v1",
  "device_code": "GATE-A01",
  "state": "closed",
  "ts": 1730000000
}
字段 类型 必填 说明
schema string 固定 gate.state.v1
device_code string 设备编码
state string open / closed / moving
ts int64 Unix 秒时间戳

4.3 道闸指令 gate.cmd.v1(系统 → 设备)

系统在进出场放行时下发开/关闸指令,设备收到后执行并回执。

{
  "schema": "gate.cmd.v1",
  "cmd_id": "3f2a1b9c-4d5e-4f6a-8b9c-0d1e2f3a4b5c",
  "device_code": "GATE-A01",
  "action": "open",
  "valid_time": 2
}
字段 类型 必填 说明
schema string 固定 gate.cmd.v1
cmd_id string 指令唯一编号(UUID),回执需原样带回
device_code string 目标设备编码
action string open(开闸)/ close(关闸)
valid_time int 道闸动作保持时长(秒),默认 2,范围 1~255

4.4 指令回执 gate.ack.v1(设备 → 系统)

设备执行完指令后立即回执。必须在 5 秒内回执,否则系统判定超时。

{
  "schema": "gate.ack.v1",
  "cmd_id": "3f2a1b9c-4d5e-4f6a-8b9c-0d1e2f3a4b5c",
  "device_code": "GATE-A01",
  "result": "success",
  "error": ""
}
字段 类型 必填 说明
schema string 固定 gate.ack.v1
cmd_id string 对应指令的 cmd_id原样带回
device_code string 设备编码
result string success(成功)/ failed(失败)
error string 失败原因(result=failed 时填写)

4.5 遗嘱消息 gate.lwt.v1(设备 → 系统,retained)

设备异常断开时,由 broker 自动发布遗嘱消息。设备无需主动发布,只需在连接时配置好 LWT(见 §2.1)。

{
  "schema": "gate.lwt.v1",
  "device_code": "GATE-A01"
}
字段 类型 必填 说明
schema string gate.lwt.v1(系统兼容 gate.lwt
device_code string 设备编码

5. 典型交互流程

5.1 设备上线

设备                          Broker(系统)
 │ 1. CONNECT(ClientID=device_code, LWT配置)  │
 │────────────────────────────────────────────▶│
 │ 2. CONNACK                                  │
 │◀────────────────────────────────────────────│
 │ 3. SUBSCRIBE .../gate/cmd                   │
 │────────────────────────────────────────────▶│
 │ 4. PUBLISH .../gate/state (retained, closed)│
 │────────────────────────────────────────────▶│  ← 系统回写设备 online

5.2 车牌识别 → 入场放行

相机                          系统                          道闸
 │ PUBLISH camera/event(in)   │                             │
 │────────────────────────────▶│ 黑名单/满位/临时车校验        │
 │                             │ PUBLISH gate/cmd(open)      │
 │                             │────────────────────────────▶│
 │                             │ PUBLISH gate/cmd/ack        │
 │                             │◀────────────────────────────│
 │                             │ (5秒内未回执则超时)          │

5.3 车牌识别 → 出场放行

同 §5.2,区别是 camera/eventdirectionout。系统会先做计费结算,再下发开闸指令。

5.4 设备离线

道闸异常断开
    │
    ▼
Broker 自动发布 retained 的 gate/lwt 遗嘱
    │
    ▼
系统收到 → 回写设备 offline + 记录「设备离线」异常

6. 字段枚举汇总

字段 取值 说明
direction in / out 进场 / 出场
state open / closed / moving 道闸开启 / 关闭 / 动作中
action open / close 开闸 / 关闸
result success / failed 指令成功 / 失败
schema 见 §4 消息类型标识

7. 设备部署配置(重要)

7.1 设备需要配置的 4 个参数

设备端部署时,需要从系统获取并配置以下参数:

参数 来源 说明
device_code 系统「设备管理」 设备编码,全局唯一
lot_id 系统「停车场管理」 所属停车场数字 ID
booth_id 系统「岗亭管理」 所属岗亭数字 ID
channel_id 系统「通道管理」 绑定通道数字 ID

7.2 坐标层级关系

停车场 ParkingLot (lot_id)
   └── 岗亭 Booth (booth_id)
         └── 通道 Channel (channel_id)
               └── 设备 UHFReader (device_code)

设备必须「绑定通道」后,坐标三元组 (lot_id, booth_id, channel_id) 才完整。MQTT 设备必须绑定通道(系统已强制校验)。

7.3 获取方式

在系统界面「停车管理 → 停车场信息」中,依次查看停车场、岗亭、通道、设备的 ID;或通过后端接口查询(/parking/lot/list/parking/booth/list/parking/channel/list/parking/device/list)。

注意:topic 中使用的是数字 ID(数据库主键),不是 lot_code/booth_code/channel_code 编码字符串。


8. 图片关联(HTTP)

8.1 关联方式

抓拍图片不通过 MQTT 传输。识别事件中通过 image_path 字段引用图片,系统前端直接加载该 URL 显示。

8.2 推荐方案(当前版本)

设备端在识别时抓拍图片,并由设备自身提供 HTTP 访问(或存到约定的图片服务器),然后在 camera.event.v1image_path 里带上该图片的完整 URL:

"image_path": "http://192.168.1.50/capture/20240814_001.jpg"

系统会把该 URL 存到车辆记录的入场/出场图片字段,工作台直接显示。

若后续需要「设备主动上传图片到系统」,可协商增加系统侧 HTTP 上传端点(POST multipart),当前版本未实现。


9. 错误处理与重试约定

场景 约定
指令下发失败(Publish 失败) 系统记录异常,本次放行标记失败
指令超时(5 秒未收到 ack) 系统判定「开闸失败」,记录道闸异常
ack result=failed 系统记录「道闸执行失败」,保留 error 信息
设备断连 靠 LWT 遗嘱触发,系统自动标记离线
设备重连 重新 CONNECT 后,先向 gate/lwt 发布 retained 空载荷清除旧遗嘱,再立即重发 retained 的 gate.state.v1
识别事件重复 系统有 3 秒防抖,同一标识 3 秒内重复事件会被丢弃

10. 联调自检清单

  • 设备能连上 tcp://<系统IP>:1883(匿名)
  • ClientID 设置为系统里的 device_code
  • 已配置 LWT 遗嘱(QoS 1 + retained)
  • 上线后先清除了 gate/lwt 的 retained 遗嘱,再发布 retained 的 gate.state.v1
  • 已订阅自己的 gate/cmd 指令 Topic
  • 识别到车牌后能发 camera.event.v1(direction 正确)
  • 收到 gate.cmd.v1 后 5 秒内能回 gate.ack.v1
  • 拔网线/断电后,系统设备列表状态变为「离线」

附录 A:消息示例汇总

A1 识别事件(进场)

{"schema":"camera.event.v1","device_code":"CAM-A01","plate_number":"粤A12345","rfid_tag":"","direction":"in","ts":1730000000,"image_path":"http://192.168.1.50/cap/001.jpg","confidence":0.97}

A2 识别事件(出场,仅 RFID)

{"schema":"camera.event.v1","device_code":"CAM-B02","plate_number":"","rfid_tag":"E28068940000500ABCDEF","direction":"out","ts":1730000010,"image_path":"","confidence":0}

A3 道闸状态(上线)

{"schema":"gate.state.v1","device_code":"GATE-A01","state":"closed","ts":1730000000}

A4 开闸指令(系统下发)

{"schema":"gate.cmd.v1","cmd_id":"3f2a1b9c-4d5e-4f6a-8b9c-0d1e2f3a4b5c","device_code":"GATE-A01","action":"open","valid_time":2}

A5 开闸回执(成功)

{"schema":"gate.ack.v1","cmd_id":"3f2a1b9c-4d5e-4f6a-8b9c-0d1e2f3a4b5c","device_code":"GATE-A01","result":"success","error":""}

A6 开闸回执(失败)

{"schema":"gate.ack.v1","cmd_id":"3f2a1b9c-4d5e-4f6a-8b9c-0d1e2f3a4b5c","device_code":"GATE-A01","result":"failed","error":"motor timeout"}

A7 遗嘱(离线)

{"schema":"gate.lwt.v1","device_code":"GATE-A01"}