diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java index 2eff7ab..b66f392 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/TestController.java @@ -16,6 +16,7 @@ import sanbing.jcpp.proto.gen.ProtocolProto; import sanbing.jcpp.proto.gen.ProtocolProto.*; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; @@ -205,4 +206,10 @@ public class TestController { return ResponseEntity.ok("success"); } + @GetMapping("/api/timeSync") + public ResponseEntity timeSync() { + pileProtocolService.timeSync("20231212000010", LocalDateTime.now()); + 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 0f660b0..88a135a 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 @@ -14,6 +14,7 @@ import sanbing.jcpp.proto.gen.ProtocolProto.SetPricingRequest; import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage; import java.math.BigDecimal; +import java.time.LocalDateTime; /** * @author baigod @@ -157,4 +158,8 @@ public interface PileProtocolService { * 离线卡数据同步应答 */ void onOfflineCardSyncResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback); + void timeSync(String pileCode, LocalDateTime time); + + void onTimeSync(UplinkQueueMessage uplinkQueueMessage, Callback callback); + } \ No newline at end of file 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 3261352..3326b00 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 @@ -7,6 +7,7 @@ package sanbing.jcpp.app.service.impl; import com.fasterxml.jackson.databind.node.ObjectNode; +import cn.hutool.core.date.DateUtil; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -27,6 +28,7 @@ import sanbing.jcpp.proto.gen.ProtocolProto.*; import sanbing.jcpp.protocol.domain.DownlinkCmdEnum; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; @@ -430,7 +432,37 @@ public class DefaultPileProtocolService implements PileProtocolService { bmsBatteryType, bmsPowerCapacity, additionalInfo); // TODO 处理相关业务逻辑,比如保存握手信息到数据库 - + + callback.onSuccess(); + } + + @Override + public void timeSync(String pileCode, LocalDateTime time) { + UUID messageId = UUID.randomUUID(); + UUID requestId = UUID.randomUUID(); + DownlinkRequestMessage.Builder downlinkRequestMessageBuilder = DownlinkRequestMessage.newBuilder() + .setMessageIdMSB(messageId.getMostSignificantBits()) + .setMessageIdLSB(messageId.getLeastSignificantBits()) + .setPileCode(pileCode) + .setRequestIdMSB(requestId.getMostSignificantBits()) + .setRequestIdLSB(requestId.getLeastSignificantBits()) + .setDownlinkCmd(DownlinkCmdEnum.SYNC_TIME_REQUEST.name()) + .setTimeSyncRequest(TimeSyncRequest.newBuilder() + .setPileCode(pileCode) + .setTime(DateUtil.formatLocalDateTime(time)) + .build()); + downlinkCallService.sendDownlinkMessage(downlinkRequestMessageBuilder, pileCode); + } + + @Override + public void onTimeSync(UplinkQueueMessage uplinkQueueMessage, Callback callback) { + log.info("对时设置应答 {}", uplinkQueueMessage); + TimeSyncResponse timeSyncResponse = uplinkQueueMessage.getTimeSyncResponse(); + String pileCode = timeSyncResponse.getPileCode(); + String time = timeSyncResponse.getTime(); + log.info("对时设置应答: 桩编码: {}, 时间: {}", pileCode, time); + // TODO 处理相关业务逻辑 + callback.onSuccess(); } @@ -450,6 +482,7 @@ public class DefaultPileProtocolService implements PileProtocolService { // TODO 处理相关业务逻辑,比如保存地锁状态信息到数据库 + callback.onSuccess(); } 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 9421749..5cbcb19 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 @@ -232,6 +232,10 @@ public class ProtocolUplinkConsumerService extends AbstractConsumerService imple pileProtocolService.onOfflineCardSyncResponse(uplinkQueueMsg, callback); + } else if (uplinkQueueMsg.hasTimeSyncResponse()) { + + pileProtocolService.onTimeSync(uplinkQueueMsg, callback); + } else { callback.onSuccess(); diff --git a/jcpp-infrastructure-proto/src/main/proto/protocol.proto b/jcpp-infrastructure-proto/src/main/proto/protocol.proto index 2437b05..fa51080 100644 --- a/jcpp-infrastructure-proto/src/main/proto/protocol.proto +++ b/jcpp-infrastructure-proto/src/main/proto/protocol.proto @@ -76,6 +76,7 @@ message UplinkQueueMessage { GroundLockStatusProto groundLockStatusProto = 39; OfflineCardBalanceUpdateResponse offlineCardBalanceUpdateResponse = 40; OfflineCardSyncResponse offlineCardSyncResponse = 41; + TimeSyncResponse timeSyncResponse = 42; } @@ -101,6 +102,7 @@ message DownlinkRequestMessage { OtaRequest otaRequest = 29; OfflineCardBalanceUpdateRequest offlineCardBalanceUpdateRequest = 30; OfflineCardSyncRequest offlineCardSyncRequest = 31; + TimeSyncRequest timeSyncRequest = 32; } message DownlinkResponseMessage { @@ -469,4 +471,14 @@ message OfflineCardSyncResponse { string pileCode = 1; // 充电桩编码 bool success = 3; optional string errorMsg = 4; -} \ No newline at end of file +} + +message TimeSyncRequest { + string pileCode = 1; + string time = 2; +} + +message TimeSyncResponse { + string pileCode = 1; + string time = 2; +} 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 cfe502d..740ddfe 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 @@ -31,6 +31,8 @@ public enum DownlinkCmdEnum { OTA_REQUEST, + SYNC_TIME_REQUEST, + OFFLINE_CARD_BALANCE_UPDATE_REQUEST, OFFLINE_CARD_SYNC_REQUEST diff --git a/jcpp-protocol-yunkuaichong/READMD.md b/jcpp-protocol-yunkuaichong/READMD.md index 43ae401..d643613 100644 --- a/jcpp-protocol-yunkuaichong/READMD.md +++ b/jcpp-protocol-yunkuaichong/READMD.md @@ -117,4 +117,11 @@ #### 成功 `68 0d 19 00 00 43 20 23 12 12 00 00 10 01 00 38 83` #### 失败 -`68 0d 19 00 00 43 20 23 12 12 00 00 10 00 01 f8 d3` \ No newline at end of file +`68 0d 19 00 00 43 20 23 12 12 00 00 10 00 01 f8 d3` +--- + +#### 0x56 对时设置 +`68 12 01 00 00 56 20 23 12 12 00 00 10 E0 2E 0C 0C 15 08 19 E8 36` + +#### 0x55 对时设置应答 +`68 12 01 00 00 55 20 23 12 12 00 00 10 E0 2E 0C 0C 15 08 19 AB 37` diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java index 8e721f0..ce1af28 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/enums/YunKuaiChongDownlinkCmdEnum.java @@ -45,6 +45,8 @@ public enum YunKuaiChongDownlinkCmdEnum { OFFLINE_CARD_SYNC_REQUEST(0x44), + SYNC_TIME_REQUEST(0x56), + ; private final Integer cmd; diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150TimeSyncDLCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150TimeSyncDLCmd.java new file mode 100644 index 0000000..69ded2a --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150TimeSyncDLCmd.java @@ -0,0 +1,44 @@ +package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.extern.slf4j.Slf4j; +import sanbing.jcpp.infrastructure.util.codec.CP56Time2aUtil; +import sanbing.jcpp.proto.gen.ProtocolProto; +import sanbing.jcpp.protocol.ProtocolContext; +import sanbing.jcpp.protocol.listener.tcp.TcpSession; +import sanbing.jcpp.protocol.listener.tcp.enums.SequenceNumberLength; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage; +import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd; + +import java.time.LocalDateTime; + +import static sanbing.jcpp.protocol.yunkuaichong.enums.YunKuaiChongDownlinkCmdEnum.SYNC_TIME; + +/** + * 云快充1.5.0对时设置 + * + * @author 发财 + * @since 1.0.0 + */ +@Slf4j +@YunKuaiChongCmd(0x56) +public class YunKuaiChongV150TimeSyncDLCmd extends YunKuaiChongDownlinkCmdExe { + @Override + public void execute(TcpSession tcpSession, YunKuaiChongDwonlinkMessage yunKuaiChongDwonlinkMessage, ProtocolContext ctx) { + log.info("云快充1.5.0对时设置"); + if (!yunKuaiChongDwonlinkMessage.getMsg().hasTimeSyncRequest()) { + return; + } + ProtocolProto.TimeSyncRequest timeSyncRequest = yunKuaiChongDwonlinkMessage.getMsg().getTimeSyncRequest(); + String pileCode = timeSyncRequest.getPileCode(); + String time = timeSyncRequest.getTime(); + ByteBuf syncTimeMsgBody = Unpooled.buffer(14); + syncTimeMsgBody.writeBytes(encodePileCode(pileCode)); + syncTimeMsgBody.writeBytes(CP56Time2aUtil.encode(DateUtil.parseLocalDateTime(time))); + encodeAndWriteFlush(SYNC_TIME, syncTimeMsgBody, tcpSession); + } +} diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150TimeSyncResultULCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150TimeSyncResultULCmd.java new file mode 100644 index 0000000..bc897ff --- /dev/null +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150TimeSyncResultULCmd.java @@ -0,0 +1,50 @@ +package sanbing.jcpp.protocol.yunkuaichong.v150.cmd; + +import cn.hutool.core.date.DateUtil; +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.infrastructure.util.codec.CP56Time2aUtil; +import sanbing.jcpp.proto.gen.ProtocolProto; +import sanbing.jcpp.protocol.ProtocolContext; +import sanbing.jcpp.protocol.listener.tcp.TcpSession; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDownlinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongDwonlinkMessage; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe; +import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage; +import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd; + +import java.time.LocalDateTime; + +/** + * 云快充1.5.0 对时结果 + * + * @author 发财 + * @since 1.0.0 + */ +@Slf4j +@YunKuaiChongCmd(0x55) +public class YunKuaiChongV150TimeSyncResultULCmd extends YunKuaiChongUplinkCmdExe { + + @Override + public void execute(TcpSession tcpSession, YunKuaiChongUplinkMessage yunKuaiChongUplinkMessage, ProtocolContext ctx) { + log.info("{} 云快充1.5.0 对时结果", tcpSession); + ByteBuf byteBuf = Unpooled.wrappedBuffer(yunKuaiChongUplinkMessage.getMsgBody()); + byte[] pileCodeBytes = new byte[7]; + byteBuf.readBytes(pileCodeBytes); + String pileCode = BCDUtil.toString(pileCodeBytes); + byte[] timeBytes = new byte[7]; + byteBuf.readBytes(timeBytes); + LocalDateTime dateTime = CP56Time2aUtil.decode(timeBytes); + String time = DateUtil.formatLocalDateTime(dateTime); + ProtocolProto.TimeSyncResponse timeSyncResponse = ProtocolProto.TimeSyncResponse.newBuilder() + .setPileCode(pileCode) + .setTime(time) + .build(); + ProtocolProto.UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(pileCode, tcpSession, yunKuaiChongUplinkMessage) + .setTimeSyncResponse(timeSyncResponse) + .build(); + tcpSession.getForwarder().sendMessage(uplinkQueueMessage); + } +}