Skip to content

能源管家OpenAPI文档 v1.0

1. 概述

由第三方使用HTTP形式进行数据对接、获取能源管家系统相关信息。

2. 前置准备/步骤

2.1 申请clientId和clientSecret

  • 线下找对接人申请clientId和clientSecret(对clientId和clientSecret信息进行保密,不要随意泄漏)
  • clientId:应用的唯一标识。
  • clientSecret:clientId对应的密钥,访问用户资源时用来验证应用的合法性。

2.2 申请请求域名

  • 具体环境域名线下找对接人提供
  • 请求域名:https://xxx
  • 接口请求示例如:查询计量设备读数 https://xxx/api/open/energy-manager-service/openApi/queryDeviceReading
  • 所有接口需通过clientId和clientSecret获取鉴权

3. 系统交互图

3.1 http请求交互图

4. 接口鉴权算法及请求示例

4.1 获取签名逻辑

  1. 对需要保护的数据进行拼接
    • 拼接方式:http请求方法 + "\n" + contentType + "\n" + 日期格式字符串 + "\n" + 请求资源uri
  2. 对拼接好的字符串和clientSecret进行HmacSHA1加密,并对加密结果进行base64编码
  3. 截取base64编码后的第5位开始的后续10个字符作为签名

4.2 获取签名示例

签名数据

项目
clientIdf3u5rgcjztb50jk5
clientSecretxtmrzck6q71rytdncigbnqwit685zij0gpk3lm6zyj54wcu
http请求方法POST
contentTypeapplication/json
日期格式RFC1123规范,例如:"EEE, dd MMM yyyy HH:mm:ss zzz"
请求的接口https://xx/api/open/energy-manager-service/openApi/test

签名过程

  1. 拼接后的字符串

    POST
    application/json; charset=UTF-8
    Sun, 04 Jan 2026 02:29:03 GMT
    /api/open/energy-manager-service/openApi/test
  2. 进行HmacSHA1加密和base64加密结果X4CMXyE2MHS9zlmwEpoSL9PKJk4=

  3. 截取base64加密后的第5位开始的后续10个字符作为签名yE2MHS9zlm

最终http请求头需携带的信息

Authorization = clientId:sign
Date = EEE, dd MMM yyyy HH:mm:ss zzz
Content-Type = application/json

请求示例

  • 方法:POST
  • URL: https://spup-uat.icloudcity.com/api/open/energy-manager-service/openApi/test

返回内容样式

json
{
  "code": 200,
  "success": true,
  "data": "成功执行了测试开放接口",
  "msg": "操作成功"
}

4.3 Java示例代码

见附录【6.3 Java签名示例代码】


5. 接口正文

5.1 批量查询计量设备读数

请求方式POST

请求路径/api/open/energy-manager-service/openApi/meterReadingBatch

请求参数

参数参数含义类型长度是否必填说明
projectCode项目编码String必填
deviceType设备类型String必填见6.1设备分类
deviceNumList设备编码List<string>200必填["MA-CC-SW-QE-FF", "YY-TT-RR-WW"]
date日期String必填样式:2025-12-11

返回参数

参数参数含义数据类型说明
code标识是否操作成功String200:显示成功
successbooleantrue
msg描述String
data返回数据Object

返回参数示例

json
{
  "code": 200,
  "success": true,
  "data": {
    "projectCode": "P0015",
    "deviceType": "01000",
    "date": "2026-01-11",
    "devReadList": [
      {
        "did": "7309853130898821120",
        "deviceNum": "D4AD2053FB7B_10",
        "deviceName": "L36 空调多联机[1-36KAP1]",
        "deviceStatus": "1",
        "currentRead": "6672.00",
        "identifier": "EPI",
        "reportTime": "2026-01-11 23:40:00",
        "desc": "存在"
      },
      {
        "did": "7309853128021528576",
        "deviceNum": "D4AD2053FB7B_05",
        "deviceName": "L14-18 住户用电[1-14-18AW]",
        "deviceStatus": "1",
        "currentRead": "521808.80",
        "identifier": "EPI",
        "reportTime": "2026-01-11 23:40:00",
        "desc": "存在"
      }
    ]
  },
  "msg": "操作成功"
}

5.2 设备台账

请求方式POST

请求路径/api/open/energy-manager-service/openApi/meter

请求参数

参数参数含义类型长度是否必填说明
projectCode项目编码String必填
deviceType设备类型String必填见6.1设备分类
pageNum页码int默认第一页
pageSize每页条数int默认10条,最大支持200条

返回参数

参数参数含义数据类型说明
code标识是否操作成功String200:显示成功
successbooleantrue
msg描述String
data返回数据Object
records数据内容Object
projectCode项目code编码String
deviceType设备类型String见6.1设备分类
deviceNum设备编码String
deviceName设备名称String
deviceStatus设备状态String见6.2设备状态分类
total总条数int
size数量int
current当前页int
pages分页数量int

返回参数示例

json
{
  "code": 200,
  "success": true,
  "data": {
    "records": [
      {
        "projectCode": "P0015",
        "deviceType": "01000",
        "deviceName": "1号变压器进线柜",
        "deviceNum": "D4AD2053FB7B_02",
        "deviceStatus": "1"
      }
    ],
    "total": 119,
    "size": 1,
    "current": 30,
    "pages": 119
  },
  "msg": "操作成功"
}

5.3 设备用量数据查询

请求方式POST

