package info.aspirecn.iov.sjjh.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper; import info.aspirecn.iov.sjjh.commons.lang.ChannelTypeHandleResponseObject; import info.aspirecn.iov.sjjh.commons.lang.Constant; import info.aspirecn.iov.sjjh.config.SupplierConfig; import info.aspirecn.iov.sjjh.constant.Constants; import info.aspirecn.iov.sjjh.entity.RequestObject; import info.aspirecn.iov.sjjh.entity.Response; import info.aspirecn.iov.sjjh.entity.VehicleHistoryPositionRequestParam; import info.aspirecn.iov.sjjh.entity.VehicleHistoryPositionResponse; import info.aspirecn.iov.sjjh.entity.geocoding.GeocodingResponseObject; import info.aspirecn.iov.sjjh.enums.VehicleHistoryPositionQueryType; import info.aspirecn.iov.sjjh.service.VehicleService; import info.aspirecn.iov.sjjh.util.DateUtil; import info.aspirecn.iov.sjjh.util.PostUtil; import info.aspirecn.iov.sjjh.util.ValidateParamUtil; import info.aspirecn.rdc.aspirecloud.node.except.utils.ErrorUtils; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * @author xusonglin * @version V1.0 **/ @Slf4j @Service public class VehicleServiceImpl implements VehicleService { @Autowired private SupplierConfig supplierConfig; private OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); @Override public ChannelTypeHandleResponseObject vehicleHistoryPositionQuery(HttpServletRequest request, String customBody, int outTime, Integer type) { ChannelTypeHandleResponseObject ret = new ChannelTypeHandleResponseObject(); ret.setIsCharge(Constant.INTERFACE_QUERY_NO_FEE); ret.setCode(Constant.SUCCESS); String upstreamCode = "" + Constant.LOG_UPSTREAM_DEFAULT_RESPONSE_CODE; request.setAttribute(Constant.LOG_UPSTREAM_RESPONSE_CODE, upstreamCode); if (outTime <= Constants.PARA_ZERO) { outTime = Constant.HTTPCLIENT_CONNECTTIMEOUT; } log.info("supplier-vehicle.vehicleHistoryPositionQuery---customBody={},outTime={}", customBody, outTime); // 解析参数 ObjectMapper objectMapper = new ObjectMapper(); VehicleHistoryPositionRequestParam requestParam; try { requestParam = objectMapper.readValue(customBody, VehicleHistoryPositionRequestParam.class); } catch (IOException ioe) { log.info("supplier-vehicle.vehicleHistoryPositionQuery-解析参数Exception:{}", ioe); ErrorUtils.captureException(ioe); ret.setCode(Constant.FAIL); ret.setResultCode(Constant.INVALID_PARAMETER_CODE); ret.setResultBody(Constant.INVALID_PARAMETER); ret.setResultDesc(Constant.INVALID_PARAMETER); return ret; } // 参数校验 if (!ValidateParamUtil.validateRequestParams(requestParam)) { ret.setCode(Constant.FAIL); ret.setResultCode(Constant.INVALID_PARAMETER_CODE); ret.setResultBody(Constant.INVALID_PARAMETER); ret.setResultDesc(Constant.INVALID_PARAMETER); return ret; } // 接口调用 Response response = new Response(); try { RequestObject requestObject = new RequestObject(); requestObject.setVehicleNumber(requestParam.getPlateNumber()); requestObject.setLicensePlateTypeCode(requestParam.getPlateColor()); requestObject.setStartTime(DateUtil.addHours(requestParam.getStartTime(), supplierConfig.getReduceHours())); requestObject.setEndTime(DateUtil.addHours(requestParam.getEndTime(), supplierConfig.getAddHours())); requestObject.setPartyFunctionCode(supplierConfig.getPartyFunctionCode()); response = PostUtil.postString(supplierConfig.getHistoryPositionUrl(), JSON.toJSONString(requestObject), supplierConfig.getAppKey(), supplierConfig.getAppSecret(), outTime); } catch (IOException e) { log.info("supplier-vehicle.vehicleHistoryPositionQuery-IOException:{}", e); ErrorUtils.captureException(e); ret.setCode(Constant.REQUEST_TIMEOUT); } catch (Exception e) { log.info("supplier-vehicle.vehicleHistoryPositionQuery-Exception:{}", e); ErrorUtils.captureException(e); ret.setCode(Constant.FAIL); } if (type.equals(VehicleHistoryPositionQueryType.VEHICLE_HISTORY_POSITION_QUERY.getValue())) { // 车辆轨迹核验 upstreamCode = setVehicleHistoryPositionQueryResponse(ret, response, requestParam); } else { // 车辆线上线下一致性验证 upstreamCode = setVehiclePositionConsistencyCheckResponse(ret, response, requestParam); } request.setAttribute(Constant.LOG_UPSTREAM_RESPONSE_CODE, upstreamCode); return ret; } private String setVehicleHistoryPositionQueryResponse(ChannelTypeHandleResponseObject ret, Response response, VehicleHistoryPositionRequestParam requestParam) { String upstreamCode = ""; log.info("supplier-vehicle.vehicleHistoryPositionQuery-responseStatus:{}", response.getStatusCode()); log.info("supplier-vehicle.vehicleHistoryPositionQuery-responseBody:{}", response.getBody()); if (response.getStatusCode() == Constants.STATUS_CODE_200) { VehicleHistoryPositionResponse positionResponse = JSON.toJavaObject(JSON.parseObject(response.getBody()), VehicleHistoryPositionResponse.class); upstreamCode = positionResponse.getResultCode(); if (positionResponse.getResultCode().equals(Constants.RESULT_CODE_0)) { if (positionResponse.getData() != null && positionResponse.getData().size() > 0) { String result = vehicleHistoryPositionQuery(positionResponse.getData(), requestParam); if (StringUtils.isBlank(result)) { JSONObject vehicleLocationInfo = new JSONObject(); vehicleLocationInfo.put("vehicleLocationInfo", positionResponse.getData()); ret.setResultCode(Constant.MATCH_CODE); ret.setResultBody(vehicleLocationInfo); ret.setResultDesc(Constant.QUERY_SUCCESS); } else { ret.setResultCode(Constant.UN_MATCH_CODE); ret.setResultBody(result); ret.setResultDesc(Constant.QUERY_SUCCESS); } } else { ret.setResultCode(Constant.UN_FIND_NUM_CODE); ret.setResultBody(Constants.NO_RESULT); ret.setResultDesc(Constants.NO_RESULT); } ret.setIsCharge(Constant.IS_CHARGE); } else if (positionResponse.getResultCode().equals(Constants.RESULT_CODE_110000)) { ret.setResultCode(Constant.UN_FIND_NUM_CODE); ret.setResultBody(Constants.NO_RESULT); ret.setResultDesc(Constants.NO_RESULT); } else { ret.setResultCode(Constant.OTHER_ERROR_CODE); ret.setResultBody(Constant.OTHER_ERROR); ret.setResultDesc(Constant.OTHER_ERROR); } } else { ret.setResultCode(Constant.OTHER_ERROR_CODE); ret.setResultBody(Constant.OTHER_ERROR); ret.setResultDesc(Constant.OTHER_ERROR); upstreamCode += response.getStatusCode(); } return upstreamCode; } private String vehicleHistoryPositionQuery(List positionList, VehicleHistoryPositionRequestParam requestParam) { /** * 1、云雁调取A-到B+之间所有的车辆轨迹(每30秒有一个经纬度数据)。 * 2、从A-到A+时间区间中每半个小时抽取一个点位信息的行政区划代码集合,将此集合与A点(起点)行政区划代码进行比对,只要有一点比对一致则视为此点核验通过。 * 3、从B-到B+时间区间中每半个小时抽取一个点位信息并转化为行政区划代码集合,将此集合与B点(终点)行政区划代码进行比对,只要有一点比对一致则视为此点核验通过。 * 4、A点到B点时间小于8小时情况依然按次逻辑处理,不做区分。 * 5、A点和B点都核验通过下视为该条轨迹核验通过,否则为核验不通过。 * 6、核验不通过情况下返回核验不通过。 * 7、核验结果一致的情况下输出结果,并输出A点到B点轨迹信息。 */ // A- String startTimeA = DateUtil.addHours(requestParam.getStartTime(), supplierConfig.getReduceHours()); // A+ String endTimeA = DateUtil.addHours(requestParam.getStartTime(), supplierConfig.getAddHours()); // B- String startTimeB = DateUtil.addHours(requestParam.getEndTime(), supplierConfig.getReduceHours()); // B+ String endTimeB = DateUtil.addHours(requestParam.getEndTime(), supplierConfig.getAddHours()); // 4小时*2=8小时(A-A+间隔),8小时*2=16个点(每半个小时取1个点) int pointNumber = supplierConfig.getAddHours()*2*2; List checkTimeListA = new ArrayList<>(); String tempStartTime = startTimeA; for (int i = 0; i < pointNumber+1; i++) { checkTimeListA.add(tempStartTime); tempStartTime = DateUtil.addMinutes(tempStartTime, 30); } List checkTimeListB = new ArrayList<>(); tempStartTime = startTimeB; for (int i = 0; i < pointNumber+1; i++) { checkTimeListB.add(tempStartTime); tempStartTime = DateUtil.addMinutes(tempStartTime, 30); } boolean checkResultA = false; // todo 这个集合为了查看位置是否正确 List verificationPositionListA = new ArrayList<>(); for (int i = 0; i < checkTimeListA.size()-1; i++) { for (VehicleHistoryPositionResponse.Data position : positionList) { if (Long.parseLong(position.getPositionTime()) > Long.parseLong(checkTimeListA.get(i)) && Long.parseLong(position.getPositionTime()) <= Long.parseLong(checkTimeListA.get(i+1))) { verificationPositionListA.add(position); if (requestParam.getLoadingCountrySubdivisionCode().equals(position.getPositionDescribe())) { checkResultA = true; } break; } } if (checkResultA) { break; } } if (!checkResultA) { return "loadingCountrySubdivisionCode与数据源不一致"; } boolean checkResultB = false; // todo 这个集合为了查看位置是否正确 List verificationPositionListB = new ArrayList<>(); for (int i = 0; i < checkTimeListB.size()-1; i++) { for (VehicleHistoryPositionResponse.Data position : positionList) { if (Long.parseLong(position.getPositionTime()) > Long.parseLong(checkTimeListB.get(i)) && Long.parseLong(position.getPositionTime()) <= Long.parseLong(checkTimeListB.get(i+1))) { verificationPositionListB.add(position); if (requestParam.getReceiptCountrySubdivisionCode().equals(position.getPositionDescribe())) { checkResultB = true; } break; } } if (checkResultB) { break; } } if (checkResultA && checkResultB) { return ""; } else { return "receiptCountrySubdivisionCode与数据源不一致"; } } private String setVehiclePositionConsistencyCheckResponse(ChannelTypeHandleResponseObject ret, Response response, VehicleHistoryPositionRequestParam requestParam) { String upstreamCode = ""; log.info("supplier-vehicle.vehicleHistoryPositionCheck-responseStatus:{}", response.getStatusCode()); log.info("supplier-vehicle.vehicleHistoryPositionCheck-responseBody:{}", response.getBody()); if (response.getStatusCode() == Constants.STATUS_CODE_200) { VehicleHistoryPositionResponse positionResponse = JSON.toJavaObject(JSON.parseObject(response.getBody()), VehicleHistoryPositionResponse.class); upstreamCode = positionResponse.getResultCode(); if (positionResponse.getResultCode().equals(Constants.RESULT_CODE_0)) { if (positionResponse.getData() != null && positionResponse.getData().size() > 0) { String result = vehiclePositionConsistencyCheck(positionResponse.getData(), requestParam); if (StringUtils.isBlank(result)) { ret.setResultCode(Constant.MATCH_CODE); ret.setResultBody(Constant.MATCH); ret.setResultDesc(Constant.QUERY_SUCCESS); } else { ret.setResultCode(Constant.UN_MATCH_CODE); ret.setResultBody(result); ret.setResultDesc(Constant.QUERY_SUCCESS); } } else { ret.setResultCode(Constant.UN_FIND_NUM_CODE); ret.setResultBody(Constants.NO_RESULT); ret.setResultDesc(Constants.NO_RESULT); } ret.setIsCharge(Constant.IS_CHARGE); } else if (positionResponse.getResultCode().equals(Constants.RESULT_CODE_110000)) { ret.setResultCode(Constant.UN_FIND_NUM_CODE); ret.setResultBody(Constants.NO_RESULT); ret.setResultDesc(Constants.NO_RESULT); } else { ret.setResultCode(Constant.OTHER_ERROR_CODE); ret.setResultBody(Constant.OTHER_ERROR); ret.setResultDesc(Constant.OTHER_ERROR); } } else { ret.setResultCode(Constant.OTHER_ERROR_CODE); ret.setResultBody(Constant.OTHER_ERROR); ret.setResultDesc(Constant.OTHER_ERROR); upstreamCode += response.getStatusCode(); } return upstreamCode; } private String vehiclePositionConsistencyCheck(List positionList, VehicleHistoryPositionRequestParam requestParam) { /** * 1、云雁调取A-到B+之间的车辆轨迹 * 2、将B点与B-到B+时间点内的行政区划代码做对比,得出比对结果一 * 将A点与A-到A+时间点内的行政区划代码做对比,得出比对结果二 * 3、核验结果有一个不一致的情况下返回不一致结果 * 4、核验结果一致的情况下一致结果 */ // A- String startTimeA = DateUtil.addHours(requestParam.getStartTime(), supplierConfig.getReduceHours()); // B- String startTimeB = DateUtil.addHours(requestParam.getEndTime(), supplierConfig.getReduceHours()); // 4小时*2=8小时(A-A+间隔),8小时*2=16个点(每半个小时取1个点) int pointNumber = supplierConfig.getAddHours()*2*2; List checkTimeListA = new ArrayList<>(); String tempStartTime = startTimeA; for (int i = 0; i < pointNumber+1; i++) { checkTimeListA.add(tempStartTime); tempStartTime = DateUtil.addMinutes(tempStartTime, 30); } List checkTimeListB = new ArrayList<>(); tempStartTime = startTimeB; for (int i = 0; i < pointNumber+1; i++) { checkTimeListB.add(tempStartTime); tempStartTime = DateUtil.addMinutes(tempStartTime, 30); } // todo 这个集合为了查看位置是否正确 List verificationPositionListA = new ArrayList<>(); for (int i = 0; i < checkTimeListA.size()-1; i++) { for (VehicleHistoryPositionResponse.Data position : positionList) { if (Long.parseLong(position.getPositionTime()) > Long.parseLong(checkTimeListA.get(i)) && Long.parseLong(position.getPositionTime()) <= Long.parseLong(checkTimeListA.get(i+1))) { verificationPositionListA.add(position); if (!requestParam.getLoadingCountrySubdivisionCode().equals(position.getPositionDescribe())) { return "loadingCountrySubdivisionCode"; } break; } } } // todo 这个集合为了查看位置是否正确 List verificationPositionListB = new ArrayList<>(); for (int i = 0; i < checkTimeListB.size()-1; i++) { for (VehicleHistoryPositionResponse.Data position : positionList) { if (Long.parseLong(position.getPositionTime()) > Long.parseLong(checkTimeListB.get(i)) && Long.parseLong(position.getPositionTime()) <= Long.parseLong(checkTimeListB.get(i+1))) { verificationPositionListB.add(position); if (!requestParam.getReceiptCountrySubdivisionCode().equals(position.getPositionDescribe())) { return "receiptCountrySubdivisionCode"; } break; } } } return ""; } }