diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/TestController.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/TestController.java index 15d4710..652967a 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/TestController.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/TestController.java @@ -323,4 +323,33 @@ public class TestController extends BaseController { return ResponseEntity.ok("success"); } + @GetMapping("/api/offlineCardClearRequest") + public ResponseEntity offlineCardClearRequest() { + + List cardNoList = Lists.newArrayList("1000000000123456", "1000000000123457", "1000000000123458", "1000000000123459", "1000000000123460"); + + pileProtocolService.offlineCardClearRequest(OfflineCardClearRequest.newBuilder() + .setPileCode("20231212000010") + .setTotal(cardNoList.size()) + .addAllCardNo(cardNoList) + .build()); + + return ResponseEntity.ok("success"); + } + + @GetMapping("/api/offlineCardQueryRequest") + public ResponseEntity offlineCardQueryRequest() { + + List cardNoList = Lists.newArrayList("1000000000123456", "1000000000123457", "1000000000123458", "1000000000123459", "1000000000123460"); + + + pileProtocolService.offlineCardQueryRequest(OfflineCardQueryRequest.newBuilder() + .setPileCode("20231212000010") + .setTotal(cardNoList.size()) + .addAllCardNo(cardNoList) + .build()); + + return ResponseEntity.ok("success"); + } + } \ No newline at end of file diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java index 485be10..294914c 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/PileProtocolService.java @@ -7,12 +7,12 @@ package sanbing.jcpp.app.service; import sanbing.jcpp.infrastructure.queue.Callback; +import sanbing.jcpp.proto.gen.DownlinkProto; import sanbing.jcpp.proto.gen.DownlinkProto.OfflineCardBalanceUpdateRequest; import sanbing.jcpp.proto.gen.DownlinkProto.OfflineCardSyncRequest; import sanbing.jcpp.proto.gen.DownlinkProto.OtaRequest; import sanbing.jcpp.proto.gen.DownlinkProto.SetPricingRequest; import sanbing.jcpp.proto.gen.UplinkProto.UplinkQueueMessage; - import java.math.BigDecimal; import java.time.LocalDateTime; @@ -184,6 +184,25 @@ public interface PileProtocolService { */ void onTimeSyncResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback); + /** + * 离线卡数据清除 + */ + void offlineCardClearRequest(DownlinkProto.OfflineCardClearRequest request); + + /** + * 离线卡数据清除应答 + */ + void onOfflineCardClearResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback); + + /** + * 离线卡数据查询 + */ + void offlineCardQueryRequest(DownlinkProto.OfflineCardQueryRequest request); + + /** + * 离线卡数据查询应答 + */ + void onOfflineCardQueryResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback); /** * 充电过程BMS需求与充电机输出 */ diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java index 2c0e0f9..c928027 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java @@ -748,6 +748,57 @@ public class DefaultPileProtocolService implements PileProtocolService { callback.onSuccess(); } + @Override + public void offlineCardClearRequest(OfflineCardClearRequest request) { + UUID messageId = UUID.randomUUID(); + UUID requestId = UUID.randomUUID(); + + DownlinkRequestMessage.Builder downlinkRequestMessageBuilder = DownlinkRequestMessage.newBuilder() + .setMessageIdMSB(messageId.getMostSignificantBits()) + .setMessageIdLSB(messageId.getLeastSignificantBits()) + .setPileCode(request.getPileCode()) + .setRequestIdMSB(requestId.getMostSignificantBits()) + .setRequestIdLSB(requestId.getLeastSignificantBits()) + .setDownlinkCmd(DownlinkCmdEnum.OFFLINE_CARD_CLEAR_REQUEST.name()) + .setOfflineCardClearRequest(request); + downlinkCallService.sendDownlinkMessage(downlinkRequestMessageBuilder,request.getPileCode()); + } + + @Override + public void onOfflineCardClearResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback) { + log.info("接收到充电桩离线卡数据清除应答 {}", uplinkQueueMessage); + + // TODO 处理相关业务逻辑 + + callback.onSuccess(); + } + + @Override + public void offlineCardQueryRequest(OfflineCardQueryRequest request) { + UUID messageId = UUID.randomUUID(); + UUID requestId = UUID.randomUUID(); + + DownlinkRequestMessage.Builder downlinkRequestMessageBuilder = DownlinkRequestMessage.newBuilder() + .setMessageIdMSB(messageId.getMostSignificantBits()) + .setMessageIdLSB(messageId.getLeastSignificantBits()) + .setPileCode(request.getPileCode()) + .setRequestIdMSB(requestId.getMostSignificantBits()) + .setRequestIdLSB(requestId.getLeastSignificantBits()) + .setDownlinkCmd(DownlinkCmdEnum.OFFLINE_CARD_QUERY_REQUEST.name()) + .setOfflineCardQueryRequest(request); + downlinkCallService.sendDownlinkMessage(downlinkRequestMessageBuilder,request.getPileCode()); + } + + @Override + public void onOfflineCardQueryResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback) { + log.info("接收到充电桩离线卡数据查询应答 {}", uplinkQueueMessage); + + + // TODO 处理相关业务逻辑 + + callback.onSuccess(); + } + private static Period createPeriod(int sn, LocalTime beginTime, LocalTime endTime, PricingModelFlag flag) { Period period = new Period(); period.setSn(sn); diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java index e7b9c05..48727ca 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/queue/consumer/ProtocolUplinkConsumerService.java @@ -245,6 +245,14 @@ public class ProtocolUplinkConsumerService extends AbstractConsumerService { pileProtocolService.onTimeSyncResponse(uplinkQueueMsg, callback); + }else if (uplinkQueueMsg.hasOfflineCardClearResponse()) { + + pileProtocolService.onOfflineCardClearResponse(uplinkQueueMsg, callback); + + }else if (uplinkQueueMsg.hasOfflineCardQueryResponse()) { + + pileProtocolService.onOfflineCardQueryResponse(uplinkQueueMsg, callback); + } else if (uplinkQueueMsg.hasBmsDemandChargerOutputProto()) { pileProtocolService.postBmsDemandChargerOutput(uplinkQueueMsg, callback); diff --git a/jcpp-infrastructure-proto/src/main/proto/downlink.proto b/jcpp-infrastructure-proto/src/main/proto/downlink.proto index 14cd479..13a3090 100644 --- a/jcpp-infrastructure-proto/src/main/proto/downlink.proto +++ b/jcpp-infrastructure-proto/src/main/proto/downlink.proto @@ -36,6 +36,8 @@ message DownlinkRequestMessage { OfflineCardSyncRequest offlineCardSyncRequest = 31; TimeSyncRequest timeSyncRequest = 32; StartChargeResponse startChargeResponse = 33; + OfflineCardClearRequest offlineCardClearRequest = 34; + OfflineCardQueryRequest offlineCardQueryRequest = 35; } // 下行响应消息 @@ -246,3 +248,15 @@ message TimeSyncRequest { string pileCode = 1; string time = 2; } + +message OfflineCardClearRequest { + string pileCode = 1; // 充电桩编码 + int32 total = 2; // 清除离线卡的个数 + repeated string cardNo = 3; // 物理卡号集合 +} + +message OfflineCardQueryRequest { + string pileCode = 1; // 充电桩编码 + int32 total = 2; // 查询离线卡的个数 + repeated string cardNo = 3; // 物理卡号集合 +} diff --git a/jcpp-infrastructure-proto/src/main/proto/uplink.proto b/jcpp-infrastructure-proto/src/main/proto/uplink.proto index 262d957..c522284 100644 --- a/jcpp-infrastructure-proto/src/main/proto/uplink.proto +++ b/jcpp-infrastructure-proto/src/main/proto/uplink.proto @@ -45,6 +45,8 @@ message UplinkQueueMessage { TimeSyncResponse timeSyncResponse = 42; BmsDemandChargerOutputProto bmsDemandChargerOutputProto = 43; StartChargeRequest startChargeRequest = 44; + OfflineCardClearResponse offlineCardClearResponse = 45; + OfflineCardQueryResponse offlineCardQueryResponse = 46; } // 会话关闭事件 @@ -339,6 +341,34 @@ message TimeSyncResponse { string time = 2; } + + +message OfflineCardClearResponse { + string pileCode = 1; // 充电桩编码 + repeated ClearResult clearResult = 2; // 清除卡号结果集合 +} + +message ClearResult { + string cardNo = 1; // 物理卡号 + bool success = 2; + optional string errorMsg = 3; +} + + + +message OfflineCardQueryResponse { + string pileCode = 1; // 充电桩编码 + repeated QueryResult queryResult = 2; // 查询卡号结果集合 +} + +message QueryResult { + string cardNo = 1; // 物理卡号 + bool exist = 2; + +} + + + // BMS需求充电机输出 message BmsDemandChargerOutputProto { string pileCode = 4; diff --git a/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/property/PropertyUtils.java b/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/property/PropertyUtils.java index c504240..287f533 100644 --- a/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/property/PropertyUtils.java +++ b/jcpp-infrastructure-util/src/main/java/sanbing/jcpp/infrastructure/util/property/PropertyUtils.java @@ -15,6 +15,8 @@ import java.util.function.Function; public class PropertyUtils { + private PropertyUtils() {} + public static Map getProps(String properties) { Map configs = new HashMap<>(); if (StringUtils.isNotEmpty(properties)) { diff --git a/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java b/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java index 715c837..f75c294 100644 --- a/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java +++ b/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/DownlinkCmdEnum.java @@ -41,5 +41,9 @@ public enum DownlinkCmdEnum { OFFLINE_CARD_SYNC_REQUEST, + OFFLINE_CARD_CLEAR_REQUEST, + + OFFLINE_CARD_QUERY_REQUEST, + START_CHARGE_ACK } \ No newline at end of file diff --git a/jcpp-protocol-yunkuaichong/READMD.md b/jcpp-protocol-yunkuaichong/READMD.md index 407d40e..8746188 100644 --- a/jcpp-protocol-yunkuaichong/READMD.md +++ b/jcpp-protocol-yunkuaichong/READMD.md @@ -141,3 +141,21 @@ #### 0x55 对时设置应答 `68 12 01 00 00 55 20 23 12 12 00 00 10 E0 2E 0C 0C 15 08 19 AB 37` + +#### 0x46 离线卡数据清除 +`68 37 03 00 00 46 20 23 12 12 00 00 10 05 00 00 00 10 00 00 00 00 12 34 56 10 00 00 00 00 12 34 57 10 00 00 00 00 12 34 58 10 00 00 00 00 12 34 59 10 00 00 00 00 12 34 60 76 2f` + +#### 0x45 离线卡数据清除应答 +#### 成功 +`68 3d 19 00 00 45 20 23 12 12 00 00 10 10 00 00 00 00 12 34 56 01 02 10 00 00 00 00 12 34 57 01 02 10 00 00 00 00 12 34 58 01 02 10 00 00 00 00 12 34 59 01 02 10 00 00 00 00 12 34 60 01 02 67 ed` +#### 失败 +`68 3d 19 00 00 45 20 23 12 12 00 00 10 10 00 00 00 00 12 34 56 00 01 10 00 00 00 00 12 34 57 00 01 10 00 00 00 00 12 34 58 00 01 10 00 00 00 00 12 34 59 00 01 10 00 00 00 00 12 34 60 00 01 70 ec` + +#### 0x48 离线卡数据查询 +`68 37 02 00 00 48 05 00 00 00 20 23 12 12 00 00 10 10 00 00 00 00 12 34 56 10 00 00 00 00 12 34 57 10 00 00 00 00 12 34 58 10 00 00 00 00 12 34 59 10 00 00 00 00 12 34 60 a9 e1` + +#### 0x47 离线卡数据查询应答 +#### 成功 +`68 38 19 00 00 47 20 23 12 12 00 00 10 10 00 00 00 00 12 34 56 01 10 00 00 00 00 12 34 57 01 10 00 00 00 00 12 34 58 01 10 00 00 00 00 12 34 59 01 10 00 00 00 00 12 34 60 01 9a 7c` +#### 失败 +`68 38 19 00 00 47 20 23 12 12 00 00 10 10 00 00 00 00 12 34 56 00 10 00 00 00 00 12 34 57 00 10 00 00 00 00 12 34 58 00 10 00 00 00 00 12 34 59 00 10 00 00 00 00 12 34 60 00 28 95` \ No newline at end of file diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java index feca495..72705e6 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/AbstractYunKuaiChongCmdExe.java @@ -49,6 +49,8 @@ public class AbstractYunKuaiChongCmdExe { private static final DecimalFormat PRICING_ID_DECIMAL_FORMAT = new DecimalFormat("0000"); + protected static final String SUCCESS = "成功"; + protected static final String UNKNOWN_MSG = "未知的异常"; @@ -82,7 +84,7 @@ public class AbstractYunKuaiChongCmdExe { } protected static byte[] encodePileCode(String pileCode) { - if (StringUtils.length(pileCode) > 32) { + if (StringUtils.length(pileCode) > 14) { throw new IllegalArgumentException("云快充可接受最大桩编号为14位"); } @@ -113,14 +115,14 @@ public class AbstractYunKuaiChongCmdExe { /** * 编码卡号为BCD格式 - * 云快充协议卡号为6字节(12位BCD码),需要做长度校验和补0操作 + * 云快充协议卡号为8字节(16位BCD码),需要做长度校验和补0操作 */ protected static byte[] encodeCardNo(String cardNo) { - if (StringUtils.length(cardNo) > 12) { - throw new IllegalArgumentException("云快充可接受最大卡号为12位"); + if (StringUtils.length(cardNo) > 16) { + throw new IllegalArgumentException("云快充可接受最大卡号为16位"); } - String cardNoStr = StringUtils.leftPad(cardNo, 12, '0'); + String cardNoStr = StringUtils.leftPad(cardNo, 16, '0'); return BCDUtil.toBytes(cardNoStr); } diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/mapping/YunKuaiChongDownlinkCmdConverter.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/mapping/YunKuaiChongDownlinkCmdConverter.java index 9eb9e23..012466e 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/mapping/YunKuaiChongDownlinkCmdConverter.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/mapping/YunKuaiChongDownlinkCmdConverter.java @@ -52,6 +52,10 @@ public class YunKuaiChongDownlinkCmdConverter implements DownlinkCmdConverter { COMMAND_MAP.put(DownlinkCmdEnum.OFFLINE_CARD_BALANCE_UPDATE_REQUEST, 0x42); COMMAND_MAP.put(DownlinkCmdEnum.OFFLINE_CARD_SYNC_REQUEST, 0x44); COMMAND_MAP.put(DownlinkCmdEnum.SYNC_TIME_REQUEST, 0x56); + COMMAND_MAP.put(DownlinkCmdEnum.OFFLINE_CARD_CLEAR_REQUEST, 0x46); + COMMAND_MAP.put(DownlinkCmdEnum.OFFLINE_CARD_QUERY_REQUEST, 0x48); + + } /** diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardBalanceUpdateRequestDLCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardBalanceUpdateRequestDLCmd.java index 5063d28..467dd9f 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardBalanceUpdateRequestDLCmd.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardBalanceUpdateRequestDLCmd.java @@ -45,7 +45,7 @@ public class YunKuaiChongV150OfflineCardBalanceUpdateRequestDLCmd extends YunKua OfflineCardBalanceUpdateRequest request = message.getMsg().getOfflineCardBalanceUpdateRequest(); msgBody.writeBytes(encodePileCode(request.getPileCode())); msgBody.writeBytes(encodeGunCode(request.getGunCode())); - msgBody.writeBytes(BCDUtil.toBytes(request.getCardNo())); + msgBody.writeBytes(encodeCardNo(request.getCardNo())); msgBody.writeIntLE(new BigDecimal(request.getLimitYuan()).movePointRight(2).intValue()); super.encodeAndWriteFlush(OFFLINE_CARD_BALANCE_UPDATE_REQUEST, msgBody, tcpSession); diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardClearRequestDLCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardClearRequestDLCmd.java new file mode 100644 index 0000000..6816ca3 --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardClearRequestDLCmd.java @@ -0,0 +1,73 @@ +/** + * 开源代码,仅供学习和交流研究使用,商用请联系三丙 + * 微信:mohan_88888 + * 抖音:程序员三丙 + * 付费课程知识星球:https://t.zsxq.com/aKtXo + */ +package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; + +import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.OFFLINE_CARD_CLEAR_REQUEST; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; +import sanbing.jcpp.proto.gen.DownlinkProto; +import sanbing.jcpp.protocol.ProtocolContext; +import sanbing.jcpp.protocol.annotation.ProtocolCmd; +import sanbing.jcpp.protocol.listener.tcp.TcpSession; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage; + + + +/** + * 云快充1.5.0 离线卡数据清除 + * + * @author bawan + */ +@Slf4j +@ProtocolCmd(value = 0x46, protocolNames = {V150, V160, V170}) +public class YunKuaiChongV150OfflineCardClearRequestDLCmd extends YunKuaiChongDownlinkCmdExe { + + @Override + public void execute(TcpSession tcpSession, YunKuaiChongDwonlinkMessage message, ProtocolContext ctx) { + log.info("{} 云快充1.5.0 离线卡数据清除", tcpSession); + + if (!message.getMsg().hasOfflineCardClearRequest()) { + log.error("云快充1.5.0 离线卡数据清除消息体为空"); + return; + } + + DownlinkProto.OfflineCardClearRequest request = message.getMsg().getOfflineCardClearRequest(); + + if (request.getTotal()>24 || request.getCardNoCount()>24) { + log.error("云快充1.5.0 离线卡数据清除 下发卡个数最大支持: 24个当前: {}个", request.getTotal()); + return; + } + // 初始化 buf + ByteBuf msgBody = Unpooled.buffer(bufferInitialCapacity(request)); + msgBody.writeBytes(encodePileCode(request.getPileCode())); + msgBody.writeIntLE(request.getTotal()); + request.getCardNoList().forEach(cardNo -> msgBody.writeBytes(encodeCardNo(cardNo))); + + super.encodeAndWriteFlush(OFFLINE_CARD_CLEAR_REQUEST, msgBody, tcpSession); + } + + + /** + * 桩编号 BCD 码 7 + * 下发卡个数 BIN 码 1 最大 15 个 + * ........ ........ ........ ........ + * n卡物理卡号 BIN 码 8 离线卡物理卡号 + * @param request request + * @return bufferInitialCapacity + */ + private int bufferInitialCapacity(DownlinkProto.OfflineCardClearRequest request) { + return 7 + 1 + (8 * request.getCardNoCount()); + } + + +} diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardClearResponseULCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardClearResponseULCmd.java new file mode 100644 index 0000000..14a14bc --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardClearResponseULCmd.java @@ -0,0 +1,105 @@ +/** + * 开源代码,仅供学习和交流研究使用,商用请联系三丙 + * 微信:mohan_88888 + * 抖音:程序员三丙 + * 付费课程知识星球:https://t.zsxq.com/aKtXo + */ +package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; + + +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170; + +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Lists; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; +import sanbing.jcpp.infrastructure.util.codec.BCDUtil; +import sanbing.jcpp.proto.gen.UplinkProto; +import sanbing.jcpp.protocol.ProtocolContext; +import sanbing.jcpp.protocol.annotation.ProtocolCmd; +import sanbing.jcpp.protocol.listener.tcp.TcpSession; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage; + +/** + * 云快充1.5.0 离线卡数据清除应答 + * + * @author bawan + */ +@Slf4j +@ProtocolCmd(value = 0x45, protocolNames = {V150, V160, V170}) +public class YunKuaiChongV150OfflineCardClearResponseULCmd extends YunKuaiChongUplinkCmdExe { + + private static final Map> CLEAR_RESULT; + + + static { + CLEAR_RESULT = Map.of( + (byte) 0x00,Map.of((byte)0x01,"卡号格式错误"), + (byte) 0x01,Map.of((byte)0x02,SUCCESS) + ); + } + + + @Override + public void execute(TcpSession tcpSession, YunKuaiChongUplinkMessage message, ProtocolContext ctx) { + log.info("{} 云快充1.5.0 离线卡数据清除应答", tcpSession); + + ByteBuf byteBuf = Unpooled.wrappedBuffer(message.getMsgBody()); + // 桩编号 + byte[] pileCodeBytes = new byte[7]; + byteBuf.readBytes(pileCodeBytes); + String pileCode = BCDUtil.toString(pileCodeBytes); + // 清除结果集合 + List clearResultList = Lists.newArrayList(); + while (byteBuf.readableBytes() >= 10) { + byte[] cardNoBytes = new byte[8]; + // 离线卡物理卡号 + byteBuf.readBytes(cardNoBytes); + String cardNo = BCDUtil.toString(cardNoBytes); + // 清除标记 0x00 清除失败 0x01 清除成功 + byte clearFlag = byteBuf.readByte(); + // 失败原因 0x01 卡号格式错误 0x02 清除成功 + byte failureReason = byteBuf.readByte(); + // clearResult + UplinkProto.ClearResult clearResult = UplinkProto.ClearResult.newBuilder() + .setCardNo(cardNo) + .setSuccess(clearFlag == 0x01) + .setErrorMsg(errorMsg(clearFlag,failureReason)) + .build(); + // add + clearResultList.add(clearResult); + } + + UplinkProto.UplinkQueueMessage queueMessage = uplinkMessageBuilder(pileCode, tcpSession, message) + .setOfflineCardClearResponse(UplinkProto.OfflineCardClearResponse.newBuilder() + .setPileCode(pileCode) + .addAllClearResult(clearResultList) + .build()) + .build(); + // 转发到后端 + tcpSession.getForwarder().sendMessage(queueMessage); + } + + + private String errorMsg(byte clearResult, byte failureReason) { + if(clearResult == 0x01) { + return SUCCESS; + } + Map clearResultMap = CLEAR_RESULT.get(clearResult); + if(null == clearResultMap) { + return UNKNOWN_MSG; + } + return clearResultMap.getOrDefault(failureReason,UNKNOWN_MSG); + } + + + +} + diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardQueryRequestDLCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardQueryRequestDLCmd.java new file mode 100644 index 0000000..9f44b28 --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardQueryRequestDLCmd.java @@ -0,0 +1,72 @@ +/** + * 开源代码,仅供学习和交流研究使用,商用请联系三丙 + * 微信:mohan_88888 + * 抖音:程序员三丙 + * 付费课程知识星球:https://t.zsxq.com/aKtXo + */ +package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; + +import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.OFFLINE_CARD_QUERY_REQUEST; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; +import sanbing.jcpp.proto.gen.DownlinkProto; +import sanbing.jcpp.protocol.ProtocolContext; +import sanbing.jcpp.protocol.annotation.ProtocolCmd; +import sanbing.jcpp.protocol.listener.tcp.TcpSession; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage; + + +/** + * 云快充1.5.0 离线卡数据查询 + * + * @author bawan + */ +@Slf4j +@ProtocolCmd(value = 0x48, protocolNames = {V150, V160, V170}) +public class YunKuaiChongV150OfflineCardQueryRequestDLCmd extends YunKuaiChongDownlinkCmdExe { + + @Override + public void execute(TcpSession tcpSession, YunKuaiChongDwonlinkMessage message, ProtocolContext ctx) { + log.info("{} 云快充1.5.0 离线卡数据查询", tcpSession); + + if (!message.getMsg().hasOfflineCardQueryRequest()) { + log.error("云快充1.5.0 离线卡数据查询消息体为空"); + return; + } + + DownlinkProto.OfflineCardQueryRequest request = message.getMsg().getOfflineCardQueryRequest(); + + if (request.getTotal()>26 || request.getCardNoCount()>26) { + log.error("云快充1.5.0 离线卡数据查询 下发卡个数最大支持: 26个当前: {}个", request.getTotal()); + return; + } + // 初始化 buf + ByteBuf msgBody = Unpooled.buffer(bufferInitialCapacity(request)); + msgBody.writeIntLE(request.getTotal()); + msgBody.writeBytes(encodePileCode(request.getPileCode())); + request.getCardNoList().forEach(cardNo -> msgBody.writeBytes(encodeCardNo(cardNo))); + + super.encodeAndWriteFlush(OFFLINE_CARD_QUERY_REQUEST, msgBody, tcpSession); + } + + + /** + * 桩编号 BCD 码 7 + * 下发卡个数 BIN 码 1 最大 15 个 + * ........ ........ ........ ........ + * n卡物理卡号 BIN 码 8 离线卡物理卡号 + * @param request request + * @return bufferInitialCapacity + */ + private int bufferInitialCapacity(DownlinkProto.OfflineCardQueryRequest request) { + return 7 + 1 + ( 8 * request.getCardNoCount()); + } + + +} diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardQueryResponseULCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardQueryResponseULCmd.java new file mode 100644 index 0000000..c5c2e97 --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardQueryResponseULCmd.java @@ -0,0 +1,80 @@ +/** + * 开源代码,仅供学习和交流研究使用,商用请联系三丙 + * 微信:mohan_88888 + * 抖音:程序员三丙 + * 付费课程知识星球:https://t.zsxq.com/aKtXo + */ +package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; + + +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V150; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V160; +import static sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolConstants.ProtocolNames.V170; + +import java.util.List; + +import com.google.common.collect.Lists; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; +import sanbing.jcpp.infrastructure.util.codec.BCDUtil; +import sanbing.jcpp.proto.gen.UplinkProto; +import sanbing.jcpp.protocol.ProtocolContext; +import sanbing.jcpp.protocol.annotation.ProtocolCmd; +import sanbing.jcpp.protocol.listener.tcp.TcpSession; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage; + + +/** + * 云快充1.5.0 离线卡数据查询应答 + * + * @author bawan + */ +@Slf4j +@ProtocolCmd(value = 0x47, protocolNames = {V150, V160, V170}) +public class YunKuaiChongV150OfflineCardQueryResponseULCmd extends YunKuaiChongUplinkCmdExe { + + + @Override + public void execute(TcpSession tcpSession, YunKuaiChongUplinkMessage message, ProtocolContext ctx) { + log.info("{} 云快充1.5.0 离线卡数据查询应答", tcpSession); + + ByteBuf byteBuf = Unpooled.wrappedBuffer(message.getMsgBody()); + // 桩编号 + byte[] pileCodeBytes = new byte[7]; + byteBuf.readBytes(pileCodeBytes); + String pileCode = BCDUtil.toString(pileCodeBytes); + + // 清除结果集合 + List queryResultList = Lists.newArrayList(); + while (byteBuf.readableBytes() >= 9) { + byte[] cardNoBytes = new byte[8]; + // 离线卡物理卡号 + byteBuf.readBytes(cardNoBytes); + String cardNo = BCDUtil.toString(cardNoBytes); + // 查询结果 0x00 不存在 0x01 存在 + byte queryResultByte = byteBuf.readByte(); + // clearResult + UplinkProto.QueryResult queryResult = UplinkProto.QueryResult.newBuilder() + .setCardNo(cardNo) + .setExist(queryResultByte == 0x01) + .build(); + // add + queryResultList.add(queryResult); + } + + UplinkProto.UplinkQueueMessage queueMessage = uplinkMessageBuilder(pileCode, tcpSession, message) + .setOfflineCardQueryResponse(UplinkProto.OfflineCardQueryResponse.newBuilder() + .setPileCode(pileCode) + .addAllQueryResult(queryResultList) + .build()) + .build(); + // 转发到后端 + tcpSession.getForwarder().sendMessage(queueMessage); + } + + +} + diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncRequestDLCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncRequestDLCmd.java index 24322bb..4b88d72 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncRequestDLCmd.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncRequestDLCmd.java @@ -9,7 +9,6 @@ package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import lombok.extern.slf4j.Slf4j; -import sanbing.jcpp.infrastructure.util.codec.BCDUtil; import sanbing.jcpp.proto.gen.DownlinkProto.OfflineCardSyncRequest; import sanbing.jcpp.protocol.ProtocolContext; import sanbing.jcpp.protocol.annotation.ProtocolCmd; @@ -41,7 +40,7 @@ public class YunKuaiChongV150OfflineCardSyncRequestDLCmd extends YunKuaiChongDow OfflineCardSyncRequest request = message.getMsg().getOfflineCardSyncRequest(); - if (request.getTotal() > 15) { + if (request.getTotal()>15 || request.getCardInfoCount()>15) { log.error("云快充1.5.0 离线卡数据同步 下发卡个数最大支持: 15个当前: {}个", request.getTotal()); return; } @@ -50,8 +49,8 @@ public class YunKuaiChongV150OfflineCardSyncRequestDLCmd extends YunKuaiChongDow msgBody.writeBytes(encodePileCode(request.getPileCode())); msgBody.writeIntLE(request.getTotal()); request.getCardInfoList().forEach(cardInfo -> { - msgBody.writeBytes(BCDUtil.toBytes(cardInfo.getLogicCardNo())); - msgBody.writeBytes(BCDUtil.toBytes(cardInfo.getCardNo())); + msgBody.writeBytes(encodeCardNo(cardInfo.getLogicCardNo())); + msgBody.writeBytes(encodeCardNo(cardInfo.getCardNo())); }); super.encodeAndWriteFlush(OFFLINE_CARD_SYNC_REQUEST, msgBody, tcpSession); diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncResponseULCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncResponseULCmd.java index 1d50693..f0cc073 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncResponseULCmd.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150OfflineCardSyncResponseULCmd.java @@ -35,10 +35,6 @@ public class YunKuaiChongV150OfflineCardSyncResponseULCmd extends YunKuaiChongUp private static final Map> FAILURE_REASON; - - private static final String SUCCESS = "成功"; - - static { FAILURE_REASON = Map.of( (byte) 0x00,Map.of((byte)0x01,"卡号格式错误",(byte)0x02,"储存空间不足"),