请求路径/api/open/energy-manager-service/openApi/queryEnergyData

请求参数

参数参数含义类型长度是否必填说明
projectCode项目编码String必填
deviceType设备类型String必填见6.1设备分类
deviceNumList设备编码List<string>50必填["MA-CC-SW-QE-FF", "YY-TT-RR-WW"]
dateType时间类型String必填日:day, 月:month, 年:year
date时间String必填日:yyyy-MM-dd, 月:yyyy-MM, 年:yyyy

返回参数

参数参数含义数据类型说明
code标识是否操作成功String200:显示成功
successbooleantrue
msg描述String
data返回数据Object
projectCode项目code编码String
deviceType设备类型String见6.1设备分类
deviceNum设备编码String
deviceName设备名称String
deviceStatus设备状态String见6.2设备状态分类
usageDetails用量明细Object
date具体的时间String传year会返回yyyy-MM,月会返回yyyy-MM-dd,日会返回yyyy-MM-dd
time详细的时间范围String传year:time为月份,传month:time为某一天,传day:time为某小时
used用能量String

返回参数示例

json
{
  "code": 200,
  "success": true,
  "data": {
    "projectCode": "P0015",
    "deviceType": "01000",
    "did": "7309853126712905728",
    "deviceNum": "D4AD2053FB7B_02",
    "deviceName": "1号变压器进线柜",
    "deviceStatus": "1",
    "usageDetails": [
      {
        "did": "7309853126712905728",
        "deviceNum": "D4AD2053FB7B_02",
        "date": "2026-01",
        "time": "01",
        "used": "704.00"
      }
    ]
  },
  "msg": "操作成功"
}

6. 附录

6.1 设备分类

编码描述
01000电表
02000水表
03000燃气
04000供热
05000供冷
06000压缩空气
07000氮气

6.2 设备状态分类

编码描述
1在线
2离线
0未激活

6.3 Java签名示例代码

java
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

@Slf4j
public class OpenApiClientAuth {

    private OpenApiClientAuth() {
    }

    private static final String DATE = "Date";
    private static final String KEY_MAC_SHA1 = "HmacSHA1";
    private static final String CONTENT_TYPE = "Content-Type";
    private static final String AUTHORIZATION = "Authorization";
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);

    private static Map<String, String> getSignHeaders(final String httpMethod, final String url, final String clientId, final String clientSecret, final String contentType) throws Exception {
        final String pathResource = OpenApiClientAuth.getPathResource(url);
        final String contentTypeValue = contentType != null ? contentType : "application/json";
        final String dateValue = DATE_TIME_FORMATTER.format(ZonedDateTime.now(ZoneId.of("GMT")));
        final String sign = OpenApiClientAuth.calculateSing(httpMethod, contentTypeValue, dateValue, pathResource, clientSecret);
        final Map<String, String> authHeaders = new HashMap<>(4);
        authHeaders.put(OpenApiClientAuth.DATE, dateValue);
        authHeaders.put(OpenApiClientAuth.AUTHORIZATION, clientId + ": " + sign);
        authHeaders.put(OpenApiClientAuth.CONTENT_TYPE, contentTypeValue);
        return authHeaders;
    }

    private static String getPathResource(final String url) {
        final String substring = url.substring(url.indexOf("/") + 3);
        return substring.substring(substring.indexOf('/'));
    }

    private static String calculateSing(final String httpMethodString, final String contentTypeValue, final String dateValue, final String pathResource, final String appSecret) throws Exception {
        final String signToString = OpenApiClientAuth.builderStringToSign(httpMethodString, contentTypeValue, dateValue, pathResource);
        final String base64HashString = hmacSha1Encrypt(signToString, appSecret);
        return base64HashString.substring(5, 15);
    }

    private static String builderStringToSign(final String method, final String contentTypeValue, final String dateValue, final String pathResource) {
        return method
                + "\n"
                + OpenApiClientAuth.handleNullString(contentTypeValue)
                + "\n"
                + OpenApiClientAuth.handleNullString(dateValue)
                + "\n"
                + pathResource;
    }

    private static String handleNullString(final String str) {
        return !StringUtils.hasText(str) ? "" : str;
    }

    private static String hmacSha1Encrypt(final String encryptText, final String encryptKey) throws Exception {
        final byte[] text = encryptText.getBytes(StandardCharsets.UTF_8);
        final byte[] keyData = encryptKey.getBytes(StandardCharsets.UTF_8);
        final SecretKeySpec secretKey = new SecretKeySpec(keyData, KEY_MAC_SHA1);
        final Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        return new String(Base64.getEncoder().encode(mac.doFinal(text)), StandardCharsets.UTF_8);
    }

    /**
     * @param url 请求地址
     */
    public static String openApiClientExecute(String url, String body, HttpMethod httpMethod, String clientId, String clientSecret) {
        // 方法实现...
        return null;
    }

    public static void main(String[] args) {
        String clientId = "yh5zmklapb0ehka0";
        String clientSecret = "cb9wt3osfum3gsle37trp4lrjk1kkq4ywcgeeg7b9e602qe";
        String postUrl = "https://spup-uat.icloudcity.com/api/open/smartpark-equipment/openApi/test";
        JSONObject body = new JSONObject();
        body.put("projectCode", "项目编码");
        body.put("equipmentName", "设备名称");
        String s2 = openApiClientExecute(postUrl, body.toJSONString(), HttpMethod.POST, clientId, clientSecret);
        System.out.println(s2);
    }
}