| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.google.common.collect.ImmutableMap; |
| | | import com.xiaopeng.api.dto.account.UcUserInfo; |
| | | import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; |
| | | import com.xiaopeng.api.dto.vehicleConvoy.ServiceVehicleListDto; |
| | | import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto; |
| | | import com.xiaopeng.api.feignClient.account.UserResourcesClient; |
| | | import com.xiaopeng.api.feignClient.automaticPilot.XpuVinClient; |
| | | import com.xiaopeng.api.feignClient.map.AdcFencePushClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpElectronicClient; |
| | |
| | | import com.xiaopeng.api.feignClient.order.XpOrderClient; |
| | | import com.xiaopeng.api.feignClient.order.XpTestOrderClient; |
| | | import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; |
| | | import com.xiaopeng.api.model.account.XpOperationsUser; |
| | | import com.xiaopeng.api.model.operation.XpElectronicFence; |
| | | import com.xiaopeng.api.model.operation.XpElectronicFenceArea; |
| | | import com.xiaopeng.api.model.order.XpOrder; |
| | |
| | | import com.xiaopeng.api.model.vehicleConvoy.*; |
| | | import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; |
| | | import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleStateVo;import com.xiaopeng.api.vo.vehicleConvoy.VehiclesCommandEnum; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehiclesCommandParamVo; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehiclesCommandVo; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.*; |
| | | import com.xiaopeng.common.core.constant.CacheConstants; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.enums.OrderStatusEnum; |
| | |
| | | @Autowired(required = false) |
| | | private AdcFencePushClient adcFencePushClient; |
| | | |
| | | @Resource |
| | | private UserVehicleClient userVehicleClient; |
| | | |
| | | @Resource |
| | | private UserResourcesClient userResourcesClient; |
| | | |
| | | @Value("${vehicle.control.distance-threshold:100}") |
| | | private int distanceThreshold; |
| | | |
| | | @Value("${vehicle.control.report.enable:true}") |
| | | private boolean reportEnable; |
| | | |
| | | @Value("${robotaxi.appId:xp_robotaxi_api}") |
| | | private String appid; |
| | | |
| | | @Override |
| | | public List<XpVehicle> listByIds(List<Long> ids) { |
| | |
| | | public List<XpVehicle> listAvailableVehicles(Long orderId, Integer orderType) { |
| | | // 1. 通过订单ID查询订单信息,获取区域ID |
| | | Long areaId = null; |
| | | if(null == orderType || 1 == orderType){ |
| | | if (null == orderType || 1 == orderType) { |
| | | R<XpOrder> orderResult = xpOrderClient.queryOrderById(orderId); |
| | | if (orderResult == null || orderResult.getData() == null) { |
| | | log.warn("查询订单失败,orderId: {}", orderId); |
| | |
| | | |
| | | XpOrder order = orderResult.getData(); |
| | | areaId = order.getXpElectronicFenceAreaId(); |
| | | }else{ |
| | | } else { |
| | | XpTestOrder testOrder = xpTestOrderClient.queryOrderById(orderId).getData(); |
| | | areaId = testOrder.getXpElectronicFenceAreaId(); |
| | | } |
| | |
| | | xpVehicleVO.setMileageRange(vehiclePosition.getMileageRange()); |
| | | xpVehicleVO.setCurrentElectricity(vehiclePosition.getCurrentElectricity()); |
| | | GeoJsonPoint point = vehiclePosition.getPoint(); |
| | | if(Objects.nonNull(point)){ |
| | | if (Objects.nonNull(point)) { |
| | | xpVehicleVO.setLongitude(point.getX()); |
| | | xpVehicleVO.setLatitude(point.getY()); |
| | | } |
| | |
| | | } |
| | | if (org.springframework.util.StringUtils.hasLength(xpVehicleVO.getVehiclePictures())) { |
| | | JSONObject jsonObject = JSONObject.parseObject(xpVehicleVO.getVehiclePictures()); |
| | | if(jsonObject!=null){ |
| | | if (jsonObject != null) { |
| | | String downloadUrl = null; |
| | | try { |
| | | // 1 |
| | | downloadUrl= aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); |
| | | downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | |
| | | VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); |
| | | if (Objects.nonNull(vehiclePosition)) { |
| | | GeoJsonPoint point = vehiclePosition.getPoint(); |
| | | if(Objects.nonNull(point)){ |
| | | Map<String, Double> distance = GeodesyUtil.getDistance(dto.getLongitude()+ "," + dto.getLatitude(), point.getX()+","+point.getY()); |
| | | if (Objects.nonNull(point)) { |
| | | Map<String, Double> distance = GeodesyUtil.getDistance(dto.getLongitude() + "," + dto.getLatitude(), point.getX() + "," + point.getY()); |
| | | if (null != distance) { |
| | | Double distance1 = distance.get("WGS84"); |
| | | if (distance1 > distanceThreshold) { |
| | | log.info("距离过远,无法打开 {} {} {}", dto.getLongitude()+ "," + dto.getLatitude(), point.getX()+","+point.getY(), distance1); |
| | | log.info("距离过远,无法打开 {} {} {}", dto.getLongitude() + "," + dto.getLatitude(), point.getX() + "," + point.getY(), distance1); |
| | | throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); |
| | | } |
| | | }else { |
| | | } else { |
| | | log.info("计算距离失败,无法打开车门"); |
| | | throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); |
| | | } |
| | | }else { |
| | | } else { |
| | | log.info("车辆无实时定位,无法打开车门"); |
| | | throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); |
| | | } |
| | |
| | | //查询后备箱开关状态(打开状态=true,关闭状态=false) |
| | | Boolean hasKey = vehicleControlUtil.queryTrunkDoorStateSync(xpOrder.getAppUserId(), xpVehicle.getVehicleVin(), reportEnable); |
| | | //打开状态 |
| | | if(hasKey){ |
| | | if (hasKey) { |
| | | xpOrder.setOpenTrunk(2); |
| | | vehiclesCommandVo.setCommandCode(VehiclesCommandEnum.DOOR_TRUNK_CLOSE.getCommand()); |
| | | }else{ |
| | | } else { |
| | | //关闭状态 |
| | | xpOrder.setOpenTrunk(1); |
| | | vehiclesCommandVo.setCommandCode(VehiclesCommandEnum.DOOR_TRUNK_OPEN.getCommand()); |
| | |
| | | log.info("车辆控制结果:{}", msgId); |
| | | if (StringUtils.isEmpty(msgId)) { |
| | | return 0; |
| | | }else { |
| | | } else { |
| | | xpOrderClient.updateOrder(xpOrder); |
| | | return 1; |
| | | } |
| | |
| | | log.info("车辆温度设置结果:{}", msgId); |
| | | if (StringUtils.isEmpty(msgId)) { |
| | | return 0; |
| | | }else { |
| | | } else { |
| | | return 1; |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | //绑定XPUID |
| | | String vin = xpVehicle.getVehicleVin(); |
| | | R<String> xpuIdByVin = xpuVinClient.getXpuIdByVin(vin); |
| | | if(200 != xpuIdByVin.getCode()){ |
| | | if (200 != xpuIdByVin.getCode()) { |
| | | throw new RuntimeException(xpuIdByVin.getMsg()); |
| | | } |
| | | String xpuid = xpuIdByVin.getData(); |
| | |
| | | // 仅在 VIN 变更或原 XPUID 为空时才重新绑定 XPUID,避免不必要的远程调用 |
| | | String vin = xpVehicle.getVehicleVin(); |
| | | R<String> xpuIdByVin = xpuVinClient.getXpuIdByVin(vin); |
| | | if(200 != xpuIdByVin.getCode()){ |
| | | if (200 != xpuIdByVin.getCode()) { |
| | | throw new RuntimeException(xpuIdByVin.getMsg()); |
| | | } |
| | | String xpuid = xpuIdByVin.getData(); |
| | |
| | | .collect(Collectors.toSet()); |
| | | LocalDate now = LocalDate.now(); |
| | | List<String> errorMessages = new ArrayList<>(); |
| | | |
| | | |
| | | for (XpVehicle vehicle : vehicles) { |
| | | List<String> reasons = new ArrayList<>(); |
| | | Locale locale = LocaleContextHolder.getLocale(); |
| | |
| | | |
| | | /** |
| | | * 获取服务车辆列表 |
| | | * |
| | | * @param dto |
| | | * @return |
| | | */ |
| | |
| | | |
| | | return list; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 运维APP解锁车门和开关后备箱 |
| | | * |
| | | * @param dto |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Integer unlockDoor(UnlockAppDTO dto, XpOperationsUser xpOperationsUser) { |
| | | XpVehicle xpVehicle = this.getById(dto.getVehicleId()); |
| | | // 判断距离是否在范围之内 15米 |
| | | VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); |
| | | if (Objects.nonNull(vehiclePosition)) { |
| | | GeoJsonPoint point = vehiclePosition.getPoint(); |
| | | if (Objects.nonNull(point)) { |
| | | Map<String, Double> distance = GeodesyUtil.getDistance(dto.getLongitude() + "," + dto.getLatitude(), point.getX() + "," + point.getY()); |
| | | if (null != distance) { |
| | | Double distance1 = distance.get("WGS84"); |
| | | if (distance1 > distanceThreshold) { |
| | | log.info("距离过远,无法打开 {} {} {}", dto.getLongitude() + "," + dto.getLatitude(), point.getX() + "," + point.getY(), distance1); |
| | | throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); |
| | | } |
| | | } else { |
| | | log.info("计算距离失败,无法打开车门"); |
| | | throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); |
| | | } |
| | | } else { |
| | | log.info("车辆无实时定位,无法打开车门"); |
| | | throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); |
| | | } |
| | | } |
| | | //先将运维人员和车辆绑定 |
| | | String phoneNumber = xpOperationsUser.getPhoneNumber(); |
| | | UcUserInfo userByMobile = userResourcesClient.getUserByMobile(phoneNumber); |
| | | Long uid = userByMobile.getUid(); |
| | | AddTaxiPassengerVo addVo = new AddTaxiPassengerVo(); |
| | | addVo.setVin(xpVehicle.getVehicleVin()); |
| | | addVo.setUid(userByMobile.getUid().toString()); |
| | | addVo.setOrderNo(phoneNumber); |
| | | addVo.setAppId(appid); |
| | | userVehicleClient.addTaxiPassenger(addVo); |
| | | log.info("已绑定运维与新车辆关系,电话号码: {}, VIN: {}", phoneNumber, xpVehicle.getVehicleVin()); |
| | | |
| | | try { |
| | | // 车门解锁、后备箱解锁 |
| | | VehiclesCommandVo vehiclesCommandVo = new VehiclesCommandVo(); |
| | | vehiclesCommandVo.setVin(xpVehicle.getVehicleVin()); |
| | | if ("door".equals(dto.getDoorType())) { |
| | | // 开启车门 判断是否为P档 |
| | | Integer gearLevel = redisService.getCacheObject(CacheConstants.GEAR_LEVEL + xpVehicle.getXpuId()); |
| | | log.info("开启车门当前车辆档位: {} {}", xpVehicle.getXpuId(), gearLevel); |
| | | if (gearLevel == null || gearLevel != 4) { |
| | | throw new ServiceException("车辆非P档,无法开启车门", I18nKeyConstant.VEHICLE_NOT_P_GEAR); |
| | | } |
| | | vehiclesCommandVo.setCommandCode(VehiclesCommandEnum.DOOR_UNLOCK.getCommand()); |
| | | } else { |
| | | // 开启后备箱 判断是否为P档 |
| | | Integer gearLevel = redisService.getCacheObject(CacheConstants.GEAR_LEVEL + xpVehicle.getXpuId()); |
| | | log.info("开启后备箱当前车辆档位: {} {}", xpVehicle.getXpuId(), gearLevel); |
| | | if (gearLevel == null || gearLevel != 4) { |
| | | throw new ServiceException("车辆非P档,无法操作后备箱", I18nKeyConstant.VEHICLE_NOT_P_GEAR); |
| | | } |
| | | //查询后备箱开关状态(打开状态=true,关闭状态=false) |
| | | Boolean hasKey = vehicleControlUtil.queryTrunkDoorStateSync(uid, xpVehicle.getVehicleVin(), reportEnable); |
| | | //打开状态 |
| | | if (hasKey) { |
| | | vehiclesCommandVo.setCommandCode(VehiclesCommandEnum.DOOR_TRUNK_CLOSE.getCommand()); |
| | | } else { |
| | | //关闭状态 |
| | | vehiclesCommandVo.setCommandCode(VehiclesCommandEnum.DOOR_TRUNK_OPEN.getCommand()); |
| | | } |
| | | } |
| | | // { |
| | | // "code": 0, |
| | | // "data": { |
| | | // "msgId": "1234556" |
| | | // }, |
| | | // "msg": "", |
| | | // "desc": "成功" |
| | | //} |
| | | String msgId = vehicleControlUtil.vehiclesCommand(vehiclesCommandVo, uid); |
| | | log.info("车辆控制结果:{}", msgId); |
| | | if (StringUtils.isEmpty(msgId)) { |
| | | return 0; |
| | | } else { |
| | | return 1; |
| | | } |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | }finally { |
| | | //解绑运维与车辆的绑定关系 |
| | | CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo(); |
| | | cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin()); |
| | | cancelTaxiPassengerVo.setUid(userByMobile.getUid().toString()); |
| | | cancelTaxiPassengerVo.setOrderNo(phoneNumber); |
| | | cancelTaxiPassengerVo.setAppId(appid); |
| | | userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | } |