mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-06-20 23:29:48 +08:00
羽信预约充电
This commit is contained in:
@@ -66,23 +66,39 @@ public class ReservationChargingResponseHandler extends AbstractYkcHandler {
|
|||||||
startIndex += length;
|
startIndex += length;
|
||||||
length = 1;
|
length = 1;
|
||||||
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr);
|
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
|
||||||
|
boolean yuxinResponse = StringUtils.equals(responseFrameType, yuxinType);
|
||||||
|
String connectorCode = yuxinResponse ? parseYuxinConnectorCode(connectorCodeByteArr) : BytesUtil.bcd2Str(connectorCodeByteArr);
|
||||||
|
|
||||||
|
String reservationType = null;
|
||||||
|
if (yuxinResponse) {
|
||||||
|
// 羽信0xB1在枪号后多一个预约方式字段: 0x00 立即预约, 0x01 取消预约。
|
||||||
|
startIndex += length;
|
||||||
|
length = 1;
|
||||||
|
byte[] reservationTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
|
reservationType = BytesUtil.bin2HexStr(reservationTypeByteArr);
|
||||||
|
}
|
||||||
|
|
||||||
// 启动结果 0x00失败 0x01成功
|
// 启动结果 0x00失败 0x01成功
|
||||||
startIndex += length;
|
startIndex += length;
|
||||||
length = 1;
|
length = 1;
|
||||||
byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
String resultCode = BytesUtil.bcd2Str(resultCodeByteArr);
|
String resultCode = yuxinResponse ? BytesUtil.bin2HexStr(resultCodeByteArr) : BytesUtil.bcd2Str(resultCodeByteArr);
|
||||||
|
|
||||||
// 失败原因
|
// 失败原因
|
||||||
startIndex += length;
|
startIndex += length;
|
||||||
length = 1;
|
length = 1;
|
||||||
byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
String failedReason = BytesUtil.bcd2Str(failedReasonByteArr);
|
String failedReason = yuxinResponse ? BytesUtil.bin2HexStr(failedReasonByteArr) : BytesUtil.bcd2Str(failedReasonByteArr);
|
||||||
|
String failedReasonMsg = yuxinResponse ? getYuxinFailedReasonMsg(failedReason) : failedReason;
|
||||||
|
|
||||||
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
|
if (yuxinResponse) {
|
||||||
log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果:{}, 失败原因:{}",
|
log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 预约方式:{}, 结果:{}, 失败原因:{}",
|
||||||
responseFrameType, transactionCode, pileSn, connectorCode, resultCode, failedReason);
|
responseFrameType, transactionCode, pileSn, connectorCode, reservationType, resultCode, failedReasonMsg);
|
||||||
|
} else {
|
||||||
|
log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果:{}, 失败原因:{}",
|
||||||
|
responseFrameType, transactionCode, pileSn, connectorCode, resultCode, failedReason);
|
||||||
|
}
|
||||||
|
|
||||||
// 根据请求id,在集合中找到与外部线程通信的SyncPromise对象
|
// 根据请求id,在集合中找到与外部线程通信的SyncPromise对象
|
||||||
String requestFrameType = YKCFrameTypeCode.PileAnswersRelation.getRequestFrameType(responseFrameType);
|
String requestFrameType = YKCFrameTypeCode.PileAnswersRelation.getRequestFrameType(responseFrameType);
|
||||||
@@ -114,4 +130,21 @@ public class ReservationChargingResponseHandler extends AbstractYkcHandler {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String parseYuxinConnectorCode(byte[] connectorCodeByteArr) {
|
||||||
|
return String.format("%02d", connectorCodeByteArr[0] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getYuxinFailedReasonMsg(String failedReason) {
|
||||||
|
if (StringUtils.equals(failedReason, "00")) {
|
||||||
|
return "无";
|
||||||
|
} else if (StringUtils.equals(failedReason, "01")) {
|
||||||
|
return "保存失败";
|
||||||
|
} else if (StringUtils.equals(failedReason, "02")) {
|
||||||
|
return "系统当前时间小于主板时间";
|
||||||
|
} else if (StringUtils.equals(failedReason, "03")) {
|
||||||
|
return "预约时间小于当前时间";
|
||||||
|
}
|
||||||
|
return failedReason;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.jsowell.common.constant.CacheConstants;
|
import com.jsowell.common.constant.CacheConstants;
|
||||||
import com.jsowell.common.constant.Constants;
|
import com.jsowell.common.constant.Constants;
|
||||||
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
|
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
|
||||||
|
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
|
||||||
import com.jsowell.common.core.redis.RedisCache;
|
import com.jsowell.common.core.redis.RedisCache;
|
||||||
import com.jsowell.common.enums.ebike.EBikeChargeResponseEnum;
|
import com.jsowell.common.enums.ebike.EBikeChargeResponseEnum;
|
||||||
import com.jsowell.common.enums.ykc.ChargingFailedReasonEnum;
|
import com.jsowell.common.enums.ykc.ChargingFailedReasonEnum;
|
||||||
@@ -513,13 +514,16 @@ public class PileRemoteService {
|
|||||||
* @return result: 1-成功; 0-失败
|
* @return result: 1-成功; 0-失败
|
||||||
*/
|
*/
|
||||||
public String reservationCharging(ReservationChargingCommand command) {
|
public String reservationCharging(ReservationChargingCommand command) {
|
||||||
String result = "1";
|
String result = "0";
|
||||||
byte[] bytes = ykcPushCommandService.pushReservationChargingCommand(command);
|
byte[] bytes = ykcPushCommandService.pushReservationChargingCommand(command);
|
||||||
// 解析结果
|
// 解析结果
|
||||||
if (Objects.isNull(bytes)) {
|
if (Objects.isNull(bytes)) {
|
||||||
result = "0";
|
result = "0";
|
||||||
} else {
|
} else {
|
||||||
YKCDataProtocol ykcDataProtocol = new YKCDataProtocol(bytes);
|
YKCDataProtocol ykcDataProtocol = new YKCDataProtocol(bytes);
|
||||||
|
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
|
||||||
|
boolean yuxinResponse = StringUtils.equals(responseFrameType,
|
||||||
|
YKCUtils.frameType2Str(YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_ANSWER_CODE.getBytes()));
|
||||||
byte[] msgBody = ykcDataProtocol.getMsgBody();
|
byte[] msgBody = ykcDataProtocol.getMsgBody();
|
||||||
int startIndex = 0;
|
int startIndex = 0;
|
||||||
int length = 16;
|
int length = 16;
|
||||||
@@ -538,17 +542,24 @@ public class PileRemoteService {
|
|||||||
startIndex += length;
|
startIndex += length;
|
||||||
length = 1;
|
length = 1;
|
||||||
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr);
|
String connectorCode = yuxinResponse ? parseYuxinConnectorCode(connectorCodeByteArr) : BytesUtil.bcd2Str(connectorCodeByteArr);
|
||||||
|
|
||||||
|
String reservationType = null;
|
||||||
|
if (yuxinResponse) {
|
||||||
|
// 羽信0xB1在枪号后多一个预约方式字段: 0x00 立即预约, 0x01 取消预约。
|
||||||
|
startIndex += length;
|
||||||
|
length = 1;
|
||||||
|
byte[] reservationTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
|
reservationType = BytesUtil.bin2HexStr(reservationTypeByteArr);
|
||||||
|
}
|
||||||
|
|
||||||
// 启动结果 0x00失败 0x01成功
|
// 启动结果 0x00失败 0x01成功
|
||||||
startIndex += length;
|
startIndex += length;
|
||||||
length = 1;
|
length = 1;
|
||||||
byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
String resultCode = BytesUtil.bcd2Str(resultCodeByteArr);
|
String resultCode = yuxinResponse ? BytesUtil.bin2HexStr(resultCodeByteArr) : BytesUtil.bcd2Str(resultCodeByteArr);
|
||||||
|
|
||||||
if (StringUtils.equals(resultCode, "00")) {
|
if (StringUtils.equals(resultCode, "01")) {
|
||||||
result = "0";
|
|
||||||
} else {
|
|
||||||
result = "1";
|
result = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,15 +567,38 @@ public class PileRemoteService {
|
|||||||
startIndex += length;
|
startIndex += length;
|
||||||
length = 1;
|
length = 1;
|
||||||
byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
|
||||||
String failedReason = BytesUtil.bcd2Str(failedReasonByteArr);
|
String failedReason = yuxinResponse ? BytesUtil.bin2HexStr(failedReasonByteArr) : BytesUtil.bcd2Str(failedReasonByteArr);
|
||||||
String failedReasonMsg = ChargingFailedReasonEnum.getMsgByCode(Integer.parseInt(failedReason, 16));
|
String failedReasonMsg = yuxinResponse
|
||||||
|
? getYuxinFailedReasonMsg(failedReason)
|
||||||
|
: ChargingFailedReasonEnum.getMsgByCode(Integer.parseInt(failedReason, 16));
|
||||||
|
|
||||||
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
|
if (yuxinResponse) {
|
||||||
log.info("{}预约充电响应sync, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果(00-失败; 01成功):{}, 失败原因:{}",
|
log.info("{}预约充电响应sync, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 预约方式:{}, 结果(00-失败; 01成功):{}, 失败原因:{}",
|
||||||
responseFrameType, transactionCode, pileSn, connectorCode, resultCode, failedReasonMsg);
|
responseFrameType, transactionCode, pileSn, connectorCode, reservationType, resultCode, failedReasonMsg);
|
||||||
|
} else {
|
||||||
|
log.info("{}预约充电响应sync, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果(00-失败; 01成功):{}, 失败原因:{}",
|
||||||
|
responseFrameType, transactionCode, pileSn, connectorCode, resultCode, failedReasonMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String parseYuxinConnectorCode(byte[] connectorCodeByteArr) {
|
||||||
|
return String.format("%02d", connectorCodeByteArr[0] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getYuxinFailedReasonMsg(String failedReason) {
|
||||||
|
if (StringUtils.equals(failedReason, "00")) {
|
||||||
|
return "无";
|
||||||
|
} else if (StringUtils.equals(failedReason, "01")) {
|
||||||
|
return "保存失败";
|
||||||
|
} else if (StringUtils.equals(failedReason, "02")) {
|
||||||
|
return "系统当前时间小于主板时间";
|
||||||
|
} else if (StringUtils.equals(failedReason, "03")) {
|
||||||
|
return "预约时间小于当前时间";
|
||||||
|
}
|
||||||
|
return failedReason;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,56 +136,17 @@ public class PileReservationInfoServiceImpl implements PileReservationInfoServic
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void activateReserved(PileReservationDTO dto) {
|
public void activateReserved(PileReservationDTO dto) {
|
||||||
// 查询其他生效中的预约
|
|
||||||
// List<PileReservationInfo> infoList = pileReservationInfoMapper.findByMemberIdAndPileSnAndStatus(dto.getMemberId(), dto.getPileSn(), "1");
|
|
||||||
// if (CollectionUtils.isNotEmpty(infoList)) {
|
|
||||||
// throw new BusinessException(ReturnCodeEnum.CODE_RESERVATION_ALREADY_EXISTS_ERROR);
|
|
||||||
// }
|
|
||||||
|
|
||||||
PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.parseInt(dto.getReservedId()));
|
PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.parseInt(dto.getReservedId()));
|
||||||
if (pileReservationInfo == null) {
|
if (pileReservationInfo == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if (!StringUtils.equals(dto.getMemberId(), pileReservationInfo.getMemberId())) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
pileReservationInfo.setStatus(Constants.ONE);
|
pileReservationInfo.setStatus(Constants.ONE);
|
||||||
// 保存之前,校验时间是否重叠
|
if (!isTimeSlotAvailable(pileReservationInfo.getMemberId(), pileReservationInfo.getPileSn(),
|
||||||
int i = saveReservation(pileReservationInfo);
|
pileReservationInfo.getStartTime(), pileReservationInfo.getEndTime(), pileReservationInfo.getId())) {
|
||||||
if (i > 0) {
|
throw new BusinessException(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_REFUSED);
|
||||||
// 查询会员的绑定vin列表
|
|
||||||
List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(pileReservationInfo.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("01")
|
|
||||||
.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();
|
|
||||||
// pileRemoteService.reservationCharging(command);
|
|
||||||
}
|
}
|
||||||
|
sendReservationCommandAndAssertSuccess(pileReservationInfo, pileReservationInfo.getMemberId(), "01");
|
||||||
|
this.insertOrUpdateSelective(pileReservationInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,48 +158,55 @@ public class PileReservationInfoServiceImpl implements PileReservationInfoServic
|
|||||||
if (pileReservationInfo == null) {
|
if (pileReservationInfo == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if (!StringUtils.equals(dto.getMemberId(), pileReservationInfo.getMemberId())) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// 校验通过可以修改预约
|
|
||||||
pileReservationInfo.setStatus(Constants.ZERO);
|
pileReservationInfo.setStatus(Constants.ZERO);
|
||||||
int i = pileReservationInfoMapper.updateByPrimaryKeySelective(pileReservationInfo);
|
sendReservationCommandAndAssertSuccess(pileReservationInfo, pileReservationInfo.getMemberId(), "02");
|
||||||
if (i > 0) {
|
this.insertOrUpdateSelective(pileReservationInfo);
|
||||||
// 查询会员的绑定vin列表
|
}
|
||||||
List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(pileReservationInfo.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";
|
private void sendReservationCommandAndAssertSuccess(PileReservationInfo pileReservationInfo, String memberId, String operation) {
|
||||||
// 发送指令
|
ReservationChargingCommand command = buildReservationChargingCommand(pileReservationInfo, memberId, operation);
|
||||||
ReservationChargingCommand command = ReservationChargingCommand.builder()
|
String result = pileRemoteService.reservationCharging(command);
|
||||||
.transactionCode(Constants.ILLEGAL_TRANSACTION_CODE)
|
if (!StringUtils.equals(result, Constants.ONE)) {
|
||||||
.pileSn(pileReservationInfo.getPileSn())
|
throw new BusinessException(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR.getValue(),
|
||||||
.connectorCode(pileReservationInfo.getPileConnectorCode().replace(pileReservationInfo.getPileSn(), ""))
|
ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR.getLabel() + ": 充电桩返回修改失败");
|
||||||
.operation("02")
|
|
||||||
.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();
|
|
||||||
// pileRemoteService.reservationCharging(command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ReservationChargingCommand buildReservationChargingCommand(PileReservationInfo pileReservationInfo, String memberId, String operation) {
|
||||||
|
List<String> vinCodes = getReservationVinCodes(memberId);
|
||||||
|
String type = StringUtils.equals(pileReservationInfo.getReservationType(), "single") ? "00" : "01";
|
||||||
|
return 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getReservationVinCodes(String memberId) {
|
||||||
|
List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(memberId);
|
||||||
|
List<String> vinCodes = Lists.newArrayList();
|
||||||
|
int count = 0;
|
||||||
|
for (MemberPlateNumberVO vo : plateNumberVOList) {
|
||||||
|
if (count < 3 && StringUtils.isNotBlank(vo.getVinCode())) {
|
||||||
|
vinCodes.add(vo.getVinCode());
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (vinCodes.size() < 3) {
|
||||||
|
vinCodes.add("");
|
||||||
|
}
|
||||||
|
return vinCodes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验时间是否重叠
|
* 校验时间是否重叠
|
||||||
* @param memberId
|
* @param memberId
|
||||||
@@ -621,4 +589,3 @@ public class PileReservationInfoServiceImpl implements PileReservationInfoServic
|
|||||||
pileReservationInfoMapper.deleteByPileSn(pileSn);
|
pileReservationInfoMapper.deleteByPileSn(pileSn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -765,6 +767,25 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public byte[] pushReservationChargingCommand(ReservationChargingCommand command) {
|
public byte[] pushReservationChargingCommand(ReservationChargingCommand command) {
|
||||||
|
String pileSn = command.getPileSn();
|
||||||
|
YKCFrameTypeCode frameTypeCode = getReservationChargingFrameType(pileSn);
|
||||||
|
byte[] msg = frameTypeCode == YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_CODE
|
||||||
|
? buildYuxinReservationChargingMsg(command)
|
||||||
|
: buildReservationChargingMsg(command);
|
||||||
|
byte[] response;
|
||||||
|
try {
|
||||||
|
response = this.supplySend(msg, pileSn, frameTypeCode);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送消息异常", e);
|
||||||
|
response = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("【=====平台下发指令=====】: 预约充电指令, 帧类型:{}, 交易流水号:{}, 桩编号:{}, 枪口号:{}, 操作(01-启动; 02-取消; 03-修改):{}, 身份验证:{}, 开始时间:{}, 结束时间:{}, 启动金额:{}",
|
||||||
|
YKCUtils.frameType2Str(frameTypeCode.getBytes()), command.getTransactionCode(), pileSn, command.getConnectorCode(), command.getOperation(), command.getVerifyIdentity(), DateUtils.formatDateTime(command.getReservedStartTime()), DateUtils.formatDateTime(command.getReservedEndTime()), command.getAmount());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] buildReservationChargingMsg(ReservationChargingCommand command) {
|
||||||
// 交易流水号
|
// 交易流水号
|
||||||
String transactionCode = command.getTransactionCode();
|
String transactionCode = command.getTransactionCode();
|
||||||
byte[] transactionCodeArr = BytesUtil.str2Bcd(transactionCode);
|
byte[] transactionCodeArr = BytesUtil.str2Bcd(transactionCode);
|
||||||
@@ -815,23 +836,57 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService {
|
|||||||
BigDecimal amount = command.getAmount();
|
BigDecimal amount = command.getAmount();
|
||||||
byte[] amountByteArr = YKCUtils.getPriceByte(amount.toString(), 2);
|
byte[] amountByteArr = YKCUtils.getPriceByte(amount.toString(), 2);
|
||||||
|
|
||||||
// 拼装msg信息
|
return Bytes.concat(transactionCodeArr, pileSnByteArr, connectorCodeByteArr, operateByteArr,
|
||||||
byte[] msg = Bytes.concat(transactionCodeArr, pileSnByteArr, connectorCodeByteArr, operateByteArr,
|
|
||||||
reservationTypeByteArr, verifyIdentityByteArr, vin1ByteArr, vin2ByteArr, vin3ByteArr,
|
reservationTypeByteArr, verifyIdentityByteArr, vin1ByteArr, vin2ByteArr, vin3ByteArr,
|
||||||
reservedStartTimeByteArr, reservedEndTimeByteArr, amountByteArr);
|
reservedStartTimeByteArr, reservedEndTimeByteArr, amountByteArr);
|
||||||
|
}
|
||||||
|
|
||||||
YKCFrameTypeCode frameTypeCode = getReservationChargingFrameType(pileSn);
|
private byte[] buildYuxinReservationChargingMsg(ReservationChargingCommand command) {
|
||||||
byte[] response;
|
byte[] transactionCodeArr = BytesUtil.ensureLengthPrependZero(BytesUtil.str2Bcd(command.getTransactionCode()), 16);
|
||||||
try {
|
byte[] pileSnByteArr = BytesUtil.ensureLengthPrependZero(BytesUtil.str2Bcd(command.getPileSn()), 7);
|
||||||
response = this.supplySend(msg, pileSn, frameTypeCode);
|
byte[] connectorCodeByteArr = BytesUtil.intToBytes(parseDecimalByte(command.getConnectorCode(), "枪口号"), 1);
|
||||||
} catch (Exception e) {
|
byte[] accountBalanceByteArr = YKCUtils.getPriceByte(getAmount(command).toString(), 2);
|
||||||
log.error("发送消息异常", e);
|
byte[] reservationTypeByteArr = BytesUtil.intToBytes(StringUtils.equals(command.getOperation(), "02") ? 0x01 : 0x00, 1);
|
||||||
response = null;
|
byte[] chargingStrategyByteArr = BytesUtil.intToBytes(0x00, 1);
|
||||||
|
byte[] chargingParamByteArr = YKCUtils.getPriceByte(BigDecimal.ZERO.toString(), 2);
|
||||||
|
byte[] systemTimeByteArr = Cp56Time2aUtil.date2Hbyte(new Date());
|
||||||
|
byte[] reservedStartTimeByteArr = Cp56Time2aUtil.date2Hbyte(getYuxinReservedStartDate(command.getReservedStartTime()));
|
||||||
|
byte[] reservationTimeoutByteArr = BytesUtil.intToBytes(getYuxinReservationTimeout(command), 1);
|
||||||
|
|
||||||
|
return Bytes.concat(transactionCodeArr, pileSnByteArr, connectorCodeByteArr, accountBalanceByteArr,
|
||||||
|
reservationTypeByteArr, chargingStrategyByteArr, chargingParamByteArr, systemTimeByteArr,
|
||||||
|
reservedStartTimeByteArr, reservationTimeoutByteArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getAmount(ReservationChargingCommand command) {
|
||||||
|
return command.getAmount() == null ? BigDecimal.ZERO : command.getAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date getYuxinReservedStartDate(LocalTime reservedStartTime) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
LocalDateTime reservedStartDateTime = now.toLocalDate().atTime(reservedStartTime);
|
||||||
|
if (!reservedStartDateTime.isAfter(now)) {
|
||||||
|
reservedStartDateTime = reservedStartDateTime.plusDays(1);
|
||||||
}
|
}
|
||||||
|
return DateUtils.localDateTime2Date(reservedStartDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
log.info("【=====平台下发指令=====】: 预约充电指令, 帧类型:{}, 交易流水号:{}, 桩编号:{}, 枪口号:{}, 操作(01-启动; 02-取消; 03-修改):{}, 身份验证:{}, 开始时间:{}, 结束时间:{}, 启动金额:{}",
|
private int getYuxinReservationTimeout(ReservationChargingCommand command) {
|
||||||
YKCUtils.frameType2Str(frameTypeCode.getBytes()), transactionCode, pileSn, connectorCode, operation, verifyIdentity, DateUtils.formatDateTime(reservedStartTime), DateUtils.formatDateTime(reservedEndTime), amount);
|
LocalTime reservedStartTime = command.getReservedStartTime();
|
||||||
return response;
|
LocalTime reservedEndTime = command.getReservedEndTime();
|
||||||
|
long timeout = Duration.between(reservedStartTime, reservedEndTime).toMinutes();
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout += TimeUnit.DAYS.toMinutes(1);
|
||||||
|
}
|
||||||
|
return (int) Math.min(timeout, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseDecimalByte(String value, String fieldName) {
|
||||||
|
int result = Integer.parseInt(value);
|
||||||
|
if (result < 0 || result > 0xFF) {
|
||||||
|
throw new IllegalArgumentException(fieldName + "超出1字节范围:" + value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private YKCFrameTypeCode getReservationChargingFrameType(String pileSn) {
|
private YKCFrameTypeCode getReservationChargingFrameType(String pileSn) {
|
||||||
|
|||||||
Reference in New Issue
Block a user