OCPP1.6协议

news/2024/10/23 9:26:50/

目录

导言

功能简介

本地授权列表

类型

IdToken

IdTagInfo

授权状态

ChargePointErrorCode

CiString50Type

充电桩状态-ChargePointStatus

远程启动停止状态 -RemoteStartStopStatus

协议指令

1、授权-Authorize

1.1 说明

1.2  Authorize.req

1.3 Authorize.conf

1.4 JSON格式

1.5 代码

2、启动通知-BootNotification

2.1 说明

2.2 BootNotification.req

2.3 BootNotification.conf

2.4 JSON格式

2.5 代码

3、心跳-HeartBeat

3.1 说明

3.2 Heartbeat.req

3.3 Heartbeat.conf

3.4 JSON格式

3.5 代码

4、状态通知-StatusNotification

4.1 说明

4.2 StatusNotification.req

4.3 StatusNotification.conf

4.4 JSON格式

4.5 代码

5、远程启动-RemoteStartTransaction

5.1 说明

5.2 RemoteStartTransaction.req

5.3 RemoteStartTransaction.conf

5.4 JSON格式

5.5 代码

6、远程停止-RemoteStopTransaction

6.1 说明

6.2 RemoteStopTransaction.req

6.3 RemoteStopTransaction.conf

6.4 JSON格式

6.5 代码

通用方法

1、转换时间为UTC格式


导言

     这是 OCPP 1.6 版的规范。
     OCPP 是一种标准的开放式协议,用于充电站与中央系统之间的通信,可适用于任何类型的充电技术。
      OCPP 1.6 引入了适应市场的新功能:智能充电、通过 Websockets 使用 JSON 的 OCPP、更好的诊断可能性( 原因 )、更多的充电点 状态 触发信息 TriggerMessage )。OCPP 1.6 以 OCPP 1.5 为基础,增加了一些新功能和大量 文字上的改进、说明,并修正了所有已知的模糊之处。由于改进和新增功能,OCPP 1 . 6 与 OCPP 1.5 并不向后兼容 。
有关变更的完整列表,请参阅 OCPP 1.6 中的新 功能。
       一些基本概念将在本介绍性章节的以下部分进行解释。各章: 由充电桩启动的操作 由中央系统启动 的操作描述 了协议支持的操作。确切的信息及其参数将在本章中详细说明: 信息 和数据类型在 "数据类型 "一章中进行了描述 : 类型 。定义的配置密钥在 "标准配置密钥名称和参数 "一章中描述: 标准配置键名称和值
     随着 OCPP 1.6 版本的推出,OCPP 有了两种不同的版本;除了基于 SOAP 的实现外,还有可能使用更为简洁的 JSON 版本。为避免在交流中混淆实现类型,我们建议使用不同的后缀 -J 和 -S 来表示 JSON 或 SOAP。一般来说, OCPP-J 表示 JSON,OCPP-S 表示 SOAP。
为了支持不同的版本,OCPP 标准分为多个文件。基础文档(您正在阅读的文档)包含技术协议规范。 OCPP SOAP 规范》(OCPP SOAP Specification )包含实现 OCPP-S 所需的实施规范。对于 OCPP-J,必须使用 OCPP JSON 规范。
为提高中央系统与充电桩之间的互操作性,建议满足 OCPP 1.6 合规性测试 文件中的要求。

功能简介

在 OCPP 1.6 中,功能和相关信息按 配置文件 分组。根据所需功能,实施者可选择实施以下一个或多个配置文件。
客户可使用这些配置文件来确定 OCPP 1.6 产品是否具备其业务所需的功能。合规性测试将根据配置文件测试产品 是否符合 OCPP 1.6 规范。 必 须 执行核心配置文件。其他配置文件为可选配置文件。 在执行核心、固件管理、本地验证列表管理和预订配置文件时,将涵盖源自 OCPP 1.5 [OCPP1. 5 ] 的所有功能。
下表显示了所有信息在其配置文件中的分组情况

本地授权列表

类型

IdToken

包含用于授权的标识符。这是一个不区分大小写的字符串。在今后的版本中,它可能会成为 一个复杂类型,以支持 多种形式的标识符。

IdTagInfo

包含有关标识符的状态信息。它在授权、开始交易和停止交易响应中返回。
如果没有给出 expiryDate,则状态没有结束日期。

授权状态

