mirror of
https://gitee.com/san-bing/JChargePointProtocol
synced 2026-05-06 02:49:57 +08:00
扩展云快充1.6
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 抖音关注:程序员三丙
|
||||
* 知识星球:https://t.zsxq.com/j9b21
|
||||
*/
|
||||
package sanbing.jcpp.protocol.yunkuaichong.v160;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sanbing.jcpp.infrastructure.util.annotation.ProtocolComponent;
|
||||
import sanbing.jcpp.protocol.ProtocolBootstrap;
|
||||
import sanbing.jcpp.protocol.ProtocolMessageProcessor;
|
||||
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongProtocolMessageProcessor;
|
||||
|
||||
import static sanbing.jcpp.protocol.yunkuaichong.v160.YunkuaichongV160ProtocolBootstrap.PROTOCOL_NAME;
|
||||
|
||||
/**
|
||||
* @author baigod
|
||||
*/
|
||||
|
||||
@ProtocolComponent(PROTOCOL_NAME)
|
||||
@Slf4j
|
||||
public class YunkuaichongV160ProtocolBootstrap extends ProtocolBootstrap {
|
||||
|
||||
public static final String PROTOCOL_NAME = "yunkuaichongV160";
|
||||
|
||||
@Override
|
||||
protected String getProtocolName() {
|
||||
return PROTOCOL_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _init() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _destroy() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtocolMessageProcessor messageProcessor() {
|
||||
return new YunKuaiChongProtocolMessageProcessor(forwarder, protocolContext);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 抖音关注:程序员三丙
|
||||
* 知识星球:https://t.zsxq.com/j9b21
|
||||
*/
|
||||
package sanbing.jcpp.protocol.yunkuaichong.v160.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.infrastructure.util.codec.BCDUtil;
|
||||
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.annotation.YunKuaiChongCmd;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import static sanbing.jcpp.protocol.yunkuaichong.enums.YunKuaiChongDownlinkCmdEnum.REMOTE_START_CHARGING;
|
||||
|
||||
/**
|
||||
* 云快充1.6.0 运营平台远程控制并充启机
|
||||
*
|
||||
* @author baigod
|
||||
*/
|
||||
@Slf4j
|
||||
@YunKuaiChongCmd(0xA4)
|
||||
public class YunKuaiChongV160RemoteParallelStartDLCmd extends YunKuaiChongDownlinkCmdExe {
|
||||
|
||||
static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, YunKuaiChongDwonlinkMessage yunKuaiChongDwonlinkMessage, ProtocolContext ctx) {
|
||||
log.info("{} 云快充1.6.0运营平台远程控制并充启机", tcpSession);
|
||||
|
||||
if (!yunKuaiChongDwonlinkMessage.getMsg().hasRemoteStartChargingRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtocolProto.RemoteStartChargingRequest remoteStartChargingRequest = yunKuaiChongDwonlinkMessage.getMsg().getRemoteStartChargingRequest();
|
||||
String pileCode = remoteStartChargingRequest.getPileCode();
|
||||
String gunCode = remoteStartChargingRequest.getGunCode();
|
||||
String tradeNo = remoteStartChargingRequest.getTradeNo();
|
||||
int limitYuan = remoteStartChargingRequest.getLimitYuan();
|
||||
|
||||
byte[] cardNo = encodeCardNo(tradeNo);
|
||||
|
||||
ByteBuf msgBody = Unpooled.buffer(44);
|
||||
// 交易流水号
|
||||
msgBody.writeBytes(encodeTradeNo(tradeNo));
|
||||
// 桩编码
|
||||
msgBody.writeBytes(encodePileCode(pileCode));
|
||||
// 枪号
|
||||
msgBody.writeBytes(encodeGunCode(gunCode));
|
||||
// 逻辑卡号 BCD码
|
||||
msgBody.writeBytes(cardNo);
|
||||
// 物理卡号
|
||||
msgBody.writeBytes(cardNo);
|
||||
// 账户余额
|
||||
msgBody.writeIntLE(limitYuan);
|
||||
// 并充序号
|
||||
msgBody.writeBytes(BCDUtil.toBytes(LocalDateTime.now().format(dateTimeFormatter)));
|
||||
|
||||
encodeAndWriteFlush(REMOTE_START_CHARGING,
|
||||
msgBody,
|
||||
tcpSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用交易流水号做卡号
|
||||
*/
|
||||
private static byte[] encodeCardNo(String tradeNo) {
|
||||
tradeNo = StringUtils.right(tradeNo, 16);
|
||||
tradeNo = StringUtils.leftPad(tradeNo, 16, '0');
|
||||
return BCDUtil.toBytes(tradeNo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 抖音关注:程序员三丙
|
||||
* 知识星球:https://t.zsxq.com/j9b21
|
||||
*/
|
||||
package sanbing.jcpp.protocol.yunkuaichong.v160.cmd;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
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.jackson.JacksonUtil;
|
||||
import sanbing.jcpp.infrastructure.util.trace.TracerContextUtil;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.RemoteStartChargingResponse;
|
||||
import sanbing.jcpp.proto.gen.ProtocolProto.UplinkQueueMessage;
|
||||
import sanbing.jcpp.protocol.ProtocolContext;
|
||||
import sanbing.jcpp.protocol.listener.tcp.TcpSession;
|
||||
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkCmdExe;
|
||||
import sanbing.jcpp.protocol.yunkuaichong.YunKuaiChongUplinkMessage;
|
||||
import sanbing.jcpp.protocol.yunkuaichong.annotation.YunKuaiChongCmd;
|
||||
|
||||
/**
|
||||
* 云快充1.6.0 远程并充启机命令回复
|
||||
*
|
||||
* @author baigod
|
||||
*/
|
||||
@Slf4j
|
||||
@YunKuaiChongCmd(0xA3)
|
||||
public class YunKuaiChongV160RemoteParallelStartResultULCmd extends YunKuaiChongUplinkCmdExe {
|
||||
|
||||
@Override
|
||||
public void execute(TcpSession tcpSession, YunKuaiChongUplinkMessage yunKuaiChongUplinkMessage, ProtocolContext ctx) {
|
||||
log.info("{} 云快充1.6.远程并充启机命令回复", tcpSession);
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(yunKuaiChongUplinkMessage.getMsgBody());
|
||||
|
||||
// 从Tracer总获取当前时间
|
||||
long ts = TracerContextUtil.getCurrentTracer().getTracerTs();
|
||||
|
||||
ObjectNode additionalInfo = JacksonUtil.newObjectNode();
|
||||
|
||||
// 1.交易流水号
|
||||
byte[] tradeNoBytes = new byte[16];
|
||||
byteBuf.readBytes(tradeNoBytes);
|
||||
String tradeNo = decodeTradeNo(tradeNoBytes);
|
||||
|
||||
// 2.桩编号
|
||||
byte[] pileCodeBytes = new byte[7];
|
||||
byteBuf.readBytes(pileCodeBytes);
|
||||
String pileCode = BCDUtil.toString(pileCodeBytes);
|
||||
|
||||
// 3.抢号
|
||||
byte gunCodeByte = byteBuf.readByte();
|
||||
String gunCode = BCDUtil.toString(gunCodeByte);
|
||||
|
||||
// 4.命令执行结果 0x00失败 0x01成功
|
||||
boolean isSuccess = (byteBuf.readByte() == 0x01);
|
||||
|
||||
// 5.失败原因 0无 1设备编码不匹配 2枪已在充电 3设备故障 4设备离线 5未插枪
|
||||
byte failReasonByte = byteBuf.readByte();
|
||||
String failReason = mapFailCode(failReasonByte);
|
||||
|
||||
// 6.主辅枪标记 0x00 主枪 0x01辅枪
|
||||
byte gunFlagByte = byteBuf.readByte();
|
||||
String gunFlag = BCDUtil.toString(gunFlagByte);
|
||||
additionalInfo.put("主辅枪标记", gunFlag);
|
||||
|
||||
// 7.并充序号,0xA4下发的并充序号
|
||||
byte[] parallelSeqNoBytes = new byte[6];
|
||||
byteBuf.readBytes(parallelSeqNoBytes);
|
||||
String parallelSeqNo = BCDUtil.toString(parallelSeqNoBytes);
|
||||
additionalInfo.put("并充序号", parallelSeqNo);
|
||||
|
||||
RemoteStartChargingResponse remoteStartChargingResponse = RemoteStartChargingResponse.newBuilder()
|
||||
.setTs(ts)
|
||||
.setPileCode(pileCode)
|
||||
.setGunCode(gunCode)
|
||||
.setTradeNo(tradeNo)
|
||||
.setSuccess(isSuccess)
|
||||
.setFailReason(failReason)
|
||||
.setAdditionalInfo(additionalInfo.toString())
|
||||
.build();
|
||||
|
||||
// 转发到后端
|
||||
UplinkQueueMessage uplinkQueueMessage = uplinkMessageBuilder(pileCode, tcpSession, yunKuaiChongUplinkMessage)
|
||||
.setRemoteStartChargingResponse(remoteStartChargingResponse)
|
||||
.build();
|
||||
|
||||
tcpSession.getForwarder().sendMessage(uplinkQueueMessage);
|
||||
}
|
||||
|
||||
public static String mapFailCode(byte failCode) {
|
||||
return switch (failCode) {
|
||||
case 0x00 -> "无";
|
||||
case 0x01 -> "设备编号不匹配";
|
||||
case 0x02 -> "枪已在充电";
|
||||
case 0x03 -> "设备故障";
|
||||
case 0x04 -> "设备离线";
|
||||
case 0x05 -> "未插枪";
|
||||
case 0x33 -> "充电失败"; // 充电失败或其他相关信息
|
||||
case 0x34 -> "待启充"; // 示例,处理收到充电命令
|
||||
default -> "未知错误代码";
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user