xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/automaticPilot/PushOrderDto.java
@@ -1,5 +1,6 @@ package com.xiaopeng.api.dto.automaticPilot; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -13,4 +14,10 @@ // 订单id @ApiModelProperty("订单id") private Long orderId; /** * 订单操作类型 */ private OrderOperationType operation_type; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automatic/OrderMissionClientFallbackFactory.java
File was deleted xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpPricingClientFallbackFactory.java
@@ -34,10 +34,11 @@ } @Override public R<?> saveXpGeoQueryEntity(XpGeoQueryEntity xpGeoQueryEntity) { log.error("保存XpGeoQueryEntity失败", cause); public R<?> updateXpGeoQueryEntity(String orderId) { log.error("更新XpGeoQueryEntity失败", cause); return R.fail(); } }; } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/vehicleConvoy/XpVehicleClientFallbackFactory.java
@@ -67,6 +67,12 @@ log.error("查询车辆信息失败,原因: {}", cause.getMessage()); return R.fail(); } @Override public R<XpVehicle> findByVehicleXpuId(String xpuid) { log.error("查询车辆信息失败,原因: {}", cause.getMessage()); return R.fail(); } }; } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/automatic/OrderMissionClient.java
File was deleted xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpPricingClient.java
@@ -27,8 +27,8 @@ /** * 保存XpGeoQueryEntity */ @PostMapping("/inner/saveXpGeoQueryEntity") R<?> saveXpGeoQueryEntity(@RequestBody XpGeoQueryEntity xpGeoQueryEntity); @PostMapping("/inner/updateXpGeoQueryEntity") R<?> updateXpGeoQueryEntity(@RequestParam String orderId); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/vehicleConvoy/XpVehicleClient.java
@@ -79,4 +79,16 @@ */ @GetMapping("/inner/vehicle/findByVehicleVin") R<XpVehicle> findByVehicleVin(@RequestParam("vehicleVin") String vehicleVin); /** * 根据车辆xpuid查询车辆信息 * * @param xpuid * @return */ @GetMapping("/inner/vehicle/findByVehicleXpuId") R<XpVehicle> findByVehicleXpuId(@RequestParam("xpuid") String xpuid); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpGeoQueryEntity.java
@@ -30,7 +30,7 @@ * 时间戳 */ @Field("timestamp") private Date timestamp; private Long timestamp; /** * 秒数 @@ -81,11 +81,11 @@ this.location = location; } public Date getTimestamp() { public Long getTimestamp() { return timestamp; } public void setTimestamp(Date timestamp) { public void setTimestamp(Long timestamp) { this.timestamp = timestamp; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
@@ -53,6 +53,7 @@ @ApiModelProperty(value = "订单来源 1=APP下单") private Integer orderSource; @ApiModelProperty(value = "乘车时间") private LocalDateTime rideTime; @@ -133,7 +134,8 @@ @ApiModelProperty(value = "时长分钟") private Double duration; @ApiModelProperty(value = "时长费所属时段type=1 普通时段 type=2 夜间行驶时段 3高峰时段 4节假日时段") private Integer durationType; @ApiModelProperty(value = "时长费") private BigDecimal durationMoney; @@ -145,7 +147,8 @@ @ApiModelProperty(value = "远途公里") private Double longDistance; @ApiModelProperty(value = "远途费所属时段type=1 普通时段 type=2 夜间行驶时段 3高峰时段 4节假日时段") private Integer longDistanceType; @ApiModelProperty(value = "远途费") private BigDecimal longDistancemoney; xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrderEvaluate.java
@@ -30,7 +30,7 @@ private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.ASSIGN_ID) private Long id; @ApiModelProperty(value = "订单id") xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/vehicleConvoy/XpVehicle.java
@@ -40,6 +40,9 @@ @ApiModelProperty(value = "车辆vin码") private String vehicleVin; @ApiModelProperty(value = "车辆xpuid") private String xpuId; @ApiModelProperty(value = "车牌号") private String plateNumber; xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/RouteAndFareVo.java
@@ -1,5 +1,6 @@ package com.xiaopeng.api.vo.operation; import com.xiaopeng.api.vo.order.XpPricingCardVo; import io.swagger.annotations.ApiModel; @lombok.Data @@ -10,4 +11,7 @@ private FareVo fareEstimate; private XpPricingCardVo xpPricingCard; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/FareBreakdownDetailVo.java
@@ -15,7 +15,7 @@ private String time; @ApiModelProperty(value = "里程 单位公里") private BigDecimal mileage; @ApiModelProperty(value = "时间") @ApiModelProperty(value = "时间 分钟") private long duration; @ApiModelProperty(value = "金额") private BigDecimal money; xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -17,10 +17,12 @@ com.xiaopeng.api.factory.account.XpOperationUserClientFallbackFactory com.xiaopeng.api.factory.operation.XpElectronicClientFallbackFactory com.xiaopeng.api.factory.operation.XpOpenCityClientFallbackFactory com.xiaopeng.api.factory.operation.ReassignOrderClientFallbackFactory com.xiaopeng.api.factory.vehicleConvoy.UserVehicleClientFallbackFactory com.xiaopeng.api.factory.vehicleConvoy.XpFleetOperationsClientFallbackFactory com.xiaopeng.api.factory.pushMessage.XpPushMessageClientFallbackFactory com.xiaopeng.api.factory.account.UserResourcesClientFallbackFactory com.xiaopeng.api.factory.vehicleConvoy.VehicleControlClientFallbackFactory com.xiaopeng.api.factory.automaticPilot.XPUClientFallbackFactory com.xiaopeng.api.factory.automaticPilot.XpuVimClientFallbackFactory com.xiaopeng.api.factory.maintenance.XpCheckLocationClientFallbackFactory xp-robotaxi-automaticPilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/KafkaTestController.java
@@ -1,21 +1,14 @@ package com.xiaopeng.automaticPilot.controller; import com.alibaba.fastjson2.JSON; import com.xiaopeng.api.vo.automaticPilot.proto.up.MsgContent; import com.xiaopeng.automaticPilot.service.KafkaConsumerService; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.RestController; /** * Kafka 测试控制器 */ @Slf4j @RestController @RequestMapping("/kafka") @Api(tags = "Kafka 测试接口") public class KafkaTestController { @Autowired @@ -31,13 +24,8 @@ */ @KafkaListener(topics = "topic-prod-robotaxi-xpu-high", groupId = "group-robotaxi-xpu") public void topicProdRobotaxiXpuHigh(String message) { try { log.info("收到XPU上报高优先级主题消息: {}", message); kafkaConsumerService.topicProdRobotaxiXpuHigh(message); } catch (Exception e) { log.error("处理XPU上报高优先级主题消息失败: {}", message, e); throw e; } log.info("收到XPU上报高优先级主题消息: {}", message); kafkaConsumerService.topicProdRobotaxiXpuHigh(message); } /** @@ -47,12 +35,7 @@ */ @KafkaListener(topics = "topic-prod-robotaxi-xpu-normal", groupId = "group-robotaxi-xpu") public void topicProdRobotaxiXpuNormal(String message) { try { log.info("收到XPU上报低优先级主题消息: {}", message); kafkaConsumerService.topicProdRobotaxiXpuNormal(message); } catch (Exception e) { log.error("处理XPU上报低优先级主题消息失败: {}", message, e); throw e; } log.info("收到XPU上报低优先级主题消息: {}", message); kafkaConsumerService.topicProdRobotaxiXpuNormal(message); } } xp-robotaxi-automaticPilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -8,6 +8,8 @@ import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.RTTask; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskStatus; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskType; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperation; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import com.xiaopeng.automaticPilot.util.XPUUtil; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.utils.SnowFlake; @@ -52,4 +54,19 @@ } return R.ok(false); } @PostMapping("/inner/cancelOrder") R<Boolean> cancelOrder(@RequestBody PushOrderDto dto){ OrderOperation operation = new OrderOperation(); operation.setOrder_id(dto.getOrderId().toString()); operation.setTask_id("CANCEL_MISSION_"+ IdUtil.fastUUID()); operation.setOperation_type(dto.getOperation_type()); SnowFlake snowFlake = new SnowFlake(0, 0); snowFlake.withStartTimestamp(1420041600000L); long sequence = snowFlake.nextId(); xpuUtil.cloudOrderOperation(operation,dto.getVin(),sequence); redisService.setCacheObject(String.valueOf(sequence),"cancelOrder_"+dto.getOrderId()+"_"+ dto.getVin(),30l, TimeUnit.MINUTES); return R.ok(true); } } xp-robotaxi-automaticPilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -6,12 +6,15 @@ import com.alibaba.fastjson2.JSONObject; import com.xiaopeng.api.dto.map.OrderRouteAndFareDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.operation.ReassignOrderDTO; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.pushMessage.PushOrderRouteDTO; import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; import com.xiaopeng.api.feignClient.map.XpMapClient; import com.xiaopeng.api.feignClient.operation.ReassignOrderClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; @@ -32,6 +35,7 @@ import com.xiaopeng.api.vo.automaticPilot.proto.up.xpuNavigationRequest.NavigationRequest; import com.xiaopeng.api.vo.automaticPilot.proto.up.xpuNavigationRequest.OrderPhase; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo; import com.xiaopeng.automaticPilot.util.XPUUtil; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.OrderStatusEnum; @@ -52,6 +56,9 @@ import javax.annotation.Resource; import java.util.*; import java.util.concurrent.TimeUnit; import static org.bouncycastle.asn1.x500.style.RFC4519Style.l; import static org.bouncycastle.asn1.x500.style.RFC4519Style.uid; /** * Kafka 消费者服务 @@ -77,9 +84,13 @@ @Autowired public RedisTemplate redisTemplate; @Autowired private UserVehicleClient userVehicleClient; @Resource private XpPushMessageClient xpPushMessageClient; @Autowired private ReassignOrderClient reassignOrderClient; @@ -89,6 +100,24 @@ */ public void topicProdRobotaxiXpuHigh(String message) { MsgContent msgContent = JSON.parseObject(message, MsgContent.class); handleXPUMessage(msgContent, message); } /** * 消费消息 - XPU上报Robotaxi云端的消息topic(低优先级) */ public void topicProdRobotaxiXpuNormal(String message) { MsgContent msgContent = JSON.parseObject(message, MsgContent.class); handleXPUMessage(msgContent, message); } /** * 处理XPU消息 * @param msgContent * @param message */ public void handleXPUMessage(MsgContent msgContent, String message){ RtMsgHeader header = msgContent.getHeader(); MessageType type = header.getType(); //处理请求消息 @@ -166,94 +195,21 @@ Object sequence = redisTemplate.opsForValue().get(requestSeq); if(sequence!=null){ String[] split = sequence.toString().split("_"); if(split[0].equals("pushOrder")){ String typeStr = split[0]; // 推单处理 if(typeStr.equals("pushOrder")){ PopOrderDto dto = new PopOrderDto(); dto.setOrderId(Long.valueOf(split[1])); dto.setXpVehicleVin(split[2]); xpOrderClient.popOrder(dto); } } } } } /** * 消费消息 - XPU上报Robotaxi云端的消息topic(低优先级) */ public void topicProdRobotaxiXpuNormal(String message) { MsgContent msgContent = JSON.parseObject(message, MsgContent.class); RtMsgHeader header = msgContent.getHeader(); MessageType type = header.getType(); //处理请求消息 if (MessageType.MESSAGE_TYPE_REQUEST == type) { //区分业务类型 RTCmdType cmd = header.getCmd(); switch (cmd) { case SYSTEM_STATUS_XPU: log.info("XPU发布系统运行状态 (XPU→云端):{}", message); systemStatusXpu(msgContent); break; case XPU_NAVIGATION_REQUEST: log.info("XPU向云端请求导航 (XPU→云端):{}", message); xpuNavigationRequest(msgContent); break; case TRIP_STATUS_UPDATE_EVENT: log.info("行程状态更新(XPU→云端)(XPU→座舱):{}", message); break; case PULLOVER_STATUS_EVENT: log.info("靠边停车状态(XPU→云端)(XPU→座舱):{}", message); break; case DRIVING_MODE_UPDATE_EVENT: log.info("驾驶模式变化(XPU→云端)(XPU→座舱):{}", message); break; case SYSTEM_STATUS_UPDATE_EVENT: log.info("系统状态变化(XPU→云端)(XPU→座舱):{}", message); break; case TASK_STATE_UPDATE_EVENT: log.info("任务状态变化(XPU→云端)(XPU→座舱):{}", message); break; case ORDER_STATE_UPDATE_EVENT: log.info("订单状态变化(XPU→云端)(XPU→座舱):{}", message); orderStateUpdateEvent(msgContent); break; case POINT_ARRIVAL_STATUS_EVENT: log.info("到达目标点状态(XPU→云端)(XPU→座舱):{}", message); break; case PICKUP_CONFIRMATION_EVENT: log.info("用户上车确认(XPU→云端)(XPU→座舱):{}", message); break; case DROPOFF_INFO_EVENT: log.info("用户下车信息(XPU→云端):{}", message); break; case NAVIGATION_DEVIATION_EVENT: log.info("导航偏航(XPU→云端):{}", message); navigationDeviationEvent(msgContent); break; case EMERGENCY_STOP_EVENT: log.info("急停(XPU→云端)(XPU→座舱):{}", message); break; case NAVIGATION_UPDATE_EVENT: log.info("导航信息变化(XPU→云端):{}", message); break; case TASK_QUEUE_UPDATE_EVENT: log.info("XPU待执行任务队列(XPU→云端):{}", message); break; case SYSTEM_STATE_ANAPSHOT_SYNC_EVENT: log.info("每次MQTT连接之后触发 (XPU→云端):{}", message); break; case ORDER_STATE_UPDATE_TO_CDU_EVENT: log.info("更新订单状态到CDU (XPU→云端):{}", message); break; default: log.info("消息不在处理范围内,忽略:{}", message); } } } /** @@ -273,7 +229,9 @@ Float alt = naviPose.getAlt(); //获取车辆静态信息 VehicleStaticInfo staticInfo = systemRuntimeStatus.getVehicle_status().getStatic_info(); String vin = staticInfo.getVin(); String xpuId = staticInfo.getXpu_id(); XpVehicle xpVehicle = xpVehicleClient.findByVehicleXpuId(xpuId).getData(); String vin = xpVehicle.getVehicleVin(); //先响应消息 Long sequence = msgContent.getHeader().getSequence(); responseMessage(sequence, vin); @@ -325,6 +283,56 @@ /** * XPU发布系统运行状态---车辆实时位置 * * @param msgContent */ public void systemStatusXpuAndReassign(MsgContent msgContent) { //开始处理消息对应的业务逻辑 SystemRuntimeStatus systemRuntimeStatus = msgContent.getContent_detail().getObject("systemRuntimeStatus", SystemRuntimeStatus.class); AbnormalReason abnormalReason = systemRuntimeStatus.getSystem_status().getAbnormal_reason(); // 判断是否为故障状态 if (abnormalReason == AbnormalReason.FAULT) { log.info("车辆故障,开始处理故障"); // TODO 添加异常任务 // 解绑用户与车辆关系 CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo(); String orderId = systemRuntimeStatus.getRunning_order_status_info().getOrder_id(); XpOrder xpOrder = xpOrderClient.queryOrderById(Long.parseLong(orderId)).getData(); XpVehicle vehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); if (vehicle != null) { // 修改车辆状态 vehicle.setOperatingStatus(4); xpVehicleClient.updateVehicleById(vehicle); cancelTaxiPassengerVo.setVin(vehicle.getVehicleVin()); cancelTaxiPassengerVo.setUid(xpOrder.getAppUserId().toString()); cancelTaxiPassengerVo.setOrderNo(xpOrder.getOrderNumber()); // TODO // cancelTaxiPassengerVo.setAppId(); userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); } // 取消订单 R<?> r = xpOrderClient.cancelOrder(String.valueOf(xpOrder.getId())); if (r.getCode() == R.SUCCESS){ log.info("取消订单成功"); // 重新派单 ReassignOrderDTO reassignOrderDTO = new ReassignOrderDTO(); reassignOrderDTO.setUid(xpOrder.getAppUserId().toString()); reassignOrderDTO.setOrderNo(xpOrder.getOrderNumber()); reassignOrderDTO.setCount(10); RealtimePose pose = systemRuntimeStatus.getPose(); Wgs naviPose = pose.getNavi_pose(); Double latitude = naviPose.getLatitude(); Double longitude = naviPose.getLongitude(); reassignOrderDTO.setLongitude(longitude); reassignOrderDTO.setLatitude(latitude); reassignOrderClient.reassignOrder(reassignOrderDTO); } } } /** * XPU向云端请求导航 * * @param msgContent xp-robotaxi-automaticPilot-boot/src/main/java/com/xiaopeng/automaticPilot/util/XPUUtil.java
@@ -8,16 +8,23 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson2.JSON; import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto; import com.xiaopeng.api.feignClient.automaticPilot.VmpOpenServiceClient; import com.xiaopeng.api.feignClient.automaticPilot.XPUClient; import com.xiaopeng.api.vo.automaticPilot.MqttPublishVo; import com.xiaopeng.api.vo.automaticPilot.proto.down.*; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.RTTask; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperation; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.utils.uuid.UUID; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; /** * 自动驾驶接口对接文档 @@ -28,6 +35,15 @@ @Resource private XPUClient xpuClient; @Resource private VmpOpenServiceClient vmpOpenServiceClient; // 查询车管绑定类型,1:XPUID,2:待扩展 public static final String XPU_ID_TYPE = "1"; // 查询车管 车辆xpuid信息返回字段,用于按需返回字段 public static final List<String> TYPE_LIST = Collections.singletonList("1"); /** @@ -51,10 +67,11 @@ jsonObject.put("task", task); msgContent.setContent_detail(jsonObject); log.info("云端-->XPU 创建订单:{}", msgContent); //根据车辆VIN查询XPUID String xpuId = getXpuIdByVin(vin); //组装请求消息体 MqttPublishVo vo = new MqttPublishVo(); vo.setTopic("topic-prod-xpu-robotaxi-high/" + vin); vo.setTopic("topic-prod-xpu-robotaxi-high/" + xpuId); vo.setPayload(JSON.toJSONString(msgContent)); return xpuClient.publish(vo); } @@ -82,14 +99,12 @@ jsonObject.put("operation", operation); msgContent.setContent_detail(jsonObject); log.info("云端-->XPU 操作订单:{}", msgContent); //根据车辆VIN查询XPUID String xpuId = getXpuIdByVin(vin); //组装请求消息体 MqttPublishVo vo = new MqttPublishVo(); vo.setTopic("topic-prod-xpu-robotaxi-high/" + vin); vo.setTopic("topic-prod-xpu-robotaxi-high/" + xpuId); vo.setPayload(JSON.toJSONString(msgContent)); return xpuClient.publish(vo); } @@ -118,11 +133,32 @@ jsonObject.put("resposne", responseMessage); msgContent.setContent_detail(jsonObject); log.info("云端-->XPU 响应消息:{}", msgContent); //根据车辆VIN查询XPUID String xpuId = getXpuIdByVin(vin); //组装请求消息体 MqttPublishVo vo = new MqttPublishVo(); vo.setTopic("topic-prod-xpu-robotaxi-high/" + vin); vo.setTopic("topic-prod-xpu-robotaxi-high/" + xpuId); vo.setPayload(JSON.toJSONString(msgContent)); return xpuClient.publish(vo); } /** * @description: 根据vin查询xpuId * @param: vin * @return: xpuId */ public String getXpuIdByVin(String vin) { Map<String, String> xpuIdMapping = vmpOpenServiceClient.getVehicleBindInfoByVin(vin, TYPE_LIST); log.info("getMqttPublishTopic vin,{},xpuIdMapping,{}", vin, JSON.toJSONString(xpuIdMapping)); if (xpuIdMapping == null || StringUtils.isEmpty(xpuIdMapping.get(XPU_ID_TYPE)) ) { log.error("根据vin查询车辆xpuid信息为空,vin={}", vin); throw new RuntimeException("根据vin查询车辆xpuid信息为空"); } return xpuIdMapping.get(XPU_ID_TYPE); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java
@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import java.util.Date; /** * <p> @@ -49,29 +50,28 @@ } @PostMapping("/base/v1/mini-program/navigation/route-and-fare") @ApiOperation(value = "导航-获取路线和费用",tags = {"小程序-获取路线和费用"},response = RouteAndFareVo.class) @ApiOperation(value = "导航-获取路线和费用", tags = {"小程序-获取路线和费用"}, response = RouteAndFareVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R<RouteAndFareVo> getRouteAndFare(@RequestBody @Valid RouteAndFareDto routeAndFareDto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpPricingService.getRouteAndFare(routeAndFareDto,uid)); return R.ok(xpPricingService.getRouteAndFare(routeAndFareDto, uid)); } // 根据开通城市 获取定价 @GetMapping("/getPricingByCityId/{cityId}") public R<XpPricing> getPricingByCityId(@PathVariable("cityId")Long cityId) { public R<XpPricing> getPricingByCityId(@PathVariable("cityId") Long cityId) { XpPricing pricing = xpPricingService.lambdaQuery().eq(XpPricing::getCityId, cityId).last("limit 1").one(); return R.ok(pricing); } @GetMapping("/base/v1/mini-program/pricing/rules/{openCityId}") @ApiOperation(value = "获取费用规则",tags = {"小程序-根据开通城市获取费用规则"},response = String.class) @ApiOperation(value = "获取费用规则", tags = {"小程序-根据开通城市获取费用规则"}, response = String.class) public R<?> getPricingRules(@PathVariable Long openCityId) { XpPricing xpPricing = xpPricingService.getOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, openCityId).eq(XpPricing::getPricingType, 1).last("limit 1")); if(xpPricing!=null){ if (xpPricing != null) { return R.ok(xpPricing.getPriceRule()); } return R.ok(""); @@ -84,20 +84,20 @@ * @return */ @PostMapping("/base/v1/mini-program/pricing/getWaitTime") @ApiOperation(value = "获取等待时间",tags = {"小程序-获取等待时间"},response = Integer.class) public R<Integer> getWaitTime(@RequestBody LonLatDto dto){ return R.ok(xpPricingService.getWaitTime(dto.getLongitude(),dto.getLatitude())); @ApiOperation(value = "获取等待时间", tags = {"小程序-获取等待时间"}, response = Integer.class) public R<Integer> getWaitTime(@RequestBody LonLatDto dto) { return R.ok(xpPricingService.getWaitTime(dto.getLongitude(), dto.getLatitude())); } /** * 保存信息 * @param xpGeoQueryEntity * @param * @return */ @PostMapping("/inner/saveXpGeoQueryEntity") public R<?> saveXpGeoQueryEntity(@RequestBody XpGeoQueryEntity xpGeoQueryEntity){ xpGeoQueryEntityService.save(xpGeoQueryEntity); @PostMapping("/inner/updateXpGeoQueryEntity") public R<?> updateXpGeoQueryEntity(@RequestParam String orderId) { xpGeoQueryEntityService.updateByOrderId(orderId); return R.ok(); } @@ -106,7 +106,7 @@ * 播单 */ @PostMapping("/base/v1/mini-program/order/save") @ApiOperation(value = "保存订单",tags = {"小程序-保存订单"}) @ApiOperation(value = "保存订单", tags = {"小程序-保存订单"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R<SaveOrderVo> saveOrder(@RequestBody @Validated XpOrderDto dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); @@ -115,8 +115,6 @@ saveOrderVo.setOrderId(l); return R.ok(saveOrderVo); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpGeoQueryEntityService.java
@@ -20,6 +20,9 @@ String time ); /** * 保存地理查询实体 * @param entity 地理查询实体 @@ -27,6 +30,12 @@ */ XpGeoQueryEntity save(XpGeoQueryEntity entity); /** * 修改 */ XpGeoQueryEntity updateByOrderId(String orderId); /** * 根据ID查询实体 * @param id 实体ID xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpBannerServiceImpl.java
@@ -27,7 +27,6 @@ @Override public List<XpBannerListVo> getXpBannerList() { LambdaQueryWrapper<XpBanner> wrapper = new LambdaQueryWrapper<>(); // TODO 魔法数字 wrapper.eq(XpBanner::getBannerStatus,1); // 当前时间在开始和结束时间范围内 wrapper.ge(XpBanner::getStartTime,System.currentTimeMillis()); xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpGeoQueryEntityServiceImpl.java
@@ -1,17 +1,25 @@ package com.xiaopeng.operation.service.impl; import com.xiaopeng.api.model.operation.XpGeoQueryEntity; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.operation.repository.XpGeoQueryEntityRepository; import com.xiaopeng.operation.service.IXpGeoQueryEntityService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * MongoDB 地理查询服务实现类 @@ -21,6 +29,9 @@ @Autowired private XpGeoQueryEntityRepository repository; @Autowired private MongoTemplate mongoTemplate; /** * 通过经纬度查询固定范围500米内、一周内、指定时段的数据 @@ -35,26 +46,43 @@ double latitude, String time ) { // 创建中心点坐标 Point point = new Point(longitude, latitude); // 设置距离范围为500米 Distance distance = new Distance(0.5, Metrics.KILOMETERS); // 0.5公里 = 500米 // 计算一周前的时间 // // 计算一周前的时间 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_YEAR, -7); Date startTime = calendar.getTime(); Long startTime = calendar.getTime().getTime(); // 执行查询 - 使用新的方法,包含时段过滤 return repository.findByLocationNearAndTimestampAfterAndTimeAndStatusGreaterThan( point, 500, startTime, time, // 时段过滤 1 // 状态大于1 // 1. 创建查询点 Point referencePoint = new Point(longitude, latitude); // 2. 构建 NearQuery - 完全使用 NearQuery 的 API NearQuery nearQuery = NearQuery.near(referencePoint, Metrics.KILOMETERS) .maxDistance(0.5) // 转成公里 .spherical(true); // 3.时间>startTime time = time参数 // 3. 创建额外的查询条件 Query query = new Query(); query.addCriteria(Criteria.where("timestamp").gte(startTime)); query.addCriteria(Criteria.where("time").is(time)); // 将 NearQuery 和额外的查询条件合并 nearQuery.query(query); // 4. 执行查询 - 明确指定集合名 GeoResults<XpGeoQueryEntity> geoResults = mongoTemplate.geoNear( nearQuery, XpGeoQueryEntity.class, "xp_geo_query_entity" // 明确指定集合名,避免映射错误 ); // 5. 提取结果 return geoResults.getContent().stream() .map(geoResult -> geoResult.getContent()) .collect(Collectors.toList()); } /** @@ -67,6 +95,25 @@ return repository.save(entity); } @Override public XpGeoQueryEntity updateByOrderId(String orderId) { Query query = new Query(Criteria.where("orderId").is(orderId)); XpGeoQueryEntity xpGeoQueryEntity = mongoTemplate.findOne(query, XpGeoQueryEntity.class); Long timestamp = xpGeoQueryEntity.getTimestamp(); long time = new Date().getTime(); // 计算2个时间的秒数差 long seconds = (time- timestamp) / 1000; Update update = new Update().set("seconds", seconds).set("status", 1); if(xpGeoQueryEntity.getStatus()==0){ mongoTemplate.findAndModify(query, update, XpGeoQueryEntity.class); } return null; } /** * 根据ID查询实体 * @param id 实体ID xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -20,6 +20,7 @@ import com.xiaopeng.api.vo.operation.FareVo; import com.xiaopeng.api.vo.operation.RouteAndFareVo; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.order.XpPricingCardVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.exception.ServiceException; @@ -35,12 +36,13 @@ import com.xiaopeng.operation.utils.XpPricingUtil; import com.xiaopeng.operation.utils.holiday.HolidayUtil; import com.xiaopeng.operation.utils.map.FastDistanceCalculator; import com.xiaopeng.operation.vo.XpPricingCardVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.stereotype.Service; import javax.annotation.PreDestroy; import javax.annotation.Resource; import java.time.Duration; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.*; @@ -89,8 +91,6 @@ @Resource private XpElectronicFenceAreaMapper xpElectronicFenceAreaMapper; @Resource private XpVehicleClient xpVehicleClient; @Resource private XpPointMapper xpPointMapper; @@ -206,6 +206,8 @@ // ); XpPricingCardVo xpPricingCardVo = new XpPricingCardVo(); // 3. 并行执行远程服务调用 判断是否同一经营区域 CompletableFuture<R<Boolean>> diagnosisAreaFuture = CompletableFuture.supplyAsync( () -> xpMapClient.diagnosisArea(routeAndFareDto), @@ -274,6 +276,9 @@ RouteAndFareVo routeAndFareVo = new RouteAndFareVo(); // routeAndFareVo.setRoute(routeVo); routeAndFareVo.setXpPricingCard(xpPricingCardVo); FareVo fareVo = new FareVo(); // fareVo.setEstimatedDistanceKm(routeVo.getDistance().doubleValue() / 1000); // fareVo.setEstimatedDurationMin(routeVo.getDuration() / 60); @@ -333,7 +338,7 @@ return 1; } else { // 已完成接单的数据 List<XpGeoQueryEntity> validEntities = entities.stream().filter(e -> e.getStatus() > 1).collect(Collectors.toList()); List<XpGeoQueryEntity> validEntities = entities.stream().filter(e -> e.getStatus() == 1).collect(Collectors.toList()); // 计算平均等待时间 OptionalDouble averageOptional = validEntities.stream().mapToDouble(XpGeoQueryEntity::getSeconds).average(); @@ -347,6 +352,8 @@ double waitMinutes = (average * count) / 60; if (waitMinutes > 3) { throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME); }else if(waitMinutes==0){ return 1; } return (int) waitMinutes; } @@ -415,6 +422,8 @@ // 生成订单数据 XpOrder xpOrder = new XpOrder(); xpOrder.setVehicleId(1l); // xpOrder.setStartMileage(Double.valueOf(startMileage)); @@ -517,6 +526,16 @@ xpOrder.setQueueName(s); xpOrderClient.updateOrder(xpOrder); // 存储mongodb 数据 XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity(); xpGeoQueryEntity.setOrderId(orderId.toString()); xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(),xpPoint.getPointLat())); // 计算2个时间的秒数 xpGeoQueryEntity.setTime(currentTimeSlot); xpGeoQueryEntity.setStatus(0); xpGeoQueryEntity.setTimestamp(System.currentTimeMillis()); geoQueryEntityService.save(xpGeoQueryEntity); return orderId; } } @@ -525,6 +544,18 @@ redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule())); xpOrder.setQueueName(key); xpOrderClient.updateOrder(xpOrder); // 存储mongodb 数据 XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity(); xpGeoQueryEntity.setOrderId(orderId.toString()); xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(),xpPoint.getPointLat())); // 计算2个时间的秒数 xpGeoQueryEntity.setTime(currentTimeSlot); xpGeoQueryEntity.setStatus(0); geoQueryEntityService.save(xpGeoQueryEntity); return orderId; // xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -1,14 +1,15 @@ package com.xiaopeng.operation.utils; import cn.hutool.core.bean.BeanUtil; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.map.RouteAndFareDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.operation.VehiclePositionByVinDto; import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.map.XpMapClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.VehicleControlClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpTradingStrategy; @@ -16,6 +17,7 @@ import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.operation.VehiclePositionVo; import com.xiaopeng.api.vo.vehicleConvoy.AddTaxiPassengerVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.domain.R; @@ -25,8 +27,8 @@ import com.xiaopeng.operation.service.IXpTradingStrategyService; import com.xiaopeng.operation.service.XpPointService; import com.xiaopeng.operation.utils.mango.VehiclePositionService; import com.xiaopeng.api.vo.operation.VehiclePositionVo; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; @@ -39,6 +41,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Slf4j @Component public class TaskOrderUtil { @@ -72,6 +75,9 @@ @Autowired private XpMapClient xpMapClient; // @Autowired private OrderMissionClient orderMissionClient; // 自定义线程池 @@ -102,7 +108,7 @@ String[] split = firstElement.toString().split("_"); // 如果未处理 创建新任务 if (split[2].equals("0")) { String value = split[0] + "_" + split[1] + "_1" + "_"+split[3] + "_"+ split[4] + "_"+ split[5] + "_"+ split[6] + "_"+ split[7]; String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7]; // 状态改为处理中 redisService.updateFirst(name, value); threadPoolTaskExecutor.submit(() -> { @@ -220,8 +226,8 @@ @SneakyThrows private void processPushOrder(String quoteName, int count, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, String distance, String duration, String planRule) { System.out.println("进入推单环环节"); if(count==0){ count=1; if (count == 0) { count = 1; } // 订单状态 R<XpOrder> xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); @@ -596,7 +602,142 @@ // 订单价值 if (Objects.equals(secondMax, tendencyOrderValue)) { // 订单价值 // 时间差权重 Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference(); // 距离差权重 Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference(); // 距离权重 Integer weightDistance = xpTradingStrategy.getWeightDistance(); // 时间权重 Integer weightTime = xpTradingStrategy.getWeightTime(); // 电量权重 Integer weightElectricity = xpTradingStrategy.getWeightElectricity(); // 找出最大的值是那个 Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity)))); // 时间差 if (max1.equals(weightTimeDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration(); vehiclePosition.setTimeDifference(durationDifference); } } } if (max1.equals(weightDistanceDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance(); vehiclePosition.setDistanceDifference(distanceDifference); } } } if (max1.equals(weightDistance)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } } if (max1.equals(weightTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } } if (max1.equals(weightElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size1 = tendencyElectricity; // 做比对的分数 int temp1 = availableVehiclesNearby.get(0).getCurrentElectricity(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size1); if (temp1 != vehiclePosition.getCurrentElectricity()) { size1--; } } } // 算出总分 再来排序计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()); } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList()); int size2 = tendencyOrderValue; // 做比对的分数 double temp2 = availableVehiclesNearby.get(0).getOrderValueTotal(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size2); if (temp2 != vehiclePosition.getOrderValueTotal()) { size2--; } } } } @@ -616,7 +757,7 @@ RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePositionVo.getVin()); lock.lock(10, TimeUnit.SECONDS); System.err.println("队列:"+quoteName+" 车辆:"+vehiclePositionVo.getVin()+"订单"+orderNo); System.err.println("队列:" + quoteName + " 车辆:" + vehiclePositionVo.getVin() + "订单" + orderNo); try { // VehiclePosition vehiclePosition = vehiclePositionService.findByVehicleId(vehiclePositionVo.getVehicle_id()); R<XpVehicle> vehiclePositionR = xpVehicleClient.findByVehicleVin(vehiclePositionVo.getVin()); @@ -630,27 +771,15 @@ } // 关闭巡游单子 TODO AddTaxiPassengerVo addTaxiPassengerVo = new AddTaxiPassengerVo(); addTaxiPassengerVo.setVin(vehiclePosition.getVehicleVin()); addTaxiPassengerVo.setUid(uid); addTaxiPassengerVo.setOrderNo(orderNo); // TODO appid addTaxiPassengerVo.setAppId(""); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(xpOrder.getId()); pushOrderDto.setVin(vehiclePosition.getVehicleVin()); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.addTaxiPassenger(addTaxiPassengerVo); if (baseVehicleUserDto!=null && baseVehicleUserDto.getCode() == 200) { // TODO 下单 // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); // 调用推送服务 orderId + carVin // 绑定成功 弹出这个队列第一个订单 redisService.popFirstElement(quoteName); return; } } catch (Exception e) { e.printStackTrace(); } finally { @@ -666,33 +795,25 @@ lock.lock(10, TimeUnit.SECONDS); try { // 查询车辆状态 R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); if(vehicleR.getCode()!=200){ continue; } XpVehicle vehicleId1 = vehicleR.getData(); R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); if (vehicleR.getCode() != 200) { continue; } XpVehicle vehicleId1 = vehicleR.getData(); if (vehicleId1.getStatus() != 1 || vehicleId1.getState() != 0) { lock.unlock(); continue; } if (vehiclePosition.getHasOrder() == 1) { // 关闭巡游单子 TODO } AddTaxiPassengerVo addTaxiPassengerVo = new AddTaxiPassengerVo(); addTaxiPassengerVo.setVin(vehiclePosition.getVin()); addTaxiPassengerVo.setUid(uid); addTaxiPassengerVo.setOrderNo(orderNo); // TODO appid addTaxiPassengerVo.setAppId(""); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.addTaxiPassenger(addTaxiPassengerVo); if (baseVehicleUserDto.getCode() == 200) { // 关闭巡游单子 TODO PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(xpOrder.getId()); pushOrderDto.setVin(vehiclePosition.getVin()); redisService.popFirstElement(quoteName); lock.unlock(); return; } // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); } catch (Exception e) { } finally { @@ -704,5 +825,70 @@ } } /** * 订单处理 * @param count 轮数 * @param uid * @param longitude 经度 * @param latitude 纬度 * @param orderNo 订单号 */ @SneakyThrows public void reassignPushOrder(int count, String uid, Double longitude, Double latitude, String orderNo) { System.out.println("进入推单环环节"); if (count == 0) { count = 1; } // 订单状态 R<XpOrder> xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { return; } if (xpOrderR.getData().getStatus() != 1) { return; } XpOrder data = xpOrderR.getData(); XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null); for (int i = 0; i < count; i++) { log.info("进入找车环节"); List<VehiclePosition> positionList = vehiclePositionService.findAvailableVehiclesNearby(longitude, latitude, xpTradingStrategy.getOnePushDistance(), xpTradingStrategy.getSimultaneouslyOrderCount()); // 获取车辆的区域信息 if (positionList.isEmpty()) { continue; } // 直接派单 定义一个锁来锁定车辆 VehiclePosition vehiclePosition = positionList.get(0); String vehicleVin = vehiclePosition.getVin(); RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePosition.getVin()); lock.lock(10, TimeUnit.SECONDS); try { // 查询车辆状态 R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); if (vehicleR.getCode() != 200) { continue; } XpVehicle vehicleId1 = vehicleR.getData(); if (vehicleId1.getStatus() != 1 || vehicleId1.getState() != 0) { lock.unlock(); continue; } // 关闭巡游单子 TODO PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(data.getId()); pushOrderDto.setVin(vehiclePosition.getVin()); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); } catch (Exception e) { } finally { lock.unlock(); } } } } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.ImmutableMap; import com.xiaopeng.api.dto.account.GetUserCouponDto; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; @@ -20,6 +21,7 @@ import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; import com.xiaopeng.api.feignClient.account.XpAppUserClient; import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.operation.XpPointClient; import com.xiaopeng.api.feignClient.operation.XpPricingClient; import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient; @@ -33,14 +35,13 @@ import com.xiaopeng.api.model.operation.XpFeedbackType; import com.xiaopeng.api.model.operation.XpPoint; import com.xiaopeng.api.model.operation.XpPricing; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.order.XpOrderCancel; import com.xiaopeng.api.model.order.XpOrderEvaluate; import com.xiaopeng.api.model.order.XpOrderReassign; import com.xiaopeng.api.model.order.*; import com.xiaopeng.api.model.vehicleConvoy.XpFleet; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.account.UserCouponVo; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import com.xiaopeng.api.vo.order.*; import com.xiaopeng.api.vo.vehicleConvoy.AddTaxiPassengerVo; import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.domain.R; @@ -62,6 +63,7 @@ import com.xiaopeng.order.job.jobs.OrderCancelJob; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import com.xiaopeng.order.mangodb.service.OrderTrajectoryService; import com.xiaopeng.order.mapper.XpOrderDetailMapper; import com.xiaopeng.order.mapper.XpOrderMapper; import com.xiaopeng.order.model.dto.XpOrderCommentDto; import com.xiaopeng.order.model.dto.XpOrderPayDto; @@ -127,6 +129,8 @@ private final XpSystemSettingClient xpSystemSettingClient; private final OrderTrajectoryService orderTrajectoryService; private final XpPushMessageClient xpPushMessageClient; private final OrderMissionClient orderMissionClient; private final XpOrderDetailMapper xpOrderDetailMapper; @Autowired private MongoTemplate mongoTemplate; @@ -726,7 +730,6 @@ // TODO 加配置文件取 cancelTaxiPassengerVo.setAppId(""); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); if (baseVehicleUserDto.getCode() != 200) { throw new RuntimeException("取消订单失败"); @@ -749,6 +752,13 @@ Integer i = Integer.valueOf(cacheObject.toString()); redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, i + 1); } // 下发命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.VEHICLE_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); } @Override @@ -769,7 +779,10 @@ xpOrderCancelService.save(xpOrderCancel); // 推送消息 R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId()); XpVehicle xpVehicle = xpVehicleR.getData(); // 消息推送 Map<String, Object> params = new HashMap<>(); Map<String, Object> content = new HashMap<>(); @@ -784,6 +797,13 @@ sendMessageDTO.setAppUserId(String.valueOf(order.getAppUserId())); xpPushMessageClient.sendStatus(sendMessageDTO); log.info("订单取消消息推送完毕"); // 下发命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); } /** @@ -817,6 +837,7 @@ evaluate.setFeedbackContent(dto.getFeedbackContent()); evaluate.setFeedbackPictures(dto.getFeedbackPictures()); evaluate.setFeedbackTypeId(dto.getFeedbackTypeId()); evaluate.setCreateTime(LocalDateTime.now()); xpOrderEvaluateService.save(evaluate); } @@ -882,6 +903,7 @@ @Override public void endTrip(Long orderId, String uid) { List<XpOrderDetail> xpOrderDetails = new ArrayList<>(); // 起步价格明细 List<FareBreakdownDetailVo> start = new ArrayList<>(); // 里程费价格明细 @@ -962,11 +984,11 @@ } // --- 远途加价区间配置 (关键修改) --- // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2) config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(5.0, 6.0, 1.2)); config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num6")), Double.parseDouble(basicPricingJson.getString("num7")), Double.parseDouble(basicPricingJson.getString("num8")))); // 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0) config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(6.0, 7.0, 2.0)); config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num9")), Double.parseDouble(basicPricingJson.getString("num10")), Double.parseDouble(basicPricingJson.getString("num11")))); // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值 config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(7.0, 8.0, 3.5)); config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num12")), 999999, Double.parseDouble(basicPricingJson.getString("num13")))); TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService(); Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getCreateTime()), order.getMileageKilometers(), gpsPoints, config); @@ -1035,6 +1057,7 @@ mileageDetail.setMileage(distance); mileageDetail.setMoney(money); } mileage.add(mileageDetail); } // 封装时长费 @@ -1054,354 +1077,39 @@ longDistance.add(longDetail); } } // // 计算实际价格 // // 查询订单轨迹 // List<OrderTrajectory> trajectories = mongoTemplate.find( // new Query(Criteria.where("orderId").is(orderId)) // .with(Sort.by(Sort.Direction.ASC, "locatetime")), // OrderTrajectory.class // ); // // 计算等待时间 // LocalDateTime boardingTime = order.getBoardingTime();// 上车时间 // LocalDateTime arrivalTime = order.getArrivalTime();// 车辆到达上车点时间 // // 行程开始时间 // Integer waitTime = Math.abs((int) Duration.between(boardingTime, arrivalTime).getSeconds()); // // // 行程总时间 秒 // LocalDateTime tripBegin = order.getTripBegin(); // LocalDateTime tripEnd = order.getTripEnd(); // long seconds = Duration.between(tripBegin, tripEnd).getSeconds(); // // 默认费率1 // double priceRate = 1; // if (pricing.getIsDynamicPrice() == 1) { // // 先判断是否已经调价过了 // Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid); // if (userDynamicPriceObj != null) { // // 是否调价过了 // priceRate = Double.parseDouble(userDynamicPriceObj.toString()); // } else { // // 没有调过 // //是否触发动态调价 redis获取 // Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + order.getCityId()); // if (dynamicPriceObj != null) { // JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson()); // // 触发动态调价 // // value=时间 // String timeStr = dynamicPriceObj.toString(); // // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 // Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId())); // // X单上升一次调价 // Integer orderNum = getOrderNum(jsonObject, 4); // // 需要调价的次数 // int count = num / orderNum; // if (count > 0) { // // 计算每次上升的费率 // Integer upRate = getOrderNum(jsonObject, 5); // BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); // for (int i = count; i > 0; i--) { // // 当前费率+(费率*上升百分比) // priceRate = new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue(); // } // // 冷却时间 // Integer time = getOrderNum(jsonObject, 6); // // 触发调价了 // redisService.setCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid, priceRate, time.longValue(), TimeUnit.MINUTES); // } // // } // } // } // if (trajectories.isEmpty()) { // return; // } // // 起步价规则 // String startingFareJson = pricing.getStartingFareJson(); // JSONArray startingFareJsonArray = JSONArray.parseArray(startingFareJson); // // 基础信息规则 // String basicPricing = pricing.getBasicPricingJson(); // JSONObject basicPricingJson = JSONObject.parseObject(basicPricing); // // // 计算过后得到起步价 // String num3 = ""; // String num4 = ""; // String num5 = ""; // String num6 = ""; // String num7 = ""; // String startTime = ""; // String endTime = ""; // // 等待费设置 // String num4Wait = basicPricingJson.getString("num4"); // String num5Wait = basicPricingJson.getString("num5"); // // 远途费设置 // String numLong6 = basicPricingJson.getString("num6"); // String numLong7 = basicPricingJson.getString("num7"); // String numLong8 = basicPricingJson.getString("num8"); // String numLong9 = basicPricingJson.getString("num9"); // String numLong10 = basicPricingJson.getString("num10"); // String numLong11 = basicPricingJson.getString("num11"); // String numLong12 = basicPricingJson.getString("num12"); // String numLong13 = basicPricingJson.getString("num13"); // String numLong14 = basicPricingJson.getString("num14"); // String numLong15 = basicPricingJson.getString("num15"); // // 节假日基础价格规则 // String num29 = basicPricingJson.getString("num29"); // String num30 = basicPricingJson.getString("num30"); // String num31 = basicPricingJson.getString("num31"); // String num32 = basicPricingJson.getString("num32"); // String num33 = basicPricingJson.getString("num33"); // String num34 = basicPricingJson.getString("num34"); // // // 高峰期基础价格规则 // String num21 = basicPricingJson.getString("num21"); // String num22 = basicPricingJson.getString("num22"); // String num23 = basicPricingJson.getString("num23"); // String num24 = basicPricingJson.getString("num24"); // String num25 = basicPricingJson.getString("num25"); // String num26 = basicPricingJson.getString("num26"); // String num27 = basicPricingJson.getString("num27"); // String num28 = basicPricingJson.getString("num28"); // // 夜间行驶基础价格规则 // String num14 = basicPricingJson.getString("num14"); // String num15 = basicPricingJson.getString("num15"); // String num16 = basicPricingJson.getString("num16"); // String num17 = basicPricingJson.getString("num17"); // String num18 = basicPricingJson.getString("num18"); // String num19 = basicPricingJson.getString("num19"); // String num20 = basicPricingJson.getString("num20"); // // 起步里程 // Double startDistance = 0.00D; // // 临时超出起步里程的额外里程 // Double mileageDistance = 0.00D; // // 起步价所属时段 type 1 普通时段 2 夜间行驶时段 3 高峰时段 4 节假日时段 // Integer startType = 1; // // 里程费所属时段 type 0默认临时 1 普通时段 2 夜间行驶时段 3 高峰时段 4 节假日时段 // Integer mileageType = 0; // // 里程费所属时段临时字段 用于区分时段是否变化 type 0默认临时 1 普通时段 2 夜间行驶时段 3 高峰时段 4 节假日时段 // Integer mileageTypeTemp = 0; // // // 起步价时段开始时间 // Date startDate = DateUtils.toDate(order.getTripBegin()); // // 根据订单创建时间确定使用哪个起步价规则 // Date createTime = DateUtils.toDate(order.getCreateTime()); // // 起步价时段结束时间 // Date endDate = new Date(); // // 计算订单总行驶距离,单位米 // Double totalDistance = 0.00D; // // 起步价计算完成表示 // boolean startFlag = true; // SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm"); // if (pricing.getPricingType() == 1) { // // // 计算起步价 // for (Object o : startingFareJsonArray) { // JSONObject startingFare = (JSONObject) o; // Calendar calendarStart = Calendar.getInstance(); // calendarStart.setTime(createTime); // calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num1").split(":")[0])); // calendarStart.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num1").split(":")[1])); // // Calendar calendarEnd = Calendar.getInstance(); // calendarEnd.setTime(createTime); // calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num2").split(":")[0])); // calendarEnd.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num2").split(":")[1])); // // 找到符合条件的直接跳出循环 // if (createTime.getTime() > calendarStart.getTimeInMillis() && createTime.getTime() < calendarEnd.getTimeInMillis()) { // num3 = startingFare.getString("num3"); // num4 = startingFare.getString("num4"); // num5 = startingFare.getString("num5"); // num6 = startingFare.getString("num6"); // num7 = startingFare.getString("num7"); // startTime = startingFare.getString("num1"); // endTime = startingFare.getString("num2"); // break; // } // } // // 判断是否为夜间行驶 起步价修改 // Calendar calendarStart = Calendar.getInstance(); // calendarStart.setTime(createTime); // calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num14.split("-")[0].split(":")[0])); // calendarStart.set(Calendar.MINUTE, Integer.valueOf(num14.split("-")[0].split(":")[1])); // Calendar calendarEnd = Calendar.getInstance(); // calendarEnd.setTime(createTime); // calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num14.split("-")[1].split(":")[0])); // calendarEnd.set(Calendar.MINUTE, Integer.valueOf(num14.split("-")[1].split(":")[1])); // if (createTime.getTime() > calendarStart.getTimeInMillis() && createTime.getTime() < calendarEnd.getTimeInMillis() // ) { // num3 = num15; // num6 = num16; // num7 = num17; // startType = 2; // // } // // 判断是否为高峰期 // Calendar calendar1Start = Calendar.getInstance(); // calendar1Start.setTime(createTime); // calendar1Start.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num21.split("-")[0].split(":")[0])); // calendar1Start.set(Calendar.MINUTE, Integer.valueOf(num21.split("-")[0].split(":")[1])); // // Calendar calendar1End = Calendar.getInstance(); // calendar1End.setTime(createTime); // calendar1End.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num21.split("-")[1].split(":")[0])); // calendar1End.set(Calendar.MINUTE, Integer.valueOf(num21.split("-")[1].split(":")[1])); // // Calendar calendar2Start = Calendar.getInstance(); // calendar2Start.setTime(createTime); // calendar2Start.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num22.split("-")[0].split("-")[0].split(":")[0])); // calendar2Start.set(Calendar.MINUTE, Integer.valueOf(num22.split("-")[0].split("-")[0].split(":")[1])); // // Calendar calendar2End = Calendar.getInstance(); // calendar2End.setTime(createTime); // calendar2End.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num22.split("-")[1].split(":")[0])); // calendar2End.set(Calendar.MINUTE, Integer.valueOf(num22.split("-")[1].split(":")[1])); // // 判断是否为高峰期 起步价,里程费,时长费修改 // if ((createTime.getTime() > calendar1Start.getTimeInMillis() && createTime.getTime() < calendar1End.getTimeInMillis()) // || (createTime.getTime() > calendar2Start.getTimeInMillis() && createTime.getTime() < calendar2End.getTimeInMillis())) { // num3 = num23; // num6 = num24; // num7 = num25; // startType = 3; // } // // 判断当前是否属于节假日 // boolean holiday = holidayUtil.isHoliday(DateUtils.toLocalDate(createTime)); // if (holiday) { // // 判断是否为节假日 起步价修改 // num3 = num29; // num6 = num30; // num7 = num31; // startType = 4; // } // // 查询起步价结束时间段 // for (OrderTrajectory trajectory : trajectories) { // Long locatetime = trajectory.getLocatetime(); // endDate = new Date(locatetime); // LocalDateTime end = DateUtils.dateToLocalDateTime(endDate); // if (end.isAfter(tripBegin)) { // // 行程开始 开始计算里程数 // if (startDistance >= Double.parseDouble(num4)) { // // 行驶里程大于基础配置里程 那么起步价时段计算完成 // break; // } // startDistance += trajectory.getDistance(); // } // } // // 起步价价格明细封装 // FareBreakdownDetailVo startDetail = new FareBreakdownDetailVo(); // startDetail.setType(startType); // startDetail.setTime(timeFormat.format(startDate) + "-" + timeFormat.format(endDate)); // startDetail.setMileage(new BigDecimal(startDistance / 1000).setScale(2, RoundingMode.HALF_UP)); // // // 计算startDate和endDate相差多少分钟 // // 将 Date 转换为 LocalDateTime // LocalDateTime startDateTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); // LocalDateTime endDateTime = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); // // // 计算时间差(单位:分钟) // long minutesDifference = Duration.between(startDateTime, endDateTime).toMinutes(); // startDetail.setDuration(minutesDifference); // startDetail.setMoney(new BigDecimal(num3)); // start.add(startDetail); // // // // 计算起步价格、里程、时段、行驶时间 //// calculateStartingFare(trajectories, tripBegin, startFlag, startDistance, startingFareJsonArray, num3, num4, num5, endDate, order, num14, num15, num16, num17, startType, num21, num22, num23, num24, num25, num29, num30, num31, timeFormat, startDate, start); // // for (OrderTrajectory trajectory : trajectories) { //// FareBreakdownDetailVo mileageDetail = new FareBreakdownDetailVo(); //// mileageDetail.setType(); //// mileageDetail.setTime(); //// mileageDetail.setMileage(); //// mileageDetail.setDuration(); //// mileageDetail.setMoney(); // // Long locatetime = trajectory.getLocatetime(); // Date mileageDate = new Date(locatetime); // LocalDateTime begin = DateUtils.dateToLocalDateTime(mileageDate); // if (begin.isAfter(tripBegin)) { // totalDistance += trajectory.getDistance(); // if (totalDistance >= startDistance) { // // 开始累加起步里程 // mileageDistance += trajectory.getDistance(); // // 判断当前里程费属于什么时段 //// mileageTypeTemp // MileageDto param = new MileageDto(); // param.setMileage(num6); // param.setTime(num7); // param.setMileageTypeTemp(mileageTypeTemp); // MileageDto mileageDto = mileageType(param,startingFareJsonArray, mileageDate, begin, num14, num16, num17, num21, num22, num24, num25, num30, num31); // if (mileageType==0){ // // 首次 // mileageType = mileageDto.getMileageTypeTemp(); // mileageTypeTemp= mileageDto.getMileageTypeTemp(); // } else if (mileageType!=mileageTypeTemp){ // // 新时段 // FareBreakdownDetailVo fareBreakdownDetailVo = new FareBreakdownDetailVo(); // fareBreakdownDetailVo.setType(mileageType); // fareBreakdownDetailVo.setTime(timeFormat.format(endDate)+"-"+timeFormat.format(mileageDate)); // double md = mileageDistance / 1000; // fareBreakdownDetailVo.setMileage(new BigDecimal(md).setScale(2, RoundingMode.HALF_UP)); // // 计算startDate和endDate相差多少分钟 // // 将 Date 转换为 LocalDateTime // LocalDateTime startMileageTime = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); // LocalDateTime endMileageTime = mileageDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); // // // 计算时间差(单位:分钟) // long minutesDifferenceMileage = Duration.between(startMileageTime, endMileageTime).toMinutes(); // startDetail.setDuration(minutesDifference); // fareBreakdownDetailVo.setDuration(minutesDifferenceMileage); // // 如果md小数位是0 那么舍弃小数,如果小数位不为0 那么进1 // fareBreakdownDetailVo.setMileage(new BigDecimal(md).setScale(2, RoundingMode.HALF_UP)); // Integer temp = (int)md; // if (md> temp){ // temp=temp+1; // } // // 超出的里程 // fareBreakdownDetailVo.setMoney(new BigDecimal(temp*6)); // mileage.add(fareBreakdownDetailVo); // // 修改时段标识 // mileageType = mileageTypeTemp; // // 修改新时段开始时间 // endDate = mileageDate; // }else{ // // 时段未变化 // } // } // } // } // // 开始计算里程费用 // for (OrderTrajectory trajectory : trajectories) { // Long locatetime = trajectory.getLocatetime(); // Date mileageDate = new Date(locatetime); // LocalDateTime begin = DateUtils.dateToLocalDateTime(mileageDate); // // 行驶里程大于起步里程配置 开始计算里程和里程费 // if (begin.isAfter(tripBegin)) { // totalDistance += trajectory.getDistance(); // double v = totalDistance / 1000.0; // if (v >= Double.parseDouble(num5)) { // // 增加超出起步里程的里程数 // mileageDistance += trajectory.getDistance(); // // } // if (mileageType == 0) { // // 第一次计算里程费 // // } // } // } // } else { // // } // //// XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationPrice( //// order.getAppUserId().toString(),JSON.parseObject(pricing.getBasicPricingJson()), //// JSON.parseArray(pricing.getStartingFareJson()), //// pricing.getDynamicPricingJson(), //// pricing.getIsDynamicPrice(), //// totalDistance, //// seconds, //// order.getCityId() //// ); for (FareBreakdownDetailVo fareBreakdownDetailVo : start) { XpOrderDetail xpOrderDetail = new XpOrderDetail(); BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setDetailType(1); xpOrderDetail.setCreateTime(LocalDateTime.now()); xpOrderDetails.add(xpOrderDetail); } BigDecimal mileageMoney = BigDecimal.ZERO; for (FareBreakdownDetailVo fareBreakdownDetailVo : mileage) { XpOrderDetail xpOrderDetail = new XpOrderDetail(); BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setDetailType(2); xpOrderDetail.setCreateTime(LocalDateTime.now()); mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); xpOrderDetails.add(xpOrderDetail); } order.setMileageMoney(mileageMoney); for (XpOrderDetail xpOrderDetail : xpOrderDetails) { xpOrderDetailMapper.insert(xpOrderDetail); } for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) { order.setDurationType(fareBreakdownDetailVo.getType()); order.setDurationMoney(fareBreakdownDetailVo.getMoney()); order.setDuration(Double.parseDouble(fareBreakdownDetailVo.getDuration()+"")); } for (FareBreakdownDetailVo fareBreakdownDetailVo : longDistance) { order.setLongDistanceType(fareBreakdownDetailVo.getType()); order.setLongDistance(fareBreakdownDetailVo.getMileage().doubleValue()); order.setLongDistancemoney(fareBreakdownDetailVo.getMoney()); } baseMapper.updateById(order); } @@ -1743,8 +1451,11 @@ orderDetailVo.setFeedbackPictures(evaluate.getFeedbackPictures()); orderDetailVo.setFeedbackContent(evaluate.getFeedbackContent()); orderDetailVo.setOrderRating(evaluate.getOrderRating()); XpFeedbackType feedbackType = xpSystemSettingClient.getFeedbackTypeById(evaluate.getFeedbackTypeId()).getData(); orderDetailVo.setFeedbackTypeName(feedbackType.getFeedbackType()); if(evaluate.getFeedbackTypeId()!=null){ XpFeedbackType feedbackType = xpSystemSettingClient.getFeedbackTypeById(evaluate.getFeedbackTypeId()).getData(); orderDetailVo.setFeedbackTypeName(feedbackType.getFeedbackType()); } } List<OrderTrajectory> trajectories = mongoTemplate.find( new Query(Criteria.where("orderId").is(orderId)) @@ -1776,35 +1487,35 @@ @Transactional // @ShardingTransactionType(TransactionType.BASE) public void popOrder(PopOrderDto dto) { XpOrder order = this.getById(dto.getOrderId()); order.setAcceptanceTime(LocalDateTime.now()); AddTaxiPassengerVo addTaxiPassengerVo = new AddTaxiPassengerVo(); R<XpVehicle> byVehicleVin = xpVehicleClient.findByVehicleVin(dto.getXpVehicleVin()); if (byVehicleVin.getCode() == 200) { order.setVehicleId(byVehicleVin.getData().getId()); addTaxiPassengerVo.setVin(byVehicleVin.getData().getVehicleVin()); } order.setStatus(2); // Redis弹出这个队列元素 // value 订单Id_经纬度_状态_用户id_订单编号_距离_时间 String popFirstElement = redisService.popFirstElement(order.getQueueName()); XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity(); String[] split = popFirstElement.split("_"); xpGeoQueryEntity.setOrderId(split[0]); String[] split1 = split[1].split(","); xpGeoQueryEntity.setLocation(new GeoJsonPoint(Double.parseDouble(split1[0]), Double.parseDouble(split1[1]))); xpGeoQueryEntity.setTimestamp(new Date()); // 计算2个时间的秒数 LocalDateTime createTime = order.getCreateTime(); LocalDateTime acceptanceTime = order.getAcceptanceTime(); xpGeoQueryEntity.setSeconds((int) Duration.between(createTime, acceptanceTime).getSeconds()); String currentTimeSlot = DateUtils.getCurrentTimeSlot(); xpGeoQueryEntity.setTime(currentTimeSlot); // 存mongo数据 xpPricingClient.saveXpGeoQueryEntity(xpGeoQueryEntity); this.updateById(order); addTaxiPassengerVo.setUid(order.getAppUserId().toString()); addTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO appid addTaxiPassengerVo.setAppId(""); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.addTaxiPassenger(addTaxiPassengerVo); if(baseVehicleUserDto.getCode()==200){ // Redis弹出这个队列元素 // value 订单Id_经纬度_状态_用户id_订单编号_距离_时间 String popFirstElement = redisService.popFirstElement(order.getQueueName()); XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity(); String[] split = popFirstElement.split("_"); xpGeoQueryEntity.setOrderId(split[0]); // 存mongo数据 xpPricingClient.updateXpGeoQueryEntity(split[0]); this.updateById(order); } } xp-robotaxi-vehicleConvoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -404,6 +404,20 @@ XpVehicle xpVehicle = xpVehicleService.getOne(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getVehicleVin, vehicleVin)); return R.ok(xpVehicle); } /** * 根据XPUID查询车辆信息 * @param xpuid * @return */ @GetMapping("/inner/vehicle/findByVehicleXpuId") public R<XpVehicle> findByVehicleXpuId(@RequestParam("xpuid") String xpuid){ XpVehicle xpVehicle = xpVehicleService.getOne(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getXpuId, xpuid)); return R.ok(xpVehicle); } /** * 查询可改派的车辆列表 * xp-robotaxi-vehicleConvoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto; import com.xiaopeng.api.feignClient.automaticPilot.XpuVinClient; import com.xiaopeng.api.feignClient.operation.XpElectronicClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.model.operation.XpElectronicFence; @@ -37,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; @@ -65,6 +67,9 @@ @Autowired private IXpVehicleAnnualRecordService xpVehicleAnnualRecordService; @Resource private XpuVinClient xpuVinClient; @Override public List<XpVehicle> listByIds(List<Long> ids) { @@ -191,6 +196,10 @@ xpVehicle.setStatus(1); // 设置入库时间 xpVehicle.setWarehousingTime(LocalDateTime.now()); //绑定XPUID String vin = xpVehicle.getVehicleVin(); String xpuid = xpuVinClient.getXpuIdByVin(vin).getData(); xpVehicle.setXpuId(xpuid); this.save(xpVehicle); } @@ -200,6 +209,10 @@ // DTO转实体 XpVehicle xpVehicle = new XpVehicle(); BeanUtil.copyProperties(dto, xpVehicle); //绑定XPUID String vin = xpVehicle.getVehicleVin(); String xpuid = xpuVinClient.getXpuIdByVin(vin).getData(); xpVehicle.setXpuId(xpuid); this.updateById(xpVehicle); }