接入指南
接入主线
  • 登录取 token,后续 HTTP 与 WebSocket 共用同一登录态
  • 查设备类型与属性,拿到订阅三要素(deviceTypeKey / identifier / deviceCode)
  • 建立 WebSocket 连接,订阅实时值、接收告警推送
  • 需要控制时经 WS 或 HTTP 下置,并以推送确认执行结果
  • 用 HTTP 查历史值、告警与能耗数据
适用读者
第三方系统的集成开发人员:BA、IBMS、自建大屏、定时同步任务等对接方
接入前准备
向平台管理员申请专用集成账号与 projectId,见 接入前准备
在线调试
平台内置 Swagger 接口调试页:http://{host}:1998/doc.html
打个比方:token 是一张门禁卡
登录是办卡(每次登录发一张新卡,旧卡在有效期内继续可用);请求头与 WS 连接地址是刷卡进门;有效期临近时调 refresh 是续期;logout 是注销。卡等同于账号权限——不要写进日志、不要随 URL 外发,疑似泄露立即注销并换密码。
1
快速入门
主线六步:登录 → 查设备 → 订阅实时值 → 下置 → 查能耗
接入主线
登录取 token
查类型与属性
查设备列表
WS 订阅实时值
下置控制
查能耗 / 告警
用最短路径跑通主线,各步骤细节见对应章节

① 登录取 token(记下 data.access_token):

bash
curl -X POST 'http://{host}:1998/system/token/login' \
  -H 'Content-Type: application/json' \
  -d '{"username": "openapi", "password": "******"}'

② 查设备类型与属性(拿 deviceTypeKey / identifier):

bash
curl 'http://{host}:1998/iot/deviceType' -H 'Authorization: {token}' -H 'Project-Id: 1'
curl 'http://{host}:1998/iot/deviceTypeProperties/1001' -H 'Authorization: {token}' -H 'Project-Id: 1'

③ 查设备(拿 deviceCode):

bash
curl 'http://{host}:1998/iot/device/list?deviceTypeKey=1001' -H 'Authorization: {token}' -H 'Project-Id: 1'

④ 建立 WebSocket 连接并订阅实时值:连接 ws://{host}:1998/base/websocket?token={access_token}&projectId=1,收到 ConnectResponse 确认就绪后,发送 SubscribeDevicePointValue 消息(设备 + 属性列表,报文格式见 订阅设备点位值),随后通过 SubscribeDevicePointValue_Publish 主题接收快照与变更推送。

⑤ 下置控制:复用同一连接发送 SetDeviceProperty 消息(报文见 WS 单设备下置),按 SetDeviceProperty_Reply 与后续推送确认结果。

⑥ 查询能耗 / 告警 / 历史值(HTTP):

bash
curl 'http://{host}:1998/energy/statistics/subItem?category=elec&groupType=area&startTime=2026-09-01&endTime=2026-09-30&unit=day' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

跑通主线后,按需求阅读对应章节接入其余接口;按场景组织的完整接入流程见 快速接入样例。

2
鉴权方式
统一响应结构与通用约定

平台 HTTP 与 WebSocket 使用同一套登录态:先调用 HTTP 登录接口获取 token,之后 HTTP 请求通过请求头携带,WebSocket 通过连接 URL 查询参数携带(浏览器原生 WebSocket 无法自定义请求头)。所有 HTTP 接口返回统一包装 Result<T>:

一次登录 · 两条通道携带同一 token
登录接口
POST /system/token/login
access_token
HTTP 请求
请求头 Authorization: {token}
填原值 · 无 Bearer 前缀
WebSocket 连接
URL 参数 ?token={token}&projectId={projectId}
浏览器原生 WS 无法自定义请求头
json
{
  "success": true,
  "code": 200,
  "msg": "操作成功",
  "data": {},
  "total": 0
}
字段类型说明
successboolean是否成功
codeint状态码,200 成功;4xx 为业务/鉴权错误
msgstring状态描述
dataT业务数据,结构由具体接口决定
totallong分页接口返回总条数,非分页接口为 0

通用约定:

  • 数据格式 JSON,字符集 UTF-8;
  • 时区统一为 GMT+8(Asia/Shanghai),时间字段格式见各接口说明;
  • 分页接口统一使用 pageNum(当前页,从 1 开始)与 pageSize(每页条数)。
HTTP 鉴权

第一步:登录换取 token

bash
curl -X POST 'http://{host}:1998/system/token/login' \
  -H 'Content-Type: application/json' \
  -d '{"username": "openapi", "password": "******"}'
字段类型必填说明
usernamestring是平台分配的集成账号
passwordstring是密码

响应:

json
{
  "success": true,
  "code": 200,
  "data": {
    "access_token": "6c4b1f2e8a9d4e0f9b2a7c8d5e6f7081",
    "expires_in": 864000,
    "project": { "id": "1", "projectName": "示例项目" }
  }
}
字段说明
access_token访问令牌,后续所有请求携带
expires_in有效期(秒),默认 864000(10 天)
project账号当前默认项目信息

第二步:后续请求携带 token

请求头必填说明
Authorization: {access_token}是填 token 原值,无 Bearer 前缀
Project-Id: {projectId}否多项目账号用来指定目标项目;不传时使用账号默认项目
bash
curl 'http://{host}:1998/iot/deviceType' \
  -H 'Authorization: 6c4b1f2e8a9d4e0f9b2a7c8d5e6f7081' \
  -H 'Project-Id: 1'

token 生命周期

接口方法说明
/system/token/refreshPOST刷新续期当前 token(建议在过期前调用)
/system/token/logoutDELETE登出并注销当前 token
/system/token/expired-status✅GET查询当前 token 过期状态(路径末尾含「✅」字符,调用时需按 URL 编码传递)
  • 平台允许同一账号多处同时登录,每次登录生成新 token,旧 token 在有效期内仍可用;
  • token 有效期内无访问频率限制(不会因闲置被冻结);
  • token 等同于访问凭证,请妥善保管;疑似泄露立即调用 logout 作废并联系平台方更换密码。
WebSocket 鉴权

WebSocket 在握手阶段完成鉴权,token 通过 URL 查询参数传递:

text
ws://{host}:1998/base/websocket?token={access_token}&projectId={projectId}
参数必填说明
token是HTTP 登录获得的 access_token
projectId否声明关注的项目,服务端按项目过滤推送目标;也可用握手请求头 Project-Id 传递

鉴权规则:

  • token 无效或未登录时握手直接失败,连接被拒绝;
  • 握手成功后服务端立即下发 ConnectResponse 消息确认连接就绪(见 通用消息结构);
  • 连接中断后重连,需重新完成订阅(订阅关系随连接销毁)。

为什么 token 走 URL 而不是请求头?浏览器原生 WebSocket 无法自定义请求头,平台为兼容浏览器直连把鉴权放进了查询参数。代价是 token 可能被反向代理/访问日志记录——生产环境建议使用 wss://,并避免在不受控网络传输。

错误码与异常响应

鉴权与权限错误码(HTTP 状态仍为 200,错误信息在响应体中):