枚举
Authorize.req 响应中的状态。

ChargePointErrorCode

StatusNotification.req 中报告的充电点状态。
中文
英文

CiString50Type

通用字符串,不区分大小写,共 50 个字符。
中文
英文

充电桩状态-ChargePointStatus

StatusNotification.req 中报告的状态。可为充电点主控制器(connectorId = 0)或特定连接器报告状态。充电点主
控制器的状态是枚举的一个子集: 可用 不可用 故障
可运行状态包括 可用 准备 充电 暂停 EVSE 暂停 EV 完成 保留 。不工作状态包括 不可用 故障
英文
远程启动停止状态- RemoteStartStopStatus
枚举
RemoteStartTransaction.req RemoteStopTransaction.req 请求的结果。
英文

远程启动停止状态 -RemoteStartStopStatus

枚举
RemoteStartTransaction.req RemoteStopTransaction.req 请求的结果。
英文

协议指令

1、授权-Authorize

1.1 说明

      在电动汽车车主开始或停止充电之前,充电桩必须授权操作。充电点只能在授权后才能提供能量。停止交易时, 只有当用于停止交易的标识符与开始交易的标识符不同时,充电桩才会发送 Authorize.req 消息。
Authorize.req 应仅用于授权标识符收费。
本地授权列表 所述,充电点可在不涉及中央系统的情况下在本地授权标识符。如果用户提交的 idTag 不在本地
授权列表或授权缓存中,则充电点应向中央系统发送 Authorize.req PDU 请求授权。如果 idTag 存在于本地授权
列表或授权缓存中,则充电点可以向中央系统发送 Authorize.req PDU。
收到 Authorize.req PDU 后,中心系统应回应一个 Authorize.conf PDU。此响应 PDU 应表明中心系统是否接受
idTag。如果中心系统 接受 idTag,那么响应 PDU 可以包括 parentIdTag ,并且必须包括 表示接受或拒绝原因的 授权
状态值。
如果 Charge Point 已实施了授权缓存,那么在收到 Authorize.conf PDU 后,如果 idTag 不在 本地授权列表 中,
Charge Point 应按照 授权 缓存中所述,用响应中的 IdTagInfo 值更新缓存条目

1.2  Authorize.req

它包含充电点发送到中央系统的 Authorize.req PDU 的字段定义。

1.3 Authorize.conf

它包含中央系统为响应 Authorize.req PDU 而向充电点发送的 Authorize. conf PDU 的字段定义。

1.4 JSON格式

【SEND】♂[2,"yiBSjMizbzFWUcmz","Authorize",{"idTag":"F3F7C00B"}]


【RECV】♀[3,"yiBSjMizbzFWUcmz",{"idTagInfo":{"status":"Accepted"}}]

1.5 代码

逻辑处理

/**
*   授权
* @param data
* @param msgId
* @param msgType
* @param
* @param
* @return
*/
public ReturnData Authorize(String data,String msgId,
String msgType,String ip,String action,String body){
// 桩子 发起的充电,都要走授权
ReturnData returnData=new ReturnData();
try {
// 根据ip查询对应的设备
String equSql="select * from jk_equ where ip='"+ip+"' order by communication_time desc ";
Record equRecord=Db.findFirst(equSql);
if(null!=equRecord){
// [2,"m3MxfgtUXBR1QoyY","Authorize",{"idTag":"43AA3CA6"}]
JSONObject idTagObj=JSONObject.parseObject(data);
// 卡号 43AA3CA6
String idTag=idTagObj.getString("idTag");
IdTagInfo info=new IdTagInfo();
info.setStatus("Accepted");

// 时间推迟 60分钟
Date endDate=DateUtil.getAfterMinute(new Date(),60);
String utcStr=DateUtil.localToUTC(endDate);
info.setExpiryDate(utcStr);

List resultList=new ArrayList();
resultList.add(Integer.parseInt(msgType)+1);
resultList.add(msgId);
AuthorizeConfig authorizeConfig=new AuthorizeConfig();
authorizeConfig.setIdTagInfo(info);
resultList.add(authorizeConfig);

returnData.setResult(true);
log.info("刷卡返回信息:{}",JSON.toJSONString(resultList));
String json=new ObjectMapper().writeValueAsString(resultList);
returnData.setData(json);
}else{
log.error("收到充电点反馈,并且开启事务异常:设备不在线");
returnData.setMsg("设备不在线");
returnData.setResult(false);
}
}catch (Exception e){
log.error("收到充电点反馈,并且开启事务异常",e);
returnData.setResult(false);
}
return returnData;
}

