Files
jsowell-charger-web/jsowell-pile/src/main/java/com/jsowell/pile/service/PileRemoteService.java

364 lines
12 KiB
Java
Raw Normal View History

2023-07-08 09:44:05 +08:00
package com.jsowell.pile.service;
2023-03-04 16:29:55 +08:00
2024-09-14 17:19:05 +08:00
import com.alibaba.fastjson2.JSON;
2023-03-04 16:29:55 +08:00
import com.google.common.collect.Lists;
import com.jsowell.common.constant.CacheConstants;
2024-08-01 18:03:21 +08:00
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
import com.jsowell.common.core.redis.RedisCache;
2024-08-01 18:03:21 +08:00
import com.jsowell.common.enums.ykc.ChargingFailedReasonEnum;
2023-06-29 16:58:29 +08:00
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
2024-08-01 18:03:21 +08:00
import com.jsowell.common.util.BytesUtil;
2023-03-04 16:29:55 +08:00
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.PileBillingTemplate;
2023-06-29 16:58:29 +08:00
import com.jsowell.pile.domain.PileFirmwareInfo;
2024-09-14 17:19:05 +08:00
import com.jsowell.pile.domain.ebike.deviceupload.ChargingOperationResponse;
2023-06-29 16:58:29 +08:00
import com.jsowell.pile.domain.ykcCommond.*;
2023-03-04 16:29:55 +08:00
import com.jsowell.pile.dto.PublishBillingTemplateDTO;
2023-06-29 16:58:29 +08:00
import com.jsowell.pile.dto.RemoteAccountBalanceUpdateDTO;
import com.jsowell.pile.dto.UpdateFirmwareDTO;
2023-03-04 16:29:55 +08:00
import com.jsowell.pile.vo.web.BillingTemplateVO;
2023-03-10 14:08:10 +08:00
import com.jsowell.pile.vo.web.PileDetailVO;
2023-03-04 16:29:55 +08:00
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
2024-05-17 17:07:19 +08:00
import org.springframework.beans.factory.annotation.Value;
2023-03-04 16:29:55 +08:00
import org.springframework.stereotype.Service;
2023-03-16 15:23:01 +08:00
import java.math.BigDecimal;
2024-05-21 10:05:57 +08:00
import java.net.InetAddress;
import java.net.UnknownHostException;
2023-03-04 16:29:55 +08:00
import java.util.Date;
import java.util.List;
2024-08-01 17:34:01 +08:00
import java.util.Objects;
2023-03-04 16:29:55 +08:00
@Service
public class PileRemoteService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
2024-01-06 15:20:28 +08:00
private PileBillingTemplateService pileBillingTemplateService;
2023-03-04 16:29:55 +08:00
@Autowired
2024-01-06 15:20:28 +08:00
private PileBasicInfoService pileBasicInfoService;
2023-03-04 16:29:55 +08:00
@Autowired
private YKCPushCommandService ykcPushCommandService;
2023-04-06 16:18:06 +08:00
@Autowired
2024-01-06 15:20:28 +08:00
private PileFirmwareInfoService pileFirmwareInfoService;
2023-06-29 16:58:29 +08:00
@Autowired
private RedisCache redisCache;
2024-05-17 17:07:19 +08:00
2024-09-12 13:51:43 +08:00
@Autowired
private EBikeSendCommandService eBikeSendCommandService;
2024-05-17 17:07:19 +08:00
@Value("${remoteUpdate.server}")
private String serverAddress;
@Value("${remoteUpdate.port}")
private int port;
2024-05-20 11:43:00 +08:00
@Value("${remoteUpdate.username}")
private String username;
@Value("${remoteUpdate.password}")
private String password;
2023-03-04 16:29:55 +08:00
/**
* 获取充电桩实时数据信息
*
* @param pileSn 充电桩sn
* @param connectorCode 枪口号
*/
public void getRealTimeMonitorData(String pileSn, String connectorCode) {
if (StringUtils.isNotEmpty(pileSn) || StringUtils.isNotEmpty(connectorCode)) {
GetRealTimeMonitorDataCommand command = GetRealTimeMonitorDataCommand.builder()
.pileSn(pileSn)
.connectorCode(connectorCode)
.build();
ykcPushCommandService.pushGetRealTimeMonitorDataCommand(command);
}
}
/**
* 重启指令
*
* @param pileSn 充电桩sn
*/
public void reboot(String pileSn) {
RebootCommand command = RebootCommand.builder().pileSn(pileSn).build();
ykcPushCommandService.pushRebootCommand(command);
}
/**
* 远程启动充电 0x34
*
* @param pileSn 充电桩sn
*/
2023-12-06 10:40:46 +08:00
public void remoteStartCharging(String pileSn, String connectorCode, String transactionCode, BigDecimal chargeAmount) {
2023-03-16 15:23:01 +08:00
if (StringUtils.isEmpty(pileSn) || StringUtils.isEmpty(connectorCode)) {
log.warn("远程启动充电, 充电桩编号和枪口号不能为空");
return;
}
2024-07-30 11:59:25 +08:00
log.info("【=====平台下发指令=====】: 远程启动充电, 桩号:{}, 枪口号:{}", pileSn, connectorCode);
2023-03-16 15:23:01 +08:00
StartChargingCommand startChargingCommand = StartChargingCommand.builder()
.pileSn(pileSn)
.connectorCode(connectorCode)
.transactionCode(transactionCode)
2023-12-06 10:40:46 +08:00
.chargeAmount(chargeAmount)
2023-03-16 15:23:01 +08:00
.build();
ykcPushCommandService.pushStartChargingCommand(startChargingCommand);
}
2023-03-04 16:29:55 +08:00
2024-09-12 13:51:43 +08:00
/**
* 电单车远程启动充电
*/
public void remoteStartChargingEBike(String pileSn, String connectorCode, String transactionCode, BigDecimal chargeAmount) {
if (StringUtils.isEmpty(pileSn) || StringUtils.isEmpty(connectorCode)) {
log.warn("远程启动充电, 充电桩编号和枪口号不能为空");
return;
}
log.info("【=====平台下发指令=====】: 电单车远程启动充电, 桩号:{}, 枪口号:{}", pileSn, connectorCode);
StartChargingCommand startChargingCommand = StartChargingCommand.builder()
.pileSn(pileSn)
.connectorCode(connectorCode)
.transactionCode(transactionCode)
.chargeAmount(chargeAmount)
.build();
2024-09-14 13:56:58 +08:00
try {
2024-09-14 17:19:05 +08:00
ChargingOperationResponse startChargingResponse = eBikeSendCommandService.sendStartChargingCommand(startChargingCommand);
log.info("StartChargingResponse:{}", JSON.toJSONString(startChargingResponse));
2024-09-14 13:56:58 +08:00
} catch (Exception e) {
log.error("电单车远程启动充电error", e);
}
2024-09-12 13:51:43 +08:00
}
2023-03-04 16:29:55 +08:00
/**
* 远程停止充电
*/
public void remoteStopCharging(String pileSn, String connectorCode, String transactionCode) {
// 获取充电桩0x13数据校验交易流水号是否一致
String pileIsChargingKey = CacheConstants.PILE_IS_CHARGING + pileSn + connectorCode;
String redisResult = redisCache.getCacheObject(pileIsChargingKey);
2024-02-28 14:47:47 +08:00
if (StringUtils.isNotBlank(redisResult) && !StringUtils.equals(redisResult, transactionCode)) {
2024-06-12 09:13:18 +08:00
log.info("发送远程停止充电指令-充电桩枪口编号:{}, 获取到正在充电中的交易流水号:{}, 与入参交易流水号:{}不一致, function return", pileSn + connectorCode, redisResult, transactionCode);
return;
}
2023-03-04 16:29:55 +08:00
StopChargingCommand command = StopChargingCommand.builder()
.pileSn(pileSn)
.connectorCode(connectorCode)
.build();
ykcPushCommandService.pushStopChargingCommand(command);
2024-06-12 09:13:18 +08:00
log.info("remoteStopCharging success, pileConnectorCode:{}, transactionCode:{}", pileSn + connectorCode, transactionCode);
2023-03-04 16:29:55 +08:00
}
/**
* 下发充电桩二维码
*
* @param pileSn 充电桩sn
*/
public void issueQRCode(String pileSn) {
2023-04-07 09:18:31 +08:00
issueQRCode(pileSn, null);
}
public void issueQRCode(String pileSn, String qrcodePrefix) {
2023-03-04 16:29:55 +08:00
IssueQRCodeCommand command = IssueQRCodeCommand.builder().pileSn(pileSn).build();
2023-04-07 09:18:31 +08:00
if (StringUtils.isNotBlank(qrcodePrefix)) {
command.setQrcodePrefix(qrcodePrefix);
2023-04-06 16:18:06 +08:00
}
2023-04-07 08:23:04 +08:00
ykcPushCommandService.pushIssueQRCodeCommand(command);
2023-03-04 16:29:55 +08:00
}
/**
* 充电桩对时
*
* @param pileSn 充电桩sn
*/
public void proofreadTime(String pileSn) {
ProofreadTimeCommand command = ProofreadTimeCommand.builder().pileSn(pileSn).build();
ykcPushCommandService.pushProofreadTimeCommand(command);
}
/**
* 下发充电桩计费模型
*/
public void publishPileBillingTemplate(String pileSn, BillingTemplateVO billingTemplateVO) {
PublishPileBillingTemplateCommand command = PublishPileBillingTemplateCommand.builder()
.billingTemplateVO(billingTemplateVO)
.pileSn(pileSn)
.build();
ykcPushCommandService.pushPublishPileBillingTemplate(command);
}
/**
* 下发计费模板
* @param dto
* @return
*/
public boolean publishBillingTemplate(PublishBillingTemplateDTO dto) {
// 获取计费模板信息
BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateByTemplateId(dto.getTemplateId());
if (billingTemplateVO == null) {
log.warn("获取计费模板信息, 通过模板id:{}查询计费模板为null", dto.getTemplateId());
return false;
}
// 更新计费模板的发布时间
PileBillingTemplate pileBillingTemplate = new PileBillingTemplate();
pileBillingTemplate.setId(Long.valueOf(billingTemplateVO.getTemplateId()));
pileBillingTemplate.setPublishTime(new Date());
pileBillingTemplateService.updatePileBillingTemplate(pileBillingTemplate);
2024-09-04 14:27:15 +08:00
// 获取到站点下所有的桩, 下发计费模板, 电单车不支持
if (StringUtils.equals(billingTemplateVO.getDeviceType(), "1")) {
List<PileDetailVO> pileList = pileBasicInfoService.selectPileListByStationIds(Lists.newArrayList(Long.valueOf(dto.getStationId())));
if (CollectionUtils.isNotEmpty(pileList)) {
for (PileDetailVO pileInfoVO : pileList) {
// 下发计费模板
publishPileBillingTemplate(pileInfoVO.getPileSn(), billingTemplateVO);
}
}
2023-03-04 16:29:55 +08:00
}
2023-06-27 11:11:43 +08:00
// 修改计费模板状态
2024-09-04 14:03:28 +08:00
pileBillingTemplateService.changeStationTemplate(dto.getStationId(), dto.getTemplateId(), billingTemplateVO.getDeviceType());
2023-03-04 16:29:55 +08:00
return true;
}
/**
* 远程更新
*/
2023-06-27 09:14:30 +08:00
public void updateFirmware(UpdateFirmwareDTO dto) {
2023-06-29 16:58:29 +08:00
PileFirmwareInfo pileFirmwareInfo = pileFirmwareInfoService.selectPileFirmwareInfoById(Long.valueOf(dto.getFirmwareId()));
if (pileFirmwareInfo == null) {
throw new BusinessException(ReturnCodeEnum.CODE_FIRMWARE_NOT_FOUND_ERROR);
}
2024-05-21 10:05:57 +08:00
String ip;
try {
2024-05-21 15:32:40 +08:00
String server = StringUtils.removeHttp(serverAddress);
ip = InetAddress.getByName(server).getHostAddress();
2024-05-21 10:05:57 +08:00
} catch (UnknownHostException e) {
throw new BusinessException("", "无法解析出IP");
}
2023-06-27 09:14:30 +08:00
UpdateFirmwareCommand command = UpdateFirmwareCommand.builder()
.pileSnList(dto.getPileSns())
2024-05-21 10:05:57 +08:00
.serverAddress(ip)
2024-05-17 17:07:19 +08:00
.port(port)
2024-05-20 11:43:00 +08:00
.username(username)
.password(password)
2023-06-29 16:58:29 +08:00
.filePath(pileFirmwareInfo.getFilePath())
2023-06-27 09:14:30 +08:00
.build();
2023-03-04 16:29:55 +08:00
ykcPushCommandService.pushUpdateFileCommand(command);
}
2024-05-21 15:32:40 +08:00
public static void main(String[] args) {
//获取百度IP地址
try {
System.out.println("www.baidu.com的地址: "+InetAddress.getByName("www.baidu.com").getHostAddress());
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
//获取百度IP地址
try {
System.out.println("jsowell的地址: "+InetAddress.getByName("apitest.jsowellcloud.com").getHostAddress());
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
String serverAddress = "http://apitest.jsowellcloud.com";
String ip;
try {
String server = StringUtils.removeHttp(serverAddress);;
ip = InetAddress.getByName(server).getHostAddress();
} catch (UnknownHostException e) {
throw new BusinessException("", "无法解析出IP");
}
System.out.println("=====" + ip);
}
/**
* 远程账户余额更新
*/
public void remoteAccountBalanceUpdate(RemoteAccountBalanceUpdateDTO dto) {
RemoteAccountBalanceUpdateCommand command = RemoteAccountBalanceUpdateCommand.builder()
.pileSn(dto.getPileSn())
.connectorCode(dto.getConnectorCode())
.accountBalance(dto.getAccountBalance())
.build();
if (StringUtils.isNotBlank(dto.getLogicCard())) {
command.setLogicCard(dto.getLogicCard());
}
ykcPushCommandService.pushAccountBalanceUpdateCommand(command);
}
2023-08-02 10:35:13 +08:00
public void remoteControlGroundLock(RemoteControlGroundLockCommand command) {
ykcPushCommandService.pushRemoteControlGroundLock(command);
}
2024-05-20 16:51:11 +08:00
/**
2024-07-02 15:24:36 +08:00
* 预约充电指令/预约指令
2024-08-01 17:34:01 +08:00
* @return result: 1-成功; 0-失败
2024-05-20 16:51:11 +08:00
*/
2024-08-01 17:34:01 +08:00
public String reservationCharging(ReservationChargingCommand command) {
String result = "1";
byte[] bytes = ykcPushCommandService.pushReservationChargingCommand(command);
// 解析结果
if (Objects.isNull(bytes)) {
result = "0";
2024-08-01 18:03:21 +08:00
} else {
YKCDataProtocol ykcDataProtocol = new YKCDataProtocol(bytes);
byte[] msgBody = ykcDataProtocol.getMsgBody();
int startIndex = 0;
int length = 16;
// 交易流水号
byte[] transactionCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String transactionCode = BytesUtil.bcd2Str(transactionCodeByteArr);
// 桩编码
startIndex += length;
length = 7;
byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String pileSn = BytesUtil.bcd2Str(pileSnByteArr);
// 枪口号
startIndex += length;
length = 1;
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr);
// 启动结果 0x00失败 0x01成功
startIndex += length;
length = 1;
byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String resultCode = BytesUtil.bcd2Str(resultCodeByteArr);
if (StringUtils.equals(resultCode, "00")) {
result = "0";
} else {
result = "1";
}
// 失败原因
startIndex += length;
length = 1;
byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String failedReason = BytesUtil.bcd2Str(failedReasonByteArr);
String failedReasonMsg = ChargingFailedReasonEnum.getMsgByCode(Integer.parseInt(failedReason, 16));
2024-08-28 14:00:20 +08:00
log.info("0x59预约充电响应sync, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果(00-失败; 01成功):{}, 失败原因:{}",
2024-08-01 18:03:21 +08:00
transactionCode, pileSn, connectorCode, resultCode, failedReasonMsg);
2024-08-01 17:34:01 +08:00
}
return result;
2024-05-20 16:51:11 +08:00
}
2024-08-01 15:13:14 +08:00
2023-03-04 16:29:55 +08:00
}