mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-21 19:45:09 +08:00
364 lines
12 KiB
Java
364 lines
12 KiB
Java
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;
|
||
}
|
||
|
||
}
|