update 电单车协议

This commit is contained in:
Guoqs
2024-09-02 13:59:14 +08:00
parent 3221c9ae67
commit a41264d1b9
3 changed files with 105 additions and 9 deletions

View File

@@ -1,5 +1,6 @@
package com.jsowell.pile.domain.ebike;
import com.google.common.primitives.Bytes;
import com.jsowell.common.YouDianUtils;
import com.jsowell.common.util.BytesUtil;
import com.jsowell.pile.domain.ebike.deviceupload.*;
@@ -12,13 +13,13 @@ import java.util.Arrays;
@Getter
@Setter
public abstract class AbsEBikeMessage {
private String header; // 包头 (3字节)
private int length; // 长度 (2字节)
private int physicalId; // 物理ID (4字节)
private int messageId; // 消息ID (2字节)
private String command; // 命令 (1字节)
private Object payload; // 数据 (n字节)
private int checksum; // 校验 (2字节)
protected String header; // 包头 (3字节)
protected int length; // 长度 (2字节)
protected int physicalId; // 物理ID (4字节)
protected int messageId; // 消息ID (2字节)
protected String command; // 命令 (1字节)
protected Object payload; // 数据 (n字节)
protected int checksum; // 校验 (2字节)
public AbsEBikeMessage(String header, int length, int physicalId, int messageId, String command, Object payload, int checksum) {
this.header = header;
@@ -106,32 +107,44 @@ public abstract class AbsEBikeMessage {
public abstract byte[] getMessageBytes();
public static void main(String[] args) {
String s = "44 4e 59 00 0d 3b 37 ab 04 b9 00 22 54 33 cc 66 03 7b".replace(" ", "");
String s = "44 4E 59 26 00 3B 37 AB 04 02 00 82 00 64 01 00 00 01 01 00 00 12 34 56 78 12 34 56 78 12 34 56 78 12 34 56 78 80 70 88 13 F8 08";
s = s.replace(" ", "");
byte[] messageBytes = BytesUtil.hexStringToByteArray(s);
// 读取包头
byte[] headerBytes = Arrays.copyOfRange(messageBytes, 0, 3);
String header = new String(headerBytes, StandardCharsets.UTF_8);
System.out.println("header: " + header);
byte[] header2 = header.getBytes();
System.out.println("反序列header: " + header2);
// 读取长度
byte[] lengthBytes = Arrays.copyOfRange(messageBytes, 3, 5);
int length = BytesUtil.bytesToIntLittle(lengthBytes);
System.out.println("length: " + length);
byte[] length2 = BytesUtil.intToBytesLittle(length);
System.out.println("反序列length: " + length2);
// 读取物理ID
byte[] physicalIdBytes = Arrays.copyOfRange(messageBytes, 5, 9);
int physicalId = BytesUtil.bytesToIntLittle(physicalIdBytes);
System.out.println("physicalId: " + physicalId);
byte[] physicalId2 = BytesUtil.intToBytesLittle(physicalId, 4);
System.out.println("反序列physicalId: " + physicalId2);
// 读取消息ID
byte[] messageIdBytes = Arrays.copyOfRange(messageBytes, 9, 11);
int messageId = BytesUtil.bytesToIntLittle(messageIdBytes);
System.out.println("messageId: " + messageId);
byte[] messageId2 = BytesUtil.intToBytesLittle(messageId);
System.out.println("反序列messageId: " + messageId2);
// 读取命令
byte commandByte = messageBytes[11];
String command = BytesUtil.bcd2StrLittle(new byte[]{commandByte});
System.out.println("command: " + command);
byte[] command2 = BytesUtil.str2Bcd(command);
System.out.println("反序列command: " + command2);
// 读取数据
byte[] dataBytes = Arrays.copyOfRange(messageBytes, 12, messageBytes.length - 2);
@@ -142,6 +155,9 @@ public abstract class AbsEBikeMessage {
byte[] checksumBytes = Arrays.copyOfRange(messageBytes, messageBytes.length - 2, messageBytes.length);
int checksum = BytesUtil.bytesToIntLittle(checksumBytes);
System.out.println("checksum: " + checksum);
byte[] concat = Bytes.concat(header2, length2, physicalId2, messageId2, command2);
System.out.println("concat: " + BytesUtil.printHexBinary(concat));
}
}

View File

@@ -1,5 +1,7 @@
package com.jsowell.pile.domain.ebike.serversend;
import com.google.common.primitives.Bytes;
import com.jsowell.common.YouDianUtils;
import com.jsowell.common.util.BytesUtil;
import com.jsowell.pile.domain.ebike.AbsEBikeMessage;
import lombok.Getter;
@@ -26,7 +28,23 @@ public class EBikeMessageCmd82 extends AbsEBikeMessage {
@Override
public byte[] getMessageBytes() {
return new byte[0];
// 包头
byte[] headerBytes = BytesUtil.str2AscLittle(header);
// 长度
byte[] lengthBytes = BytesUtil.intToBytesLittle(length);
// 物理ID
byte[] physicalIdBytes = BytesUtil.intToBytesLittle(physicalId);
// 消息ID
byte[] messageIdBytes = BytesUtil.intToBytesLittle(messageId);
// 命令
byte[] commandBytes = BytesUtil.str2Bcd(command);
// 数据
byte[] payloadBytes = specificData.getBytes();
// 拼接
byte[] concat = Bytes.concat(headerBytes, lengthBytes, physicalIdBytes, messageIdBytes, commandBytes, payloadBytes);
// 校验和
byte[] checksumBytes = YouDianUtils.getCheckFieldBytes(concat);
return Bytes.concat(concat, checksumBytes);
}
public SpecificData getSpecificData() {
@@ -102,5 +120,46 @@ public class EBikeMessageCmd82 extends AbsEBikeMessage {
byte maxFullChargePowerCheckTimeBytes = dataBytes[37];
this.maxFullChargePowerCheckTime = BytesUtil.bcd2StrLittle(new byte[]{maxFullChargePowerCheckTimeBytes});
}
// 获取字节数组
public byte[] getBytes() {
// 费率模式
byte[] rateModeBytes = BytesUtil.str2Bcd(rateMode);
// 余额/有效期
byte[] balanceOrValidityBytes = BytesUtil.str2Bcd(balanceOrValidity);
// 端口号
byte[] portNumberBytes = BytesUtil.str2Bcd(portNumber);
// 充电命令
byte[] chargeCommandBytes = BytesUtil.str2Bcd(chargeCommand);
// 充电时长/电量
byte[] chargeDurationOrPowerBytes = BytesUtil.str2Bcd(chargeDurationOrPower);
// 订单编号
byte[] orderNumberBytes = BytesUtil.str2Bcd(orderNumber);
// 最大充电时长
byte[] maxChargeDurationBytes = BytesUtil.str2Bcd(maxChargeDuration);
// 过载功率
byte[] overloadPowerBytes = BytesUtil.str2Bcd(overloadPower);
// 二维码灯
byte[] qrCodeLightBytes = BytesUtil.str2Bcd(qrCodeLight);
// 长充模式
byte[] longChargeModeBytes = BytesUtil.str2Bcd(longChargeMode);
// 额外浮充时间
byte[] extraFloatChargeTimeBytes = BytesUtil.str2Bcd(extraFloatChargeTime);
// 是否跳过短路检测
byte[] skipShortCircuitDetectionBytes = BytesUtil.str2Bcd(skipShortCircuitDetection);
// 不判断用户拔出
byte[] noUserPullOutCheckBytes = BytesUtil.str2Bcd(noUserPullOutCheck);
// 强制带充满自停
byte[] forceAutoStopWhenFullBytes = BytesUtil.str2Bcd(forceAutoStopWhenFull);
// 充满功率
byte[] fullChargePowerBytes = BytesUtil.str2Bcd(fullChargePower);
// 最大充满功率最长判断时间
byte[] maxFullChargePowerCheckTimeBytes = BytesUtil.str2Bcd(maxFullChargePowerCheckTime);
return Bytes.concat(rateModeBytes, balanceOrValidityBytes, portNumberBytes, chargeCommandBytes,
chargeDurationOrPowerBytes, orderNumberBytes, maxChargeDurationBytes, overloadPowerBytes,
qrCodeLightBytes, longChargeModeBytes, extraFloatChargeTimeBytes, skipShortCircuitDetectionBytes,
noUserPullOutCheckBytes, forceAutoStopWhenFullBytes, fullChargePowerBytes,
maxFullChargePowerCheckTimeBytes);
}
}
}

View File

@@ -1,13 +1,34 @@
package com.jsowell.pile.service.impl;
import com.jsowell.common.enums.ykc.PileChannelEntity;
import com.jsowell.common.util.BytesUtil;
import com.jsowell.pile.domain.ebike.AbsEBikeMessage;
import com.jsowell.pile.service.EBikeSendCommandService;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Slf4j
@Service
public class EBikeSendCommandServiceImpl implements EBikeSendCommandService {
@Override
public void send(String pileSn, AbsEBikeMessage msg) {
// 获取桩的channel
ChannelHandlerContext ctx = PileChannelEntity.getChannelByPileSn(pileSn);
if (Objects.isNull(ctx)) {
log.error("电单车send命令失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", pileSn);
throw new NullPointerException("channel");
}
if (Objects.isNull(msg)) {
log.error("电单车send命令失败, msg为空!");
throw new NullPointerException("msg");
}
String str = "44 4E 59 26 00 3B 37 AB 04 02 00 82 00 64 01 00 00 01 01 00 00 12 34 56 78 12 34 56 78 12 34 56 78 12 34 56 78 80 70 88 13 F8 08";
byte[] messageBytes = BytesUtil.hexStringToByteArray(str);
ctx.writeAndFlush(messageBytes);
}
}