mirror of
https://gitee.com/san-bing/JChargePointProtocol
synced 2026-05-03 17:39:55 +08:00
!21 绿能109,103,102,101,203,201指令提交
* 合并后代码修改 * 合并后代码修改 * Merge remote-tracking branch 'refs/remotes/upstream/master' into maste… * PR后代码修改 * 109)充电桩状态信息包上报 * 109)充电桩状态信息包上报
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
package sanbing.jcpp.app.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -21,6 +22,7 @@ import sanbing.jcpp.infrastructure.proto.model.PricingModel;
|
||||
import sanbing.jcpp.infrastructure.proto.model.PricingModel.FlagPrice;
|
||||
import sanbing.jcpp.infrastructure.proto.model.PricingModel.Period;
|
||||
import sanbing.jcpp.infrastructure.queue.Callback;
|
||||
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.*;
|
||||
import sanbing.jcpp.protocol.domain.DownlinkCmdEnum;
|
||||
|
||||
@@ -254,6 +256,7 @@ public class DefaultPileProtocolService implements PileProtocolService {
|
||||
@Override
|
||||
public void onTransactionRecordRequest(UplinkQueueMessage uplinkQueueMessage, Callback callback) {
|
||||
log.info("接收到充电桩交易记录上报 {}", uplinkQueueMessage);
|
||||
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
|
||||
|
||||
TransactionRecordRequest transactionRecordRequest = uplinkQueueMessage.getTransactionRecordRequest();
|
||||
|
||||
@@ -262,10 +265,12 @@ public class DefaultPileProtocolService implements PileProtocolService {
|
||||
|
||||
// 构造下行计费
|
||||
DownlinkRequestMessage.Builder downlinkMessageBuilder = createDownlinkMessageBuilder(uplinkQueueMessage, pileCode);
|
||||
|
||||
downlinkMessageBuilder.setDownlinkCmd(DownlinkCmdEnum.TRANSACTION_RECORD_ACK.name());
|
||||
downlinkMessageBuilder.setTransactionRecordResponse(TransactionRecordResponse.newBuilder()
|
||||
.setTradeNo(tradeNo)
|
||||
.setSuccess(true)
|
||||
.setAdditionalInfo(additionalInfo.toString())
|
||||
.build());
|
||||
|
||||
downlinkCallService.sendDownlinkMessage(downlinkMessageBuilder, pileCode);
|
||||
|
||||
@@ -344,6 +344,7 @@ message BmsChargingErrorProto {
|
||||
message TransactionRecordResponse {
|
||||
string tradeNo = 6;
|
||||
bool success = 7;
|
||||
optional string additionalInfo = 20;
|
||||
}
|
||||
|
||||
message BmsParamConfigReportProto {
|
||||
|
||||
@@ -16,5 +16,21 @@
|
||||
|
||||
#### 109 充电桩状态信息包上报
|
||||
`AAF5D00010C46D00000000003230323331323132303030303130000000000000000000000000000000000000010101000000000000000000000020250808105527FF00000000000000000000000000000000000000000000000000000000000000F567720000000000F5677200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003232460000000000000000000000000000000000000044`
|
||||
#### 103 服务器应答充电桩状态信息包
|
||||
`AA F5 0E 00 10 04 67 00 00 00 00 00 01 68 `
|
||||
|
||||
---
|
||||
|
||||
#### 203 充电桩上报充电订单
|
||||
`AA F5 95 01 10 08 CB 00 00 00 00 00 32 30 32 33 31 32 31 32 30 30 30 30 31 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 25 08 12 20 07 08 FF 20 25 08 12 20 22 06 FF 82 03 00 00 1E 3A 02 01 00 00 F3 3A 00 00 94 63 4F 01 00 00 00 00 87 9E 4F 01 00 00 00 00 42 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C 4E 42 53 43 31 33 4B 58 50 5A 30 34 36 35 34 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F3 3A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 31 30 36 30 33 30 33 37 35 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F3 02 00 00 3B`
|
||||
#### 201 服务器应答订单信息
|
||||
`AA F5 32 00 10 02 C9 00 00 00 00 00 02 31 30 36 30 33 30 33 37 35 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6`
|
||||
|
||||
---
|
||||
|
||||
#### 102 充电桩上传心跳包信息
|
||||
`AA F5 3F 00 10 02 66 00 00 00 00 00 32 30 32 33 31 32 31 32 30 30 30 30 31 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14`
|
||||
#### 101 服务器应答心跳包信息
|
||||
`AA F5 0F 00 10 03 65 00 00 00 00 00 00 00 65`
|
||||
|
||||
---
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 告警码-故障码定义
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum LvnengAlarmCodeEnum {
|
||||
|
||||
CODE_304(304, "通道匹配异常"),
|
||||
CODE_305(305, "主输出接触器故障"),
|
||||
CODE_307(307, "交流接触器故障"),
|
||||
CODE_308(308, "熔断器故障"),
|
||||
CODE_309(309, "防雷故障"),
|
||||
CODE_310(310, "电子锁故障"),
|
||||
CODE_312(312, "充电模块风扇故障"),
|
||||
CODE_313(313, "直流输出过压"),
|
||||
CODE_314(314, "直流输出欠压"),
|
||||
CODE_315(315, "直流输出过流"),
|
||||
CODE_316(316, "车辆端口电压负压"),
|
||||
CODE_317(317, "交流输入过压"),
|
||||
CODE_318(318, "交流输入欠压"),
|
||||
CODE_319(319, "交流输入频率过频"),
|
||||
CODE_320(320, "交流输入频率欠频"),
|
||||
CODE_321(321, "交流输入电压不平衡"),
|
||||
CODE_322(322, "交流输入 A 相缺相"),
|
||||
CODE_323(323, "交流输入 B 相缺相"),
|
||||
CODE_324(324, "交流输入 C 相缺相"),
|
||||
CODE_325(325, "交流输入过载"),
|
||||
CODE_326(326, "交流输入异常"),
|
||||
CODE_327(327, "充电模块输出过压"),
|
||||
CODE_328(328, "充电模块过流"),
|
||||
CODE_329(329, "充电模块过温"),
|
||||
CODE_330(330, "环境温度过温"),
|
||||
CODE_331(331, "环境温度过低"),
|
||||
CODE_332(332, "系统无可用模块"),
|
||||
CODE_333(333, "充电模块命令执行失败"),
|
||||
CODE_334(334, "充电控制器通信故障"),
|
||||
CODE_335(335, "采集板通讯故障"),
|
||||
CODE_336(336, "电表离线"),
|
||||
CODE_337(337, "与集控器通信中断"),
|
||||
CODE_338(338, "读卡器通信故障"),
|
||||
CODE_339(339, "绝缘故障"),
|
||||
CODE_340(340, "系统模块混插"),
|
||||
CODE_341(341, "系统急停故障"),
|
||||
CODE_342(342, "主从通信异常"),
|
||||
CODE_343(343, "电表校验错误"),
|
||||
CODE_344(344, "系统门磁故障"),
|
||||
CODE_345(345, "系统风机故障"),
|
||||
CODE_346(346, "并联接触器故障"),
|
||||
CODE_347(347, "并联接触器驱动失效"),
|
||||
CODE_348(348, "绝缘监测告警"),
|
||||
CODE_351(351, "TMU ID 重复"),
|
||||
CODE_352(352, "BMS 数据异常"),
|
||||
CODE_353(353, "电池单体过压"),
|
||||
CODE_354(354, "电池整包过压保护"),
|
||||
CODE_355(355, "电池过流保护"),
|
||||
CODE_356(356, "电池过充保护"),
|
||||
CODE_357(357, "电池电压异常"),
|
||||
CODE_358(358, "电池低温保护"),
|
||||
CODE_359(359, "BMS 热失控"),
|
||||
CODE_360(360, "BMS 辅源异常"),
|
||||
CODE_361(361, "CMU 辅源异常"),
|
||||
CODE_362(362, "车辆继电器开路保护"),
|
||||
CODE_364(364, "TMU 过温"),
|
||||
CODE_368(368, "电池电压过高"),
|
||||
CODE_369(369, "电池 SOC 过高"),
|
||||
CODE_370(370, "电池 SOC 过低"),
|
||||
CODE_371(371, "电池充电过流"),
|
||||
CODE_372(372, "电池温度过高"),
|
||||
CODE_373(373, "电池绝缘故障"),
|
||||
CODE_374(374, "电池输出连接器异常"),
|
||||
CODE_385(385, "CC1 电压异常"),
|
||||
CODE_386(386, "TMU 所有通道不匹配"),
|
||||
CODE_387(387, "电表参数不匹配"),
|
||||
CODE_388(388, "枪头短路"),
|
||||
CODE_389(389, "TMU 条码异常"),
|
||||
CODE_390(390, "TMU 风扇故障"),
|
||||
CODE_391(391, "充电系统不匹配"),
|
||||
CODE_392(392, "模块开启失败"),
|
||||
CODE_394(394, "交流接触器反馈故障"),
|
||||
CODE_432(432, "湿度告警故障"),
|
||||
CODE_433(433, "枪头过温告警"),
|
||||
CODE_434(434, "系统过温故障"),
|
||||
CODE_435(435, "机柜浸水故障"),
|
||||
CODE_436(436, "机柜倾倒故障"),
|
||||
CODE_437(437, "机柜烟雾故障"),
|
||||
CODE_442(442, "CMU ID 重复"),
|
||||
CODE_443(443, "机柜防尘网告警"),
|
||||
CODE_506(506, "未定义的错误"),
|
||||
CODE_513(513, "IO 板离线"),
|
||||
CODE_514(514, "IO 板故障"),
|
||||
CODE_515(515, "TMU 互锁异常"),
|
||||
CODE_516(516, "输出接触器前级电压异常"),
|
||||
CODE_517(517, "模块地址超范围或地址重复"),
|
||||
CODE_518(518, "模块槽位不匹配"),
|
||||
CODE_519(519, "TMU 急停故障"),
|
||||
CODE_520(520, "CMU 门磁故障"),
|
||||
CODE_521(521, "TMU 门磁故障"),
|
||||
CODE_522(522, "IO 板互锁故障"),
|
||||
CODE_523(523, "CMU 互锁异常"),
|
||||
CODE_524(524, "CMU 无可用模块故障"),
|
||||
CODE_525(525, "交流输入接触器拒动/误动故障"),
|
||||
CODE_526(526, "交流输入接触器粘连故障"),
|
||||
CODE_528(528, "泄放回路故障"),
|
||||
CODE_529(529, "TMU 无模块可用故障"),
|
||||
CODE_531(531, "TCU 离线故障"),
|
||||
CODE_532(532, "电表分流器反接故障"),
|
||||
CODE_533(533, "绝缘检测仪通信故障"),
|
||||
CODE_534(534, "终端 TCU 平台类型未配置"),
|
||||
CODE_535(535, "车辆接触器粘连"),
|
||||
CODE_536(536, "TMU 程序与终端类型不匹配"),
|
||||
CODE_537(537, "SW2 与 SW3 拨码设置错误"),
|
||||
CODE_538(538, "TMU 拨码地址超范围");
|
||||
|
||||
/**
|
||||
* 故障代码
|
||||
*/
|
||||
private final int code;
|
||||
|
||||
/**
|
||||
* 故障描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
|
||||
private static final String UNKNOWN_DESC = "未知故障码";
|
||||
private static final Map<Integer, LvnengAlarmCodeEnum> CODE_TO_ENUM_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (LvnengAlarmCodeEnum enumValue : LvnengAlarmCodeEnum.values()) {
|
||||
CODE_TO_ENUM_MAP.put(enumValue.getCode(), enumValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getByCode(Long code) {
|
||||
LvnengAlarmCodeEnum lvnengAlarmCodeEnum = CODE_TO_ENUM_MAP.get(code.intValue());
|
||||
if (lvnengAlarmCodeEnum == null) {
|
||||
return UNKNOWN_DESC;
|
||||
}
|
||||
return lvnengAlarmCodeEnum.getDescription();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,8 +18,13 @@ public enum LvnengDownlinkCmdEnum {
|
||||
|
||||
LOGIN_ACK((short) 105),
|
||||
|
||||
SYNC_TIME((short) 3)
|
||||
;
|
||||
SYNC_TIME((short) 3),
|
||||
|
||||
HEARTBEAT_ACK((short) 101),
|
||||
|
||||
REAL_TIME_DATA_ACK((short) 103),
|
||||
|
||||
TRANSACTION_RECORD_ACK((short) 201);
|
||||
|
||||
private final short cmd;
|
||||
|
||||
|
||||
@@ -0,0 +1,511 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 充电桩结束原因编码定义
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum LvnengPileFinishReasonEnum {
|
||||
// 中止代码1 → 上报值:1 + 256 = 257
|
||||
CODE_257(257, "BMS 中止"),
|
||||
|
||||
// 中止代码2 → 上报值:2 + 256 = 258
|
||||
CODE_258(258, "平台中止"),
|
||||
|
||||
// 中止代码3 → 上报值:3 + 256 = 259
|
||||
CODE_259(259, "人工设定条件中止"),
|
||||
|
||||
// 中止代码4 → 上报值:4 + 256 = 260
|
||||
CODE_260(260, "人工中止"),
|
||||
|
||||
// 中止代码5 → 上报值:5 + 256 = 261
|
||||
CODE_261(261, "充电机故障中止"),
|
||||
|
||||
// 中止代码6 → 上报值:6 + 256 = 262
|
||||
CODE_262(262, "连接器故障中止"),
|
||||
|
||||
// 中止代码7 → 上报值:7 + 256 = 263
|
||||
CODE_263(263, "连接器拔出中止"),
|
||||
|
||||
// 中止代码9 → 上报值:9 + 256 = 265
|
||||
CODE_265(265, "主接触器异常中止"),
|
||||
|
||||
// 中止代码10 → 上报值:10 + 256 = 266
|
||||
CODE_266(266, "并联接触器异常中止"),
|
||||
|
||||
// 中止代码11 → 上报值:11 + 256 = 267
|
||||
CODE_267(267, "电子锁异常中止"),
|
||||
|
||||
// 中止代码12 → 上报值:12 + 256 = 268
|
||||
CODE_268(268, "充电电压异常中止"),
|
||||
|
||||
// 中止代码13 → 上报值:13 + 256 = 269
|
||||
CODE_269(269, "充电电流小中止"),
|
||||
|
||||
// 中止代码14 → 上报值:14 + 256 = 270
|
||||
CODE_270(270, "充电电流过流中止"),
|
||||
|
||||
// 中止代码15 → 上报值:15 + 256 = 271
|
||||
CODE_271(271, "充电电压不匹配中止"),
|
||||
|
||||
// 中止代码16 → 上报值:16 + 256 = 272
|
||||
CODE_272(272, "BMS 数据不刷新中止"),
|
||||
|
||||
// 中止代码17 → 上报值:17 + 256 = 273
|
||||
CODE_273(273, "电能表通信故障中止"),
|
||||
|
||||
// 中止代码19 → 上报值:19 + 256 = 275
|
||||
CODE_275(275, "SOC 满中止"),
|
||||
|
||||
// 中止代码22 → 上报值:22 + 256 = 278
|
||||
CODE_278(278, "主动防护电池过温中止"),
|
||||
|
||||
// 中止代码23 → 上报值:23 + 256 = 279
|
||||
CODE_279(279, "主动防护电池低温中止"),
|
||||
|
||||
// 中止代码24 → 上报值:24 + 256 = 280
|
||||
CODE_280(280, "主动防护电池热失控中止"),
|
||||
|
||||
// 中止代码25 → 上报值:25 + 256 = 281
|
||||
CODE_281(281, "主动防护电池过充中止"),
|
||||
|
||||
// 中止代码26 → 上报值:26 + 256 = 282
|
||||
CODE_282(282, "BMS 辅助电源异常中止"),
|
||||
|
||||
// 中止代码27 → 上报值:27 + 256 = 283
|
||||
CODE_283(283, "BMS 接触器开路故障中止"),
|
||||
|
||||
// 中止代码28 → 上报值:28 + 256 = 284
|
||||
CODE_284(284, "主动防护 BMS 数据超范围中止"),
|
||||
|
||||
// 中止代码29 → 上报值:29 + 256 = 285
|
||||
CODE_285(285, "TMU 过温中止"),
|
||||
|
||||
// 中止代码30 → 上报值:30 + 256 = 286
|
||||
CODE_286(286, "主动防护电池端口电压异常中止"),
|
||||
|
||||
// 中止代码33 → 上报值:33 + 256 = 289
|
||||
CODE_289(289, "拔枪中止"),
|
||||
|
||||
// 中止代码34 → 上报值:34 + 256 = 290
|
||||
CODE_290(290, "设备过温中止"),
|
||||
|
||||
// 中止代码35 → 上报值:35 + 256 = 291
|
||||
CODE_291(291, "过流中止"),
|
||||
|
||||
// 中止代码36 → 上报值:36 + 256 = 292
|
||||
CODE_292(292, "过压中止"),
|
||||
|
||||
// 中止代码37 → 上报值:37 + 256 = 293
|
||||
CODE_293(293, "欠压中止"),
|
||||
|
||||
// 中止代码40 → 上报值:40 + 256 = 296
|
||||
CODE_296(296, "充电枪座过温中止"),
|
||||
|
||||
// 中止代码43 → 上报值:43 + 256 = 299
|
||||
CODE_299(299, "枪头过温中止"),
|
||||
|
||||
// 中止代码44 → 上报值:44 + 256 = 300
|
||||
CODE_300(300, "模块开启失败中止"),
|
||||
|
||||
// 中止代码46 → 上报值:46 + 256 = 302
|
||||
CODE_302(302, "浸水故障中止"),
|
||||
|
||||
// 中止代码49 → 上报值:49 + 256 = 305
|
||||
CODE_305(305, "结束中不响应启动充电命令中止"),
|
||||
|
||||
// 中止代码51 → 上报值:51 + 256 = 307
|
||||
CODE_307(307, "主动防护电池单体过压中止"),
|
||||
|
||||
// 中止代码52 → 上报值:52 + 256 = 308
|
||||
CODE_308(308, "主动防护电池整包过压中止"),
|
||||
|
||||
// 中止代码53 → 上报值:53 + 256 = 309
|
||||
CODE_309(309, "电表校验错误中止"),
|
||||
|
||||
// 中止代码54 → 上报值:54 + 256 = 310
|
||||
CODE_310(310, "BMS 通讯超时中止"),
|
||||
|
||||
// 中止代码55 → 上报值:55 + 256 = 311
|
||||
CODE_311(311, "充电电压不匹配中止"),
|
||||
|
||||
// 中止代码56 → 上报值:56 + 256 = 312
|
||||
CODE_312(312, "系统风扇故障中止"),
|
||||
|
||||
// 中止代码57 → 上报值:57 + 256 = 313
|
||||
CODE_313(313, "CMU 急停中止"),
|
||||
|
||||
// 中止代码58 → 上报值:58 + 256 = 314
|
||||
CODE_314(314, "充电机绝缘异常中止"),
|
||||
|
||||
// 中止代码59 → 上报值:59 + 256 = 315
|
||||
CODE_315(315, "充电机无可用模块中止"),
|
||||
|
||||
// 中止代码62 → 上报值:62 + 256 = 318
|
||||
CODE_318(318, "熔断器故障中止"),
|
||||
|
||||
// 中止代码63 → 上报值:63 + 256 = 319
|
||||
CODE_319(319, "模块匹配异常中止"),
|
||||
|
||||
// 中止代码64 → 上报值:64 + 256 = 320
|
||||
CODE_320(320, "配置或升级中不响应启动充电中止"),
|
||||
|
||||
// 中止代码65 → 上报值:65 + 256 = 321
|
||||
CODE_321(321, "主动防护未解除中止"),
|
||||
|
||||
// 中止代码66 → 上报值:66 + 256 = 322
|
||||
CODE_322(322, "车辆电池达到目标 SOC 中止"),
|
||||
|
||||
// 中止代码67 → 上报值:67 + 256 = 323
|
||||
CODE_323(323, "车辆达到总电压目标值中止"),
|
||||
|
||||
// 中止代码68 → 上报值:68 + 256 = 324
|
||||
CODE_324(324, "车辆达到单体电压目标值中止"),
|
||||
|
||||
// 中止代码69 → 上报值:69 + 256 = 325
|
||||
CODE_325(325, "车辆 bms 绝缘故障中止"),
|
||||
|
||||
// 中止代码70 → 上报值:70 + 256 = 326
|
||||
CODE_326(326, "车辆输出连接器过温故障中止"),
|
||||
|
||||
// 中止代码71 → 上报值:71 + 256 = 327
|
||||
CODE_327(327, "车辆 BMS 元件、输出连接器过温中止"),
|
||||
|
||||
// 中止代码72 → 上报值:72 + 256 = 328
|
||||
CODE_328(328, "车辆充电连接器故障中止"),
|
||||
|
||||
// 中止代码73 → 上报值:73 + 256 = 329
|
||||
CODE_329(329, "车辆电池组温度过高故障中止"),
|
||||
|
||||
// 中止代码74 → 上报值:74 + 256 = 330
|
||||
CODE_330(330, "车辆高压继电器故障中止"),
|
||||
|
||||
// 中止代码75 → 上报值:75 + 256 = 331
|
||||
CODE_331(331, "车辆监测点 CC2 电压检测故障中止"),
|
||||
|
||||
// 中止代码76 → 上报值:76 + 256 = 332
|
||||
CODE_332(332, "车辆其他故障"),
|
||||
|
||||
// 中止代码77 → 上报值:77 + 256 = 333
|
||||
CODE_333(333, "车辆电流过大中止"),
|
||||
|
||||
// 中止代码78 → 上报值:78 + 256 = 334
|
||||
CODE_334(334, "车辆电压异常中止"),
|
||||
|
||||
// 中止代码79 → 上报值:79 + 256 = 335
|
||||
CODE_335(335, "BMS 中止"),
|
||||
|
||||
// 中止代码91 → 上报值:91 + 256 = 347
|
||||
CODE_347(347, "终端离线中止"),
|
||||
|
||||
// 中止代码92 → 上报值:92 + 256 = 348
|
||||
CODE_348(348, "平台离线中止"),
|
||||
|
||||
// 中止代码93 → 上报值:93 + 256 = 349
|
||||
CODE_349(349, "充电命令超时中止"),
|
||||
|
||||
// 中止代码94 → 上报值:94 + 256 = 350
|
||||
CODE_350(350, "启动超时中止"),
|
||||
|
||||
// 中止代码95 → 上报值:95 + 256 = 351
|
||||
CODE_351(351, "放电启动超时中止"),
|
||||
|
||||
// 中止代码96 → 上报值:96 + 256 = 352
|
||||
CODE_352(352, "非法启动中止"),
|
||||
|
||||
// 中止代码97 → 上报值:97 + 256 = 353
|
||||
CODE_353(353, "显示屏操作中止"),
|
||||
|
||||
// 中止代码98 → 上报值:98 + 256 = 354
|
||||
CODE_354(354, "内部 VIN 申请中止"),
|
||||
|
||||
// 中止代码99 → 上报值:99 + 256 = 355
|
||||
CODE_355(355, "显示屏刷卡中止"),
|
||||
|
||||
// 中止代码100 → 上报值:100 + 256 = 356
|
||||
CODE_356(356, "异常电度中止"),
|
||||
|
||||
// 中止代码101 → 上报值:101 + 256 = 357
|
||||
CODE_357(357, "余额不足中止"),
|
||||
|
||||
// 中止代码102 → 上报值:102 + 256 = 358
|
||||
CODE_358(358, "定电量充中止"),
|
||||
|
||||
// 中止代码103 → 上报值:103 + 256 = 359
|
||||
CODE_359(359, "定时间充中止"),
|
||||
|
||||
// 中止代码104 → 上报值:104 + 256 = 360
|
||||
CODE_360(360, "错峰充电中止"),
|
||||
|
||||
// 中止代码105 → 上报值:105 + 256 = 361
|
||||
CODE_361(361, "定金额充中止"),
|
||||
|
||||
// 中止代码134 → 上报值:134 + 256 = 390
|
||||
CODE_390(390, "短路故障中止"),
|
||||
|
||||
// 中止代码136 → 上报值:136 + 256 = 392
|
||||
CODE_392(392, "车辆端口电压负压"),
|
||||
|
||||
// 中止代码149 → 上报值:149 + 256 = 405
|
||||
CODE_405(405, "机柜倾倒中止"),
|
||||
|
||||
// 中止代码150 → 上报值:150 + 256 = 406
|
||||
CODE_406(406, "机柜烟雾故障中止"),
|
||||
|
||||
// 中止代码151 → 上报值:151 + 256 = 407
|
||||
CODE_407(407, "机柜温湿度报警故障中止"),
|
||||
|
||||
// 中止代码257 → 上报值:257 + 256 = 513
|
||||
CODE_513(513, "IO 板离线中止"),
|
||||
|
||||
// 中止代码258 → 上报值:258 + 256 = 514
|
||||
CODE_514(514, "TMU 与 CMU 离线中止"),
|
||||
|
||||
// 中止代码265 → 上报值:265 + 256 = 521
|
||||
CODE_521(521, "CMU 门磁触发中止"),
|
||||
|
||||
// 中止代码266 → 上报值:266 + 256 = 522
|
||||
CODE_522(522, "TMU 急停中止"),
|
||||
|
||||
// 中止代码267 → 上报值:267 + 256 = 523
|
||||
CODE_523(523, "TMU 互锁异常中止"),
|
||||
|
||||
// 中止代码268 → 上报值:268 + 256 = 524
|
||||
CODE_524(524, "输出接触器前级电压异常中止"),
|
||||
|
||||
// 中止代码269 → 上报值:269 + 256 = 525
|
||||
CODE_525(525, "TMU 门磁触发中止"),
|
||||
|
||||
// 终止代码270 → 上报值:270 + 256 = 526
|
||||
CODE_526(526, "IO 板互锁异常中止"),
|
||||
|
||||
// 终止代码271 → 上报值:271 + 256 = 527
|
||||
CODE_527(527, "CMU 互锁异常中止"),
|
||||
|
||||
// 终止代码272 → 上报值:272 + 256 = 528
|
||||
CODE_528(528, "CMU 无可用模块中止"),
|
||||
|
||||
// 终止代码273 → 上报值:273 + 256 = 529
|
||||
CODE_529(529, "TMU 无可用模块中止"),
|
||||
|
||||
// 终止代码274 → 上报值:274 + 256 = 530
|
||||
CODE_530(530, "交流输入接触器拒动/误动中止"),
|
||||
|
||||
// 终止代码275 → 上报值:275 + 256 = 531
|
||||
CODE_531(531, "交流输入接触器粘连中止"),
|
||||
|
||||
// 终止代码276 → 上报值:276 + 256 = 532
|
||||
CODE_532(532, "交流输入异常中止"),
|
||||
|
||||
// 终止代码277 → 上报值:277 + 256 = 533
|
||||
CODE_533(533, "泄放回路故障中止"),
|
||||
|
||||
// 终止代码278 → 上报值:278 + 256 = 534
|
||||
CODE_534(534, "BMS 上报电压异常中止"),
|
||||
|
||||
// 终止代码279 → 上报值:279 + 256 = 535
|
||||
CODE_535(535, "电池电压低中止"),
|
||||
|
||||
// 终止代码280 → 上报值:280 + 256 = 536
|
||||
CODE_536(536, "直流输出接触器后级电压异常中止"),
|
||||
|
||||
// 终止代码282 → 上报值:282 + 256 = 538
|
||||
CODE_538(538, "BRM 数据异常中止"),
|
||||
|
||||
// 终止代码283 → 上报值:283 + 256 = 539
|
||||
CODE_539(539, "BCP 数据异常中止"),
|
||||
|
||||
// 终止代码284 → 上报值:284 + 256 = 540
|
||||
CODE_540(540, "BRO 超时中止"),
|
||||
|
||||
// 终止代码285 → 上报值:285 + 256 = 541
|
||||
CODE_541(541, "BCL 超时中止"),
|
||||
|
||||
// 终止代码286 → 上报值:286 + 256 = 542
|
||||
CODE_542(542, "BCS 超时中止"),
|
||||
|
||||
// 终止代码287 → 上报值:287 + 256 = 543
|
||||
CODE_543(543, "BMS 通信协议版本不匹配中止"),
|
||||
|
||||
// 终止代码288 → 上报值:288 + 256 = 544
|
||||
CODE_544(544, "预充阶段调压失败中止"),
|
||||
|
||||
// 终止代码289 → 上报值:289 + 256 = 545
|
||||
CODE_545(545, "防雷器故障中止"),
|
||||
|
||||
// 终止代码290 → 上报值:290 + 256 = 546
|
||||
CODE_546(546, "交流输入断路器故障中止"),
|
||||
|
||||
// 终止代码291 → 上报值:291 + 256 = 547
|
||||
CODE_547(547, "充电中辅源故障"),
|
||||
|
||||
// 终止代码292 → 上报值:292 + 256 = 548
|
||||
CODE_548(548, "直流母线输出电压过压故障中止"),
|
||||
|
||||
// 终止代码293 → 上报值:293 + 256 = 549
|
||||
CODE_549(549, "直流母线输出电压欠压故障中止"),
|
||||
|
||||
// 终止代码294 → 上报值:294 + 256 = 550
|
||||
CODE_550(550, "直流母线输出电流过流故障中止"),
|
||||
|
||||
// 终止代码295 → 上报值:295 + 256 = 551
|
||||
CODE_551(551, "电池最高允许电压小于充电机最小电压"),
|
||||
|
||||
// 终止代码296 → 上报值:296 + 256 = 552
|
||||
CODE_552(552, "绝缘监测前直流输出接触器外侧电压≥10 V"),
|
||||
|
||||
// 终止代码297 → 上报值:297 + 256 = 553
|
||||
CODE_553(553, "电池端电压大于电池最高允许充电电压"),
|
||||
|
||||
// 终止代码298 → 上报值:298 + 256 = 554
|
||||
CODE_554(554, "BRM 超时中止"),
|
||||
|
||||
// 终止代码299 → 上报值:299 + 256 = 555
|
||||
CODE_555(555, "BCP 超时中止"),
|
||||
|
||||
// 终止代码300 → 上报值:300 + 256 = 556
|
||||
CODE_556(556, "BRO 超时中止(0xAA)"),
|
||||
|
||||
// 终止代码301 → 上报值:301 + 256 = 557
|
||||
CODE_557(557, "灯板通信故障"),
|
||||
|
||||
// 终止代码302 → 上报值:302 + 256 = 558
|
||||
CODE_558(558, "BSM 超时"),
|
||||
|
||||
// 终止代码303 → 上报值:303 + 256 = 559
|
||||
CODE_559(559, "BSM 报文中单体动力蓄电池电压过压"),
|
||||
|
||||
// 终止代码304 → 上报值:304 + 256 = 560
|
||||
CODE_560(560, "BSM 报文中单体动力蓄电池电压过低"),
|
||||
|
||||
// 终止代码305 → 上报值:305 + 256 = 561
|
||||
CODE_561(561, "BSM 报文中 SOC 过高"),
|
||||
|
||||
// 终止代码306 → 上报值:306 + 256 = 562
|
||||
CODE_562(562, "BSM 报文中 SOC 过低"),
|
||||
|
||||
// 终止代码307 → 上报值:307 + 256 = 563
|
||||
CODE_563(563, "BSM 报文中充电过电流"),
|
||||
|
||||
// 终止代码308 → 上报值:308 + 256 = 564
|
||||
CODE_564(564, "BSM 报文中动力蓄电池温度过高"),
|
||||
|
||||
// 终止代码309 → 上报值:309 + 256 = 565
|
||||
CODE_565(565, "BSM 报文中动力蓄电池绝缘状态异常"),
|
||||
|
||||
// 终止代码310 → 上报值:310 + 256 = 566
|
||||
CODE_566(566, "BSM 报文中连接器连接状态异常"),
|
||||
|
||||
// 终止代码311 → 上报值:311 + 256 = 567
|
||||
CODE_567(567, "双枪同充辅枪充电异常"),
|
||||
|
||||
// 终止代码313 → 上报值:313 + 256 = 569
|
||||
CODE_569(569, "TCU 离线中止"),
|
||||
|
||||
// 终止代码314 → 上报值:314 + 256 = 570
|
||||
CODE_570(570, "电表分流器反接故障"),
|
||||
|
||||
// 终止代码315 → 上报值:315 + 256 = 571
|
||||
CODE_571(571, "终端按钮中止"),
|
||||
|
||||
// 终止代码316 → 上报值:316 + 256 = 572
|
||||
CODE_572(572, "安全防护电池包单体过压保护中止"),
|
||||
|
||||
// 终止代码317 → 上报值:317 + 256 = 573
|
||||
CODE_573(573, "安全防护电池过温保护中止"),
|
||||
|
||||
// 终止代码318 → 上报值:318 + 256 = 574
|
||||
CODE_574(574, "安全防护电池温升热失控异常保护中止"),
|
||||
|
||||
// 终止代码319 → 上报值:319 + 256 = 575
|
||||
CODE_575(575, "安全防护温差过大保护中止"),
|
||||
|
||||
// 终止代码320 → 上报值:320 + 256 = 576
|
||||
CODE_576(576, "安全防护 BMS 数据不更新保护中止"),
|
||||
|
||||
// 终止代码321 → 上报值:321 + 256 = 577
|
||||
CODE_577(577, "安全防护充电电量过充保护中止"),
|
||||
|
||||
// 终止代码322 → 上报值:322 + 256 = 578
|
||||
CODE_578(578, "安全防护整车充电过流保护中止"),
|
||||
|
||||
// 终止代码323 → 上报值:323 + 256 = 579
|
||||
CODE_579(579, "安全防护整车电池包过压保护中止"),
|
||||
|
||||
// 终止代码324 → 上报值:324 + 256 = 580
|
||||
CODE_580(580, "安全防护 SOC 数据异常保护中止"),
|
||||
|
||||
// 终止代码325 → 上报值:325 + 256 = 581
|
||||
CODE_581(581, "安全防护 BCP 电池电压异常保护中止"),
|
||||
|
||||
// 终止代码326 → 上报值:326 + 256 = 582
|
||||
CODE_582(582, "安全防护 BCP 电压与实际电池电压不符保护中止"),
|
||||
|
||||
// 终止代码327 → 上报值:327 + 256 = 583
|
||||
CODE_583(583, "安全防护电芯电压极差异常保护中止"),
|
||||
|
||||
// 终止代码328 → 上报值:328 + 256 = 584
|
||||
CODE_584(584, "安全防护设备空闲枪头带电异常保护中止"),
|
||||
|
||||
// 终止代码329 → 上报值:329 + 256 = 585
|
||||
CODE_585(585, "CHademo 充电车辆主动中止"),
|
||||
|
||||
// 终止代码330 → 上报值:330 + 256 = 586
|
||||
CODE_586(586, "CHademo 充电 Premission 信号异常中止"),
|
||||
|
||||
// 终止代码331 → 上报值:331 + 256 = 587
|
||||
CODE_587(587, "CHademo 充电车辆接触器异常中止"),
|
||||
|
||||
// 终止代码332 → 上报值:332 + 256 = 588
|
||||
CODE_588(588, "CHademo 充电车辆故障中止"),
|
||||
|
||||
// 终止代码333 → 上报值:333 + 256 = 589
|
||||
CODE_589(589, "CHademo 充电通信超时中止"),
|
||||
|
||||
// 终止代码334 → 上报值:334 + 256 = 590
|
||||
CODE_590(590, "CHademo 充电车辆报充电机异常中止"),
|
||||
|
||||
// 终止代码335 → 上报值:335 + 256 = 591
|
||||
CODE_591(591, "绝缘检测仪通信故障中止"),
|
||||
|
||||
// 终止代码336 → 上报值:336 + 256 = 592
|
||||
CODE_592(592, "液冷 AB 板 CAN3 离线中止");
|
||||
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String description;
|
||||
|
||||
|
||||
private static final String UNKNOWN_DESC = "未知结束原因";
|
||||
private static final Map<Integer, LvnengPileFinishReasonEnum> CODE_TO_ENUM_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (LvnengPileFinishReasonEnum enumValue : LvnengPileFinishReasonEnum.values()) {
|
||||
CODE_TO_ENUM_MAP.put(enumValue.getCode(), enumValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getByCode(Long code) {
|
||||
LvnengPileFinishReasonEnum lvnengPileFinishReasonEnum = CODE_TO_ENUM_MAP.get(code.intValue());
|
||||
if (lvnengPileFinishReasonEnum == null) {
|
||||
return UNKNOWN_DESC;
|
||||
}
|
||||
return lvnengPileFinishReasonEnum.getDescription();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 充电桩启动类型枚举
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum LvnengPileStartTypeEnum {
|
||||
/**
|
||||
* 0:刷卡启动
|
||||
* 1:服务器启动
|
||||
* 2:本地管理员启动
|
||||
* 3:VIN 启动 生产个枚举类
|
||||
*/
|
||||
|
||||
CARD_SWIPE(0, "刷卡启动"),
|
||||
|
||||
|
||||
SERVER(1, "服务器启动"),
|
||||
|
||||
|
||||
LOCAL_ADMIN(2, "本地管理员启动"),
|
||||
|
||||
|
||||
VIN(3, "VIN启动");
|
||||
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String description;
|
||||
|
||||
private static final String UNKNOWN_DESC = "未知类型";
|
||||
private static final Map<Integer, LvnengPileStartTypeEnum> CODE_TO_ENUM_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (LvnengPileStartTypeEnum enumValue : LvnengPileStartTypeEnum.values()) {
|
||||
CODE_TO_ENUM_MAP.put(enumValue.getCode(), enumValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getByCode(int code) {
|
||||
LvnengPileStartTypeEnum lvnengPileStartTypeEnum = CODE_TO_ENUM_MAP.get(code);
|
||||
if (lvnengPileStartTypeEnum == null) {
|
||||
return UNKNOWN_DESC;
|
||||
}
|
||||
return lvnengPileStartTypeEnum.getDescription();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 充电桩状态枚举
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum LvnengPileStatusEnum {
|
||||
/**
|
||||
* 0-空闲中
|
||||
* 1-正准备开始充电
|
||||
* 2-充电进行中
|
||||
* 3-充电结東
|
||||
* 4-启动失败
|
||||
* 5-预约状态
|
||||
* 6-系统故障(不能给汽车充电)
|
||||
* 注:目前工作状态只有 0,2,6
|
||||
*/
|
||||
|
||||
IDLE(0, "空闲中"),
|
||||
|
||||
CHARGING(2, "充电进行中"),
|
||||
|
||||
SYSTEM_FAILURE(6, "系统故障(不能给汽车充电)");
|
||||
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String description;
|
||||
|
||||
|
||||
private static final String UNKNOWN_DESC = "未知状态";
|
||||
private static final Map<Integer, LvnengPileStatusEnum> CODE_TO_ENUM_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (LvnengPileStatusEnum enumValue : LvnengPileStatusEnum.values()) {
|
||||
CODE_TO_ENUM_MAP.put(enumValue.getCode(), enumValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getByCode(int code) {
|
||||
LvnengPileStatusEnum lvnengPileStatusEnum = CODE_TO_ENUM_MAP.get(code);
|
||||
if (lvnengPileStatusEnum == null) {
|
||||
return UNKNOWN_DESC;
|
||||
}
|
||||
return lvnengPileStatusEnum.getDescription();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.HeartBeatRequest;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.annotation.LvnengCmd;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static sanbing.jcpp.protocol.lvneng.enums.LvnengDownlinkCmdEnum.HEARTBEAT_ACK;
|
||||
|
||||
/**
|
||||
* 绿能3.4 充电桩上传心跳包
|
||||
*/
|
||||
@Slf4j
|
||||
@LvnengCmd(102)
|
||||
public class LvnengV340HeartbeatULCmd extends LvnengUplinkCmdExe {
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengUplinkMessage lvnengUplinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4充电桩上报心跳包请求", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(lvnengUplinkMessage.getMsgBody());
|
||||
|
||||
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
|
||||
|
||||
//1预留
|
||||
byteBuf.skipBytes(2);
|
||||
//2预留
|
||||
byteBuf.skipBytes(2);
|
||||
|
||||
//3充电桩编码
|
||||
byte[] pileCodeBytes = new byte[32];
|
||||
byteBuf.readBytes(pileCodeBytes);
|
||||
String pileCode = StringUtils.trim(new String(pileCodeBytes, StandardCharsets.US_ASCII));
|
||||
|
||||
//4心跳序号
|
||||
int flag = byteBuf.readShortLE();
|
||||
additionalInfo.put("心跳序号", flag);
|
||||
//5预留
|
||||
byteBuf.skipBytes(16);
|
||||
|
||||
|
||||
tcpSession.addPileCode(pileCode);
|
||||
|
||||
// 注册前置会话
|
||||
ctx.getProtocolSessionRegistryProvider().register(tcpSession);
|
||||
|
||||
// 转发到后端
|
||||
HeartBeatRequest heartBeatRequest = HeartBeatRequest.newBuilder()
|
||||
.setPileCode(pileCode)
|
||||
.setRemoteAddress(tcpSession.getAddress().toString())
|
||||
.setNodeId(ctx.getServiceInfoProvider().getServiceId())
|
||||
.setNodeHostAddress(ctx.getServiceInfoProvider().getHostAddress())
|
||||
.setNodeRestPort(ctx.getServiceInfoProvider().getRestPort())
|
||||
.setNodeGrpcPort(ctx.getServiceInfoProvider().getGrpcPort())
|
||||
.setAdditionalInfo(additionalInfo.toString())
|
||||
.build();
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(heartBeatRequest.getPileCode(), tcpSession, lvnengUplinkMessage)
|
||||
.setHeartBeatRequest(heartBeatRequest)
|
||||
.build();
|
||||
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
//服务器应答心跳包信息
|
||||
pingAck(tcpSession, flag);
|
||||
}
|
||||
|
||||
private void pingAck(TcpSession tcpSession, int flag) {
|
||||
ByteBuf pingAckMsgBody = Unpooled.buffer(6);
|
||||
pingAckMsgBody.writeShortLE(0);
|
||||
pingAckMsgBody.writeShortLE(0);
|
||||
pingAckMsgBody.writeShortLE(flag);
|
||||
|
||||
encodeAndWriteFlush(HEARTBEAT_ACK,
|
||||
pingAckMsgBody,
|
||||
tcpSession);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import sanbing.jcpp.infrastructure.util.codec.BCDUtil;
|
||||
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.GunRunStatus;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.GunRunStatusProto;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.annotation.LvnengCmd;
|
||||
import sanbing.jcpp.protocol.lvneng.enums.LvnengAlarmCodeEnum;
|
||||
import sanbing.jcpp.protocol.lvneng.enums.LvnengPileStartTypeEnum;
|
||||
import sanbing.jcpp.protocol.lvneng.enums.LvnengPileStatusEnum;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static sanbing.jcpp.protocol.lvneng.enums.LvnengDownlinkCmdEnum.REAL_TIME_DATA_ACK;
|
||||
|
||||
/**
|
||||
* 绿能3.4 充电桩状态信息包上报
|
||||
*/
|
||||
@Slf4j
|
||||
@LvnengCmd(109)
|
||||
public class LvnengV340RealTimeDataULCmd extends LvnengUplinkCmdExe {
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengUplinkMessage lvnengUplinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4充电桩状态信息包上报请求", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(lvnengUplinkMessage.getMsgBody());
|
||||
|
||||
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
|
||||
// 从Tracer总获取当前时间
|
||||
long ts = TracerContextUtil.getCurrentTracer().getTracerTs();
|
||||
|
||||
//1预留
|
||||
byteBuf.skipBytes(2);
|
||||
//2预留
|
||||
byteBuf.skipBytes(2);
|
||||
|
||||
//3充电桩编码
|
||||
byte[] pileCodeBytes = new byte[32];
|
||||
byteBuf.readBytes(pileCodeBytes);
|
||||
String pileCode = StringUtils.trim(new String(pileCodeBytes, StandardCharsets.US_ASCII));
|
||||
|
||||
//4 充电枪数量
|
||||
byte gunsNum = byteBuf.readByte();
|
||||
additionalInfo.put("充电枪数量", gunsNum);
|
||||
|
||||
//5 充电枪口
|
||||
byte gunCode = byteBuf.readByte();
|
||||
additionalInfo.put("充电枪口", gunCode);
|
||||
|
||||
//6 充电枪类型
|
||||
byte gunType = byteBuf.readByte();
|
||||
additionalInfo.put("充电枪类型", gunType);
|
||||
|
||||
//7 工作状态
|
||||
byte pileStatus = byteBuf.readByte();
|
||||
String pileStatusCode = LvnengPileStatusEnum.getByCode(pileStatus);
|
||||
additionalInfo.put("工作状态", pileStatusCode);
|
||||
|
||||
//8 当前 SOC %
|
||||
byte soc = byteBuf.readByte();
|
||||
additionalInfo.put("soc", soc);
|
||||
|
||||
/** 9 告警码,0-无告警 非0参靠枚举类
|
||||
* @see LvnengAlarmCodeEnum
|
||||
*/
|
||||
long alarmCode = byteBuf.readUnsignedInt();
|
||||
String alarmCodeDesc = alarmCode == 0L ? "" : LvnengAlarmCodeEnum.getByCode(alarmCode);
|
||||
additionalInfo.put("告警码", alarmCodeDesc);
|
||||
|
||||
//10 车连接状态
|
||||
byte carLinkStatus = byteBuf.readByte();
|
||||
additionalInfo.put("车连接状态", getCarLinkDesc(carLinkStatus));
|
||||
|
||||
//11 本次充电累计充电费用 精度0.01元
|
||||
BigDecimal totalAmount = reduceMagnification(byteBuf.readUnsignedIntLE(), 100, 2);
|
||||
additionalInfo.put("本次充电累计充电费用", totalAmount);
|
||||
//12 当前时间
|
||||
byte[] bytes = new byte[8];
|
||||
byteBuf.readBytes(bytes);
|
||||
LocalDateTime localDateTime = BCDUtil.bcdToDate(bytes);
|
||||
long instant = localDateTime!=null?localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli():0L;
|
||||
additionalInfo.put("当前时间", instant);
|
||||
|
||||
//13 直流充电电压
|
||||
short DCV = byteBuf.readShortLE();
|
||||
additionalInfo.put("直流充电电压", DCV);
|
||||
|
||||
//14 直流充电电流
|
||||
short DCC = byteBuf.readShortLE();
|
||||
additionalInfo.put("直流充电电压", DCC);
|
||||
|
||||
//15 BMS 需求电压
|
||||
short bmsDCV = byteBuf.readShortLE();
|
||||
additionalInfo.put(" BMS 需求电压", bmsDCV);
|
||||
|
||||
//16 BMS 需求电流
|
||||
short bmsDCC = byteBuf.readShortLE();
|
||||
additionalInfo.put(" BMS 需求电压", bmsDCC);
|
||||
|
||||
//17 BMS 充电模式 1- 恒压 2- 恒流
|
||||
byte bmsChargingType = byteBuf.readByte();
|
||||
additionalInfo.put(" BMS 需求电压", getBmsChargingTypeDesc(bmsChargingType));
|
||||
|
||||
//18 交流 A 相充电电压
|
||||
short aACV = byteBuf.readShortLE();
|
||||
additionalInfo.put("交流 A 相充电电压", aACV);
|
||||
|
||||
//19 交流B相充电电压
|
||||
short bACV = byteBuf.readShortLE();
|
||||
additionalInfo.put("交流B相充电电压", bACV);
|
||||
|
||||
//20 交流 C相充电电压
|
||||
short cACV = byteBuf.readShortLE();
|
||||
additionalInfo.put("交流 C相充电电压", cACV);
|
||||
|
||||
//21 预留
|
||||
byteBuf.skipBytes(2);
|
||||
//22 预留
|
||||
byteBuf.skipBytes(2);
|
||||
//23 预留
|
||||
byteBuf.skipBytes(2);
|
||||
|
||||
//24 剩余充电时间 min
|
||||
short remainingTimeMin = byteBuf.readShortLE();
|
||||
additionalInfo.put("剩余充电时间 min", remainingTimeMin);
|
||||
|
||||
//25 充电时长 秒
|
||||
long totalChargingTime = byteBuf.readUnsignedIntLE();
|
||||
additionalInfo.put("充电时长 秒", totalChargingTime);
|
||||
|
||||
//26 本次充电累计充电电量 精度:0.001lkWh
|
||||
BigDecimal totalChargingEnergyKWh = reduceMagnification(byteBuf.readUnsignedIntLE(), 1000, 3);
|
||||
additionalInfo.put("本次充电累计充电电量", totalChargingEnergyKWh.toString());
|
||||
|
||||
//27 充电前电表读数 精度:0.001lkWh
|
||||
BigDecimal beforeNum = reduceMagnification(byteBuf.readLongLE(), 1000, 3);
|
||||
additionalInfo.put("充电前电表读数", beforeNum.toString());
|
||||
|
||||
//28 当前电表读数 精度:0.001lkWh
|
||||
BigDecimal currentNum = reduceMagnification(byteBuf.readLongLE(), 1000, 3);
|
||||
additionalInfo.put("当前电表读数", currentNum.toString());
|
||||
|
||||
//29 充电启动方式
|
||||
byte chargingType = byteBuf.readByte();
|
||||
String chargingTypeDesc = LvnengPileStartTypeEnum.getByCode(chargingType);
|
||||
additionalInfo.put("充电启动方式", chargingTypeDesc);
|
||||
|
||||
//30 预留
|
||||
byteBuf.skipBytes(1);
|
||||
//31 预留
|
||||
byteBuf.skipBytes(4);
|
||||
//32 预留
|
||||
byteBuf.skipBytes(1);
|
||||
|
||||
//33 云平台充电流水号/充电卡号
|
||||
byte[] tradeNoBytes = new byte[32];
|
||||
byteBuf.readBytes(tradeNoBytes);
|
||||
String tradeNo = BCDUtil.toString(tradeNoBytes);
|
||||
additionalInfo.put("云平台充电流水号/充电卡号", tradeNo);
|
||||
|
||||
//34 预留
|
||||
byteBuf.skipBytes(1);
|
||||
//35 预留
|
||||
byteBuf.skipBytes(8);
|
||||
|
||||
//36 当前电费,这里是整型,要乘以 0.01 才能得到真实的金额,单位元
|
||||
BigDecimal currentFee = reduceMagnification(byteBuf.readUnsignedIntLE(), 100, 2);
|
||||
additionalInfo.put("当前电费", currentFee.toString());
|
||||
|
||||
//37 当前服务费 这里是整型,要乘以 0.01 才能得到真实的金额,单位元
|
||||
BigDecimal currentServiceFee = reduceMagnification(byteBuf.readUnsignedIntLE(), 100, 2);
|
||||
additionalInfo.put("当前服务费", currentServiceFee.toString());
|
||||
|
||||
//38 充电功率 分辨率:0.1kW
|
||||
BigDecimal chargingPower = reduceMagnification(byteBuf.readUnsignedIntLE(), 10, 1);
|
||||
additionalInfo.put("充电功率", chargingPower.toString());
|
||||
|
||||
//39 预留
|
||||
byteBuf.skipBytes(4);
|
||||
//40 预留
|
||||
byteBuf.skipBytes(4);
|
||||
//41 预留
|
||||
byteBuf.skipBytes(4);
|
||||
|
||||
//42 出风口温度 预留 偏移量-50, -50-200
|
||||
byteBuf.skipBytes(1);
|
||||
//43 环境温度 预留 偏移量-50, -50-200
|
||||
byteBuf.skipBytes(1);
|
||||
//44 充电枪温度 预留 偏移量-50, -50-200
|
||||
byteBuf.skipBytes(1);
|
||||
|
||||
//45 车辆 VIN 码 直流桩有效,正常有效长度是字节17,18 位为‘\0’
|
||||
byte[] vinCodeByte = new byte[18];
|
||||
byteBuf.readBytes(vinCodeByte);
|
||||
String vinCode = new String(vinCodeByte, StandardCharsets.US_ASCII);
|
||||
additionalInfo.put("车辆 VIN 码", vinCode);
|
||||
|
||||
//46 预留 1
|
||||
byteBuf.skipBytes(1);
|
||||
|
||||
|
||||
tcpSession.addPileCode(pileCode);
|
||||
|
||||
// 注册前置会话
|
||||
ctx.getProtocolSessionRegistryProvider().register(tcpSession);
|
||||
|
||||
// 抢状态
|
||||
GunRunStatus gunRunStatus = parseGunRunStatus(pileStatus);
|
||||
GunRunStatusProto gunRunStatusProto = GunRunStatusProto.newBuilder()
|
||||
.setTs(ts)
|
||||
.setPileCode(pileCode)
|
||||
.setGunCode(gunCode + "")
|
||||
.setGunRunStatus(gunRunStatus)
|
||||
.addAllFaultMessages(Stream.of(alarmCodeDesc).collect(Collectors.toList()))
|
||||
.setAdditionalInfo(additionalInfo.toString())
|
||||
.build();
|
||||
|
||||
|
||||
// 转发到后端
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(gunRunStatusProto.getPileCode(), tcpSession, lvnengUplinkMessage)
|
||||
.setGunRunStatusProto(gunRunStatusProto)
|
||||
.build();
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
|
||||
if (StringUtils.isNotBlank(tradeNo)) {
|
||||
|
||||
// 充电进度
|
||||
ProtocolProto.ChargingProgressProto.Builder chargingProgressProtoBuilder = ProtocolProto.ChargingProgressProto.newBuilder()
|
||||
.setTs(ts)
|
||||
.setPileCode(pileCode)
|
||||
.setGunCode(gunCode + "")
|
||||
.setTradeNo(tradeNo)
|
||||
.setOutputVoltage(String.valueOf(DCV))
|
||||
.setOutputCurrent(String.valueOf(DCC))
|
||||
.setSoc(soc)
|
||||
.setTotalChargingDurationMin((int)totalChargingTime)
|
||||
.setTotalChargingEnergyKWh(totalChargingEnergyKWh.toPlainString())
|
||||
.setTotalChargingCostYuan(totalAmount.toPlainString())
|
||||
.setAdditionalInfo(additionalInfo.toString());
|
||||
|
||||
UplinkQueueMessage chargingProgressMessage = uplinkMessageBuilder(pileCode, tcpSession, lvnengUplinkMessage)
|
||||
.setChargingProgressProto(chargingProgressProtoBuilder)
|
||||
.build();
|
||||
|
||||
tcpSession.getForwarder().sendMessage(chargingProgressMessage);
|
||||
}
|
||||
|
||||
//服务器应答充电桩状态信息包
|
||||
realTimeDataAck(tcpSession, gunCode);
|
||||
}
|
||||
|
||||
private void realTimeDataAck(TcpSession tcpSession, byte gunCode) {
|
||||
ByteBuf pingAckMsgBody = Unpooled.buffer(5);
|
||||
pingAckMsgBody.writeShortLE(0);
|
||||
pingAckMsgBody.writeShortLE(0);
|
||||
pingAckMsgBody.writeByte(gunCode);
|
||||
|
||||
encodeAndWriteFlush(REAL_TIME_DATA_ACK,
|
||||
pingAckMsgBody,
|
||||
tcpSession);
|
||||
}
|
||||
|
||||
protected static BigDecimal reduceMagnification(long value, int magnification, int scale) {
|
||||
return new BigDecimal(value).divide(new BigDecimal(magnification), scale, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
|
||||
protected static String getBmsChargingTypeDesc(int value) {
|
||||
return switch (value) {
|
||||
case 1 -> "恒压";
|
||||
case 2 -> "恒流";
|
||||
default -> "未知";
|
||||
};
|
||||
}
|
||||
|
||||
protected static String getCarLinkDesc(int value) {
|
||||
// 目前只有 0 和 2 状态。
|
||||
return switch (value) {
|
||||
case 0 -> "断开";
|
||||
case 1 -> "半连接";
|
||||
case 2 -> "连接";
|
||||
default -> "未知";
|
||||
};
|
||||
}
|
||||
|
||||
private static GunRunStatus parseGunRunStatus(int gunStatus) {
|
||||
GunRunStatus gunRunStatus = GunRunStatus.UNKNOWN;
|
||||
if (gunStatus == 0) {
|
||||
gunRunStatus = GunRunStatus.IDLE;
|
||||
} else if (gunStatus == 2) {
|
||||
gunRunStatus = GunRunStatus.CHARGING;
|
||||
} else if (gunStatus == 6) {
|
||||
gunRunStatus = GunRunStatus.FAULT;
|
||||
}
|
||||
return gunRunStatus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.TransactionRecordResponse;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDownlinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDwonlinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.annotation.LvnengCmd;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static sanbing.jcpp.protocol.lvneng.enums.LvnengDownlinkCmdEnum.TRANSACTION_RECORD_ACK;
|
||||
|
||||
/**
|
||||
* 绿能3.4 服务器应答订单信息
|
||||
*/
|
||||
@Slf4j
|
||||
@LvnengCmd(201)
|
||||
public class LvnengV340TransactionRecordAckDLCmd extends LvnengDownlinkCmdExe {
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengDwonlinkMessage lvnengDwonlinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4服务器订单应答", tcpSession);
|
||||
|
||||
if (!lvnengDwonlinkMessage.getMsg().hasTransactionRecordResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TransactionRecordResponse transactionRecordResponse = lvnengDwonlinkMessage.getMsg().getTransactionRecordResponse();
|
||||
|
||||
LvnengUplinkMessage requestData = JacksonUtil.fromBytes(lvnengDwonlinkMessage.getMsg().getRequestData().toByteArray(), LvnengUplinkMessage.class);
|
||||
|
||||
// 获取上行报文
|
||||
byte[] uplinkRawFrame = requestData.getRawFrame();
|
||||
|
||||
// 从上行报文中取出桩编号字节数组
|
||||
byte[] gunCodeBytes = Arrays.copyOfRange(uplinkRawFrame, 45, 46);
|
||||
byte[] indexBytes = Arrays.copyOfRange(uplinkRawFrame, 128, 132);
|
||||
|
||||
ByteBuf pingAckMsgBody = Unpooled.buffer(41);
|
||||
//1预留
|
||||
pingAckMsgBody.writeShortLE(0x00);
|
||||
//2预留
|
||||
pingAckMsgBody.writeShortLE(0x00);
|
||||
//3充电枪口
|
||||
pingAckMsgBody.writeBytes(gunCodeBytes);
|
||||
//4流水号
|
||||
pingAckMsgBody.writeBytes(encodeTradeNo(transactionRecordResponse.getTradeNo()));
|
||||
//5内部索引号
|
||||
pingAckMsgBody.writeBytes(indexBytes);
|
||||
encodeAndWriteFlush(TRANSACTION_RECORD_ACK,
|
||||
pingAckMsgBody,
|
||||
tcpSession);
|
||||
}
|
||||
|
||||
protected static byte[] encodeTradeNo(String tradeNo) {
|
||||
// 将tradeNo 读取到32字节数组内
|
||||
byte[] bytes = new byte[32];
|
||||
byte[] tradeNoBytes = tradeNo.getBytes(StandardCharsets.US_ASCII);
|
||||
int copyLength = Math.min(tradeNoBytes.length, bytes.length);
|
||||
System.arraycopy(tradeNoBytes, 0, bytes, 0, copyLength);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import sanbing.jcpp.infrastructure.util.codec.BCDUtil;
|
||||
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.TimePeriodDetail;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.TimePeriodDetail.PeriodItem;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.TransactionDetail;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.TransactionRecordRequest;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.annotation.LvnengCmd;
|
||||
import sanbing.jcpp.protocol.lvneng.enums.LvnengPileFinishReasonEnum;
|
||||
import sanbing.jcpp.protocol.lvneng.enums.LvnengPileStartTypeEnum;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 绿能3.4 充电桩上报充电订单
|
||||
*/
|
||||
@Slf4j
|
||||
@LvnengCmd(203)
|
||||
public class LvnengV340TransactionRecordULCmd extends LvnengUplinkCmdExe {
|
||||
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengUplinkMessage lvnengUplinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4充电桩上报充电订单请求", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(lvnengUplinkMessage.getMsgBody());
|
||||
|
||||
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
|
||||
|
||||
//1预留
|
||||
byteBuf.skipBytes(2);
|
||||
//2预留
|
||||
byteBuf.skipBytes(2);
|
||||
|
||||
//3充电桩编码
|
||||
byte[] pileCodeBytes = new byte[32];
|
||||
byteBuf.readBytes(pileCodeBytes);
|
||||
String pileCode = StringUtils.trim(new String(pileCodeBytes, StandardCharsets.US_ASCII));
|
||||
|
||||
//4 充电枪位置类型
|
||||
byte gunType = byteBuf.readByte();
|
||||
additionalInfo.put("充电枪位置类型", gunType);
|
||||
|
||||
//5 充电枪口
|
||||
byte gunCode = byteBuf.readByte();
|
||||
additionalInfo.put("充电枪口", gunCode);
|
||||
|
||||
//6 卡号
|
||||
byte[] cardCodeBytes = new byte[32];
|
||||
byteBuf.readBytes(cardCodeBytes);
|
||||
String cardCode = StringUtils.trim(new String(cardCodeBytes, StandardCharsets.US_ASCII));
|
||||
additionalInfo.put("卡号", cardCode);
|
||||
|
||||
//7 充电开始时间
|
||||
byte[] chargingStartTimeBytes = new byte[8];
|
||||
byteBuf.readBytes(chargingStartTimeBytes);
|
||||
LocalDateTime start = BCDUtil.bcdToDate(chargingStartTimeBytes);
|
||||
long startTs = start != null ? start.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : 0L;
|
||||
|
||||
//8 充电结束时间
|
||||
byte[] chargingEndTimeBytes = new byte[8];
|
||||
byteBuf.readBytes(chargingEndTimeBytes);
|
||||
LocalDateTime endTime = BCDUtil.bcdToDate(chargingEndTimeBytes);
|
||||
long endTs = endTime != null ? endTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : 0L;
|
||||
|
||||
//9 充电时间长度 单位秒
|
||||
long chargingTotalTime = byteBuf.readUnsignedIntLE();
|
||||
additionalInfo.put("充电时间长度 单位秒", chargingTotalTime);
|
||||
|
||||
//10 开始 SOC
|
||||
byte startSoc = byteBuf.readByte();
|
||||
additionalInfo.put("开始 SOC", startSoc);
|
||||
|
||||
//11 结束 SOC
|
||||
byte endSoc = byteBuf.readByte();
|
||||
additionalInfo.put("结束 SOC", endSoc);
|
||||
|
||||
//12 充电结束原因
|
||||
long finishReasonCode = byteBuf.readUnsignedIntLE();
|
||||
String finishReason = LvnengPileFinishReasonEnum.getByCode(finishReasonCode);
|
||||
|
||||
//13 本次充电电量 精度:0.001kWh
|
||||
BigDecimal totalEnergy = reduceMagnification(byteBuf.readUnsignedIntLE(), 1000, 3);
|
||||
|
||||
//14 充电前电表读数 精度:0.001kWh
|
||||
BigDecimal chargingBeforeNum = reduceMagnification(byteBuf.readLongLE(), 1000, 3);
|
||||
additionalInfo.put("充电前电表读数", chargingBeforeNum);
|
||||
|
||||
//15 充电后电表读数 精度:0.001kWh
|
||||
BigDecimal chargingAfterNum = reduceMagnification(byteBuf.readLongLE(), 1000, 3);
|
||||
additionalInfo.put("充电后电表读数", chargingAfterNum);
|
||||
|
||||
//16 本次充电金额 0.01 元 ,电费和服务费之和。
|
||||
BigDecimal totalAmount = reduceMagnification(byteBuf.readUnsignedIntLE(), 100, 2);
|
||||
|
||||
//17 内部索引号 4 字节有符号整形,每一条充电记录 都唯一编号,用于充电机内部做唯一标志
|
||||
int index = byteBuf.readIntLE();
|
||||
additionalInfo.put("内部索引号", index);
|
||||
additionalInfo.put("index", index);
|
||||
|
||||
//18 预留
|
||||
byteBuf.skipBytes(4);
|
||||
//19 预留
|
||||
byteBuf.skipBytes(4);
|
||||
//20 预留
|
||||
byteBuf.skipBytes(4);
|
||||
//21 预留
|
||||
byteBuf.skipBytes(1);
|
||||
//22 预留
|
||||
byteBuf.skipBytes(1);
|
||||
//23 预留
|
||||
byteBuf.skipBytes(4);
|
||||
|
||||
//24 车辆 VIN
|
||||
byte[] cardVinBytes = new byte[17];
|
||||
byteBuf.readBytes(cardVinBytes);
|
||||
String cardVin = StringUtils.trim(new String(cardVinBytes, StandardCharsets.US_ASCII));
|
||||
additionalInfo.put("车辆 VIN", cardVin);
|
||||
|
||||
//25 车牌号
|
||||
byte[] cardNumBytes = new byte[8];
|
||||
byteBuf.readBytes(cardNumBytes);
|
||||
String cardNum = StringUtils.trim(new String(cardNumBytes, StandardCharsets.US_ASCII));
|
||||
additionalInfo.put("车牌号", cardNum);
|
||||
|
||||
// 24小时,48个时间段,开始时间段[00:00:00〜00:30:00],最后时间段[23:30:00-00:00:00] 0.001kwh
|
||||
LocalTime currentTime = LocalTime.MIDNIGHT;
|
||||
List<PeriodItem> list = new ArrayList<>();
|
||||
for (int i = 1; i < 49; i++) {
|
||||
BigDecimal chargingCapacity = reduceMagnification(byteBuf.readUnsignedIntLE(), 1000, 3);
|
||||
PeriodItem timePeriodDetail = PeriodItem.newBuilder()
|
||||
.setPeriodNo(i)
|
||||
.setStartTime(dateFormat(currentTime))
|
||||
.setEndTime(dateFormat(currentTime.plusMinutes(30)))
|
||||
.setEnergyKWh(chargingCapacity.toString())
|
||||
.build();
|
||||
list.add(timePeriodDetail);
|
||||
}
|
||||
|
||||
//74 启动方式
|
||||
byte startType = byteBuf.readByte();
|
||||
String startTypeCode = LvnengPileStartTypeEnum.getByCode(startType);
|
||||
additionalInfo.put("启动方式", startTypeCode);
|
||||
|
||||
//75 充电流水号
|
||||
byte[] tradeNoBytes = new byte[32];
|
||||
byteBuf.readBytes(tradeNoBytes);
|
||||
String tradeNo = StringUtils.trim(new String(tradeNoBytes, StandardCharsets.US_ASCII));
|
||||
|
||||
//76 充电服务费
|
||||
BigDecimal serviceFee = reduceMagnification(byteBuf.readUnsignedIntLE(), 100, 2);
|
||||
additionalInfo.put("充电服务费", serviceFee.toString());
|
||||
|
||||
tcpSession.addPileCode(pileCode);
|
||||
|
||||
|
||||
//充电明细
|
||||
TimePeriodDetail timePeriodDetail = TimePeriodDetail.newBuilder()
|
||||
.addAllPeriods(list)
|
||||
.build();
|
||||
//订单明细
|
||||
TransactionDetail transactionDetail = TransactionDetail.newBuilder()
|
||||
.setType(ProtocolProto.DetailType.TIME_PERIOD)
|
||||
.setTimePeriod(timePeriodDetail)
|
||||
.build();
|
||||
|
||||
// 注册前置会话
|
||||
ctx.getProtocolSessionRegistryProvider().register(tcpSession);
|
||||
|
||||
// 转发到后端
|
||||
TransactionRecordRequest transactionRecord = TransactionRecordRequest.newBuilder()
|
||||
.setPileCode(pileCode)
|
||||
.setGunCode(gunCode + "")
|
||||
.setTradeNo(tradeNo)
|
||||
.setStartTs(startTs)
|
||||
.setEndTs(endTs)
|
||||
.setTotalEnergyKWh(totalEnergy.toString())
|
||||
.setTotalAmountYuan(totalAmount.toString())
|
||||
.setStopReason(finishReason)
|
||||
.setDetail(transactionDetail)
|
||||
.setAdditionalInfo(additionalInfo.toString())
|
||||
.build();
|
||||
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(transactionRecord.getPileCode(), tcpSession, lvnengUplinkMessage)
|
||||
.setTransactionRecordRequest(transactionRecord)
|
||||
.build();
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected static BigDecimal reduceMagnification(long value, int magnification, int scale) {
|
||||
return new BigDecimal(value).divide(new BigDecimal(magnification), scale, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
protected static String dateFormat(LocalTime time) {
|
||||
return time.format(DATE_TIME_FORMATTER);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user