实体类 

1、IdTagInfo

import lombok.Data;
/**
*
* 授权token回复详细信息
*/
@Data
public class IdTagInfo {
// Accepted 允许使用可充电的标识符
// Blocked 标识符已被阻止。不允许充电。
// Expired 标识符已过期。不允许充电。
// Invalid 标识符未知。不允许充电。
// ConcurrentTx 标识符已涉及到另一个事务中,并且不允许有多个事务。(仅与StartTransaction.req相关。)
private String status;
// 这其中包含idTag应该从授权缓存中删除的日期。
private String expiryDate;
//private IdToken idToken;//父级标识符。
}

2、AuthorizeConfig

import lombok.Data;
/**
* 授权配置
*/
@Data
public class AuthorizeConfig {
   private IdTagInfo idTagInfo;
}

2、启动通知-BootNotification

2.1 说明

其中包含中央系统为响应 BootNotification. req PDU 而向充电点发送的 BootNotification. conf PDU 的字段定义。
启动后,充电点应向中央系统发出请求,提供有关其配置的信息(如版本、供应商等)。中央系统应作出回应, 表明是否接受该充电点。
每次启动或重启时,充电点都应发送 BootNotification.req PDU。在物理开机/重启和成功完成 BootNotification( 中央系统返回 "接受 "或 " 等待 " 之间,充电点不得向中央系统发送任何其他请求。这包括缓存的 充电点中仍然存在的信息。
当中央系统以 " 已接受 " Accepted )状态回复 BootNotification.conf 时,充电点 将 根据回复 PDU 中的时间间隔调整心 跳间隔,建议将其内部时钟与提供的中央系统当前时间同步。如果中央系统返回的不是 " 接受 " ,则间隔字段的值表 示发送下一个启动通知请求 前的最短等待时间 。如果时间间隔值为零,则充电点自 行 选择等待时间间隔,以避免中心系统收到大量请求。除非有 TriggerMessage.req 请求,否则充电点不应提前发送 BootNotification.req
如果中央系统返回 " 拒绝 " 状态,充电点不得向中央系统发送任何 OCPP 报文,直到上述重试间隔时间结束。在此时间间隔内,中央系统可能无法再联系到充电点。例如,充电点可以关闭其通信通道或关闭其通信硬件。中央系统也可以 关闭通信通道,例如释放系统资源。 在拒绝 期间,充电点不得响应任何由中央系统发起的信息。
中央系统也可以返回一个 " 待定 " 注册状态,以表明它希望在中央系统接受该充电点之前检索或设置充电点的某些 信息。如果中央系统返回 "等待 " 状态,充电点或中央系统都不应关闭通信通道。中央系统可发送请求信息,从充电点获取信息或更改其配置。充电点应响应这些信息。除非中央系统发出 TriggerMessage.req 请求,否则充电点不得向中央系统发送请求信息。
待处理 状态下,不允许使用以下由中央系统发起的报文: RemoteStartTransaction.req
RemoteStopTransaction.req。

2.2 BootNotification.req

中文图

英文图

2.3 BootNotification.conf

中文图

英文图

2.4 JSON格式

