mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 02:55:04 +08:00
Merge branch 'dev-new' into dev-new-rabbitmq
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package com.jsowell.netty.factory;
|
||||
|
||||
import com.jsowell.netty.strategy.ykc.AbstractYkcStrategy;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工厂设计模式
|
||||
* 云快充操作
|
||||
*/
|
||||
@Component
|
||||
public class YKCOperateFactoryV2 {
|
||||
|
||||
@Autowired
|
||||
private Map<String, AbstractYkcStrategy> strategyMap;
|
||||
|
||||
private static Map<String, String> operationMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
//初始化实现类
|
||||
operationMap.put("0x01", "loginRequestStrategy");
|
||||
operationMap.put("0x05", "billingTemplateValidateRequestStrategy");
|
||||
// more operators
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册
|
||||
* @param str
|
||||
* @param handler
|
||||
*/
|
||||
// public void register(String str, AbstractYkcHandlerV2 handler) {
|
||||
// if (StringUtils.isBlank(str) || Objects.isNull(handler)) {
|
||||
// return;
|
||||
// }
|
||||
// strategyMap.put(str, handler);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取
|
||||
*/
|
||||
public AbstractYkcStrategy getInvokeStrategy(String frameType) {
|
||||
String s = operationMap.get(frameType);
|
||||
return strategyMap.get(s);
|
||||
}
|
||||
}
|
||||
@@ -24,26 +24,10 @@ public abstract class AbstractYkcHandler implements InitializingBean {
|
||||
|
||||
private static final String REQUEST_PREFIX = "Request_";
|
||||
|
||||
/**
|
||||
* 执行逻辑
|
||||
* 有应答
|
||||
*/
|
||||
// public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
|
||||
public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行逻辑
|
||||
* 不需要应答
|
||||
*/
|
||||
// public void pushProcess() {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 组装应答的结果
|
||||
* @param ykcDataProtocol 请求数据
|
||||
|
||||
@@ -115,6 +115,7 @@ public class LoginRequestHandler extends AbstractYkcHandler {
|
||||
String business = BytesUtil.bcd2Str(businessTypeByteArr);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) {
|
||||
if (verifyTheDuplicateRequest(ykcDataProtocol, ctx)) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -60,28 +61,34 @@ public class ParameterConfigurationHandler extends AbstractYkcHandler {
|
||||
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;
|
||||
@@ -89,26 +96,30 @@ public class ParameterConfigurationHandler extends AbstractYkcHandler {
|
||||
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);
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.YKCUtils;
|
||||
import com.jsowell.netty.factory.YKCOperateFactory;
|
||||
import com.jsowell.netty.factory.YKCOperateFactoryV2;
|
||||
import com.jsowell.netty.handler.yunkuaichong.AbstractYkcHandler;
|
||||
import com.jsowell.netty.service.yunkuaichong.YKCBusinessService;
|
||||
import com.jsowell.pile.service.OrderBasicInfoService;
|
||||
@@ -31,6 +32,9 @@ public class YKCBusinessServiceImpl implements YKCBusinessService {
|
||||
@Autowired
|
||||
private OrderBasicInfoService orderBasicInfoService;
|
||||
|
||||
@Autowired
|
||||
private YKCOperateFactoryV2 ykcOperateFactoryV2; // 使用注解注入
|
||||
|
||||
@Override
|
||||
public byte[] process(byte[] msg, ChannelHandlerContext ctx) {
|
||||
if (!YKCUtils.checkMsg(msg)) {
|
||||
@@ -42,6 +46,7 @@ public class YKCBusinessServiceImpl implements YKCBusinessService {
|
||||
String frameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
|
||||
// 获取业务处理handler
|
||||
AbstractYkcHandler invokeStrategy = YKCOperateFactory.getInvokeStrategy(frameType);
|
||||
// AbstractYkcHandlerV2 invokeStrategy = ykcOperateFactoryV2.getInvokeStrategy(frameType);
|
||||
return invokeStrategy.supplyProcess(ykcDataProtocol, ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.jsowell.netty.strategy.ykc;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
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.StaticRedisCache;
|
||||
import com.jsowell.common.enums.ykc.PileChannelEntity;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
import com.jsowell.common.util.CRC16Util;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
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.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;
|
||||
|
||||
/**
|
||||
* 计费模板验证请求Handler
|
||||
*
|
||||
* @author JS-ZZA
|
||||
* @date 2022/9/17 14:10
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BillingTemplateValidateRequestStrategy implements AbstractYkcStrategy {
|
||||
|
||||
private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.BILLING_TEMPLATE_VALIDATE_CODE.getBytes());
|
||||
|
||||
@Autowired
|
||||
private PileBillingTemplateService pileBillingTemplateService;
|
||||
|
||||
@Autowired
|
||||
private YKCPushCommandService ykcPushCommandService;
|
||||
|
||||
// @Override
|
||||
// public void afterPropertiesSet() throws Exception {
|
||||
// YKCOperateFactory.register(type, this);
|
||||
// }
|
||||
@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 getResult(ykcDataProtocol, messageBody);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
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.LoginRequestData;
|
||||
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.StringUtils;
|
||||
import com.jsowell.common.util.YKCUtils;
|
||||
import com.jsowell.common.util.spring.SpringUtils;
|
||||
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 java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LoginRequestStrategy 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<String> newProgramVersionList = Lists.newArrayList("c6-30");
|
||||
|
||||
// 引入线程池
|
||||
private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor");
|
||||
|
||||
// @Override
|
||||
// public void afterPropertiesSet() throws Exception {
|
||||
// YKCOperateFactory.register(type, this);
|
||||
// }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 获取消息体
|
||||
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, ctx);
|
||||
|
||||
// 桩类型 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);
|
||||
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);
|
||||
|
||||
// *********************** 字段解析完成,下面进行逻辑处理 *********************** //
|
||||
LoginRequestData loginRequestData = LoginRequestData.builder()
|
||||
.pileSn(pileSn)
|
||||
.pileType(pileType)
|
||||
.connectorNum(connectorNum)
|
||||
.communicationVersion(communicationVersion)
|
||||
.programVersion(programVersion)
|
||||
.internetConnection(internetConnection)
|
||||
.iccid(iccid)
|
||||
.business(business)
|
||||
.build();
|
||||
|
||||
// 结果(默认 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(loginRequestData);
|
||||
pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString());
|
||||
} catch (Exception e) {
|
||||
log.error("保存报文失败pileSn:{}", pileSn, e);
|
||||
}
|
||||
}, executor);
|
||||
|
||||
// 消息体
|
||||
byte[] messageBody = Bytes.concat(pileSnByte, flag);
|
||||
return getResult(ykcDataProtocol, messageBody);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user