LocusOrbitServiceImpl.java 10.6 KB
package com.objecteye.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.objecteye.entity.LocusOrbitQueryParams;
import com.objecteye.entity.LocusOrbitResultParams;
import com.objecteye.entity.PageResult;
import com.objecteye.pojo.RabbitMQVehicle;
import com.objecteye.service.AreaEquipmentService;
import com.objecteye.service.ILocusOrbitService;
import com.objecteye.utils.GlobalUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 汽车轨迹接口
 *
 * @author liuhaoyu
 */
@Service
public class LocusOrbitServiceImpl implements ILocusOrbitService {

    private final Logger logger = LoggerFactory.getLogger(LocusOrbitServiceImpl.class);

    private final String URL = "http://192.168.10.4:10002/vehicle/analysisFile";

    /**
     * 车牌置信度界限值
     */
    private final double NUM_SCORE_LIMIT = 0.9;

    /**
     * 抓拍时间需要去重的时间间隔
     */
    private final Long DISTINCT_TIME_INTERVAL = 60000L;

    @Autowired
    private AreaEquipmentService areaEquipmentService;
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 轨迹分析接口
     *
     * @param locusOrbitQueryParams 请求参数模型
     * @return 结果集 key: 车牌号, value: 车牌号对应的轨迹信息
     */
    @Override
    public List<LocusOrbitResultParams> locusOrbitByPlateNumber(LocusOrbitQueryParams locusOrbitQueryParams) {
        // 所有符合条件的原始数据
        List<RabbitMQVehicle> rabbitMqVehicles = mongoTemplate.find(locusOrbitQueryConditionDbHandle(locusOrbitQueryParams), RabbitMQVehicle.class);
        return simplePlateNumberHandle(rabbitMqVehicles);
    }

