package com.xiaopeng.vehicleConvoy.util;
|
|
|
import cn.hutool.core.util.StrUtil;
|
import com.alibaba.fastjson2.JSON;
|
import com.xiaopeng.api.dto.vehicleConvoy.BaseImOpenDto;
|
import com.xiaopeng.api.dto.vehicleConvoy.ImOpenQueryStateDto;
|
import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto;
|
import com.xiaopeng.api.feignClient.vehicleConvoy.VehicleControlClient;
|
import com.xiaopeng.api.vo.vehicleConvoy.VehicleStateVo;
|
import com.xiaopeng.api.vo.vehicleConvoy.VehiclesCommandVo;
|
import com.xiaopeng.vehicleConvoy.service.AsyncVehicleStateService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
|
import javax.annotation.Resource;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.concurrent.CompletableFuture;
|
|
/**
|
* 车辆控制工具类
|
*/
|
@Slf4j
|
@Component
|
public class VehicleControlUtil {
|
|
public static final String OPEN_ID_ROBOT_TAXI = "robot_taxi";
|
@Resource
|
private VehicleControlClient vehicleControlClient;
|
@Resource
|
private AsyncVehicleStateService asyncVehicleStateService;
|
// 车辆控制接口appid
|
@Value("${vehicle.control.appId}")
|
private String appid;
|
// 车辆控制接口appSecret
|
@Value("${vehicle.control.appSecret}")
|
private String appSecret;
|
|
|
/**
|
* 查询车辆内温度
|
*
|
* @param uid 用户id
|
* @param vin 车辆vin
|
* 测试车辆:L1NNSGHA5PB000204
|
* @return 车辆温度信息
|
*/
|
public VehicleTemperatureDto queryVehicleTemperature(String uid, String vin) {
|
String nonce = System.currentTimeMillis() + "";
|
Set<String> stateList = new HashSet<>();
|
stateList.add("hvacInnerTemp");
|
stateList.add("trunkAjarCloseSt");
|
Map<String, String> map = new HashMap<>();
|
map.put("nonce", nonce);
|
map.put("openId", OPEN_ID_ROBOT_TAXI);
|
map.put("accessToken", "");
|
map.put("body", "");
|
map.put("vin", vin);
|
map.put("stateList", StrUtil.join(",", stateList));
|
String sign = SignatureUtils.getSignatureSHA1(appid, map, appSecret);
|
log.info("查询车内温度 请求参数:uid={}, vin={}", uid, vin);
|
ImOpenQueryStateDto baseImOpenDto = vehicleControlClient.queryVehicleTemperature(appid, nonce, "", sign, OPEN_ID_ROBOT_TAXI, vin, stateList, uid);
|
log.info("查询车内温度 结果:{}", JSON.toJSONString(baseImOpenDto));
|
if (null == baseImOpenDto || null == baseImOpenDto.getData()) {
|
throw new RuntimeException("查询车内温度失败");
|
}
|
if (0 != baseImOpenDto.getCode()) {
|
throw new RuntimeException("查询车内温度失败:" + baseImOpenDto.getMsg());
|
}
|
VehicleTemperatureDto vehicleTemperatureDto = baseImOpenDto.getData();
|
vehicleTemperatureDto.setVin(vin);
|
return vehicleTemperatureDto;
|
}
|
|
/**
|
* 同步查询车辆后备箱状态
|
* 下发一次指令,等待回调结果(1秒超时)
|
*
|
* @param uid 用户ID
|
* @param vin 车辆VIN码
|
* @return 查询后备箱开关状态(打开状态=true,关闭状态=false)
|
* @throws RuntimeException 查询失败或1秒超时
|
*/
|
public Boolean queryTrunkDoorStateSync(Long uid, String vin, boolean reportEnable) {
|
log.info("开始同步查询车辆后备箱状态: uid={}, vin={} (1秒超时)", uid, vin);
|
if (!reportEnable) {
|
VehicleTemperatureDto vehicleTemperatureDto = queryVehicleTemperature(String.valueOf(uid), vin);
|
VehicleStateVo vehicleStateVo = vehicleTemperatureDto.getStateMap().get("trunkAjarCloseSt");
|
return null != vehicleStateVo && vehicleStateVo.getValue().equals("1");
|
}
|
try {
|
// 使用异步服务查询状态,内部有1秒超时处理
|
CompletableFuture<VehicleTemperatureDto> future = asyncVehicleStateService
|
.queryVehicleStateAsync(String.valueOf(uid), vin);
|
|
// 等待回调结果,由AsyncVehicleStateService内部处理超时
|
VehicleTemperatureDto result = future.get();
|
|
if (result == null) {
|
throw new RuntimeException("查询车辆状态失败: 未获取到状态数据");
|
}
|
|
log.info("同步查询车辆后备箱状态成功: uid={}, vin={}", uid, vin);
|
VehicleStateVo vehicleStateVo = result.getStateMap().get("trunkAjarCloseSt");
|
log.info("同步查询车辆后备箱状态成功: uid={}, vin={}, vehicleStateVo={}", uid, vin, JSON.toJSONString(vehicleStateVo));
|
return null != vehicleStateVo && vehicleStateVo.getValue().equals("5");
|
|
} catch (java.util.concurrent.ExecutionException e) {
|
Throwable cause = e.getCause();
|
if (cause instanceof RuntimeException && cause.getMessage().contains("查询超时")) {
|
log.error("查询车辆后备箱状态超时: uid={}, vin={} (1秒超时)", uid, vin);
|
throw new RuntimeException("查询车辆状态超时,请稍后重试");
|
} else {
|
log.error("同步查询车辆后备箱状态失败: uid={}, vin={}", uid, vin, cause);
|
throw new RuntimeException("查询车辆状态失败: " + (cause != null ? cause.getMessage() : e.getMessage()));
|
}
|
} catch (Exception e) {
|
log.error("同步查询车辆后备箱状态失败: uid={}, vin={}", uid, vin, e);
|
throw new RuntimeException("查询车辆状态失败: " + e.getMessage());
|
}
|
}
|
|
|
/**
|
* 车辆控制操作
|
* <p>
|
* 注意:签名计算由 VehicleControlSignatureInterceptor 拦截器处理
|
* 拦截器会在 Feign 序列化 body 后,使用真实的 body 重新计算签名
|
*
|
* @param commandVo 车辆控制命令参数
|
* @return msgId 消息id,对比消息回调通知
|
* 测试车辆:L1NNSGHA5PB000204
|
*/
|
public String vehiclesCommand(VehiclesCommandVo commandVo, Long uid) {
|
String nonce = System.currentTimeMillis() + "";
|
BaseImOpenDto baseImOpenDto = vehicleControlClient.vehiclesCommand(
|
appid,
|
nonce,
|
"",
|
"",
|
OPEN_ID_ROBOT_TAXI,
|
commandVo,
|
uid
|
);
|
|
if (null == baseImOpenDto || null == baseImOpenDto.getData()) {
|
throw new RuntimeException("车辆控制失败");
|
}
|
if (0 != baseImOpenDto.getCode()) {
|
throw new RuntimeException("车辆控制失败:" + baseImOpenDto.getMsg());
|
}
|
return baseImOpenDto.getData().getMsgId();
|
}
|
}
|