[2,\"e3ba4698-d64b-447e-81f5-0bf0e09700eb\",\"BootNotification\",{\"chargePointVendor\":\"\",\"chargePointModel\":\"\",\"chargePointSerialNumber\":\"\",\"chargeBoxSerialNumber\":\"\",\"firmwareVersion\":\"\",\"iccid\":\"\",\"imsi\":\"\",\"meterType\":\"\",\"meterSerialNumber\":\"\"}]

[3, "e3ba4698-d64b-447e-81f5-0bf0e09700eb", {"status": "Accepted", "interval": 30, "currentTime": "2023-10-10T03:37:53Z"}]

2.5 代码

1.逻辑处理

/**
* 设备启动通知
* @param data
* @param msgId
* @param msgType
* @param action
* @param ip
* @return
*/
public ReturnData BootNotification(String data,String msgId,String msgType,String action,String ip,String body){
ReturnData returnData=new ReturnData();
try {
equHex=equHex.replaceAll("/","");
BootNotificationReq req=JSON.parseObject(data,BootNotificationReq.class);
String chargePointSerialNumber=req.getChargePointSerialNumber();//充电桩编号
log.info("sn的Hex{}",chargePointSerialNumber);
String states="Accepted";// 默认拒绝
BootNotificationConf conf=new BootNotificationConf();
String utcDateStr=DateUtil.localToUTC(new Date());

conf.setCurrentTime(utcDateStr); //过期时间
conf.setInterval(30);
conf.setStatus(states);

List resultList=new ArrayList();
resultList.add(Integer.parseInt(msgType)+1);
resultList.add(msgId);
resultList.add(conf);
String json = new ObjectMapper().writeValueAsString(resultList); //用此方法转为json字符串
returnData.setData(json);
returnData.setResult(true);
}catch (Exception e){
log.error("启动通知异常",e);
returnData.setResult(false);
}
return returnData;
}

2. BootNotificationReq
import lombok.Data;
/**
* 启动通知req
*/
@Data
public class BootNotificationReq {
//可选。它包含一个值,用来标识充电点内的充电箱的序列号。已弃用
//,将在未来的版本中被删除
private String chargeBoxSerialNumber;
//需要。这包含一个标识字符点模型的值。
private String chargePointModel;//充电桩模型
//可选。这其中包含一个标识充电点序列号的值。
private String chargePointSerialNumber;
//需要。这包含一个标识特征点的供应商的值
private String chargePointVendor;
//可选。这其中包含了充电点的固件版本
private String firmwareVersion;
//可选。其中包含调制解调器SIM卡的ICCID。
private String iccid;
//可选。其中包含调制解调器SIM卡的IMSI。
private String imsi;
//可选。其中包含充电点的主电表的序列号。
private String meterSerialNumber;
//可选。这包含了充电点的主电表的类型。
private String meterType;
}

3. BootNotificationConf

import lombok.Data;
/**
* 启动通知回复
*/
@Data
public class BootNotificationConf {
// Accepted 充电点已被中央系统接受。
//Pending 中央系统还没有准备好接受充电点。中央系统可以发送信息来检索信息或准备充电点。
// Rejected 中央系统不接受充电点。当中央系统不知道充电点id时,可能会发生这种情况以上翻译结果来自有道神经网络翻译(YNMT)· 通用场景
private String status;
//需要。这包含了中央系统的当前时间。
private String currentTime;
//需要。当接受注册状态时,它包含以秒为单位的心跳间隔。如果中央系统返回的不
//是“接受”,则间隔字段的值表示发送下一个引导通知请求之前的最小等待时间
private Integer interval;
}

3、心跳-HeartBeat

3.1 说明

为了让中央系统知道充电点仍处于连接状态,充电点会在可配置的时间间隔后发送心跳信息。
充电点应发送 Heartbeat.req PDU,以确保中央系统知道充电点还活着。
收到 Heartbeat.req PDU 后,中央系统应响应 Heartbeat.conf 。响应 PDU 应包含中央系统的当前时间,建议充电点使用该时间同步其内部时钟。
当另一个 PDU 已在配置的心跳时间间隔内发送到中央系统时,充电点可以跳过发送 Heartbeat.req PDU。这意 味着只要收到 PDU,中央系统就应该认为充电点是可用的,就像它收到 Heartbeat.req PDU 时一样。
注意:对于 WebSocket 上的 JSON,发送心跳并不是强制性的。不过,为了实现时间同步,建议至少每24 小时发送一次心跳。

3.2 Heartbeat.req

未定义字段

3.3 Heartbeat.conf

 它包含中央系统为响应 Heartbeat.req PDU 而发送给充电点的 Heartbeat.conf PDU 的字段定义。

中文

英文

3.4 JSON格式

[SEND ->] [2,"QsGAIVnh39SDvmzg","Heartbeat",{}]


[RECV <-] [3,"QsGAIVnh39SDvmzg",{"currentTime":"2023-05-17T14:26:10.306+08:00"}]

3.5 代码

1、逻辑

/**
* 设备心跳
* @return
*/
public ReturnData equheartbeat(String data,String msgType,
String msgId,String action,String ip,String body) {
ReturnData returnData = new ReturnData();
try {
log.info("设备心跳{}",data);
if(null!=ip && !"".equals(ip)){
List resultList=new ArrayList();
resultList.add(Integer.parseInt(msgType)+1);
resultList.add(msgId);
Map<String,Object> map=new HashMap<>();
Heartbeat heartbeat=new Heartbeat();
String utcStr=DateUtil.localToUTC(new Date());
heartbeat.setCurrentTime(utcStr);

map.put(action,heartbeat);
resultList.add(heartbeat);
returnData.setData(JSON.toJSONString(resultList));
returnData.setResult(true);
}
}else{
returnData.setMsg("设备心跳异常,无法获取ip");
returnData.setCode("111111");
returnData.setResult(false);
return returnData;
}
} catch (Exception e) {
returnData.setMsg("设备心跳异常"+e);
returnData.setCode("111111");
returnData.setResult(false);
e.printStackTrace();
}
return returnData;
}

