Files
jsowell-charger-web/jsowell-pile/src/main/java/com/jsowell/pile/service/PileRemoteService.java
2024-09-14 17:19:05 +08:00

364 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.jsowell.pile.service;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.ykc.ChargingFailedReasonEnum;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.BytesUtil;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.PileBillingTemplate;
import com.jsowell.pile.domain.PileFirmwareInfo;
import com.jsowell.pile.domain.ebike.deviceupload.ChargingOperationResponse;
import com.jsowell.pile.domain.ykcCommond.*;
import com.jsowell.pile.dto.PublishBillingTemplateDTO;
import com.jsowell.pile.dto.RemoteAccountBalanceUpdateDTO;
import com.jsowell.pile.dto.UpdateFirmwareDTO;
import com.jsowell.pile.vo.web.BillingTemplateVO;
import com.jsowell.pile.vo.web.PileDetailVO;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Service
public class PileRemoteService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private PileBillingTemplateService pileBillingTemplateService;
@Autowired
private PileBasicInfoService pileBasicInfoService;
@Autowired
private YKCPushCommandService ykcPushCommandService;
@Autowired
private PileFirmwareInfoService pileFirmwareInfoService;
@Autowired
private RedisCache redisCache;
@Autowired
private EBikeSendCommandService eBikeSendCommandService;
@Value("${remoteUpdate.server}")
private String serverAddress;
@Value("${remoteUpdate.port}")
private int port;
@Value("${remoteUpdate.username}")
private String username;
@Value("${remoteUpdate.password}")
private String password;
/**
* 获取充电桩实时数据信息
*
* @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
*/
public void remoteStartCharging(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();
ykcPushCommandService.pushStartChargingCommand(startChargingCommand);
}
/**
* 电单车远程启动充电
*/
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();
try {
ChargingOperationResponse startChargingResponse = eBikeSendCommandService.sendStartChargingCommand(startChargingCommand);
log.info("StartChargingResponse:{}", JSON.toJSONString(startChargingResponse));
} catch (Exception e) {
log.error("电单车远程启动充电error", e);
}
}
/**
* 远程停止充电
*/
public void remoteStopCharging(String pileSn, String connectorCode, String transactionCode) {
// 获取充电桩0x13数据校验交易流水号是否一致
String pileIsChargingKey = CacheConstants.PILE_IS_CHARGING + pileSn + connectorCode;
String redisResult = redisCache.getCacheObject(pileIsChargingKey);
if (StringUtils.isNotBlank(redisResult) && !StringUtils.equals(redisResult, transactionCode)) {
log.info("发送远程停止充电指令-充电桩枪口编号:{}, 获取到正在充电中的交易流水号:{}, 与入参交易流水号:{}不一致, function return", pileSn + connectorCode, redisResult, transactionCode);
return;
}
StopChargingCommand command = StopChargingCommand.builder()
.pileSn(pileSn)
.connectorCode(connectorCode)
.build();
ykcPushCommandService.pushStopChargingCommand(command);
log.info("remoteStopCharging success, pileConnectorCode:{}, transactionCode:{}", pileSn + connectorCode, transactionCode);
}
/**
* 下发充电桩二维码
*
* @param pileSn 充电桩sn
*/
public void issueQRCode(String pileSn) {
issueQRCode(pileSn, null);
}
public void issueQRCode(String pileSn, String qrcodePrefix) {
IssueQRCodeCommand command = IssueQRCodeCommand.builder().pileSn(pileSn).build();
if (StringUtils.isNotBlank(qrcodePrefix)) {
command.setQrcodePrefix(qrcodePrefix);
}
ykcPushCommandService.pushIssueQRCodeCommand(command);
}
/**
* 充电桩对时
*
* @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);
// 获取到站点下所有的桩, 下发计费模板, 电单车不支持
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);
}
}
}
// 修改计费模板状态
pileBillingTemplateService.changeStationTemplate(dto.getStationId(), dto.getTemplateId(), billingTemplateVO.getDeviceType());
return true;
}
/**
* 远程更新
*/
public void updateFirmware(UpdateFirmwareDTO dto) {
PileFirmwareInfo pileFirmwareInfo = pileFirmwareInfoService.selectPileFirmwareInfoById(Long.valueOf(dto.getFirmwareId()));
if (pileFirmwareInfo == null) {
throw new BusinessException(ReturnCodeEnum.CODE_FIRMWARE_NOT_FOUND_ERROR);
}
String ip;
try {
String server = StringUtils.removeHttp(serverAddress);
ip = InetAddress.getByName(server).getHostAddress();
} catch (UnknownHostException e) {
throw new BusinessException("", "无法解析出IP");
}
UpdateFirmwareCommand command = UpdateFirmwareCommand.builder()
.pileSnList(dto.getPileSns())
.serverAddress(ip)
.port(port)
.username(username)
.password(password)
.filePath(pileFirmwareInfo.getFilePath())
.build();
ykcPushCommandService.pushUpdateFileCommand(command);
}
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);
}
public void remoteControlGroundLock(RemoteControlGroundLockCommand command) {
ykcPushCommandService.pushRemoteControlGroundLock(command);
}
/**
* 预约充电指令/预约指令
* @return result: 1-成功; 0-失败
*/
public String reservationCharging(ReservationChargingCommand command) {
String result = "1";
byte[] bytes = ykcPushCommandService.pushReservationChargingCommand(command);
// 解析结果
if (Objects.isNull(bytes)) {
result = "0";
} 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));
log.info("0x59预约充电响应sync, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果(00-失败; 01成功):{}, 失败原因:{}",
transactionCode, pileSn, connectorCode, resultCode, failedReasonMsg);
}
return result;
}
}