Files
silk/物联网设备接口和数据格式.md

548 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 物联网设备接口和数据格式
## 一、MQTT Topic 结构
后端同时订阅 `silk/+/+/+/up/telemetry``silk/+/+/+/down/cmd`(部分设备 publish/subscribe 方向反配)。下行命令主题根据设备实际上报主题自动推导:
- 设备上报 `/up/telemetry` -> 命令发送到 `/down/cmd`
- 设备上报 `/down/cmd` -> 命令发送到 `/up/telemetry`(反配设备)
| 方向 | 主题格式 | 示例 |
|------|----------|------|
| **上行**(设备 -> 后端) | `silk/{appId}/{roomKey}/{deviceKey}/up/telemetry` | `silk/default/room-001/sensor-001/up/telemetry` |
| **下行**(后端 -> 设备) | `silk/{appId}/{roomKey}/{deviceKey}/down/cmd` | `silk/default/room-001/sensor-001/down/cmd` |
### 路径段说明
| 段 | 说明 | 示例值 |
|----|------|--------|
| `silk` | 系统前缀(固定) | `silk` |
| `{appId}` | 应用标识 | `default` |
| `{roomKey}` | 房间标识 | `room-001` |
| `{deviceKey}` | 设备标识(MAC 或自定义 ID) | `sensor-001``28562f8c35e8` |
> **注意**GSTMB1 设备的 `deviceKey` 在数据库中使用 MAC 地址(如 `28562f8c35e8`),但 topic 路径中仍使用配网时配置的名称(如 `sensor-001`)。后端通过消息体中的 `mac` 字段识别设备。
---
## 二、GSTMB1 温湿度传感器
### 设备信息
| 项目 | 值 |
|------|-----|
| 型号 | GSTMB1 |
| 厂商 | GeekOpen / smart-bird.cn |
| 通信协议 | MQTT |
| 设备标识 | MAC 地址(如 `28562f8c35e8` |
| 上报指标 | temperature、humidity、signal 等 |
### 1. 设备定时上报(遥测数据)
设备直接在 body 顶层放置数值字段,后端自动提取 `temperature``humidity``signal``lux``co2` 等字段。
```json
{
"type": "GSTMB1",
"mac": "28562f8c35e8",
"temperature": 28.24,
"humidity": 57.83,
"signal": -75,
"ip": "192.168.1.56",
"ssid": "GeekOpen",
"version": "1.0.5"
}
```
### 2. 命令响应(设备 -> 后端)
`source` 字段为 `"command"` 表示是对下行命令的回复。
**成功响应(info-all):**
```json
{
"commandName": "info-all",
"mac": "28562f8c35e8",
"source": "command",
"success": true,
"temperature": 28.24,
"humidity": 57.83,
"signal": "-75",
"ip": "192.168.1.56",
"ssid": "GeekOpen",
"version": "1.0.5",
"dhcpEnable": 1,
"h_compensate": 0,
"t_compensate": 0,
"timerEnable": 1,
"timerInterval": 15
}
```
**错误响应:**
```json
{
"commandName": "error",
"mac": "28562f8c35e8",
"source": "command",
"success": false,
"message": "MQTT消息缺少必要的type字段"
}
```
### 3. 下行命令(后端 -> 设备)
| 功能 | API 端点 | 命令 JSON |
|------|----------|-----------|
| 获取设备信息 | `POST /api/v1/devices/:id/gstmb1/info` | `{"type":"info","messageId":"..."}` |
| 重启设备 | `POST /api/v1/devices/:id/gstmb1/restart` | `{"type":"setting","system":"restart"}` |
| 恢复出厂设置 | `POST /api/v1/devices/:id/gstmb1/command` | `{"type":"setting","system":"reset"}` |
| 设置上报间隔 | `POST /api/v1/devices/:id/gstmb1/interval` | `{"type":"setting","messageId":"...","timerEnable":1,"timerInterval":60}` |
| 自定义命令 | `POST /api/v1/devices/:id/gstmb1/command` | 任意 JSON 原样转发 |
**参数说明:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `type` | String | **必填**。命令类型:`info`(查询)、`setting`(设置)、`event`(控制) |
| `messageId` | String | 消息 ID,设备响应时原样返回 |
| `system` | String | `restart`(重启)、`reset`(恢复出厂) |
| `timerEnable` | int | 定时上报开关:`0`(关闭)、`1`(开启) |
| `timerInterval` | int | 上报间隔(秒),范围 5-86400 |
> API 端点中的 `:id` 是数据库中设备的 UUID,不是 MAC 地址。需 JWT 认证。
### 4. 命令响应字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `commandName` | String | 命令名称:`info-all``device-timer-interval``controller-restart``controller-reset``error` |
| `mac` | String | 设备 MAC 地址 |
| `source` | String | 固定 `"command"`,表示命令响应 |
| `success` | boolean | 执行结果 |
| `message` | String | 执行返回结果或错误信息 |
| `temperature` | Float | 温度(摄氏度) |
| `humidity` | Float | 湿度(% |
| `signal` | String | WiFi 信号强度(dBm),0~-50 最好,<-100 无信号 |
| `ip` | String | 设备内网 IP |
| `ssid` | String | WiFi 名称 |
| `version` | String | 固件版本 |
| `dhcpEnable` | int | DHCP 开关:`1`(开启)、`0`(关闭) |
| `t_compensate` | Float | 温度补偿(范围 -20 至 +20) |
| `h_compensate` | Float | 湿度补偿(范围 -20 至 +20) |
| `timerEnable` | int | 定时上报开关 |
| `timerInterval` | int | 上报间隔(秒) |
---
## 三、GSPE1B 智能插座
### 设备信息
| 项目 | 值 |
|------|-----|
| 型号 | GSPE1B |
| 厂商 | GeekOpen / smart-bird.cn |
| 通信协议 | MQTT |
| 设备类型 | 控制器(actuator |
| 设备标识 | MAC 地址(如 `e8f60a2f01e8` |
| 上报指标 | voltage、current、power、energy、key(通断状态) |
> **注意**:该设备的 MQTT 主题方向与常规配置相反——设备发布到 `/down/cmd` 主题,订阅 `/up/telemetry` 主题接收命令。后端已适配此情况。
### 1. 设备定时上报(遥测数据)
设备每 15 秒自动上报电量数据,`source` 字段为 `"auto"`
```json
{
"mac": "e8f60a2f01e8",
"source": "auto",
"voltage": 226.234,
"current": 0.327,
"power": 66.795,
"energy": 0.025,
"key": 1
}
```
### 2. 命令响应(设备 -> 后端)
`source` 字段为 `"command"` 表示是对下行命令的回复。
**info-all 响应(设备信息):**
```json
{
"commandName": "info-all",
"mac": "e8f60a2f01e8",
"source": "command",
"success": true,
"key": 1,
"onState": 2,
"wifiLock": 0,
"keyLock": 0,
"timerEnable": 1,
"timerInterval": 15,
"signal": "-75",
"ip": "192.168.1.59",
"version": "1.0.5"
}
```
**info-statistic 响应(电量信息):**
```json
{
"commandName": "info-statistic",
"mac": "e8f60a2f01e8",
"source": "command",
"success": true,
"voltage": 226.234,
"current": 0.327,
"power": 66.795,
"energy": 0.025,
"key": 1
}
```
**controller-event 响应(通断控制后回复):**
与 info-all 格式相同,包含设备状态信息。
### 3. 下行命令(后端 -> 设备)
| 功能 | API 端点 | 命令 JSON |
|------|----------|-----------|
| 通电 | `POST /api/v1/devices/:id/plug/on` | `{"type":"event","key":1}` |
| 断电 | `POST /api/v1/devices/:id/plug/off` | `{"type":"event","key":0}` |
| 查询设备信息 | `POST /api/v1/devices/:id/plug/info` | `{"type":"info","messageId":"..."}` |
| 查询电量 | `POST /api/v1/devices/:id/plug/statistic` | `{"type":"statistic","messageId":"..."}` |
| 重启设备 | `POST /api/v1/devices/:id/gstmb1/restart` | `{"type":"setting","system":"restart"}` |
| 设置上报间隔 | `POST /api/v1/devices/:id/gstmb1/interval` | `{"type":"setting","timerEnable":1,"timerInterval":60}` |
> API 端点中的 `:id` 是数据库中设备的 UUID,不是 MAC 地址。需 JWT 认证。
### 4. 指标字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `voltage` | Float | 电压(V),如 `226.234` |
| `current` | Float | 电流(A),如 `0.327` |
| `power` | Float | 功率(W),如 `66.795` |
| `energy` | Float | 累计电量(kWh),如 `0.025` |
| `key` | int | 通断状态:`1`(通电)、`0`(断电) |
| `onState` | int | 上电状态:`0`(保持断电)、`1`(保持通电)、`2`(记忆上次状态) |
| `wifiLock` | int | WiFi 锁:`0`(关闭)、`1`(开启) |
| `keyLock` | int | 按键锁:`0`(关闭)、`1`(开启) |
### 5. 命令响应字段说明
| commandName | 说明 |
|-------------|------|
| `info-all` | 设备信息查询响应,包含 key、onState、wifiLock、timerEnable 等 |
| `info-statistic` | 电量查询响应,包含 voltage、current、power、energy、key |
| `controller-event` | 通断控制响应,格式同 info-all |
| `error` | 错误响应,`success: false``message` 字段描述错误原因 |
---
## 四、GSCW1M-4G 4G 智能断路器
### 设备信息
| 项目 | 值 |
|------|-----|
| 型号 | GSCW1M-4G |
| 厂商 | GeekOpen / smart-bird.cn |
| 通信协议 | MQTT over 4G LTE(合宙780ex4G全网通) |
| 设备类型 | 控制器(actuator |
| 设备标识 | IMEI 号(如 `862323080741518`),消息体中使用 `imei` 字段 |
| 上报指标 | voltage、current、power、energy、key(通断状态)、signal0-31 |
> **与 GSPE1B 的区别**:4G 通信(非 WiFi);设备标识用 `imei`(非 `mac`);信号强度为 0-31 整数(非 dBm);`timerInterval` 单位为毫秒(非秒);响应消息**无** `source` 和 `commandName` 字段。
>
> **固件 Bug**:部分设备在 info 响应中 `imei` 的第二位 `6` 误发为 `G`(如 `8G2323080741518`),statistic 响应中则为正确的 `862323080741518`。后端已做规范化处理(`G` -> `6`)。
>
> **主题方向**:与 GSPE1B 智能插座相同,设备响应消息出现在订阅主题(`/down/cmd`)上,而非发布主题(`/up/telemetry`)。后端已适配。
### 1. 设备响应(设备 -> 后端)
断路器的响应消息**没有** `source: "command"` 字段,所有响应均作为遥测数据处理,后端自动提取 body 中的数值字段。
**info 响应(设备信息):**
```json
{
"key": 0,
"iccid": "898604E6192390306804",
"imei": "862323080741518",
"signal": 30,
"version": "1.0.1",
"timerEnable": 0,
"keyLock": 0,
"type": "Breaker-plus-1-4G",
"timerInterval": 0,
"resetLock": 0,
"onState": 2
}
```
**statistic 响应(电量信息):**
```json
{
"voltage": "230.547",
"current": "0.035",
"power": "4.547",
"energy": "0.001",
"key": 1,
"imei": "862323080741518",
"messageId": "auto"
}
```
> **注意**:断路器的 `voltage`、`current`、`power`、`energy` 字段为**字符串类型**(如 `"230.547"`),后端 `toFloat` 函数自动转换为数值入库。`messageId` 为 `"auto"` 时表示定时上报数据。
**event 响应(通断控制后回复):**
```json
{
"iccid": "898604E6192390306804",
"timerEnable": 1,
"onState": 2,
"timerInterval": 60,
"resetLock": 0,
"imei": "862323080741518",
"messageId": "0875c300-a0eb-475b-83ea-607eb27d19a0",
"keyLock": 0,
"type": "Breaker-plus-1-4G",
"signal": 30,
"version": "1.0.1",
"key": 0
}
```
### 2. 下行命令(后端 -> 设备)
命令格式与 GSPE1B 智能插座完全相同,复用同一套 API:
| 功能 | API 端点 | 命令 JSON |
|------|----------|-----------|
| 通电 | `POST /api/v1/devices/:id/plug/on` | `{"type":"event","key":1}` |
| 断电 | `POST /api/v1/devices/:id/plug/off` | `{"type":"event","key":0}` |
| 查询设备信息 | `POST /api/v1/devices/:id/plug/info` | `{"type":"info","messageId":"..."}` |
| 查询电量 | `POST /api/v1/devices/:id/plug/statistic` | `{"type":"statistic","messageId":"..."}` |
| 设置按键锁 | `POST /api/v1/devices/:id/gstmb1/command` | `{"type":"setting","keyLock":0}` |
| 设置定时上报 | `POST /api/v1/devices/:id/gstmb1/interval` | `{"type":"setting","timerEnable":1,"timerInterval":10000}` |
| 重启设备 | `POST /api/v1/devices/:id/gstmb1/restart` | `{"type":"setting","system":"restart"}` |
| 恢复出厂设置 | `POST /api/v1/devices/:id/gstmb1/command` | `{"type":"setting","system":"reset"}` |
> `timerInterval` 单位为**毫秒**(如 `10000` = 10 秒),取值范围 5000-86400000。
### 3. 指标字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `voltage` | Float | 电压(V),如 `226.024` |
| `current` | Float | 电流(A),如 `15.027` |
| `power` | Float | 功率(W),如 `2921.511` |
| `energy` | Float | 累计电量(kWh),如 `25.047`,断电不归零,重置后归零 |
| `key` | int | 通断状态:`1`(通电)、`0`(断电) |
| `signal` | int | 4G 信号强度,0-31,值越大越好 |
| `imei` | String | 设备 IMEI(唯一标识,非数值指标) |
| `iccid` | String | 物联网卡 ICCID(非数值指标) |
| `onState` | int | 上电默认状态:`0`(记忆)、`1`(断电)、`2`(通电) |
| `keyLock` | int | 按键锁:`0`(关闭)、`1`(开启) |
| `resetLock` | int | 重置锁:`0`(关闭)、`1`(开启) |
| `timerEnable` | int | 定时上报:`0`(关闭)、`1`(开启) |
| `timerInterval` | int | 上报间隔(毫秒),如 `10000` = 10 秒 |
---
## 五、GSCU1B-4G 智能红外控制器
### 设备信息
| 项目 | 值 |
|------|-----|
| 型号 | GSCU1B-4G |
| 厂商 | GeekOpen / smart-bird.cn |
| 通信协议 | MQTT over 4G LTE(合宙780ex4G全网通) |
| 设备类型 | 控制器(actuator |
| 设备标识 | IMEI 号(如 `864269069911747`),消息体中使用 `imei` 字段 |
| 设备代号 | `Infrared-Controller-4G` |
| 功能 | 红外码学习、发射、擦除,遥控空调/电视/风扇等家电 |
| 红外码编号 | 1-248,可同时存储多个遥控器的红外码 |
> 与断路器共用 `imei` 标识和 IMEI 规范化逻辑。无电压/电流/功率等电量指标,仅有 `signal`(4G 信号强度 0-31)。
### 1. 设备响应(设备 -> 后端)
**info 响应(设备信息):**
```json
{
"signal": 25,
"code": "Infrared-Controller-4G",
"version": "1.0.0",
"iccid": "89860323442024493202",
"type": "info",
"imei": "864269069911747"
}
```
**learn 响应(学习红外码结果):**
```json
{
"type": "infrared",
"action": "learn",
"imei": "864269069911747",
"success": true
}
```
**emit 响应(发射红外码结果):**
```json
{
"type": "infrared",
"action": "emit",
"imei": "864269069911747",
"success": true
}
```
> `success: false` 表示发射失败(红外编号对应的红外码为空)。学习成功蜂鸣器响 1 声,失败无声。
### 2. 下行命令(后端 -> 设备)
| 功能 | API 端点 | 命令 JSON |
|------|----------|-----------|
| 查询设备信息 | `POST /api/v1/devices/:id/plug/info` | `{"type":"info","messageId":"..."}` |
| 学习红外码 | `POST /api/v1/devices/:id/ir/learn` | `{"type":"infrared","action":"learn","data":{"no":100}}` |
| 发射红外码 | `POST /api/v1/devices/:id/ir/emit` | `{"type":"infrared","action":"emit","data":{"no":100}}` |
| 取消学习 | `POST /api/v1/devices/:id/ir/cancel` | `{"type":"infrared","action":"learnCancel"}` |
| 擦除全部红外码 | `POST /api/v1/devices/:id/ir/erase` | `{"type":"infrared","action":"erase"}` |
| 重启设备 | `POST /api/v1/devices/:id/gstmb1/restart` | `{"type":"setting","system":"restart"}` |
> 学习和发射命令的 body 需包含 `{"no": N}`N 为 1-248 的红外码编号。
### 3. 推荐红外码编号规划
| 编号 | 用途 | 学习方法 |
|------|------|---------|
| 100 | 关机 | 遥控器对准控制器,按关机键 |
| 101 | 标准制冷 | 遥控器设为制冷 25°C 风量自动,按开机键 |
| 102 | 标准制热 | 遥控器设为制热 30°C 风量自动,按开机键 |
| 103+ | 自定义 | 按需扩展 |
### 4. 红外码学习流程
1. 后端发送 `{"type":"infrared","action":"learn","data":{"no":100}}`
2. 设备进入学习状态(不响应其他指令)
3. 遥控器对准设备,按一下对应按键
4. 设备"嘀"一声,返回 `{"success":true}`
5. 后续发送 `{"type":"infrared","action":"emit","data":{"no":100}}` 即可控制
---
## 六、通用 MQTT 数据格式(非 GSTMB1 设备)
后端同时兼容以下消息格式,按优先级依次匹配:
### 1. metrics 对象格式
```json
{
"msgId": "msg-test-001",
"ts": 1751900000000,
"metrics": {
"temperature": 24.8,
"humidity": 78.2,
"lux": 360,
"co2": 890
}
}
```
### 2. data 数组格式
```json
{
"data": [
{"metric": "temperature", "value": 24.8},
{"metric": "humidity", "value": 78.2}
]
}
```
### 3. 单值格式
```json
{
"metric": "temperature",
"value": 24.8
}
```
### 4. GSTMB1 顶层字段格式
```json
{
"type": "GSTMB1",
"mac": "28562f8c35e8",
"temperature": 28.24,
"humidity": 57.83
}
```
### 设备标识优先级
1. `body.deviceKey`(显式指定)
2. `body.mac`GSTMB1 传感器 / GSPE1B 智能插座)
3. `body.imei`GSCW1M-4G 断路器,自动将 `G` 规范化为 `6`
4. topic 路径第 4 段(如 `sensor-001`
---
## 七、后端处理逻辑
### 消息处理流程
```
MQTT 消息到达
├── JSON 解析失败 → 记录警告,丢弃
├── 提取 deviceKeymac > deviceKey > topic[3]
├── 记录 deviceKey → 上行主题映射(用于下行命令)
├── 更新设备 online_status = "online", last_seen = now
├── source == "command"?
│ ├── success == false -> 记录警告,结束
│ ├── commandName == "info-all" / "device-timer-interval" -> 提取温湿度入库
│ ├── commandName == "info-statistic" / "controller-event" -> 提取电压/电流/功率/电量入库
│ └── 其他 -> 记录日志,结束
└── 提取遥测指标(按优先级)
├── body.metrics(对象)
├── body.data(数组)
├── body.value(单值)
└── body 顶层字段(温度/湿度/电压/电流/功率/电量/通断状态等)
├── 持久化(IoTDB 优先,降级 PostgreSQL
├── WebSocket 推送前端
└── 阈值检测
```
### 离线检测
- 每 60 秒检查一次
- 超过 5 分钟未上报的设备标记为 `offline`
- 通过 WebSocket 广播状态变更