2、Heartbeat

import lombok.Data;
/**
* 设备心跳
*/
@Data
public class Heartbeat {
        private String currentTime;
}

4、状态通知-StatusNotification

4.1 说明

充电点向中央系统发送通知,告知中央系统充电点的状态变化或错误。下表描述了充电点可能向中央系统发送 StatusNotification.req PDU 时从先前状态(左列)到新状态(上行)的变化。
注意:
OCPP 以前版本中定义的 " 占用 状态 "已不再适用。 占用状态状态分为五个新状态:准备状态、充电状态、暂停 EV 状态、暂停 EVSE 状态 和 完成。
状态通知中使用的是 EVSE,而不是插座或充电桩,以便将来兼容。

4.2 StatusNotification.req

其中包含充电点发送到中央系统的 StatusNotification.req PDU 的字段定义。
中文
英文

4.3 StatusNotification.conf

其中包含中央系统为响应 StatusNotification.req PDU 而向充电点发送的 StatusNotification.conf PDU 的字段定义。
未定义字段。

4.4 JSON格式

插枪


[SEND ->] [2,"I5622jdZvMI5nrqc","StatusNotification",{"connectorId":1,"errorCode":"NoError","status":"Preparing","timestamp":"2023-08-14T05:31:03Z"}]

[RECV <-] [3,"I5622jdZvMI5nrqc","{}"]

拔枪

[SEND ->] [2,"5KaXyxFzqamWjDJ3","StatusNotification",{"connectorId":1,"errorCode":"NoError","status":"Available","timestamp":"2023-08-14T06:47:10Z"}]

[3,"5KaXyxFzqamWjDJ3","{}"]

4.5 代码

/**
* 状态通知 data,msgType,msgId,action
* @param data
* @param msgType
* @param msgId
* @param action
* @return
*/
public ReturnData statusNotification(String data, String msgType,String msgId,
String action,String ip,String body) {
log.info("设备开始充电状态上报{}",data);
ReturnData returnData = new ReturnData();
String startInfo="";
StatusNotification statusNotification=JSON.parseObject(data,StatusNotification.class);
boolean start=false;
if ("Available".equals(statusNotification.getStatus())
|| "Preparing".equals(statusNotification.getStatus())
|| "Charging".equals(statusNotification.getStatus() )
){ //0x00失败 0x01成功
start=true;
}else {
start=false;
startInfo=statusNotification.getStatus();
}
if (start){
log.info("设备开始充电状态上报信息{}");
}else {
log.info("设备开始充电状态上报,失败代码{},失败详情{}",statusNotification.getStatus(),startInfo);
}
List resultList=new ArrayList();
resultList.add(Integer.parseInt(msgType)+1);
resultList.add(msgId);
resultList.add(new ArrayList<>());

returnData.setData(JSON.toJSONString(resultList));
returnData.setResult(true);
return returnData;
}

StatusNotification

/**
* 发起充电回调
*/
@Data
public class StatusNotification {
private Integer connectorId;//通道ID
private String errorCode;//错误代码

// Available 第一次收到充电命令,且可用
// Preparing 不是第一次收到充电命令,但是可用
// Charging 当连接器的接触器关闭时,允许车辆充电(操作性)
// SuspendedEVSE 当电动汽车连接到EVSE,但EVSE没有向电动汽车提供能源时,例如由于智能充电限制、本地供电电源限制,或由于StartTransaction.conf表明不允许充电等。(操作性的)
// SuspendedEV 当电动汽车连接到EVSE时,EVSE会提供能源,但电动汽车不吸收任何能源。(操作性的)
private String status;//状态
private String timestamp;//时间戳

}

5、远程启动-RemoteStartTransaction