code含义处理建议
431未登录检查 Authorization 头是否携带
432权限验证过期重新登录或调用 refresh
433权限无效token 错误/被登出,重新登录
434账号或密码错误检查登录凭据
440账号被禁用联系平台管理员
461~467项目/功能权限类错误检查 Project-Id 与账号权限

业务失败响应形态:success=false,code=400(通用业务错误),msg 为第一条具体原因(参数校验失败时返回校验消息,如「开始时间不能为空」):

json
{ "success": false, "code": 400, "msg": "back.energy.能源类型不能为空", "data": null, "total": 0 }

常见触发:必填参数缺失、参数类型不匹配(msg 形如「参数'xx'类型错误,应为Long类型」)、请求体 JSON 解析失败、业务规则不满足(如设备不存在、下置目标不可写)。

WebSocket 错误:下行消息 code 字段——200 成功;400 业务失败(msg 含原因,如下置失败「写值失败: {描述}」);403 无权限。握手阶段的鉴权失败不产生消息体,连接直接被拒绝。

错误定位建议:先看 msg;msg 中 back.xxx. 前缀为国际化消息键,若返回了未翻译的键值(多见于冷门分支),请联系平台方确认含义。

接入前准备

第三方接入前,请向平台管理员申请以下资源:

  1. 专用集成账号:独立于人员账号开通,仅授予本档所列接口所需的查询权限(如需设备控制,另行授予控制权限),并绑定目标项目。不要使用人员账号或管理员账号对接;
  2. 项目标识 projectId:对接目标项目的 ID。登录后可通过 GET /system/project/my/projects 查询当前账号有权限的项目列表获取(字段:id、projectName、projectCode);登录响应中的 data.project.id 即账号默认项目;
  3. 账号密码通过线下安全渠道交付。

为什么必须用专用集成账号?集成账号的权限边界就是第三方系统的能力边界——用人员账号对接,对方账号一离职 token 即失效,集成中断;用管理员账号对接,等于把全平台写权限交给了外部系统,任何泄露都是全量泄露。

3
设备类型、属性与点位查询
订阅三要素的获取顺序
设备类型
deviceTypeKey
类型属性
identifier
设备列表
deviceCode
设备点位
devicePointId
WebSocket 订阅需要前三要素;HTTP 下置需要 devicePointId
查询设备类型列表
bash
curl 'http://{host}:1998/iot/deviceType?deviceTypeName=电表' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /iot/deviceType(列表)/ GET /iot/deviceType/page?pageNum=1&pageSize=10(分页)。常用查询参数(均可选):

参数类型说明
deviceTypeNamestring类型名称模糊查询
areaIdlong按区域过滤
subsystemIdlong按子系统过滤
sourceTypesint 列表来源:1-平台创建 2-驱动上报

响应 data 数组元素(节选):

json
[
  {
    "id": 101,
    "deviceTypeKey": 1001,
    "deviceTypeName": "多功能电表",
    "deviceTypeDescription": "0.2S 级三相电能表",
    "createSource": 2,
    "sourceType": 2,
    "driverName": "MQTT网关",
    "instanceName": "GW-001"
  }
]
字段说明
deviceTypeKey设备类型唯一标识(订阅/属性查询都用它)
deviceTypeName / deviceTypeDescription类型名称 / 描述
createSource / sourceType1-平台用户创建 2-驱动上报
driverName / instanceName来源驱动与实例(平台创建的为空)

subsystemId(子系统 id)可通过 GET /system/subsystem 查询当前项目子系统列表获取(字段:id、name,支持按 name 模糊过滤)。

查询设备类型属性(物模型)
bash
curl 'http://{host}:1998/iot/deviceTypeProperties/1001' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /iot/deviceTypeProperties/{deviceTypeKey},可选参数 isPropertiesHide(默认 false)。响应 data 数组元素(节选):

json
[
  {
    "id": 9001,
    "deviceTypeKey": 1001,
    "propertyIdentifier": "switch",
    "propertyName": "启停控制",
    "dataType": "bool",
    "dataSpecUnit": "",
    "propertyAccessMode": "rw",
    "dataSpecZero": "关",
    "dataSpecOne": "开",
    "dataRatio": 1.0,
    "dataOffset": 0.0
  }
]
字段说明
propertyIdentifier属性唯一标识,即订阅所需的 identifier
propertyName属性名称
dataType数据类型(double/int/bool/text/enum 等)
dataSpecUnit / dataSpecUnitName单位编码 / 单位名称
propertyAccessMode访问权限:r 只读、rw 读写(仅 rw 属性可下置)
dataSpecMax / dataSpecMin / dataSpecStep数值范围与步长
dataSpecZero / dataSpecOne布尔值定义(bool 类型)
dataRatio / dataOffset值变换倍率与偏移
查询设备列表
bash
curl 'http://{host}:1998/iot/device/list?deviceTypeKey=1001' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /iot/device/list(列表)/ GET /iot/device/page(分页)。常用查询参数(均可选):

参数类型说明
deviceTypeKeylong按设备类型过滤
deviceCodestring设备标识精确查询
displayNamestring设备显示名模糊查询
areaIdlong按区域过滤
deviceStatusint0-未使用 1-离线 2-正常运行 3-已禁用
isQueryDevicePointboolean是否附带设备点位信息,默认 false

响应 data 数组元素(节选):

json
[
  {
    "id": 5001,
    "deviceCode": "AHU-001",
    "deviceTypeKey": 1001,
    "displayName": "1#空调机组",
    "deviceStatus": 2,
    "onlineStatus": 1,
    "areaName": "一层机房"
  }
]
字段说明
deviceCode设备唯一标识,订阅所需
deviceTypeKey所属设备类型
displayName显示名
deviceStatus数据更新维度状态
onlineStatus在离线规则判定状态:0-未知 1-在线 2-离线 3-故障
查询设备点位

获取设备下点位明细,含下置所需的 devicePointId:

bash
curl -X POST 'http://{host}:1998/iot/device/listDevicePoint' \
  -H 'Authorization: {token}' -H 'Project-Id: 1' \
  -H 'Content-Type: application/json' \
  -d '{"deviceCode": "AHU-001", "includeVirtual": true, "pageNum": 1, "pageSize": 50}'

POST /iot/device/listDevicePoint,请求体:

字段类型必填说明
deviceCodestring是设备标识
propertyNamestring否属性名称模糊过滤
propertyIdentifierstring否属性标识模糊过滤
includeVirtualboolean否是否包含虚点,默认只查实点
pageNum / pageSizelong否分页

响应 data 数组元素(节选):

json
[
  {
    "devicePointId": 77001,
    "propertyIdentifier": "switch",
    "propertyName": "启停控制",
    "realPoint": true,
    "realPointId": 33001,
    "curValue": "1",
    "valueModifiedTime": "2026-09-03 10:00:00",
    "deviceId": 5001
  }
]
字段说明
devicePointId设备属性点位 ID(HTTP 下置用)
propertyIdentifier / propertyName属性标识 / 名称
realPointtrue 实点 / false 虚点
realPointId散点 id(散点下置用)
curValue / valueModifiedTime当前值 / 最后变更时间
批量获取设备实时值

