This commit is contained in:
Lemon
2024-08-27 09:57:42 +08:00
26 changed files with 571 additions and 242 deletions

View File

@@ -101,4 +101,43 @@ public abstract class AbsEBikeMessage {
}
}
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(" ", "");
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[] lengthBytes = Arrays.copyOfRange(messageBytes, 3, 5);
int length = BytesUtil.bytesToIntLittle(lengthBytes);
System.out.println("length: " + length);
// 读取物理ID
byte[] physicalIdBytes = Arrays.copyOfRange(messageBytes, 5, 9);
int physicalId = BytesUtil.bytesToIntLittle(physicalIdBytes);
System.out.println("physicalId: " + physicalId);
// 读取消息ID
byte[] messageIdBytes = Arrays.copyOfRange(messageBytes, 9, 11);
int messageId = BytesUtil.bytesToIntLittle(messageIdBytes);
System.out.println("messageId: " + messageId);
// 读取命令
byte commandByte = messageBytes[11];
String command = BytesUtil.bcd2StrLittle(new byte[]{commandByte});
System.out.println("command: " + command);
// 读取数据
byte[] dataBytes = Arrays.copyOfRange(messageBytes, 12, messageBytes.length - 2);
String data = BytesUtil.bytesToIntLittle(dataBytes) + "";
System.out.println("data: " + data);
// 读取校验
byte[] checksumBytes = Arrays.copyOfRange(messageBytes, messageBytes.length - 2, messageBytes.length);
int checksum = BytesUtil.bytesToIntLittle(checksumBytes);
System.out.println("checksum: " + checksum);
}
}

View File

@@ -0,0 +1,57 @@
package com.jsowell.pile.domain.ebike;
import com.jsowell.pile.domain.ebike.deviceupload.*;
import lombok.extern.slf4j.Slf4j;
/**
* 友电电单车协议指令
*/
@Slf4j
public enum EBikeCommandEnum {
// HEARTBEAT("01", "设备心跳包"),
REGISTRATION("20", "设备注册包", EBikeMessageCmd20.class),
GET_SERVER_TIME("22", "设备获取服务器时间", EBikeMessageCmd22.class),
HEARTBEAT_2("21", "设备心跳包", EBikeMessageCmd21.class),
CARD_OPERATION("02", "刷卡操作", EBikeMessageCmd02.class),
SETTLEMENT_UPLOAD("03", "结算消费信息上传", EBikeMessageCmd03.class),
CHARGE_PORT_CONFIRMATION("04", "充电端口订单确认", EBikeMessageCmd04.class),
POWER_HEARTBEAT("06", "端口充电时功率心跳包", EBikeMessageCmd06.class),
// CHARGER_HEARTBEAT("41", "充电柜专有心跳包", EBikeMessageCmd41.class),
// ALARM_PUSH("42", "报警推送指令", EBikeMessageCmd20.class),
// CHARGE_COMPLETE("43", "充电完成通知,但不结算", EBikeMessageCmd20.class),
// PORT_PUSH("44", "端口推送指令", EBikeMessageCmd20.class);
;
EBikeCommandEnum(String code, String desc, Class<? extends AbsEBikeMessage> msgClass) {
this.code = code;
this.desc = desc;
this.msgClass = msgClass;
}
private final String code; // 帧类型code
private final String desc; // 帧类型名称
private final Class<? extends AbsEBikeMessage> msgClass;
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
public Class<? extends AbsEBikeMessage> getMsgClass() {
return msgClass;
}
public static Class<? extends AbsEBikeMessage> getMsgClassByCode(String code) {
for (EBikeCommandEnum e : EBikeCommandEnum.values()) {
if (e.getCode().equals(code)) {
return e.getMsgClass();
}
}
return null;
}
}

View File

@@ -60,10 +60,10 @@ public class EBikeMessageCmd20 extends AbsEBikeMessage {
private String powerBoardVersion;
public DeviceRegister(byte[] dataBytes) {
this.firmwareVersion = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)) + "";
this.firmwareVersion = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)) * 0.01 + "";
this.portNumber = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 2, 3)) + "";
this.virtualId = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 3, 4)) + "";
this.deviceType = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 4, 5));
this.deviceType = BytesUtil.printHexBinary(Arrays.copyOfRange(dataBytes, 4, 5));
this.workMode = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 5, 6));
this.powerBoardVersion = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 6, 8));
}

