mirror of
https://gitee.com/san-bing/JChargePointProtocol
synced 2026-05-03 17:39:55 +08:00
1103,1104,5,6指令,充电桩二维码下发和响应3,4指令
This commit is contained in:
@@ -67,6 +67,21 @@ public class TestController extends BaseController {
|
||||
return ResponseEntity.ok("success");
|
||||
}
|
||||
|
||||
@GetMapping("/setQrcode")
|
||||
public ResponseEntity<String> setQrcode() {
|
||||
QrcodeModelProto rcodeModelProto = QrcodeModelProto.newBuilder()
|
||||
.setGunName("1号枪二维码")
|
||||
.setCode("www.baidu.com/rcode=1")
|
||||
.build();
|
||||
SetQrcodeRequest setQrcodeRequest = SetQrcodeRequest.newBuilder()
|
||||
.setPileCode("20231212000010")
|
||||
.setQrcodeModel(rcodeModelProto)
|
||||
.build();
|
||||
|
||||
pileProtocolService.setQrcode(setQrcodeRequest);
|
||||
|
||||
return ResponseEntity.ok("success");
|
||||
}
|
||||
@GetMapping("/restartPile")
|
||||
public ResponseEntity<String> restartPile() {
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ 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 sanbing.jcpp.proto.gen.DownlinkProto.SetQrcodeRequest;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -189,4 +190,12 @@ public interface PileProtocolService {
|
||||
*/
|
||||
void postBmsDemandChargerOutput(UplinkQueueMessage uplinkQueueMessage, Callback callback);
|
||||
|
||||
/**
|
||||
* 服务器下发充电桩字符型参数
|
||||
*/
|
||||
void setQrcode( SetQrcodeRequest setQrcodeRequest );
|
||||
/**
|
||||
* 服务器下发充电桩字符型参数反馈
|
||||
*/
|
||||
void onSetQrcodeResponse(UplinkQueueMessage uplinkQueueMsg, Callback callback);
|
||||
}
|
||||
@@ -657,6 +657,33 @@ public class DefaultPileProtocolService implements PileProtocolService {
|
||||
callback.onSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQrcode(SetQrcodeRequest setQrcodeRequest) {
|
||||
UUID messageId = UUID.randomUUID();
|
||||
UUID requestId = UUID.randomUUID();
|
||||
String pileCode = setQrcodeRequest.getPileCode();
|
||||
|
||||
DownlinkRequestMessage.Builder downlinkRequestMessageBuilder = DownlinkRequestMessage.newBuilder()
|
||||
.setMessageIdMSB(messageId.getMostSignificantBits())
|
||||
.setMessageIdLSB(messageId.getLeastSignificantBits())
|
||||
.setPileCode(pileCode)
|
||||
.setRequestIdMSB(requestId.getMostSignificantBits())
|
||||
.setRequestIdLSB(requestId.getLeastSignificantBits())
|
||||
.setDownlinkCmd(DownlinkCmdEnum.SET_QRCODE.name())
|
||||
.setSetQrcodeRequest(setQrcodeRequest);
|
||||
|
||||
downlinkCallService.sendDownlinkMessage(downlinkRequestMessageBuilder, pileCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetQrcodeResponse(UplinkQueueMessage uplinkQueueMessage, Callback callback) {
|
||||
log.info("下发充电桩字符型应答 {}", uplinkQueueMessage);
|
||||
|
||||
// TODO 处理相关业务逻辑
|
||||
|
||||
callback.onSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postLockStatus(UplinkQueueMessage uplinkQueueMessage, Callback callback) {
|
||||
log.info("接收到地锁状态信息 {}", uplinkQueueMessage);
|
||||
|
||||
@@ -253,6 +253,10 @@ public class ProtocolUplinkConsumerService extends AbstractConsumerService {
|
||||
|
||||
pileProtocolService.onStartChargeRequest(uplinkQueueMsg, callback);
|
||||
|
||||
} else if (uplinkQueueMsg.hasSetQrcodeResponse()) {
|
||||
|
||||
pileProtocolService.onSetQrcodeResponse(uplinkQueueMsg, callback);
|
||||
|
||||
} else {
|
||||
|
||||
callback.onSuccess();
|
||||
|
||||
@@ -36,6 +36,7 @@ message DownlinkRequestMessage {
|
||||
OfflineCardSyncRequest offlineCardSyncRequest = 31;
|
||||
TimeSyncRequest timeSyncRequest = 32;
|
||||
StartChargeResponse startChargeResponse = 33;
|
||||
SetQrcodeRequest setQrcodeRequest = 34;
|
||||
}
|
||||
|
||||
// 下行响应消息
|
||||
@@ -246,3 +247,13 @@ message TimeSyncRequest {
|
||||
string pileCode = 1;
|
||||
string time = 2;
|
||||
}
|
||||
// 设置二维码请求
|
||||
message SetQrcodeRequest {
|
||||
string pileCode = 4;
|
||||
QrcodeModelProto qrcodeModel = 1;
|
||||
}
|
||||
|
||||
message QrcodeModelProto {
|
||||
string gunName = 11;
|
||||
string code = 12;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ message UplinkQueueMessage {
|
||||
TimeSyncResponse timeSyncResponse = 42;
|
||||
BmsDemandChargerOutputProto bmsDemandChargerOutputProto = 43;
|
||||
StartChargeRequest startChargeRequest = 44;
|
||||
SetQrcodeResponse setQrcodeResponse = 45;
|
||||
|
||||
}
|
||||
|
||||
// 会话关闭事件
|
||||
@@ -346,3 +348,10 @@ message BmsDemandChargerOutputProto {
|
||||
string tradeNo = 6;
|
||||
optional string additionalInfo = 20;
|
||||
}
|
||||
// 设置二维码响应
|
||||
message SetQrcodeResponse {
|
||||
bool success = 1;
|
||||
string pileCode = 4;
|
||||
int32 type = 7;
|
||||
int32 startAddr = 8;
|
||||
}
|
||||
@@ -23,6 +23,8 @@ public enum DownlinkCmdEnum {
|
||||
|
||||
SET_PRICING,
|
||||
|
||||
SET_QRCODE,
|
||||
|
||||
REMOTE_START_CHARGING,
|
||||
|
||||
REMOTE_STOP_CHARGING,
|
||||
|
||||
@@ -33,4 +33,25 @@
|
||||
#### 101 服务器应答心跳包信息
|
||||
`AA F5 0F 00 10 03 65 00 00 00 00 00 00 00 65`
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
#### 1103 服务器设置 24 时电费计价策略信息
|
||||
`AA F5 49 02 10 02 4F 04 00 00 00 1E 1C 69 00 00 F1 49 00 00 00 1E 01 00 B3 93 00 00 D4 DF 00 00 01 00 01 1E E0 56 00 00 08 76 00 00 01 1E 02 00 C8 A4 00 00 48 A1 00 00 02 00 02 1E 90 BC 00 00 50 25 00 00 02 1E 03 00 BD 34 00 00 E9 85 00 00 03 00 03 1E 12 40 00 00 BA 71 00 00 03 1E 04 00 2C 2A 00 00 10 47 00 00 04 00 04 1E 8C 25 00 00 3D 92 00 00 04 1E 05 00 41 CC 00 00 BD B6 00 00 05 00 05 1E 28 79 00 00 F6 42 00 00 05 1E 06 00 BC BC 00 00 A6 B2 00 00 06 00 06 1E 18 66 00 00 47 E9 00 00 06 1E 07 00 99 C0 00 00 02 E9 00 00 07 00 07 1E 3B 74 00 00 45 92 00 00 07 1E 08 00 05 5D 00 00 C6 E5 00 00 08 00 08 1E C4 D9 00 00 FC 8C 00 00 08 1E 09 00 53 D7 00 00 EA B2 00 00 09 00 09 1E 98 0A 00 00 6D E1 00 00 09 1E 0A 00 E7 D7 00 00 F8 9E 00 00 0A 00 0A 1E 39 25 00 00 54 27 00 00 0A 1E 0B 00 82 A6 00 00 78 3A 00 00 0B 00 0B 1E BF A8 00 00 1C 70 00 00 0B 1E 0C 00 EF 81 00 00 7A 18 00 00 0C 00 0C 1E D1 8D 00 00 B9 6F 00 00 0C 1E 0D 00 FC 91 00 00 4B 05 00 00 0D 00 0D 1E 9A 82 00 00 2C 3D 00 00 0D 1E 0E 00 4C 26 00 00 C7 02 00 00 0E 00 0E 1E 6D 87 00 00 50 A7 00 00 0E 1E 0F 00 EB E4 00 00 4D 8F 00 00 0F 00 0F 1E 23 9C 00 00 10 32 00 00 0F 1E 10 00 74 1B 00 00 C5 6A 00 00 10 00 10 1E 5A 9F 00 00 E8 1D 00 00 10 1E 11 00 F8 CE 00 00 A2 75 00 00 11 00 11 1E 9F 39 00 00 67 66 00 00 11 1E 12 00 CA 89 00 00 4E 35 00 00 12 00 12 1E 5D 8A 00 00 91 CE 00 00 12 1E 13 00 0E 47 00 00 FC 7A 00 00 13 00 13 1E 7E CD 00 00 06 14 00 00 13 1E 14 00 96 B0 00 00 24 E9 00 00 14 00 14 1E AC 20 00 00 7D 35 00 00 14 1E 15 00 45 BD 00 00 17 C1 00 00 15 00 15 1E 67 2B 00 00 9E DF 00 00 15 1E 16 00 16 83 00 00 7F 6B 00 00 16 00 16 1E 88 D2 00 00 76 5A 00 00 16 1E 17 00 15 C0 00 00 77 C6 00 00 17 00 17 1E 1E 35 00 00 1F 46 00 00 17 1E 00 00 30 DF 00 00 47 17 00 00 35 `
|
||||
#### 1104 充电桩应答服务器设置 24 时电费计价策略信息
|
||||
`AA F5 0A 00 10 02 50 04 00 54`
|
||||
|
||||
---
|
||||
|
||||
#### 5 服务器下发充电桩控制命令(停止充电)
|
||||
`AA F5 19 00 10 02 05 00 00 00 00 00 01 02 00 00 00 01 04 00 55 00 00 00 62`
|
||||
#### 6 充电桩对服务器控制命令应答(停止充电应答)
|
||||
`AA F5 34 00 10 03 06 00 00 00 00 00 32 30 32 33 31 32 31 32 30 30 30 30 31 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 00 00 00 01 00 B8`
|
||||
|
||||
---
|
||||
|
||||
#### 3 服务器下发充电桩字符型参数
|
||||
`AA F5 29 00 10 03 03 00 00 00 00 00 01 0D 00 00 00 00 01 77 77 77 2E 62 61 69 64 75 2E 63 6F 6D 2F 72 63 6F 64 65 3D 31 C1 `
|
||||
### 4 充电桩参数字符形设置/查询应答
|
||||
`AA F5 33 00 10 04 04 00 00 00 00 00 32 30 32 33 31 32 31 32 30 30 30 30 31 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0D 00 00 00 00 C0`
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 充电桩状态枚举
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum LvnengGunCodeNameEnum {
|
||||
|
||||
GUN_QR_CODE_1(13, "1号枪二维码"),
|
||||
GUN_QR_CODE_2(14, "2号枪二维码"),
|
||||
GUN_QR_CODE_3(15, "3号枪二维码"),
|
||||
GUN_QR_CODE_4(16, "4号枪二维码"),
|
||||
GUN_QR_CODE_5(17, "5号枪二维码"),
|
||||
GUN_QR_CODE_6(18, "6号枪二维码"),
|
||||
GUN_QR_CODE_7(19, "7号枪二维码"),
|
||||
GUN_QR_CODE_8(20, "8号枪二维码"),
|
||||
GUN_QR_CODE_9(21, "9号枪二维码"),
|
||||
GUN_QR_CODE_10(22, "10号枪二维码"),
|
||||
GUN_QR_CODE_11(23, "11号枪二维码"),
|
||||
GUN_QR_CODE_12(24, "12号枪二维码"),
|
||||
GUN_QR_CODE_13(25, "13号枪二维码"),
|
||||
GUN_QR_CODE_14(26, "14号枪二维码"),
|
||||
GUN_QR_CODE_15(27, "15号枪二维码"),
|
||||
GUN_QR_CODE_16(28, "16号枪二维码"),
|
||||
GUN_QR_CODE_17(29, "17号枪二维码"),
|
||||
GUN_QR_CODE_18(30, "18号枪二维码"),
|
||||
GUN_QR_CODE_19(31, "19号枪二维码"),
|
||||
GUN_QR_CODE_20(32, "20号枪二维码"),
|
||||
GUN_QR_CODE_21(33, "21号枪二维码"),
|
||||
GUN_QR_CODE_22(34, "22号枪二维码"),
|
||||
GUN_QR_CODE_23(35, "23号枪二维码"),
|
||||
GUN_QR_CODE_24(36, "24号枪二维码"),
|
||||
GUN_QR_CODE_25(37, "25号枪二维码"),
|
||||
GUN_QR_CODE_26(38, "26号枪二维码"),
|
||||
GUN_QR_CODE_27(39, "27号枪二维码"),
|
||||
GUN_QR_CODE_28(40, "28号枪二维码"),
|
||||
GUN_QR_CODE_29(41, "29号枪二维码"),
|
||||
GUN_QR_CODE_30(42, "30号枪二维码"),
|
||||
GUN_QR_CODE_31(43, "31号枪二维码"),
|
||||
GUN_QR_CODE_32(44, "32号枪二维码");
|
||||
|
||||
/**
|
||||
* 参数地址
|
||||
*/
|
||||
private final int parameterAddress;
|
||||
|
||||
/**
|
||||
* 枪二维码描述(便于理解枚举含义)
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static final String UNKNOWN_DESC = "未知状态";
|
||||
private static final Map<String, LvnengGunCodeNameEnum> CODE_TO_ENUM_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (LvnengGunCodeNameEnum enumValue : LvnengGunCodeNameEnum.values()) {
|
||||
CODE_TO_ENUM_MAP.put(enumValue.getDescription(), enumValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static Integer getParameterAddress(String description) {
|
||||
LvnengGunCodeNameEnum lvnengPileStatusEnum = CODE_TO_ENUM_MAP.get(description);
|
||||
if (lvnengPileStatusEnum == null) {
|
||||
return null;
|
||||
}
|
||||
return lvnengPileStatusEnum.getParameterAddress();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,6 +42,9 @@ public class LvnengDownlinkCmdConverter implements DownlinkCmdConverter {
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.TRANSACTION_RECORD_ACK, 201);
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.HEARTBEAT_ACK, 101); // 心跳应答
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.REAL_TIME_DATA_ACK, 103); // 实时数据应答
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.SET_PRICING, 1103);//设置价格模型应答
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.REMOTE_STOP_CHARGING, 5);//远程停止充电
|
||||
COMMAND_MAP.put(DownlinkCmdEnum.SET_QRCODE, 3);//设置二维码
|
||||
// 绿能协议支持以上命令,其他命令返回null
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import sanbing.jcpp.infrastructure.util.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
|
||||
import sanbing.jcpp.proto.gen.UplinkProto.RemoteStopChargingResponse;
|
||||
import sanbing.jcpp.proto.gen.UplinkProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.annotation.ProtocolCmd;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static sanbing.jcpp.protocol.lvneng.LvnengProtocolConstants.ProtocolNames.V340;
|
||||
|
||||
/**
|
||||
* 绿能3.4 充电桩对服务器控制命令应答
|
||||
*/
|
||||
@Slf4j
|
||||
@ProtocolCmd(value = 6, protocolNames = {V340})
|
||||
public class LvnengV340RemoteStopAckULCmd extends LvnengUplinkCmdExe {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengUplinkMessage lvnengUplinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4 充电桩对服务器控制命令应答", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(lvnengUplinkMessage.getMsgBody());
|
||||
|
||||
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
|
||||
// 从Tracer总获取当前时间
|
||||
long ts = TracerContextUtil.getCurrentTracer().getTracerTs();
|
||||
//1预留
|
||||
byteBuf.skipBytes(2);
|
||||
//2预留
|
||||
byteBuf.skipBytes(2);
|
||||
|
||||
//3充电桩编码
|
||||
byte[] pileCodeBytes = new byte[32];
|
||||
byteBuf.readBytes(pileCodeBytes);
|
||||
String pileCode = StringUtils.trim(new String(pileCodeBytes, StandardCharsets.US_ASCII));
|
||||
|
||||
|
||||
//4 充电枪口
|
||||
int gunCode = byteBuf.readByte();
|
||||
additionalInfo.put("充电枪口", gunCode);
|
||||
|
||||
//5 命令启始标志
|
||||
long flag = byteBuf.readUnsignedIntLE();
|
||||
additionalInfo.put("命令启始标志", flag);
|
||||
|
||||
//6 命令个数
|
||||
int paramCount = byteBuf.readByte();
|
||||
additionalInfo.put("命令个数", paramCount);
|
||||
|
||||
// 7 命令执行结果 0x00成功 0x01失败
|
||||
boolean isSuccess = (byteBuf.readByte() == 0x00);
|
||||
|
||||
|
||||
tcpSession.addPileCode(pileCode);
|
||||
|
||||
|
||||
RemoteStopChargingResponse remoteStopChargingResponse = RemoteStopChargingResponse.newBuilder()
|
||||
.setPileCode(pileCode)
|
||||
.setGunCode(gunCode+"")
|
||||
.setSuccess(isSuccess)
|
||||
.setAdditionalInfo(additionalInfo.toString())
|
||||
.build();
|
||||
|
||||
// 转发到后端
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(pileCode, tcpSession, lvnengUplinkMessage)
|
||||
.setRemoteStopChargingResponse(remoteStopChargingResponse)
|
||||
.build();
|
||||
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
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.lvneng.LvnengDownlinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDwonlinkMessage;
|
||||
|
||||
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.REMOTE_STOP_CHARGING;
|
||||
import static sanbing.jcpp.protocol.lvneng.LvnengProtocolConstants.ProtocolNames.V340;
|
||||
|
||||
/**
|
||||
* 绿能3.4 服务器下发充电桩控制命令
|
||||
* 目前只支持停止充电
|
||||
*/
|
||||
@Slf4j
|
||||
@ProtocolCmd(value = 5, protocolNames = {V340})
|
||||
public class LvnengV340RemoteStopDLCmd extends LvnengDownlinkCmdExe {
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengDwonlinkMessage lvnengDwonlinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4 服务器下发充电桩控制命令", tcpSession);
|
||||
|
||||
if (!lvnengDwonlinkMessage.getMsg().hasRemoteStopChargingRequest()) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
DownlinkProto.RemoteStopChargingRequest remoteStopChargingRequest = lvnengDwonlinkMessage.getMsg().getRemoteStopChargingRequest();
|
||||
String pileCode = remoteStopChargingRequest.getPileCode();
|
||||
String gunCode = remoteStopChargingRequest.getGunCode();
|
||||
|
||||
ByteBuf msgBody = Unpooled.buffer(44);
|
||||
//1预留
|
||||
msgBody.writeShortLE(0x00);
|
||||
//2预留
|
||||
msgBody.writeShortLE(0x00);
|
||||
//3充电枪口
|
||||
msgBody.writeByte(Integer.parseInt(gunCode));
|
||||
//启始命令地址
|
||||
msgBody.writeIntLE(2);
|
||||
//命令个数
|
||||
msgBody.writeByte(1);
|
||||
//命令参数长度
|
||||
msgBody.writeShortLE(4);
|
||||
//命令参数
|
||||
msgBody.writeIntLE(0x55);
|
||||
encodeAndWriteFlush(REMOTE_STOP_CHARGING,
|
||||
msgBody,
|
||||
tcpSession);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sanbing.jcpp.proto.gen.UplinkProto;
|
||||
import sanbing.jcpp.proto.gen.UplinkProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.annotation.ProtocolCmd;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
|
||||
import static sanbing.jcpp.protocol.lvneng.LvnengProtocolConstants.ProtocolNames.V340;
|
||||
|
||||
/**
|
||||
* 绿能3.4 充电桩应答服务器设置 24 时电费计价策略信息
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
@ProtocolCmd(value = 1104, protocolNames = {V340})
|
||||
public class LvnengV340SetPricingModelAckULCmd extends LvnengUplinkCmdExe {
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengUplinkMessage lvnengUplinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4 充电桩应答服务器设置 24 时电费计价策略信息", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(lvnengUplinkMessage.getMsgBody());
|
||||
// 1.设置结果 0x00:成功 0x01:失败
|
||||
boolean isSuccess = (byteBuf.readByte() == 0x00);
|
||||
|
||||
// 转发到后端
|
||||
UplinkProto.SetPricingResponse setPricingResponse = UplinkProto.SetPricingResponse.newBuilder()
|
||||
.setSuccess(isSuccess)
|
||||
.build();
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(setPricingResponse.getPileCode(), tcpSession, lvnengUplinkMessage)
|
||||
.setSetPricingResponse(setPricingResponse)
|
||||
.build();
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sanbing.jcpp.proto.gen.DownlinkProto;
|
||||
import sanbing.jcpp.proto.gen.DownlinkProto.SetPricingRequest;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.annotation.ProtocolCmd;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDownlinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDwonlinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.mapping.LvnengDownlinkCmdConverter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.SET_PRICING;
|
||||
import static sanbing.jcpp.protocol.lvneng.LvnengProtocolConstants.ProtocolNames.V340;
|
||||
|
||||
/**
|
||||
* 绿能3.4 服务器设置 24 时电费计价策略信息
|
||||
*/
|
||||
@Slf4j
|
||||
@ProtocolCmd(value = 1103, protocolNames = {V340})
|
||||
public class LvnengV340SetPricingModelDLCmd extends LvnengDownlinkCmdExe {
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengDwonlinkMessage lvnengDwonlinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4服务器设置 24 时电费计价策略信息", tcpSession);
|
||||
|
||||
if (!lvnengDwonlinkMessage.getMsg().hasSetPricingRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetPricingRequest setPricingRequest = lvnengDwonlinkMessage.getMsg().getSetPricingRequest();
|
||||
|
||||
long pricingId = setPricingRequest.getPricingId();
|
||||
String pileCode = setPricingRequest.getPileCode();
|
||||
DownlinkProto.PricingModelProto pricingModel = setPricingRequest.getPricingModel();
|
||||
// 适配新的protobuf结构:根据计费规则获取价格信息
|
||||
List<DownlinkProto.TimePeriodItemProto> periodList = null;
|
||||
|
||||
if (pricingModel.hasTimePeriodPricing()) {
|
||||
// 时段计价:使用运营商自定义时段计费
|
||||
DownlinkProto.TimePeriodPricingProto timePeriodPricing = pricingModel.getTimePeriodPricing();
|
||||
periodList = timePeriodPricing.getPeriodsList();
|
||||
|
||||
|
||||
} else {
|
||||
// 未知计费模式
|
||||
log.error("未知的计费模式,桩编号: {}, 计费ID: {}, 计费规则: {}", pileCode, pricingId, pricingModel.getRule());
|
||||
throw new IllegalArgumentException("未知的计费模式: " + pricingModel.getRule());
|
||||
}
|
||||
|
||||
// 一个时间段(开始小时1+开始分钟1+结束小时1+结束分钟1+4电费+4服务费)*48个时间段
|
||||
ByteBuf setPricingAckMsgBody = Unpooled.buffer(576);
|
||||
for (DownlinkProto.TimePeriodItemProto x : periodList) {
|
||||
LocalTime startTime = dateFormat(x.getStartTime());
|
||||
setPricingAckMsgBody.writeByte(startTime.getHour());
|
||||
setPricingAckMsgBody.writeByte(startTime.getMinute());
|
||||
|
||||
LocalTime endTime = dateFormat(x.getEndTime());
|
||||
setPricingAckMsgBody.writeByte(endTime.getHour());
|
||||
setPricingAckMsgBody.writeByte(endTime.getMinute());
|
||||
|
||||
setPricingAckMsgBody.writeIntLE(buildPrice(x.getElecPrice()));
|
||||
setPricingAckMsgBody.writeIntLE(buildPrice(x.getServPrice()));
|
||||
}
|
||||
|
||||
|
||||
// 放进缓存后再下发
|
||||
tcpSession.getRequestCache().put(pileCode + LvnengDownlinkCmdConverter.getInstance().convertToCmd(SET_PRICING), pricingId);
|
||||
|
||||
encodeAndWriteFlush(SET_PRICING,
|
||||
setPricingAckMsgBody,
|
||||
tcpSession);
|
||||
}
|
||||
|
||||
protected static LocalTime dateFormat(String time) {
|
||||
return LocalTime.parse(time, DATE_TIME_FORMATTER);
|
||||
}
|
||||
|
||||
protected static int buildPrice(String price) {
|
||||
return new BigDecimal(price).setScale(4, RoundingMode.HALF_UP).multiply(new BigDecimal(10000)).intValueExact();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import sanbing.jcpp.proto.gen.UplinkProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.proto.gen.UplinkProto.SetQrcodeResponse;
|
||||
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.annotation.ProtocolCmd;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengUplinkMessage;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static sanbing.jcpp.protocol.lvneng.LvnengProtocolConstants.ProtocolNames.V340;
|
||||
|
||||
/**
|
||||
* 绿能3.4 充电桩参数字符形设置应答
|
||||
*/
|
||||
@Slf4j
|
||||
@ProtocolCmd(value = 4, protocolNames = {V340})
|
||||
public class LvnengV340SetQrcodeModelAckULCmd extends LvnengUplinkCmdExe {
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengUplinkMessage lvnengUplinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4 充电桩参数字符形设置/查询应答", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(lvnengUplinkMessage.getMsgBody());
|
||||
//1预留
|
||||
byteBuf.skipBytes(2);
|
||||
//2预留
|
||||
byteBuf.skipBytes(2);
|
||||
|
||||
//3充电桩编码
|
||||
byte[] pileCodeBytes = new byte[32];
|
||||
byteBuf.readBytes(pileCodeBytes);
|
||||
String pileCode = StringUtils.trim(new String(pileCodeBytes, StandardCharsets.US_ASCII));
|
||||
|
||||
//4 0-査询 1-设置
|
||||
int type = byteBuf.readByte();
|
||||
|
||||
//5启始地址
|
||||
long startAddress = byteBuf.readUnsignedIntLE();
|
||||
|
||||
// 6.设置结果 0x00:成功 0x01:失败
|
||||
boolean isSuccess = (byteBuf.readByte() == 0x00);
|
||||
//todo 查询应答逻辑没有处理
|
||||
|
||||
// 转发到后端
|
||||
SetQrcodeResponse setQrcodeResponse = SetQrcodeResponse.newBuilder()
|
||||
.setPileCode(pileCode)
|
||||
.setType(type)
|
||||
.setStartAddr((int) startAddress)
|
||||
.setSuccess(isSuccess)
|
||||
.build();
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(setQrcodeResponse.getPileCode(), tcpSession, lvnengUplinkMessage)
|
||||
.setSetQrcodeResponse(setQrcodeResponse)
|
||||
.build();
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 开源代码,仅供学习和交流研究使用,商用请联系三丙
|
||||
* 微信:mohan_88888
|
||||
* 抖音:程序员三丙
|
||||
* 付费课程知识星球:https://t.zsxq.com/aKtXo
|
||||
*/
|
||||
package sanbing.jcpp.protocol.lvneng.v340.cmd;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sanbing.jcpp.proto.gen.DownlinkProto.QrcodeModelProto;
|
||||
import sanbing.jcpp.proto.gen.DownlinkProto.SetQrcodeRequest;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.annotation.ProtocolCmd;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDownlinkCmdExe;
|
||||
import sanbing.jcpp.protocol.lvneng.LvnengDwonlinkMessage;
|
||||
import sanbing.jcpp.protocol.lvneng.enums.LvnengGunCodeNameEnum;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static sanbing.jcpp.protocol.domain.DownlinkCmdEnum.SET_QRCODE;
|
||||
import static sanbing.jcpp.protocol.lvneng.LvnengProtocolConstants.ProtocolNames.V340;
|
||||
|
||||
/**
|
||||
* 绿能3.4 服务器下发充电桩字符型参数
|
||||
*/
|
||||
@Slf4j
|
||||
@ProtocolCmd(value = 3, protocolNames = {V340})
|
||||
public class LvnengV340SetQrcodeModelDLCmd extends LvnengDownlinkCmdExe {
|
||||
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, LvnengDwonlinkMessage lvnengDwonlinkMessage, ProtocolContext ctx) {
|
||||
log.debug("{} 绿能3.4 服务器下发充电桩字符型参数", tcpSession);
|
||||
|
||||
if (!lvnengDwonlinkMessage.getMsg().hasSetQrcodeRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetQrcodeRequest setQrcodeRequest = lvnengDwonlinkMessage.getMsg().getSetQrcodeRequest();
|
||||
QrcodeModelProto qrcodeModel = setQrcodeRequest.getQrcodeModel();
|
||||
Integer parameterAddress = LvnengGunCodeNameEnum.getParameterAddress(qrcodeModel.getGunName());
|
||||
if (parameterAddress == null) {
|
||||
log.error("{} 充电桩参数地址不存在", qrcodeModel.getGunName());
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf msgBody = Unpooled.buffer(267);
|
||||
// 预留1
|
||||
msgBody.writeShortLE(0);
|
||||
// 预留1
|
||||
msgBody.writeShortLE(0);
|
||||
//0-查询 1-设置
|
||||
msgBody.writeByte(1);
|
||||
// 4 参数起始地址,子命令
|
||||
msgBody.writeIntLE(parameterAddress);
|
||||
//6 参数字节长度
|
||||
msgBody.writeShortLE(256);
|
||||
//7 命令参数数据
|
||||
msgBody.writeBytes(qrcodeModel.getCode().getBytes(StandardCharsets.US_ASCII));
|
||||
//获取二维码参数地址
|
||||
|
||||
|
||||
// 放进缓存后再下发
|
||||
// tcpSession.getRequestCache().put(pileCode + LvnengDownlinkCmdConverter.getInstance().convertToCmd(SET_PRICING), pricingId);
|
||||
|
||||
encodeAndWriteFlush(SET_QRCODE,
|
||||
msgBody,
|
||||
tcpSession);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user