外观
读取控制参数
接口说明
读取指定控制器当前的控制参数状态:天窗、遮阳幕、风机、湿帘、灌溉计划等设备的 运行状态(status)、序号(order)与开合位置(position)。
本接口提供 HTTP 与 WebSocket 两种形态,返回结构一致:
| 形态 | 地址 | 适用场景 |
|---|---|---|
| HTTP | GET https://mqtt.iot.auto-control.com.cn/api/device_status | 进页面时读一次 |
| WebSocket | ws://mqtt.iot.auto-control.com.cn/ws/device-status | 页面常驻、实时刷新 |
读 status 字段之前,先看懂位语义
status 是一个二进制位串(如 "00000100"),每位代表一个开关或运行方向。 解析规则见下方 status 位语义。 位序方向与设备类型有关,读错方向会导致状态完全相反。
一、HTTP 版本
请求地址
text
GET https://mqtt.iot.auto-control.com.cn/api/device_status1
请求方法
GET
请求参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
deviceCode | String | 是 | 设备编码 | 2022070314150044 |
接口文档对 deviceCode 的描述有误
deviceCode 是设备编码,取自 设备列表 的 code 字段。
请求头
| 请求头 | 值 | 必填 |
|---|---|---|
Authorization | Bearer <token> | 是 |
返回字段
风格 B 精简包装,data 为控制参数数组:
| 字段名 | 类型 | 说明 | 示例 |
|---|---|---|---|
code | Int | 状态码,200 为成功 | 200 |
message | String | 提示信息,成功时为 SuccessCode | SuccessCode |
data[].name | String | 控制项名称(中文) | 一级风机 |
data[].name | String | 控制项名称(中文) | 一级风机 |
data[].status | String | Int | 状态值:isBit=1 时是位串,isBit=0 时是数字(见下方位语义) | "00000100" |
data[].order | Int | 同一控制项的序号;同名控制项可能有多条(灌溉计划等) | 0 |
data[].position | String | Int | 开合位置,仅在指定位置模式下是十进制值 | "100" |
data[].deviceTypeNumber | Int | 设备类型编号,用于与 address 映射表对照 | 16 |
data[].isBit | Int | 该控制项是否是位串语义:1 是位串 / 0 是数值 | 1 |
data[].suffix | String | 补充说明文字,无值时为 "" | 第一组控制标志 |
status 的类型会变,取决于 isBit
实测同一台设备上两种形态并存:
isBit | status 类型 | 示例 | 含义 |
|---|---|---|---|
1 | 字符串位串 | "00000101" | 按位解析(开关停 / 自动手动) |
0 | 数字 | 1、43、3 | 直接就是数值(如配方编号、天数) |
必须先看 isBit 再决定怎么解析 status,否则字符串/数字混用会直接报类型错误。
position 也可能是字符串或数字
实测同一设备上既有 "100"(字符串)也有 0(数字)。 反序列化时请用宽松类型(如 Java 的 JsonNode、Python 的 Any)。
请求示例
bash
curl 'https://mqtt.iot.auto-control.com.cn/api/device_status?deviceCode=2022070314150044' \
-H "Authorization: Bearer <token>"1
2
2
http
GET /api/device_status?deviceCode=2022070314150044 HTTP/1.1
Host: mqtt.iot.auto-control.com.cn
Authorization: Bearer <token>1
2
3
2
3
python
import requests
RT_HOST = "https://mqtt.iot.auto-control.com.cn"
def get_device_status(token: str, device_code: str):
"""读取控制参数。返回 (控制项列表, {名称: 位串}) 。"""
resp = requests.get(
f"{RT_HOST}/api/device_status",
params={"deviceCode": device_code},
headers={"Authorization": f"Bearer {token}"},
timeout=20,
)
body = resp.json()
if body.get("code") != 200:
raise RuntimeError(f"查询失败: {body.get('code')} {body.get('message')}")
items = body.get("data") or []
by_name = {}
for it in items:
key = f'{it["name"]}#{it["order"]}' if it.get("order") else it["name"]
by_name[key] = it["status"]
return items, by_name
def decode_switch_stop(status: str):
"""解析『开关停』型设备。
bit0=1 开;bit0=0 且 bit1=1 关;其余为停。
自动/手动:bit2=0 且 bit3=0 ⇒ 自动,否则手动。
"""
bits = status.zfill(8) # 从左侧补 0,保证 8 位
# 按『从左向右』阅读:第 0 位 = 第 0 个字符
b0, b1, b2, b3 = bits[0], bits[1], bits[2], bits[3]
if b0 == "1":
state = "开"
elif b1 == "1":
state = "关"
else:
state = "停"
mode = "自动" if (b2 == "0" and b3 == "0") else "手动"
return state, mode
if __name__ == "__main__":
items, _ = get_device_status("<你的 token>", "2022070314150044")
for it in items:
state, mode = decode_switch_stop(it["status"])
print(f'{it["name"]:<12} status={it["status"]} {mode}{state} position={it["position"]!r}')1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
返回示例
json
{
"code": 200,
"data": [
{ "name": "一级风机", "status": "00000100", "order": 0, "position": "", "deviceTypeNumber": 16 },
{ "name": "二级风机", "status": "00000100", "order": 0, "position": "", "deviceTypeNumber": 17 },
{ "name": "三级风机", "status": "00000100", "order": 0, "position": "", "deviceTypeNumber": 18 },
{ "name": "湿帘", "status": "00000100", "order": 0, "position": "", "deviceTypeNumber": 19 },
{ "name": "室外屋顶喷淋", "status": "00000000", "order": 0, "position": "", "deviceTypeNumber": 37 },
{ "name": "灌溉计划灌水", "status": "00000000", "order": 1, "position": "", "deviceTypeNumber": 49 },
{ "name": "灌溉计划灌水", "status": "00000000", "order": 2, "position": "", "deviceTypeNumber": 49 }
],
"message": "SuccessCode"
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
二、WebSocket 版本
接口说明
建立长连接后,客户端先发送一条 JSON 消息指定 deviceCode, 服务端随后按固定间隔持续推送该设备的控制参数。
请求地址
text
ws://mqtt.iot.auto-control.com.cn/ws/device-status1
请求方法
WebSocket(ws://;如需加密请用 wss://)
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
deviceCode | String | 是 | 设备编码,通过连接建立后的第一条消息发送(不是 URL 参数) |
推送频率
推送间隔暂未定义
接口文档未说明推送频率。服务端实现里有一个可配置的推送间隔环境变量 (默认 7 秒),但这是服务端配置,对第三方不可见也不保证。 请以实际观测到的推送节奏为准,并在客户端做超时检测(例如 60 秒无推送则认为连接异常)。
交互流程
text
客户端 服务端
| ---- 建立 WebSocket 连接 -------> |
| ---- {"deviceCode":"2022..."} --> | (第一条消息,指定要订阅的设备)
| <--- {code:200, data:[...]} ----- | (立即推送一次)
| <--- {code:200, data:[...]} ----- | (之后按间隔持续推送)
| ---- 关闭连接 / 发送空消息 ------> | (断开或发送非 JSON 会结束推送)1
2
3
4
5
6
2
3
4
5
6
请求示例
javascript
// 浏览器 / Node.js(ws 库)
const ws = new WebSocket('ws://mqtt.iot.auto-control.com.cn/ws/device-status')
ws.onopen = () => {
// 连接建立后必须发一条 JSON 指定设备
ws.send(JSON.stringify({ deviceCode: '2022070314150044' }))
}
ws.onmessage = (event) => {
const body = JSON.parse(event.data)
if (body.code !== 200) return
for (const item of body.data || []) {
console.log(item.name, item.status, item.position)
}
}
ws.onclose = () => console.log('连接已关闭,需要重连')
ws.onerror = (e) => console.error('WebSocket 错误', e)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
python
# Python websockets 库
# pip install websockets
import asyncio
import json
import websockets
WS_URL = "ws://mqtt.iot.auto-control.com.cn/ws/device-status"
async def watch_device_status(device_code: str):
async with websockets.connect(WS_URL, ping_interval=30) as ws:
await ws.send(json.dumps({"deviceCode": device_code}))
async for raw in ws:
body = json.loads(raw)
if body.get("code") != 200:
continue
for item in body.get("data") or []:
print(f'{item["name"]:<12} {item["status"]} {item["position"]}')
if __name__ == "__main__":
asyncio.run(watch_device_status("2022070314150044"))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
返回示例
推送内容与 HTTP 版本完全一致:
json
{
"code": 200,
"data": [
{ "name": "一级风机", "status": "00000100", "order": 0, "position": "", "deviceTypeNumber": 16 },
{ "name": "湿帘", "status": "00000100", "order": 0, "position": "", "deviceTypeNumber": 19 }
],
"message": "SuccessCode"
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
status 位语义
这段是全文最容易出错的地方,请逐字阅读
接口文档针对 status 给出的说明(照录):
举例 如果 status = 00000100,如果设备为 '开关停' 设备:先从 bit0 开始解析,如果 bit0 = 1 即为开, bit0 如果不等于 0,那就看 bit1,bit1 = 1 即为关,如果 bit1 不等于 1,状态即为 '停'; 如果设备是 '开关型' 设备,那么只关注 bit0,bit0=1 为开,bit0=0 为关; 自动手动判断:bit2 = 0 bit3 = 0 即为自动状态,其他情况为手动状态
position:'开关停' 型的设备当前开合的位置
「开关停」型设备
| 判断顺序 | 条件 | 结果 |
|---|---|---|
| 1 | bit0 == 1 | 开 |
| 2 | bit0 != 1 且 bit1 == 1 | 关 |
| 3 | 其他 | 停 |
「开关型」设备
| 条件 | 结果 |
|---|---|
bit0 == 1 | 开 |
bit0 == 0 | 关 |
自动 / 手动模式(两类设备通用)
| 条件 | 结果 |
|---|---|
bit2 == 0 且 bit3 == 0 | 自动 |
| 其他 | 手动 |
关于「左起」还是「右起」—— 请务必现场核对
文档文字是「从 bit0 开始解析」,而文档给出的各位映射表(见下)是按 从右往左编号的(10000000 对应 bit7、00000001 对应 bit0)。
两处存在方向上的矛盾。实际核对时的可靠做法:
- 在平台页面上操作一个设备(例如把一级风机切到「手动开」)
- 同时调用本接口,观察
status的哪一位发生了变化 - 用这个观测结果确定你所在环境的位序方向,并写成单元测试固化下来
不要凭猜测写死位序。
文档给出的状态位映射表(种类型设备示例)
以下表格照录 接口文档,位串按文档写法保留
天窗类(左向天窗 / 右向天窗)
| 位串 | 状态 |
|---|---|
00000110 | 手动关闭 |
00000101 | 手动打开 |
00000100 | 手动静止 |
00000000 | 自动静止 |
00000001 | 自动开 |
00000010 | 自动关 |
文档中该表第一行的位串写作
0000110(7 位),此处按上下文补为00000110(8 位)。
补光灯
| 位串 | 状态 |
|---|---|
00000101 | 手动开 |
00000100 | 手动关 |
00000000 | 关 |
位表与文字说明的口径不完全一致
上表的位串取值(00000101 = 手动打开)与「开关停」的解析规则 (bit0=1 为开)看起来并非同一套编号体系,同时也未说明这些位串对应哪种设备类型。
结论:这些位串请当作「已知状态样本」用于比对,不要直接推导解析算法。 真正的解析逻辑请按上面的三张判断表实现,并用现场操作核对位序。
注意事项
order 用于区分同名控制项
灌溉计划等控制项会有多路同名条目(如 灌溉计划灌水 同时有 order=0/1/2)。 解析时请用 名称 + order 作为唯一键,不要只用名称。
position 只在有行程的设备上有意义
position 是「开关停」型设备(天窗、遮阳幕等)的当前开合位置。 对风机、补光灯这类无行程的设备,position 恒为空串 ""。 文档未说明 position 的取值格式(是百分比 0-100 还是原始行程值),请以实际返回为准。
配合 address 映射表使用
返回体里的 deviceTypeNumber(如 16=一级风机)可以与 address 控制地址全量表 以及 设备类型映射表 对照, 建立「名称 → 地址」的映射,用于后续下发 控制指令。
WebSocket 连接注意事项(生产环境必读)
- 必须先发一条指定
deviceCode的 JSON 消息,否则不会收到任何推送 - 收到空消息或非 JSON 消息会导致服务端结束推送 —— 客户端不要发送额外数据
- 生产环境请使用
wss://,并做好断线重连(建议指数退避,避免风暴) - 需要心跳 / 超时检测:长时间无推送时主动断开重连
- 一个设备一个连接;批量监控多台设备时请评估连接数
下一步
- → 读取地址值:按 address 精确读取某个参数的值
- → 控制设备:下发控制指令
- → WebSocket 接口:其余实时推送通道