不依赖 WebSocket 长连接、按需拉取设备属性当前值,适合定时同步类场景:

bash
curl -X POST 'http://{host}:1998/iot/device/batchRealValue' \
  -H 'Authorization: {token}' -H 'Project-Id: 1' \
  -H 'Content-Type: application/json' \
  -d '[
    {"deviceTypeKey": 1001, "deviceTypePropertie": "temp", "deviceCodeList": ["AHU-001", "AHU-002"]}
  ]'

POST /iot/device/batchRealValue,请求体为数组,元素结构:

字段类型必填说明
deviceTypeKeylong是设备类型标识
deviceTypePropertiestring是属性标识(单值,查多个属性时传多个元素)
deviceCodeListstring[]是设备标识列表

响应 data 数组元素:

json
[
  {
    "deviceTypeKey": 1001,
    "deviceType": "空调机组",
    "deviceCode": "AHU-001",
    "displayName": "1#空调机组",
    "deviceTypePropertie": "temp",
    "identifierValue": 26.5
  }
]

该接口为轮询式快照,值变化实时性要求高的场景仍建议使用 第四章的 WebSocket 订阅;轮询频率建议不低于 30s 一次。

设备属性树与设备统计

设备属性树:一次调用返回「设备 + 其全部属性」的树结构,适合搭建设备/点位选择 UI,替代 3.1→3.2→3.3 三步拼装:

bash
curl 'http://{host}:1998/iot/device/getDeviceAndPropertieTree?deviceTypeKey=1001' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /iot/device/getDeviceAndPropertieTree,参数(均可选):subsystemId(子系统 id)、deviceTypeKey(设备类型)、propertyIdentifier(属性标识)、keyWord(关键字搜索)。响应 data 元素:id、labelCode(设备标识,即 deviceCode)、deviceTypeKey、displayName、deviceTypeProperties(该设备的属性列表,含标识与名称)。

设备统计:

接口方法入参返回
/iot/device/countByDeviceTypePOSTdeviceTypeKey 列表Map<deviceTypeKey, {total 总数, updateData 数据已更新, unUpdateData 未更新, notUsed 未使用}>
/iot/device/countPOST统计条件列表按类型/分组/属性条件组合的各条件下设备数量
bash
curl -X POST 'http://{host}:1998/iot/device/countByDeviceType' \
  -H 'Authorization: {token}' -H 'Project-Id: 1' \
  -H 'Content-Type: application/json' -d '[1001, 1002]'
项目总览

首页概览数据,无需参数:

接口说明返回(Map 键)
GET /iot/overview/projectOverview项目总览subSysTemCount 子系统数、deviceCount 设备数、userCount 用户数、alarmMsgCount 告警数、unreadAlarmCount 未读告警数、ruleCount 规则数、timePlanCount 定时计划数等
GET /iot/overview/deviceTypeStatusOverview按子系统统计设备状态键为子系统名,值为 {totalCount, changeDataCount, unChangeDataCount, unusedCount}
bash
curl 'http://{host}:1998/iot/overview/projectOverview' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'
4
WebSocket 实时值订阅
WS 订阅交互时序 · 从建连到持续推送
① 建立连接 ws://{host}:1998/base/websocket?token={token}&projectId={projectId}
② 握手鉴权通过,收到 ConnectResponse 即就绪(token 无效则连接被拒)
③ 发送订阅 SubscribeDevicePointValue(设备 + 属性列表)
④ 订阅应答 SubscribeDevicePointValue_Reply,code=200 即成功
⑤ 立即收到一次当前值快照
⑥ 值变化时持续推送(值不变不推送)
断线重连后订阅关系清空——从 ① 重新开始:验证 token 建连并重发订阅(指数退避,见 4.5)
通用消息结构

基础业务通道(/base/websocket)采用「动作分发」机制。客户端 → 服务端:

json
{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "action": "SubscribeDevicePointValue",
  "data": "…JSON 字符串…"
}
字段说明
eventId客户端生成的 UUID,用于关联请求与响应
action动作名称
dataJSON 字符串(注意是字符串,不是内嵌对象),结构由 action 决定

服务端 → 客户端:

json
{
  "code": 200,
  "msg": "状态信息",
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "topic": "SubscribeDevicePointValue_Reply",
  "data": {},
  "projectId": "1"
}
字段说明
code200 成功;400 业务失败;403 无权限
topic消息主题,客户端按 topic 分发处理
eventId对应请求的 eventId
data业务数据,结构由 topic 决定

连接建立成功后服务端会先主动下发一条:

json
{ "topic": "ConnectResponse", "msg": "success" }

最容易踩的坑:data 双重序列化。data 是「数组序列化后的字符串」,不是内嵌对象——发送前要对业务体单独做一次 JSON.stringify,解析推送时也要先 JSON.parse 再取字段。直接把对象塞进 data 发送,服务端按动作解析会失败。

订阅设备点位值

上行:

json
{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "action": "SubscribeDevicePointValue",
  "data": "[{\"deviceCode\":\"AHU-001\",\"deviceTypeKey\":\"1001\",\"identifier\":[\"temp\",\"switch\"]}]"
}

data 为数组序列化后的字符串,元素结构:

字段类型说明
deviceCodestring设备标识
deviceTypeKeystring设备类型标识
identifierstring[]属性标识列表(3.2 接口获得),支持真实点与已启用的虚拟点

下行(订阅应答):

json
{
  "code": 200,
  "msg": "订阅设备点位值消息成功",
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "topic": "SubscribeDevicePointValue_Reply",
  "data": "success"
}

订阅成功后会立即收到一次当前值快照,之后值变化时持续推送。

服务端推送:点位值变更

topic = SubscribeDevicePointValue_Publish:

json
{
  "code": 200,
  "msg": "属性值变化",
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "topic": "SubscribeDevicePointValue_Publish",
  "data": [
    {
      "deviceCode": "AHU-001",
      "deviceTypeKey": "1001",
      "projectId": "1",
      "propertyItems": [
        { "identifier": "temp", "value": 26.5, "dataSpecUnit": "℃", "dataSpecUnitName": "摄氏度" }
      ]
    }
  ]
}
字段说明
data[].deviceCode / data[].deviceTypeKey设备标识 / 类型标识
data[].propertyItems[].identifier属性标识
data[].propertyItems[].value属性值(数值按项目配置保留小数位,布尔原样)
data[].propertyItems[].dataSpecUnit单位

触发场景:① 实时采集值变化;② 订阅成功后的快照;③ 下置失败后的数据纠正(见 5.1)。

取消订阅

上行:

json
{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "action": "UnSubscribeDevicePointValue",
  "data": "[{\"deviceCode\":\"AHU-001\",\"deviceTypeKey\":1001,\"identifier\":[\"temp\"]}]"
}

注意类型不一致:取消订阅的 deviceTypeKey 为数字,与订阅时的字符串不同(协议历史如此,请按此处示例书写)。

