mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 11:05:18 +08:00
同步充电桩数据
This commit is contained in:
@@ -2,11 +2,13 @@ package com.jsowell.pile.jcpp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.pile.domain.JcppSyncRecord;
|
||||
import com.jsowell.pile.domain.PileBasicInfo;
|
||||
import com.jsowell.pile.domain.PileConnectorInfo;
|
||||
import com.jsowell.pile.jcpp.dto.sync.*;
|
||||
import com.jsowell.pile.jcpp.service.IJcppAuthService;
|
||||
import com.jsowell.pile.jcpp.service.IJcppPileSyncService;
|
||||
import com.jsowell.pile.mapper.JcppSyncRecordMapper;
|
||||
import com.jsowell.pile.service.PileBasicInfoService;
|
||||
@@ -40,10 +42,13 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
@Autowired
|
||||
private JcppSyncRecordMapper jcppSyncRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private IJcppAuthService jcppAuthService;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Value("${jcpp.sync.api-url:http://localhost:8080/api/sync}")
|
||||
@Value("${jcpp.sync.api-url:http://localhost:8180/api/sync}")
|
||||
private String jcppApiUrl;
|
||||
|
||||
@Value("${jcpp.sync.batch-size:100}")
|
||||
@@ -196,7 +201,7 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
List<PileConnectorInfo> gunList = pileConnectorInfoService.selectPileConnectorInfoList(queryGun);
|
||||
|
||||
// 3. 转换数据格式
|
||||
List<JcppPileSyncDTO> pileDTOs = convertPilesToDTO(List.of(pile));
|
||||
List<JcppPileSyncDTO> pileDTOs = convertPilesToDTO(Lists.newArrayList(pile));
|
||||
List<JcppGunSyncDTO> gunDTOs = convertGunsToDTO(gunList);
|
||||
|
||||
// 4. 调用 JCPP 同步接口
|
||||
@@ -227,9 +232,9 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
dto.setProtocol(pile.getSoftwareProtocol());
|
||||
|
||||
// 品牌、型号、制造商(可为空)
|
||||
dto.setBrand(null); // Web 项目中没有这些字段
|
||||
dto.setBrand("jsowell"); // Web 项目中没有这些字段
|
||||
dto.setModel(null);
|
||||
dto.setManufacturer(null);
|
||||
dto.setManufacturer("jsowell");
|
||||
|
||||
// 类型映射:1-运营桩 → OPERATION, 2-个人桩 → PERSONAL
|
||||
String type = "OPERATION"; // 默认运营桩
|
||||
@@ -244,11 +249,11 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
additionalInfo.put("webStationId", pile.getStationId());
|
||||
additionalInfo.put("businessType", pile.getBusinessType());
|
||||
additionalInfo.put("secretKey", pile.getSecretKey());
|
||||
additionalInfo.put("longitude", pile.getLongitude());
|
||||
additionalInfo.put("latitude", pile.getLatitude());
|
||||
additionalInfo.put("iccid", pile.getIccid());
|
||||
// additionalInfo.put("longitude", pile.getLongitude());
|
||||
// additionalInfo.put("latitude", pile.getLatitude());
|
||||
additionalInfo.put("iccid", pile.getIccId());
|
||||
additionalInfo.put("merchantId", pile.getMerchantId());
|
||||
additionalInfo.put("vinFlag", pile.getVinFlag());
|
||||
// additionalInfo.put("vinFlag", pile.get());
|
||||
|
||||
dto.setAdditionalInfo(additionalInfo);
|
||||
|
||||
@@ -333,17 +338,30 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
private List<JcppSyncResult> syncPilesToJcpp(List<JcppPileSyncDTO> pileDTOs) {
|
||||
String url = jcppApiUrl + "/piles";
|
||||
|
||||
// 构建请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("piles", pileDTOs);
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
|
||||
|
||||
try {
|
||||
// 获取访问令牌
|
||||
String token = jcppAuthService.getAccessToken();
|
||||
if (token == null || token.isEmpty()) {
|
||||
log.error("无法获取 JCPP 访问令牌");
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppPileSyncDTO dto : pileDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getPileCode(), "无法获取访问令牌"));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// 构建请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("piles", pileDTOs);
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
|
||||
|
||||
// 发送请求
|
||||
ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
|
||||
|
||||
@@ -352,6 +370,12 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
JSONObject responseBody = JSON.parseObject(response.getBody());
|
||||
List<JcppSyncResult> results = responseBody.getList("results", JcppSyncResult.class);
|
||||
return results != null ? results : new ArrayList<>();
|
||||
} else if (response.getStatusCode() == HttpStatus.UNAUTHORIZED) {
|
||||
// token 过期,清除缓存并重试一次
|
||||
log.warn("JCPP 访问令牌已过期,清除缓存并重试");
|
||||
jcppAuthService.clearToken();
|
||||
// 递归调用重试(只重试一次)
|
||||
return retrySyncPilesToJcpp(pileDTOs);
|
||||
} else {
|
||||
log.error("JCPP 充电桩同步接口返回错误: {}", response.getStatusCode());
|
||||
// 返回失败结果
|
||||
@@ -372,23 +396,158 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重试同步充电桩(token 过期时使用)
|
||||
*/
|
||||
private List<JcppSyncResult> retrySyncPilesToJcpp(List<JcppPileSyncDTO> pileDTOs) {
|
||||
String url = jcppApiUrl + "/piles";
|
||||
|
||||
try {
|
||||
// 重新获取访问令牌
|
||||
String token = jcppAuthService.getAccessToken();
|
||||
if (token == null || token.isEmpty()) {
|
||||
log.error("重试时仍无法获取 JCPP 访问令牌");
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppPileSyncDTO dto : pileDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getPileCode(), "无法获取访问令牌"));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// 构建请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("piles", pileDTOs);
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
|
||||
|
||||
// 发送请求
|
||||
ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
// 解析响应
|
||||
JSONObject responseBody = JSON.parseObject(response.getBody());
|
||||
List<JcppSyncResult> results = responseBody.getList("results", JcppSyncResult.class);
|
||||
return results != null ? results : new ArrayList<>();
|
||||
} else {
|
||||
log.error("JCPP 充电桩同步接口返回错误: {}", response.getStatusCode());
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppPileSyncDTO dto : pileDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getPileCode(), "接口返回错误: " + response.getStatusCode()));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("重试调用 JCPP 充电桩同步接口异常", e);
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppPileSyncDTO dto : pileDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getPileCode(), "接口调用异常: " + e.getMessage()));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步充电枪到 JCPP
|
||||
*/
|
||||
private List<JcppSyncResult> syncGunsToJcpp(List<JcppGunSyncDTO> gunDTOs) {
|
||||
String url = jcppApiUrl + "/guns";
|
||||
|
||||
// 构建请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("guns", gunDTOs);
|
||||
try {
|
||||
// 获取访问令牌
|
||||
String token = jcppAuthService.getAccessToken();
|
||||
if (token == null || token.isEmpty()) {
|
||||
log.error("无法获取 JCPP 访问令牌");
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppGunSyncDTO dto : gunDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getGunCode(), "无法获取访问令牌"));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
// 构建请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("guns", gunDTOs);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
|
||||
|
||||
// 发送请求
|
||||
ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
// 解析响应
|
||||
JSONObject responseBody = JSON.parseObject(response.getBody());
|
||||
List<JcppSyncResult> results = responseBody.getList("results", JcppSyncResult.class);
|
||||
return results != null ? results : new ArrayList<>();
|
||||
} else if (response.getStatusCode() == HttpStatus.UNAUTHORIZED) {
|
||||
// token 过期,清除缓存并重试一次
|
||||
log.warn("JCPP 访问令牌已过期,清除缓存并重试");
|
||||
jcppAuthService.clearToken();
|
||||
// 递归调用重试(只重试一次)
|
||||
return retrySyncGunsToJcpp(gunDTOs);
|
||||
} else {
|
||||
log.error("JCPP 充电枪同步接口返回错误: {}", response.getStatusCode());
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppGunSyncDTO dto : gunDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getGunCode(), "接口返回错误: " + response.getStatusCode()));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("调用 JCPP 充电枪同步接口异常", e);
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppGunSyncDTO dto : gunDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getGunCode(), "接口调用异常: " + e.getMessage()));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重试同步充电枪(token 过期时使用)
|
||||
*/
|
||||
private List<JcppSyncResult> retrySyncGunsToJcpp(List<JcppGunSyncDTO> gunDTOs) {
|
||||
String url = jcppApiUrl + "/guns";
|
||||
|
||||
try {
|
||||
// 重新获取访问令牌
|
||||
String token = jcppAuthService.getAccessToken();
|
||||
if (token == null || token.isEmpty()) {
|
||||
log.error("重试时仍无法获取 JCPP 访问令牌");
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppGunSyncDTO dto : gunDTOs) {
|
||||
results.add(JcppSyncResult.fail(dto.getGunCode(), "无法获取访问令牌"));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// 构建请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("guns", gunDTOs);
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers);
|
||||
|
||||
// 发送请求
|
||||
ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
|
||||
|
||||
@@ -407,7 +566,7 @@ public class JcppPileSyncServiceImpl implements IJcppPileSyncService {
|
||||
return results;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("调用 JCPP 充电枪同步接口异常", e);
|
||||
log.error("重试调用 JCPP 充电枪同步接口异常", e);
|
||||
// 返回失败结果
|
||||
List<JcppSyncResult> results = new ArrayList<>();
|
||||
for (JcppGunSyncDTO dto : gunDTOs) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.jsowell.pile.mapper;
|
||||
|
||||
import com.jsowell.pile.domain.JcppSyncRecord;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -9,6 +10,7 @@ import java.util.List;
|
||||
*
|
||||
* @author jsowell
|
||||
*/
|
||||
@Repository
|
||||
public interface JcppSyncRecordMapper {
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user