package com.jsowell.netty.handler; import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.Lists; import com.google.common.primitives.Bytes; 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.core.redis.RedisCache; import com.jsowell.common.util.BytesUtil; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.YKCOperateFactory; import com.jsowell.pile.domain.PileBasicInfo; import com.jsowell.pile.domain.ykcCommond.IssueQRCodeCommand; import com.jsowell.pile.domain.ykcCommond.ProofreadTimeCommand; import com.jsowell.pile.service.IPileBasicInfoService; import com.jsowell.pile.service.IPileMsgRecordService; import com.jsowell.pile.service.YKCPushCommandService; import io.netty.channel.Channel; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.List; import java.util.concurrent.CompletableFuture; @Slf4j @Component public class LoginRequestHandler extends AbstractHandler { @Autowired private IPileBasicInfoService pileBasicInfoService; @Autowired private YKCPushCommandService ykcPushCommandService; @Autowired private IPileMsgRecordService pileMsgRecordService; @Autowired private RedisCache redisCache; private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.LOGIN_CODE.getBytes()); private List newProgramVersionList = Lists.newArrayList("c6-30"); @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); } @Override public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) { // log.info("[===执行登录逻辑===] param:{}, channel:{}", JSONObject.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); // log.info("桩号:{}", pileSn); // 保存时间 saveLastTimeAndCheckChannel(pileSn, channel); // 桩类型 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); 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(); } }); // 异步发送对时指令 CompletableFuture.runAsync(() -> { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } // 对时 ProofreadTimeCommand command = ProofreadTimeCommand.builder().pileSn(pileSn).build(); ykcPushCommandService.pushProofreadTimeCommand(command); }); // 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); }); if (StringUtils.equals("00", internetConnection)) { CompletableFuture.runAsync(() -> { // 充电桩使用的sim卡,把信息存库 try { pileBasicInfoService.updatePileSimInfo(pileSn, iccid); // pileBasicInfoService.updatePileSimInfoV2(pileSn, iccid); } catch (Exception e) { log.error("更新充电桩sim卡信息失败pileSn:{}, iccid:{}", pileSn, iccid, e); } }); } } // 异步保持登录报文 CompletableFuture.runAsync(() -> { // 保存报文 没有登录认证通过还要不要保存报文? try { String jsonMsg = JSONObject.toJSONString(loginRequestData); pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString()); } catch (Exception e) { log.error("保存报文失败pileSn:{}", pileSn, e); } }); // 消息体 byte[] messageBody = Bytes.concat(pileSnByte, flag); return getResult(ykcDataProtocol, messageBody); } }