下行:topic = UnSubscribeDevicePointValue_Reply,data: "success"。

连接生命周期与使用约束
  • 基础业务通道由 TCP/容器层保活,业务侧无强制心跳;建议客户端按 30~60s 周期自检连接状态;
  • 连接关闭(网络抖动、服务重启)后订阅关系清空,重连成功需重新发送订阅;
  • token 过期后新握手会被拒绝,需先重新登录拿新 token 再重连;
  • 使用约束(重要):当前服务端未设订阅配额,请对接方自律——
    • 单连接订阅点位数建议不超过 2000(以平台方现场评估为准);
    • 断线重连请使用指数退避(如 1s/2s/4s…上限 60s),避免雪崩式重连;
    • 订阅/取消订阅为管理型消息,不要高频反复收发。

为什么重连后总是收不到推送?订阅关系随连接销毁——重连建立的是一条「全新」连接,服务端不会自动恢复旧订阅。正确姿势是:重连成功 → 重新发送全部订阅消息 → 再恢复正常业务。配合指数退避使用——集中断电恢复时若全部客户端无退避地同时重连,会把服务端打垮。

5
设备控制(属性下置)
共同约束

下置 = 向设备属性写入控制值(如启停、设定温度)。开放两类通道:WS 动作(面向设备/设备范围,推荐)与 HTTP 接口(面向具体点位 ID)。共同约束:

  • 仅 propertyAccessMode = rw 的属性可下置(见 3.2);
  • value 一律使用字符串形式传输;
  • 下置成功后,若该点位已被订阅,值变化会通过 SubscribeDevicePointValue_Publish 推送回来;下置失败时服务端会额外下发一次点位值纠正推送,客户端应以纠正推送为准回滚本地状态;
  • 设备离线或驱动不支持写时下置失败(code: 400)。
下置确认闭环 · 受理与执行两步确认
发送下置
WS 动作 / HTTP 接口
Reply 200
平台已受理
设备执行
取决于在线状态与驱动
执行成功 → 收到「值变化推送」,按推送值更新本地状态
执行失败 → 收到「纠正推送」,按纠正值回滚本地状态
受理 ≠ 执行完成:最终一律以订阅推送的值为准

为什么 Reply 200 不等于控制成功?200 只表示「平台已受理下发」,执行取决于设备与驱动状态——设备离线或驱动不支持写都会在受理后才失败。所以下置的确认闭环有两步:先看 Reply 是否受理,再等订阅推送的实际值;失败时服务端会下发一次纠正推送,以纠正推送的值为准回滚本地状态,否则界面显示的设备状态会与实值脱节。

WS:单设备属性下置 SetDeviceProperty

上行:

json
{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "action": "SetDeviceProperty",
  "data": "[{\"deviceCode\":\"AHU-001\",\"deviceTypeKey\":\"1001\",\"propertyItems\":[{\"identifier\":\"switch\",\"value\":\"1\"}]}]"
}

data 为数组序列化后的字符串,元素结构:

字段类型说明
deviceCodestring设备标识
deviceTypeKeystring设备类型标识
propertyItemsarray待下置属性项列表
propertyItems[].identifierstring属性标识
propertyItems[].valuestring属性值(字符串形式)

下行:topic = SetDeviceProperty_Reply。成功:

json
{ "code": 200, "msg": "下置点位属性成功", "topic": "SetDeviceProperty_Reply", "data": "success" }

失败(含权限拒绝/下置异常):

json
{ "code": 400, "msg": "写值失败: {错误描述}", "topic": "SetDeviceProperty_Reply" }
WS:按区域/类型批量下置 SetDeviceTypeProperty

按「区域 + 设备类型 + 设备分组」圈定设备范围,对匹配到的所有设备批量下置相同属性值。上行:

json
{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "action": "SetDeviceTypeProperty",
  "data": "[{\"deviceGroupId\":1,\"areaId\":10,\"deviceTypeKey\":1001,\"propertyItems\":[{\"identifier\":\"switch\",\"value\":\"1\"}]}]"
}
字段类型说明
deviceGroupIdlong设备分组 ID
areaIdlong区域 ID
deviceTypeKeylong设备类型标识(此处为数字)
propertyItemsarray待下置属性项列表(identifier + value)

deviceGroupId(设备分组 id)可通过 GET /iot/deviceGroup/list 查询当前项目设备分组列表获取(字段:id、deviceGroupName、deviceGroupDescr、deviceTypeKey)。

下行:topic = SetDeviceTypeProperty_Reply,成功/失败结构同 5.1。

HTTP:下置设备属性点位值
bash
curl -X POST 'http://{host}:1998/iot/driver/issueDevicePointValue' \
  -H 'Authorization: {token}' -H 'Project-Id: 1' \
  -H 'Content-Type: application/json' \
  -d '{"devicePointId": 77001, "value": "1"}'

POST /iot/driver/issueDevicePointValue(按设备属性点位下置),请求体:

字段类型必填说明
devicePointIdlong是设备属性点位 ID(3.4 接口获得)
valuestring是点位值(字符串形式)

