网关设备协议
本页是网关类设备的 MQTT 协议参考:网关如何代表子设备上报数据、通知上下线。操作入门版见《网关设备上报数据》。
一、角色模型
平台 ◀── 一条 MQTT 连接(网关令牌认证)── 网关 ──现场总线── 子设备 xN- 网关:设备类型为"网关设备"的平台建档实体,是唯一连接平台的角色;
- 子设备:在平台建档为普通设备并挂在网关下,不连接平台、无令牌;
- 数据归属:报文里的子设备外部 ID 决定数据记在哪台子设备名下。
网关自己有传感器数据时,用《直连设备协议》的 v1/devices/me/telemetry 上报,数据记在网关名下;子设备数据一律走 v1/gateway/... 主题。
二、子设备上报的前置条件
平台按「网关 + 外部 ID」定位子设备,因此:
- 子设备必须先在平台建档(挂在该网关下);
- 建档时的外部 ID 必须与报文里的设备名完全一致(平台仅忽略首尾空格,内部空格、大小写、下划线都必须一致);
- 同一网关下外部 ID 不可重复。
未建档或名字对不上的子设备报文会被跳过(平台记录日志),同一批报文里的其他子设备不受影响——这个隔离设计让一台子设备的配置错误不至于拖垮整个网关。
三、子设备遥测
主题
v1/gateway/telemetry报文格式
顶层是「子设备外部 ID → 数据点数组」的字典,一条报文可同时带多台子设备、多个数据点:
json
{
"Device A": [
{ "ts": 1735689600000, "values": { "temperature": 42, "humidity": 55 } }
],
"Device B": [
{ "ts": 1735689600000, "values": { "temperature": 38 } },
{ "ts": 1735689660000, "values": { "temperature": 39 } }
]
}| 要素 | 说明 |
|---|---|
| 顶层键 | 子设备外部 ID(即建档时填写的名称标识) |
| 值 | 必须为数组,每个元素是一个数据点 |
| 数据点 | { "ts": 毫秒时间戳, "values": { 字段: 值 } };ts 可省略,按平台接收时间入库 |
| 字段名规则 | 与直连设备一致:原样存储、类型保持一致 |
| 处理粒度 | 平台逐台子设备、逐个数据点处理;单点失败不影响其余 |
四、子设备属性
主题
v1/gateway/attributes报文格式
顶层是「子设备外部 ID → 属性字典」,值为对象(不包数组):
json
{
"Device A": { "firmwareVersion": "2.1", "protocol": "modbus-rtu" },
"Device B": { "firmwareVersion": "1.0" }
}属性按子设备 upsert,只保留每个字段的最新值,规则与直连设备属性一致。
五、子设备上下线通知
主题与报文
v1/gateway/connect 子设备上线
v1/gateway/disconnect 子设备下线
报文:{ "device": "Device A" }device 填子设备外部 ID。平台据此更新对应子设备的连接状态。
使用建议
- 子设备首次上报数据前先发一次 connect,让状态先于数据变为在线;
- 子设备从现场总线上消失时发 disconnect;
- 不需要为每条数据报文重复发送上下线通知。
子设备在线状态的连带规则
| 事件 | 平台行为 |
|---|---|
| 网关连接成功 | 仅网关自身置在线(子设备状态不受影响) |
| 网关断开连接 | 该网关名下所有子设备一并置为离线 |
| 收到 connect/disconnect | 对应子设备置在线/离线 |
子设备的在线状态始终跟随网关:网关掉线后,即使子设备还在总线上活着,平台也一律显示离线——因为平台已无法从网关获取它们的数据。设备端无需为此做任何补偿逻辑。
六、配额与频率
- 每个子设备的每个数据点都计入该子设备所属租户的每日消息配额(子设备与租户同属一家,通常即网关的租户);
- 配额耗尽时丢弃发生在单台子设备、单条数据点粒度,不会因一台子设备超限影响其他子设备。
七、最小可用示例
python
import json, time
import paho.mqtt.client as mqtt # pip install paho-mqtt>=2.0
GW = "网关设备的 Access Token"
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=GW)
client.username_pw_set(GW)
client.connect("平台 MQTT 地址", 1883, keepalive=60)
client.loop_start()
now = int(time.time() * 1000)
# 1) 子设备上线
client.publish("v1/gateway/connect",
json.dumps({"device": "Device A"}), qos=1)
# 2) 子设备遥测(可多台子设备一条报文)
client.publish("v1/gateway/telemetry", json.dumps({
"Device A": [{"ts": now, "values": {"temperature": 42}}],
}), qos=1)
# 3) 子设备属性
client.publish("v1/gateway/attributes", json.dumps({
"Device A": {"firmwareVersion": "2.1"},
}), qos=1)下一步:从平台向网关/子设备下发控制指令,请看《设备 RPC》。