| | |
| | | package com.xiaopeng.pushMessage.controller; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.xiaopeng.api.dto.operation.LonLatDto; |
| | | import com.xiaopeng.api.dto.pushMessage.PushOrderRouteDTO; |
| | | import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; |
| | | import com.xiaopeng.api.feignClient.order.XpOrderClient; |
| | | import com.xiaopeng.api.feignClient.order.XpTestOrderClient; |
| | | import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; |
| | | import com.xiaopeng.api.model.order.XpOrder; |
| | | import com.xiaopeng.api.model.order.XpTestOrder; |
| | | import com.xiaopeng.api.vo.operation.RouteVo; |
| | | import com.xiaopeng.common.core.constant.CacheConstants; |
| | | import com.xiaopeng.common.core.constant.Constants; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.enums.PushMessageTypeEnum; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.pushMessage.utils.MapMatchingUtil; |
| | | import io.swagger.annotations.Api; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.powermock.core.ListMap; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.LinkedBlockingQueue; |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | @Slf4j |
| | | @Api(tags = "订单推送轨迹接口") |
| | | @RestController |
| | | @RequestMapping("") |
| | |
| | | private XpOrderClient xpOrderClient; |
| | | |
| | | /** |
| | | * 通过定位推送订单轨迹 |
| | | * 通过车辆实时位置 |
| | | * 给乘客端推送剩余轨迹和剩余里程时长 |
| | | * @return |
| | | */ |
| | | @PostMapping("/inner/v1/order/pushOrderRoute") |
| | | public R<String> pushOrderRoute(@Validated @RequestBody PushOrderRouteDTO dto) { |
| | | |
| | | // 获取路线规划 |
| | | RouteVo routeVo = redisService.getCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType()); |
| | | |
| | | if(Objects.nonNull(routeVo)){ |
| | | |
| | | // 查询订单信息 |
| | | Integer routeType = dto.getRouteType(); |
| | | //正常订单 |
| | | if(routeType == 1){ |
| | | XpOrder xpOrder = xpOrderClient.queryOrderById(dto.getOrderId()).getData(); |
| | | |
| | | // 计算实时点位到线段的最优截取 |
| | | List<LonLatDto> lonLatDtos = MapMatchingUtil.clipBySegmentDistance(routeVo.getPolyline(), new LonLatDto(dto.getLongitude(), dto.getLatitude())); |
| | | |
| | | routeVo.setDistance(dto.getDistance()); |
| | | routeVo.setDuration(dto.getDuration()); |
| | | routeVo.setPolyline(lonLatDtos); |
| | | |
| | | // 存储最新路线偏离缓存,后续进行轨迹截取 |
| | | redisService.setCacheObject(CacheConstants.ORDER_ROUTE_CAPTURE + "_" + dto.getOrderId() + "_" +dto.getRouteType(), routeVo); |
| | | |
| | | // 封装轨迹点位集合 |
| | | Map<String, Object> polyline = new HashMap<>(); |
| | | for (LonLatDto lonLatDto : lonLatDtos) { |
| | | polyline.put("longitude",lonLatDto.getLongitude()); |
| | | polyline.put("latitude",lonLatDto.getLatitude()); |
| | | // 获取路线规划 |
| | | String key = ""; |
| | | //接驾情况,获取车辆位置到起点的导航 |
| | | if(xpOrder.getStatus() == 2 || xpOrder.getStatus() == 3){ |
| | | key = "ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(); |
| | | }else{ |
| | | key = "ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(); |
| | | } |
| | | // 封装路由详情 |
| | | Map<String, Object> route = new HashMap<>(); |
| | | route.put("distance",dto.getDistance()); |
| | | route.put("duration",dto.getDuration()); |
| | | route.put("polyline",JSONObject.toJSONString(polyline)); |
| | | Object cacheObject = redisService.getCacheObject(key); |
| | | RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class); |
| | | |
| | | // 封装消息内容 |
| | | Integer routeType = dto.getRouteType(); |
| | | if(routeType == 2){ |
| | | routeType = 3; |
| | | }else { |
| | | routeType = xpOrder.getStatus() == 4 ? 1 : 2; |
| | | if(Objects.nonNull(routeVo)){ |
| | | Integer distance = dto.getDistance(); |
| | | Integer duration = dto.getDuration(); |
| | | // 计算实时点位到线段的最优截取 |
| | | Map<String, List<LonLatDto>> remainingNavigation = MapMatchingUtil.getRemainingNavigation(routeVo.getPolyline(), dto.getLongitude(), dto.getLatitude()); |
| | | //当订单状态为5的时候(乘客已上车)需要推送导航的距离和剩余时间 |
| | | //因为这个状态,车端推的依然是接驾的剩余里程和时间,就会导致数据和小程序的页面跳转匹配不上 |
| | | //小程序是只要乘客上车后就跳转到行程开始页面 |
| | | if(5 != xpOrder.getStatus()){ |
| | | routeVo.setDistance(distance); |
| | | routeVo.setDuration(duration); |
| | | }else{ |
| | | distance = routeVo.getDistance(); |
| | | duration = routeVo.getDuration(); |
| | | } |
| | | List<LonLatDto> lonLatDtos = remainingNavigation.get("unserved"); |
| | | List<LonLatDto> lonLatDtos1 = remainingNavigation.get("served"); |
| | | routeVo.setPolyline(lonLatDtos); |
| | | routeVo.setServed(lonLatDtos1); |
| | | |
| | | // 存储最新路线偏离缓存,后续进行轨迹截取 |
| | | redisService.setCacheObject(key, JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS); |
| | | |
| | | // 封装轨迹点位集合 |
| | | List<Map<String, Object>> polyline = new ArrayList<>(); |
| | | for (LonLatDto lonLatDto : lonLatDtos) { |
| | | Map<String, Object> polylineMap = new HashMap<>(); |
| | | polylineMap.put("longitude",lonLatDto.getLongitude()); |
| | | polylineMap.put("latitude",lonLatDto.getLatitude()); |
| | | polyline.add(polylineMap); |
| | | } |
| | | List<Map<String, Object>> served = new ArrayList<>(); |
| | | for (LonLatDto lonLatDto : lonLatDtos1) { |
| | | Map<String, Object> polylineMap = new HashMap<>(); |
| | | polylineMap.put("longitude",lonLatDto.getLongitude()); |
| | | polylineMap.put("latitude",lonLatDto.getLatitude()); |
| | | served.add(polylineMap); |
| | | } |
| | | // 封装路由详情 |
| | | Map<String, Object> route = new HashMap<>(); |
| | | route.put("distance",distance); |
| | | route.put("duration",duration); |
| | | route.put("polyline",JSONObject.toJSONString(polyline)); |
| | | route.put("served",JSONObject.toJSONString(served)); |
| | | |
| | | Map<String, Object> content = new HashMap<>(); |
| | | content.put("orderId",dto.getOrderId().toString()); |
| | | content.put("routeType",routeType); |
| | | content.put("direction",dto.getDirection()); |
| | | content.put("route",JSONObject.toJSONString(route)); |
| | | |
| | | // 封装轨迹信息 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | params.put("type", PushMessageTypeEnum.ORDER_ROUTE.getDesc()); |
| | | params.put("content", JSONObject.toJSONString(content)); |
| | | params.put("timestamp", new Date().getTime()+""); |
| | | |
| | | // 进行消息推送 |
| | | SendMessageDTO sendMessageDTO = new SendMessageDTO(); |
| | | sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId())); |
| | | sendMessageDTO.setMessage(JSONObject.toJSONString(params)); |
| | | R<String> stringR = xpPushMessageClient.sendRoute(sendMessageDTO); |
| | | //推送失败,重试3次 |
| | | if(stringR.getCode() != Constants.SUCCESS){ |
| | | ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); |
| | | executor.execute(() -> { |
| | | for (int i = 0; i < 3; i++) { |
| | | R<String> stringR1 = xpPushMessageClient.sendStatus(sendMessageDTO); |
| | | if(stringR1.getCode() == Constants.SUCCESS){ |
| | | break; |
| | | } |
| | | try { |
| | | Thread.sleep(1000); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | log.info("推送乘客端剩余导航数据消息失败:{} {} {}", stringR1.getMsg(), JSON.toJSONString(sendMessageDTO), xpOrder.getOrderNumber()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | log.info("推送剩余导航数据成功 {} {}", xpOrder.getOrderNumber(), JSON.toJSONString(routeVo)); |
| | | } |
| | | Map<String, Object> content = new HashMap<>(); |
| | | content.put("orderId",dto.getOrderId()); |
| | | content.put("routeType",routeType); |
| | | content.put("route",JSONObject.toJSONString(route)); |
| | | |
| | | // 封装轨迹信息 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | params.put("type", PushMessageTypeEnum.ORDER_ROUTE.getDesc()); |
| | | params.put("content", JSONObject.toJSONString(content)); |
| | | params.put("timestamp", new Date().getTime()+""); |
| | | |
| | | // 进行消息推送 |
| | | SendMessageDTO sendMessageDTO = new SendMessageDTO(); |
| | | sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId())); |
| | | sendMessageDTO.setMessage(JSONObject.toJSONString(params)); |
| | | xpPushMessageClient.sendRoute(sendMessageDTO); |
| | | } |
| | | return R.ok(); |
| | | } |