xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/automaticPilot/MqttPublishDto.java
New file @@ -0,0 +1,19 @@ package com.xiaopeng.api.dto.automaticPilot; import lombok.Data; @Data public class MqttPublishDto { /** * 状态码 */ private Integer code; /** * 状态信息 */ private String msg; /** * 数据 */ private Object data; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/ElectronicFenceAddDto.java
@@ -10,6 +10,7 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -24,7 +25,8 @@ private String cityCode; @ApiModelProperty(value = "围栏编号唯一 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001)") private String electronicNumber; @ApiModelProperty(value = "面积") private BigDecimal area; @ApiModelProperty(value = "围栏状态 0=草稿 1=待启用 2=启用中 3=已停用 草稿传0 发布传1") @NotNull(message = "围栏状态不能为空") private Integer status; @@ -35,7 +37,6 @@ private Integer effectType; @ApiModelProperty(value = "生效时间") @NotNull(message = "生效时间不能为空") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime effectTime; @@ -44,7 +45,6 @@ private Integer failureType; @ApiModelProperty(value = "失效时间") @NotNull(message = "失效时间不能为空") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime failureTime; xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/ElectronicFenceUpdateDto.java
@@ -38,7 +38,6 @@ private Integer effectType; @ApiModelProperty(value = "生效时间") @NotNull(message = "生效时间不能为空") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime effectTime; @@ -47,7 +46,6 @@ private Integer failureType; @ApiModelProperty(value = "失效时间") @NotNull(message = "失效时间不能为空") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime failureTime; xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automaticPilot/XPUClientFallbackFactory.java
New file @@ -0,0 +1,22 @@ package com.xiaopeng.api.factory.automaticPilot; import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto; import com.xiaopeng.api.feignClient.automaticPilot.XPUClient; import com.xiaopeng.api.vo.automaticPilot.MqttPublishVo; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; @Slf4j public class XPUClientFallbackFactory implements FallbackFactory<XPUClient> { @Override public XPUClient create(Throwable cause) { return new XPUClient(){ @Override public MqttPublishDto publish(MqttPublishVo vo) { log.error("推送XPU-MQTT消息失败: {}", cause.getMessage()); return null; } }; } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpElectronicClientFallbackFactory.java
@@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestBody; import java.util.Collection; import java.util.List; @@ -54,7 +55,7 @@ } @Override public R copy(Integer id) { public R<Long> copy(@RequestBody Integer id) { log.error("复制电子围栏失败:{}", cause.getMessage()); return R.fail("复制电子围栏失败"); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpSystemSettingClientFallbackFactory.java
@@ -3,6 +3,7 @@ import com.xiaopeng.api.feignClient.operation.SysLogClient; import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient; import com.xiaopeng.api.model.operation.SysOperLog; import com.xiaopeng.api.model.operation.XpFeedbackType; import com.xiaopeng.common.core.domain.R; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; @@ -25,6 +26,12 @@ log.error("获取自动结束行程时间失败:{}", cause.getMessage()); return R.fail("获取自动结束行程时间失败,"+cause.getMessage()); } @Override public R<XpFeedbackType> getFeedbackTypeById(Long id) { log.error("获取反馈类型名称失败:{}", cause.getMessage()); return R.fail(null); } }; } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/automaticPilot/XPUClient.java
New file @@ -0,0 +1,25 @@ package com.xiaopeng.api.feignClient.automaticPilot; import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto; import com.xiaopeng.api.factory.automaticPilot.XPUClientFallbackFactory; import com.xiaopeng.api.vo.automaticPilot.MqttPublishVo; import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @FeignClient(contextId = "XPUClient", value = ServiceNameConstantsEnum.XP_MQTT_ROUTER_THIRDPARTY_BOOT, fallbackFactory = XPUClientFallbackFactory.class) public interface XPUClient { /** * 推送MQTT消息 * @param vo */ @PostMapping("/logan/mqtt/publish") MqttPublishDto publish(@RequestBody MqttPublishVo vo); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpElectronicClient.java
@@ -12,10 +12,7 @@ import com.xiaopeng.common.core.web.page.PageInfo; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.*; import java.util.Collection; import java.util.List; @@ -40,8 +37,8 @@ /** * 电子围栏详情 */ @GetMapping("/api/v1/electronicFence/queryById") R<ElectronicFenceDetailVo> queryById(Long id); @PostMapping("/api/v1/electronicFence/queryById") R<ElectronicFenceDetailVo> queryById(@RequestParam("id")Long id); /** * 编辑电子围栏 */ @@ -50,8 +47,8 @@ /** * 复制电子围栏 */ @PutMapping("/api/v1/electronicFence/copy") R copy(Integer id); @PostMapping("/api/v1/electronicFence/copy") R<Long> copy(@RequestParam("id") Integer id); /** * 根据ID列表批量查询电子围栏 xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpSystemSettingClient.java
@@ -1,11 +1,13 @@ package com.xiaopeng.api.feignClient.operation; import com.xiaopeng.api.factory.operation.XpSystemSettingClientFallbackFactory; import com.xiaopeng.api.model.operation.XpFeedbackType; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.Mapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @FeignClient(contextId = "XpSystemSettingClient", value = ServiceNameConstantsEnum.XP_OPERATION_SERVICE, fallbackFactory = XpSystemSettingClientFallbackFactory.class) @@ -22,4 +24,10 @@ @GetMapping("/api/v1/mini-program/support/getOrderFinishTime") R<Integer> getOrderFinishTime(); /** * 获取反馈类型 * @return */ @GetMapping("/base/v1/mini-program/getFeedbackTypeById/{id}") R<XpFeedbackType> getFeedbackTypeById(@PathVariable("id")Long id); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpElectronicFenceArea.java
@@ -3,6 +3,8 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import java.math.BigDecimal; import java.time.LocalDateTime; import java.io.Serializable; @@ -37,7 +39,8 @@ @ApiModelProperty(value = "围栏id") private Long electronicId; @ApiModelProperty(value = "面积") private BigDecimal area; @ApiModelProperty(value = "区域名称") private String areaName; xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrderEvaluate.java
@@ -49,9 +49,9 @@ private LocalDateTime evaluateTime; @ApiModelProperty(value = "问题类型id") private Integer feedbackTypeId; private Long feedbackTypeId; @ApiModelProperty(value = "反馈内容") private Integer feedbackContent; private String feedbackContent; @ApiModelProperty(value = "图片 json格式") private Integer feedbackPictures; private String feedbackPictures; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/automaticPilot/MqttPublishVo.java
New file @@ -0,0 +1,15 @@ package com.xiaopeng.api.vo.automaticPilot; import lombok.Data; @Data public class MqttPublishVo { /** * 消息内容 */ private String payload; /** * Mqtt topic */ private String topic; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/automaticPilot/proto/up/ResponseMessage.java
New file @@ -0,0 +1,22 @@ package com.xiaopeng.api.vo.automaticPilot.proto.up; import lombok.Data; /** * 应答消息 */ @Data public class ResponseMessage { /** * 对应请求seq */ private Long request_seq; /** * 响应码 */ private StatusCode code; /** * 时间戳(毫秒) */ private Long timestamp; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/automaticPilot/proto/up/StatusCode.java
New file @@ -0,0 +1,29 @@ package com.xiaopeng.api.vo.automaticPilot.proto.up; /** * HTTP状态码枚举 */ public enum StatusCode { HTTP_STATUS_CODE_UNSPECIFIED(0), OK(200), // 成功 BAD_REQUEST(400), // 请求参数错误 FORBIDDEN(403), NOT_FOUND(404), REQUEST_TIMEOUT(408), // 请求超时 INTERNAL_SERVER_ERROR(500); // 失败 private int value; StatusCode(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -21,4 +21,5 @@ 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.vehicleConvoy.VehicleControlClientFallbackFactory com.xiaopeng.api.factory.automaticPilot.XPUClientFallbackFactory xp-robotaxi-automaticPilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -153,7 +153,15 @@ } //消息应答 if(MessageType.MESSAGE_TYPE_RESPONSE == type){ com.xiaopeng.api.vo.automaticPilot.proto.up.ResponseMessage resposne = msgContent.getContent_detail().getObject("resposne", com.xiaopeng.api.vo.automaticPilot.proto.up.ResponseMessage.class); com.xiaopeng.api.vo.automaticPilot.proto.up.StatusCode code = resposne.getCode(); Long requestSeq = resposne.getRequest_seq(); if(code == com.xiaopeng.api.vo.automaticPilot.proto.up.StatusCode.OK){ } } } /** @@ -239,9 +247,6 @@ * @param msgContent */ public void systemStatusXpu(MsgContent msgContent) { //先响应消息 Long sequence = msgContent.getHeader().getSequence(); responseMessage(sequence); //开始处理消息对应的业务逻辑 SystemRuntimeStatus systemRuntimeStatus = msgContent.getContent_detail().getObject("systemRuntimeStatus", SystemRuntimeStatus.class); //获取实时位姿 @@ -254,6 +259,10 @@ //获取车辆静态信息 VehicleStaticInfo staticInfo = systemRuntimeStatus.getVehicle_status().getStatic_info(); String vin = staticInfo.getVin(); //先响应消息 Long sequence = msgContent.getHeader().getSequence(); responseMessage(sequence, vin); //保存车辆实时位置到redis redisTemplate.opsForGeo().add("vehiclePosition:" + vin, new GeoJsonPoint(longitude, latitude), vin); //保存车辆实时信息到mongodb @@ -306,9 +315,6 @@ * @param msgContent */ public void xpuNavigationRequest(MsgContent msgContent) { //先响应消息 Long sequence = msgContent.getHeader().getSequence(); responseMessage(sequence); //开始处理消息对应的业务逻辑 NavigationRequest naviRequest = msgContent.getContent_detail().getObject("naviRequest", NavigationRequest.class); String orderId = naviRequest.getOrder_id(); @@ -322,15 +328,15 @@ break; case ROUTE_TO_PICKUP: log.info("驶往上车点的行程"); buildNaviRequest(orderId, taskId, orderPhase); buildNaviRequest(orderId, taskId, orderPhase, msgContent.getHeader().getSequence()); break; case ROUTE_TO_DESTINATION: log.info("驶往下车点的行程"); buildNaviRequest(orderId, taskId, orderPhase); buildNaviRequest(orderId, taskId, orderPhase, msgContent.getHeader().getSequence()); break; case ROUTE_TO_CRUISE: log.info("巡游阶段路线"); buildNaviRequest(orderId, taskId, orderPhase); buildNaviRequest(orderId, taskId, orderPhase, msgContent.getHeader().getSequence()); break; } } @@ -344,7 +350,6 @@ public void navigationDeviationEvent(MsgContent msgContent) { //先响应消息 Long sequence = msgContent.getHeader().getSequence(); responseMessage(sequence); //开始处理消息对应的业务逻辑 NavigationDeviationEvent deviationEvent = msgContent.getContent_detail().getObject("deviationEvent", NavigationDeviationEvent.class); //偏航事件类型 1:请求导航,2:取消导航 @@ -366,6 +371,8 @@ origin.setLatitude(latitude); destination.setLongitude(116.40528); destination.setLatitude(39.90498); //响应消息 responseMessage(sequence, ""); } else { //正常单 R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId)); @@ -373,6 +380,9 @@ throw new RuntimeException("订单不存在"); } XpOrder xpOrder = xpOrderR.getData(); XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); //响应消息 responseMessage(sequence, xpVehicle.getVehicleVin()); //驶往上车点的行程 if (Arrays.asList(3).contains(xpOrder.getStatus())) { //查询司机当前位置到起点的线路 @@ -399,7 +409,7 @@ } RouteVo routeVo = routeVoR.getData(); //构建导航下发请求对象 cloudOrderOperation(orderType, orderId, taskId, routeVo); cloudOrderOperation(orderType, orderId, taskId, routeVo, xpVehicle.getVehicleVin()); } } } @@ -412,7 +422,7 @@ * @param taskId * @param orderPhase */ public void buildNaviRequest(String orderId, String taskId, OrderPhase orderPhase) { public void buildNaviRequest(String orderId, String taskId, OrderPhase orderPhase, Long sequence) { //订单类型 1:乘客订单,2=巡游订单 Integer orderType = 1; LonLatDto destination = new LonLatDto(); @@ -426,6 +436,9 @@ origin.setLatitude(39.90498); destination.setLongitude(116.40528); destination.setLatitude(39.90498); //先响应消息 responseMessage(sequence, ""); } } else { //正常单 @@ -437,6 +450,9 @@ //驶往上车点的行程 if (orderPhase.equals(OrderPhase.ROUTE_TO_PICKUP)) { XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); //先响应消息 responseMessage(sequence, xpVehicle.getVehicleVin()); //查询车辆位置 VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); if (Objects.isNull(vehiclePosition)) { throw new RuntimeException("车辆位置信息不存在"); @@ -463,9 +479,10 @@ if (200 != routeVoR.getCode()) { throw new RuntimeException("获取订单线路和运费失败"); } XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); RouteVo routeVo = routeVoR.getData(); //构建导航下发请求对象 cloudOrderOperation(orderType, orderId, taskId, routeVo); cloudOrderOperation(orderType, orderId, taskId, routeVo, xpVehicle.getVehicleVin()); } } @@ -475,7 +492,7 @@ * * @param routeVo */ public void cloudOrderOperation(Integer orderType, String orderId, String taskId, RouteVo routeVo) { public void cloudOrderOperation(Integer orderType, String orderId, String taskId, RouteVo routeVo, String vin) { //构建消息体 OrderOperation orderOperation = new OrderOperation(); orderOperation.setOrder_id(orderId); @@ -511,19 +528,19 @@ } orderOperation.setWaypoints(waypoints); //开发发送请求到XPU xpuUtil.cloudOrderOperation(orderOperation); xpuUtil.cloudOrderOperation(orderOperation, vin); } /** * 构建响应消息 */ public void responseMessage(Long request_seq) { public void responseMessage(Long request_seq, String vin) { ResponseMessage responseMessage = new ResponseMessage(); responseMessage.setRequest_seq(request_seq); responseMessage.setCode(StatusCode.OK); responseMessage.setTimestamp(System.currentTimeMillis()); xpuUtil.responseMessage(responseMessage); xpuUtil.responseMessage(responseMessage, vin); } @@ -534,7 +551,6 @@ public void orderStateUpdateEvent(MsgContent msgContent) { //先响应消息 Long sequence = msgContent.getHeader().getSequence(); responseMessage(sequence); //开始处理消息对应的业务逻辑 OrderStatusInfoEvent orderStatusInfoEvent = msgContent.getContent_detail().getObject("orderStatusInfoEvent", OrderStatusInfoEvent.class); //只处理请求消息 @@ -550,7 +566,7 @@ break; case ORDER_RECEIVED: //收到订单 buildPushOrderStatus(orderId, OrderStatusEnum.READY_DEPART); buildPushOrderStatus(orderId, OrderStatusEnum.READY_DEPART, sequence); break; case ORDER_STARTED: //开始执行订单 @@ -558,7 +574,7 @@ break; case ORDER_EN_ROUTE_TO_PICKUP: //前往上车点 buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP); buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP, sequence); break; case ORDER_ARRIVED_AT_PICKUP: //到达上车点 @@ -566,15 +582,15 @@ break; case ORDER_WAITING_FOR_PICKUP: //等待乘客上车 buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP_GUESTS); buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP_GUESTS, sequence); break; case ORDER_PASSENGER_ONBOARD: //乘客已上车 buildPushOrderStatus(orderId, OrderStatusEnum.PASSENGER_BOARDED); buildPushOrderStatus(orderId, OrderStatusEnum.PASSENGER_BOARDED, sequence); break; case ORDER_EN_ROUTE_TO_DESTINATION: //前往目的地 buildPushOrderStatus(orderId, OrderStatusEnum.IN_SERVICE); buildPushOrderStatus(orderId, OrderStatusEnum.IN_SERVICE, sequence); break; case ORDER_ARRIVED_AT_DESTINATION: //到达目的地 @@ -582,11 +598,11 @@ break; case ORDER_WAITING_FOR_DROPOFF: //等待乘客下车 buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS); buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence); break; case ORDER_DROPOFF_COMPLETED: //下车完成 buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION); buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence); break; case ORDER_COMPLETED: //已完成 @@ -594,11 +610,11 @@ break; case ORDER_CANCELLED: //已取消 buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED); buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED, sequence); break; case ORDER_ARRIVED_AT_CRUISE_DESTINATION: //到达巡游终点 buildPushOrderStatus(orderId, null); buildPushOrderStatus(orderId, null, sequence); break; case ORDER_PAUSED: //订单暂停 @@ -616,11 +632,19 @@ * @param orderId * @param status */ public void buildPushOrderStatus(String orderId, OrderStatusEnum status){ public void buildPushOrderStatus(String orderId, OrderStatusEnum status, Long sequence){ if(orderId.contains("XU")){ //巡游单 //响应消息 responseMessage(sequence, ""); }else{ //普通单 R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId)); XpOrder xpOrder = xpOrderR.getData(); XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); //响应消息 responseMessage(sequence, xpVehicle.getVehicleVin()); //构建推送消息 Map<String, Object> params = new HashMap<>(); Map<String, Object> content = new HashMap<>(); @@ -630,8 +654,6 @@ params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content)); params.put("timestamp", System.currentTimeMillis() + ""); String message = JSONObject.toJSONString(params); R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId)); XpOrder xpOrder = xpOrderR.getData(); Long appUserId = xpOrder.getAppUserId(); SendMessageDTO dto = new SendMessageDTO(); dto.setAppUserId(appUserId + ""); xp-robotaxi-automaticPilot-boot/src/main/java/com/xiaopeng/automaticPilot/util/XPUUtil.java
@@ -7,13 +7,17 @@ import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson2.JSON; import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto; 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.cloudOrderOperation.OrderOperation; 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.utils.uuid.UUID; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * 自动驾驶接口对接文档 @@ -22,11 +26,8 @@ @Component public class XPUUtil { /** * 接口地址 */ @Value("${xpu.url}") private String xpuUrl; @Resource private XPUClient xpuClient; /** @@ -35,7 +36,7 @@ * @param task * @return */ public ResponseMessage cloudCreateOrder(RTTask task) { public MqttPublishDto cloudCreateOrder(RTTask task, String vin) { MsgContent msgContent = new MsgContent(); // 消息头 RtMsgHeader header = new RtMsgHeader(); @@ -50,22 +51,12 @@ jsonObject.put("task", task); msgContent.setContent_detail(jsonObject); log.info("云端-->XPU 创建订单:{}", msgContent); HttpRequest post = HttpUtil.createPost(""); post.body(JSON.toJSONString(msgContent)); HttpResponse execute = post.execute(); int status = execute.getStatus(); if (200 != status) { throw new RuntimeException("XPU 接口异常:" + execute.getStatus()); } MsgContent resMsgContent = JSON.parseObject(execute.body(), MsgContent.class); RtMsgHeader resHeader = resMsgContent.getHeader(); int value = resHeader.getType().getValue(); //只处理应答消息 if (value == MessageType.MESSAGE_TYPE_RESPONSE.getValue()) { JSONObject contentDetail = resMsgContent.getContent_detail(); return contentDetail.getObject("response", ResponseMessage.class); } return null; //组装请求消息体 MqttPublishVo vo = new MqttPublishVo(); vo.setTopic("topic-prod-xpu-robotaxi-high/" + vin); vo.setPayload(JSON.toJSONString(msgContent)); return xpuClient.publish(vo); } @@ -76,7 +67,7 @@ * @param operation * @return */ public ResponseMessage cloudOrderOperation(OrderOperation operation) { public MqttPublishDto cloudOrderOperation(OrderOperation operation, String vin) { MsgContent msgContent = new MsgContent(); // 消息头 RtMsgHeader header = new RtMsgHeader(); @@ -92,22 +83,11 @@ jsonObject.put("operation", operation); msgContent.setContent_detail(jsonObject); log.info("云端-->XPU 操作订单:{}", msgContent); HttpRequest post = HttpUtil.createPost(""); post.body(JSON.toJSONString(msgContent)); HttpResponse execute = post.execute(); int status = execute.getStatus(); if (200 != status) { throw new RuntimeException("XPU 接口异常:" + execute.getStatus()); } MsgContent resMsgContent = JSON.parseObject(execute.body(), MsgContent.class); RtMsgHeader resHeader = resMsgContent.getHeader(); int value = resHeader.getType().getValue(); //只处理应答消息 if (value == MessageType.MESSAGE_TYPE_RESPONSE.getValue()) { JSONObject contentDetail = resMsgContent.getContent_detail(); return contentDetail.getObject("response", ResponseMessage.class); } return null; //组装请求消息体 MqttPublishVo vo = new MqttPublishVo(); vo.setTopic("topic-prod-xpu-robotaxi-high/" + vin); vo.setPayload(JSON.toJSONString(msgContent)); return xpuClient.publish(vo); } @@ -119,7 +99,7 @@ * @param responseMessage * @return */ public ResponseMessage responseMessage(ResponseMessage responseMessage) { public MqttPublishDto responseMessage(ResponseMessage responseMessage, String vin) { MsgContent msgContent = new MsgContent(); // 消息头 RtMsgHeader header = new RtMsgHeader(); @@ -135,14 +115,11 @@ jsonObject.put("resposne", responseMessage); msgContent.setContent_detail(jsonObject); log.info("云端-->XPU 响应消息:{}", msgContent); HttpRequest post = HttpUtil.createPost(""); post.body(JSON.toJSONString(msgContent)); HttpResponse execute = post.execute(); int status = execute.getStatus(); if (200 != status) { throw new RuntimeException("XPU 接口异常:" + execute.getStatus()); } return null; //组装请求消息体 MqttPublishVo vo = new MqttPublishVo(); vo.setTopic("topic-prod-xpu-robotaxi-high/" + vin); vo.setPayload(JSON.toJSONString(msgContent)); return xpuClient.publish(vo); } } xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/dto/ServiceNameConstantsEnum.java
@@ -61,5 +61,9 @@ * 小鹏用车控服务 */ String XP_IM_OPEN_BOOT_SERVICE = "xp-im-open-boot"; /** * 小鹏用车控服务 */ String XP_MQTT_ROUTER_THIRDPARTY_BOOT = "xp-mqtt-router-thirdparty-boot"; } xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
@@ -14,6 +14,7 @@ import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.bean.BeanUtils; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.service.TokenService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -39,6 +40,8 @@ public class XpElectronicFenceManagementController { @Resource private TokenService tokenService; @Resource private XpElectronicClient xpElectronicClient; @@ -56,6 +59,7 @@ @ApiOperation(value = "新增电子围栏") @Transactional public R add(@Validated @RequestBody ElectronicFenceAddDto dto) { return xpElectronicClient.add(dto); } @@ -75,10 +79,10 @@ /** * 电子围栏详情 */ @GetMapping("/queryById") @PostMapping("/queryById") @ResponseBody @ApiOperation(value = "电子围栏详情") public R<ElectronicFenceDetailVo> queryById(Long id) { public R<ElectronicFenceDetailVo> queryById(@RequestParam("id")Long id) { return xpElectronicClient.queryById(id); } @@ -96,11 +100,9 @@ /** * 复制电子围栏 */ @GetMapping("/copy") @ResponseBody @PostMapping("/copy") @ApiOperation(value = "复制电子围栏") @Transactional public R copy(Integer id) { public R<Long> copy(@RequestParam("id") Integer id) { return xpElectronicClient.copy(id); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/config/DataUpdateHandlerConfig.java
@@ -50,7 +50,6 @@ } this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); this.setFieldValByName("createBy", userName, metaObject); } /** xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpElectronicFenceController.java
@@ -110,9 +110,9 @@ /** * 电子围栏详情 */ @GetMapping("/queryById") @PostMapping("/queryById") @ApiOperation(value = "电子围栏详情") public R<ElectronicFenceDetailVo> queryById(Long id) { public R<ElectronicFenceDetailVo> queryById(@RequestParam("id")Long id) { ElectronicFenceDetailVo res = new ElectronicFenceDetailVo(); XpElectronicFence electronicFence = xpElectronicFenceService.getById(id); if (electronicFence == null) { @@ -141,10 +141,10 @@ /** * 复制电子围栏 */ @GetMapping("/copy") @PostMapping("/copy") @ApiOperation(value = "复制电子围栏") @Transactional public R copy(Integer id) { public R<Long> copy(@RequestParam("id") Integer id) { XpElectronicFence electronicFence = xpElectronicFenceService.getById(id); if (electronicFence.getStatus()==2){ throw new ServiceException( @@ -165,7 +165,7 @@ area.setAreaName("副本_"+area.getAreaName()); } xpElectronicFenceAreaService.saveBatch(electronicFenceAreaList); return R.ok(); return R.ok(electronicFence.getId()); } /** xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpFeedbackTypeController.java
@@ -8,6 +8,7 @@ import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; @@ -36,7 +37,14 @@ public XpFeedbackTypeController(IXpFeedbackTypeService xpFeedbackTypeService) { this.xpFeedbackTypeService = xpFeedbackTypeService; } /** * 获取反馈类型 * @return */ @GetMapping("/getFeedbackTypeById/{id}") public R<XpFeedbackType> getFeedbackTypeById(@PathVariable("id")Long id){ return R.ok(xpFeedbackTypeService.getById(id)); } @GetMapping("/feedback-type/getList") @ApiOperation(value = "获取意见反馈类型列表",tags = {"意见反馈类型列表"},response = XpFeedbackType.class) xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java
@@ -15,6 +15,7 @@ import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.DateUtils; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.utils.bean.BeanUtils; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.operation.constant.I18nKeyConstant; @@ -65,6 +66,9 @@ @Override public PageInfo<XpElectronicFence> pageList(ElectronicPageListQuery query) { PageInfo<XpElectronicFence> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); if (StringUtils.isEmpty(query.getCreateSort())&& StringUtils.isEmpty(query.getUpdateSort())){ query.setCreateSort("2"); } List<XpElectronicFence> list = this.baseMapper.pageList(pageInfo, query); if (list.isEmpty()) { return new PageInfo<>(); @@ -78,7 +82,9 @@ if (xpElectronicFenceAreas != null) { xpElectronicFence.setOperatingAreaCount(xpElectronicFenceAreas.stream().filter(xpElectronicFenceArea -> xpElectronicFenceArea.getAreaType() == 1).count()); xpElectronicFence.setProhibitedAreaCount(xpElectronicFenceAreas.stream().filter(xpElectronicFenceArea -> xpElectronicFenceArea.getAreaType() == 2).count()); }else{ xpElectronicFence.setOperatingAreaCount(0L); xpElectronicFence.setProhibitedAreaCount(0L); } } pageInfo.setRecords(list); @@ -194,6 +200,7 @@ for (XpElectronicFenceArea area : newElectronicFenceAreas) { area.setElectronicId(xpElectronicFence.getId()); area.setAreaStatus(1); area.setArea(area.getArea()); area.setCityCode(dto.getCityCode()); xpElectronicFenceAreaMapper.insert(area); @@ -333,6 +340,7 @@ for (XpElectronicFenceArea area : updatedElectronicFenceAreas) { area.setElectronicId(dto.getId()); // 设置关联的电子围栏ID area.setCityCode(dto.getCityCode()); area.setArea(area.getArea()); xpElectronicFenceAreaMapper.insert(area); } if (dto.getStatus() == 2) { xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -28,6 +28,7 @@ import com.xiaopeng.order.model.vo.XpOrderHistoryVO; import com.xiaopeng.order.model.vo.XpOrderPageVO; import com.xiaopeng.order.service.IXpOrderService; import com.xiaopeng.order.vo.OrderDetailVo; import com.xiaopeng.unifiedverification.interceptor.XpClientCheck; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -252,7 +253,6 @@ return R.ok(); } /** * 获取用户快捷胶囊 历史 时段 终点高点 */ @@ -265,6 +265,18 @@ return R.ok(xpOrderService.getUserQuickCapsule(uid)); } /** * 获取订单详情 */ @PutMapping("/api/v1/mini-program/order/orderDetail/{orderId}") @ApiOperation(value = "获取订单详情", tags = {"小程序-获取订单详情"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R<OrderDetailVo> orderDetail(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); ; return R.ok(xpOrderService.orderDetail(orderId,uid)); } /** xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/dto/XpOrderCommentDto.java
@@ -12,9 +12,9 @@ @ApiModelProperty(value = "订单评分") private Integer orderRating; @ApiModelProperty(value = "问题类型id") private Integer feedbackTypeId; private Long feedbackTypeId; @ApiModelProperty(value = "反馈内容") private Integer feedbackContent; private String feedbackContent; @ApiModelProperty(value = "图片 json格式") private Integer feedbackPictures; private String feedbackPictures; } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -21,6 +21,7 @@ import com.xiaopeng.order.model.vo.XpOrderDetailVO; import com.xiaopeng.order.model.vo.XpOrderHistoryVO; import com.xiaopeng.order.model.vo.XpOrderPageVO; import com.xiaopeng.order.vo.OrderDetailVo; import java.util.List; @@ -186,4 +187,6 @@ * @param orderTrajectory */ void saveVehicleLocation(OrderTrajectory orderTrajectory); OrderDetailVo orderDetail(Long orderId, String uid); } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -28,6 +28,7 @@ import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.account.XpAppUser; import com.xiaopeng.api.model.operation.XpFeedbackType; import com.xiaopeng.api.model.operation.XpPoint; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.order.XpOrderCancel; @@ -69,6 +70,8 @@ import com.xiaopeng.order.service.IXpOrderReassignService; import com.xiaopeng.order.service.IXpOrderService; import com.xiaopeng.order.utils.holiday.HolidayUtil; import com.xiaopeng.order.vo.OrderDetailVo; import io.swagger.annotations.ApiModelProperty; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; @@ -913,6 +916,8 @@ userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); } // 计算起步价 // // 计算实际价格 // // 根据订单所属开通城市id 查询定价 // R<XpPricing> pricingByCityId = xpPricingClient.getPricingByCityId(order.getCityId()); @@ -1588,6 +1593,49 @@ } } @Override public OrderDetailVo orderDetail(Long orderId, String uid) { OrderDetailVo orderDetailVo = new OrderDetailVo(); XpOrder order = this.getById(orderId); BeanUtils.copyProperties(order, orderDetailVo); // 查询车辆信息 XpVehicle vehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); if (vehicle!=null){ orderDetailVo.setVehicleCode(vehicle.getVehicleCode()); orderDetailVo.setPlateNumber(vehicle.getPlateNumber()); orderDetailVo.setVehicleColor(vehicle.getVehicleColor()); orderDetailVo.setVehiclePictures(vehicle.getVehiclePictures()); } // 查询评价信息 XpOrderEvaluate evaluate = xpOrderEvaluateService.lambdaQuery().eq(XpOrderEvaluate::getOrderId, orderId) .last("limit 1").one(); if (evaluate != null) { orderDetailVo.setFeedbackPictures(evaluate.getFeedbackPictures()); orderDetailVo.setFeedbackContent(evaluate.getFeedbackContent()); orderDetailVo.setOrderRating(evaluate.getOrderRating()); XpFeedbackType feedbackType = xpSystemSettingClient.getFeedbackTypeById(evaluate.getFeedbackTypeId()).getData(); orderDetailVo.setFeedbackTypeName(feedbackType.getFeedbackType()); } List<OrderTrajectory> trajectories = mongoTemplate.find( new Query(Criteria.where("orderId").is(orderId)) .with(Sort.by(Sort.Direction.ASC, "locatetime")), OrderTrajectory.class ); orderDetailVo.setTrajectories(trajectories); if (order.getTripBegin()!=null&&order.getTripEnd()!=null){ // 计算两个时间相差多少分钟 long minutesDifference = Duration.between(order.getTripBegin(), order.getTripEnd()).toMinutes(); orderDetailVo.setOrderTime(minutesDifference); }else{ orderDetailVo.setOrderTime(0l); } if (order.getStartMileage()!=null){ orderDetailVo.setTotalMileage(order.getStartMileage()+(order.getMileageKilometers()!=null?order.getMileageKilometers():0D)); } return orderDetailVo; } /** * 获取当前用户正在执行的订单 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/vo/OrderDetailVo.java
New file @@ -0,0 +1,37 @@ package com.xiaopeng.order.vo; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @Data @ApiModel(value = "订单详情") public class OrderDetailVo extends XpOrder { @ApiModelProperty(value = "车辆编码") private String vehicleCode; @ApiModelProperty(value = "车牌号") private String plateNumber; @ApiModelProperty(value = "车辆颜色") private String vehicleColor; @ApiModelProperty(value = "车辆图片") private String vehiclePictures; @ApiModelProperty(value = "反馈图片") private String feedbackPictures; @ApiModelProperty(value = "反馈内容") private String feedbackContent; @ApiModelProperty(value = "问题类型") private String feedbackTypeName; @ApiModelProperty(value = "评分") private Integer orderRating; @ApiModelProperty(value = "时长分钟") private Long orderTime; @ApiModelProperty(value = "总里程") private Double totalMileage; @ApiModelProperty(value = "轨迹") private List<OrderTrajectory> trajectories; } xp-robotaxi-vehicleConvoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/SnowFlake.java
New file @@ -0,0 +1,111 @@ package com.xiaopeng.vehicleConvoy.util; /** * see @https://raw.githubusercontent.com/beyondfengyu/SnowFlake/master/SnowFlake.java * Created by Lox on 2017/8/21. */ public class SnowFlake { /** * 起始的时间戳 */ private static long START_STMP = 1503305692631L; /** * 每一部分占用的位数 */ private final static long SEQUENCE_BIT = 12; //序列号占用的位数 private final static long MACHINE_BIT = 5; //机器标识占用的位数 private final static long DATACENTER_BIT = 5;//数据中心占用的位数 /** * 每一部分的最大值 */ public final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); public final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); /** * 每一部分向左的位移 */ private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; //数据中心 private long machineId; //机器标识 private long sequence = 0L; //序列号 private long lastStmp = -1L;//上一次时间戳 public SnowFlake(long datacenterId, long machineId) { if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0"); } if (machineId > MAX_MACHINE_NUM || machineId < 0) { throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); } this.datacenterId = datacenterId; this.machineId = machineId; } /** * 设置初始时间,各业务方的旧算法有可能初始时间不一致,请使用 * @param timestamp 设定的新初始时间戳 * @return 当前对象 */ public SnowFlake withStartTimestamp(long timestamp) { SnowFlake.START_STMP = timestamp; return this; } /** * 产生下一个ID * * @return */ public synchronized long nextId() { long currStmp = getNewstmp(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (currStmp == lastStmp) { //相同毫秒内,序列号自增 sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大 if (sequence == 0L) { currStmp = getNextMill(); } } else { //不同毫秒内,序列号置为0 sequence = 0L; } lastStmp = currStmp; return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分 | datacenterId << DATACENTER_LEFT //数据中心部分 | machineId << MACHINE_LEFT //机器标识部分 | sequence; //序列号部分 } private long getNextMill() { long mill = getNewstmp(); while (mill <= lastStmp) { mill = getNewstmp(); } return mill; } private long getNewstmp() { return System.currentTimeMillis(); } // public static void main(String[] args) { // SnowFlake snowFlake = new SnowFlake(0, 0); // snowFlake.withStartTimestamp(1420041600000L); // // for (int i = 0; i < (1 << 5); i++) { // System.out.println(snowFlake.nextId()); // } // } }