    /**
     * 轨迹分析接口(图片搜索)
     *
     * @param gcxh                  车辆序号
     * @param locusOrbitQueryParams 请求参数模型
     * @param multipartFile         文件信息
     * @return 车牌号对应的轨迹信息
     */
    @Override
    public List<LocusOrbitResultParams> locusOrbitByPlateNumber(int gcxh, LocusOrbitQueryParams locusOrbitQueryParams, MultipartFile multipartFile) {
        String fileName = multipartFile.getOriginalFilename();
        String picPath = GlobalUtil.dbPath1() + File.separator + "picture" + File.separator + fileName;
        File newFile = new File(picPath);
        try {
            multipartFile.transferTo(newFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String response = GlobalUtil.httpExecute(URL, newFile);
        // 使用完成之后删除文件
        newFile.delete();
        if (null == response || "".equals(response)) {
            return null;
        }

        JSONObject responseObj = JSON.parseObject(response);
        JSONArray infoArr = responseObj.getJSONObject("result").getJSONArray("info");
        if (null == infoArr || infoArr.size() == 0) {
            return null;
        }
        List<JSONObject> infoList = infoArr.toJavaList(JSONObject.class);
        JSONObject infoObj = infoList.get(gcxh);
        // 车牌置信度超过0.9 直接用车牌
        double numScore = infoObj.getJSONObject("vehicle_plate_det_recg_res").getDoubleValue("numScore");
        if (numScore > NUM_SCORE_LIMIT) {
            JSONArray plateNumParamsArr = infoObj.getJSONObject("vehicle_plate_det_recg_res").getJSONArray("plateNumParams");
            StringBuilder plateNumberBuilder = new StringBuilder();
            for (int i = 0; i < plateNumParamsArr.size(); i++) {
                JSONObject plateNumParamObj = plateNumParamsArr.getJSONObject(i);
                if (null == plateNumParamObj) {
                    continue;
                }
                plateNumberBuilder.append(plateNumParamObj.getString("character"));
            }
            locusOrbitQueryParams.setPlateNumber(plateNumberBuilder.toString());
        } else {
            return new ArrayList<>();
        }

        return locusOrbitByPlateNumber(locusOrbitQueryParams);
    }

    /**
     * 拼接查询条件
     *
     * @param locusOrbitQueryParams 请求参数模型
     * @return mongo用query对象
     */
    private Query locusOrbitQueryConditionDbHandle(LocusOrbitQueryParams locusOrbitQueryParams) {
        Criteria criteria = new Criteria();
        // 地区id
        if (null != locusOrbitQueryParams.getCustomsPass()) {
            List<Integer> customsPass = areaEquipmentService.findCaptureById(locusOrbitQueryParams.getCustomsPass());
            criteria.and("deviceid").in(customsPass);
        }
        // 车牌
        criteria.and("vehicle_plate_hphm").is(locusOrbitQueryParams.getPlateNumber());
        // 开始时间
        // 结束时间
        Long startTime = locusOrbitQueryParams.getStartTime();
        Long endTime = locusOrbitQueryParams.getEndTime();

        if (null == startTime) {
            if (null != endTime) {
                criteria.and("pictime").lte(endTime);
            }
        } else if (null == endTime) {
            criteria.and("pictime").gte(startTime);
        } else {
            criteria.and("pictime").gte(startTime).lte(endTime);
        }

        Query query = Query.query(criteria);
        query.fields().include("id");
        query.fields().include("pictime");
        query.fields().include("longitude");
        query.fields().include("latitude");
        query.fields().include("equipmentName");
        query.fields().include("snapshoturl");
        query.fields().include("vehicle_plate_hphm");

        return query;
    }

    /**
     * 单个车牌时间段去重(去重抓拍时间不超过1分钟的数据)
     *
     * @param rabbitMqVehicles 原始数据
     * @return 结果集
     */
    private List<LocusOrbitResultParams> simplePlateNumberHandle(List<RabbitMQVehicle> rabbitMqVehicles) {
        List<LocusOrbitResultParams> resultList = new ArrayList<>();
        // 倒序排列
        rabbitMqVehicles.sort((o1, o2) -> (int) (o2.getPictime() - o1.getPictime()));

        // 时间游标
        Long lastPictime = Long.MAX_VALUE;

        for (RabbitMQVehicle rabbitMqVehicle : rabbitMqVehicles) {
            if (null == rabbitMqVehicle || null == rabbitMqVehicle.getPictime()) {
                continue;
            }
            Long currentPictime = rabbitMqVehicle.getPictime();
            // 更新时间游标
            if (lastPictime - currentPictime > DISTINCT_TIME_INTERVAL) {
                lastPictime = currentPictime;
                LocusOrbitResultParams locusOrbitResultParams = new LocusOrbitResultParams();
                locusOrbitResultParams.setId(rabbitMqVehicle.getId());
                locusOrbitResultParams.setPlateNumber(rabbitMqVehicle.getVehicle_plate_hphm());
                locusOrbitResultParams.setPictime(DateUtil.format(new Date(currentPictime), "yyyy-MM-dd HH:mm:ss"));
                locusOrbitResultParams.setLongitude(rabbitMqVehicle.getLongitude());
                locusOrbitResultParams.setLatitude(rabbitMqVehicle.getLatitude());
                locusOrbitResultParams.setEquipmentName(rabbitMqVehicle.getEquipmentName());
                locusOrbitResultParams.setSnapshotUrl(rabbitMqVehicle.getSnapshoturl());
                resultList.add(locusOrbitResultParams);
            }
        }
        // 重新排序
        resultList.sort((o1, o2) -> {
            if (DateUtil.parse(o1.getPictime()).getTime() - DateUtil.parse(o2.getPictime()).getTime() > 0) {
                return 1;
            } else if (DateUtil.parse(o1.getPictime()).getTime() - DateUtil.parse(o2.getPictime()).getTime() < 0) {
                return -1;
            } else {
                return 0;
            }
        });
        return resultList;
    }

    /**
     * 轨迹分析页面列表
     *
     * @param locusOrbitQueryParams 请求参数模型
     * @param currentpage           页码
     * @param pagevolume            页面容量
     * @return 结果集
     */
    @Override
    public PageResult locusOrbitTableByPlateNumber(LocusOrbitQueryParams locusOrbitQueryParams, Integer currentpage, Integer pagevolume) {
        Criteria criteria = new Criteria();
        Long startTime = locusOrbitQueryParams.getStartTime();
        Long endTime = locusOrbitQueryParams.getEndTime();
        if (null != startTime && null != endTime) {
            criteria.and("pictime").gte(startTime).lte(endTime);
        } else if (null != startTime) {
            criteria.and("pictime").gte(startTime);
        } else if (null != endTime) {
            criteria.and("pictime").lte(endTime);
        }
        criteria.and("vehicle_plate_hphm").is(locusOrbitQueryParams.getPlateNumber());

        Query query = Query.query(criteria);
        query.fields().include("id");
        query.fields().include("pictime");
        query.fields().include("equipmentName");
        query.fields().include("snapshoturl");
        query.fields().include("vehicle_plate_hphm");

        List<RabbitMQVehicle> rabbitMqVehicles = mongoTemplate.find(query.skip((currentpage - 1) * pagevolume).limit(pagevolume)
                .with(Sort.by(Sort.Order.asc("pictime"))), RabbitMQVehicle.class);

        List<LocusOrbitResultParams> resultList = new ArrayList<>();
        for (RabbitMQVehicle rabbitMqVehicle : rabbitMqVehicles) {
            LocusOrbitResultParams locusOrbitResultParams = new LocusOrbitResultParams();
            if (null != rabbitMqVehicle) {
                locusOrbitResultParams.setId(rabbitMqVehicle.getId());
                locusOrbitResultParams.setSnapshotUrl(rabbitMqVehicle.getSnapshoturl());
                locusOrbitResultParams.setEquipmentName(rabbitMqVehicle.getEquipmentName());
                locusOrbitResultParams.setPlateNumber(rabbitMqVehicle.getVehicle_plate_hphm());
                locusOrbitResultParams.setPictime(DateUtil.format(new Date(rabbitMqVehicle.getPictime()), "yyyy-MM-dd HH:mm:ss"));
            }
            resultList.add(locusOrbitResultParams);
        }

        long total = mongoTemplate.count(query, RabbitMQVehicle.class);
        // 总页数
        int totalPage = (int) Math.ceil((double) total / pagevolume);

        return new PageResult<>(totalPage, resultList);
    }
}