5.1 说明

中央系统可通过发送 RemoteStartTransaction.req 请求充电点启动交易。充电点收到后,应回复
RemoteStartTransaction.conf ,并说明是否接受请求并尝试启动交易。
RemoteStartTransaction.req 消息的效果取决于
充电点中的 AuthorizeRemoteTxRequests 配置密钥。
如果 AuthorizeRemoteTxRequests 的值为 true ,则充值点的行为应如同响应 充值点的本地操作,即使用
RemoteStartTransaction.req 消息中给出的 idTag 开始交易。这意味着充电点将首先尝试使用 本地授权列
授权缓存 和/或 Authorize.req 请求对 idTag 进行 授权 。只有在获得授权后,交易才会启动。
如果 AuthorizeRemoteTxRequests 的值为 false ,充值点应立即尝试为 RemoteStartTransaction.req
消息中给出的 idTag 开始交易。请注意,在 RemoteStopTransaction.req(transactionId)RemoteStopTransaction.conf(status)
、当交易开始时,充电点将向中央系统发送一个 StartTransaction(开始交易)请求,中央系统在处理该 StartTransaction 请求时将检查 idTag 的授权状态。
以下典型用例是进行远程启动交易的原因:
使 CPO 操作员能够帮助遇到问题的电动车驾驶员启动交易。
启用移动应用程序,通过中央系统控制收费交易。
启用短信功能,通过中央系统控制收费交易。
RemoteStartTransaction.req 应包含一个标识符(
idTag),如果充电点能够启动交易,则应使用该标识符向中央系
统发送 StartTransaction.req 。交易的启动方式与 StartTransaction 中描述的方式相同。如果要在特定连接器上启
动事务, RemoteStartTransaction.req 可以包含连接器 ID。如果没有提供连接器 ID,则由充值点控制连接器的选
择。充值点可以拒绝没有连接器 ID 的 RemoteStartTransaction.req。
中央系统可以在 RemoteStartTransaction 请求中包含一个 ChargingProfile ChargingProfile 的目的应设置为
TxProfile 。如果被接受,充电点应在交易中使用该 ChargingProfile。
如果不支持智能充电的充电桩收到带有充电配置文件的 RemoteStartTransaction.req,则应忽
略此参数。

5.2 RemoteStartTransaction.req

它包含中央系统发送给充电点的 RemoteStartTransaction.req PDU 的字段定义。
中文
连接器ID指:枪号
英文

5.3 RemoteStartTransaction.conf

其中包含从充电点发送到中央系统的 RemoteStartTransaction.conf PDU 的字段定义。
中文
英文

5.4 JSON格式

[RECV <-] [2,"4f08e280-b5b2-4197-82ef-f10a1f351fcb","RemoteStartTransaction",{"connectorId":1,"idTag":"C35CEA09"}]
[SEND ->] [3,"4f08e280-b5b2-4197-82ef-f10a1f351fcb",{"status":"Accepted"}]

5.5 代码

业务逻辑太多,请查看远程启停充电更新文档;

6、远程停止-RemoteStopTransaction

6.1 说明

中央系统可通过向充电点发送带有事务标识符的 RemoteStopTransaction.req 请求 充电点停止事务。充电点应回复 RemoteStopTransaction.conf ,并给出一个状态,说明它是否接受了请求,以及是否正在进行并将停止一个带有给定事务标识(transactionId)的事务。
这种停止事务的远程请求等同于停止事务的本地操作。因此,应停止交易,充值点应发送 StopTransaction.req, 并酌情解锁连接器。
以下两个主要用例是进行远程停止交易的原因:
使 CPO 操作员能够帮助遇到问题的电动车驾驶员停止交易。
启用移动应用程序,通过中央系统控制收费交易。

6.2 RemoteStopTransaction.req

事务id-枪号

它包含中央系统发送给充电点的 RemoteStopTransaction.req PDU 的字段定义。
英文

6.3 RemoteStopTransaction.conf

其中包含从充电点发送到中央系统的 RemoteStopTransaction.conf PDU 的字段定义。
英文

6.4 JSON格式

[RECV <-] [2,"28f7d946-c019-4071-8800-8e07426836f2","RemoteStopTransaction",{"transactionId":12023}]
[SEND ->] [3,"28f7d946-c019-4071-8800-8e07426836f2",{"status":"Accepted"}]