View File

@@ -38,6 +38,7 @@ public class EBikeMessageCmd21 extends AbsEBikeMessage {
public static class DeviceHeartbeat {
/**
* 电压:设备的当前电压(打包发送心跳包指令时的当前时间点的实时电压)
* 2024年8月26日15点02分 已经转为标准单位V
*/
private String voltage;
@@ -68,10 +69,10 @@ public class EBikeMessageCmd21 extends AbsEBikeMessage {
public DeviceHeartbeat(byte[] dataBytes) {
this.voltage = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)) + "";
this.voltage = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)) * 0.1 + "";
this.portNumber = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 2, 3));
byte[] statusBytes = Arrays.copyOfRange(dataBytes, 3, this.portNumber);
byte[] statusBytes = BytesUtil.copyBytes(dataBytes, 3, this.portNumber);
List<String> statusList = Lists.newArrayList();
for (byte statusByte : statusBytes) {
int status = BytesUtil.bytesToIntLittle(new byte[]{statusByte});

View File

@@ -2121,7 +2121,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
} catch (BaseAdaPayException e) {
throw new RuntimeException(e);
}
logger.info("根据订单号:{}, 查询到支付信息:{}", orderCode, JSON.toJSONString(paymentInfoSet));
logger.info("根据订单号:{}, 查询到支付信息:{}, ", orderCode, JSON.toJSONString(paymentInfoSet));
if (CollectionUtils.isNotEmpty(paymentInfoSet)) {
for (PaymentInfo paymentInfo : paymentInfoSet) {
String paymentId = paymentInfo.getPaymentId();
@@ -3796,7 +3796,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
String orderCode = generateNewOrderCode();
String transactionCode = chargingStartupResult.getTransactionCode();
String status = StringUtils.equals(chargingStartupResult.getStartupResult(), "00")
String status = StringUtils.equals(chargingStartupResult.getStartupResult(), "01")
? OrderStatusEnum.IN_THE_CHARGING.getValue()
: OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue();
@@ -3826,11 +3826,17 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
.reason(chargingStartupResult.getFailReason())
.build();
OrderDetail orderDetail = OrderDetail.builder()
.orderCode(orderCode)
.delFlag(DelFlagEnum.NORMAL.getValue())
.build();
// 保存到数据库
OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder()
.orderBasicInfo(orderBasicInfo)
.orderDetail(null)
.orderDetail(orderDetail)
.build();
logger.info("createReservationOrder, chargingStartupResult:{}, 订单信息:{}", JSON.toJSONString(chargingStartupResult), JSON.toJSONString(orderBasicInfo));
pileTransactionService.doCreateOrder(createOrderTransactionDTO);
OrderPayRecord principalPayRecord = OrderPayRecord.builder()

View File

@@ -412,6 +412,18 @@ public class PileReservationInfoServiceImpl implements PileReservationInfoServic
return 0;
}
// 是否发指令 false:不发指令 true:发指令, 默认不发指令
boolean sendFlag = false;
if (StringUtils.equals(pileReservationInfo.getStatus(), "1")) {
sendFlag = true;
}
// 发指令结果 false:失败 true:成功, 默认失败
boolean sendResult = false;
// 是否更新数据库 false:不更新 true:更新, 默认更新
boolean updateFlag = true;
// 操作 0x01:启动 0x02:取消 0x03:修改
String operation = "03";
if (StringUtils.isNotBlank(dto.getStartTime())) {
@@ -431,47 +443,55 @@ public class PileReservationInfoServiceImpl implements PileReservationInfoServic
if (StringUtils.equals(dto.getStatus(), Constants.ZERO)) {
// 停用
operation = "02";
sendFlag = true;
} else if (StringUtils.equals(dto.getStatus(), Constants.ONE)) {
// 启用
operation = "01";
sendFlag = true;
}
}
pileReservationInfo.setUpdateBy(dto.getMemberId());
/*
发送指令, 收到回复更新数据库
发送指令
*/
// 查询会员的绑定vin列表 2024年7月30日11点04分 以当前请求会员的VIN为准
List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(dto.getMemberId());
List<String> vinCodes = Lists.newArrayList();
int count = 0;
for (MemberPlateNumberVO vo : plateNumberVOList) {
if (count < 3 && StringUtils.isNotBlank(vo.getVinCode())) {
vinCodes.add(vo.getVinCode());
count++;
if (sendFlag) {
// 查询会员的绑定vin列表 2024年7月30日11点04分 以当前请求会员的VIN为准
List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(dto.getMemberId());
List<String> vinCodes = Lists.newArrayList();
int count = 0;
for (MemberPlateNumberVO vo : plateNumberVOList) {
if (count < 3 && StringUtils.isNotBlank(vo.getVinCode())) {
vinCodes.add(vo.getVinCode());
count++;
}
}
// 如果 vinCodes 的数量少于 3用 "0" 补足
while (vinCodes.size() < 3) {
vinCodes.add("");
}
String type = StringUtils.equals(pileReservationInfo.getReservationType(), "single") ? "00" : "01";
ReservationChargingCommand command = ReservationChargingCommand.builder()
.transactionCode(Constants.ILLEGAL_TRANSACTION_CODE)
.pileSn(pileReservationInfo.getPileSn())
.connectorCode(pileReservationInfo.getPileConnectorCode().replace(pileReservationInfo.getPileSn(), ""))
.operation(operation)
.reservationType(type)
.verifyIdentity(pileReservationInfo.getVerifyIdentity())
.vin1(vinCodes.get(0))
.vin2(vinCodes.get(1))
.vin3(vinCodes.get(2))
.reservedStartTime(pileReservationInfo.getStartTime().toLocalTime())
.reservedEndTime(pileReservationInfo.getEndTime().toLocalTime())
.amount(Constants.WHITELIST_DEFAULT_AMOUNT)
.build();
String result = pileRemoteService.reservationCharging(command);
sendResult = StringUtils.equals(result, Constants.ONE);
}
// 如果 vinCodes 的数量少于 3用 "0" 补足
while (vinCodes.size() < 3) {
vinCodes.add("");
}
String type = StringUtils.equals(pileReservationInfo.getReservationType(), "single") ? "00" : "01";
ReservationChargingCommand command = ReservationChargingCommand.builder()
.transactionCode(Constants.ILLEGAL_TRANSACTION_CODE)
.pileSn(pileReservationInfo.getPileSn())
.connectorCode(pileReservationInfo.getPileConnectorCode().replace(pileReservationInfo.getPileSn(), ""))
.operation(operation)
.reservationType(type)
.verifyIdentity(pileReservationInfo.getVerifyIdentity())
.vin1(vinCodes.get(0))
.vin2(vinCodes.get(1))
.vin3(vinCodes.get(2))
.reservedStartTime(pileReservationInfo.getStartTime().toLocalTime())
.reservedEndTime(pileReservationInfo.getEndTime().toLocalTime())
.amount(Constants.WHITELIST_DEFAULT_AMOUNT)
.build();
String result = pileRemoteService.reservationCharging(command);
if (StringUtils.equals(result, Constants.ONE)) {
log.info("修改预约充电信息, updateFlag:{}, sendFlag:{}, sendResult:{}", updateFlag, sendFlag, sendResult);
// 更新数据库, 一般情况下是都更新的, 只有在发送指令并发送失败的情况下才不更新
if (updateFlag && (sendFlag == sendResult)) {
return this.insertOrUpdateSelective(pileReservationInfo);
}
return 0;

View File

@@ -207,7 +207,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService {
});
// 等待获取结果
byte[] rpcResponse = syncPromise.get2(timeout, unit);
byte[] rpcResponse = syncPromise.get(timeout, unit);
if(rpcResponse == null) {
if(syncPromise.isTimeout()) {