From 0521ba95dd0f54bb8ec36b15770cf52679e3ec04 Mon Sep 17 00:00:00 2001 From: jsowell <123@jsowell.com> Date: Wed, 10 Jun 2026 16:38:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4Strategy=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/ykc/AbstractYkcStrategy.java | 82 --- .../ykc/BMSAbortDuringChargingStrategy.java | 97 --- .../BMSDemandAndChargerOutputStrategy.java | 109 --- .../strategy/ykc/BMSInformationStrategy.java | 100 --- .../strategy/ykc/BillingTemplateStrategy.java | 76 -- .../ykc/BillingTemplateValidateStrategy.java | 73 -- .../netty/strategy/ykc/ChargeEndStrategy.java | 123 ---- ...gerAbortedDuringChargingPhaseStrategy.java | 94 --- .../ykc/ChargingHandshakeStrategy.java | 126 ---- .../ykc/ConfirmStartChargingStrategy.java | 340 --------- .../strategy/ykc/ErrorMessageStrategy.java | 94 --- .../ykc/GroundLockDataUploadStrategy.java | 184 ----- .../ykc/HeartbeatRequestStrategy.java | 62 -- .../netty/strategy/ykc/LoginStrategy.java | 231 ------ .../ykc/OfflineCardDataCleaningStrategy.java | 70 -- .../ykc/OfflineCardDataQueryStrategy.java | 61 -- .../ykc/OfflineCardDataSyncStrategy.java | 58 -- .../strategy/ykc/ParameterConfigStrategy.java | 137 ---- .../PileWorkingParameterSettingStrategy.java | 53 -- .../ykc/QueryPileWorkParamsStrategy.java | 90 --- .../ykc/RemoteControlGroundLockStrategy.java | 75 -- .../ykc/RemoteIssuedQrCodeStrategy.java | 53 -- .../strategy/ykc/RemoteRestartStrategy.java | 63 -- .../ykc/RemoteStartChargingStrategy.java | 157 ---- .../ykc/RemoteStopChargingStrategy.java | 99 --- .../strategy/ykc/RemoteUpdateStrategy.java | 53 -- ...ervationChargingStartupResultStrategy.java | 161 ---- .../ykc/ReservationChargingStrategy.java | 97 --- .../ykc/SettingPileWorkParamsStrategy.java | 95 --- .../ykc/TimeCheckSettingStrategy.java | 57 -- .../ykc/TransactionRecordsStrategy.java | 689 ------------------ .../ykc/UploadRealTimeMonitorStrategy.java | 420 ----------- 32 files changed, 4279 deletions(-) delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSAbortDuringChargingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSDemandAndChargerOutputStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSInformationStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargeEndStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargerAbortedDuringChargingPhaseStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargingHandshakeStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ConfirmStartChargingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ErrorMessageStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/GroundLockDataUploadStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/HeartbeatRequestStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataCleaningStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataQueryStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataSyncStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ParameterConfigStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/PileWorkingParameterSettingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/QueryPileWorkParamsStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteControlGroundLockStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteIssuedQrCodeStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteRestartStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStartChargingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStopChargingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteUpdateStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStartupResultStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/SettingPileWorkParamsStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TimeCheckSettingStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TransactionRecordsStrategy.java delete mode 100644 jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/UploadRealTimeMonitorStrategy.java diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java deleted file mode 100644 index f3f81af6e..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.constant.CacheConstants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.redis.StaticRedisCache; -import com.jsowell.common.enums.ykc.PileChannelEntity; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.YKCUtils; -import io.netty.channel.ChannelHandlerContext; - -/** - * 模板方法模式 - */ -public interface AbstractYkcStrategy { - - String REQUEST_PREFIX = "Request_"; - - - byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel); - - /** - * 组装应答的结果 - * @param ykcDataProtocol 请求数据 - * @param messageBody 消息体 - * @return 应答结果 - */ - // default byte[] getResult(YKCDataProtocol ykcDataProtocol, byte[] messageBody) { - // // 起始标志 - // byte[] head = ykcDataProtocol.getHead(); - // - // // 序列号域 - // byte[] serialNumber = ykcDataProtocol.getSerialNumber(); - // - // // 加密标志 - // byte[] encryptFlag = ykcDataProtocol.getEncryptFlag(); - // - // // 请求帧类型 - // byte[] requestFrameType = ykcDataProtocol.getFrameType(); - // - // // 应答帧类型 - // byte[] responseFrameType = YKCFrameTypeCode.PlatformAnswersRelation.getResponseFrameTypeBytes(requestFrameType); - // - // // 数据域 值为“序列号域+加密标志+帧类型标志+消息体”字节数之和 - // byte[] dataFields = Bytes.concat(serialNumber, encryptFlag, responseFrameType, messageBody); - // - // // 计算crc: 从序列号域到数据域的 CRC 校验 - // int crc16 = CRC16Util.calcCrc16(dataFields); - // - // return Bytes.concat(head, BytesUtil.intToBytes(dataFields.length, 1), dataFields, BytesUtil.intToBytes(crc16)); - // } - - /** - * 保存桩最后链接到平台的时间 - * @param pileSn 桩编号 - */ - default void saveLastTimeAndCheckChannel(String pileSn, ChannelHandlerContext ctx) { - String redisKey = CacheConstants.PILE_LAST_CONNECTION + pileSn; - StaticRedisCache.staticRedisCache.setCacheObject(redisKey, DateUtils.getDateTime(), CacheConstants.cache_expire_time_30d); - - // 保存桩号和channel的关系 - PileChannelEntity.checkChannel(pileSn, ctx); - } - - /** - * 阻止重复帧 - * @return true 重复 - */ - default boolean verifyTheDuplicateRequest(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { - // 获取序列号域 - int serialNumber = BytesUtil.bytesToIntLittle(ykcDataProtocol.getSerialNumber()); - // 获取帧类型 - String frameTypeStr = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType()); - // 获取channelId - String channelId = ctx.channel().id().asShortText(); - String redisKey = REQUEST_PREFIX + channelId + "_" + frameTypeStr; - Boolean result = StaticRedisCache.staticRedisCache.setnx(redisKey, ykcDataProtocol.getHEXString(), 30); - // result返回false说明没有设置成功,就是说已经有相同请求了,所以返回true重复 - return !result; - } - -} \ No newline at end of file diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSAbortDuringChargingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSAbortDuringChargingStrategy.java deleted file mode 100644 index 7ef2fbbf0..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSAbortDuringChargingStrategy.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电阶段 BMS 中止Handler - * - * GBT-27930 充电桩与 BMS 充电阶段 BMS 中止报文 - * @author JS-ZZA - * @date 2022/9/19 13:32 - */ -@Slf4j -@Component -public class BMSAbortDuringChargingStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.BMS_ABORT_DURING_CHARGING_PHASE_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电阶段 BMS 中止===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String orderCode = BytesUtil.bcd2Str(serialNumByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); - - /** - * BMS 中止充电原因 - * 1-2 位——所需求的 SOC 目标值 - * 3-4 位——达到总电压的设定值 - * 5-6 位——达到单体电压设定值 - * 7-8 位——充电机主动中止 - */ - startIndex += length; - byte[] BMSStopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - - /** - * BMS 中止充电故障原因 - * 1-2 位——绝缘故障 - * 3-4 位——输出连接器过温故障 - * 5-6 位——BMS 元件、输出连接 器过温 - * 7-8 位——充电连接器故障 - * 9-10 位——电池组温度过高故障 - * 11-12 位——高压继电器故障 - * 13-14 位——检测点 2 电压检测故障 - * 15-16 位——其他故障 - */ - startIndex += length; - length = 2; - byte[] BMSStopFaultReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - /** - * BMS 中止充电错误原因 - * 1-2 位——电流过大 - * 3-4 位——电压异常 - * 5-8 位——预留位 - */ - startIndex += length; - byte[] BMSStopErrorReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSDemandAndChargerOutputStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSDemandAndChargerOutputStrategy.java deleted file mode 100644 index 55d31f603..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSDemandAndChargerOutputStrategy.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电过程 BMS 需求与充电机输出 0x23 - * - * GBT-27930 充电桩与 BMS 充电过程 BMS 需求、充电机输出 - * @author JS-ZZA - * @date 2022/9/19 13:51 - */ -@Slf4j -@Component -public class BMSDemandAndChargerOutputStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGING_PROCESS_BMS_DEMAND_AND_CHARGER_OUTPUT_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电过程 BMS 需求与充电机输出===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电压需求 0.1 V/位, 0 V 偏移量 - startIndex += length; - length = 2; - byte[] bmsVoltageDemandByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电流需求 0.1 A/位, -400 A 偏移量 - startIndex += length; - byte[] bmsCurrentDemandByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 充电模式 0x01:恒压充电; 0x02:恒流充电 - startIndex += length; - length = 1; - byte[] bmsChargingModelByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 充电电压测量值 0.1 V/位, 0 V 偏移量 - startIndex += length; - length = 2; - byte[] bmsChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 充电电流测量值 0.1 A/位, -400 A 偏移量 - startIndex += length; - byte[] bmsChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 最高单体动力蓄电池电压及组号 1-12 位:最高单体动力蓄电池电压, 数据分辨率: 0.01 V/位, 0 V 偏移量;数据范围: 0~24 V; 13-16 位: 最高单体动力蓄电池电 压所在组号,数据分辨率: 1/位, 0 偏移量;数据范围: 0~15 - startIndex += length; - byte[] bmsMaxVoltageAndGroupNum = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 当前荷电状态 SOC( %) 1%/位, 0%偏移量; 数据范围: 0~100% - startIndex += length; - length = 1; - byte[] socByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 估算剩余充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min - startIndex += length; - length = 2; - byte[] bmsTheRestChargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 电桩电压输出值 0.1 V/位, 0 V 偏移量 - startIndex += length; - byte[] pileVoltageOutputByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 电桩电流输出值 0.1 A/位, -400 A 偏移量 - startIndex += length; - byte[] pileCurrentOutputByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 累计充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min - startIndex += length; - byte[] chargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSInformationStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSInformationStrategy.java deleted file mode 100644 index 8811a6198..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BMSInformationStrategy.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电过程 BMS 信息 0x25 - * - * GBT-27930 充电桩与 BMS 充电过程 BMS 信息 - * @author JS-ZZA - * @date 2022/9/19 13:53 - */ -@Slf4j -@Component -public class BMSInformationStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGING_PROCESS_BMS_INFORMATION_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电过程 BMS 信息===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 最高单体动力蓄电池电压所在编号 1/位, 1 偏移量; 数据范围: 1~256 - startIndex += length; - byte[] BMSMaxVoltageNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 最高动力蓄电池温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC - startIndex += length; - byte[] BMSMaxBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 最高温度检测点编号 1/位, 1 偏移量; 数据范围: 1~128 - startIndex += length; - byte[] maxTemperatureDetectionNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 最低动力蓄电池温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC - startIndex += length; - byte[] minBatteryTemperature = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 最低动力蓄电池温度检测点编号 1/位, 1 偏移量; 数据范围: 1~128 - startIndex += length; - byte[] minTemperatureDetectionNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - /** - * 9-12 - * 9: BMS 单体动力蓄电池电压过高 /过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) - * 10: BMS 整车动力蓄电池荷电状态 SOC 过高/过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) - * 11: BMS 动力蓄电池充电过电流 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - * 12: BMS 动力蓄电池温度过高 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - */ - startIndex += length; - byte[] numNineToTwelve = BytesUtil.copyBytes(msgBody, startIndex, length); - - /** - * 13-16 - * 13: BMS 动力蓄电池绝缘状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - * 14: BMS 动力蓄电池组输出连接器连接状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - * 15: 充电禁止 (<00>: =禁止; <01>: =允许) - * 16: 预留位 00 - */ - startIndex += length; - byte[] numThirteenToSixteen = BytesUtil.copyBytes(msgBody, startIndex, length); - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateStrategy.java deleted file mode 100644 index 2bcded7d9..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateStrategy.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.service.PileBillingTemplateService; -import com.jsowell.pile.service.YKCPushCommandService; -import com.jsowell.pile.vo.web.BillingTemplateVO; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 计费模板请求 Handler - * - * @author JS-ZZA - * @date 2022/9/17 15:59 - */ -@Slf4j -@Component -public class BillingTemplateStrategy implements AbstractYkcStrategy { - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.BILLING_TEMPLATE_CODE.getBytes()); - - @Autowired - private PileBillingTemplateService pileBillingTemplateService; - - @Autowired - private YKCPushCommandService ykcPushCommandService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { - // log.info("[===执行计费模板请求逻辑===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体(此请求消息体只有桩编码) - byte[] pileSnByte = ykcDataProtocol.getMsgBody(); - String pileSn = BytesUtil.binary(pileSnByte, 16); - // log.info("桩号:{}", pileSn); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, ctx); - - // 根据桩号查询计费模板 - BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); - if (billingTemplateVO == null) { - log.warn("根据桩号:{},查询计费模板为null", pileSn); - return null; - } - - // log.info("下面进行下发二维码 pileSn:{}, thread:{}", pileSn, Thread.currentThread().getName()); - // CompletableFuture.runAsync(() -> { - // try { - // Thread.sleep(200); - // } catch (InterruptedException e) { - // e.printStackTrace(); - // } - // // 下发二维码 - // IssueQRCodeCommand issueQRCodeCommand = IssueQRCodeCommand.builder().pileSn(pileSn).build(); - // ykcPushCommandService.pushIssueQRCodeCommand(issueQRCodeCommand); - // }); - - byte[] messageBody = pileBillingTemplateService.generateBillingTemplateMsgBody(pileSn, billingTemplateVO); - - return YKCUtils.getResult(ykcDataProtocol, messageBody); - } - -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateStrategy.java deleted file mode 100644 index 139103257..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateStrategy.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.google.common.primitives.Bytes; -import com.jsowell.common.annotation.CostTime; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.service.PileBillingTemplateService; -import com.jsowell.pile.service.YKCPushCommandService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; - -/** - * 计费模板验证请求Handler - * - * @author JS-ZZA - * @date 2022/9/17 14:10 - */ -@Slf4j -@Service -public class BillingTemplateValidateStrategy implements AbstractYkcStrategy { - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.BILLING_TEMPLATE_VALIDATE_CODE.getBytes()); - - @Autowired - private PileBillingTemplateService pileBillingTemplateService; - - @Autowired - private YKCPushCommandService ykcPushCommandService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @CostTime - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===执行计费模板验证请求逻辑===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩号 - byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.binary(pileSnByte, 16); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 计费模型编码 - startIndex += length; - length = 2; - byte[] billingTemplateCodeByte = BytesUtil.copyBytes(msgBody, startIndex, length); - String billingTemplateCode = BytesUtil.binary(billingTemplateCodeByte, 16); - - // byte[] flag = Constants.oneByteArray; 0x00 桩计费模型与平台一致 0x01桩计费模型与平台不一致 - byte[] flag = Constants.zeroByteArray; - - // 消息体 - byte[] messageBody = Bytes.concat(pileSnByte, billingTemplateCodeByte, flag); - return YKCUtils.getResult(ykcDataProtocol, messageBody); - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargeEndStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargeEndStrategy.java deleted file mode 100644 index 2a8561857..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargeEndStrategy.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.service.OrderBasicInfoService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; -import java.util.Objects; - -/** - * 充电结束Handler - * 0x19 - * GBT-27930 充电桩与 BMS 充电结束阶段报文 - * @author JS-ZZA - * @date 2022/9/19 13:27 - */ -@Slf4j -@Component -public class ChargeEndStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGE_END_CODE.getBytes()); - - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===执行充电结束逻辑===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // BMS中止荷电状态 SOC 1%/位, 0%偏移量; 数据范围: 0~100% - startIndex += length; - byte[] BMSStopChargingSOC = BytesUtil.copyBytes(msgBody, startIndex, length); - String stopSoc = BytesUtil.binary(BMSStopChargingSOC, 10); - - // BMS 动力蓄电池单体最低电压 0.01 V/位, 0 V 偏移量;数据范围: 0 ~24 V - startIndex += length; - length = 2; - byte[] BMSBatteryMinVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 动力蓄电池单体最高电压 0.01 V/位, 0 V 偏移量;数据范围: 0 ~24 V - startIndex += length; - byte[] BMSBatteryMaxVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 动力蓄电池最低温度 1ºC/位, -50 ºC 偏移量;数据范围: -50 ºC ~+200 ºC - startIndex += length; - length = 1; - byte[] BMSBatteryMinTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 动力蓄电池最高温度 1ºC/位, -50 ºC 偏移量;数据范围: -50 ºC ~+200 ºC - startIndex += length; - byte[] BMSBatteryMaxTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 电桩累计充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min - startIndex += length; - length = 2; - byte[] pileSumChargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 电桩输出能量 0.1 kWh/位, 0 kWh 偏移量; 数据范围: 0~1000 kWh - startIndex += length; - byte[] pileOutputEnergyByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 电桩充电机编号 充电机编号, 1/位, 1偏移量 ,数据范围 : 0 ~ 0xFFFFFFFF - startIndex += length; - length = 4; - byte[] pileChargedCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 查询订单 将结束soc传入 - OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - if (Objects.nonNull(orderInfo)) { - Date nowDate = DateUtils.getNowDate(); // 当前时间 - - // 只更新个别字段 - OrderBasicInfo updateOrder = new OrderBasicInfo(); - updateOrder.setId(orderInfo.getId()); - updateOrder.setEndSoc(stopSoc); - if (orderInfo.getChargeEndTime() == null) { - updateOrder.setChargeEndTime(nowDate); // 结束充电时间 - } - updateOrder.setUpdateTime(nowDate); - orderBasicInfoService.updateOrderBasicInfo(updateOrder); - } - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargerAbortedDuringChargingPhaseStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargerAbortedDuringChargingPhaseStrategy.java deleted file mode 100644 index be9a79ea4..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargerAbortedDuringChargingPhaseStrategy.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电阶段充电机中止Handler 0x21 - * - * GBT-27930 充电桩与 BMS 充电阶段充电机中止报文 - * @author JS-ZZA - * @date 2022/9/19 13:35 - */ -@Slf4j -@Component -public class ChargerAbortedDuringChargingPhaseStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.THE_CHARGER_IS_ABORTED_DURING_THE_CHARGING_PHASE_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电阶段充电机中止===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - /** - * BMS 中止充电原因 - * 1-2 位——达到充电机设定 的条件中止 - * 3-4 位——人工中止 - * 5-6 位——异常中止 - * 7-8 位——BMS 主动中止 - */ - startIndex += length; - byte[] BMSStopChargingReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - /** - * BMS 中止充电故障原因 - * 1-2 位——充电机过温故障 - * 3-4 位——充电连接器故障 - * 5-6 位——充电机内部过温故障 - * 7-8 位——所需电量不 能传送 - * 9-10 位——充电机急停故障 - * 11-12 位——其他故障 - * 13-16 位——预留位 - */ - startIndex += length; - length = 2; - byte[] BMSStopChargingFaultReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - /** - * BMS 中止充电错误原因 - * 1-2 位——电流不匹配 - * 3-4 位——电压异常 - * 5-8 位——预留位 - */ - startIndex += length; - length = 1; - byte[] BMSStopChargingErrorReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargingHandshakeStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargingHandshakeStrategy.java deleted file mode 100644 index a19f4bdf0..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ChargingHandshakeStrategy.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电握手 - * - * GBT-27930 充电桩与 BMS 充电握手阶段报文 - * @author JS-ZZA - * @date 2022/9/19 13:20 - */ -@Slf4j -@Component -public class ChargingHandshakeStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGING_HANDSHAKE_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===执行充电握手逻辑===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 通信协议版本号 当前版本为 V1.1, 表示为: byte3, byte2—0001H;byte1—01H - startIndex += length; - length = 3; - byte[] BMSCommunicationProtocolVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池类型 01H:铅酸电池;02H:氢 电池;03H:磷酸铁锂电池;04H:锰 酸锂电池;05H:钴酸锂电池 ;06H: 三元材料电池;07H:聚合物锂离子 电池;08H:钛酸锂电池;FFH:其他 - startIndex += length; - length = 1; - byte[] BMSBatteryTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 整车动力蓄电池系统额定容量 0.1 Ah /位, 0 Ah 偏移量 - startIndex += length; - length = 2; - byte[] BMSBatteryCapacityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 整车动力蓄电池系统额定总电压 0.1V/位, 0V 偏移量 - startIndex += length; - byte[] BMSBatteryVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池生产厂商名称 - startIndex += length; - length = 4; - byte[] BMSBatteryFactoryByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池组序号 - startIndex += length; - byte[] BMSBatteryNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池组生产日期年 1985 年偏移量, 数据范围: 1985~ 2235 年 - startIndex += length; - length = 1; - byte[] BMSProductionDateYearByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池组生产日期月 0 月偏移量, 数据范围: 1~12 月 - startIndex += length; - byte[] BMSProductionDateMonthByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池组生产日期日 0 日偏移量, 数据范围: 1~31 日 - startIndex += length; - byte[] BMSProductionDateDayByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池组充电次数 1 次/位, 0 次偏移量, 以 BMS 统 计为准 - startIndex += length; - length = 3; - byte[] BMSChargingTimesByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 电池组产权标识 (<0>: =租赁; <1>: =车自有) - startIndex += length; - length = 1; - byte[] BMSPropertyIdentificationByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 预留位 - startIndex += length; - byte[] BMSReservePosition = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 车辆识别码 - startIndex += length; - length = 17; - byte[] BMSCarIdentifyCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // BMS 软件版本号 - startIndex += length; - length = 8; - byte[] BMSSoftwareVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ConfirmStartChargingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ConfirmStartChargingStrategy.java deleted file mode 100644 index 286124735..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ConfirmStartChargingStrategy.java +++ /dev/null @@ -1,340 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.google.common.primitives.Bytes; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.enums.ykc.CardStatusEnum; -import com.jsowell.common.enums.ykc.ReturnCodeEnum; -import com.jsowell.common.enums.ykc.StartModeEnum; -import com.jsowell.common.exception.BusinessException; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.MemberPlateNumberRelation; -import com.jsowell.pile.domain.PileAuthCard; -import com.jsowell.pile.dto.ConfirmStartChargingData; -import com.jsowell.pile.dto.GenerateOrderDTO; -import com.jsowell.pile.service.MemberPlateNumberRelationService; -import com.jsowell.pile.service.OrderBasicInfoService; -import com.jsowell.pile.service.PileAuthCardService; -import com.jsowell.pile.service.PileMsgRecordService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Arrays; -import java.util.Map; - -/** - * 充电桩主动申请启动充电 0x31 - * - * 启动充电鉴权结果 - * @author JS-ZZA - * @date 2022/9/19 14:29 - */ -@Slf4j -@Component -public class ConfirmStartChargingStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REQUEST_START_CHARGING_CODE.getBytes()); - - @Autowired - private PileAuthCardService pileAuthCardService; - - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - @Autowired - private MemberPlateNumberRelationService memberPlateNumberRelationService; - - @Autowired - private PileMsgRecordService pileMsgRecordService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电桩主动申请启动充电===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编码 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.binary(pileSnByteArr, 16); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorNumByteArr); - - // 启动方式 - // 0x01 表示通过刷卡启动充电 - // 0x02 表求通过帐号启动充电 (暂不支持) - // 0x03 表示vin码启动充电 - startIndex += length; - byte[] startModeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String startMode = BytesUtil.bcd2Str(startModeByteArr); - - // 是否需要密码 0x00 不需要 0x01 需要 - startIndex += length; - byte[] needPasswordFlagByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String needPasswordFlag = BytesUtil.bcd2Str(needPasswordFlagByteArr); - - // 物理卡号 不足 8 位补 0 - startIndex += length; - length = 8; - byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - log.info("充电桩主动申请启动充电cardNumByteArr:{}", cardNumByteArr); - String physicsCard = BytesUtil.binary(cardNumByteArr, 16); - - // 输入密码 对用户输入的密码进行16 位MD5 加密,采用小写上传 - startIndex += length; - length = 16; - byte[] inputPasswordByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String inputPasswordHexStr = BytesUtil.bin2HexStr(inputPasswordByteArr); - - // VIN码 - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String vinCode = BytesUtil.ascii2StrLittle(vinCodeByteArr); - String vinCode = YKCUtils.parseVin(vinCodeByteArr); - - ConfirmStartChargingData confirmStartChargingData = ConfirmStartChargingData.builder() - .pileSn(pileSn) - .connectorCode(connectorCode) - .startMode(startMode) - .needPasswordFlag(needPasswordFlag) - .inputPasswordByteArr(inputPasswordHexStr) - .physicsCard(physicsCard) - .vinCode(vinCode) - .build(); - - byte[] defeatReasonByteArr = Constants.zeroByteArray; - /** - * 刷卡启动充电 - */ - String logicCard = ""; - byte[] authenticationFlagByteArr = Constants.zeroByteArray; // 鉴权成功标识 - byte[] accountBalanceByteArr = Constants.zeroByteArray; // 账户余额 - String transactionCode = ""; - try { - if (StringUtils.equals("01", startMode)) { - log.info("桩号:{}, 申请充电物理卡号:{}", pileSn, physicsCard); - // 查询卡信息 根据传过来的物理卡号查询数据库中此卡信息 - PileAuthCard pileAuthCardInfo = pileAuthCardService.selectCardInfoByLogicCard(physicsCard); - if (pileAuthCardInfo == null) { - // 未查到此卡信息 - throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_NO_INFO); - } - if (StringUtils.isBlank(pileAuthCardInfo.getMemberId())) { - // 卡未绑定用户 - throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_NOT_BIND_USER); - } - - // 判断卡状态 - if (!StringUtils.equals(CardStatusEnum.NORMAL.getCode(), pileAuthCardInfo.getStatus())) { - log.info("卡号:{}, 状态:{}, 非正常使用状态", physicsCard, CardStatusEnum.getCardStatus(pileAuthCardInfo.getStatus())); - return null; - } - - // 刷卡生成订单 刷卡启动充电 - GenerateOrderDTO dto = new GenerateOrderDTO(); - dto.setPileAuthCardInfo(pileAuthCardInfo); - dto.setPileSn(pileSn); - dto.setConnectorCode(connectorCode); - dto.setStartMode(StartModeEnum.AUTH_CARD.getValue()); - dto.setMemberId(pileAuthCardInfo.getMemberId()); - Map map = orderBasicInfoService.generateOrderByCard(dto); - if (map != null) { - transactionCode = (String) map.get("transactionCode"); - accountBalanceByteArr = YKCUtils.getPriceByte(String.valueOf(map.get("accountBalance")), 2); - // 鉴权成功标识 0x00 失败 0x01 成功 - authenticationFlagByteArr = Constants.oneByteArray; - }else { - throw new BusinessException("", "生成刷卡订单失败"); - } - } - } catch (BusinessException e){ - transactionCode = Constants.ILLEGAL_TRANSACTION_CODE; - accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8); - authenticationFlagByteArr = Constants.zeroByteArray; - log.error("刷卡启动充电鉴权 error:{}, {}", e.getCode(), e.getMessage()); - } catch (Exception e){ - transactionCode = Constants.ILLEGAL_TRANSACTION_CODE; - accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8); - authenticationFlagByteArr = Constants.zeroByteArray; - log.error("刷卡启动充电鉴权 error", e); - } - - try { - /** - * VIN码启动充电 - */ - if (StringUtils.equals("03", startMode)) { - log.info("桩号:{}, 申请充电VIN码:{}, 反转后:{}", pileSn, vinCode, StringUtils.reverse(vinCode)); - // 通过vin码查询数据库绑定用户信息 - MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode); - if (plateInfo == null) { - // throw new BusinessException("", vinCode + "未查到绑定用户信息"); - log.error(vinCode + "未查到绑定用户信息"); - defeatReasonByteArr = new byte[] {0x09}; // 系统中vin 码不存在 - transactionCode = Constants.ILLEGAL_TRANSACTION_CODE; - accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8); - authenticationFlagByteArr = Constants.zeroByteArray; - } - // if (!StringUtils.equals("1", plateInfo.getVinStatus())) { - // // 1- 正常使用 - // throw new BusinessException("", vinCode + "vin状态不正确"); - // } - // vin码生成订单 vin启动充电 - GenerateOrderDTO dto = new GenerateOrderDTO(); - dto.setMemberPlateNumberRelation(plateInfo); - dto.setPileSn(pileSn); - dto.setConnectorCode(connectorCode); - dto.setStartMode(StartModeEnum.VIN_CODE.getValue()); - dto.setMemberId(plateInfo.getMemberId()); - Map map = orderBasicInfoService.generateOrderByCard(dto); - if (map != null) { - transactionCode = (String) map.get("transactionCode"); - accountBalanceByteArr = YKCUtils.getPriceByte(String.valueOf(map.get("accountBalance")), 2); - // 鉴权成功标识 0x00 失败 0x01 成功 - authenticationFlagByteArr = Constants.oneByteArray; - }else { - throw new BusinessException("", "生成vin订单失败"); - } - } - }catch (BusinessException e){ - transactionCode = Constants.ILLEGAL_TRANSACTION_CODE; - accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8); - authenticationFlagByteArr = Constants.zeroByteArray; - String code = e.getCode(); - String message = e.getMessage(); - if (StringUtils.length(code) == 2) { - defeatReasonByteArr = BytesUtil.str2Bcd(code); - } - - log.error("VIN码启动充电鉴权 error:{}, {}", code, message); - }catch (Exception e) { - transactionCode = Constants.ILLEGAL_TRANSACTION_CODE; - accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8); - authenticationFlagByteArr = Constants.zeroByteArray; - - log.error("VIN码启动充电鉴权 error", e); - } - - // 应答 - // 交易流水号 - // String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); - byte[] serialNumByteArr = BytesUtil.str2Bcd(transactionCode); - - /** - * 失败原因 - * 0x01 账户不存在 - * 0x02 账户冻结 - * 0x03 账户余额不足 - * 0x04 该卡存在未结账记录 - * 0x05 桩停用 - * 0x06 该账户不能在此桩上充电 - * 0x07 密码错误 - * 0x08 电站电容不足 - * 0x09 系统中vin 码不存在 - * 0x0A 该桩存在未结账记录 - * 0x0B 该桩不支持刷卡 - */ - // byte[] defeatReasonByteArr = Constants.zeroByteArray; - - // 保存报文 - String jsonMsg = JSON.toJSONString(confirmStartChargingData); - // pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString()); - - // 拼装消息体 - byte[] msgBodyByteArr = Bytes.concat(serialNumByteArr, pileSnByteArr, connectorNumByteArr, cardNumByteArr, accountBalanceByteArr, - authenticationFlagByteArr, defeatReasonByteArr); - - return YKCUtils.getResult(ykcDataProtocol, msgBodyByteArr); - } - - /** - * 充电桩主动申请充电 逻辑 - * @param confirmStartChargingData - * @return - */ - private byte[] confirmStartCharging(ConfirmStartChargingData confirmStartChargingData) { - String startMode = confirmStartChargingData.getStartMode(); - String pileSn = confirmStartChargingData.getPileSn(); - String connectorCode = confirmStartChargingData.getConnectorCode(); - - GenerateOrderDTO dto = null; - try { - if (StringUtils.equals("01", startMode)) { - String physicsCard = confirmStartChargingData.getPhysicsCard(); - // 查询卡信息 根据传过来的物理卡号查询数据库中此卡信息 - PileAuthCard pileAuthCardInfo = pileAuthCardService.selectCardInfoByLogicCard(physicsCard); - if (pileAuthCardInfo == null) { - // 未查到此卡信息 - throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_NO_INFO); - } - if (StringUtils.isBlank(pileAuthCardInfo.getMemberId())) { - // 卡未绑定用户 - throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_NOT_BIND_USER); - } - - // 判断卡状态 - if (!StringUtils.equals(CardStatusEnum.NORMAL.getCode(), pileAuthCardInfo.getStatus())) { - log.info("卡号:{}, 状态:{}, 非正常使用状态", physicsCard, CardStatusEnum.getCardStatus(pileAuthCardInfo.getStatus())); - return null; - } - dto = new GenerateOrderDTO(); - dto.setPileAuthCardInfo(pileAuthCardInfo); - dto.setPileSn(pileSn); - dto.setConnectorCode(connectorCode); - dto.setStartMode(StartModeEnum.AUTH_CARD.getValue()); - dto.setMemberId(pileAuthCardInfo.getMemberId()); - } else if (StringUtils.equals("03", startMode)) { - String vinCode = confirmStartChargingData.getVinCode(); - // 通过vin码查询数据库绑定用户信息 - MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode); - if (plateInfo == null) { - throw new BusinessException("", vinCode + "未查到绑定用户信息"); - } - dto = new GenerateOrderDTO(); - dto.setMemberPlateNumberRelation(plateInfo); - dto.setPileSn(pileSn); - dto.setConnectorCode(connectorCode); - dto.setStartMode(StartModeEnum.VIN_CODE.getValue()); - dto.setMemberId(plateInfo.getMemberId()); - } - - if (dto != null) { - // Map map = orderBasicInfoService.generateOrderByCard(dto); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - - return null; - } - - public static void main(String[] args) { - String msg = "01"; - System.out.println(StringUtils.length(msg)); - byte[] bytes = BytesUtil.str2Bcd(msg); - byte[] a = new byte[]{0x01}; - String s = Arrays.toString(bytes); - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ErrorMessageStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ErrorMessageStrategy.java deleted file mode 100644 index efacb006d..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ErrorMessageStrategy.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 错误报文Handler - * - * GBT-27930 充电桩与 BMS 充电错误报文 - * @author JS-ZZA - * @date 2022/9/19 13:29 - */ -@Slf4j -@Component -public class ErrorMessageStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.ERROR_MESSAGE_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===错误报文===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号4-6 <00>: =正常; <01>: =超时; <10>: =不可信状态 - startIndex += length; - byte[] NumFourToSix = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号7-9 - startIndex += length; - byte[] NumSevenToNine = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号10-12 - startIndex += length; - byte[] NumTenToTwelve = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号13-14 - startIndex += length; - byte[] NumThirteenToFourteen = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号15-16 - startIndex += length; - byte[] NumFifteenToSixteen = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号17-19 - startIndex += length; - byte[] NumSeventeenToNineteen = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号20-23 - startIndex += length; - byte[] NumTwentyToTwentyThree = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 序号24-25 - startIndex += length; - byte[] NumTwentyFourToTwentyFive = BytesUtil.copyBytes(msgBody, startIndex, length); - - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/GroundLockDataUploadStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/GroundLockDataUploadStrategy.java deleted file mode 100644 index 429e5d247..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/GroundLockDataUploadStrategy.java +++ /dev/null @@ -1,184 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.jsowell.common.constant.CacheConstants; -import com.jsowell.common.core.domain.ykc.GroundLockData; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.core.redis.RedisCache; -import com.jsowell.common.enums.parkplatform.ParkingLockAlarmEnum; -import com.jsowell.common.enums.parkplatform.ParkingLockStatusEnum; -import com.jsowell.common.enums.parkplatform.ParkingStatusEnum; -import com.jsowell.common.enums.uniapp.OccupyOrderPayStatusEnum; -import com.jsowell.common.enums.uniapp.OccupyOrderStatusEnum; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderPileOccupy; -import com.jsowell.pile.service.OrderPileOccupyService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Locale; -import java.util.Objects; - -/** - * 地锁数据上送 - * - * 地锁状态/报警信息变化时,桩立刻上送变位/报警信息;地锁状态不变化时,每隔 5 分钟周期 性上送地锁状态。若无报警信息,不上送。 - * - * @author JS-ZZA - * @date 2022/9/19 15:21 - */ -@Slf4j -@Component -public class GroundLockDataUploadStrategy implements AbstractYkcStrategy { - @Autowired - private RedisCache redisCache; - - @Autowired - private OrderPileOccupyService orderPileOccupyService; - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.GROUND_LOCK_DATA_UPLOAD_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===地锁数据上送===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - // 桩编码 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, 0, 7); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, 7, 1); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - /** - * 车位锁状态 - * 0x00:未到位状态 - * 0x55:升锁到位状态 - * 0xFF:降锁到位状态 - */ - byte[] parkingLockStatusByteArr = BytesUtil.copyBytes(msgBody, 8, 1); - // String parkingLockStatus = BytesUtil.bcd2Str(parkingLockStatusByteArr); - String parkingLockStatus = BytesUtil.bin2HexStr(parkingLockStatusByteArr).toUpperCase(Locale.ROOT); - String parkingLockStatusDesc = ParkingLockStatusEnum.getLabelByValue(parkingLockStatus); - - // 车位状态 0x00:无车辆 0xFF:停放车辆 - byte[] parkingStatusByteArr = BytesUtil.copyBytes(msgBody, 9, 1); - // String parkingStatus = BytesUtil.bcd2Str(parkingStatusByteArr); - String parkingStatus = BytesUtil.bin2HexStr(parkingStatusByteArr).toUpperCase(Locale.ROOT); - String parkingStatusDesc = ParkingStatusEnum.getLabelByValue(parkingStatus); - - // 地锁电量状态 百分比值0~100 - byte[] groundLockElectricByteArr = BytesUtil.copyBytes(msgBody, 10, 1); - String groundLockElectric = BytesUtil.bcd2Str(groundLockElectricByteArr); - - // 报警状态 0x00:正常无报警 0xFF:待机状态摇臂破坏 0x55:摇臂升降异常(未到位) - byte[] alarmStatusByteArr = BytesUtil.copyBytes(msgBody, 11, 1); - // String alarmStatus = BytesUtil.bcd2Str(alarmStatusByteArr); - String alarmStatus = BytesUtil.bin2HexStr(alarmStatusByteArr).toUpperCase(Locale.ROOT); - String alarmStatusDesc = ParkingLockAlarmEnum.getLabelByValue(alarmStatus); - - // 预留位 全部置0 - byte[] waitingUseByteArr = BytesUtil.copyBytes(msgBody, 12, 4); - String waitingUse = BytesUtil.bcd2Str(waitingUseByteArr); - - if (StringUtils.equals(parkingLockStatus, ParkingLockStatusEnum.LOCKED_RAISED.getValue())) { - if (StringUtils.equals(parkingStatus, ParkingStatusEnum.NO_VEHICLES.getValue())) { - try { - raiseTheGroundLock(pileSn, connectorCode); - }catch (Exception e) { - log.error("升锁逻辑error,", e); - } - } - } else if (StringUtils.equals(parkingLockStatus, ParkingLockStatusEnum.LOCKED_LOWERED.getValue())) { - if (StringUtils.equals(parkingStatus, ParkingStatusEnum.PARKED_VEHICLES.getValue())) { - try { - lowerTheGroundLock(pileSn, connectorCode); - }catch (Exception e) { - log.error("降锁逻辑error,", e); - } - } - } - - // 封装到对象中 - GroundLockData data = GroundLockData.builder() - .pileSn(pileSn) - .connectorCode(connectorCode) - .parkingLockStatus(parkingLockStatus) - .parkingStatus(parkingStatus) - .groundLockElectric(groundLockElectric) - .alarmStatus(alarmStatus) - .time(DateUtils.getDateTime()) - .build(); - - // 地锁信息放缓存中 缓存10分钟 - String redisKey = CacheConstants.GROUND_LOCK_DATA + pileSn + connectorCode; - redisCache.setCacheObject(redisKey, data, CacheConstants.cache_expire_time_10m); - - log.info("[===地锁数据上送===] result: 桩编码:{}, 枪号:{}, 车位锁状态:{}, 车位锁状态描述:{}, 车位状态:{}, 车位状态描述:{}, 地锁电量状态:{}, 报警状态:{}, 报警状态描述:{}", - pileSn, connectorCode, parkingLockStatus, parkingLockStatusDesc, parkingStatus, parkingStatusDesc, groundLockElectric, alarmStatus, alarmStatusDesc); - return null; - } - - /** - * 降锁成功的时候调用 - */ - private void lowerTheGroundLock(String pileSn, String connectorCode) { - // 查出草稿单占桩订单,将开始时间set进订单信息 - OrderPileOccupy orderInfo = orderPileOccupyService.getDraftOccupyOrder(pileSn, connectorCode); - if (orderInfo == null) { - return; - } - if (Objects.isNull(orderInfo.getStartTime())) { - orderInfo.setStatus(OccupyOrderStatusEnum.OCCUPIED.getCode()); - orderInfo.setStartTime(DateUtils.getNowDate()); - orderInfo.setPayStatus(OccupyOrderPayStatusEnum.UN_PAY.getCode()); - // 修改数据库 - log.info("降锁成功,修改订单状态:{}", JSON.toJSONString(orderInfo)); - orderPileOccupyService.updateByPrimaryKeySelective(orderInfo); - } - } - - /** - * 升锁成功时调用 - */ - private void raiseTheGroundLock(String pileSn, String connectorCode) { - // 两种情况 1是没有停车,地锁自动升起;2是停车完成地锁升起 - // boolean stopCarFlag = true; - - // 获取现在缓存中占桩订单编号 - String redisKey = CacheConstants.GROUND_LOCK_OCCUPY_ORDER + pileSn + connectorCode; - String occupyCode = redisCache.getCacheObject(redisKey); - if (StringUtils.isBlank(occupyCode)) { - log.info("桩号:{}, 枪口:{}未查询到占桩订单", pileSn, connectorCode); - return; - } - // 根据占桩订单号查询订单信息 - OrderPileOccupy orderPileOccupy = orderPileOccupyService.queryByOccupyCode(occupyCode); - String orderStatus = orderPileOccupy.getStatus(); - if (StringUtils.equals(OccupyOrderStatusEnum.DRAFT_ORDER.getCode(), orderStatus)) { - // 草稿单,关闭占桩订单 - orderPileOccupyService.closeOccupyPileOrder(pileSn, connectorCode); - }else { - // 占桩订单,停止占桩订单计时 - orderPileOccupyService.stopOccupyPileOrder(pileSn, connectorCode); - } - - String occupyOrderKey = CacheConstants.GROUND_LOCK_OCCUPY_ORDER + pileSn + connectorCode; - redisCache.deleteObject(occupyOrderKey); - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/HeartbeatRequestStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/HeartbeatRequestStrategy.java deleted file mode 100644 index 294f4c88c..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/HeartbeatRequestStrategy.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.google.common.primitives.Bytes; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.core.domain.ykc.device2platform.Data0x03; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.service.PileBasicInfoService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电桩心跳包 - */ -@Slf4j -@Component -public class HeartbeatRequestStrategy implements AbstractYkcStrategy { - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.HEART_BEAT_CODE.getBytes()); - - @Autowired - private PileBasicInfoService pileBasicInfoService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { - Data0x03 data0x03 = new Data0x03(ykcDataProtocol.getBytes()); - data0x03.setChannelId(ctx.channel().id()); - log.info("Data0x03:{}, ", data0x03); - String pileSn = data0x03.getPileSn(); - String connectorCode = data0x03.getConnectorCode(); - String connectorStatus = data0x03.getConnectorStatus(); - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, ctx); - - // 公共方法修改状态 - try { - pileBasicInfoService.updateStatus(BytesUtil.bcd2Str(ykcDataProtocol.getFrameType()), pileSn, connectorCode, connectorStatus, null); - } catch (Exception e) { - log.error("公共方法修改状态error", e); - } - - // 心跳应答(置0) - byte[] flag = Constants.zeroByteArray; - - // 消息体 - byte[] messageBody = Bytes.concat(YKCUtils.getPileSnBytes(pileSn), YKCUtils.getPileSnBytes(connectorCode), flag); - return YKCUtils.getResult(ykcDataProtocol, messageBody); - } - -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginStrategy.java deleted file mode 100644 index b3f1bbc7c..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginStrategy.java +++ /dev/null @@ -1,231 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.google.common.collect.Lists; -import com.google.common.primitives.Bytes; -import com.jsowell.common.annotation.CostTime; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.core.domain.ykc.device2platform.Data0x01; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.common.util.spring.SpringUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.PileBasicInfo; -import com.jsowell.pile.domain.ykcCommond.IssueQRCodeCommand; -import com.jsowell.pile.domain.ykcCommond.ProofreadTimeCommand; -import com.jsowell.pile.domain.ykcCommond.PublishPileBillingTemplateCommand; -import com.jsowell.pile.service.PileBasicInfoService; -import com.jsowell.pile.service.PileBillingTemplateService; -import com.jsowell.pile.service.PileMsgRecordService; -import com.jsowell.pile.service.YKCPushCommandService; -import com.jsowell.pile.vo.web.BillingTemplateVO; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -@Slf4j -@Service -public class LoginStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.LOGIN_CODE.getBytes()); - - @Autowired - private PileBasicInfoService pileBasicInfoService; - - @Autowired - private YKCPushCommandService ykcPushCommandService; - - @Autowired - private PileMsgRecordService pileMsgRecordService; - - @Autowired - private PileBillingTemplateService pileBillingTemplateService; - - private List newProgramVersionList = Lists.newArrayList("c6-30"); - - // 引入线程池 - private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); - - @PostConstruct - public void init() { - // log.info("类名:{}", this.getClass().getSimpleName()); - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - // log.info("注册成功, operationMap:{}", YKCOperateFactoryV2.getOperationMap()); - } - - // public static void main(String[] args) { - // String msg = "8800000000009000020f56312e323035303000898604940121c138531304"; - // byte[] msgBody = BytesUtil.str2Bcd(msg); - // - // int startIndex = 0; - // int length = 7; - // - // // 桩编码 - // byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); - // String pileSn = BytesUtil.binary(pileSnByte, 16); - // // log.info("桩号:{}", pileSn); - // - // // 桩类型 0 表示直流桩, 1 表示交流桩 - // startIndex += length; - // length = 1; - // byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String pileType = BytesUtil.bcd2Str(pileTypeByteArr); - // - // // 充电枪数量 - // startIndex += length; - // byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String connectorNum = BytesUtil.bcd2Str(connectorNumByteArr); - // - // // 通信协议版本 版本号乘 10,v1.0 表示 0x0A - // startIndex += length; - // byte[] communicationVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // // int i = Integer.parseInt(BytesUtil.bcd2Str(communicationVersionByteArr)); // 0F --> 15 - // BigDecimal bigDecimal = new BigDecimal(BytesUtil.bcd2Str(communicationVersionByteArr)); - // BigDecimal communicationVersionTemp = bigDecimal.divide(new BigDecimal(10)); - // String communicationVersion = "v" + communicationVersionTemp; - // - // // 程序版本 - // startIndex += length; - // length = 8; - // byte[] programVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String programVersion = BytesUtil.ascii2Str(programVersionByteArr); - // log.info("程序版本:{} length:{}", programVersion, programVersion.length()); - // - // // 网络连接类型 0x00 SIM 卡 0x01 LAN 0x02 WAN 0x03 其他 - // startIndex += length; - // length = 1; - // byte[] internetConnectionTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String internetConnection = BytesUtil.bcd2Str(internetConnectionTypeByteArr); - // - // // sim卡 - // startIndex += length; - // length = 10; - // byte[] simCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String iccid = BytesUtil.bin2HexStr(simCardNumByteArr); - // - // // 运营商 0x00 移动 0x02 电信 0x03 联通 0x04 其他 - // startIndex += length; - // length = 1; - // byte[] businessTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String business = BytesUtil.bcd2Str(businessTypeByteArr); - // } - - @CostTime - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { - if (verifyTheDuplicateRequest(ykcDataProtocol, ctx)) { - // 阻止重复帧 - return null; - } - - Data0x01 data0x01 = new Data0x01(ykcDataProtocol.getBytes()); - data0x01.setChannelId(ctx.channel().id()); - log.info("data0x01:{}", data0x01); - - // *********************** 字段解析完成,下面进行逻辑处理 *********************** // - String pileSn = data0x01.getPileSn(); - String iccid = data0x01.getIccid(); - String internetConnection = data0x01.getInternetConnection(); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, ctx); - - // 结果(默认 0x01:登录失败) - byte[] flag = Constants.oneByteArray; - - // 通过桩编码SN查询数据库,如果有数据,则登录成功,否则登录失败 - PileBasicInfo pileBasicInfo = null; - try { - pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); - } catch (Exception e) { - log.error("selectPileBasicInfoBySN发生异常", e); - } - - if (pileBasicInfo != null) { - flag = Constants.zeroByteArray; - - // 异步修改充电桩状态 - CompletableFuture.runAsync(() -> { - try { - // 更改桩和该桩下的枪口状态分别为 在线、空闲 公共方法修改状态 - pileBasicInfoService.updateStatus(BytesUtil.bcd2Str(ykcDataProtocol.getFrameType()), pileSn, null, null, null); - } catch (Exception e) { - e.printStackTrace(); - } - }, executor); - - // 异步发送对时指令 - CompletableFuture.runAsync(() -> { - try { - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // 对时 - ProofreadTimeCommand command = ProofreadTimeCommand.builder().pileSn(pileSn).build(); - ykcPushCommandService.pushProofreadTimeCommand(command); - }, executor); - - // log.info("下面进行下发二维码 pileSn:{}, thread:{}", pileSn, Thread.currentThread().getName()); - // 异步发送下发二维码指令 - CompletableFuture.runAsync(() -> { - try { - Thread.sleep(600); - } catch (InterruptedException e) { - e.printStackTrace(); - } - // 下发二维码 - IssueQRCodeCommand issueQRCodeCommand = IssueQRCodeCommand.builder().pileSn(pileSn).build(); - ykcPushCommandService.pushIssueQRCodeCommand(issueQRCodeCommand); - }, executor); - - // 异步发送0x58 - CompletableFuture.runAsync(() -> { - // 查询计费模板 - BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); - PublishPileBillingTemplateCommand command = PublishPileBillingTemplateCommand.builder() - .pileSn(pileSn) - .billingTemplateVO(billingTemplateVO) - .build(); - // 发送请求 - ykcPushCommandService.pushPublishPileBillingTemplate(command); - }, executor); - - if (StringUtils.equals("00", internetConnection)) { - CompletableFuture.runAsync(() -> { - // 充电桩使用的sim卡,把信息存库 - try { - // pileBasicInfoService.updatePileSimInfo(pileSn, iccid); - // pileBasicInfoService.updatePileSimInfoV2(pileSn, iccid); - pileBasicInfoService.bindPileSimCard(pileSn, iccid); - } catch (Exception e) { - log.error("更新充电桩sim卡信息失败pileSn:{}, iccid:{}", pileSn, iccid, e); - } - }, executor); - } - } - - // 异步保持登录报文 - CompletableFuture.runAsync(() -> { - // 保存报文 没有登录认证通过还要不要保存报文? - try { - String jsonMsg = JSON.toJSONString(data0x01); - // pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString()); - } catch (Exception e) { - log.error("保存报文失败pileSn:{}", pileSn, e); - } - }, executor); - - // 消息体 - byte[] messageBody = Bytes.concat(YKCUtils.getPileSnBytes(pileSn), flag); - return YKCUtils.getResult(ykcDataProtocol, messageBody); - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataCleaningStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataCleaningStrategy.java deleted file mode 100644 index d630f8ec4..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataCleaningStrategy.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 离线卡数据清除应答 - * - * @author JS-ZZA - * @date 2022/9/27 9:59 - */ -@Slf4j -@Component -public class OfflineCardDataCleaningStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.OFFLINE_CARD_DATA_CLEANING_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===离线卡数据清除应答===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编码 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 第 1 个卡物理卡号 - startIndex += length; - length = 8; - byte[] firstCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 清除标记 0x00 清除失败 0x01 清除成功 - startIndex += length; - length = 1; - byte[] cleanFlagByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 失败原因 0x01 卡号格式错误 0x02 清除成功 - startIndex += length; - byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 第N个物理卡号 - - // 清除标记 - - // 失败原因 - - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataQueryStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataQueryStrategy.java deleted file mode 100644 index d0defc20f..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataQueryStrategy.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 离线卡数据查询应答 - * - * @author JS-ZZA - * @date 2022/9/27 10:20 - */ -@Slf4j -@Component -public class OfflineCardDataQueryStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.OFFLINE_CARD_DATA_QUERY_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===离线卡数据查询应答===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 第1个卡物理卡号 - startIndex += length; - length = 8; - byte[] firstCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 查询结果 - startIndex += length; - length = 1; - byte[] firstCardResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 第N+1个卡物理卡号 - // 查询结果 - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataSyncStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataSyncStrategy.java deleted file mode 100644 index b886db88b..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/OfflineCardDataSyncStrategy.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 离线卡数据同步应答 - * - * @author JS-ZZA - * @date 2022/9/27 9:31 - */ -@Slf4j -@Component -public class OfflineCardDataSyncStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.OFFLINE_CARD_DATA_SYNCHRONIZATION_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===离线卡数据同步应答===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - //消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编码 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 保存结果 0x00 失败 0x01 成功 - startIndex += length; - length = 1; - byte[] resultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - // 失败原因 0x01 卡号格式错误 0x02 储存空间不足 - startIndex += length; - byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ParameterConfigStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ParameterConfigStrategy.java deleted file mode 100644 index 6958c1410..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ParameterConfigStrategy.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.service.OrderBasicInfoService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Objects; - -/** - * 参数配置 Handler - * - * GBT-27930 充电桩与 BMS 参数配置阶段报文 - * @author JS-ZZA - * @date 2022/9/19 13:24 - */ -@Slf4j -@Component -public class ParameterConfigStrategy implements AbstractYkcStrategy { - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.PARAMETER_CONFIGURATION_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===参数配置===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileConnectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); - - // BMS 单体动力蓄电池最高允许充电电压 0.01 V/位, 0 V 偏移量; 数据范围: 0~24 V - startIndex += length; - length = 2; - byte[] BMSMaxVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String BMSMaxVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxVoltageByteArr) * 0.01); - - // BMS 最高允许充电电流 0.1 A/位, -400A 偏移量 - startIndex += length; - byte[] BMSMaxCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String BMSMaxCurrent = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxCurrentByteArr) * 0.1 - 400); - - // BMS 动力蓄电池标称总能量 0.1 kWh/位, 0 kWh 偏移量; 数据范围: 0~1000 kWh - startIndex += length; - byte[] BMSSumEnergyByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String BMSSumEnergy = String.valueOf(BytesUtil.bytesToIntLittle(BMSSumEnergyByteArr) * 0.1); - - // BMS 最高允许充电总电压 0.1 V/位, 0 V 偏移量 - startIndex += length; - byte[] BMSMaxChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String BMSMaxChargingVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxChargingVoltageByteArr) * 0.1); - - // BMS 最高允许温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC - startIndex += length; - length = 1; - byte[] BMSMaxTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String BMSMaxTemperature = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxTemperatureByteArr) - 50); - - // BMS 整车动力 蓄电池荷电状态(soc) 0.1%/位, 0%偏移量;数据范围: 0~100% - startIndex += length; - length = 2; - byte[] BMSSocByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String soc = YKCUtils.convertVoltageCurrent(BMSSocByteArr); - - // BMS 整车动力蓄电池当前电池电压 整车动力蓄电池总电压 - startIndex += length; - byte[] BMSRealTimeVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String BMSRealTimeVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSRealTimeVoltageByteArr) * 0.1); - - // 电桩最高输出电压 0.1 V /位, 0 V 偏移量 - startIndex += length; - byte[] pileMaxOutputVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileMaxOutputVoltage = String.valueOf(BytesUtil.bytesToIntLittle(pileMaxOutputVoltageByteArr) * 0.1); - - // 电桩最低输出电压 0.1 V /位, 0 V 偏移量 - startIndex += length; - byte[] pileMinOutputVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileMinOutputVoltage = String.valueOf(BytesUtil.bytesToIntLittle(pileMinOutputVoltageByteArr) * 0.1); - - // 电桩最大输出电流 0.1 A/位, -400 A 偏移量 - startIndex += length; - byte[] pileMaxOutputCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileMaxOutputCurrent = String.valueOf(BytesUtil.bytesToIntLittle(pileMaxOutputCurrentByteArr) * 0.1 - 400); - - // 电桩最小输出电流 0.1 A/位, -400 A 偏移量 - startIndex += length; - byte[] pileMinOutputCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileMinOutputCurrent = String.valueOf(BytesUtil.bytesToIntLittle(pileMinOutputCurrentByteArr) * 0.1 - 400); - - // 查询该订单下信息,将起始soc传入 - OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - if (Objects.nonNull(orderInfo)) { - OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() - .id(orderInfo.getId()) - .startSoc(soc) - .build(); - orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); - log.info("更新订单起始SOC, orderCode:{}, transactionCode:{}, startSoc:{}", orderInfo.getOrderCode(), transactionCode, soc); - } - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/PileWorkingParameterSettingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/PileWorkingParameterSettingStrategy.java deleted file mode 100644 index 6d244ddc9..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/PileWorkingParameterSettingStrategy.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 充电桩工作参数设置应答 - * - * @author JS-ZZA - * @date 2022/9/27 10:40 - */ -@Slf4j -@Component -public class PileWorkingParameterSettingStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGING_PILE_WORKING_PARAMETER_SETTING_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电桩工作参数设置应答===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 设置结果 - startIndex += length; - length = 1; - byte[] settingResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/QueryPileWorkParamsStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/QueryPileWorkParamsStrategy.java deleted file mode 100644 index 7e8b4c4e3..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/QueryPileWorkParamsStrategy.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 0x27 充电桩査询工作参数回复 - * - * @author JS-ZZA - * @date 2023/4/4 10:06 - */ -@Slf4j -@Component -public class QueryPileWorkParamsStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.QUERY_PILE_WORK_PARAMS_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[====充电桩査询工作参数回复====] param:{}", JSON.toJSONString(ykcDataProtocol)); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编码 - byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.binary(pileSnByte, 16); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 充电桩类型 0x00:直流0x01:交流 - startIndex += length; - length = 1; - byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileType = BytesUtil.bcd2Str(pileTypeByteArr); - - // 最高充电电压 精确到小数点后一位;待机置零 - startIndex += length; - length = 2; - byte[] maxChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String maxChargingVoltage = YKCUtils.convertVoltageCurrent(maxChargingVoltageByteArr); - - // 最高充电电流 - startIndex += length; - byte[] maxChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String maxChargingCurrent = YKCUtils.convertVoltageCurrent(maxChargingCurrentByteArr); - - // 最大充电功率 - startIndex += length; - byte[] maxChargingPowerByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String maxChargingPower = YKCUtils.convertVoltageCurrent(maxChargingPowerByteArr); - - // 当前充电电压 - startIndex += length; - byte[] instantChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String instantChargingVoltage = YKCUtils.convertVoltageCurrent(instantChargingVoltageByteArr); - - // 当前充电电流 - startIndex += length; - byte[] instantChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String instantChargingCurrent = YKCUtils.convertVoltageCurrent(instantChargingCurrentByteArr); - - // 当前充电功率 - startIndex += length; - byte[] instantChargingPowerByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String instantChargingPower = YKCUtils.convertVoltageCurrent(instantChargingPowerByteArr); - - log.info("[====充电桩査询工作参数回复====] 桩编号:{}, 充电桩类型:{}, 最大充电电压:{}, 最高充电电流:{}, " + - "最大充电功率:{}, 当前充电电压:{}, 当前充电电流:{}, 当前充电功率:{}", - pileSn, pileType, maxChargingVoltage, maxChargingCurrent, maxChargingPower, instantChargingVoltage, - instantChargingCurrent, instantChargingPower); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteControlGroundLockStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteControlGroundLockStrategy.java deleted file mode 100644 index 81e1e3f5e..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteControlGroundLockStrategy.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.service.OrderPileOccupyService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Locale; - -/** - * 充电桩返回遥控地锁升锁与降锁数据(上行) - * - * @author JS-ZZA - * @date 2022/9/27 13:21 - */ -@Slf4j -@Component -public class RemoteControlGroundLockStrategy implements AbstractYkcStrategy { - - @Autowired - private OrderPileOccupyService orderPileOccupyService; - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_CONTROL_GROUND_LOCK_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===充电桩返回遥控地锁升锁与降锁数据(上行)===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // 升/降地锁标识 升锁 0X55,降锁 0XFF - startIndex += length; - byte[] raiseLowMarkingByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String raiseLowMarking = BytesUtil.bin2HexStr(raiseLowMarkingByteArr).toUpperCase(Locale.ROOT); - - // 地锁控制返回标志 布尔型( 1, 鉴权成功; 0, 鉴权失败) - startIndex += length; - byte[] controlResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String controlResult = BytesUtil.bcd2Str(controlResultByteArr); - - // 预留位 - startIndex += length; - length = 4; - byte[] waitingUseByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - log.info("===充电桩返回遥控地锁升锁与降锁数据(上行)=== result: 桩编号:{}, 枪号:{}, 升/降地锁标识:{}, 地锁控制返回标志:( 1, 鉴权成功; 0, 鉴权失败){}", - pileSn, connectorCode,raiseLowMarking, controlResult); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteIssuedQrCodeStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteIssuedQrCodeStrategy.java deleted file mode 100644 index 5be265a5f..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteIssuedQrCodeStrategy.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 桩应答远程下发二维码前缀指令 - * - * @author JS-ZZA - * @date 2022/9/29 14:10 - */ -@Slf4j -@Component -public class RemoteIssuedQrCodeStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_ISSUE_QRCODE_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===桩应答远程下发二维码前缀指令===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编码 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 下发结果 0x00:成功 0x01:失败 - startIndex += length; - length = 1; - byte[] issuedResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteRestartStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteRestartStrategy.java deleted file mode 100644 index e8af48759..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteRestartStrategy.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.service.PileMsgRecordService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 远程重启应答 - * - * @author JS-ZZA - * @date 2022/9/27 13:27 - */ -@Slf4j -@Component -public class RemoteRestartStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_RESTART_ANSWER_CODE.getBytes()); - - @Autowired - private PileMsgRecordService pileMsgRecordService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===远程重启应答===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 保存报文 - String jsonMsg = JSON.toJSONString(ykcDataProtocol); - // pileMsgRecordService.save(pileSn, null, type, jsonMsg, ykcDataProtocol.getHEXString()); - - // 设置结果 - startIndex += length; - length = 1; - byte[] settingResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStartChargingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStartChargingStrategy.java deleted file mode 100644 index c50325824..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStartChargingStrategy.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.constant.Constants; -import com.jsowell.common.constant.mq.ThirdPartyRabbitConstants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.enums.ykc.ChargingFailedReasonEnum; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.common.util.spring.SpringUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.service.OrderBasicInfoService; -import com.jsowell.thirdparty.common.CommonService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.concurrent.CompletableFuture; - -/** - * 远程启动充电命令回复 0x33, 0x34 - * - * @author JS-ZZA - * @date 2022/9/19 14:35 - */ -@Slf4j -@Component -public class RemoteStartChargingStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_CONTROL_START_CHARGING_ANSWER_CODE.getBytes()); - - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - @Autowired - private CommonService commonService; - - @Autowired - private RabbitTemplate rabbitTemplate; - - // 引入线程池 - private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===远程启动充电命令回复===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // 启动结果 0x00失败 0x01成功 - startIndex += length; - byte[] startResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String startResult = BytesUtil.bcd2Str(startResultByteArr); - - /** - * 失败原因 - * - * 桩在收到启充命令后,检测到未插枪则发送 0x33 报文回复充电失败。 - * 若在 60 秒(以收到 0x34 时间开始计算)内检测到枪重新连接,则补送 0x33 成功报文;超时或者离线等其他异常,桩不启充、不补发 0x33 报文 - * 0x00 无 - * 0x01 设备编号不匹配 - * 0x02 枪已在充电 - * 0x03 设备故障 - * 0x04 设备离线 - * 0x05 未插枪 - */ - startIndex += length; - byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String failedReason = BytesUtil.bin2HexStr(failedReasonByteArr); - String failedReasonMsg = ChargingFailedReasonEnum.getMsgByCode(Integer.parseInt(failedReason, 16)); - - if (StringUtils.equals(startResult, Constants.DOUBLE_ZERO)) { - // 启动失败 682204000001000000000041 - orderBasicInfoService.chargingPileFailedToStart(transactionCode, failedReasonMsg); - } else { - // 启动成功 - orderBasicInfoService.chargingPileStartedSuccessfully(transactionCode); - } - // orderBasicInfoService.updateOrderBasicInfo(orderInfo); - log.info("远程启动充电命令回复-交易流水号:{}, 桩编码:{}, 枪号:{}, 启动结果(00-失败, 01-成功):{}, 失败原因:{}", transactionCode, pileSn, connectorCode, startResult, failedReasonMsg); - - // 异步推送第三方平台 -// CompletableFuture.runAsync(() -> { -// OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); -// if (orderInfo == null) { -// return; -// } -// try { -// // 启动结果回复 -// commonService.commonPushStartChargeResult(orderInfo); -// -// } catch (Exception e) { -// e.printStackTrace(); -// } -// // 启动失败, 推送第三方订单信息 -// if (StringUtils.equals(startResult, Constants.DOUBLE_ZERO)) { -// try { -// Thread.sleep(500); -// commonService.commonPushOrderInfo(orderInfo); -// } catch (Exception e) { -// log.error("统一推送第三方平台订单信息error, ", e); -// } -// } -// }, executor); - // Todo 待完善 - CompletableFuture.runAsync(() -> { - OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - if (orderInfo == null) { - return; - } - if (StringUtils.equals(startResult, Constants.DOUBLE_ZERO)){ - // 启动失败, 推送第三方订单信息 - try { - Thread.sleep(500); - rabbitTemplate.convertAndSend(ThirdPartyRabbitConstants.WCC_THIRDPARTY_NAME, ThirdPartyRabbitConstants.ROUTING_KEY_STARTUP_CHARGING_FAILED_PUSH, orderInfo); - } catch (Exception e) { - log.error("统一推送第三方平台订单信息error, ", e); - } - } - }, executor); - - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStopChargingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStopChargingStrategy.java deleted file mode 100644 index 377e7f040..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteStopChargingStrategy.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.enums.ykc.OrderStatusEnum; -import com.jsowell.common.enums.ykc.StopChargingFailedReasonEnum; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.service.OrderBasicInfoService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; - -/** - * 远程停机命令回复 - * - * @author JS-ZZA - * @date 2022/9/19 14:37 - */ -@Slf4j -@Component -public class RemoteStopChargingStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_CONTROL_STOP_CHARGING_ANSWER_CODE.getBytes()); - - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===远程停机命令回复===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // 停止结果 0x00失败 0x01成功 - startIndex += length; - byte[] stopResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String stopResult = BytesUtil.bcd2Str(stopResultByteArr); - - /** - * 失败原因 - * 0x00 无 - * 0x01 设备编号不匹配 - * 0x02 枪未处于充电状态 - * 0x03 其他 - */ - startIndex += length; - byte[] reasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String reasonCode = BytesUtil.bcd2Str(reasonByteArr); - String reason = StopChargingFailedReasonEnum.getMsgByCode(reasonCode); - - // 通过桩编号+枪口号 查出订单 - OrderBasicInfo order = orderBasicInfoService.queryChargingByPileSnAndConnectorCode(pileSn, connectorCode); - if (order != null) { - // 收到停机回复后,修改订单状态 - if (StringUtils.equals(stopResult, "01")) { - // 停机成功,修改订单状态为 待结算 - order.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue()); - if (order.getChargeEndTime() == null) { - order.setChargeEndTime(new Date()); // 结束充电时间 - } - } else { - // 停机失败,修改订单状态为 异常 - order.setOrderStatus(OrderStatusEnum.ABNORMAL.getValue()); - order.setReason(reason); - } - orderBasicInfoService.updateOrderBasicInfo(order); - } - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteUpdateStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteUpdateStrategy.java deleted file mode 100644 index 46ea1eb1a..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/RemoteUpdateStrategy.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 远程更新应答 - * - * @author JS-ZZA - * @date 2022/9/27 13:32 - */ -@Slf4j -@Component -public class RemoteUpdateStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_UPDATE_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[====远程更新应答====] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, 0, 7); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 升级状态 0x00-成功 0x01-编号错误 0x02-程序与桩型号不符 0x03-下载更新文件超时 - startIndex += length; - length = 1; - byte[] updateStatusByteArr = BytesUtil.copyBytes(msgBody, 7, 1); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStartupResultStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStartupResultStrategy.java deleted file mode 100644 index 50e062427..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStartupResultStrategy.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.google.common.primitives.Bytes; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.enums.ykc.ChargingFailedReasonEnum; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.dto.ReservationChargingStartupResult; -import com.jsowell.pile.service.PileBasicInfoService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 0x65预约充电启动结果上送 - */ -@Slf4j -@Component -public class ReservationChargingStartupResultStrategy implements AbstractYkcStrategy { - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.RESERVATION_CHARGING_STARTUP_RESULT_CODE.getBytes()); - - @Autowired - private PileBasicInfoService pileBasicInfoService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - public static void main(String[] args) { - // 获取消息体 - String msg = "8823000000071801240823102300000088230000000718010190"; - byte[] msgBody = BytesUtil.str2Bcd(msg); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] transactionCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(transactionCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // vin - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String vinCode = YKCUtils.parseVin(vinCodeByteArr); // 解析vin - - // 启动结果 0x00失败 0x01成功 - startIndex += length; - length = 1; - byte[] startupResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String startupResult = BytesUtil.bcd2Str(startupResultByteArr); - String startupResultMsg = StringUtils.equals(startupResult, "00") ? "失败" : "成功"; - - // 失败原因 - startIndex += length; - length = 1; - byte[] failReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String failReason = BytesUtil.bcd2Str(failReasonByteArr); - String failReasonMsg = ChargingFailedReasonEnum.getMsgByCode(Integer.parseInt(failReason, 16)); - - log.info("[===预约充电启动结果上送===]交易流水号:{}, 桩编号:{}, 枪号:{}, vin:{}, 启动结果:{}, 失败原因:{}", - transactionCode, pileSn, connectorCode, vinCode, startupResult + "-" +startupResultMsg, failReasonMsg); - - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - log.info("[===预约充电启动结果上送===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] transactionCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(transactionCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // vin - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String vinCode = YKCUtils.parseVin(vinCodeByteArr); // 解析vin - - // 启动结果 0x00失败 0x01成功 - startIndex += length; - length = 1; - byte[] startupResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String startupResult = BytesUtil.bcd2Str(startupResultByteArr); - String startupResultMsg = StringUtils.equals(startupResult, "00") ? "失败" : "成功"; - - // 失败原因 - startIndex += length; - length = 1; - byte[] failReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String failReason = BytesUtil.bcd2Str(failReasonByteArr); - String failReasonMsg = ChargingFailedReasonEnum.getMsgByCode(Integer.parseInt(failReason, 16)); - - log.info("[===预约充电启动结果上送===]交易流水号:{}, 桩编号:{}, 枪号:{}, vin:{}, 启动结果:{}, 失败原因:{}", - transactionCode, pileSn, connectorCode, vinCode, startupResult + "-" +startupResultMsg, failReasonMsg); - /* - 应答 - 确认结果 0x00 成功 0x01 失败 - */ - byte[] confirmResultBytes = Constants.zeroByteArray; - try { - ReservationChargingStartupResult chargingStartupResult = ReservationChargingStartupResult.builder() - .transactionCode(transactionCode) - .pileSn(pileSn) - .connectorCode(connectorCode) - .vinCode(vinCode) - .startupResult(startupResult) - .failReason(failReasonMsg) - .build(); - pileBasicInfoService.startupResult(chargingStartupResult); - } catch (Exception e) { - log.error("预约充电启动结果上送error", e); - confirmResultBytes = Constants.oneByteArray; - } - - byte[] concatMsgBody = Bytes.concat(transactionCodeByteArr, pileSnByteArr, connectorCodeByteArr, confirmResultBytes); - return YKCUtils.getResult(ykcDataProtocol, concatMsgBody); - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStrategy.java deleted file mode 100644 index 195b8cb9b..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/ReservationChargingStrategy.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.jsowell.common.constant.CacheConstants; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.core.redis.RedisCache; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.PileReservationInfo; -import com.jsowell.pile.service.PileReservationInfoService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 预约充电响应 - */ -@Slf4j -@Component -public class ReservationChargingStrategy implements AbstractYkcStrategy { - - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.RESERVATION_CHARGING_SETUP_ANSWER_CODE.getBytes()); - - @Autowired - private RedisCache redisCache; - - @Autowired - private PileReservationInfoService pileReservationInfoService; - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[====远程更新应答====] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] transactionCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(transactionCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪口号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - // 启动结果 0x00失败 0x01成功 - startIndex += length; - length = 1; - byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String resultCode = BytesUtil.bcd2Str(resultCodeByteArr); - - // 失败原因 - startIndex += length; - length = 1; - byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String failedReason = BytesUtil.bcd2Str(failedReasonByteArr); - - log.info("0x59预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果:{}, 失败原因:{}", - transactionCode, pileSn, connectorCode, resultCode, failedReason); - - // 如果收到成功, 从redis取值, 保存到数据库 - if ("01".equals(resultCode)) { - // 预约成功, 删除redis中的预约信息 - String redisKey = CacheConstants.UPDATE_RESERVATION_INFO + pileSn + connectorCode; - String cacheObject = redisCache.getCacheObject(redisKey); - log.info("预约充电-收到成功, redisKey:{}, result:{}", redisKey, cacheObject); - if (cacheObject != null) { - log.info("修改预约充电相应成功, 更新数据库"); - PileReservationInfo pileReservationInfo = JSON.parseObject(cacheObject, PileReservationInfo.class); - pileReservationInfoService.insertOrUpdateSelective(pileReservationInfo); - } - } - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/SettingPileWorkParamsStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/SettingPileWorkParamsStrategy.java deleted file mode 100644 index abef07fb0..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/SettingPileWorkParamsStrategy.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 0x29 平台设置工作参数回复 - * - * @author JS-ZZA - * @date 2023/4/4 13:43 - */ -@Component -@Slf4j -public class SettingPileWorkParamsStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.SETTING_PILE_WORK_PARAMS_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[====平台设置工作参数回复====] param:{}", JSON.toJSONString(ykcDataProtocol)); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编码 - byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.binary(pileSnByte, 16); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 设置状态 0x00-成功 0x01-失败 - startIndex += length; - length = 1; - byte[] settingStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String settingStatus = BytesUtil.bcd2Str(settingStatusByteArr); - - // 充电桩类型 0x00:直流 0x01:交流 - startIndex += length; - byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileType = BytesUtil.bcd2Str(pileTypeByteArr); - - // 最高充电电压 精确到小数点后一位;待机置零 - startIndex += length; - length = 2; - byte[] maxChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String maxChargingVoltage = YKCUtils.convertVoltageCurrent(maxChargingVoltageByteArr); - - // 最高充电电流 - startIndex += length; - byte[] maxChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String maxChargingCurrent = YKCUtils.convertVoltageCurrent(maxChargingCurrentByteArr); - - // 最大充电功率 - startIndex += length; - byte[] maxChargingPowerByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String maxChargingPower = YKCUtils.convertVoltageCurrent(maxChargingPowerByteArr); - - // 当前充电电压 - startIndex += length; - byte[] instantChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String instantChargingVoltage = YKCUtils.convertVoltageCurrent(instantChargingVoltageByteArr); - - // 当前充电电流 - startIndex += length; - byte[] instantChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String instantChargingCurrent = YKCUtils.convertVoltageCurrent(instantChargingCurrentByteArr); - - // 当前充电功率 - startIndex += length; - byte[] instantChargingPowerByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String instantChargingPower = YKCUtils.convertVoltageCurrent(instantChargingPowerByteArr); - - log.info("[====平台设置工作参数回复====] 桩编号:{}, 设置状态:{}, 充电桩类型:{}, 最大充电电压:{}, 最高充电电流:{}, " + - "最大充电功率:{}, 当前充电电压:{}, 当前充电电流:{}, 当前充电功率:{}", - pileSn, settingStatus, pileType, maxChargingVoltage, maxChargingCurrent, maxChargingPower, instantChargingVoltage, - instantChargingCurrent, instantChargingPower); - - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TimeCheckSettingStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TimeCheckSettingStrategy.java deleted file mode 100644 index 9321ca3f5..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TimeCheckSettingStrategy.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.Cp56Time2a.Cp56Time2aUtil; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; - -/** - * 对时设置应答 - * - * @author JS-ZZA - * @date 2022/9/27 11:09 - */ -@Slf4j -@Component -public class TimeCheckSettingStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.TIME_CHECK_SETTING_ANSWER_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - } - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===对时设置应答===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 7; - - // 桩编号 - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 当前时间 - startIndex += length; - length = 7; - byte[] currentTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date date = Cp56Time2aUtil.byte2Hdate(currentTimeByteArr); - log.info("对时设置应答, pileSn:{}, channelId:{}, 充电桩当前时间:{}", pileSn, channel.channel().id().asShortText(), DateUtils.formatDateTime(date)); - return null; - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TransactionRecordsStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TransactionRecordsStrategy.java deleted file mode 100644 index 1c661ca11..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/TransactionRecordsStrategy.java +++ /dev/null @@ -1,689 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.alibaba.fastjson2.JSON; -import com.google.common.primitives.Bytes; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.core.domain.ykc.TransactionRecordsData; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.core.redis.RedisCache; -import com.jsowell.common.enums.ykc.OrderStatusEnum; -import com.jsowell.common.enums.ykc.YKCChargingStopReasonEnum; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.Cp56Time2a.Cp56Time2aUtil; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.common.util.id.IdUtils; -import com.jsowell.common.util.spring.SpringUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.domain.PileBasicInfo; -import com.jsowell.pile.service.*; -import com.jsowell.pile.service.programlogic.AbstractProgramLogic; -import com.jsowell.pile.service.programlogic.ProgramLogicFactory; -import com.jsowell.thirdparty.common.CommonService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; -import java.util.Objects; - -/** - * 交易记录确认 - * 这一帧仅是报文交互使用, 意指平台成功接收到交易记录报文,并不代表交易订单成功结算 - * 运营平台接收到结算账单上传后,都需回复此确认信息。若桩未收到回复帧,则 5 分钟后继续 上送一次交易记录, - * 此情况下无论平台是否成功回复都停止上送。 - * - * @author JS-ZZA - * @date 2022/9/19 14:40 - */ -@Slf4j -@Component -public class TransactionRecordsStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes()); - private final String oldVersionType = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_OLD_VERSION_CODE.getBytes()); - - // 引入线程池 - private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - YKCOperateFactoryV2.register(oldVersionType, this.getClass().getSimpleName()); - } - - @Autowired - private RedisCache redisCache; - - @Autowired - private PileMsgRecordService pileMsgRecordService; - - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - @Autowired - private PileMerchantInfoService pileMerchantInfoService; - - @Autowired - private CommonService commonService; - - @Autowired - private PileBasicInfoService pileBasicInfoService; - - @Autowired - private PersonalChargingRecordService personalChargingRecordService; - - - /*public static void main(String[] args) { - BigDecimal totalElectricity = new BigDecimal("23.73"); - if (totalElectricity.compareTo(BigDecimal.TEN) > 0) { - // 充电度数大于10度 - System.out.println("123"); - } - - - // 获取消息体 - String msg = "000000000000000000000000000000008823000000030601a08c2e0d0404170000380d0404170000000000000000000000000000000000000000000000000000000000000000400d0300ee250000ee250000c84b000000000000000000000000000000000000e0bb040000cee1040000ee250000ee250000c84b00000000000000000000000000000000000000010000380d04041745a511101970000000"; - byte[] msgBody = BytesUtil.str2Bcd(msg); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - - // 开始时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String binary = BytesUtil.binary(startTimeByteArr, 16); - Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr); - String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate); - - - // 结束时间 CP56Time2a 格式 - startIndex += length; - byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr); - String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate); - - // 尖单价 精确到小数点后五位(尖电费+尖服务费,见费率帧) - startIndex += length; - length = 4; - byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5); - - // 尖电量 精确到小数点后四位 - startIndex += length; - length = 4; - byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4); - - // 计损尖电量 - startIndex += length; - byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4); - - // 尖金额 - startIndex += length; - byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4); - - // 峰单价 精确到小数点后五位(峰电费+峰服务费) - startIndex += length; - byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5); - - // 峰电量 - startIndex += length; - byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4); - - // 计损峰电量 - startIndex += length; - byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4); - - // 峰金额 - startIndex += length; - byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4); - - // 平单价 精确到小数点后五位(平电费+平服务费) - startIndex += length; - byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5); - - // 平电量 - startIndex += length; - byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4); - - // 计损平电量 - startIndex += length; - byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4); - - // 平金额 - startIndex += length; - byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4); - - // 谷单价 精确到小数点后五位(谷电费+谷 服务费) - startIndex += length; - byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5); - - // 谷电量 - startIndex += length; - byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4); - - // 计损谷电量 - startIndex += length; - byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4); - - // 谷金额 - startIndex += length; - byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4); - - // 电表总起值 - startIndex += length; - length = 5; - byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4); - - // 电表总止值 - startIndex += length; - byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4); - - // 总电量 - startIndex += length; - length = 4; - byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4); - - // 计损总电量 - startIndex += length; - byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4); - - // 消费金额 精确到小数点后四位,包含电费、 服务费 - startIndex += length; - byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4); - - // VIN 码 VIN 码,此处 VIN 码和充电时 VIN 码不同, 正序直接上传, 无需补 0 和反序 - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String vinCode = BytesUtil.ascii2Str(vinCodeByteArr); - - *//** - * 交易标识 - * 0x01: app 启动 - * 0x02:卡启动 - * 0x04:离线卡启动 - * 0x05: vin 码启动充电 - *//* - startIndex += length; - length = 1; - byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr); - - // 交易时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr); - String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate); - - // 停止原因 - startIndex += length; - length = 1; - byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr); - String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(Integer.parseInt(stopReason, 16)); - - // 物理卡号 不足 8 位补 0 - startIndex += length; - length = 8; - byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // byte[] logicCardNum = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16); - String logicCard = BytesUtil.binary(cardNumByteArr, 16); - log.info("桩号:{}, 发送交易记录物理卡号:{}", pileSn, logicCard); - - log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " + - "峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " + - "谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " + - "电动汽车唯一标识:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}", - transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount, - peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount, - valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity, - consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard); - - // 交易记录封装到对象里 - TransactionRecordsData data = TransactionRecordsData.builder() - // .orderCode(transactionCode) - .transactionCode(transactionCode) - .pileSn(pileSn) - .connectorCode(connectorCode) - .startTime(startTime) - .endTime(endTime) - .sharpPrice(sharpPrice) - .sharpUsedElectricity(sharpUsedElectricity) - .sharpPlanLossElectricity(sharpPlanLossElectricity) - .sharpAmount(sharpAmount) - .peakPrice(peakPrice) - .peakUsedElectricity(peakUsedElectricity) - .peakPlanLossElectricity(peakPlanLossElectricity) - .peakAmount(peakAmount) - .flatPrice(flatPrice) - .flatUsedElectricity(flatUsedElectricity) - .flatPlanLossElectricity(flatPlanLossElectricity) - .flatAmount(flatAmount) - .valleyPrice(valleyPrice) - .valleyUsedElectricity(valleyUsedElectricity) - .valleyPlanLossElectricity(valleyPlanLossElectricity) - .valleyAmount(valleyAmount) - .ammeterTotalStart(ammeterTotalStart) - .ammeterTotalEnd(ammeterTotalEnd) - // .totalElectricity(totalElectricity) - .planLossTotalElectricity(planLossTotalElectricity) - .consumptionAmount(consumptionAmount) - .vinCode(vinCode) - .transactionIdentifier(transactionIdentifier) - .transactionTime(transactionTime) - .stopReasonMsg(stopReasonMsg) - .logicCard(logicCard) - .build(); - - boolean flag = !StringUtils.equals("0000000000000000", "a511101970000000"); - System.out.println(flag); - - }*/ - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===交易记录===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] transactionCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(transactionCodeByteArr); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - - - // 开始时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // String binary = BytesUtil.binary(startTimeByteArr, 16); - Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr); - String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate); - - - // 结束时间 CP56Time2a 格式 - startIndex += length; - byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr); - String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate); - - // 尖单价 精确到小数点后五位(尖电费+尖服务费,见费率帧) - startIndex += length; - length = 4; - byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5); - - // 尖电量 精确到小数点后四位 - startIndex += length; - length = 4; - byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4); - - // 计损尖电量 - startIndex += length; - byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4); - - // 尖金额 - startIndex += length; - byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4); - - // 峰单价 精确到小数点后五位(峰电费+峰服务费) - startIndex += length; - byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5); - - // 峰电量 - startIndex += length; - byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4); - - // 计损峰电量 - startIndex += length; - byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4); - - // 峰金额 - startIndex += length; - byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4); - - // 平单价 精确到小数点后五位(平电费+平服务费) - startIndex += length; - byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5); - - // 平电量 - startIndex += length; - byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4); - - // 计损平电量 - startIndex += length; - byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4); - - // 平金额 - startIndex += length; - byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4); - - // 谷单价 精确到小数点后五位(谷电费+谷 服务费) - startIndex += length; - byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5); - - // 谷电量 - startIndex += length; - byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4); - - // 计损谷电量 - startIndex += length; - byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4); - - // 谷金额 - startIndex += length; - byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4); - - // 电表总起值 - startIndex += length; - length = 5; - byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4); - - // 电表总止值 - startIndex += length; - byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4); - - // 总电量 - startIndex += length; - length = 4; - byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4); - - // 计损总电量 - startIndex += length; - byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4); - - // 消费金额 精确到小数点后四位,包含电费、 服务费 - startIndex += length; - byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4); - - // VIN 码 VIN 码,此处 VIN 码和充电时 VIN 码不同, 正序直接上传, 无需补 0 和反序 - startIndex += length; - length = 17; - byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String vinCode = YKCUtils.parseVin(vinCodeByteArr); // 解析vin - - /** - * 交易标识 - * 0x01: app 启动 - * 0x02:卡启动 - * 0x04:离线卡启动 - * 0x05: vin 码启动充电 - */ - startIndex += length; - length = 1; - byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr); - - // 交易时间 CP56Time2a 格式 - startIndex += length; - length = 7; - byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr); - String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate); - - // 停止原因 - startIndex += length; - length = 1; - byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr); - int i = Integer.parseInt(stopReason, 16); - String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(i); - - // 物理卡号 不足 8 位补 0 - startIndex += length; - length = 8; - byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - // log.info("交易记录确认cardNumByteArr:{}", cardNumByteArr); - String logicCard = BytesUtil.binary(cardNumByteArr, 16); - // log.info("桩号:{}, 发送交易记录物理卡号:{}", pileSn, logicCard); - - log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " + - "峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " + - "谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " + - "vin码:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}", - transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount, - peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount, - valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity, - consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard); - - // 交易记录封装到对象里 - TransactionRecordsData data = TransactionRecordsData.builder() - // .orderCode(transactionCode) - .transactionCode(transactionCode) - .pileSn(pileSn) - .connectorCode(connectorCode) - .startTime(startTime) - .endTime(endTime) - .sharpPrice(sharpPrice) - .sharpUsedElectricity(sharpUsedElectricity) - .sharpPlanLossElectricity(sharpPlanLossElectricity) - .sharpAmount(sharpAmount) - .peakPrice(peakPrice) - .peakUsedElectricity(peakUsedElectricity) - .peakPlanLossElectricity(peakPlanLossElectricity) - .peakAmount(peakAmount) - .flatPrice(flatPrice) - .flatUsedElectricity(flatUsedElectricity) - .flatPlanLossElectricity(flatPlanLossElectricity) - .flatAmount(flatAmount) - .valleyPrice(valleyPrice) - .valleyUsedElectricity(valleyUsedElectricity) - .valleyPlanLossElectricity(valleyPlanLossElectricity) - .valleyAmount(valleyAmount) - .ammeterTotalStart(ammeterTotalStart) - .ammeterTotalEnd(ammeterTotalEnd) - .totalElectricity(totalElectricity) - .planLossTotalElectricity(planLossTotalElectricity) - .consumptionAmount(consumptionAmount) - .vinCode(vinCode) - .transactionIdentifier(transactionIdentifier) - .transactionTime(transactionTime) - .stopReasonMsg(stopReasonMsg) - .logicCard(logicCard) - .build(); - - // 保存报文 - String jsonMsg = JSON.toJSONString(data); - // pileMsgRecordService.save(pileSn, pileSn + connectorCode, type, jsonMsg, ykcDataProtocol.getHEXString()); - - // 处理订单加锁 - String lockKey = "settle_order_" + transactionCode; - String uuid = IdUtils.fastUUID(); - try { - // redis锁 - Boolean isLock = redisCache.lock(lockKey, uuid, 1500); - if (isLock) { - processOrder(data); - } - } catch (Exception e) { - log.error("处理订单transactionCode:{}, 发生异常", transactionCode, e); - } finally { - if (uuid.equals(redisCache.getCacheObject(lockKey).toString())) { - redisCache.unLock(lockKey); - } - } - - /* - 应答 - 确认结果 0x00 上传成功 0x01 非法账单 - 2022年12月15日11点28分发现返回 01非法账单,充电桩会持续上传交易记录,后面产生的交易记录被阻塞 - */ - byte[] confirmResultBytes = Constants.zeroByteArray; - byte[] concatMsgBody = Bytes.concat(transactionCodeByteArr, confirmResultBytes); - - return YKCUtils.getResult(ykcDataProtocol, concatMsgBody); - } - - /** - * 收到交易记录 处理订单 - * - * @param data - */ - private void processOrder(TransactionRecordsData data) { - String pileSn = data.getPileSn(); // 充电桩编号 - PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); - if (StringUtils.equals(pileBasicInfo.getBusinessType(), Constants.TWO)) { - personalChargingRecordService.processPersonalChargingRecord(data); - // return; - } - - String transactionCode = data.getTransactionCode(); - // 根据交易流水号查询订单信息 - OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - if (orderBasicInfo != null) { - // 平台存在订单 - orderBasicInfo.setReason(data.getStopReasonMsg()); - // 如果订单状态为 异常,则改为 待结算 - if (StringUtils.equals(OrderStatusEnum.ABNORMAL.getValue(), orderBasicInfo.getOrderStatus())) { - orderBasicInfo.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue()); - } - // 校验一下开始时间和结束时间,防止充电中桩离线,时间不准确 - if (Objects.isNull(orderBasicInfo.getChargeStartTime())) { // 开始时间 - orderBasicInfo.setChargeStartTime(DateUtils.parseDate(data.getStartTime())); - } - if (Objects.isNull(orderBasicInfo.getChargeEndTime())) { // 结束时间 - orderBasicInfo.setChargeEndTime(DateUtils.parseDate(data.getEndTime())); - } - - // 校验结束时间 - if (orderBasicInfo.getChargeEndTime().before(orderBasicInfo.getChargeStartTime())) { - orderBasicInfo.setChargeEndTime(new Date()); - } - - orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); - - // 重新查询订单信息 - orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - - // 结算订单操作 - try { - // 新逻辑 - String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); - AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); - orderLogic.settleOrder(data, orderBasicInfo); - } catch (Exception e) { - log.error("结算订单发生异常 orderCode:{}", orderBasicInfo.getOrderCode(), e); - } - - // 异步绑定第三方平台优惠券 - // OrderBasicInfo finalOrderBasicInfo = orderBasicInfo; - // String redisKey = CacheConstants.CAR_BIND_COUPON_BY_ORDER_CODE + orderBasicInfo.getOrderCode(); - // Object cacheObject = redisCache.getCacheObject(redisKey); - // if (cacheObject == null) { - // CompletableFuture.runAsync(() -> { - // try { - // String bindResult = commonService.bindCoupon(finalOrderBasicInfo); - // log.info("绑定优惠券 订单信息:{}, result:{}", finalOrderBasicInfo, bindResult); - // // 删除绑定优惠券缓存 - // redisCache.deleteObject(redisKey); - // } catch (Exception e) { - // log.error("绑定优惠券 error,", e); - // } - // }, executor); - // } - - // 异步推送第三方平台订单信息 - // CompletableFuture.runAsync(() -> { - // try { - // commonService.commonPushOrderInfo(finalOrderBasicInfo); - // } catch (Exception e) { - // log.error("推送第三方平台订单信息error, ", e); - // e.printStackTrace(); - // } - // }, executor); - - // 异步推送第三方平台订单信息V2 - // CompletableFuture.runAsync(() -> { - // try { - // commonService.commonPushOrderInfoV2(finalOrderBasicInfo); - // } catch (Exception e) { - // log.error("推送第三方平台订单信息error, ", e); - // e.printStackTrace(); - // } - // }, executor); - } else { - // 平台没有查到订单 - orderBasicInfoService.saveAbnormalOrder(data); - log.warn("充电桩传来的交易记录,根据交易流水号:{}查询不到订单,判定为可疑账单", transactionCode); - } - } -} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/UploadRealTimeMonitorStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/UploadRealTimeMonitorStrategy.java deleted file mode 100644 index bdde705a5..000000000 --- a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/UploadRealTimeMonitorStrategy.java +++ /dev/null @@ -1,420 +0,0 @@ -package com.jsowell.netty.strategy.ykc; - -import com.jsowell.common.constant.CacheConstants; -import com.jsowell.common.constant.Constants; -import com.jsowell.common.constant.mq.ThirdPartyRabbitConstants; -import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; -import com.jsowell.common.core.domain.ykc.YKCDataProtocol; -import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; -import com.jsowell.common.core.redis.RedisCache; -import com.jsowell.common.enums.ykc.OrderPayStatusEnum; -import com.jsowell.common.enums.ykc.OrderStatusEnum; -import com.jsowell.common.enums.ykc.PileConnectorStatusEnum; -import com.jsowell.common.enums.ykc.YKCPileFaultReasonEnum; -import com.jsowell.common.util.BytesUtil; -import com.jsowell.common.util.StringUtils; -import com.jsowell.common.util.YKCUtils; -import com.jsowell.common.util.spring.SpringUtils; -import com.jsowell.netty.factory.YKCOperateFactoryV2; -import com.jsowell.pile.domain.OrderBasicInfo; -import com.jsowell.pile.service.OrderBasicInfoService; -import com.jsowell.pile.service.PileBasicInfoService; -import com.jsowell.thirdparty.common.CommonService; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -/** - * 获取桩上传的实时监测数据 0x13 - * - * @author JS-ZZA - * @date 2022/9/19 9:08 - */ -@Slf4j -@Component -public class UploadRealTimeMonitorStrategy implements AbstractYkcStrategy { - private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.UPLOAD_REAL_TIME_MONITOR_DATA_CODE.getBytes()); - private final String oldVersionType = YKCUtils.frameType2Str(YKCFrameTypeCode.UPLOAD_REAL_TIME_MONITOR_DATA_OLD_VERSION_CODE.getBytes()); - - @PostConstruct - public void init() { - YKCOperateFactoryV2.register(type, this.getClass().getSimpleName()); - YKCOperateFactoryV2.register(oldVersionType, this.getClass().getSimpleName()); - } - - // 引入线程池 - private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); - - @Autowired - private PileBasicInfoService pileBasicInfoService; - - @Autowired - private OrderBasicInfoService orderBasicInfoService; - - @Autowired - private CommonService commonService; - - @Autowired - private RedisCache redisCache; - - @Autowired - private RabbitTemplate rabbitTemplate; - - - @Override - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { - // log.info("[===获取桩上传的实时监测数据===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); - RealTimeMonitorData realTimeMonitorData = new RealTimeMonitorData(); - - // 获取消息体 - byte[] msgBody = ykcDataProtocol.getMsgBody(); - // log.info("上传实时数据msgBody:{}", BytesUtil.bcd2Str(msgBody)); - int startIndex = 0; - int length = 16; - - // 交易流水号 - byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr); - realTimeMonitorData.setTransactionCode(transactionCode); - - // 桩编码 - startIndex += length; - length = 7; - byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String pileSn = BytesUtil.bcd2Str(pileSnByteArr); - realTimeMonitorData.setPileSn(pileSn); - - // 保存时间 - saveLastTimeAndCheckChannel(pileSn, channel); - - // 枪号 - startIndex += length; - length = 1; - byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr); - realTimeMonitorData.setConnectorCode(connectorCode); - - // 枪口编号 - String pileConnectorCode = pileSn + connectorCode; - - // 枪口状态 0x00:离线 0x01:故障 0x02:空闲 0x03:充电 0x04 预约中 - startIndex += length; - length = 1; - byte[] connectorStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String connectorStatus = BytesUtil.bcd2Str(connectorStatusByteArr); - realTimeMonitorData.setConnectorStatus(connectorStatus); - - // 是否归位 0x00:否 0x01:是 0x02:未知(无法检测到枪是否插回枪座即 未知) - startIndex += length; - length = 1; - byte[] homingFlagByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String homingFlag = BytesUtil.bcd2Str(homingFlagByteArr); - realTimeMonitorData.setHomingFlag(homingFlag); - - // 是否插枪 0x00:否 0x01:是 - startIndex += length; - length = 1; - byte[] isChargerPluggedInByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String isChargerPluggedIn = BytesUtil.bcd2Str(isChargerPluggedInByteArr); - realTimeMonitorData.setPutGunType(isChargerPluggedIn); - - // 输出电压 精确到小数点后一位;待机置零 - startIndex += length; - length = 2; - byte[] outputVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String outputVoltage = YKCUtils.convertVoltageCurrent(outputVoltageByteArr); - realTimeMonitorData.setOutputVoltage(outputVoltage); - - // 输出电流 精确到小数点后一位;待机置零 - startIndex += length; - length = 2; - byte[] outputCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String outputCurrent = YKCUtils.convertVoltageCurrent(outputCurrentByteArr); - realTimeMonitorData.setOutputCurrent(outputCurrent); - - // 枪线温度 整形, 偏移量-50;待机置零 - startIndex += length; - length = 1; - byte[] gunLineTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String gunLineTemperature = YKCUtils.transitionTemperature(gunLineTemperatureByteArr); - realTimeMonitorData.setGunLineTemperature(gunLineTemperature); - - // 枪线编码 没有置零 - startIndex += length; - length = 8; - byte[] gunLineCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String gunLineCode = BytesUtil.bcd2Str(gunLineCodeByteArr); - realTimeMonitorData.setGunLineCode(gunLineCode); - - // SOC 待机置零;交流桩置零 - startIndex += length; - length = 1; - byte[] SOCByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String SOC = String.valueOf(SOCByteArr[0]); - realTimeMonitorData.setSOC(SOC); - - // 电池组最高温度 整形, 偏移量-50 ºC;待机置零; 交流桩置零 - startIndex += length; - length = 1; - byte[] batteryMaxTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String batteryMaxTemperature = YKCUtils.transitionTemperature(batteryMaxTemperatureByteArr); - realTimeMonitorData.setBatteryMaxTemperature(batteryMaxTemperature); - - // 累计充电时间 单位: min;待机置零 - startIndex += length; - length = 2; - byte[] sumChargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - int sumChargingTime = BytesUtil.bytesToIntLittle(sumChargingTimeByteArr); - realTimeMonitorData.setSumChargingTime(String.valueOf(sumChargingTime)); - - // 剩余时间 单位: min;待机置零、交流桩置零 - startIndex += length; - length = 2; - byte[] timeRemainingByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - int timeRemaining = BytesUtil.bytesToIntLittle(timeRemainingByteArr); - realTimeMonitorData.setTimeRemaining(String.valueOf(timeRemaining)); - - // 充电度数 精确到小数点后四位;待机置零 - startIndex += length; - length = 4; - byte[] chargingDegreeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String chargingDegree = YKCUtils.convertDecimalPoint(chargingDegreeByteArr, 4); - realTimeMonitorData.setChargingDegree(chargingDegree); - - // 计损充电度数 精确到小数点后四位;待机置零 未设置计损比例时等于充电度数 - startIndex += length; - length = 4; - byte[] lossDegreeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String lossDegree = YKCUtils.convertDecimalPoint(lossDegreeByteArr, 4); - realTimeMonitorData.setLossDegree(lossDegree); - - // 已充金额 精确到小数点后四位;待机置零 (电费+服务费) *计损充电度数 - startIndex += length; - length = 4; - byte[] chargingAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String chargingAmount = YKCUtils.convertDecimalPoint(chargingAmountByteArr, 4); - realTimeMonitorData.setChargingAmount(chargingAmount); - - /** - * 硬件故障 - * - * Bit 位表示(0 否 1 是), 低位到高位顺序 - * Bit1:急停按钮动作故障; - * Bit2:无可用整流模块; - * Bit3:出风口温度过高; - * Bit4:交流防雷故障; - * Bit5:交直流模块 DC20 通信中断; - * Bit6:绝缘检测模块 FC08 通信中断; - * Bit7:电度表通信中断; - * Bit8:读卡器通信中断; - * Bit9: RC10 通信中断; - * Bit10:风扇调速板故障; - * Bit11:直流熔断器故障; - * Bit12:高压接触器故障; - * Bit13:门打开; - */ - startIndex += length; - length = 2; - byte[] hardwareFaultTempByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - String hardwareFaultTemp = BytesUtil.bcd2Str(hardwareFaultTempByteArr); - String faultReason = "无"; - - if (!StringUtils.equals(hardwareFaultTemp, "0000")) { - // 不等于0000说明有故障 - StringBuffer sb = new StringBuffer(hardwareFaultTemp); - String lowOrder = sb.substring(0, 2); - String highOrder = sb.substring(2, 4); - - // String hardwareFault = highOrder + lowOrder; - byte[] hardwareFaultByteArr = BytesUtil.str2Bcd(highOrder + lowOrder); - String binStr = BytesUtil.bytes2BinStr(hardwareFaultByteArr); - // log.info("binStr:{}", binStr); // 0000 0000 0000 0001 - int faultCode = 0; - for (int i = 0; i < binStr.length(); i++) { - if (binStr.charAt(i) == '1') { - faultCode = 15 - i; - break; - } - } - faultReason = YKCPileFaultReasonEnum.getValueByCode(faultCode); - } - realTimeMonitorData.setHardwareFault(faultReason); - - if (!StringUtils.equals(connectorStatus, PileConnectorStatusEnum.FREE.getValue())) { - log.info("0x13上传实时监测数据==交易流水号:{}, 桩编号:{}, 枪口号:{}, 枪口状态:{}, 枪口状态描述:{}, 枪是否归位(00-否;01-是;02-未知):{}, 是否插枪(00-否;01-是):{}, 输出电压:{}, 输出电流:{}, 枪线温度:{}, " + - "枪线编码:{}, SOC:{}, 电池组最高温度:{}, 累计充电时间:{}, 剩余时间:{}, 充电度数:{}, 记损充电度数:{}, 已充金额:{}, " + - "硬件故障:{}, 故障码转换结果:{}", transactionCode, pileSn, connectorCode, connectorStatus, PileConnectorStatusEnum.getLabelByValue(connectorStatus), homingFlag, isChargerPluggedIn, outputVoltage, - outputCurrent, gunLineTemperature, gunLineCode, SOC, batteryMaxTemperature, sumChargingTime, timeRemaining, - chargingDegree, lossDegree, chargingAmount, hardwareFaultTemp, faultReason - ); - } - - // 插枪状态 - String plugRedisKey = CacheConstants.CHARGER_PLUGGED_IN_STATUS + pileConnectorCode; - if (StringUtils.equals("01", isChargerPluggedIn)) { - // 插枪状态 - if (redisCache.setnx(plugRedisKey, pileConnectorCode, CacheConstants.cache_expire_time_30d)) { - // log.info("时间:{}, 枪口号:{}, 首次插入充电枪", DateUtils.getDateTime(), pileConnectorCode); - // 设置成功说明 第一次插枪 - // pileBasicInfoService.firstPlugInCharger(pileConnectorCode); - } - } else { - // 未插枪状态 - if (redisCache.hasKey(plugRedisKey) && redisCache.deleteObject(plugRedisKey)) { - // log.info("时间:{}, 枪口号:{}, 首次拔出充电枪", DateUtils.getDateTime(), pileConnectorCode); - // redis有值,并且删除成功,说明首次拔枪 - // pileBasicInfoService.firstUnplugCharger(pileConnectorCode); - } - } - - // 公共方法修改状态 - pileBasicInfoService.updateStatus(BytesUtil.bcd2Str(ykcDataProtocol.getFrameType()), pileSn, connectorCode, connectorStatus, isChargerPluggedIn); - - // 01表示故障 - if (StringUtils.equals(connectorStatus, PileConnectorStatusEnum.FAULT.getValue())) { - // 故障原因存入缓存 - String redisKey = CacheConstants.PILE_HARDWARE_FAULT + pileConnectorCode; - redisCache.setCacheObject(redisKey, faultReason, 5, TimeUnit.MINUTES); - } - - // 03表示充电中 - if (StringUtils.equals(connectorStatus, PileConnectorStatusEnum.OCCUPIED_CHARGING.getValue())) { - // 默认保存到redis - boolean saveRedisFlag = true; - - // 查询数据库中该订单当前信息 - OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); - if (Objects.nonNull(orderInfo)) { - if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue()) - || StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.STAY_SETTLEMENT.getValue())) { - // 在订单状态为 订单完成或待结算,不保存 - saveRedisFlag = false; - } - - boolean updateFlag = false; - if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.NOT_START.getValue()) - || StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ABNORMAL.getValue()) - || StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.STAY_SETTLEMENT.getValue())) { - updateFlag = true; - // 如果是未启动状态或者异常状态, 修改这个订单状态为充电中 2023年7月7日新增 如果是待结算状态,也改为充电中 - orderInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue()); - } - - if (StringUtils.equals(orderInfo.getPayStatus(), OrderPayStatusEnum.unpaid.getValue())) { - // 如果发现该订单的支付状态为 0-待支付,将该订单支付状态改为 1-支付完成 - orderInfo.setPayStatus(OrderPayStatusEnum.paid.getValue()); - } - - // 如果原来没有开始充电时间就保存当前时间为开始充电时间 - if (orderInfo.getChargeStartTime() == null) { - updateFlag = true; - orderInfo.setChargeStartTime(new Date()); - } - - if (updateFlag) { - orderBasicInfoService.updateOrderBasicInfo(orderInfo); - } - } - - // 充电时保存实时数据到redis - if (saveRedisFlag) { - pileBasicInfoService.saveRealTimeMonitorData2Redis(realTimeMonitorData); - } - // 判断该订单是否需要下发优惠券 - // String redisKey = CacheConstants.CAR_BIND_COUPON_BY_ORDER_CODE + orderInfo.getOrderCode(); - // Object cacheObject = redisCache.getCacheObject(redisKey); - // if (cacheObject == null && sumChargingTime >= 10) { - // // 异步绑定优惠券并设置缓存 - // CompletableFuture.runAsync(() -> { - // try { - // commonService.bindCoupon(orderInfo); - // redisCache.setCacheObject(redisKey, Boolean.TRUE, 24, TimeUnit.HOURS); - // } catch (Exception e) { - // log.error("异步绑定车辆优惠券 error,", e); - // } - // }, executor); - // } - - } - -// // 异步推送第三方平台实时数据 -// CompletableFuture.runAsync(() -> { -// try { -// commonService.pushRealTimeInfo(pileSn, connectorCode, connectorStatus, realTimeMonitorData, transactionCode); -// } catch (Exception e) { -// log.error("统一推送第三方平台实时数据 error,", e); -// } -// }, executor); -// -// // 异步推送第三方平台实时数据V2 -// CompletableFuture.runAsync(() -> { -// try { -// commonService.pushRealTimeInfoV2(pileSn, connectorCode, connectorStatus, realTimeMonitorData, transactionCode); -// } catch (Exception e) { -// log.error("统一推送第三方平台实时数据V2 error, ", e); -// } -// }, executor); -// -// if (StringUtils.equals(connectorStatus, Constants.ONE)) { -// // 故障 -// // 异步推送第三方平台告警信息 -// CompletableFuture.runAsync(() -> { -// try { -// commonService.commonPushAlarmInfo(pileConnectorCode, connectorStatus, realTimeMonitorData.getPutGunType()); -// } catch (Exception e) { -// log.error("统一推送第三方平台告警信息 error, ", e); -// } -// }, executor); -// } - - // TODO 测试mq - // 向mq中发送实时数据消息,给第三方服务消费 - CompletableFuture.runAsync(() -> { - try { - rabbitTemplate.convertAndSend(ThirdPartyRabbitConstants.WCC_THIRDPARTY_NAME,ThirdPartyRabbitConstants.ROUTING_KEY_REALTIME_DATA_PUSH, realTimeMonitorData); - } catch (Exception e){ - log.error("向mq中发送实时数据消息供第三方服务消费 error, ", e); - } - if (StringUtils.equals(connectorStatus,Constants.ONE)){ - // 故障 - // 异步推送第三方平台告警信息 - try { - rabbitTemplate.convertAndSend(ThirdPartyRabbitConstants.WCC_THIRDPARTY_NAME,ThirdPartyRabbitConstants.ROUTING_KEY_ALARM_PUSH, realTimeMonitorData.getPutGunType()); - } catch (Exception e) { - log.error("统一推送第三方平台告警信息 error, ", e); - } - } - }, executor); - - return null; - } - - public static void main(String[] args) { - StringBuffer sb = new StringBuffer("0100"); - String lowOrder = sb.substring(0, 2); - String highOrder = sb.substring(2, 4); - - // String hardwareFault = highOrder + lowOrder; - byte[] hardwareFaultByteArr = BytesUtil.str2Bcd(highOrder + lowOrder); - String binStr = BytesUtil.bytes2BinStr(hardwareFaultByteArr); - // log.info("binStr:{}", binStr); // 0000 0000 0000 0001 - int faultCode = 0; - for (int i = 0; i < binStr.length(); i++) { - if (binStr.charAt(i) == '1') { - faultCode = 16 - i; - break; - } - } - String faultReason = YKCPileFaultReasonEnum.getValueByCode(faultCode); - System.out.println(faultReason); - } -}