响应 data: true 表示已受理下发。该接口属于设备控制通道(非驱动管理),/iot/driver/** 下其余管理类接口不对外开放。

HTTP:散点下置点位值
bash
curl -X POST 'http://{host}:1998/iot/driver/issuePointValue' \
  -H 'Authorization: {token}' -H 'Project-Id: 1' \
  -H 'Content-Type: application/json' \
  -d '{"pointId": 33001, "value": "1"}'

POST /iot/driver/issuePointValue(散点维度下置),请求体:

字段类型必填说明
pointIdlong是散点 ID(3.4 接口的 realPointId)
valuestring是点位值(字符串形式)

一般场景优先使用 5.1(WS)或 5.3(HTTP 设备属性点位);散点下置面向未挂接设备模型的裸点位,需要平台方确认点位归属后再使用。

控制记录查询

查询平台侧产生的设备控制(下置)记录,可用于第三方系统做操作留痕与审计:

bash
curl 'http://{host}:1998/iot/deviceControl/record/page?displayName=1%23空调机组&pageNum=1&pageSize=20' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /iot/deviceControl/record/page(分页)/ GET /iot/deviceControl/record/list(列表)。过滤参数(均可选,按记录字段过滤):

参数类型说明
deviceIdlong按设备 id 过滤
displayNamestring按设备名称模糊过滤
deviceTypeKeylong按设备类型过滤
propertyIdentifierstring按属性标识过滤
controlResultstring按控制结果过滤
pageNum / pageSizelong分页参数

响应 data 数组元素(节选):

json
[
  {
    "id": 9001,
    "deviceId": 5001,
    "displayName": "1#空调机组",
    "deviceTypeKey": 1001,
    "deviceTypeName": "空调机组",
    "propertyIdentifier": "switch",
    "propertyIdentifierName": "启停控制",
    "propertyValue": "1",
    "controlValue": "0",
    "controlResult": "成功"
  }
]
字段说明
displayName / deviceTypeName设备名称 / 设备类型名称
propertyIdentifier / propertyIdentifierName被控属性标识 / 名称
propertyValue / controlValue下置前的属性值 / 下置的控制值
controlResult控制结果描述

本章的下置操作(WS 与 HTTP)均会在此留痕,含平台自身用户的控制记录。

6
历史值查询
查询设备属性历史值

查询设备属性的历史值序列,支持原始值与周期聚合值:

bash
curl -X POST 'http://{host}:1998/iot/device/getPropertyHistoryValue' \
  -H 'Authorization: {token}' -H 'Project-Id: 1' \
  -H 'Content-Type: application/json' \
  -d '{
    "deviceCodeList": ["AHU-001"],
    "beginTime": "2026-09-01 00:00:00",
    "endTime": "2026-09-03 00:00:00",
    "queryOriginalValue": false,
    "periodicTimeValue": 15,
    "periodicUnit": "minute"
  }'

POST /iot/device/getPropertyHistoryValue,请求体:

字段类型必填说明
deviceCodeListstring[]是设备标识列表(支持多设备)
beginTime / endTimestring是格式 yyyy-MM-dd HH:mm:ss(GMT+8)
queryOriginalValueboolean否true 查原始值;false(默认)查周期聚合值
periodicTimeValueint否聚合周期数值,仅查询周期值时有效,如 15
periodicUnitstring否聚合周期单位:second/minute/hour/day/month/year
deviceTypeKeylong否按设备类型过滤

响应 data 数组元素:

json
[
  {
    "deviceCode": "AHU-001",
    "displayName": "1#空调机组",
    "propertyValues": {
      "temp": [
        { "identifier": "temp", "name": "回风温度", "time": 1756684800000, "dataType": "double", "value": 26.5 }
      ]
    }
  }
]
字段说明
propertyValuesMap:key 为属性标识,value 为该属性的历史值数组
[].time毫秒时间戳(GMT+8)
[].value / dataType值 / 数据类型

历史值按属性的历史记录频率存储(由属性配置的更新周期决定,见 3.2 属性的 updateCycleSeconds 字段),查询跨度大时建议使用周期聚合值控制返回量。

7
告警数据
WS 实时告警推送

告警数据有两个获取面:WS 实时推送(产生即推)与 HTTP 历史查询(检索/列表)。连接与订阅机制见第四章。当产生告警且告警方式配置为「弹窗 / 声音」时,服务端按 userId + projectId 定向推送,topic = SetAlarmMsg:

告警的两个获取面 · 配合使用
WS 实时推送(管即时)
SetAlarmMsg 主题 · 产生即推
仅弹窗 / 声音两种告警方式走 WS
HTTP 分页查询(管回溯)
/alarm/msg/page · 检索历史
按级别 / 类型 / 状态 / 设备过滤
json
{
  "code": 200,
  "msg": "success",
  "topic": "SetAlarmMsg",
  "projectId": "1",
  "data": {
    "alarmMsgId": 10086,
    "alarmMethod": ["POPUP", "SOUND"],
    "alarmTime": "2026-09-03T10:00:00",
    "content": "1#空调离线",
    "title": "设备离线告警",
    "alarmLevel": "严重",
    "notReadCount": 5
  }
}
字段说明
alarmMsgId告警消息 ID(可用 7.3 详情接口回查完整信息)
alarmMethod告警方式(POPUP 弹窗 / SOUND 声音;微信/短信/邮件等走各自通道,不经 WS)
content / title告警内容 / 类型标题
alarmLevel告警级别名称
notReadCount当前未读告警数
告警分页查询
bash
curl 'http://{host}:1998/alarm/msg/page?alarmStatus=unhandled&pageNum=1&pageSize=20' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /alarm/msg/page(分页)/ GET /alarm/msg/list(全量,慎用)。查询参数(均可选,直接拼接在 URL 上):

参数类型说明
alarmLevelstring级别:critical 严重 / major 重要 / minor 一般 / trivial 次要
alarmTypestring类型:threshold 阈值 / strategy 策略 / driver 驱动异常 / energy 能耗 / offline 离线 / authorization 授权 / system 系统
alarmStatusstring状态:in_progress 处理中 / unhandled 未处理 / handled 已处理 / recovered 已恢复
deviceCodestring按告警设备过滤
areaIdint按区域过滤
isAscboolean是否按时间升序,默认 false(最新在前)
pageNum / pageSizelong分页参数

响应 data 数组元素(节选):

json
[
  {
    "id": 10086,
    "alarmLevel": "critical",
    "alarmType": "offline",
    "alarmStatus": "unhandled",
    "deviceCode": "AHU-001",
    "description": "1#空调离线",
    "readFlag": false,
    "alarmTime": "2026-09-03 10:00:00",
    "handleTime": null,
    "handleSuggess": null
  }
]

告警类型与级别的枚举键值也可通过 GET /alarm/typeLevel/MapType、GET /alarm/typeLevel/MapLevel 在线获取(与本表及枚举字典一致)。

当前报警与未读数

当前报警(最新 N 条,常用于监控大屏轮询):GET /alarm/msg/current?limit=10,limit 默认 10;过滤参数同 7.2。

告警详情:GET /alarm/msg/{id} → 单条完整 SysAlarmMsg。

未读数:GET /alarm/msg/countNotRead → data 为未读条数。

告警统计

按维度聚合的告警统计,过滤参数同 7.2(级别/类型/状态/设备/区域,均为可选),统计范围默认为当前项目全部告警:

接口说明返回
GET /alarm/msg/count/type按报警类型统计Map<类型, 数量>
GET /alarm/msg/count/level按报警级别统计各级别数量对象
GET /alarm/msg/count/status按报警状态统计各状态数量对象
GET /alarm/msg/count/subsystem按子系统统计各子系统数量对象
GET /alarm/msg/count/area按区域统计各区域数量对象
GET /alarm/msg/count/day按日统计[{日期, 数量}] 列表
GET /alarm/msg/count/hour按小时统计[{小时, 数量}] 列表
bash
curl 'http://{host}:1998/alarm/msg/count/type?alarmStatus=unhandled' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

响应示例(count/type):

json
{ "data": { "offline": 3, "threshold": 12, "driver": 1 } }
8
能耗数据
能耗模型(只读视角)

能耗统计由平台采集链路(表计读数)自动计算生成,本接口集只读,第三方无需也无法写入能耗数据。查询前需理解三个维度:

  • 能源分类 category:elec(电)、water(水)、gas(气)、ener(能量);
  • 区域:树形结构(楼栋→楼层→房间…),查询/下置中用 areaId;
  • 分项:能耗分项(照明插座、空调、动力…),按能源分类维护,用 subItemId。

统计粒度:平台按15 分钟 / 时 / 日 / 月粒度定时计算,查询接口通过 unit 参数选择输出粒度。

能耗查询的参数拼装
category
能源分类(必填)
groupType + groupId
区域 / 租户
subItemId
分项(可选)
unit + 时间范围
粒度与格式联动
时间格式随 unit 变化(时/日/月/季/年各不相同),传错即报参数错误——见 8.4 参数表

为什么能耗接口只开放查询?能耗是「表计读数 + 平台计算」的产物,真相源在采集链路里——外部写入的能耗既无计量依据,也会覆盖平台统计结果。第三方的控制诉求应走第五章设备控制,而不是伪造能耗数据。

获取分项、区域与基础数据

分项列表(拿 subItemId 与可用分项):

bash
curl 'http://{host}:1998/energy/subItem/list?category=elec' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /energy/subItem/list,参数:

参数类型必填说明
categorystring是能源分类:elec/water/gas/ener
codestring否分项编码过滤
namestring否分项名称过滤

响应 data 元素:

json
[
  { "id": 3, "category": "elec", "subItemCode": "LIGHTING", "subItemName": "照明插座用电", "sort": 1, "meterCount": 12 }
]

区域列表(拿 areaId):

  • GET /system/area/list(系统区域)/ GET /system/area/page(分页);字段:id、areaCode、areaName、parentId、pathName(全路径名);
  • GET /energy/area?category=elec&onlyMeter=true&containSub=true(能耗视角,带每区域表具数;onlyMeter 只看绑了表具的区域,containSub 是否含子区域,默认 true)。

能耗租户列表(拿租户 id,用于 8.4 groupType=tenant 场景):GET /energy/tenant/list → 字段:id、tenantCode、tenantName、parentId(支持树形租户结构)。

表具绑定关系(查询哪块表挂在哪个区域/分项下,做能耗页面的拓扑底座):GET /energy/bindMeter/list?category=elec,参数:category(必填)、areaId/subItemId/tenantId(可选过滤)。响应 data 元素(节选):id(表具 id)、iotDeviceCode(设备标识)、identifier(读数属性标识)、category、areaId、subItemId、tenantId、lineId、maxPower。

能源分类列表:GET /energy/category/list(分类为固定四类,见 8.1,此接口返回分类的展示信息)。

区域能耗查询
bash
curl 'http://{host}:1998/energy/area/consumption/page?pageNum=1&pageSize=10&startTime=2026-09-01&endTime=2026-09-30' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /energy/area/consumption/page,参数:

参数类型必填说明
startTime / endTimedate是格式 yyyy-MM-dd
pageNum / pageSizelong否分页参数(建议携带;缺省时不分页)

响应 data 元素:

json
{
  "areaName": "1号楼",
  "areaCode": "BLD-01",
  "typeList": [
    { "name": "电", "unit": "kWh", "value": 18234.5 },
    { "name": "水", "unit": "m³", "value": 356.2 }
  ],
  "total": 18590.7
}
分项能耗统计(同族接口的参数基准)
bash
curl 'http://{host}:1998/energy/statistics/subItem?category=elec&groupType=area&startTime=2026-09-01&endTime=2026-09-30&unit=day&subItemId=3' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /energy/statistics/subItem,参数:

参数类型必填说明
categorystring是能源分类:elec/water/gas/ener
groupTypestring是分组维度:area 区域 / tenant 租户
groupIdint否区域/租户 id,不填查全部
startTime / endTimestring是格式随 unit 变化:时 2026-09-01 00:00:00、天 2026-09-01、月 2026-09、季 20261(上半年)/20262(下半年)、年 2026
unitstring是统计周期:hour/day/month/quarter/year
subItemIdint否分项 id,不填或 -1 查全部分项

响应 data:

json
[
  { "id": 3, "name": "照明插座用电", "value": 3562.4 },
  { "id": 4, "name": "空调用电", "value": 8976.2 }
]

同一前缀下其余统计接口与 8.4 参数结构一致(category/groupType/时间范围/unit),见 8.11 统计树、图表与费用;排名与对比见 8.5,能流图见 8.6。

能耗排名与对比

能耗排名:

bash
curl 'http://{host}:1998/energy/statistics/rank?category=elec&groupType=area&groupIdList=10&groupIdList=11&beginTime=2026-09-01&endTime=2026-09-30&unit=day&limit=10' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'

GET /energy/statistics/rank,参数:

参数类型必填说明
categorystring是能源分类:elec/water/gas/ener
groupTypestring是分组维度:area 区域 / tenant 租户
groupIdListint 列表是参与排名的区域/租户 id 列表(URL 重复参数传多值)
beginTime / endTimestring是格式随 unit 变化(同 8.4)
unitstring是统计周期:hour/day/month/quarter/year
limitint是排行数量
ascboolean否是否从小到大,默认从大到小

响应 data:排名列表,每项含分组名称、本期值 value、上期值 lastValue、环比 periodOn。

能耗对比:POST /energy/statistics/compare,请求体为 8.4 的 EnergyStatisticsQuery 结构(groupIdList 填多个对比对象),响应为各对比对象的分期能耗序列(含合计)。

能流桑基图

GET /energy/statistics/flow/sankey,参数:

参数类型必填说明
categorystring是能源分类:elec/water/gas/ener
flowTypestring是流向类型:area 区域 / sub_item 分项 / meter 总分表
beginTime / endTimestring是格式:天 2026-09-01、月 2026-09、季 20261

响应 data:桑基图结构,nodes(节点,含 value/childValue/diff 损耗)+ links(流向,含 value)。

用能总览

GET /energy/overview/* 系列接口,除 meterCount/subItem 的 category 可选外,其余接口 category 均必填:

接口参数说明返回
GET /energy/overview/meterCountcategory(可选)表具规模在线/离线/未使用/总表具数
GET /energy/overview/subItemcategory(可选)分项占比[{分项 id, 名称, value}]
GET /energy/overview/periodOncategory, unit环比与同期本期值/上期值/环比/同期对比(unit:day/month/year)
GET /energy/overview/rankcategory, groupType(默认 area), days用能排行排行榜(days:7 或 30)
GET /energy/overview/loadcategory用能负荷今日/昨日/近 7 日负荷曲线
GET /energy/overview/banner/daycategory日横幅今日/昨日/上周用量、日环比/周环比、碳排放、折标准煤
GET /energy/overview/banner/monthcategory月横幅本月累计用量、碳排放、折标准煤
GET /energy/overview/banner/yearcategory年横幅本年累计用量、碳排放、折标准煤
能耗报表

/energy/report/* 系列接口,请求参数均含分页(pageNum/pageSize)。通用参数:

参数类型必填说明
categorystring是能源分类:elec/water/gas/ener
reportTypestring是报表类型:ANNUAL 年报 / MONTHLY 月报 / RANGE 自定义范围
timestring条件年报 2026、月报 2026-09(年报/月报时使用)
beginTime / endTimedate条件2026-09-01(reportType=RANGE 时使用)

各接口:

接口方法额外参数说明
/energy/report/meterPOSTlineId(必填,支线 id)单表能耗报表(含起止底码 startValue/endValue)
/energy/report/groupGETgroupType(必填)系统(区域/租户)能耗报表
/energy/report/subItemGETgroupId(必填,区域或租户 id)分项能耗报表
/energy/report/categoryTypeFeeGETgroupType(必填)费用统计报表(区域/租户维度)

lineId(支线 id)可通过 GET /energy/line/list 查询能源支线列表获取。各报表响应为 cellMap 结构(键为日期,值为该期用量/环比/同比等单元格列表)。

同比环比

POST /energy/yoyAndMomComparison/getYoYAndMoM,请求体:

字段类型必填说明
categoryCodestring是能源分类编码(elec/water/gas/ener)
areaIdlong否区域 id(与 areaName 二选一过滤)
areaNamestring否区域名称
startYearint否起始年份,如 2025
compareYearint否对比年份,如 2026

响应 data:逐月的同比/环比对比序列。

能耗异常

异常清单:GET /energy/exception/list,参数:category(必填)、deviceName/deviceCode(可选,按设备过滤)、date(可选,2026-09-01)、分页参数。响应为表计异常清单(异常表计、异常类型等)。

异常日期:GET /energy/exception/time?category=elec&time=2026-09,响应 Map<日期, 是否异常>,用于日历标注哪些天存在能耗异常。

统计树、图表与费用接口

/energy/statistics/* 同族接口,参数与 8.4 一致(category、groupType、groupId、时间范围随 unit 变化、subItemId 等),返回各自结构:

接口方法说明返回
/energy/statistics/treeGET区域(或租户)统计树树形结构,节点含各期能耗值,父节点聚合子节点
/energy/statistics/chartGET趋势图表数据分期能耗序列(图表横轴/纵轴数据)
/energy/statistics/bannerGET统计横幅汇总量、环比/同比等横幅指标
/energy/statistics/feeGET能耗费用总费用、分类费用、单位面积费用、人均费用等
/energy/statistics/totalMeterGET总表数据总表口径的能耗列表
bash
curl 'http://{host}:1998/energy/statistics/tree?category=elec&groupType=area&startTime=2026-09-01&endTime=2026-09-30&unit=day' \
  -H 'Authorization: {token}' -H 'Project-Id: 1'
9
快速接入样例
样例一:订阅一台设备的指定属性实时值

接入流程:

  1. 确认订阅三要素:GET /iot/deviceType(拿 deviceTypeKey)→ GET /iot/deviceTypeProperties/{deviceTypeKey}(拿 identifier,确认属性存在)→ GET /iot/device/list(拿 deviceCode);也可用 GET /iot/device/getDeviceAndPropertieTree(3.6)一次拿全;
  2. 登录取 token:POST /system/token/login,记下 access_token(2.2);
  3. 建立连接:ws://{host}:1998/base/websocket?token={access_token}&projectId={projectId},等待 ConnectResponse 确认就绪(2.3);
  4. 发送订阅:SubscribeDevicePointValue,data 填设备与属性列表(4.2 报文格式),收到 SubscribeDevicePointValue_Reply 且 code=200 即成功;
  5. 接收推送:SubscribeDevicePointValue_Publish 先下发一次当前值快照,之后值变化时持续推送;按 deviceCode + identifier 更新本地缓存;
  6. 调整订阅:追加订阅=再次发送订阅消息;部分取消=UnSubscribeDevicePointValue(4.4);全部放弃=直接断开连接。

注意点:

  • data 字段是JSON 字符串(双重序列化),不是内嵌对象;
  • 订阅时 deviceTypeKey 为字符串,取消订阅时为数字(4.4);
  • 订阅成功立即收到快照;此后值不变不推送;
  • 断线重连后订阅关系清空,必须重发订阅;重连请用指数退避(上限 60s,见 10.1);
  • token 过期后握手会被拒绝,重连前先验证 token(调用任一 HTTP 接口或先 refresh);
  • 单连接订阅点位数建议不超过 2000(4.5)。
样例二:定时轮询实时值(无长连接场景)

适合无法维持 WebSocket 的环境(定时同步任务等)。

接入流程:登录取 token → 按「设备类型 + 属性」组织查询条件 → 定时调用 POST /iot/device/batchRealValue(3.5)→ 读取返回中各设备的 identifierValue。

注意点:

  • deviceTypePropertie 为单值,查询多个属性时拆成多个数组元素;
  • 轮询间隔不低于 30s(10.1);实时性要求高请改用样例一;
  • 该接口为快照查询,与 WS 推送的值同源。
样例三:下置控制并确认结果

接入流程:

  1. 确认可下置:目标属性 propertyAccessMode = rw(3.2);
  2. 先订阅该点位(样例一),用于接收执行结果;
  3. 发送下置:WS 发送 SetDeviceProperty(5.1),或 HTTP 调用 POST /iot/driver/issueDevicePointValue(5.3,需先经 3.4 拿 devicePointId);
  4. 确认结果:处理 SetDeviceProperty_Reply;200 表示平台已受理,实际执行结果以订阅推送为准。

注意点:

  • value 一律使用字符串形式;
  • Reply 200 ≠ 设备执行完成,仅为受理;设备离线或驱动不支持写会返回 400;
  • 下置失败时服务端会下发一次点位值纠正推送,以纠正推送的值为准回滚本地状态(5.1);
  • 控制留痕可在 5.5 控制记录接口回查。
样例四:拉取属性历史曲线

接入流程:确定设备与时间范围 → 调用 POST /iot/device/getPropertyHistoryValue(第六章),跨度大时使用周期聚合(queryOriginalValue=false + periodicTimeValue/periodicUnit)→ 以返回的 propertyValues[identifier] 数组为曲线数据点(time 为毫秒时间戳,升序)。

注意点:

  • 时间格式 yyyy-MM-dd HH:mm:ss,时区 GMT+8;
  • 返回覆盖设备全部有历史值的属性,按 identifier 取所需键即可;
  • 历史值存储频率由属性配置决定(3.2 的 updateCycleSeconds);大跨度查询务必用周期聚合控制返回量。
样例五:接收实时告警

接入流程:按样例一建立 WS 连接并声明 projectId → 无需额外订阅动作,配置为弹窗/声音方式的告警会自动以 SetAlarmMsg 主题推送(7.1)→ 需要完整信息时用 alarmMsgId 调 GET /alarm/msg/{id}(7.3)补全。

注意点:

  • 仅弹窗(POPUP)/声音(SOUND)两种告警方式走 WS,微信/短信等走各自通道;
  • WS 管即时告警,HTTP 分页查询(7.2)管历史回溯,两者配合使用;
  • 推送按 userId + projectId 定向,集成账号收到的即其权限范围内的告警。
10
使用约定与常见问题
调用频率与重试约定
  • 平台当前未对 HTTP 接口设强制限流,请对接方自律:轮询类调用(实时值、总览、告警轮询)建议不低于 30s 一次;WebSocket 是实时值的首选通道,能用订阅就不要轮询;
  • 单 WebSocket 连接订阅点位数建议不超过 2000(以平台方现场评估为准);
  • 断线/失败重试一律使用指数退避(1s/2s/4s…上限 60s),避免雪崩式重连或重试风暴;
  • 大时间跨度的历史值查询请使用周期聚合值(见第六章)控制返回量,避免一次拉取数万条原始值;
  • 后续平台侧若启用服务端配额,将提前通知并更新本档。
兼容性约定
  • 响应字段只增不减:新增字段不视为破坏性变更,对接方解析请忽略未知字段;
  • 破坏性变更(字段删除/改义、接口下线)将提前通知对接方,并在版本记录中注明;
  • 各枚举值域(枚举字典)如有扩充,新值会随版本更新公告,对接方解析枚举请做好未知值兜底。
常见问题(FAQ)
对接过程中的高频问题,先查这里再联系平台方
调用返回 431/432/433 怎么办?
431 检查 Authorization 头是否携带;432/433 说明 token 过期或失效,重新登录,或先调 POST /system/token/refresh 续期。
WebSocket 握手直接失败(连不上)?
按顺序排查:① token 是否有效(先用它调一个 HTTP 接口验证);② URL 是否用了 token 查询参数而非请求头;③ 网络中间设备是否放行 WebSocket 升级(Upgrade/Connection 头);④ 生产是否需要 wss://。
订阅成功但收不到推送?
① 确认收到过订阅后的快照(快照都没有 = 订阅参数有误,核对 deviceCode/deviceTypeKey/identifier);② 该点位值未变化则不会推送,属正常;③ 连接过期重连后未重新订阅(订阅关系随连接销毁)。
分页 total 有值但 data 为空?
检查 pageNum 是否超出总页数;部分接口缺省分页参数时行为不同,建议始终携带 pageNum/pageSize。
能耗/统计类接口的时间格式为什么每个接口不一样?
统计接口的时间格式随 unit 变化(如 unit=hour 用 2026-09-01 00:00:00、unit=month 用 2026-09、季用 20261/20262),详见 8.4 参数表——这是平台既有约定,传错格式会返回参数错误。
返回的 msg 是 back.xxx.xxx 这样的键?
国际化消息键未被翻译,多为冷门错误分支,请联系平台方确认含义并反馈。
下置返回成功但设备没动作?
data: true/Reply 200 表示平台已受理下发,执行结果取决于设备与驱动状态;设备离线或驱动不支持写会返回 400。下置失败时服务端会下发一次点位值纠正推送,请以纠正推送为准回滚本地状态(见 5.1)。
能耗查询没有数据?
能耗由平台定时计算(15 分钟/时/日/月粒度),刚接入的表具或刚过去的时段可能尚未算出;数据在但查不到时优先核对 category 与时间格式(见上一条 FAQ)。
11
附录:接口总览与枚举字典
接口总览
模块接口方法说明
鉴权/system/token/loginPOST登录取 token
/system/token/refreshPOST刷新 token
/system/token/logoutDELETE登出
/system/project/my/projectsGET当前账号有权限的项目(拿 projectId)
设备/iot/deviceType / /iot/deviceType/pageGET设备类型列表/分页
/iot/deviceTypeProperties/{deviceTypeKey}GET类型属性(物模型)
/iot/device/list / /iot/device/pageGET设备列表/分页
/iot/device/listDevicePointPOST设备点位(拿 devicePointId)
/iot/device/batchRealValuePOST批量获取设备实时值
/iot/device/getDeviceAndPropertieTreeGET设备属性树
/iot/device/count / /iot/device/countByDeviceTypePOST设备数量统计
/iot/overview/projectOverview / deviceTypeStatusOverviewGET项目/子系统设备状态总览
/iot/deviceGroup/listGET设备分组列表(拿 deviceGroupId)
/system/subsystemGET子系统列表(拿 subsystemId)
WebSocketws://{host}:{port}/base/websocket?token=&projectId=—实时值订阅/下置/告警推送通道
控制WS SetDeviceProperty / SetDeviceTypeProperty—属性下置(单设备/按范围批量)
/iot/driver/issueDevicePointValuePOSTHTTP 下置设备属性点位值
/iot/driver/issuePointValuePOSTHTTP 散点下置
/iot/deviceControl/record/page / listGET控制记录查询(审计)
历史值/iot/device/getPropertyHistoryValuePOST历史值(原始/周期聚合)
告警/alarm/msg/page / /alarm/msg/listGET告警分页/列表
/alarm/msg/currentGET当前报警
/alarm/msg/{id}GET告警详情
/alarm/msg/countNotReadGET未读告警数
/alarm/msg/count/type·level·status·subsystem·area·day·hourGET告警各维度统计
/alarm/typeLevel/MapType / MapLevelGET告警类型/级别枚举字典
能耗/energy/subItem/listGET分项列表(拿 subItemId)
/system/area/list / /energy/areaGET区域列表(拿 areaId)
/energy/tenant/listGET能耗租户列表(拿租户 id)
/energy/line/listGET能源支线列表(拿 lineId)
/energy/category/listGET能源分类展示信息
/energy/bindMeter/listGET表具绑定关系查询
/energy/area/consumption/pageGET区域能耗
/energy/statistics/subItemGET分项能耗统计
/energy/statistics/rank / compareGET/POST能耗排名/对比
/energy/statistics/flow/sankeyGET能流桑基图
/energy/statistics/tree·chart·banner·fee·totalMeterGET统计树/图表/横幅/费用/总表
/energy/overview/*(meterCount/subItem/periodOn/rank/load/banner)GET用能总览套件
/energy/report/meter·group·subItem·categoryTypeFeePOST/GET能耗与费用报表
/energy/yoyAndMomComparison/getYoYAndMoMPOST同比环比
/energy/exception/list / timeGET能耗异常清单/异常日期
枚举字典

正文中出现的全部枚举值汇总。对接方解析时请对未知值做兜底处理(见 兼容性约定)。

枚举取值使用处
能源分类 categoryelec 电 / water 水 / gas 气 / ener 能量能耗各接口
分组类型 groupTypearea 区域 / tenant 租户能耗统计/报表/排名
统计周期 unithour / day / month / quarter / year能耗统计(时间格式随 unit 变化)
聚合周期单位 periodicUnitsecond / minute / hour / day / month / year历史值查询
报表类型 reportTypeANNUAL 年报 / MONTHLY 月报 / RANGE 自定义范围能耗报表
流向类型 flowTypearea 区域 / sub_item 分项 / meter 总分表能流桑基图
告警级别 alarmLevelcritical 严重 / major 重要 / minor 一般 / trivial 次要告警查询
告警类型 alarmTypethreshold 阈值 / strategy 策略 / driver 驱动异常 / energy 能耗 / offline 离线 / authorization 授权 / system 系统告警查询
告警状态 alarmStatusin_progress 处理中 / unhandled 未处理 / handled 已处理 / recovered 已恢复告警查询
设备状态 deviceStatus0 未使用 / 1 离线 / 2 正常运行 / 3 已禁用设备查询(数据更新维度)
在离线判定状态 onlineStatus0 未知 / 1 在线 / 2 离线 / 3 故障设备查询
创建来源 createSource / sourceType1 平台用户 / 2 驱动上报 / 3 配置文件设备类型查询
属性访问权限 propertyAccessModer 只读 / rw 读写设备类型属性(仅 rw 可下置)
属性数据类型 dataTypedouble / int / bool / text / enum 等设备类型属性