diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileBillingTemplateController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileBillingTemplateController.java index 8336adeb2..b227ddcab 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileBillingTemplateController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileBillingTemplateController.java @@ -115,6 +115,7 @@ public class PileBillingTemplateController extends BaseController { public AjaxResult createBillingTemplate(@RequestBody CreateOrUpdateBillingTemplateDTO dto) { logger.info("新增计费模板 param:{}", JSON.toJSONString(dto)); pileBillingTemplateService.createBillingTemplate(dto); + publishBillingTemplate(dto); // 发布 return AjaxResult.success(); } @@ -128,9 +129,19 @@ public class PileBillingTemplateController extends BaseController { public AjaxResult updateBillingTemplate(@RequestBody CreateOrUpdateBillingTemplateDTO dto) { logger.info("修改计费模板 param:{}", JSON.toJSONString(dto)); pileBillingTemplateService.updateBillingTemplate(dto); + publishBillingTemplate(dto); // 发布 return AjaxResult.success(); } + private void publishBillingTemplate(CreateOrUpdateBillingTemplateDTO dto) { + // 发布计费模板 + PublishBillingTemplateDTO publishBillingTemplateDTO = new PublishBillingTemplateDTO(); + publishBillingTemplateDTO.setTemplateId(dto.getBillingTemplateId()); + publishBillingTemplateDTO.setStationId(dto.getStationId()); + logger.info("新增或者更新后发布计费模板, param:{}", JSON.toJSONString(publishBillingTemplateDTO)); + pileRemoteService.publishBillingTemplate(publishBillingTemplateDTO); + } + /** * 查询公共计费模板 */ diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java index 62b374149..9b04e29a9 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java @@ -233,6 +233,7 @@ public class PileBillingTemplateServiceImpl implements PileBillingTemplateServic log.info("根据计费模板id:{},查询为null。无法修改直接返回", dto.getBillingTemplateId()); return; } + dto.setStationId(billingTemplate.getStationId() + ""); billingTemplate.setType(dto.getType()); billingTemplate.setTemplateRemark(dto.getTemplateRemark()); 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 11b2edd94..981d8b094 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 @@ -61,11 +61,94 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { YKCUtils.frameType2Str(YKCFrameTypeCode.RESERVATION_CHARGING_SETUP_CODE.getBytes()) ); - public byte[] send(byte[] msg, String pileSn, Enum frameTypeCode) throws Exception { - return this.send(msg, pileSn, frameTypeCode, 1, TimeUnit.SECONDS); + /** + * 发送消息,无返回值 + */ + public void runSend(byte[] msg, String pileSn, Enum frameTypeCode) throws Exception { + // 通过桩编号获取channel + ChannelHandlerContext ctx = PileChannelEntity.getChannelByPileSn(pileSn); + String value = ((YKCFrameTypeCode) frameTypeCode).getValue(); // 帧类型名称 + if (Objects.isNull(ctx)) { + log.error("push命令[{}]失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", value, pileSn); + throw new NullPointerException("channel"); + } + if(msg == null) { + throw new NullPointerException("msg"); + } + + /* + 拼接报文 + */ + // 起始标志 + byte[] head = new byte[]{0x68}; + + // 序列号域 + byte[] serialNumber = new byte[]{0x00, 0x00}; + + // 加密标志 + byte[] encryptFlag = new byte[]{0x00}; + + // 帧类型标志 + byte[] frameType = new byte[]{(byte) ((YKCFrameTypeCode) frameTypeCode).getCode()}; + + // 序列号域+加密标志+帧类型标志+消息体 + byte[] temp = Bytes.concat(serialNumber, encryptFlag, frameType, msg); + + // 数据长度 + 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); + ByteBuf byteBuf = ctx.channel().alloc().buffer().writeBytes(writeMsg); + ChannelFuture channelFuture = ctx.channel().writeAndFlush(byteBuf); + channelFuture.addListener((ChannelFutureListener) channelFutureListener -> { + // 检查操作的状态 + if (channelFutureListener.isSuccess()) { + log.info("【push结果===>成功】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", + pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), value, wholeMsg); + } else { + // 如果发生错误,则访问描述原因的Throwable + Throwable cause = channelFutureListener.cause(); + log.info("【push结果===>失败】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", + pileSn, ctx.channel().remoteAddress(), ctx.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); + } } - public byte[] send(byte[] msg, String pileSn, Enum frameTypeCode, long timeout, TimeUnit unit) throws Exception { + /** + * 发送消息,有返回值 + * @param msg + * @param pileSn + * @param frameTypeCode + * @return + * @throws Exception + */ + public byte[] supplySend(byte[] msg, String pileSn, Enum frameTypeCode) throws Exception { + return this.supplySend(msg, pileSn, frameTypeCode, 1, TimeUnit.SECONDS); + } + + /** + * 发送消息,有返回值 + * @param msg + * @param pileSn + * @param frameTypeCode + * @return + * @throws Exception + */ + public byte[] supplySend(byte[] msg, String pileSn, Enum frameTypeCode, long timeout, TimeUnit unit) throws Exception { // 通过桩编号获取channel ChannelHandlerContext ctx = PileChannelEntity.getChannelByPileSn(pileSn); String value = ((YKCFrameTypeCode) frameTypeCode).getValue(); // 帧类型名称 @@ -202,7 +285,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msgBody = Bytes.concat(orderIdByteArr, pileSnByteArr, connectorCodeByteArr, logicCardNumByteArr, physicsCardNumByteArr, accountBalanceByteArr); try { - this.send(msgBody, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_START_CHARGING_CODE); + this.supplySend(msgBody, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_START_CHARGING_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -223,7 +306,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { // 远程停机 byte[] msgBody = Bytes.concat(BytesUtil.str2Bcd(pileSn), BytesUtil.str2Bcd(connectorCode)); try { - this.send(msgBody, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_STOP_CHARGING_CODE); + this.supplySend(msgBody, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_STOP_CHARGING_CODE); } catch (Exception e) { log.error("发送停止充电 error:", e); } @@ -236,7 +319,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { String connectorCode = command.getConnectorCode(); byte[] msg = BytesUtil.str2Bcd(pileSn + connectorCode); try { - this.send(msg, pileSn, YKCFrameTypeCode.READ_REAL_TIME_MONITOR_DATA_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.READ_REAL_TIME_MONITOR_DATA_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -249,7 +332,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msg = BytesUtil.str2Bcd(pileSn + Constants.ZERO_ONE); log.info("【=====平台下发指令=====】:重启充电桩:,{}", pileSn); try { - this.send(msg, pileSn, YKCFrameTypeCode.REMOTE_RESTART_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.REMOTE_RESTART_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -294,7 +377,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { // push消息 try { - this.send(msg, pileSn, YKCFrameTypeCode.REMOTE_ISSUE_QRCODE_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.REMOTE_ISSUE_QRCODE_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -320,7 +403,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msg = Bytes.concat(pileSnByteArr, dateBytes); try { - this.send(msg, pileSn, YKCFrameTypeCode.TIME_CHECK_SETTING_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.TIME_CHECK_SETTING_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -341,7 +424,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { // 发送 if (messageBody != null) { try { - this.send(messageBody, pileSn, YKCFrameTypeCode.BILLING_TEMPLATE_SETTING_CODE); + this.supplySend(messageBody, pileSn, YKCFrameTypeCode.BILLING_TEMPLATE_SETTING_CODE); } catch (Exception e) { log.error("向充电桩发送计费模板error", e); } @@ -404,7 +487,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { updateServerPortByteArr, userNameByteArr, passwordByteArr, filePathByteArr, performTypeByteArr, overTimeByteArr); try { - this.send(msgBody, pileModelInfoVO.getPileSn(), YKCFrameTypeCode.REMOTE_UPDATE_CODE); + this.supplySend(msgBody, pileModelInfoVO.getPileSn(), YKCFrameTypeCode.REMOTE_UPDATE_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -438,7 +521,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msg = Bytes.concat(pileSnByteArr, workingStateByteArr, maxPowerByteArr); try { - this.send(msg, pileSn, YKCFrameTypeCode.CHARGING_PILE_WORKING_PARAMETER_SETTING_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.CHARGING_PILE_WORKING_PARAMETER_SETTING_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -469,7 +552,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msg = Bytes.concat(pileSnByteArr, pileType); try { - this.send(msg, pileSn, YKCFrameTypeCode.QUERY_PILE_WORK_PARAMS_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.QUERY_PILE_WORK_PARAMS_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -499,7 +582,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msg = Bytes.concat(pileSnByteArr, connectorCodeByteArr, logicByteArr, priceByte); try { - this.send(msg, pileSn, YKCFrameTypeCode.REMOTE_ACCOUNT_BALANCE_UPDATE_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.REMOTE_ACCOUNT_BALANCE_UPDATE_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -536,7 +619,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] msg = Bytes.concat(pileSnByteArr, connectorCodeByteArr, operateByteArr, obligateByteArr); try { - this.send(msg, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_GROUND_LOCK_CODE); + this.supplySend(msg, pileSn, YKCFrameTypeCode.REMOTE_CONTROL_GROUND_LOCK_CODE); } catch (Exception e) { throw new RuntimeException(e); } @@ -607,7 +690,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { byte[] response; try { - response = this.send(msg, pileSn, YKCFrameTypeCode.RESERVATION_CHARGING_SETUP_CODE); + response = this.supplySend(msg, pileSn, YKCFrameTypeCode.RESERVATION_CHARGING_SETUP_CODE); } catch (Exception e) { log.error("发送消息异常", e); response = null; diff --git a/jsowell-ui/src/views/billing/template/components/addBilling.vue b/jsowell-ui/src/views/billing/template/components/addBilling.vue index 439409763..4eabc8d69 100644 --- a/jsowell-ui/src/views/billing/template/components/addBilling.vue +++ b/jsowell-ui/src/views/billing/template/components/addBilling.vue @@ -288,7 +288,8 @@
取 消 - 确 定 + + 保存并发布