6.5 代码

业务逻辑太多,请查看远程启停充电更新文档;

通用方法

1、转换时间为UTC格式

public static String localToUTC(Date localDate) {
  long localTimeInMillis=localDate.getTime();
  /** long时间转换成Calendar */
  Calendar calendar= Calendar.getInstance();
  calendar.setTimeInMillis(localTimeInMillis);
  /** 取得时间偏移量 */
  int zoneOffset = calendar.get(java.util.Calendar.ZONE_OFFSET);
  /** 取得夏令时差 */
  int dstOffset = calendar.get(java.util.Calendar.DST_OFFSET);
  /** 从本地时间里扣除这些差量,即可以取得UTC时间*/
  calendar.add(java.util.Calendar.MILLISECOND, -(zoneOffset + dstOffset));
  /** 取得的时间就是UTC标准时间 */
  Date utcDate=new Date(calendar.getTimeInMillis());
  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
  String timeStr=df.format(utcDate);
  return timeStr;
}


http://www.ppmy.cn/news/1162149.html

相关文章

Systrace学习笔记

Systrace学习笔记 1.Systrace快捷键2.线程状态3.CPU info4.图形化4.1 Frames帧4.2 用户活动4.3 CPU活动4.4 系统事件 5. SystemServer5.1 SystemServer简介5.2 窗口动画5.3 AMS(ActivityManagerService)5.4 WMS(WindowMagerService)5.5 ServiceThread5.6 HandlerThread 6. Surf…

木与空间的舞蹈:奥地利住宅的独特设计

国外著名设计师&#xff0c;为一位业主设计了一座住宅&#xff0c;附带有附属建筑和有盖的入口&#xff0c;形成了像庭院一样的建筑群。 这座住宅采用了当地的传统建筑风格&#xff0c;有长方形的平面和陡峭的顶棚&#xff0c;与周围的房屋相符。然而&#xff0c;内部设计别具一…

《视觉 SLAM 十四讲》V2 第 12 讲 建图

文章目录 12.2 单目稠密 重建12.2.2 极线搜索 && 块匹配12.2.3 高斯分布的深度滤波器 12.3 单目稠密重建 【Code】待改进12.3.4 图像间的变换 12.4 RGB-D 稠密建图12.4.1 点云地图 【Code】查询OpenCV版本 opencv_version 12.4.2 从点云 重建 网格 【Code】查看PCL 版本…

Confluence 自定义博文列表

1. 概述 Confluence 自有博文列表无法实现列表自定义功能&#xff0c;实现该需求可采用页面中引用博文宏标签控制的方式 2. 实现方式 功能入口&#xff1a; Confluence →指定空间→创建页面 功能说明&#xff1a; &#xff08;1&#xff09;页面引用博文宏 &#xff08;…

纯css+js自制下拉框

前提 因为html的select标签&#xff0c;下拉框自定义程度非常的低&#xff0c;为了贴合而项目ui显示&#xff0c;所以打算自制下拉框 代码 html <div class"pos-rel"><div id"select" class"select get-select"><span class&…

Matlab-ODE45:求解状态变量(微分方程组)

ode45函数 ode45实际上是数值分析中数值求解微分方程组的一种方法&#xff0c;4阶五级Runge-Kutta算法。 调用方法 ​ 其实这种方程的每一个状态变量都是t 的函数&#xff0c;我们可以从现代控制理论的状态空间来想。因此返回[ t , x ]&#xff0c;其中t是一个列向量&#xf…

idea热加载,JRebel 插件是目前最好用的热加载插件,它支持 IDEA Ultimate 旗舰版、Community 社区版

1.如何安装 ① 点击 https://plugins.jetbrains.com/plugin/4441-jrebel-and-xrebel/versions 地址&#xff0c;下载 2022.4.1 版本。如下图所示&#xff1a; ② 打开 [Preference -> Plugins] 菜单&#xff0c;点击「Install Plugin from Disk…」按钮&#xff0c;选择刚下…

Python 框架学习 Django篇 (三) 链接数据库

只要你是做后端开发的&#xff0c;那么就离不开各种数据库&#xff0c;Django框架对各种数据库都非常友好&#xff0c;比如常见的PostgreSQL、MySQL、SQLite、Oracle&#xff0c;django都对他们提供了统一调用api&#xff0c;我们这里主要使用mysql数据库作为演示 一、ORM机制 …