本文档用于规范能源管理系统后台接口调用标准,为前端开发、第三方对接、接口测试提供统一依据。
适用接口范围包括:
| 项目 | 说明 |
|---|---|
| 基础服务地址 | http://192.168.10.180:8089/api |
| 请求编码 | UTF-8 |
| 默认请求方式 | POST |
| 默认请求头 | Content-Type: application/json |
| 鉴权方式 | 登录接口无需鉴权;业务接口需在请求头携带 token |
| 序号 | 接口 | 路径 | 是否鉴权 | 主要用途 |
|---|---|---|---|---|
| 1 | 获取授权 Token | /thingshome-admin/sys/service/getToken |
否 | 使用账号密码换取全局业务接口 Token |
| 2 | 查询小时电量数据 | /thingshome-ems/realTime/selectByCustom |
是 | 按时间范围、采集点位、能源类型查询小时用电量 |
字段与文档一致性说明:
tagNameList 在参数表中写为 String,但请求示例为数组;结合字段名和接口语义,建议按 Array[String] 传参。energyTypeList 原文写为 Arrary[String],应为 Array[String]。type: "1",但参数表未说明;建议测试时保留该字段,避免后端依赖。data.dataList.fullTime、data.energyValue.thisValue 结构可能表示 data 内含列表对象,实际返回结构需以联调响应为准。| 项目 | 内容 |
|---|---|
| 接口路径 | /thingshome-admin/sys/service/getToken |
| 完整地址 | http://192.168.10.180:8089/api/thingshome-admin/sys/service/getToken |
| 请求方式 | POST |
| 是否鉴权 | 否 |
| 接口用途 | 通过账号密码登录,获取全局接口授权 Token |
| 参数名 | 是否必填 | 说明 |
|---|---|---|
Content-Type |
是 | 固定为 application/json |
| 参数名 | 类型 | 是否必填 | 说明 | 示例值 |
|---|---|---|---|---|
username |
String | 是 | 系统后台登录账号 | dt |
password |
String | 是 | 系统后台登录密码 | dt2026 |
{
"username": "dt",
"password": "dt2026"
}
| 参数名 | 类型 | 说明 |
|---|---|---|
msg |
String | 操作结果提示 |
code |
Integer | 0 表示成功,非 0 表示失败 |
data |
Object | 固定返回 null,无业务数据 |
expire |
Long | Token 有效时长,单位秒,默认 43200 秒 |
token |
String | 接口全局授权凭证,业务接口请求头携带 |
{
"msg": "操作成功",
"code": 0,
"data": null,
"expire": 43200,
"token": "3b622f1e7620d97589ba56d4b2ada5f4"
}
{
"msg": "账号或密码不正确",
"code": 500,
"data": null
}
curl -X POST "http://192.168.10.180:8089/api/thingshome-admin/sys/service/getToken" \
-H "Content-Type: application/json" \
-d '{"username":"dt","password":"dt2026"}'
依赖安装:pip install requests
import requests
base_url = "http://192.168.10.180:8089/api"
url = f"{base_url}/thingshome-admin/sys/service/getToken"
payload = {
"username": "dt",
"password": "dt2026",
}
response = requests.post(url, json=payload, timeout=15)
print("HTTP Status:", response.status_code)
print(response.text)
response.raise_for_status()
result = response.json()
if result.get("code") == 0:
print("Token:", result.get("token"))
else:
raise RuntimeError(f"登录失败: {result}")
| 项目 | 内容 |
|---|---|
| 接口路径 | /thingshome-ems/realTime/selectByCustom |
| 完整地址 | http://192.168.10.180:8089/api/thingshome-ems/realTime/selectByCustom |
| 请求方式 | POST |
| 是否鉴权 | 是,请求头必须携带 token |
| 接口用途 | 根据时间范围、采集点位、能源类型查询小时维度用电量,支持同比、环比数据计算 |
| 参数名 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
Content-Type |
String | 是 | 固定为 application/json |
token |
String | 是 | 登录接口获取的授权凭证 |
| 参数名 | 类型 | 是否必填 | 说明 | 示例值 |
|---|---|---|---|---|
type |
String | 建议传 | 原始示例包含该字段,参数表未说明 | 1 |
tagNameList |
Array[String] | 是 | 设备采集点位 ID 列表 | ["1024a2f19bbe464ab9073b5f5d92eea5"] |
energyTypeList |
Array[String] | 是 | 能源类型,固定为 ["electric power"] |
["electric power"] |
tb |
String | 是 | 固定为 0 |
0 |
startTime |
String | 是 | 查询开始时间,格式 yyyy-MM-dd HH:mm:ss |
2026-07-01 00:00:00 |
endTime |
String | 是 | 查询结束时间,格式 yyyy-MM-dd HH:mm:ss |
2026-07-01 23:59:59 |
dateCode |
String | 是 | 小时维度固定为 h |
h |
{
"type": "1",
"tagNameList": ["1024a2f19bbe464ab9073b5f5d92eea5"],
"energyTypeList": ["electric power"],
"tb": "0",
"startTime": "2026-07-01 00:00:00",
"endTime": "2026-07-01 23:59:59",
"dateCode": "h"
}
| 参数名 | 类型 | 说明 |
|---|---|---|
msg |
String | 请求结果提示 |
code |
Integer | 状态码,0 表示成功 |
data |
Array/Object | 电量数据结果,实际结构以接口返回为准 |
data.dataList.fullTime |
String | 数据统计小时时间 |
data.energyValue.thisValue |
Double | 当前小时用电量,单位 kWh |
先将登录接口返回的 Token 替换到 $TOKEN。
export TOKEN="替换为登录接口返回的token"
date && curl -X POST "http://192.168.10.180:8089/api/thingshome-ems/realTime/selectByCustom" \
-H "Content-Type: application/json" \
-H "token: ${TOKEN}" \
-d '{"type":"1","tagNameList":["451a9243-7817-4b75-87df-f1cae52dfa30", "44ca7632-b9a5-47e8-af4b-2fe3971021fc","0a55b5eb-9a7a-401c-954a-9ce4488f5a8b"],"energyTypeList":["electric power"],"tb":"0","startTime":"2026-07-01 15:00:00","endTime":"2026-07-01 18:59:59","dateCode":"h"}'
依赖安装:pip install requests
import requests
base_url = "http://192.168.10.180:8089/api"
login_url = f"{base_url}/thingshome-admin/sys/service/getToken"
login_payload = {
"username": "dt",
"password": "dt2026",
}
login_response = requests.post(login_url, json=login_payload, timeout=15)
print("Login HTTP Status:", login_response.status_code)
print(login_response.text)
login_response.raise_for_status()
login_result = login_response.json()
if login_result.get("code") != 0:
raise RuntimeError(f"登录失败: {login_result}")
token = login_result["token"]
query_url = f"{base_url}/thingshome-ems/realTime/selectByCustom"
headers = {
"Content-Type": "application/json",
"token": token,
}
query_payload = {
"type": "1",
"tagNameList": ["1024a2f19bbe464ab9073b5f5d92eea5"],
"energyTypeList": ["electric power"],
"tb": "0",
"startTime": "2026-07-01 23:30:00",
"endTime": "2026-07-01 23:59:59",
"dateCode": "h",
}
query_response = requests.post(query_url, headers=headers, json=query_payload, timeout=30)
print("Query HTTP Status:", query_response.status_code)
print(query_response.text)
query_response.raise_for_status()
query_result = query_response.json()
if query_result.get("code") != 0:
raise RuntimeError(f"查询失败: {query_result}")
{
"msg": "操作成功",
"code": 0,
"data": {
"unit": "kW·h",
"data": [
{
"name": "全厂",
"id": "1024a2f19bbe464ab9073b5f5d92eea5",
"parentId": "0",
"type": null,
"value": 0.0,
"tbValue": 0.0,
"hbValue": 0.0,
"tbCost": 0.0,
"hbCost": 0.0,
"tbCoal": 0.0,
"hbCoal": 0.0,
"tbCarbon": 0.0,
"hbCarbon": 0.0,
"tbCompare": 0.0,
"hbCompare": 0.0,
"dataList": [
{
"id": "1024a2f19bbe464ab9073b5f5d92eea5",
"costValue": 0.0,
"coalValue": 0.0,
"carbonValue": 0.0,
"hbValue": 0.0,
"tbValue": 0.0,
"hbCarbon": 0.0,
"tbCarbon": 0.0,
"hbCoal": 0.0,
"tbCoal": 0.0,
"hbCost": 0.0,
"tbCost": 0.0,
"sort": null,
"hbCompare": 0.0,
"tbCompare": 0.0,
"name": "全厂",
"unit": "kW·h",
"aggregationType": null,
"fullTime": "2026-07-01 23:00:00",
"forecastValue": null,
"savingValue": null,
"productName": null,
"energyType": "electric power",
"weekTime": null,
"thisValue": 0.0,
"time": "2026-07-01 23",
"unitName": "kW·h",
"acquisitionTime": "2026-07-01 23",
"mean": null,
"up": null,
"low": null,
"std": null,
"cpk": null,
"status": 1,
"paramsList": null,
"ybList": null,
"e": null,
"t": null,
"coalUnit": null,
"carbonUnit": null,
"costUnit": null,
"forestValue": null,
"deviationValue": null,
"forestDeviationValue": null
}
],
"unit": "kW·h",
"unitName": "kW·h",
"costValue": 0.0,
"coalValue": 0.0,
"carbonValue": 0.0,
"sort": 0,
"energyType": "electric power",
"fullName": "全厂",
"accuracy": "0.0",
"coalUnit": null,
"carbonUnit": null,
"costUnit": null
}
],
"trend": [
{
"id": "1024a2f19bbe464ab9073b5f5d92eea5",
"costValue": 0.0,
"coalValue": 0.0,
"carbonValue": 0.0,
"hbValue": 0.0,
"tbValue": 0.0,
"hbCarbon": 0.0,
"tbCarbon": 0.0,
"hbCoal": 0.0,
"tbCoal": 0.0,
"hbCost": 0.0,
"tbCost": 0.0,
"sort": null,
"hbCompare": 0.0,
"tbCompare": 0.0,
"name": "全厂",
"unit": "kW·h",
"aggregationType": null,
"fullTime": "2026-07-01 23:00:00",
"forecastValue": null,
"savingValue": null,
"productName": null,
"energyType": "electric power",
"weekTime": null,
"thisValue": 0.0,
"time": "2026-07-01 23",
"unitName": "kW·h",
"acquisitionTime": "2026-07-01 23",
"mean": null,
"up": null,
"low": null,
"std": null,
"cpk": null,
"status": 1,
"paramsList": null,
"ybList": null,
"e": null,
"t": null,
"coalUnit": null,
"carbonUnit": null,
"costUnit": null,
"forestValue": null,
"deviationValue": null,
"forestDeviationValue": null
}
],
"sum": 0.0
}
}
43200 秒,业务接口测试时优先复用同一个 Token。tagNameList 点位 ID 是否存在、时间范围内是否有小时电量数据。token。使用 Python 编写小时数据采集程序,定时从能源管理系统接口查询上一小时点位数据,通过 addpointdatum 接口写入点位数据,并触发计算聚合接口。
已实现脚本:main.py。
程序默认每小时第 30 分钟执行一次。
示例:
18:30 执行一次17:00:0017:59:59begin 时间戳:17:00:00end 时间戳:18:00:00时间戳按当前服务器本地时区转换。
程序使用 YAML 配置文件,默认读取 config.yaml。
配置示例:
energy_chaowang:
base_url: "http://192.168.10.180:8089/api"
username: "dt"
password: "dt2026"
login_timeout_seconds: 15
query_timeout_seconds: 30
token_refresh_interval_hours: 6
points:
file: "points.xlsx"
services:
basedataportal: "http://basedataportal-svc:8080"
calcagg: "http://127.0.0.1:8080"
schedule:
minute: 30
logging:
file: "logs/jdf-energy-collector.log"
retention_days: 3
字段说明:
| 配置项 | 说明 |
|---|---|
energy_chaowang.base_url |
能源管理系统接口基础地址 |
energy_chaowang.username |
登录用户名 |
energy_chaowang.password |
登录密码 |
energy_chaowang.login_timeout_seconds |
登录接口超时时间 |
energy_chaowang.query_timeout_seconds |
小时点位数据查询接口超时时间 |
energy_chaowang.token_refresh_interval_hours |
Token 重新登录间隔,默认 6 小时 |
points.file |
点位 Excel 文件路径 |
services.basedataportal |
基础数据服务基础地址,例如 http://basedataportal-svc:8080 |
services.calcagg |
计算聚合服务基础地址,例如 http://127.0.0.1:8080 |
schedule.minute |
每小时执行分钟,默认 30 |
logging.file |
日志文件路径 |
logging.retention_days |
日志保留天数,默认 3 天 |
点位文件为 points.xlsx。
点位文件只在程序启动时读取一次,后续每次 run_once 直接使用内存中的点位映射。
启动时会校验:
id 列不能有重复值point_id 列不能有重复值使用字段:
| Excel 列名 | 用途 |
|---|---|
id |
作为能源管理系统查询接口 tagNameList 的内容 |
point_id |
作为 addpointdatum 和聚合接口 point_ids 的内容 |
Excel 示例:
| id | point_id |
|---|---|
b541250d-23a8-432c-863a-e6807c70da0f |
P_TEST_1 |
0c1867f8-cc95-46a3-a3f4-ff56b0ffc3bf |
P_TEST_2 |
程序启动后首次查询小时点位数据前,需要先调用登录接口获取 Token。Token 保存在内存中,后续查询复用该 Token。
登录刷新规则:
6 小时重新调用一次登录接口energy_chaowang.token_refresh_interval_hours 配置10:00,下次登录接口请求时间为 16:00登录重试规则:
60 秒后重试3 次3 次全部失败后,本轮任务终止请求体中的 tagNameList 使用 points.xlsx 的 id 列。
请求体示例:
{
"type": "1",
"tagNameList": [
"points.xlsx 中的 id"
],
"energyTypeList": [
"electric power"
],
"tb": "0",
"startTime": "2026-07-03 17:00:00",
"endTime": "2026-07-03 17:59:59",
"dateCode": "h"
}
查询接口重试规则:
timeout 时重试timeout 后等待 10 秒3 次addpointdatum 写入和聚合调用每次调用 HTTP 接口前后都会写入日志,日志包含请求接口、请求参数、响应内容、HTTP 状态码和耗时 elapsed_ms。敏感字段如 password、token 会脱敏。
优先从响应数据中解析:
data.data[*].dataList[*]
若该结构为空,则尝试读取:
data.trend[*]
需要获取字段:
| 字段 | 用途 |
|---|---|
id |
匹配 Excel 中的 id |
name |
打印输出 |
fullTime |
打印输出,并转换为服务器本地时区时间戳 |
thisValue |
打印输出;非 0 时作为 addpointdatum 的 value 写入 |
打印内容包含:
name, fullTime, thisValue
接口地址拼接规则:
{services.basedataportal}/ai/addpointdatum
请求体为数组,每个元素对应一个 point_id。
请求体示例:
[
{
"point_id": "Excel中的point_id",
"data": [
{
"ts": 1781770962,
"value": "49.97"
}
]
}
]
字段说明:
| 字段 | 说明 |
|---|---|
point_id |
来自 points.xlsx 的 point_id 列 |
data[].ts |
接口响应中的 fullTime 按服务器本地时区转换后的秒级时间戳 |
data[].value |
接口响应中的 thisValue,按字符串写入 |
写入方式:按点位聚合为一个数组后,一次性调用 addpointdatum 接口。
若 thisValue 为 0 或 0.0,该点位跳过写入,并记录当前遍历对象内容。
若 addpointdatum 响应中的 state != 0,本轮任务失败,不继续调用计算聚合接口。
addpointdatum 写入成功后,调用计算聚合接口。
接口地址拼接规则:
{services.calcagg}/api/calcagg/calc_agg_points_range
请求体:
{
"end": 1893528000,
"begin": 1893524400,
"sync_run": true,
"point_ids": [
"Excel中的point_id"
],
"operator_id": 1,
"operator_name": "jdf-energy-collector"
}
字段说明:
| 字段 | 说明 |
|---|---|
begin |
上一个整点时间戳,例如 17:00:00 |
end |
当前整点时间戳,例如 18:00:00 |
sync_run |
固定为 true |
point_ids |
本轮成功写入 addpointdatum 的 Excel point_id 列 |
operator_id |
固定为 1 |
operator_name |
固定为 jdf-energy-collector |
响应处理规则:
state != 0,打印完整响应内容elapsed_ms安装依赖:
poetry install
常驻运行:
poetry run python main.py --config config.yaml
程序依赖:
requests
openpyxl
PyYAML