diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java index fd6337427..dce523302 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java @@ -14,6 +14,7 @@ import com.jsowell.pile.domain.AdapayMemberAccount; import com.jsowell.pile.domain.MemberPlateNumberRelation; import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.ykcCommond.ReservationChargingCommand; +import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.service.programlogic.AbstractProgramLogic; @@ -83,7 +84,11 @@ public class TempController extends BaseController { public RestApiResponse tempStartCharging(@RequestBody QueryOrderDTO dto) { RestApiResponse response = null; try { - eBikeSendCommandService.startCharging(dto.getPileSn(), dto.getConnectorCode()); + StartChargingCommand command = StartChargingCommand.builder() + .pileSn(dto.getPileSn()) + .connectorCode(dto.getConnectorCode()) + .build(); + eBikeSendCommandService.sendStartChargingCommand(command); response = new RestApiResponse<>(); } catch (Exception e) { logger.error("电单车开始充电 error", e); diff --git a/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java b/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java index eb72349b7..42be0aa5f 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java +++ b/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java @@ -10,6 +10,8 @@ import java.math.BigDecimal; * @author jsowell */ public class Constants { + // 电单车协议包头 + public static final String EBIKE_HEADER = "DNY"; // 十六进制前缀 public static final String HEX_PREFIX = "0x"; diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java b/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java index e9322b2ef..bde1b7224 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java @@ -380,7 +380,7 @@ public class BytesUtil { // int i = BytesUtil.bytesToIntLittle(length); // System.out.println(i); - String testStr = "DNY"; + String testStr = Constants.EBIKE_HEADER; byte[] hexBytes = stringToHexBytes(testStr, 3); System.out.println("Hex Bytes: " + bytesToHex(hexBytes)); } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java index d53155360..ff1643411 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java @@ -1,5 +1,6 @@ package com.jsowell.netty.decoder; +import com.jsowell.common.constant.Constants; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; @@ -47,7 +48,7 @@ public class StartAndLengthFieldFrameDecoder extends ByteToMessageDecoder { buffer.getBytes(beginReader, headerBytes, 0, HEADER_LENGTH_DNY); String header = new String(headerBytes, StandardCharsets.UTF_8); // log.info("检查包头是否是DNY, header:{}", header); - if ("DNY".equals(header)) { + if (Constants.EBIKE_HEADER.equals(header)) { // 处理 DNY 协议 decodeDnyMessage(buffer, out, beginReader); return; @@ -73,7 +74,7 @@ public class StartAndLengthFieldFrameDecoder extends ByteToMessageDecoder { byte[] headerBytes = new byte[HEADER_LENGTH_DNY]; buffer.getBytes(beginReader, headerBytes, 0, HEADER_LENGTH_DNY); String header = new String(headerBytes, StandardCharsets.UTF_8); - return "DNY".equals(header); + return Constants.EBIKE_HEADER.equals(header); } return false; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java index 99532daa5..b82c28e5d 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java @@ -2,6 +2,7 @@ package com.jsowell.pile.domain.ebike.serversend; import com.google.common.primitives.Bytes; import com.jsowell.common.YouDianUtils; +import com.jsowell.common.constant.Constants; import com.jsowell.common.util.BytesUtil; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import lombok.*; @@ -35,7 +36,7 @@ public class EBikeMessageCmd82 extends AbsEBikeMessage { @Override public byte[] getMessageBytes() { // 包头 - byte[] headerBytes = BytesUtil.stringToHexBytes(header, 3); + byte[] headerBytes = BytesUtil.stringToHexBytes(Constants.EBIKE_HEADER, 3); // 物理ID byte[] physicalIdBytes = YouDianUtils.getPhysicalIdBytes(physicalId); // 消息ID @@ -75,13 +76,13 @@ public class EBikeMessageCmd82 extends AbsEBikeMessage { private int chargeCommand; // 充电命令 (1字节) // 告知设备的充电时长/电量, 如是0x0000则说明是充满自停, 其他数值则按照时长/电量充电, 且充满不会自停, - private int chargeDurationOrPower; // 充电时长/电量 (2字节) + private int chargeTimeOrPower; // 充电时长/电量 (2字节) // 生成给桩的交易流水号, 桩协议叫订单编号 private String transactionCode; // 订单编号 (16字节) // 最大充电时长、过载功率:(只对当前端口当前订单有效,不影响其他端口)动态设置此参数,如果参数为0表示不修改,会使用设备的设置值,默认10小时 - private int maxChargeDuration; // 最大充电时长 (2字节) + private int maxChargeTime; // 最大充电时长 (2字节) private int overloadPower; // 过载功率 (2字节) // 二维码灯:0=打开,1=关闭,针对部分有二维码灯的设备有效。此设置是针对下一次插头插入时是否点亮二维码背光灯,保存在内存中,断电重启后就会失效 @@ -112,13 +113,13 @@ public class EBikeMessageCmd82 extends AbsEBikeMessage { this.chargeCommand = BytesUtil.bytesToIntLittle(new byte[]{chargeCommandBytes}); byte[] chargeDurationOrPowerBytes = Arrays.copyOfRange(dataBytes, 7, 9); - this.chargeDurationOrPower = BytesUtil.bytesToIntLittle(chargeDurationOrPowerBytes); + this.chargeTimeOrPower = BytesUtil.bytesToIntLittle(chargeDurationOrPowerBytes); byte[] orderNumberBytes = Arrays.copyOfRange(dataBytes, 9, 25); this.transactionCode = BytesUtil.bcd2StrLittle(orderNumberBytes); byte[] maxChargeDurationBytes = Arrays.copyOfRange(dataBytes, 25, 27); - this.maxChargeDuration = BytesUtil.bytesToIntLittle(maxChargeDurationBytes); + this.maxChargeTime = BytesUtil.bytesToIntLittle(maxChargeDurationBytes); byte[] overloadPowerBytes = Arrays.copyOfRange(dataBytes, 27, 29); this.overloadPower = BytesUtil.bytesToIntLittle(overloadPowerBytes); @@ -159,11 +160,11 @@ public class EBikeMessageCmd82 extends AbsEBikeMessage { // 充电命令 byte[] chargeCommandBytes = BytesUtil.intToBytesLittle(chargeCommand, 1); // 充电时长/电量 - byte[] chargeDurationOrPowerBytes = BytesUtil.intToBytesLittle(chargeDurationOrPower, 2); + byte[] chargeDurationOrPowerBytes = BytesUtil.intToBytesLittle(chargeTimeOrPower, 2); // 订单编号 byte[] orderNumberBytes = BytesUtil.ensureLength(BytesUtil.str2Bcd(transactionCode), 16); // 最大充电时长 - byte[] maxChargeDurationBytes = BytesUtil.intToBytesLittle(maxChargeDuration, 2); + byte[] maxChargeDurationBytes = BytesUtil.intToBytesLittle(maxChargeTime, 2); // 过载功率 byte[] overloadPowerBytes = BytesUtil.intToBytesLittle(overloadPower, 2); // 二维码灯 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java index c683765f8..f6c97fefa 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java @@ -15,4 +15,9 @@ import lombok.NoArgsConstructor; public class StopChargingCommand { private String pileSn; private String connectorCode; + + /** + * 交易流水号 + */ + private String transactionCode; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java index 6f2a81956..901f46515 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java @@ -1,10 +1,23 @@ package com.jsowell.pile.service; +import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; +import com.jsowell.pile.domain.ykcCommond.StopChargingCommand; + /** * 电单车发送命令服务 */ public interface EBikeSendCommandService { - // void send(String pileSn, AbsEBikeMessage msg); - void startCharging(String pileSn, String connectorCode); + /** + * 启动充电 + * @param command + */ + void sendStartChargingCommand(StartChargingCommand command); + + /** + * 停止充电 + * @param command + */ + void sendStopChargingCommand(StopChargingCommand command); + } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java index 9e0c86e89..cb7ed5bd6 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java @@ -3,9 +3,12 @@ package com.jsowell.pile.service.impl; import com.jsowell.common.enums.ykc.PileChannelEntity; import com.jsowell.common.util.BytesUtil; import com.jsowell.common.util.RandomUtil; +import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.IdUtils; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.serversend.EBikeMessageCmd82; +import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; +import com.jsowell.pile.domain.ykcCommond.StopChargingCommand; import com.jsowell.pile.service.EBikeSendCommandService; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; @@ -20,15 +23,23 @@ import java.util.Objects; @Service public class EBikeSendCommandServiceImpl implements EBikeSendCommandService { + // 过载功率, 单位0.1W, 2450 * 0.1 = 2450W + private final int OVER_LOAD_POWER = 2450; + /** * 电单车发送启动充电指令 - * @param pileSn 电单车桩号 - * @param connectorCode 枪口号 */ @Override - public void startCharging(String pileSn, String connectorCode) { + public void sendStartChargingCommand(StartChargingCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + String transactionCode = command.getTransactionCode(); + if (StringUtils.isBlank(transactionCode)) { + transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); + } + + // 组装参数 EBikeMessageCmd82 message = new EBikeMessageCmd82(); - message.setHeader("DNY"); message.setPhysicalId(Integer.parseInt(pileSn)); message.setMessageId(RandomUtil.getRandomNumber(4)); message.setCommand("82"); @@ -44,16 +55,63 @@ public class EBikeSendCommandServiceImpl implements EBikeSendCommandService { data.setChargeCommand(1); // 充电时长/功率 int chargeDurationOrPower = 0; - data.setChargeDurationOrPower(chargeDurationOrPower); + data.setChargeTimeOrPower(chargeDurationOrPower); // 订单编号 - String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); data.setTransactionCode(transactionCode); // 最大充电时长 - data.setMaxChargeDuration(0); + data.setMaxChargeTime(0); // 过载功率 - data.setOverloadPower(3000); + data.setOverloadPower(OVER_LOAD_POWER); + data.setQrCodeLight(0); + data.setLongChargeMode(0); + data.setExtraFloatChargeTime(0); + data.setSkipShortCircuitDetection(0); + data.setNoUserPullOutCheck(0); + data.setForceAutoStopWhenFull(0); + data.setFullChargePower(0); + data.setMaxFullChargePowerCheckTime(0); + message.setData(data); + this.send(message); + } + + /** + * 发送停止充电指令 + * @param command + */ + @Override + public void sendStopChargingCommand(StopChargingCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + String transactionCode = command.getTransactionCode(); + + // 组装参数 + EBikeMessageCmd82 message = new EBikeMessageCmd82(); + message.setPhysicalId(Integer.parseInt(pileSn)); + message.setMessageId(RandomUtil.getRandomNumber(4)); + message.setCommand("82"); + + EBikeMessageCmd82.SpecificData data = new EBikeMessageCmd82.SpecificData(); + // 充电模式 + data.setRateMode(3); + // 余额或有效期 + data.setBalanceOrValidity(1234); + // 端口号 + data.setPortNumber(Integer.parseInt(connectorCode)); + // 充电命令 + data.setChargeCommand(0); + // 充电时长/功率 + int chargeDurationOrPower = 0; + data.setChargeTimeOrPower(chargeDurationOrPower); + + // 订单编号 + data.setTransactionCode(transactionCode); + + // 最大充电时长 + data.setMaxChargeTime(0); + // 过载功率 + data.setOverloadPower(OVER_LOAD_POWER); data.setQrCodeLight(0); data.setLongChargeMode(0); data.setExtraFloatChargeTime(0); 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 077060897..70d2c7d84 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 @@ -281,6 +281,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { } catch (Exception e) { throw new RuntimeException(e); } + log.info("【=====平台下发充电指令=====】:订单id:{}, 桩号:{}, 枪口号:{}, 逻辑卡号:{}, 物理卡号:{}, 账户余额:{}", transactionCode, pileSn, BytesUtil.bcd2Str(connectorCodeByteArr), logicCardNum, physicsCardNum, chargeAmount); }