From 7d61ba4f6851f1aa382193c4a57513c1131eb775 Mon Sep 17 00:00:00 2001 From: Guoqs <123@jsowell.com> Date: Wed, 29 May 2024 14:16:27 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E9=A2=84=E7=BA=A6=E5=85=85=E7=94=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/common/CommonController.java | 3 - .../impl/OrderBasicInfoServiceImpl.java | 46 +- .../impl/YKCPushCommandServiceImpl.java | 792 +++++++++--------- 3 files changed, 425 insertions(+), 416 deletions(-) diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java index 3605b7888..a2c370613 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java @@ -40,9 +40,6 @@ public class CommonController { private static final String FILE_DELIMETER = ","; - @Value("${remoteUpdate.path}") - private String FIRMWARE_FILEPATH; - /** * 通用下载请求 * diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 58b476c86..db7be6a59 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -3054,7 +3054,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { } else if (StartModeEnum.VIN_CODE.getValue().equals(dto.getStartMode())) { sendStartCharging = false; } else if (StartTypeEnum.RESERVED.getValue().equals(orderInfo.getStartType())) { - sendStartCharging = false; + // sendStartCharging = false; } else if (OrderStatusEnum.STAY_RETROACTIVE_AMOUNT.getValue().equals(orderInfo.getOrderStatus())) { sendStartCharging = false; } @@ -3107,6 +3107,28 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { logger.info("订单:{}支付成功, 发送启动指令", dto.getOrderCode()); } + /** + * 异步发送预约充电指令 + */ + if (StringUtils.equals(orderInfo.getStartType(), StartTypeEnum.RESERVED.getValue())) { + ReservedChargingCommand command = ReservedChargingCommand.builder() + .transactionCode(orderInfo.getTransactionCode()) + .pileSn(orderInfo.getPileSn()) + .connectorCode(orderInfo.getPileConnectorCode()) + .operation(BytesUtil.bcd2Str(new byte[]{0x01})) + .reservedStartTime(orderInfo.getReservedStartTime()) + .reservedStartTime(orderInfo.getReservedEndTime()) + .amount(new BigDecimal(Constants.FIVE_HUNDRED)) + .build(); + CompletableFuture.runAsync(() -> { + try { + pileRemoteService.reservedCharging(command); + } catch (Exception e) { + logger.error("异步发送预约充电指令, orderCode:{}", orderInfo.getOrderCode(), e); + } + }); + } + if (OrderStatusEnum.STAY_RETROACTIVE_AMOUNT.getValue().equals(orderInfo.getOrderStatus())) { // 如果订单状态是待补缴,表示已经停止充电了,需要补缴费用,补缴完成订单状态改为订单完成,设置结算时间 orderInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); @@ -3591,28 +3613,6 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { .orderDetail(orderDetail) .build(); pileTransactionService.doCreateOrder(createOrderTransactionDTO); - - /** - * 异步发送预约充电指令 - */ - if (StringUtils.equals(dto.getStartType(), StartTypeEnum.RESERVED.getValue())) { - ReservedChargingCommand command = ReservedChargingCommand.builder() - .transactionCode(orderBasicInfo.getTransactionCode()) - .pileSn(orderBasicInfo.getPileSn()) - .connectorCode(orderBasicInfo.getPileConnectorCode()) - .operation(BytesUtil.bcd2Str(new byte[]{0x01})) - .reservedStartTime(DateUtils.parseDate(dto.getReservedStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS)) - .reservedStartTime(DateUtils.parseDate(dto.getReservedEndTime(), DateUtils.YYYY_MM_DD_HH_MM_SS)) - .amount(new BigDecimal(Constants.FIVE_HUNDRED)) - .build(); - CompletableFuture.runAsync(() -> { - try { - pileRemoteService.reservedCharging(command); - } catch (Exception e) { - logger.error("异步发送预约充电指令, orderCode:{}", orderBasicInfo.getOrderCode(), e); - } - }); - } return orderBasicInfo; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java index 54a5fd241..b48da1a8c 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java @@ -34,477 +34,489 @@ import java.util.Objects; @Slf4j @Service public class YKCPushCommandServiceImpl implements YKCPushCommandService { - @Autowired - private PileBillingTemplateService pileBillingTemplateService; + @Autowired + private PileBillingTemplateService pileBillingTemplateService; - @Autowired - private PileModelInfoService pileModelInfoService; + @Autowired + private PileModelInfoService pileModelInfoService; - @Autowired - private PileBasicInfoService pileBasicInfoService; + @Autowired + private PileBasicInfoService pileBasicInfoService; - @Autowired - private PileStationInfoService pileStationInfoService; + @Autowired + private PileStationInfoService pileStationInfoService; - @Autowired - private PileMsgRecordService pileMsgRecordService; + @Autowired + private PileMsgRecordService pileMsgRecordService; - @Autowired - private PileConnectorInfoService pileConnectorInfoService; + @Autowired + private PileConnectorInfoService pileConnectorInfoService; - // 需要记录报文的数据帧类型 - private final List frameTypeList = Lists.newArrayList( - YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_RESTART_CODE.getBytes()), - YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_CONTROL_START_CODE.getBytes()), - YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_STOP_CHARGING_CODE.getBytes()) - ); + // 需要记录报文的数据帧类型 + private final List frameTypeList = Lists.newArrayList( + YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_RESTART_CODE.getBytes()), + YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_CONTROL_START_CODE.getBytes()), + YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_STOP_CHARGING_CODE.getBytes()) + ); - /** - * 发送push消息 - * @param msg - * @param pileSn - * @param frameTypeCode - * @return - */ - public boolean push(byte[] msg, String pileSn, Enum frameTypeCode) { - // 通过桩编号获取channel - Channel channel = PileChannelEntity.getChannelByPileSn(pileSn); - String value = ((YKCFrameTypeCode) frameTypeCode).getValue(); - if (Objects.isNull(channel)) { - log.error("push命令[{}]失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", value, pileSn); - return false; - } - /** - * 拼接报文 - */ - // 起始标志 - byte[] head = new byte[]{0x68}; + /** + * 发送push消息 + * + * @param msg + * @param pileSn + * @param frameTypeCode + * @return + */ + public boolean push(byte[] msg, String pileSn, Enum frameTypeCode) { + // 通过桩编号获取channel + Channel channel = PileChannelEntity.getChannelByPileSn(pileSn); + String value = ((YKCFrameTypeCode) frameTypeCode).getValue(); + if (Objects.isNull(channel)) { + log.error("push命令[{}]失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", value, pileSn); + return false; + } + /** + * 拼接报文 + */ + // 起始标志 + byte[] head = new byte[]{0x68}; - // 序列号域 - byte[] serialNumber = new byte[]{0x00, 0x00}; + // 序列号域 + byte[] serialNumber = new byte[]{0x00, 0x00}; - // 加密标志 - byte[] encryptFlag = new byte[]{0x00}; + // 加密标志 + byte[] encryptFlag = new byte[]{0x00}; - // 帧类型标志 - byte[] frameType = new byte[]{(byte) ((YKCFrameTypeCode) frameTypeCode).getCode()}; + // 帧类型标志 + byte[] frameType = new byte[]{(byte) ((YKCFrameTypeCode) frameTypeCode).getCode()}; - // 序列号域+加密标志+帧类型标志+消息体 - byte[] temp = Bytes.concat(serialNumber, encryptFlag, frameType, msg); + // 序列号域+加密标志+帧类型标志+消息体 + byte[] temp = Bytes.concat(serialNumber, encryptFlag, frameType, msg); - // 数据长度 - byte[] length = BytesUtil.intToBytes(temp.length, 1); + // 数据长度 + byte[] length = BytesUtil.intToBytes(temp.length, 1); - // 帧校验域 - byte[] crc = BytesUtil.intToBytes(CRC16Util.calcCrc16(temp)); - // 返回报文 - byte[] writeMsg = Bytes.concat(head, length, temp, crc); - // 返回完整的报文 string类型 - String wholeMsg= BytesUtil.binary(writeMsg, 16); - // log.info("[" + channel.remoteAddress() + "] 主动发送push请求信息:{}", wholeMsg); - ByteBuf byteBuf = channel.alloc().buffer().writeBytes(writeMsg); - ChannelFuture channelFuture = channel.writeAndFlush(byteBuf); - channelFuture.addListener((ChannelFutureListener) channelFutureListener -> { - // 检查操作的状态 - if (channelFutureListener.isSuccess()) { - log.info("push结果【成功】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", - pileSn, channel.remoteAddress(), channel.id(), value, wholeMsg); - } else { - // 如果发生错误,则访问描述原因的Throwable - Throwable cause = channelFutureListener.cause(); - log.info("push结果【失败】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", - pileSn, channel.remoteAddress(), channel.id(), value, wholeMsg); - log.error("push发送命令失败, pileSn:{}", pileSn, cause); - } - }); + // 帧校验域 + byte[] crc = BytesUtil.intToBytes(CRC16Util.calcCrc16(temp)); + // 返回报文 + byte[] writeMsg = Bytes.concat(head, length, temp, crc); + // 返回完整的报文 string类型 + String wholeMsg = BytesUtil.binary(writeMsg, 16); + // log.info("[" + channel.remoteAddress() + "] 主动发送push请求信息:{}", wholeMsg); + ByteBuf byteBuf = channel.alloc().buffer().writeBytes(writeMsg); + ChannelFuture channelFuture = channel.writeAndFlush(byteBuf); + channelFuture.addListener((ChannelFutureListener) channelFutureListener -> { + // 检查操作的状态 + if (channelFutureListener.isSuccess()) { + log.info("push结果【成功】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", + pileSn, channel.remoteAddress(), channel.id(), value, wholeMsg); + } else { + // 如果发生错误,则访问描述原因的Throwable + Throwable cause = channelFutureListener.cause(); + log.info("push结果【失败】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", + pileSn, channel.remoteAddress(), channel.id(), value, wholeMsg); + log.error("push发送命令失败, pileSn:{}", pileSn, cause); + } + }); - // 保存报文 - String frameTypeStr = YKCUtils.frameType2Str(((YKCFrameTypeCode) frameTypeCode).getBytes()); - if (frameTypeList.contains(frameTypeStr)) { - pileMsgRecordService.save(pileSn, null, frameTypeStr, null, wholeMsg); - } - return true; - } + // 保存报文 + String frameTypeStr = YKCUtils.frameType2Str(((YKCFrameTypeCode) frameTypeCode).getBytes()); + if (frameTypeList.contains(frameTypeStr)) { + pileMsgRecordService.save(pileSn, null, frameTypeStr, null, wholeMsg); + } + return true; + } - /** - * 发送启动充电指令 - */ - @Override - public void pushStartChargingCommand(StartChargingCommand command) { - String pileSn = command.getPileSn(); - String connectorCode = command.getConnectorCode(); - String transactionCode = command.getTransactionCode(); - if (StringUtils.isEmpty(pileSn) || StringUtils.isEmpty(connectorCode) ) { - log.error("远程启动充电, 充电桩编号和枪口号不能为空"); - return; - } - if (StringUtils.isEmpty(transactionCode)) { - log.error("远程启动充电, 交易流水号不能为空"); - return; - } - if (command.getChargeAmount() == null || BigDecimal.ZERO.equals(command.getChargeAmount())) { - log.error("远程启动充电, 充电金额不能为0"); - return; - } + /** + * 发送启动充电指令 + */ + @Override + public void pushStartChargingCommand(StartChargingCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + String transactionCode = command.getTransactionCode(); + if (StringUtils.isEmpty(pileSn) || StringUtils.isEmpty(connectorCode)) { + log.error("远程启动充电, 充电桩编号和枪口号不能为空"); + return; + } + if (StringUtils.isEmpty(transactionCode)) { + log.error("远程启动充电, 交易流水号不能为空"); + return; + } + if (command.getChargeAmount() == null || BigDecimal.ZERO.equals(command.getChargeAmount())) { + log.error("远程启动充电, 充电金额不能为0"); + return; + } - // 枪口号 - byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); + // 枪口号 + byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); - // 交易流水号 - byte[] orderIdByteArr = BytesUtil.str2Bcd(transactionCode); + // 交易流水号 + byte[] orderIdByteArr = BytesUtil.str2Bcd(transactionCode); - // 桩编号 - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + // 桩编号 + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 逻辑卡号 - String logicCardNum = StringUtils.isBlank(command.getLogicCardNum()) - ? Constants.ZERO - : command.getLogicCardNum(); - byte[] logicCardNumByteArr = BytesUtil.checkLengthAndFrontAppendZero(BytesUtil.str2Bcd(logicCardNum), 16); + // 逻辑卡号 + String logicCardNum = StringUtils.isBlank(command.getLogicCardNum()) + ? Constants.ZERO + : command.getLogicCardNum(); + byte[] logicCardNumByteArr = BytesUtil.checkLengthAndFrontAppendZero(BytesUtil.str2Bcd(logicCardNum), 16); - // 物理卡号 - String physicsCardNum = StringUtils.isBlank(command.getPhysicsCardNum()) - ? Constants.ZERO - : command.getPhysicsCardNum(); - byte[] physicsCardNumByteArr = BytesUtil.checkLengthAndFrontAppendZero(BytesUtil.str2Bcd(physicsCardNum), 16); + // 物理卡号 + String physicsCardNum = StringUtils.isBlank(command.getPhysicsCardNum()) + ? Constants.ZERO + : command.getPhysicsCardNum(); + byte[] physicsCardNumByteArr = BytesUtil.checkLengthAndFrontAppendZero(BytesUtil.str2Bcd(physicsCardNum), 16); - // 账户余额 - BigDecimal chargeAmount = command.getChargeAmount(); - byte[] accountBalanceByteArr = YKCUtils.getPriceByte(chargeAmount.toString(), 2); + // 账户余额 + BigDecimal chargeAmount = command.getChargeAmount(); + byte[] accountBalanceByteArr = YKCUtils.getPriceByte(chargeAmount.toString(), 2); - byte[] msgBody = Bytes.concat(orderIdByteArr, pileSnByteArr, connectorCodeByteArr, logicCardNumByteArr, physicsCardNumByteArr, accountBalanceByteArr); - this.push(msgBody, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_START_CODE); - log.info("【=====平台下发充电指令=====】:订单id:{}, 桩号:{}, 枪口号:{}, 逻辑卡号:{}, 物理卡号:{}, 账户余额:{}", - transactionCode, pileSn, BytesUtil.bcd2Str(connectorCodeByteArr), logicCardNum, physicsCardNum, chargeAmount); - } + byte[] msgBody = Bytes.concat(orderIdByteArr, pileSnByteArr, connectorCodeByteArr, logicCardNumByteArr, physicsCardNumByteArr, accountBalanceByteArr); + this.push(msgBody, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_START_CODE); + log.info("【=====平台下发充电指令=====】:订单id:{}, 桩号:{}, 枪口号:{}, 逻辑卡号:{}, 物理卡号:{}, 账户余额:{}", + transactionCode, pileSn, BytesUtil.bcd2Str(connectorCodeByteArr), logicCardNum, physicsCardNum, chargeAmount); + } - /** - * 发送停止ch - * @param command - */ - @Override - public void pushStopChargingCommand(StopChargingCommand command) { - String pileSn = command.getPileSn(); - String connectorCode = command.getConnectorCode(); - // 远程停机 - byte[] msgBody = Bytes.concat(BytesUtil.str2Bcd(pileSn), BytesUtil.str2Bcd(connectorCode)); - this.push(msgBody, pileSn, YKCFrameTypeCode.REMOTE_STOP_CHARGING_CODE); - log.info("【=====平台下发指令=====】:远程停止充电,桩号:{},枪口号:{}", pileSn, connectorCode); - } + /** + * 发送停止ch + * + * @param command + */ + @Override + public void pushStopChargingCommand(StopChargingCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + // 远程停机 + byte[] msgBody = Bytes.concat(BytesUtil.str2Bcd(pileSn), BytesUtil.str2Bcd(connectorCode)); + this.push(msgBody, pileSn, YKCFrameTypeCode.REMOTE_STOP_CHARGING_CODE); + log.info("【=====平台下发指令=====】:远程停止充电,桩号:{},枪口号:{}", pileSn, connectorCode); + } - @Override - public void pushGetRealTimeMonitorDataCommand(GetRealTimeMonitorDataCommand command) { - String pileSn = command.getPileSn(); - String connectorCode = command.getConnectorCode(); - byte[] msg = BytesUtil.str2Bcd(pileSn + connectorCode); - this.push(msg, pileSn, YKCFrameTypeCode.READ_REAL_TIME_MONITOR_DATA_CODE); - log.info("【=====平台下发指令=====】:获取充电桩:{} 的 {} 枪口实时数据信息", pileSn, connectorCode); - } + @Override + public void pushGetRealTimeMonitorDataCommand(GetRealTimeMonitorDataCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + byte[] msg = BytesUtil.str2Bcd(pileSn + connectorCode); + this.push(msg, pileSn, YKCFrameTypeCode.READ_REAL_TIME_MONITOR_DATA_CODE); + log.info("【=====平台下发指令=====】:获取充电桩:{} 的 {} 枪口实时数据信息", pileSn, connectorCode); + } - @Override - public void pushRebootCommand(RebootCommand command) { - String pileSn = command.getPileSn(); - byte[] msg = BytesUtil.str2Bcd(pileSn + Constants.ZERO_ONE); - log.info("【=====平台下发指令=====】:重启充电桩:,{}", pileSn); - this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_RESTART_CODE); + @Override + public void pushRebootCommand(RebootCommand command) { + String pileSn = command.getPileSn(); + byte[] msg = BytesUtil.str2Bcd(pileSn + Constants.ZERO_ONE); + log.info("【=====平台下发指令=====】:重启充电桩:,{}", pileSn); + this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_RESTART_CODE); - } + } - // 下发二维码 - @Override - public void pushIssueQRCodeCommand(IssueQRCodeCommand command) { - // log.info("异步下发二维码 thread:{}", Thread.currentThread().getName()); - String pileSn = command.getPileSn(); - // 桩编码 - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + // 下发二维码 + @Override + public void pushIssueQRCodeCommand(IssueQRCodeCommand command) { + // log.info("异步下发二维码 thread:{}", Thread.currentThread().getName()); + String pileSn = command.getPileSn(); + // 桩编码 + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 二维码格式 0x00:第一种 前缀+桩编号 0x01:第二种 前缀+桩编号+枪编号 - byte[] qrCodeTypeByteArr = Constants.oneByteArray; + // 二维码格式 0x00:第一种 前缀+桩编号 0x01:第二种 前缀+桩编号+枪编号 + byte[] qrCodeTypeByteArr = Constants.oneByteArray; - // 二维码前缀 如:“www.baidu.com?No=” - // String qrCodePrefix = "https://wx.charging.shbochong.cn/prepare_charge?code="; - // String qrCodePrefix = pileBasicInfoService.getPileQrCodeUrl(null); - String qrCodePrefix = ""; - if (StringUtils.isNotBlank(command.getQrcodePrefix())) { - qrCodePrefix = command.getQrcodePrefix(); - } else { - PileStationVO pileStationVO = pileStationInfoService.getStationInfoByPileSn(pileSn); - if (StringUtils.isNotBlank(pileStationVO.getQrcodePrefix())) { - // 如果有配置二维码前缀,使用配置里的。(例如希晓) - qrCodePrefix = pileStationVO.getQrcodePrefix(); - } else { - // 为空则给平台二维码前缀 - qrCodePrefix = pileConnectorInfoService.getPileConnectorQrCodeUrl(null); - } - } + // 二维码前缀 如:“www.baidu.com?No=” + // String qrCodePrefix = "https://wx.charging.shbochong.cn/prepare_charge?code="; + // String qrCodePrefix = pileBasicInfoService.getPileQrCodeUrl(null); + String qrCodePrefix = ""; + if (StringUtils.isNotBlank(command.getQrcodePrefix())) { + qrCodePrefix = command.getQrcodePrefix(); + } else { + PileStationVO pileStationVO = pileStationInfoService.getStationInfoByPileSn(pileSn); + if (StringUtils.isNotBlank(pileStationVO.getQrcodePrefix())) { + // 如果有配置二维码前缀,使用配置里的。(例如希晓) + qrCodePrefix = pileStationVO.getQrcodePrefix(); + } else { + // 为空则给平台二维码前缀 + qrCodePrefix = pileConnectorInfoService.getPileConnectorQrCodeUrl(null); + } + } - byte[] qrCodePrefixByteArr = BytesUtil.str2Asc(qrCodePrefix); + byte[] qrCodePrefixByteArr = BytesUtil.str2Asc(qrCodePrefix); - // 二维码前缀长度 二维码前缀长度长度最大不超过200 字节 - int length = qrCodePrefix.length(); - byte[] qrCodePrefixLengthByteArr = BytesUtil.intToBytes(length, 1); + // 二维码前缀长度 二维码前缀长度长度最大不超过200 字节 + int length = qrCodePrefix.length(); + byte[] qrCodePrefixLengthByteArr = BytesUtil.intToBytes(length, 1); - // 拼接消息体 - byte[] msg = Bytes.concat(pileSnByteArr, qrCodeTypeByteArr, qrCodePrefixLengthByteArr, qrCodePrefixByteArr); + // 拼接消息体 + byte[] msg = Bytes.concat(pileSnByteArr, qrCodeTypeByteArr, qrCodePrefixLengthByteArr, qrCodePrefixByteArr); - // push消息 - boolean result = this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_ISSUE_QRCODE_CODE); - log.info("=====平台下发指令===== pileSn:{}, 下发二维码,地址为:{}", pileSn, qrCodePrefix); - } + // push消息 + boolean result = this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_ISSUE_QRCODE_CODE); + log.info("=====平台下发指令===== pileSn:{}, 下发二维码,地址为:{}", pileSn, qrCodePrefix); + } - /** - * 0x56 对时设置 - * @param command - */ - @Override - public void pushProofreadTimeCommand(ProofreadTimeCommand command) { - // log.info("充电桩对时,thread:{}", Thread.currentThread().getName()); - String pileSn = command.getPileSn(); - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + /** + * 0x56 对时设置 + * + * @param command + */ + @Override + public void pushProofreadTimeCommand(ProofreadTimeCommand command) { + // log.info("充电桩对时,thread:{}", Thread.currentThread().getName()); + String pileSn = command.getPileSn(); + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 时间 - Date date = DateUtils.parseDate(DateUtils.getDateTime()); - byte[] dateBytes = Cp56Time2aUtil.date2Hbyte(date); + // 时间 + Date date = DateUtils.parseDate(DateUtils.getDateTime()); + byte[] dateBytes = Cp56Time2aUtil.date2Hbyte(date); - // 拼装msg - byte[] msg = Bytes.concat(pileSnByteArr, dateBytes); + // 拼装msg + byte[] msg = Bytes.concat(pileSnByteArr, dateBytes); - this.push(msg, pileSn, YKCFrameTypeCode.TIME_CHECK_SETTING_CODE); - log.info("[充电桩:{}对时, 时间:{}, CP56Time2a:{}]", pileSn, DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, date), BytesUtil.binary(dateBytes, 16)); - } + this.push(msg, pileSn, YKCFrameTypeCode.TIME_CHECK_SETTING_CODE); + log.info("[充电桩:{}对时, 时间:{}, CP56Time2a:{}]", pileSn, DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, date), BytesUtil.binary(dateBytes, 16)); + } - /** - * 向充电桩发送计费模板 - * @param command - */ - @Override - public void pushPublishPileBillingTemplate(PublishPileBillingTemplateCommand command) { - BillingTemplateVO billingTemplateVO = command.getBillingTemplateVO(); - String pileSn = command.getPileSn(); - // 转换 - byte[] messageBody = pileBillingTemplateService.generateBillingTemplateMsgBody(pileSn, billingTemplateVO); - // 发送 - if (messageBody != null) { - this.push(messageBody, pileSn, YKCFrameTypeCode.BILLING_TEMPLATE_SETTING_CODE); - } - } + /** + * 向充电桩发送计费模板 + * + * @param command + */ + @Override + public void pushPublishPileBillingTemplate(PublishPileBillingTemplateCommand command) { + BillingTemplateVO billingTemplateVO = command.getBillingTemplateVO(); + String pileSn = command.getPileSn(); + // 转换 + byte[] messageBody = pileBillingTemplateService.generateBillingTemplateMsgBody(pileSn, billingTemplateVO); + // 发送 + if (messageBody != null) { + this.push(messageBody, pileSn, YKCFrameTypeCode.BILLING_TEMPLATE_SETTING_CODE); + } + } - public static void main(String[] args) { - System.out.println(Constants.updateServerPort); - String numHex = Integer.toHexString(21); - byte[] bytes = BytesUtil.hexString2Bytes(numHex); - System.out.println(bytes); + public static void main(String[] args) { + System.out.println(Constants.updateServerPort); + String numHex = Integer.toHexString(21); + byte[] bytes = BytesUtil.hexString2Bytes(numHex); + System.out.println(bytes); - } + } - @Override - public void pushUpdateFileCommand(UpdateFirmwareCommand command) { - List pileSns = command.getPileSnList(); - if (CollectionUtils.isEmpty(pileSns)) { - return; - } + @Override + public void pushUpdateFileCommand(UpdateFirmwareCommand command) { + List pileSns = command.getPileSnList(); + if (CollectionUtils.isEmpty(pileSns)) { + return; + } - List list = pileModelInfoService.getPileModelInfoByPileSnList(pileSns); - if (CollectionUtils.isEmpty(list)) { - return; - } - // 获取桩型号 01:直流 02:交流 - byte[] pileModelType; - for (PileModelInfoVO pileModelInfoVO : list) { - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileModelInfoVO.getPileSn()); + List list = pileModelInfoService.getPileModelInfoByPileSnList(pileSns); + if (CollectionUtils.isEmpty(list)) { + return; + } + // 获取桩型号 01:直流 02:交流 + byte[] pileModelType; + for (PileModelInfoVO pileModelInfoVO : list) { + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileModelInfoVO.getPileSn()); - // 数据库 1- 快充(直流) 2-慢充(交流) + // 数据库 1- 快充(直流) 2-慢充(交流) /*if (StringUtils.equals(pileModelInfoVO.getSpeedType(), Constants.ONE)) { pileModelType = Constants.oneByteArray; } else { pileModelType = Constants.twoByteArray; }*/ - pileModelType = Constants.zeroByteArray; + pileModelType = Constants.zeroByteArray; - // 额定功率 - String ratedPower = pileModelInfoVO.getRatedPower(); - int i = Integer.parseInt(ratedPower); + // 额定功率 + String ratedPower = pileModelInfoVO.getRatedPower(); + int i = Integer.parseInt(ratedPower); - // byte[] ratedPowerByteArr = Base64.getDecoder().decode(ratedPower); - byte[] ratedPowerByteArr = BytesUtil.ensureLength(Constants.zeroByteArray, 2); + // byte[] ratedPowerByteArr = Base64.getDecoder().decode(ratedPower); + byte[] ratedPowerByteArr = BytesUtil.ensureLength(Constants.zeroByteArray, 2); - // 升级服务器地址 - byte[] updateServerAddressByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getServerAddress()), 16); + // 升级服务器地址 + byte[] updateServerAddressByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getServerAddress()), 16); - // 升级服务器端口 - byte[] updateServerPortByteArr = BytesUtil.ensureLength(BytesUtil.hexString2Bytes(Integer.toHexString(command.getPort())), 2); + // 升级服务器端口 + byte[] updateServerPortByteArr = BytesUtil.ensureLength(BytesUtil.hexString2Bytes(Integer.toHexString(command.getPort())), 2); - // 用户名 - byte[] userNameByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getUsername()), 16); + // 用户名 + byte[] userNameByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getUsername()), 16); - // 密码 - byte[] passwordByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getPassword()), 16); + // 密码 + byte[] passwordByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getPassword()), 16); - // 文件路径 - byte[] filePathByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getFilePath()), 32); + // 文件路径 + byte[] filePathByteArr = BytesUtil.ensureLength(BytesUtil.str2Asc(command.getFilePath()), 32); - // 执行控制 01:立即执行 02:空闲执行 - byte[] performTypeByteArr = Constants.oneByteArray; + // 执行控制 01:立即执行 02:空闲执行 + byte[] performTypeByteArr = Constants.oneByteArray; - // 下载超时时间 单位:min - byte[] overTimeByteArr = new byte[]{0x05}; + // 下载超时时间 单位:min + byte[] overTimeByteArr = new byte[]{0x05}; - byte[] msgBody = Bytes.concat(pileSnByteArr, pileModelType, ratedPowerByteArr, updateServerAddressByteArr, - updateServerPortByteArr, userNameByteArr, passwordByteArr, filePathByteArr, performTypeByteArr, overTimeByteArr); + byte[] msgBody = Bytes.concat(pileSnByteArr, pileModelType, ratedPowerByteArr, updateServerAddressByteArr, + updateServerPortByteArr, userNameByteArr, passwordByteArr, filePathByteArr, performTypeByteArr, overTimeByteArr); - this.push(msgBody, pileModelInfoVO.getPileSn(), YKCFrameTypeCode.REMOTE_UPDATE_CODE); - log.info("【=====平台下发指令=====】:远程更新, 桩号:{}, 类型:{}, 额定功率:{}, 服务器地址:{}, 端口号:{}, 用户名:{}, 密码:{}, 文件路径:{}", - pileModelInfoVO.getPileSn(), pileModelType, BytesUtil.bcd2Str(ratedPowerByteArr), BytesUtil.binary(updateServerAddressByteArr, 16), - BytesUtil.binary(updateServerPortByteArr, 16), BytesUtil.binary(userNameByteArr, 16), BytesUtil.binary(passwordByteArr, 16), - BytesUtil.binary(filePathByteArr, 16)); - } - } + this.push(msgBody, pileModelInfoVO.getPileSn(), YKCFrameTypeCode.REMOTE_UPDATE_CODE); + log.info("【=====平台下发指令=====】:远程更新, 桩号:{}, 类型:{}, 额定功率:{}, 服务器地址:{}, 端口号:{}, 用户名:{}, 密码:{}, 文件路径:{}", + pileModelInfoVO.getPileSn(), pileModelType, BytesUtil.bcd2Str(ratedPowerByteArr), BytesUtil.binary(updateServerAddressByteArr, 16), + BytesUtil.binary(updateServerPortByteArr, 16), BytesUtil.binary(userNameByteArr, 16), BytesUtil.binary(passwordByteArr, 16), + BytesUtil.binary(filePathByteArr, 16)); + } + } - @Override - public void pushPileSettingCommand(PileSettingCommand command) { + @Override + public void pushPileSettingCommand(PileSettingCommand command) { - // 充电桩编号 - String pileSn = command.getPileSn(); - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + // 充电桩编号 + String pileSn = command.getPileSn(); + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 工作状态 - String workingState = command.getWorkingState(); - byte[] workingStateByteArr; - if (StringUtils.equals(workingState, "0")) { - workingStateByteArr = Constants.zeroByteArray; - } else { - workingStateByteArr = Constants.oneByteArray; - } + // 工作状态 + String workingState = command.getWorkingState(); + byte[] workingStateByteArr; + if (StringUtils.equals(workingState, "0")) { + workingStateByteArr = Constants.zeroByteArray; + } else { + workingStateByteArr = Constants.oneByteArray; + } - // 最大功率 - Integer maxPower = command.getMaxPower(); - byte[] maxPowerByteArr = BytesUtil.str2Bcd(maxPower.toString()); + // 最大功率 + Integer maxPower = command.getMaxPower(); + byte[] maxPowerByteArr = BytesUtil.str2Bcd(maxPower.toString()); - byte[] msg = Bytes.concat(pileSnByteArr, workingStateByteArr, maxPowerByteArr); + byte[] msg = Bytes.concat(pileSnByteArr, workingStateByteArr, maxPowerByteArr); - this.push(msg, pileSn, YKCFrameTypeCode.CHARGING_PILE_WORKING_PARAMETER_SETTING_CODE); - } + this.push(msg, pileSn, YKCFrameTypeCode.CHARGING_PILE_WORKING_PARAMETER_SETTING_CODE); + } - /** - * 平台査询工作参数 - * @param command - */ - @Override - public void pushQueryWorkParamsCommand(QueryWorkParamsCommand command) { - // 桩编号 - String pileSn = command.getPileSn(); - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 桩类型 - byte[] pileType = Constants.oneByteArray; - PileModelInfoVO info = pileModelInfoService.getPileModelInfoByPileSn(pileSn); - if (info == null) { - throw new BusinessException(ReturnCodeEnum.CODE_GET_PILE_DETAIL_ERROR); - } - String chargerPileType = info.getChargerPileType(); - if (StringUtils.equals("1", chargerPileType)) { - // 直流 - pileType = Constants.zeroByteArray; - } - // 拼装msg信息 - byte[] msg = Bytes.concat(pileSnByteArr, pileType); + /** + * 平台査询工作参数 + * + * @param command + */ + @Override + public void pushQueryWorkParamsCommand(QueryWorkParamsCommand command) { + // 桩编号 + String pileSn = command.getPileSn(); + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + // 桩类型 + byte[] pileType = Constants.oneByteArray; + PileModelInfoVO info = pileModelInfoService.getPileModelInfoByPileSn(pileSn); + if (info == null) { + throw new BusinessException(ReturnCodeEnum.CODE_GET_PILE_DETAIL_ERROR); + } + String chargerPileType = info.getChargerPileType(); + if (StringUtils.equals("1", chargerPileType)) { + // 直流 + pileType = Constants.zeroByteArray; + } + // 拼装msg信息 + byte[] msg = Bytes.concat(pileSnByteArr, pileType); - this.push(msg, pileSn, YKCFrameTypeCode.QUERY_PILE_WORK_PARAMS_CODE); - } + this.push(msg, pileSn, YKCFrameTypeCode.QUERY_PILE_WORK_PARAMS_CODE); + } - /** - * 远程账户余额更新 - * @param command - */ - @Override - public void pushAccountBalanceUpdateCommand(RemoteAccountBalanceUpdateCommand command) { - // 桩编号 - String pileSn = command.getPileSn(); - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 枪口号 - String connectorCode = command.getConnectorCode(); - byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); - // 卡号 - String logicCard = command.getLogicCard(); - byte[] logicByteArr = BytesUtil.str2Bcd(logicCard); - logicByteArr = BytesUtil.checkLengthAndBehindAppendZero(logicByteArr, 16); - // 修改后账户余额 - String accountBalance = command.getAccountBalance(); - byte[] priceByte = YKCUtils.getPriceByte(accountBalance, 2); - // 拼装msg信息 - byte[] msg = Bytes.concat(pileSnByteArr, connectorCodeByteArr, logicByteArr, priceByte); + /** + * 远程账户余额更新 + * + * @param command + */ + @Override + public void pushAccountBalanceUpdateCommand(RemoteAccountBalanceUpdateCommand command) { + // 桩编号 + String pileSn = command.getPileSn(); + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + // 枪口号 + String connectorCode = command.getConnectorCode(); + byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); + // 卡号 + String logicCard = command.getLogicCard(); + byte[] logicByteArr = BytesUtil.str2Bcd(logicCard); + logicByteArr = BytesUtil.checkLengthAndBehindAppendZero(logicByteArr, 16); + // 修改后账户余额 + String accountBalance = command.getAccountBalance(); + byte[] priceByte = YKCUtils.getPriceByte(accountBalance, 2); + // 拼装msg信息 + byte[] msg = Bytes.concat(pileSnByteArr, connectorCodeByteArr, logicByteArr, priceByte); - this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_ACCOUNT_BALANCE_UPDATE_CODE); - } + this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_ACCOUNT_BALANCE_UPDATE_CODE); + } - /** - * 遥控地锁 - * @param command - */ - @Override - public void pushRemoteControlGroundLock(RemoteControlGroundLockCommand command) { - // 桩编号 - String pileSn = command.getPileSn(); - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + /** + * 遥控地锁 + * + * @param command + */ + @Override + public void pushRemoteControlGroundLock(RemoteControlGroundLockCommand command) { + // 桩编号 + String pileSn = command.getPileSn(); + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 枪口号 - String connectorCode = command.getConnectorCode(); - byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); + // 枪口号 + String connectorCode = command.getConnectorCode(); + byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); - // 升/降地锁 BCD 码 1 升锁 0X55,降锁 0XFF - byte[] operateByteArr; - if (Constants.ZERO.equals(command.getOperate())) { - operateByteArr = new byte[]{(byte) 0XFF}; - } else { - operateByteArr = new byte[]{0X55}; - } + // 升/降地锁 BCD 码 1 升锁 0X55,降锁 0XFF + byte[] operateByteArr; + if (Constants.ZERO.equals(command.getOperate())) { + operateByteArr = new byte[]{(byte) 0XFF}; + } else { + operateByteArr = new byte[]{0X55}; + } - // 预留位 BIN 码 4 全部置 0 (可用于多枪) - String obligate = "0000"; - byte[] obligateByteArr = BytesUtil.str2Bcd(obligate); + // 预留位 BIN 码 4 全部置 0 (可用于多枪) + String obligate = "0000"; + byte[] obligateByteArr = BytesUtil.str2Bcd(obligate); - // 拼装msg信息 - byte[] msg = Bytes.concat(pileSnByteArr, connectorCodeByteArr, operateByteArr, obligateByteArr); + // 拼装msg信息 + byte[] msg = Bytes.concat(pileSnByteArr, connectorCodeByteArr, operateByteArr, obligateByteArr); - this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_GROUND_LOCK_LIFTING_CODE); - } + this.push(msg, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_GROUND_LOCK_LIFTING_CODE); + } - /** - * 发送预约充电命令 - * @param command - */ - @Override - public void pushReservedChargingCommand(ReservedChargingCommand command) { - // 交易流水号 - String transactionCode = command.getTransactionCode(); - byte[] transactionCodeArr = BytesUtil.str2Bcd(transactionCode); + /** + * 发送预约充电命令 + * + * @param command + */ + @Override + public void pushReservedChargingCommand(ReservedChargingCommand command) { + // 交易流水号 + String transactionCode = command.getTransactionCode(); + byte[] transactionCodeArr = BytesUtil.str2Bcd(transactionCode); - // 桩编号 - String pileSn = command.getPileSn(); - byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); + // 桩编号 + String pileSn = command.getPileSn(); + byte[] pileSnByteArr = BytesUtil.str2Bcd(pileSn); - // 枪口号 - String connectorCode = command.getConnectorCode(); - byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); + // 枪口号 + String connectorCode = command.getConnectorCode(); + byte[] connectorCodeByteArr = BytesUtil.str2Bcd(connectorCode); - // 0x01:启动 0x02:取消 0x03:修改 - String operation = command.getOperation(); - byte[] operateByteArr = BytesUtil.str2Bcd(operation); + // 0x01:启动 0x02:取消 0x03:修改 + String operation = command.getOperation(); + byte[] operateByteArr = BytesUtil.str2Bcd(operation); - // 开始时间 - Date reservedStartTime = command.getReservedStartTime(); - byte[] reservedStartTimeByteArr = Cp56Time2aUtil.date2Hbyte(DateUtils.parseDate(reservedStartTime)); + // 开始时间 + Date reservedStartTime = command.getReservedStartTime(); + byte[] reservedStartTimeByteArr = Cp56Time2aUtil.date2Hbyte(DateUtils.parseDate(reservedStartTime)); - // 结束时间 - Date reservedEndTime = command.getReservedEndTime(); - byte[] reservedEndTimeByteArr = Cp56Time2aUtil.date2Hbyte(DateUtils.parseDate(reservedEndTime)); + // 结束时间 + Date reservedEndTime = command.getReservedEndTime(); + byte[] reservedEndTimeByteArr = Cp56Time2aUtil.date2Hbyte(DateUtils.parseDate(reservedEndTime)); - // 启动金额 - BigDecimal amount = command.getAmount(); - byte[] amountByteArr = YKCUtils.getPriceByte(amount.toString(), 2); + // 启动金额 + BigDecimal amount = command.getAmount(); + byte[] amountByteArr = YKCUtils.getPriceByte(amount.toString(), 2); - // 拼装msg信息 - byte[] msg = Bytes.concat(transactionCodeArr, pileSnByteArr, connectorCodeByteArr, operateByteArr, - reservedStartTimeByteArr, reservedEndTimeByteArr, amountByteArr); - this.push(msg, pileSn, YKCFrameTypeCode.RESERVE_CHARGING_CODE); - } + // 拼装msg信息 + byte[] msg = Bytes.concat(transactionCodeArr, pileSnByteArr, connectorCodeByteArr, operateByteArr, + reservedStartTimeByteArr, reservedEndTimeByteArr, amountByteArr); + + this.push(msg, pileSn, YKCFrameTypeCode.RESERVE_CHARGING_CODE); + + log.info("=====平台下发指令=====: 预约充电指令, 交易流水号:{}, 桩编号:{}, 枪口号:{}, 操作:{}, 开始时间:{}, 结束时间:{}, 启动金额:{}", + transactionCode, pileSn, connectorCode, operation, DateUtils.formatDateTime(reservedStartTime), DateUtils.formatDateTime(reservedEndTime), amount); + } }