一、前言
在一些和车辆设备有关的项目中需要用到回显车辆的运行轨迹、或者是显示车辆的详细信息(比如里程值、速度等等),但是有些时候,安装在车辆上的GPS上报设备上报的数据并不是百分之百的精准,可能的情况有:个别点的经纬度有偏差(并没有在道路上),车辆的里程值有误等等。本实例要解决的就是车辆的轨迹点偏移和里程值的更新校准。
二、 总体思路
在了解实现流程之前,需要对几个属性进行说明。
设备号:安装在车辆上的设备的编号,也是该车辆的唯一标识。
历史轨迹文件:每辆车每天生成的一个文件名为设备号的txt文件,文件中每一行就是一个上报点位,包括速度、里程、方向、经纬度、点火状态等等数据。当车辆上的设备上报数据时,该条数据会增量更新到轨迹文件中。因此,轨迹文件中储存的就是车辆设备上报的原始点位。
每日里程表:记录一天中行驶车辆的总里程总时长等等信息,只要车辆行驶了就会有数据。
1.轨迹纠偏实现流程
1)通过每日里程表获取指定日期行驶车辆的设备号列表。
2)通过设备号列表获取到历史轨迹点位的集合
3)查询此设备号在高德猎鹰平台上的终端号,如果没有就注册该设备并获取终端号
4)通过获取到的终端号在该终端下创建轨迹,获取轨迹ID
5)上传该设备当天的所有上报点位到新创建的轨迹ID下,由于高德平台限制,一次最多只能传100个点,所以需要拆分点集合,分批次上传
6)上传完成后调用轨迹查询接口,查询该车的轨迹信息,查询时传入纠偏的具体参数,返回的结果便是纠偏之后的结果。
7)解析并保存数据,并备份源文件
2.里程校准实现流程
第一部分:先将历史轨迹中的点调一遍纠偏服务,去飘点,减少里程计算的误差。
1)通过每日里程表获取指定日期行驶车辆的设备号列表。
2)通过设备号列表获取到历史轨迹点位的集合
3)查询此设备号在高德猎鹰平台上的终端号,如果没有就注册该设备并获取终端号
4)通过获取到的终端号在该终端下创建轨迹,获取轨迹ID
5)上传该设备当天的所有上报点位到新创建的轨迹ID下,由于高德平台限制,一次最多只能传100个点,所以需要拆分点集合,分批次上传
6)上传完成后调用轨迹查询接口,查询该车的轨迹信息,查询时传入纠偏的具体参数,返回的结果便是纠偏之后的结果。
7)解析数据,并将结果集进行里程计算。
第二部分:拿到纠偏之后的数据,计算里程
1)调用高德路径规划,由于高德API限制,一次最多只能计算18个点,所以需要将点拆分后,分批次调用,累计每次请求的结果之和就是总里程值。
2)把算出来的里程值更新到每日里程表中供项目中其他功能使用。
三、高德API链接
轨迹纠偏:https://lbs.amap.com/api/track/lieying-kaifa/api/grasproad
路径规划:https://lbs.amap.com/api/webservice/guide/api/direction/
四、API实战解析
由于里程校准中包含了轨迹纠偏的步骤,所以重点举例里程校准功能
1.原始数据格式示例
{“acc”:1,“alitiude”:0,“azimuth”:0,“badDriving”:"",“battery”:0,“carId”:“4028814195956584b20164698a18a40761”,“carTel”:"",“deviceType”:"",“eventType”:"",“heightOfWater”:0,“isFloat”:0,“lac”:"",“lat”:40.383385,“lng”:115.94770799999999,“lowPower”:0,“mileage”:84779.8,“oil”:0,“oilDianZu”:0,“reportId”:"",“reportType”:"",“speed”:55.6,“status”:"",“tc”:“0123456789”,“temperature”:0,“time”:1581722832000,“working”:0}
2.部分参考源码
里程校准定时器:
package com.web.job;
import com.alibaba.fastjson.JSONObject;
import com.sdk.container.SpringContextUtil;
import com.socket.bean.TerminalHistorySpot;
import com.socket.utils.OtherUtils;
import com.web.gps.everydayMileage.entity.EverydayMileage;
import com.web.gps.everydayMileage.service.EverydayMileageService;
import com.web.gps.everydayMileage.service.RoadService;
import com.web.gps.lushu.service.LushuService;
import com.web.utils.ConstantUtil;
import com.web.utils.DateUtil;
import com.web.utils.MileageCalibrationUtil;
import com.web.utils.TerminalHistoryUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/*
* 调用高德路径规划--路径规划(驾车) 校准历史轨迹文件中的里程数
* 总体流程:通过前一天的历史轨迹计算出总里程、总时长、有效里程、有效时长。更新到每日里程表中。
准备工作:先把历史轨迹的点调一遍纠偏服务,去飘点。
API:调用驾车规划API,每十八个点计算首尾两点的里程。(分组,每组十八个点)
筛选条件:
总里程:从速度不为0 的点作为第一个点(每天的第一个点独立,从第一个速度不为0 的点开始。)开始计算到最后一个点。中间速度为0 的点里程自然也不变。工作状态不限。
总时长:除去所有速度为0的点的总时长。须除去速度为0的点的时间!
有效里程:总里程范围内,工作状态为1 的点(连续三个以上)的距离 之和。
有效时长:总里程范围内,工作状态为1 的点(连续三个以上)的时间 之和。
* 每天凌晨执行,获取前一天所有上报车辆的历史轨迹信息,进行里程校准
*
* key---用户唯一标识---用户在高德地图官网申请
* origin--出发点--传三个点,用来计算车头,规划时以最后一个点为起始点.经纬度小数点后不得超过6位。格式为x1,y1|x2,y2|x3,y3。
* destination--目的地--经度在前,纬度在后,经度和纬度用","分割,经纬度小数点后不得超过6位
* strategy--规划策略--推荐:0,速度优先,不考虑当时路况,此路线不一定距离最短
* */
public class MileageCalibrationJob implements Job{
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
private SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");
//日志对象
private static final Logger log = LoggerFactory.getLogger(MileageCalibrationJob.class);
//定义获取历史轨迹源数据的对象,第一个String为设备号,第二个String为时间
Map<String, Map<String, List<TerminalHistorySpot>>> tcMap = new HashMap<String, Map<String, List<TerminalHistorySpot>>>();
//获取调用服务所需的key,由用户申请
private static final String GAODE_USER_KEY= "用户申请的kEY";
/*调用已有Service中的方法,获取历史轨迹数据*/
private LushuService lushuService;
private EverydayMileageService everydayMileageService;
private RoadService roadService;
//构造方法实例化Service
public MileageCalibrationJob(){
super();
lushuService = (LushuService) SpringContextUtil.getBean("lushuService");
everydayMileageService = (EverydayMileageService) SpringContextUtil.getBean("everydayMileageService");
roadService = (RoadService) SpringContextUtil.getBean("roadService");
}
/*
* 定时器执行的方法
* */
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//查询每日车辆里程信息表,获取前一天上传过GPS的车辆里程信息
Map<String, Object> param = new HashMap<String, Object>();
param.put("day", DateUtil.getPastDate(1));
List<EverydayMileage> everydayList = everydayMileageService.findList(param, null);
//查询每日车辆里程信息表,获取前一天上传过GPS的车辆里程信息END获取车辆的设备号集合
int size = everydayList.size();
String[] termCodes= new String[size];
for(int i=0;i<size;i++){
termCodes[i]=everydayList.get(i).getTermCode();
}
//获取车辆的设备号集合END
//设定查询历史轨迹的始末时间BEGIN
Date before = DateUtil.getdateByStringFormat(DateUtil.getPastDate(1) + " 00:00:00", ConstantUtil.YYYYMMDD_TIME);
Date now = DateUtil.getdateByStringFormat(DateUtil.getPastDate(1) + " 23:59:59", ConstantUtil.YYYYMMDD_TIME);
//设定查询历史轨迹的始末时间END
/*---------------------------------------------------------testStart----------------*/
//测试数据先写死
/*String[] termCodes= new String[1];
termCodes[0]="01216400739";
Date before = new Date();
Date now = new Date();
try {
before = sdf.parse("2019-12-10 00:00:00");
now = sdf.parse("2019-12-10 23:59:59");
} catch (ParseException e) {
e.printStackTrace();
}*/
/*--------------------testEnd--------------------------------------------------*/
//获取前一天的历史轨迹存放路径
String path = OtherUtils.gpsHistorySpot(before);
//查询当天所有设备在该时间段的历史轨迹信息
tcMap = roadService.queryHistoricalTrajectory(termCodes,before,now,"gaode");//不进行飘点过滤的方法
if(tcMap!=null){
//hmap,key为设备号tc,value为Map<String, List<TerminalHistorySpot>>
for (Map.Entry<String, Map<String, List<TerminalHistorySpot>>> hmap : tcMap.entrySet()) {
//如果设备号不为空,遍历此设备下的历史轨迹
if(hmap.getKey()!=null){
/*查询此设备在猎鹰平台上的终端号,name为设备号*/
Integer Tid = TerminalHistoryUtil.queryTidByTname(hmap.getKey());
//如果该设备没有注册,就先注册该设备
if(Tid == -1){
log.info("当前设备未在猎鹰平台注册,无终端信息,设备号:"+ hmap.getKey());
List trCodes = new ArrayList();
trCodes.add(hmap.getKey());
boolean state = TerminalHistoryUtil.initTerminal(TerminalHistoryUtil.sid,trCodes);
if (state == true){
log.info("猎鹰平台注册设备成功!设备号:"+ hmap.getKey());
Tid = TerminalHistoryUtil.queryTidByTname(hmap.getKey());
}else {
log.info("猎鹰平台注册设备失败!设备号:"+ hmap.getKey());
}
}
if (Tid != -1){
/*创建轨迹,拿到轨迹ID(单车)*/
Integer traceId = TerminalHistoryUtil.createTrace(Tid);
//listEntry,key为时间,value为List<TerminalHistorySpot> 一天的
if(hmap.getValue().size() > 0){
for (Map.Entry<String, List<TerminalHistorySpot>> listEntry : hmap.getValue().entrySet()) {
//获取到历史轨迹数据
List<TerminalHistorySpot> list = listEntry.getValue();
if (list != null && list.size() > 0){
//总里程
Double dayKM = 0.0d;
//有效里程
Double workKm = 0.0d;
//先通过原始数据算总时长和有效时长
//总时长
Long totalSecond = MileageCalibrationUtil.countTotalityTime(list);
//有效时长
Long workSecond = MileageCalibrationUtil.countWorkTime(list);
//去除速度为0的点
List<TerminalHistorySpot> clearlist = MileageCalibrationUtil.clearZero(list);
//有效里程---补点
//筛选出有效里程的点
List<List<TerminalHistorySpot>> workPoint = MileageCalibrationUtil.getWorkPoint(clearlist);
for (List<TerminalHistorySpot> terminalHistorySpots : workPoint) {
if (terminalHistorySpots.size() > 3){
/*创建轨迹,拿到轨迹ID(单车)*/
Integer traceIdforwork = TerminalHistoryUtil.createTrace(Tid);
//如果一个片段有三条以上,就纠偏补点
ArrayList<JSONObject> newWorkPoint = MileageCalibrationUtil.getAllPoint(Tid, traceIdforwork, before, now, terminalHistorySpots);
if (newWorkPoint != null){
//转换为pojo对象集合
List<TerminalHistorySpot> worklist = TerminalHistoryUtil.convertResult(newWorkPoint);
//查询里程,并存
workKm += MileageCalibrationUtil.countDayKM(worklist);
}
TerminalHistoryUtil.deleteTrace(Tid, traceIdforwork);
}
}
//总里程---补点
ArrayList<JSONObject> result = MileageCalibrationUtil.getAllPoint(Tid,traceId,before,now,clearlist);
TerminalHistoryUtil.deleteTrace(Tid, traceId);
if (result != null && result.size() > 0){
//先获取返回的状态,判断是否正常调用接口
JSONObject state = (JSONObject)result.get(0);
String errcode = state.getString("errcode");
//返回状态正常
if(errcode.equals("10000")){
//解析并获取返回的数据
List<TerminalHistorySpot> terminalHistorySpots = TerminalHistoryUtil.convertResult(result);
//算总里程
dayKM = MileageCalibrationUtil.countDayKM(terminalHistorySpots);
}
}
log.debug("里程信息查询完成!");
Map params = new HashMap<String,String>();
params.put("termCode",hmap.getKey());
params.put("day",ymd.format(before));
//查询每日里程表中信息,单条
List<EverydayMileage> everydayMileages = everydayMileageService.findList(params, null);
//查询备份表信息,单条
List<EverydayMileage> everydayMileagesCopy = everydayMileageService.queryListForCopy(params);
if (everydayMileages != null && everydayMileages.size() > 0){
//判断备份表中是否有该车的记录,如果有就更新数据,没有就新增
if (everydayMileagesCopy != null && everydayMileagesCopy.size() > 0){
everydayMileageService.updateForCopy(everydayMileages.get(0));
}else {
everydayMileageService.saveForCopy(everydayMileages.get(0));
}
//把算出来的里程数据更新到每日里程表中
EverydayMileage everydayMileage = everydayMileages.get(0);
//把四个属性值存到新表
everydayMileage.setDayKm(dayKM/1000d);
everydayMileage.setTotalSecond(Integer.parseInt(String.valueOf(totalSecond)));
everydayMileage.setWorkKm(workKm/1000d);
everydayMileage.setWorkSecond(Integer.parseInt(String.valueOf(workSecond)));
//更新每日里程表
everydayMileageService.update(everydayMileage);
}
}else {
log.error("当前设备无历史轨迹信息,设备号:"+ hmap.getKey()+"---");
}
}
}else {
log.error("当前设备无历史轨迹信息,设备号:"+ hmap.getKey()+"---");
}
}
}else{
log.error("当前设备为null,无历史轨迹信息!");
}
}
}else{
log.error("获取历史轨迹数据失败!");
}
}
}
里程校准工具类:
package com.web.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.socket.bean.Point;
import com.socket.bean.TerminalHistorySpot;
import com.socket.utils.CoordTransformUtils;
import com.web.gps.everydayMileage.entity.HttpClient;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
import java.util.Map.Entry;
/**
* 里程校准相关工具类
*/
public class MileageCalibrationUtil {
private static final Logger log = LoggerFactory.getLogger(MileageCalibrationUtil.class);
private static final String Key = "用户申请的KEY";
//路径规划距离测量地址
private static final String queryMileageURL = "https://restapi.amap.com/v3/distance";
//路径规划API地址
private static final String drivingURL = "https://restapi.amap.com/v3/direction/driving";
/*
* 通过原始数据计算总时长
* 返回单位--秒
* */
public static Long countTotalityTime(List<TerminalHistorySpot> list){
//总时长变量(秒)
Long totalSecond = 0l;
//中间变量
Long tempSecond = 0l;
//遍历原始历史轨迹数据
for (int i = 0;i < list.size();i++){
if (list.get(i).getSpeed() != 0f){
if (tempSecond != 0l){
totalSecond += list.get(i).getTime() - tempSecond;
}
}
tempSecond = list.get(i).getTime();
}
return totalSecond/1000l;
}
/*
* 通过原始数据计算有效时长
* 返回单位--秒
* */
public static Long countWorkTime(List<TerminalHistorySpot> list){
//有效时长变量
Long workSecond = 0l;
//有效点集合
List<List<TerminalHistorySpot>> workList = getWorkPointforyuanlist(list);
//参照变量
Long tempTime = 0l;
//遍历有效点集合
for (List<TerminalHistorySpot> terminalHistorySpots : workList) {
//如果集合长度大于3,就计算时间差
if (terminalHistorySpots.size() > 3){
for (int i = 0;i < terminalHistorySpots.size();i++) {
//第一次先存参照变量
if (i == 0){
tempTime = terminalHistorySpots.get(i).getTime();
}else {
if (tempTime != 0l){
//计算后更新参照时间变量
workSecond += terminalHistorySpots.get(i).getTime() - tempTime;
}
tempTime = terminalHistorySpots.get(i).getTime();
}
}
}
}
return workSecond/1000l;
}
/*
* 封装纠偏上传点位和查询点位操作
* */
public static ArrayList<JSONObject> getAllPoint(Integer Tid, Integer traceId, Date before, Date now, List<TerminalHistorySpot> clearlist){
/*给数据分页,最多100条数据*/
List<List<TerminalHistorySpot>> partition = Lists.partition(clearlist, 100);
//test---记录重复时间戳
HashMap<String,String> localtimemap = new HashMap<String, String>();
//上传轨迹信息,纠偏
for (List<TerminalHistorySpot> terminalHistorySpots : partition) {
//根据轨迹ID上传一辆车当天的轨迹信息,一次100条
TerminalHistoryUtil.uploadTraceData(Tid,traceId,terminalHistorySpots,localtimemap);
}
//调用轨迹查询接口,查询该车的轨迹信息,并设置纠偏粒度
ArrayList<JSONObject> result = null;
try {
result = TerminalHistoryUtil.searchTracksByTrid(Tid, traceId, before.getTime(), now.getTime());
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
/*
* 筛选出有效里程的坐标点
* list:除0后的坐标集
* */
public static List<List<TerminalHistorySpot>> getWorkPoint(List<TerminalHistorySpot> list){
//有效点集合
List<List<TerminalHistorySpot>> workList = new ArrayList<List<TerminalHistorySpot>>();
//有效点子集
List<TerminalHistorySpot> templist = new ArrayList<TerminalHistorySpot>();
//遍历源数据,筛选出工作状态的点
for(int i = 0;i < list.size();i++){
//工作状态
if (list.get(i).getWorking() == 1 && list.get(i).getAcc() == 1){
templist.add(list.get(i));
}else if (templist.size() > 3){
//工作状态断了就存一次
workList.add(templist);
templist = new ArrayList<TerminalHistorySpot>();
}else {
templist = new ArrayList<TerminalHistorySpot>();
}
//防止最后一个点也是工作状态
if (i == list.size() - 1 && templist.size() > 0){
workList.add(templist);
}
}
return workList;
}
/*
* 筛选出有效里程的坐标点
* */
public static List<List<TerminalHistorySpot>> getWorkPointforyuanlist(List<TerminalHistorySpot> list){
//有效点集合
List<List<TerminalHistorySpot>> workList = new ArrayList<List<TerminalHistorySpot>>();
//有效点子集
List<TerminalHistorySpot> templist = new ArrayList<TerminalHistorySpot>();
//遍历源数据,筛选出工作状态的点
for(int i = 0;i < list.size();i++){
//工作状态
if (list.get(i).getSpeed() != 0f && list.get(i).getWorking() == 1 && list.get(i).getAcc() == 1){
templist.add(list.get(i));
}else if (templist.size() > 3){
//工作状态断了就存一次
workList.add(templist);
templist = new ArrayList<TerminalHistorySpot>();
}else {
templist = new ArrayList<TerminalHistorySpot>();
}
//防止最后一个点也是工作状态
if (i == list.size() - 1 && templist.size() > 0){
workList.add(templist);
}
}
return workList;
}
/*
* 计算里程
* list --- 纠偏后的点集合
* */
public static Double countDayKM(List<TerminalHistorySpot> list){
//总里程
Double dayKm = 0.0d;
/*给数据分页*/
List<List<TerminalHistorySpot>> partition = Lists.partition(list, 18);
for (List<TerminalHistorySpot> terminalHistorySpots : partition) {
//get请求参数
StringBuffer param = new StringBuffer();
param.append("key="+Key);
param.append("&nosteps=1");
if (terminalHistorySpots.size() > 3){
//遍历分页后的list,查询里程
for (int i = 0;i < terminalHistorySpots.size();i++){
if (i == 0){
param.append("&origin="+ String.format("%.6f",terminalHistorySpots.get(i).getLng()) + "," + String.format("%.6f",terminalHistorySpots.get(i).getLat()));
}else if (i == terminalHistorySpots.size() - 1){
param.append("&destination="+ String.format("%.6f",terminalHistorySpots.get(i).getLng()) + "," + String.format("%.6f",terminalHistorySpots.get(i).getLat()));
}else {
param.append("&waypoints="+ String.format("%.6f",terminalHistorySpots.get(i).getLng()) + "," + String.format("%.6f",terminalHistorySpots.get(i).getLat()));
//如果不是倒数第二个就加分号
if (i != terminalHistorySpots.size() - 2){
param.append(";");
}
}
}
//每18个点算一次
String result = HttpClient.sendRequest(drivingURL, param.toString(), HttpClient.METHOD_GET);
//解析结果并保存
JSONObject object = JSONObject.parseObject(result);
if (object.containsKey("infocode") && object.getString("infocode").equals("10000")){
JSONObject route = object.getJSONObject("route");
JSONArray paths = route.getJSONArray("paths");
JSONObject info = (JSONObject)paths.get(0);
String distance = info.getString("distance");
dayKm += Double.parseDouble(distance);
}
}
}
return dayKm;
}
/*
* 调用距离测量服务查询 总里程
* 传入两个list,第一个为起始点list,第二个取第一个点为终点.
* */
public static List<TerminalHistorySpot> queryMileageForGaodeAPI(Double lastMileage, List<TerminalHistorySpot> oldlist1, List<TerminalHistorySpot> oldlist2){
List<TerminalHistorySpot> list = new ArrayList<TerminalHistorySpot>();
//拼接参数字符串
StringBuffer param = new StringBuffer();
StringBuffer originsTemp = new StringBuffer();
StringBuffer destinationTemp = new StringBuffer();
destinationTemp.append(String.format("%.6f", oldlist2.get(0).getLng())+","+ String.format("%.6f", oldlist2.get(0).getLat()));
try {
param.append("key="+Key);
for (TerminalHistorySpot terminalHistorySpot : oldlist1) {
originsTemp.append(String.format("%.6f", terminalHistorySpot.getLng())+","+ String.format("%.6f", terminalHistorySpot.getLat()));
originsTemp.append("|");
}
param.append("&origins="+originsTemp.substring(0,originsTemp.length() - 1));
param.append("&destination="+destinationTemp);
//发送get请求解析数据
String result = HttpClient.sendRequest(queryMileageURL, param.toString(),HttpClient.METHOD_GET);;
//解析数据
JSONObject jsonObject = JSON.parseObject(result);
Integer errcode = Integer.parseInt((String) jsonObject.get("infocode"));
if (errcode == 10000){
//把数组转为json对象
JSONArray results = jsonObject.getJSONArray("results");
//更新里程数,前一个减去当前里程就是当前需要加的里程
for (int i = 0;i < results.size();i++){
JSONObject object = (JSONObject)results.get(i);
Double distance = object.getDouble("distance");
distance = lastMileage - distance;
//如果里程差大于零,则累加.如果小于0,则加100米
if (distance > 0){
//如果大于1000米就舍弃
if(distance > 1000){
oldlist1.get(i).setMileage(oldlist1.get(i).getMileage()+oldlist1.get(i).getSpeed()/120f);
}else {
oldlist1.get(i).setMileage(oldlist1.get(i).getMileage()+distance);
}
}else {
oldlist1.get(i).setMileage(oldlist1.get(i).getMileage()+oldlist1.get(i).getSpeed()/120f);
}
lastMileage = oldlist1.get(i).getMileage();
}
return oldlist1;
}else {
return null;
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/*
* 更新轨迹文件中里程数(速度为0的)
* */
public static List<TerminalHistorySpot> updataMileage(List<TerminalHistorySpot> list, List<TerminalHistorySpot> listnotzore){
//里程参照
Double mileage = list.get(0).getMileage();
//遍历原集合,查找是否有更新的值,如果有就更新,如果没有就和上一条的里程数相同
for (int i = 0;i < list.size();i++) {
//将调高德接口返回的gcj02坐标转换成wgs84坐标
Point pointcorve = new Point();
pointcorve.setLng(list.get(i).getLng());
pointcorve.setLat(list.get(i).getLat());
pointcorve = CoordTransformUtils.gcj02Towgs84(pointcorve);
list.get(i).setLng(pointcorve.getLng());
list.get(i).setLat(pointcorve.getLat());
Long time = list.get(i).getTime();
//查找相同时间戳的数据替换
TerminalHistorySpot terminalForList = findTerminalForList(listnotzore,time);
if (terminalForList != null){
list.get(i).setMileage(terminalForList.getMileage());
mileage = list.get(i).getMileage();
}else {
//如果没有更新的数据就和上一条替换过的里程相同
list.get(i).setMileage(mileage);
}
}
return list;
}
/*发送post请求*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static String doPost(String url, Map<String,Object> map, String charset){
org.apache.http.client.HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = (org.apache.http.client.HttpClient) new SSLClient();
httpPost = new HttpPost(url);
//设置参数
List<NameValuePair> list = new ArrayList<NameValuePair>();
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Entry<String,String> elem = (Entry<String, String>) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));
}
if(list.size() > 0){
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);
httpPost.setEntity(entity);
}
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
/**
* 向指定URL发送GET方法的请求
* @param url 发送请求的URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "/" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/*
* 返回一辆车List<TerminalHistorySpot>数据中符合时间戳值的TerminalHistorySpot对象
* */
public static TerminalHistorySpot findTerminalForList(List<TerminalHistorySpot> list, Long time){
for (TerminalHistorySpot historySpot : list) {
if (historySpot.getTime() != null && historySpot.getTime().toString().equals(time.toString())){
return historySpot;
}
}
return null;
}
/*
* 返回一辆车List<TerminalHistorySpot>数据中大于时间戳值的TerminalHistorySpot对象
* */
public static List<TerminalHistorySpot> findBigTerminalForList(List<TerminalHistorySpot> list, Long time){
List<TerminalHistorySpot> list1 = new ArrayList<TerminalHistorySpot>();
for (TerminalHistorySpot historySpot : list) {
if (historySpot.getTime() != null && historySpot.getTime() > time){
list1.add(historySpot);
}
}
return list1;
}
/**编码*/
public static final String CHAR_ENC = "UTF-8";
/**毫秒到秒*/
public static final int MILLIS_TO_SECONDS = 1000;
/**毫秒到分钟*/
public static final int MILLIS_TO_MINUTES = 60 * 1000;
/**
* 获取当前分钟数
*
* @return
*/
public static long getCurrentTimeOfMinutes() {
return System.currentTimeMillis() / MILLIS_TO_MINUTES;
}
/**
* 将异常信息转成字符串
*
* @param ex
* @return
*/
public static String transExceptionToString(Exception ex) {
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
/**
* 字符串是否为null或空串
*
* @param str
* @return
*/
public static boolean isNullOrEmpty(String str) {
if (null == str || "".equals(str)) {
return true;
}
return false;
}
/**
* url编码
*
* @param parameter
* @return
*/
public static String urlEncode(String parameter) {
try {
return URLEncoder.encode(parameter, CHAR_ENC);
} catch (UnsupportedEncodingException e) {
return parameter;
}
}
/**
* 去除速度为0的点
*
* @return list
*/
public static List<TerminalHistorySpot> clearZero(List<TerminalHistorySpot> list) {
List<TerminalHistorySpot> clearlist = new ArrayList<TerminalHistorySpot>();
for (int i = 0;i < list.size();i++) {
if (list.get(i).getSpeed() != 0f){
clearlist.add(list.get(i));
}
}
return clearlist;
}
/*
* 给历史轨迹数据中,两点距离超过一千米的点,中间进行补点.
*
* */
public static List<TerminalHistorySpot> replenishPointforjuli(List<TerminalHistorySpot> list){
try {
if (list != null && list.size() > 0){
//前一个点的时间戳
Long time = 0l;
//两个坐标点的拼接
String locations="";
String locations2 = "";
//两个点的间距
Double distance = 0.0d;
//补点的个数
int point = 0;
//坐标总差
Double lngcha = 0.0d;
Double latcha = 0.0d;
//时间总差
Long timecha = 0l;
/*遍历历史数据list*/
for (int i = 0;i < list.size();i++) {
TerminalHistorySpot terminalHistorySpot = list.get(i);
if (!locations.equals("") && time != 0){
locations2 = terminalHistorySpot.getLat()+","+terminalHistorySpot.getLng();
//计算距离
distance = distance(locations, locations2);
//如果间距大于1000M
if (distance >= 999){
//计算需要加几个点
point = distance.intValue()/999;
double[] doubles1 = latlng2double(locations);
double[] doubles2 = latlng2double(locations2);
//计算坐标差
lngcha = doubles2[1] - doubles1[1];
latcha = doubles2[0] - doubles1[0];
//计算坐标每次加多少值
Double lngmeicijia = lngcha/(point+1);
Double latmeicijia = latcha/(point+1);
//计算时间差
timecha = terminalHistorySpot.getTime() - time;
//计算每次时间加多少值
Long timemeici = timecha/(point+1);
/*补点*/
for (int j = 0;j<point;j++){
TerminalHistorySpot terminalHistorySpot1 = new TerminalHistorySpot();
terminalHistorySpot1.setLng(terminalHistorySpot.getLng()+lngmeicijia*(j+1));
terminalHistorySpot1.setLat(terminalHistorySpot.getLat()+latmeicijia*(j+1));
terminalHistorySpot1.setTime(terminalHistorySpot.getTime()+timemeici*(j+1));
terminalHistorySpot1.setSpeed(terminalHistorySpot.getSpeed());
terminalHistorySpot1.setAcc(terminalHistorySpot.getAcc());
terminalHistorySpot1.setTc(terminalHistorySpot.getTc());
terminalHistorySpot1.setAzimuth(terminalHistorySpot.getAzimuth());
terminalHistorySpot1.setWorking(terminalHistorySpot.getWorking());
terminalHistorySpot1.setMileage(terminalHistorySpot.getMileage());
list.add(i+j,terminalHistorySpot1);
}
}
}
//结束后更新中间变量
time = list.get(i).getTime();
locations = list.get(i).getLat()+","+list.get(i).getLng();
}
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
/*
* 微调历史轨迹中坐标相同的点的经纬度坐标.只修改纬度
*
* */
public static List<TerminalHistorySpot> replenishPointforzuobiao(List<TerminalHistorySpot> list){
if (list != null && list.size() > 0){
//定义纬度中间变量
Double latTemp = 0.0d;
for (int i = 0;i < list.size();i++) {
TerminalHistorySpot terminalHistorySpot = list.get(i);
if (latTemp != 0.0d){
if (equal(terminalHistorySpot.getLat(),latTemp)){
Double v = Double.parseDouble(String.valueOf(i + 1));
Double f = 10000000d;
Double pianyi = v/f;
list.get(i).setLat(add(terminalHistorySpot.getLat(),pianyi));
}else {
latTemp = terminalHistorySpot.getLat();
}
}else {
latTemp = terminalHistorySpot.getLat();
}
}
}
return list;
}
/*double数加法*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/*double判断相同*/
public static boolean equal(double a, double b) {
if ((a- b> -0.000001) && (a- b) < 0.000001)
return true;
else
return false;
}
/**
* 计算两个经纬度之间的近似距离
* 返回单位:米
*/
public static double distance(double lon1,double lat1,double lon2,double lat2){
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lon1) - rad(lon2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
Math.cos(radLat1)* Math.cos(radLat2)* Math.pow(Math.sin(b/2),2)));
// 取WGS84标准参考椭球中的地球长半径(单位:m)
s = s *6378137.0;
s = s * 10000 / 10000;
return s;
}
public static double distance(String latlng, String latlng2){
double[] p1 = latlng2double(latlng);
double[] p2 = latlng2double(latlng2);
if(p1!=null && p2!=null){
return distance(p1[1],p1[0],p2[1],p2[0]);
}
return 0;
}
public static double[] latlng2double(String latlng){
String[] arr = latlng.split(",");
if(arr.length==2){
try{
double[] r = new double[2];
r[0] = Double.parseDouble(arr[0]);
r[1] = Double.parseDouble(arr[1]);
return r;
}catch(Exception ex){
}finally{
arr = null;
}
}
return null;
}
private static double rad(double d)
{
return d * Math.PI / 180.0;
}
}
历史轨迹工具类:
package com.web.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.socket.bean.Point;
import com.socket.bean.TerminalHistorySpot;
import com.socket.utils.CoordTransformUtils;
import com.web.gps.everydayMileage.entity.HttpClient;
import com.web.gps.everydayMileage.entity.NewTerminalHistorySpot;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
import java.util.Map.Entry;
/**
* 历史轨迹纠偏相关工具类
*/
public class TerminalHistoryUtil {
private static final Logger log = LoggerFactory.getLogger(TerminalHistoryUtil.class);
//声明参数
private static final String Key = "用户申请的KEY";
private static final String initTerminalURL = "https://tsapi.amap.com/v1/track/terminal/add";
private static final String queryTidByTnameURL = "https://tsapi.amap.com/v1/track/terminal/list";
private static final String createTraceURL = "https://tsapi.amap.com/v1/track/trace/add";
private static final String uploadTraceDataURL = "https://tsapi.amap.com/v1/track/point/upload";
private static final String trsearchByTridURL = "https://tsapi.amap.com/v1/track/terminal/trsearch";
private static final String deleteTraceURL = "https://tsapi.amap.com/v1/track/trace/delete";
public static final Integer sid = "KEY下的服务ID";
//private static Map<String,String> localtimemap = new HashMap<String, String>();
/*
* 初始化猎鹰服务,创建轨迹纠偏服务
* (已改为手动创建)
* */
/*public static int initLieyingService(){
//定义参数map,转为json
HashMap param = new HashMap();
param.put("key",Key);
param.put("name",ServiceName);
JSONObject json = new JSONObject(param);
//发送post请求,解析数据
String result = sendPost(json, initServiceURL);
JSONObject jsonObject = JSON.parseObject(result);
Integer sid = (Integer) jsonObject.get("sid");
return sid;
}*/
/*
* 初始化猎鹰服务,创建轨迹终端(车辆)
* trCode -- 设备号
* */
public static boolean initTerminal(int sid, List<String> trCode){
//定义参数map
Map<String,Object> param = null;
try {
for (String tr : trCode) {
param = new HashMap<String, Object>();
param.put("key",Key);
param.put("sid", String.valueOf(sid));
param.put("name",tr);
//发送post请求,解析数据
String result = doPost(initTerminalURL,param,"utf-8");
JSONObject jsonObject = JSON.parseObject(result);
Integer tid = (Integer) jsonObject.get("errcode");
if (tid != 10000 ){
log.info(tr+"创建终端失败!!!");
}else {
log.info(tr+"创建终端成功!!!");
}
}
}catch (Exception e){
e.printStackTrace();
return false;
}
return true;
}
/*
*
* 根据终端name查询终端tid
*
* */
public static Integer queryTidByTname(String Tname) {
//定义参数map,转为json
StringBuffer param = new StringBuffer();
try {
param.append("key="+Key);
param.append("&sid="+ String.valueOf(sid));
param.append("&name="+Tname);
//发送get请求,解析数据
String result = HttpClient.sendRequest(queryTidByTnameURL, param.toString(),HttpClient.METHOD_GET);;
JSONObject jsonObject = JSON.parseObject(result);
Integer state = (Integer) jsonObject.get("errcode");
if (state == 10000) {
JSONObject data = jsonObject.getJSONObject("data");
JSONArray jsonArray = data.getJSONArray("results");
JSONObject jsonObject2 = jsonArray.getJSONObject(0);//获取第1条数据中的tid
String tid = jsonObject2.getString("tid");
return Integer.parseInt(tid);
} else {
return -1;
}
} catch (Exception e) {
return -1;
}
}
/*
* 创建轨迹,返回轨迹ID
*/
public static Integer createTrace(Integer tid){
//定义参数map
Map<String,Object> param = null;
try {
param = new HashMap<String, Object>();
param.put("key",Key);
param.put("sid", String.valueOf(sid));
param.put("tid", String.valueOf(tid));
//发送post请求,解析数据
String result = doPost(createTraceURL,param,"utf-8");
JSONObject jsonObject = JSON.parseObject(result);
Integer errcode = (Integer) jsonObject.get("errcode");
if (errcode == 10000){
JSONObject data = jsonObject.getJSONObject("data");
String trid = data.getString("trid");
return Integer.parseInt(trid);
}else {
return -1;
}
}catch (Exception e){
e.printStackTrace();
return -1;
}
}
/*
* 上传轨迹数据
* */
public static void uploadTraceData(Integer tid, Integer trid, List<TerminalHistorySpot> terminalHistorySpots, HashMap<String, String> localtimemap){
//定义上传点list
List<HashMap> points = new ArrayList<HashMap>();
//定义参数map
Map<String,Object> param = new HashMap<>();
param.put("key",Key);
param.put("sid", String.valueOf(sid));
param.put("tid", String.valueOf(tid));
param.put("trid", String.valueOf(trid));
try {
//添加上传点信息
if (terminalHistorySpots != null && terminalHistorySpots.size() > 0){
for (TerminalHistorySpot terminalHistorySpot:terminalHistorySpots) {
//添加点位详情信息
HashMap infoMap = new HashMap<>();
infoMap.put("location", String.format("%.6f", terminalHistorySpot.getLng())+","+ String.format("%.6f", terminalHistorySpot.getLat()));
infoMap.put("locatetime",terminalHistorySpot.getTime());
HashMap<String, String> map = new HashMap<>();
map.put("timetemp",terminalHistorySpot.getTime().toString());
infoMap.put("props",JSONObject.toJSON(map));
/*infoMap.put("speed",terminalHistorySpot.getSpeed());
infoMap.put("direction",terminalHistorySpot.getAzimuth());*/
points.add(infoMap);
if (localtimemap.containsKey(String.valueOf(terminalHistorySpot.getTime()))){
log.info("存在重复的时间戳!");
}else {
localtimemap.put(String.valueOf(terminalHistorySpot.getTime()), String.format("%.6f", terminalHistorySpot.getLng())+","+ String.format("%.6f", terminalHistorySpot.getLat()));
}
}
JSONArray jsonArray = (JSONArray)JSON.toJSON(points);
String string = jsonArray.toString();
param.put("points", string);
}
//发送post请求,解析数据
String result = doPost(uploadTraceDataURL,param,"utf-8");
JSONObject jsonObject = JSON.parseObject(result);
Integer errcode = (Integer) jsonObject.get("errcode");
if (errcode == 10000){
log.info("上传成功!");
}else {
log.info("上传失败!");
}
}catch (Exception e){
e.printStackTrace();
}
}
/*
* 分页查询云端历史轨迹数据并纠偏补点
* */
public static ArrayList<JSONObject> searchTracksByTrid(Integer tid, Integer trid, Long startTime, Long endTime) throws InterruptedException {
//Json数据集
ArrayList<JSONObject> trackList = new ArrayList<JSONObject>();
//查询页数
Integer page = 1;
//至少执行一次:
JSONObject jsonObject = trsearchByTrid(tid,trid,page,startTime,endTime);
trackList.add(jsonObject);
//通过解析第一次执行返回的数据,判断执行次数
JSONObject data = jsonObject.getJSONObject("data");
if (data == null){
return null;
}
JSONArray tracks = data.getJSONArray("tracks");
JSONObject center = (JSONObject) tracks.get(0);
String counts = center.getString("counts");
Integer count = Integer.parseInt(counts);
if (count >500){
//更新查询页数
page = (count - 500)/500 + 2;
//循环从第二页开始查询
for (int i = 2; i <= page;i++){
JSONObject jsonObjecttemp = trsearchByTrid(tid,trid,i,startTime,endTime);
trackList.add(jsonObjecttemp);
}
}
return trackList;
}
/*
* 查询云端的轨迹数据并纠偏补点
* */
public static JSONObject trsearchByTrid(Integer tid, Integer trid, Integer page, Long startTime, Long endTime){
//定义参数map
StringBuffer param = new StringBuffer();
try {
param.append("key="+Key);
param.append("&sid="+ String.valueOf(sid));
param.append("&tid="+ String.valueOf(tid));
param.append("&trid="+ String.valueOf(trid));
/* param.append("&starttime="+String.valueOf(1575932400000l));
param.append("&endtime="+String.valueOf(1575936000000l));*/
param.append("&correction=denoise=1,mapmatch=1,attribute=1,threshold=0,mode=driving");
param.append("&recoup=1");
param.append("&gap=50");
param.append("&page="+page);
param.append("&pagesize=500");
//发送get请求解析数据
String result = HttpClient.sendRequest(trsearchByTridURL, param.toString(),HttpClient.METHOD_GET);;
//解析数据
JSONObject jsonObject = JSON.parseObject(result);
Integer errcode = (Integer) jsonObject.get("errcode");
if (errcode == 10000){
return jsonObject;
}else {
return null;
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/*
* 删除指定轨迹ID的轨迹信息
*/
public static Boolean deleteTrace(Integer tid, Integer trid){
//定义参数map
Map<String,Object> param = null;
try {
param = new HashMap<String, Object>();
param.put("key",Key);
param.put("sid", String.valueOf(sid));
param.put("tid", String.valueOf(tid));
param.put("trid", String.valueOf(trid));
//发送post请求,解析数据
String result = doPost(deleteTraceURL,param,"utf-8");
JSONObject jsonObject = JSON.parseObject(result);
Integer errcode = (Integer) jsonObject.get("errcode");
if (errcode == 10000){
return true;
}else {
return false;
}
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/*发送post请求*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static String doPost(String url, Map<String,Object> map, String charset){
org.apache.http.client.HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = (org.apache.http.client.HttpClient) new SSLClient();
httpPost = new HttpPost(url);
//设置参数
List<NameValuePair> list = new ArrayList<NameValuePair>();
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Entry<String,String> elem = (Entry<String, String>) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));
}
if(list.size() > 0){
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);
httpPost.setEntity(entity);
}
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
/**
* 向指定URL发送GET方法的请求
* @param url 发送请求的URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "/" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/*
* 返回一辆车List<TerminalHistorySpot>数据中符合时间戳值的TerminalHistorySpot对象
* */
public static TerminalHistorySpot findTerminalForList(List<TerminalHistorySpot> list, Long time){
for (TerminalHistorySpot historySpot : list) {
if (historySpot.getTime() != null && historySpot.getTime().toString().equals(time.toString())){
return historySpot;
}
}
return null;
}
/*
* 返回一辆车List<TerminalHistorySpot>数据中大于时间戳值的TerminalHistorySpot对象
* */
public static List<TerminalHistorySpot> findBigTerminalForList(List<TerminalHistorySpot> list, Long time){
List<TerminalHistorySpot> list1 = new ArrayList<TerminalHistorySpot>();
for (TerminalHistorySpot historySpot : list) {
if (historySpot.getTime() != null && historySpot.getTime() > time){
list1.add(historySpot);
}
}
return list1;
}
/*
* 根据经纬度补纠偏返回后点的附加信息
* result--纠偏返回的信息
* list--源坐标列表
* */
public static List<NewTerminalHistorySpot> pointinfo(ArrayList<JSONObject> result, List<TerminalHistorySpot> list){
//test
int num = 0;
//新坐标list
List<NewTerminalHistorySpot> newPointList = new ArrayList<NewTerminalHistorySpot>();
//解析返回的数据,转化为自定义变量
if (result != null && result.size() > 0){
//先获取返回的状态,判断是否正常调用接口
JSONObject state = (JSONObject)result.get(0);
Integer errcode = state.getInteger("errcode");
//返回状态正常
if(errcode==10000){
/*解析数据*/
for (JSONObject jsonObject : result) {
JSONObject data = jsonObject.getJSONObject("data");
JSONArray tracks = data.getJSONArray("tracks");
JSONObject tracks0 = (JSONObject)tracks.get(0);
JSONArray points = tracks0.getJSONArray("points");
//遍历点位集合数据
NewTerminalHistorySpot newTerminalHistorySpot = null;
for (Object point : points) {
Map<String,Object> map = (Map<String,Object>)(JSONObject)point;
String location = (String)map.get("location");
String[] split = location.split(",");
//保存纠偏返回的经纬度
newTerminalHistorySpot = new NewTerminalHistorySpot();
newTerminalHistorySpot.setLng(Double.parseDouble(split[0]));
newTerminalHistorySpot.setLat(Double.parseDouble(split[1]));
//附加信息状态初始化为0(无附加信息)
newTerminalHistorySpot.setInfostate(0);
//保存新坐标信息
newPointList.add(newTerminalHistorySpot);
}
}
/*遍历源坐标数据,在新列表中找坐标相近的点(test:距离小于10米)*/
if (list != null && list.size() > 0){
//源坐标
String oldlocations = "";
//新坐标
String newlocations = "";
//两个坐标的距离
Double distance = 0d;
//定义新坐标遍历到哪儿一下标,下一轮遍历从此下标开始
int index = 0;
//新坐标如果有了附加信息,则把附加信息状态改为1,下一轮遍历时,从最后一个附加信息状态为1的新坐标往下遍历。
//遍历源坐标
for (TerminalHistorySpot terminalHistorySpot : list) {
oldlocations = terminalHistorySpot.getLat()+","+terminalHistorySpot.getLng();
//定义初始点距为10米
Double m = 100d;
//定义循环标识
Boolean flag = true;
do {
//防止死循环
if(newPointList.size() == index){
break;
}
//遍历新坐标 规定只在当前条数 +- 总条数的 范围
/*每个历史轨迹的数据都不一样*/
for (int i = index ; i < newPointList.size() && i < index + newPointList.size() * 0.15; i++) {
newlocations = newPointList.get(i).getLat()+","+newPointList.get(i).getLng();
//查询两个点的距离
distance = distance(oldlocations, newlocations);
//如果两个点之间距离小于10米,则认为当前点就是纠偏后的源坐标点,把原坐标的信息给新坐标
//找第一个最近的点
if (distance < m && newPointList.get(i).getInfostate() == 0){
num++;
newPointList.get(i).setTime(terminalHistorySpot.getTime());
newPointList.get(i).setAcc(terminalHistorySpot.getAcc());
newPointList.get(i).setAzimuth(terminalHistorySpot.getAzimuth());
newPointList.get(i).setSpeed(terminalHistorySpot.getSpeed());
newPointList.get(i).setMileage(terminalHistorySpot.getMileage());
newPointList.get(i).setWorking(terminalHistorySpot.getWorking());
newPointList.get(i).setTc(terminalHistorySpot.getTc());
newPointList.get(i).setInfostate(1);
//记录下次遍历的开始坐标为此坐标的下一位
index = i + 1;
//结束dowhile循环
flag = false;
//结束本次循环
break;
}
}
if (flag == true){
//每次加
m += 10d;
}
}while (flag);
}
}
}else{
log.error("调用高德抓路服务失败!");
}
}else {
log.info("error--调用高德服务返回结果集为空!");
}
String strings = "";
for (NewTerminalHistorySpot newTerminalHistorySpot : newPointList) {
String string = newTerminalHistorySpot.toString();
strings += string;
}
return newPointList;
}
/*
* 给补了附加信息的新坐标列表补点
*
* */
public static List<TerminalHistorySpot> addPointforNewList(List<NewTerminalHistorySpot> newPointList) {
//返回结果
List<TerminalHistorySpot> terminalHistorySpotsList = new ArrayList<TerminalHistorySpot>();
//定义参照TerminalHistorySpot对象
TerminalHistorySpot lastTerminalHistorySpot = null;
//遍历新坐标列表
for (NewTerminalHistorySpot newTerminalHistorySpot : newPointList) {
TerminalHistorySpot terminalForlocate = null;
//如果有附加信息,则不补点
if (newTerminalHistorySpot.getInfostate() == 1 && !"".equals(newTerminalHistorySpot.getTc())){
terminalForlocate = new TerminalHistorySpot();
//保存纠偏后的当前点位
//将调高德接口返回的gcj02坐标转换成wgs84坐标
Point pointcorve = new Point();
pointcorve.setLng(newTerminalHistorySpot.getLng());
pointcorve.setLat(newTerminalHistorySpot.getLat());
pointcorve = CoordTransformUtils.gcj02Towgs84(pointcorve);
terminalForlocate.setLng(pointcorve.getLng());
terminalForlocate.setLat(pointcorve.getLat());
//保存别的附加信息
terminalForlocate.setTc(newTerminalHistorySpot.getTc());
terminalForlocate.setAzimuth(newTerminalHistorySpot.getAzimuth());
terminalForlocate.setAcc(newTerminalHistorySpot.getAcc());
terminalForlocate.setSpeed(newTerminalHistorySpot.getSpeed());
terminalForlocate.setTime(newTerminalHistorySpot.getTime());
terminalForlocate.setWorking(newTerminalHistorySpot.getWorking());
terminalForlocate.setMileage(newTerminalHistorySpot.getMileage());
//保存源数据到参照变量中
lastTerminalHistorySpot = terminalForlocate;
//添加到list中
terminalHistorySpotsList.add(terminalForlocate);
} else {
//保存纠偏补的点(只有经纬度数据)
if (lastTerminalHistorySpot != null) {
terminalForlocate = new TerminalHistorySpot();
//保存纠偏后的当前点位
//将高德接口返回的gcj02坐标转换成wgs84坐标
Point pointcorve = new Point();
pointcorve.setLng(newTerminalHistorySpot.getLng());
pointcorve.setLat(newTerminalHistorySpot.getLat());
pointcorve = CoordTransformUtils.gcj02Towgs84(pointcorve);
terminalForlocate.setLng(pointcorve.getLng());
terminalForlocate.setLat(pointcorve.getLat());
//补附加信息
if (lastTerminalHistorySpot.getSpeed() == null || lastTerminalHistorySpot.getSpeed() == 0f) {
terminalForlocate.setSpeed(1f);//速度为0时,轨迹不再延申
} else {
terminalForlocate.setSpeed(lastTerminalHistorySpot.getSpeed());
}
terminalForlocate.setAzimuth(lastTerminalHistorySpot.getAzimuth());
terminalForlocate.setAcc(lastTerminalHistorySpot.getAcc());
terminalForlocate.setMileage(lastTerminalHistorySpot.getMileage());
terminalForlocate.setWorking(lastTerminalHistorySpot.getWorking());
terminalForlocate.setTc(lastTerminalHistorySpot.getTc());
terminalForlocate.setTime(lastTerminalHistorySpot.getTime() == null ? 0l : lastTerminalHistorySpot.getTime() + new Long(10l));
lastTerminalHistorySpot = terminalForlocate;
//添加到list中
terminalHistorySpotsList.add(terminalForlocate);
}
}
}
return terminalHistorySpotsList;
}
/*
* 把纠偏结果转换为List<TerminalHistorySpot>
* result--纠偏返回的信息
* */
public static List<TerminalHistorySpot> convertResult(ArrayList<JSONObject> result){
//新坐标list
List<TerminalHistorySpot> newPointList = new ArrayList<TerminalHistorySpot>();
//解析返回的数据,转化为自定义变量
if (result != null && result.size() > 0){
//先获取返回的状态,判断是否正常调用接口
JSONObject state = (JSONObject)result.get(0);
Integer errcode = state.getInteger("errcode");
//返回状态正常
if(errcode==10000){
/*解析数据*/
for (JSONObject jsonObject : result) {
JSONObject data = jsonObject.getJSONObject("data");
JSONArray tracks = data.getJSONArray("tracks");
JSONObject tracks0 = (JSONObject)tracks.get(0);
JSONArray points = tracks0.getJSONArray("points");
//遍历点位集合数据
TerminalHistorySpot newTerminalHistorySpot = null;
for (Object point : points) {
Map<String,Object> map = (Map<String,Object>)(JSONObject)point;
String location = (String)map.get("location");
String[] split = location.split(",");
//保存纠偏返回的经纬度
newTerminalHistorySpot = new TerminalHistorySpot();
newTerminalHistorySpot.setLng(Double.parseDouble(split[0]));
newTerminalHistorySpot.setLat(Double.parseDouble(split[1]));
//保存新坐标信息
newPointList.add(newTerminalHistorySpot);
}
}
}else{
log.error("调用高德抓路服务失败!");
}
}else {
log.info("error--调用高德服务返回结果集为空!");
}
return newPointList;
}
/**编码*/
public static final String CHAR_ENC = "UTF-8";
/**毫秒到秒*/
public static final int MILLIS_TO_SECONDS = 1000;
/**毫秒到分钟*/
public static final int MILLIS_TO_MINUTES = 60 * 1000;
/**
* 获取当前分钟数
*
* @return
*/
public static long getCurrentTimeOfMinutes() {
return System.currentTimeMillis() / MILLIS_TO_MINUTES;
}
/**
* 将异常信息转成字符串
*
* @param ex
* @return
*/
public static String transExceptionToString(Exception ex) {
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
/**
* 字符串是否为null或空串
*
* @param str
* @return
*/
public static boolean isNullOrEmpty(String str) {
if (null == str || "".equals(str)) {
return true;
}
return false;
}
/**
* url编码
*
* @param parameter
* @return
*/
public static String urlEncode(String parameter) {
try {
return URLEncoder.encode(parameter, CHAR_ENC);
} catch (UnsupportedEncodingException e) {
return parameter;
}
}
/**
* 将历史轨迹按时间戳从小到大排序
*
* @return list
*/
public static List<TerminalHistorySpot> sortList(List<TerminalHistorySpot> list) {
Collections.sort(list, new Comparator<TerminalHistorySpot>() {
/**
* int compare(TerminalLocator ter1, TerminalLocator ter2)
* 返回一个基本类型的整型 返回负数表示:ter1小于ter2 返回0表示:ter1和ter2相等 返回正数表示:ter1大于ter2
*/
public int compare(TerminalHistorySpot ter1, TerminalHistorySpot ter2) {
// 按照车辆终端定位设备时间戳从小到大进行升序排列
if (ter1.getTime() > ter2.getTime()) {
return 1;
}
if (ter1.getTime() == ter2.getTime()) {
return 0;
}
return -1;
}
});
//去掉里程为0的点
/*Iterator<TerminalHistorySpot> it = list.iterator();
while(it.hasNext()){
TerminalHistorySpot ter = it.next();
if(ter.getMileage()==null || ter.getMileage()==0 || ter.getMileage().equals("")){
it.remove();
}
}*/
return list;
}
/*
* 给历史轨迹数据中,两点距离超过一千米的点,中间进行补点.
* */
public static List<TerminalHistorySpot> replenishPointforjuli(List<TerminalHistorySpot> list){
try {
if (list != null && list.size() > 0){
//前一个点的时间戳
Long time = 0l;
//两个坐标点的拼接
String locations="";
String locations2 = "";
//两个点的间距
Double distance = 0.0d;
//补点的个数
int point = 0;
//坐标总差
Double lngcha = 0.0d;
Double latcha = 0.0d;
//时间总差
Long timecha = 0l;
/*遍历历史数据list*/
for (int i = 0;i < list.size();i++) {
TerminalHistorySpot terminalHistorySpot = list.get(i);
if (!locations.equals("") && time != 0){
locations2 = terminalHistorySpot.getLat()+","+terminalHistorySpot.getLng();
//计算距离
distance = distance(locations, locations2);
//如果间距大于1000M
if (distance >= 999){
//计算需要加几个点
point = distance.intValue()/999;
double[] doubles1 = latlng2double(locations);
double[] doubles2 = latlng2double(locations2);
//计算坐标差
lngcha = doubles2[1] - doubles1[1];
latcha = doubles2[0] - doubles1[0];
//计算坐标每次加多少值
Double lngmeicijia = lngcha/(point+1);
Double latmeicijia = latcha/(point+1);
//计算时间差
timecha = terminalHistorySpot.getTime() - time;
//计算每次时间加多少值
Long timemeici = timecha/(point+1);
/*补点*/
for (int j = 0;j<point;j++){
TerminalHistorySpot terminalHistorySpot1 = new TerminalHistorySpot();
terminalHistorySpot1.setLng(terminalHistorySpot.getLng()+lngmeicijia*(j+1));
terminalHistorySpot1.setLat(terminalHistorySpot.getLat()+latmeicijia*(j+1));
terminalHistorySpot1.setTime(terminalHistorySpot.getTime()+timemeici*(j+1));
terminalHistorySpot1.setSpeed(terminalHistorySpot.getSpeed());
terminalHistorySpot1.setAcc(terminalHistorySpot.getAcc());
terminalHistorySpot1.setTc(terminalHistorySpot.getTc());
terminalHistorySpot1.setAzimuth(terminalHistorySpot.getAzimuth());
terminalHistorySpot1.setWorking(terminalHistorySpot.getWorking());
terminalHistorySpot1.setMileage(terminalHistorySpot.getMileage());
list.add(i+j,terminalHistorySpot1);
}
}
}
//结束后更新中间变量
time = list.get(i).getTime();
locations = list.get(i).getLat()+","+list.get(i).getLng();
}
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
/*
* 微调历史轨迹中坐标相同的点的经纬度坐标.只修改纬度
*
* */
public static List<TerminalHistorySpot> replenishPointforzuobiao(List<TerminalHistorySpot> list){
if (list != null && list.size() > 0){
//定义纬度中间变量
Double latTemp = 0.0d;
for (int i = 0;i < list.size();i++) {
TerminalHistorySpot terminalHistorySpot = list.get(i);
if (latTemp != 0.0d){
if (equal(terminalHistorySpot.getLat(),latTemp)){
Double v = Double.parseDouble(String.valueOf(i + 1));
Double f = 10000000d;
Double pianyi = v/f;
list.get(i).setLat(add(terminalHistorySpot.getLat(),pianyi));
}else {
latTemp = terminalHistorySpot.getLat();
}
}else {
latTemp = terminalHistorySpot.getLat();
}
}
}
return list;
}
/*double数加法*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/*double判断相同*/
public static boolean equal(double a, double b) {
if ((a- b> -0.000001) && (a- b) < 0.000001)
return true;
else
return false;
}
/**
* 计算两个经纬度之间的近似距离
* 返回单位:米
*/
public static double distance(double lon1,double lat1,double lon2,double lat2){
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lon1) - rad(lon2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
Math.cos(radLat1)* Math.cos(radLat2)* Math.pow(Math.sin(b/2),2)));
// 取WGS84标准参考椭球中的地球长半径(单位:m)
s = s *6378137.0;
s = s * 10000 / 10000;
return s;
}
public static double distance(String latlng, String latlng2){
double[] p1 = latlng2double(latlng);
double[] p2 = latlng2double(latlng2);
if(p1!=null && p2!=null){
return distance(p1[1],p1[0],p2[1],p2[0]);
}
return 0;
}
public static double[] latlng2double(String latlng){
String[] arr = latlng.split(",");
if(arr.length==2){
try{
double[] r = new double[2];
r[0] = Double.parseDouble(arr[0]);
r[1] = Double.parseDouble(arr[1]);
return r;
}catch(Exception ex){
}finally{
arr = null;
}
}
return null;
}
private static double rad(double d)
{
return d * Math.PI / 180.0;
}
/**
* @Description:获取某个目录下所有直接下级文件,不包括目录下的子目录的下的文件,所以不用递归获取
*/
public static List<String> getFiles(String path) {
List<String> files = new ArrayList<String>();
File file = new File(path);
File[] tempList = file.listFiles();
for (int i = 0; i < tempList.length; i++) {
//如果是文件,获取名称
if (tempList[i].isFile()) {
files.add(tempList[i].getName());
//files.add(tempList[i].toString());
//文件名,不包含路径
}
//如果是文件夹
if (tempList[i].isDirectory()) {
//暂无操作
}
}
return files;
}
}
日期工具类:
/**
*
*/
package com.web.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 日期工具类
*/
public class DateUtil {
private static transient int gregorianCutoverYear = 1582;
/**
* 闰年中每月天数
*/
private static final int[] DAYS_P_MONTH_LY = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/**
* 非闰年中每月天数
*/
private static final int[] DAYS_P_MONTH_CY = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/**
* 代表数组里的年、月、日
*/
private static final int Y = 0, M = 1, D = 2;
public static final String YYYYMMDD_TIME="yyyy-MM-dd HH:mm:ss";
public static final String YYYYMMDD="yyyy-MM-dd";
public static SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDD_TIME);
public static SimpleDateFormat sdfymd = new SimpleDateFormat(YYYYMMDD);
/**
* 获取前一天的日期
*/
public static final Date getYesterdayDate() {
Date date = new Date();
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
// 把日期往后增加一天.整数往后推,负数往前移动
calendar.add(calendar.DATE, -1);
// 这个时间就是日期往前推一天的结果
date = calendar.getTime();
return date;
}
/**
* 将代表日期的字符串分割为代表年月日的整形数组
*
* @param date
* @return
*/
public static int[] splitYMD(String date) {
date = date.replace("-", "");
int[] ymd = {0, 0, 0};
ymd[Y] = Integer.parseInt(date.substring(0, 4));
ymd[M] = Integer.parseInt(date.substring(4, 6));
ymd[D] = Integer.parseInt(date.substring(6, 8));
return ymd;
}
/**
* 检查传入的参数代表的年份是否为闰年
*
* @param year
* @return
*/
public static boolean isLeapYear(int year) {
return year >= gregorianCutoverYear ?
((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) : (year % 4 == 0);
}
/**
* 日期加1天
*
* @param year
* @param month
* @param day
* @return
*/
private static int[] addOneDay(int year, int month, int day) {
if (isLeapYear(year)) {
day++;
if (day > DAYS_P_MONTH_LY[month - 1]) {
month++;
if (month > 12) {
year++;
month = 1;
}
day = 1;
}
} else {
day++;
if (day > DAYS_P_MONTH_CY[month - 1]) {
month++;
if (month > 12) {
year++;
month = 1;
}
day = 1;
}
}
int[] ymd = {year, month, day};
return ymd;
}
/**
* 将不足两位的月份或日期补足为两位
*
* @param decimal
* @return
*/
public static String formatMonthDay(int decimal) {
DecimalFormat df = new DecimalFormat("00");
return df.format(decimal);
}
/**
* 将不足四位的年份补足为四位
*
* @param decimal
* @return
*/
public static String formatYear(int decimal) {
DecimalFormat df = new DecimalFormat("0000");
return df.format(decimal);
}
/**
* 计算两个日期之间相隔的天数
*
* @param begin
* @param end
* @return
* @throws ParseException
*/
public static long countDay(String begin, String end) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate, endDate;
long day = 0;
try {
beginDate = format.parse(begin);
endDate = format.parse(end);
day = (endDate.getTime() - beginDate.getTime()) / (24 * 60 * 60 * 1000);
} catch (ParseException e) {
e.printStackTrace();
}
return day;
}
/**
* 以循环的方式计算日期
* @param beginDate
* @param endDate
* @return
*/
public static List<String> getEveryday(String beginDate, String endDate) {
long days = countDay(beginDate, endDate);
int[] ymd = splitYMD(beginDate);
List<String> everyDays = new ArrayList<String>();
everyDays.add(beginDate);
for (int i = 0; i < days; i++) {
ymd = addOneDay(ymd[Y], ymd[M], ymd[D]);
everyDays.add(formatYear(ymd[Y]) + "-" + formatMonthDay(ymd[M]) + "-" + formatMonthDay(ymd[D]));
}
return everyDays;
}
/**
* 传String类型的时间,指定时间格式,返回指定格式 date类型的时间
* @param sdate
* @return
*/
public static Date getdateByStringFormat(String sdate,String format){
if(!StringUtils.isNotBlank(format)){
format = YYYYMMDD_TIME;
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
if(StringUtils.isNotBlank(sdate)){
try {
Date date = sdf.parse(sdate);
return date;
}catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 到当前日期有多少日
* @param d 输入月份
* @return
*/
public static String formatData(Date d,String format){
if(d != null){
if(format == null || "".equals(format)){
format = "yyyy-MM-dd HH:mm:ss";
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
String time = sdf.format(d);
return time;
}else{
return null;
}
}
/**今天开始时间
* @return
*/
public static Date getStartTime(){
Calendar todayStart = Calendar.getInstance();
todayStart.set(Calendar.HOUR_OF_DAY, 0);
todayStart.set(Calendar.MINUTE, 0);
todayStart.set(Calendar.SECOND, 0);
todayStart.set(Calendar.MILLISECOND, 0);
return todayStart.getTime();
}
/**
* 今天结束时间
* @return
*/
public static Date getEndTime(){
Calendar todayEnd = Calendar.getInstance();
todayEnd.set(Calendar.HOUR_OF_DAY, 23);
todayEnd.set(Calendar.MINUTE, 59);
todayEnd.set(Calendar.SECOND, 59);
todayEnd.set(Calendar.MILLISECOND, 999);
return todayEnd.getTime();
}
/**
* 获取一个月的最后一天
* @param year
* @param month
* @return
*/
public static String getLastDayOfMonth(int year, int month) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
return DateUtil.formatData(cal.getTime(),YYYYMMDD);
}
/**
* 获取一个月的第一天
* @param year
* @param month
* @return
*/
public static String getFirstDayOfMonth(int year, int month) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1);
cal.set(Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DATE));
return DateUtil.formatData(cal.getTime(),YYYYMMDD);
}
/**
* 获取过去第几天的日期
*
* @param past
* @return
*/
public static String getPastDate(int past) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
Date today = calendar.getTime();
return DateUtil.formatData(today,YYYYMMDD);
}
/**
* 获取本季度开始时间 返回字符串 2018-04-01
* @return
*/
public static String getCurrentQuarterStartDate() {
Calendar c = Calendar.getInstance();
int currentMonth = c.get(Calendar.MONTH) + 1;
SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
String now = null;
try {
if (currentMonth >= 1 && currentMonth <= 3) {
c.set(Calendar.MONTH, 0);
}else if (currentMonth >= 4 && currentMonth <= 6) {
c.set(Calendar.MONTH, 3);
}else if (currentMonth >= 7 && currentMonth <= 9) {
c.set(Calendar.MONTH, 6);
}else if (currentMonth >= 10 && currentMonth <= 12) {
c.set(Calendar.MONTH, 9);
}
c.set(Calendar.DATE, 1);
now = shortSdf.format(c.getTime());
} catch (Exception e) {
e.printStackTrace();
}
return now;
}
/**
* 获取本季度开始时间
* @return
*/
public static Date getCurrentQuarterStartTime() {
Calendar c = Calendar.getInstance();
int currentMonth = c.get(Calendar.MONTH) + 1;
SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
Date now = null;
try {
if (currentMonth >= 1 && currentMonth <= 3) {
c.set(Calendar.MONTH, 0);
} else if (currentMonth >= 4 && currentMonth <= 6) {
c.set(Calendar.MONTH, 3);
} else if (currentMonth >= 7 && currentMonth <= 9) {
c.set(Calendar.MONTH, 6);
} else if (currentMonth >= 10 && currentMonth <= 12) {
c.set(Calendar.MONTH, 9);
}
c.set(Calendar.DATE, 0);
now = longSdf.parse(shortSdf.format(c.getTime()) + " 00:00:00");
} catch (Exception e) {
e.printStackTrace();
}
return now;
}
/**
* 当前季度的结束时间,即2012-03-31 23:59:59
*
* @return
*/
public static Date getCurrentQuarterEndTime() {
Calendar cal = Calendar.getInstance();
cal.setTime(getCurrentQuarterStartTime());
cal.add(Calendar.MONTH, 3);
return cal.getTime();
}
/**
* 当前季度的结束时间,即2012-03-31 23:59:59
*
* @return
*/
public static String getCurrentQuarterEndDate() {
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.setTime(getCurrentQuarterStartTime());
cal.add(Calendar.MONTH, 2);
int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
cal.add(Calendar.DAY_OF_MONTH, lastDay);
return shortSdf.format(cal.getTime());
}
/**
* 获得本月的开始时间,即2012-01-01 00:00:00
*
* @return
*/
public static Date getCurrentMonthStartTime() {
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
Date now = null;
try {
c.set(Calendar.DATE, 1);
now = shortSdf.parse(shortSdf.format(c.getTime()));
} catch (Exception e) {
e.printStackTrace();
}
return now;
}
/**
* 获得本月的结束时间,即2012-01-31 23:59:59
*
* @return
*/
public static Date getCurrentMonthEndTime() {
SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
Date now = null;
try {
c.set(Calendar.DATE, 1);
c.add(Calendar.MONTH, 1);
c.add(Calendar.DATE, -1);
now = longSdf.parse(shortSdf.format(c.getTime()) + " 23:59:59");
} catch (Exception e) {
e.printStackTrace();
}
return now;
}
/**
* 获得本月的开始时间,即2012-01-01 00:00:00
*
* @return
*/
public static Date getLastMonthStartTime() {
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
Date now = null;
try {
c.add(Calendar.MONTH, -1);
c.set(Calendar.DATE, 1);
now = shortSdf.parse(shortSdf.format(c.getTime()));
} catch (Exception e) {
e.printStackTrace();
}
return now;
}
/**
* 获得本月的结束时间,即2012-01-31 23:59:59
*
* @return
*/
public static Date getLastMonthEndTime() {
SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
Date now = null;
try {
c.set(Calendar.DATE, 1);
//c.add(Calendar.MONTH, 0);
c.add(Calendar.DATE, -1);
now = longSdf.parse(shortSdf.format(c.getTime()) + " 23:59:59");
} catch (Exception e) {
e.printStackTrace();
}
return now;
}
//获取今年是哪一年
public static Integer getNowYear() {
Date date = new Date();
GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
gc.setTime(date);
return Integer.valueOf(gc.get(1));
}
//获取本年的开始时间
public static Date getBeginDayOfYear() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, getNowYear());
// cal.set
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DATE, 1);
return getDayStartTime(cal.getTime());
}
//获取本年的结束时间
public static Date getEndDayOfYear() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, getNowYear());
cal.set(Calendar.MONTH, Calendar.DECEMBER);
cal.set(Calendar.DATE, 31);
return getDayEndTime(cal.getTime());
}
//获取某个日期的开始时间
public static Timestamp getDayStartTime(Date d) {
Calendar calendar = Calendar.getInstance();
if (null != d) calendar.setTime(d);
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
return new Timestamp(calendar.getTimeInMillis());
}
//获取某个日期的结束时间
public static Timestamp getDayEndTime(Date d) {
Calendar calendar = Calendar.getInstance();
if (null != d) calendar.setTime(d);
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
calendar.set(Calendar.MILLISECOND, 999);
return new Timestamp(calendar.getTimeInMillis());
}
//获取某个日期的开始时间
public static Date getDateForBefore1Hour(Date d) {
Calendar calendar = Calendar.getInstance();
if (null != d){
calendar.setTime(d);
}
calendar.set(Calendar.HOUR_OF_DAY,calendar.get(Calendar.HOUR_OF_DAY)-1);
return new Timestamp(calendar.getTimeInMillis());
}
/**
* 获得该月最后一天
* @param year
* @param month
* @return
*/
public static String getLastDayOfMonth2(int year,int month) {
Calendar cal = Calendar.getInstance();
//设置年份
cal.set(Calendar.YEAR, year);
//设置月份
cal.set(Calendar.MONTH, month - 1);
//获取某月最大天数
int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
//设置日历中月份的最大天数
cal.set(Calendar.DAY_OF_MONTH, lastDay);
//格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String lastDayOfMonth = sdf.format(cal.getTime());
return lastDayOfMonth;
}
public static void main(String[] args) {
// System.out.println(DateUtils.formateDate(DateUtil.getBeginDayOfYear(),"yyyy-MM-dd"));
// System.out.println(DateUtils.formateDate(DateUtil.getEndDayOfYear(),"yyyy-MM-dd"));
// System.out.println(getLastDayOfMonth2(2018,9));
// System.out.println(getCurrentQuarterEndDate());
System.out.println(getDateForBefore1Hour(new Date()));
}
/**
* 判断时间格式是否正确
* @param str
* @return
*/
public static boolean isValidDate(String str,String format) {
if(!StringUtils.isNotBlank(format)){
format = YYYYMMDD_TIME;
}
DateFormat formatter = new SimpleDateFormat(format);
try{
Date date = (Date)formatter.parse(str);
return str.equals(formatter.format(date));
}catch(Exception e){
return false;
}
}
/**
* date2比date1多的天数
* @param date1
* @param date2
* @return
*/
public static int differentDays(Date date1,Date date2)
{
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
int day1= cal1.get(Calendar.DAY_OF_YEAR);
int day2 = cal2.get(Calendar.DAY_OF_YEAR);
int year1 = cal1.get(Calendar.YEAR);
int year2 = cal2.get(Calendar.YEAR);
if(year1 != year2) //同一年
{
int timeDistance = 0 ;
for(int i = year1 ; i < year2 ; i ++)
{
if(i%4==0 && i%100!=0 || i%400==0) //闰年
{
timeDistance += 366;
}
else //不是闰年
{
timeDistance += 365;
}
}
return timeDistance + (day2-day1) ;
}
else //不同年
{
System.out.println("判断day2 - day1 : " + (day2-day1));
return day2-day1;
}
}
public static HashMap<String,String> createAllDays(String startDate, String endDate){
HashMap<String,String> allDays = new HashMap<String,String>();
try{
for(int i = 0; i < 30; i++) {
Date date = sdfymd.parse(startDate);
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
// 把日期增加一天.整数往后推,负数往前移动
calendar.add(calendar.DATE, 1);
// 这个时间就是日期往前推一天的结果
String dateStr = sdfymd.format(calendar.getTime());
allDays.put(dateStr, dateStr);
if (dateStr.equals(endDate)) {
return allDays;
}
}
}catch (Exception e){
e.printStackTrace();
}
return allDays;
}
/**
* 获得昨天的日期
* @return
*/
public static String getYestDay() {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
Calendar cal=Calendar.getInstance();
cal.add(Calendar.DATE,-1);
Date d=cal.getTime();
return sdf.format(d);
}
/**
* 获得昨天的日期
* @param date
* @return
*/
public static Date string2Date(String date) {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
return new Date();
}
}
public static String getPrevQuart(int m){
String mon = "";
if(12 == m || m < 3){
mon = "09,10,11";
}else if(3 <= m && m < 6){
mon = "12,01,02";
}else if(6 <= m && m < 9){
mon = "03,04,05";
}else{
mon = "06,07,08";
}
return mon;
}
/**
*
* @param i 过去几天 例如-1 表示过去一天 -2表示过去2天 2表示未来两天
* @return
*/
public static Date getStartTime(int i){
Calendar todayStart = Calendar.getInstance();
todayStart.add(Calendar.DATE,i);
todayStart.set(Calendar.HOUR_OF_DAY, 0);
todayStart.set(Calendar.MINUTE, 0);
todayStart.set(Calendar.SECOND, 0);
todayStart.set(Calendar.MILLISECOND, 0);
return todayStart.getTime();
}
/**
*
* @param i 过去几天 例如-1 表示过去一天 -2表示过去2天 2表示未来两天
* @return
*/
public static Date getEndTime(int i){
Calendar todayEnd = Calendar.getInstance();
todayEnd.add(Calendar.DATE,i);
todayEnd.set(Calendar.HOUR_OF_DAY, 23);
todayEnd.set(Calendar.MINUTE, 59);
todayEnd.set(Calendar.SECOND, 59);
todayEnd.set(Calendar.MILLISECOND, 999);
return todayEnd.getTime();
}
public static String getAdress(String lat, String lng) throws MalformedURLException {
long start=System.currentTimeMillis();
BufferedReader in = null;
URL tirc = new URL("http://api.map.baidu.com/geocoder/v2/?location="+lat+","+lng+"&output=json&pois=1&ak=KXIElFezuIhKnR45AbOvEwGj");
String address = null;
try {
in = new BufferedReader(new InputStreamReader(tirc.openStream(),"UTF-8"));
String res;
StringBuilder sb = new StringBuilder();
while((res = in.readLine())!=null){
sb.append(res.trim());
}
String str = sb.toString();
ObjectMapper mapper = new ObjectMapper();
if(org.apache.commons.lang3.StringUtils.isNotEmpty(str)){
JsonNode jsonNode = mapper.readTree(str);
jsonNode.findValue("status").toString();
JsonNode resultNode = jsonNode.findValue("result");
address = resultNode.findValue("formatted_address").toString();
System.out.println(address);
address = address.substring(1,address.length()-1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println(System.currentTimeMillis()-start);
return address;
}
/**
* 获取从当月开始往前推12个月的值
* @return
*/
public static List<String> getTwelvemonthValue(){
List<String> list = new ArrayList<>();
Date date = new Date();
for(int i = 11; i >= 0; i--){
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH,-i);//减i个月
// date = calendar.getTime();
list.add((calendar.getTime().getMonth()+1)+"月");
}
return list;
}
}
HTTP工具类:发送get请求等
package com.web.gps.everydayMileage.entity;
import com.web.utils.CommonUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
/**
* http客户端
*
*/
public class HttpClient {
public static final String METHOD_POST = "POST";
public static final String METHOD_GET = "GET";
/**
* HTTP连接超时,单位:毫秒
*/
private static final int CONNECT_TIMEOUT = 5 * 1000;
/**
* HTTP读超时,单位:毫秒
*/
private static final int READ_TIMEOUT = 5 * 1000;
/**
* 是否开启HTTPS
*/
public static boolean isEnableHttps = false;
/**编码*/
public static final String CHAR_ENC = "UTF-8";
/**
* 发送请求
* @param url
* @param parameters
* @param method
* @return
* @throws IOException
*/
public static String sendRequest(String url, String parameters, String method) {
HttpURLConnection urlConnection = null;
try {
if (isEnableHttps) {
urlConnection = initHttps(url, parameters, method);
} else {
urlConnection = initHttp(url, parameters, method);
}
} catch (IOException e) {
StringBuilder result = new StringBuilder();
result.append("{\"status\":").append("-1").append(",").append("\"message\":")
.append("\"").append(CommonUtils.transExceptionToString(e)).append("\"}");
return result.toString();
}
String result = null;
switch (method) {
case METHOD_POST:
result = sendPostRequest(urlConnection, parameters);
break;
case METHOD_GET:
result = sendGetRequest(urlConnection);
break;
default:
break;
}
return result;
}
/**
* 初始化HTTPS连接
*
* @param url
* @param parameters
* @param method
* @return
* @throws IOException
*/
private static HttpsURLConnection initHttps(String url, String parameters, String method) throws IOException {
URL httpUrl = initURL(url, parameters, method);
HttpsURLConnection urlConnection = (HttpsURLConnection) httpUrl.openConnection();
initConnection(urlConnection, method);
((HttpsURLConnection) urlConnection).setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
return hVerifier.verify(hostname, session);
}
});
return urlConnection;
}
/**
* 初始化HTTP
*
* @param url
* @param parameters
* @param method
* @return
* @throws IOException
*/
private static HttpURLConnection initHttp(String url, String parameters, String method) throws IOException {
URL httpUrl = initURL(url, parameters, method);
HttpURLConnection urlConnection = (HttpURLConnection) httpUrl.openConnection();
initConnection(urlConnection, method);
return urlConnection;
}
/**
* 初始化URL
*
* @param path
* @param parameters
* @param method
* @return
* @throws MalformedURLException
*/
private static URL initURL(String path, String parameters, String method) throws MalformedURLException {
URL url = null;
if (METHOD_GET.equalsIgnoreCase(method)) {
url = new URL(path + "?" + parameters);
} else {
url = new URL(path);
}
return url;
}
/**
* 初始化Connection(HttpsURLConnection继承于HttpURLConnection)
*
* @param urlConnection
* @param method
* @throws ProtocolException
*/
private static void initConnection(HttpURLConnection urlConnection, String method) throws ProtocolException {
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
urlConnection.setRequestMethod(method);
urlConnection.setConnectTimeout(CONNECT_TIMEOUT);
urlConnection.setReadTimeout(READ_TIMEOUT);
urlConnection.setUseCaches(false);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
}
/**
* 发送get请求
*
* @param urlConnection
* @return
*/
private static String sendGetRequest(HttpURLConnection urlConnection) {
InputStream inStream = null;
try {
int responseCode = urlConnection.getResponseCode();
if (HttpURLConnection.HTTP_OK == responseCode) {
inStream = urlConnection.getInputStream();
return handleInputStream(inStream);
} else {
return handleHttpResponseCode(responseCode, urlConnection.getResponseMessage());
}
} catch (IOException ex) {
return handleIOException(ex);
} finally {
if (null != inStream) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 发送post请求
*
* @param urlConnection
* @param parameters
* @return
*/
public static String sendPostRequest(HttpURLConnection urlConnection, String parameters) {
OutputStream outStream = null;
InputStream inStream = null;
try {
outStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream,CHAR_ENC));
writer.write(parameters);
writer.flush();
writer.close();
urlConnection.connect();
int responseCode = urlConnection.getResponseCode();
if (HttpURLConnection.HTTP_OK == responseCode) {
inStream = urlConnection.getInputStream();
return handleInputStream(inStream);
} else {
return handleHttpResponseCode(responseCode, urlConnection.getResponseMessage());
}
} catch (IOException ex) {
return handleIOException(ex);
} finally {
try {
if (null != outStream) {
outStream.close();
}
if (null != inStream) {
inStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 解析输入流
*
* @param inputStream
*
* @return
*
* @throws IOException
*/
private static String handleInputStream(InputStream inputStream) {
BufferedReader bufferedReader=null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
StringBuffer result = new StringBuffer("");
String line;
try {
while (null != (line = bufferedReader.readLine())) {
result.append(line);
}
} catch (IOException ex) {
return handleIOException(ex);
} finally {
if (null != bufferedReader) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
bufferedReader = null;
}
}
}
return result.toString();
}
/**
* 处理IO异常
*
* @param ex
* @return
*/
private static String handleIOException(IOException ex) {
StringBuilder result = new StringBuilder();
result.append("{\"status\":").append("-1").append(",").append("\"message\":").append("\"")
.append(CommonUtils.transExceptionToString(ex)).append("\"}");
return result.toString();
}
/**
* 处理http非ok的响应状态码
*
* @param responseCode
* @param responseString
* @return
*/
private static String handleHttpResponseCode(int responseCode, String responseString) {
StringBuilder result = new StringBuilder();
result.append("{\"status\":").append(String.valueOf(responseCode)).append(",").append("\"message\":")
.append("\"").append(responseString).append("\"}");
return result.toString();
}
}
获取历史轨迹的方法
package com.web.gps.everydayMileage.service.impl;
import com.socket.bean.TerminalHistorySpot;
import com.socket.util.gps.BaiduGPSCorrect;
import com.socket.util.gps.GpsCorrect;
import com.socket.utils.OtherUtils;
import com.web.gps.everydayMileage.entity.HttpClient;
import com.web.gps.everydayMileage.service.RoadService;
import com.web.gps.lushu.service.impl.LushuServiceImpl;
import net.sf.json.JSONObject;
import org.json.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @ClassName RoadServiceImpl
* @Description 抓路服务,校准历史轨迹
*
*/
@Service("roadService")
public class RoadServiceImpl implements RoadService {
/** 高德抓路服务的url请求地址,请求方式为GET */
public static final String GAODE_URL= "https://restapi.amap.com/v3/autograsp";
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static AtomicLong mSequenceGenerator = new AtomicLong();
private static AtomicInteger successCounter = new AtomicInteger();
private static AtomicInteger failedCounter = new AtomicInteger();
static Logger log = LoggerFactory.getLogger(LushuServiceImpl.class);
/**
* 根据历史轨迹点中的经纬度、时间、方向、速度等信息,调用高德的抓路服务,将坐标点匹配到道路之上
* @param terminalHistorySpotList
* @param userKey 调用高德服务的用户key
* @param termCode 设备号,用来标识车辆
* @return JSONObject
*/
@Override
public JSONObject adjustHistoryTrackByGaoDe(
List<TerminalHistorySpot> terminalHistorySpotList, String userKey, String termCode) {
/**
* key 用户唯一标识,用户在高德地图官网申请
carId 填写key的后四位+企业车辆唯一编号,如“abcd123456”
locations 用于抓路的经纬度坐标,要求每次传入按utc时间排列的三个或三个以上经纬度坐标对,且相邻经纬度gps时间间隔小于300s,距离小于1km
坐标的经纬度之间用","间隔,坐标对之间用"|"间隔
time gps时间,要求为utc时间,与参数locations指定的坐标点一一对应,gps时间个数与坐标点数量一致
direction 车辆的方位角,与参数locations指定的坐标点一一对应,方位角个数与坐标点数量一致
以正北方向为0度,沿顺时针方向为正值,取值范围[0,360),精确到小数点后一位
speed 车辆行驶速度,与参数locations指定的坐标点一一对应,速度值个数与坐标点数量一致,单位:km/h
*/
//根据terminalHistorySpotList中的数据拼接locations、time、direction和speed
StringBuffer locations=new StringBuffer();
StringBuffer time=new StringBuffer();
StringBuffer direction=new StringBuffer();
StringBuffer speed=new StringBuffer();
for (TerminalHistorySpot terminalHistorySpot : terminalHistorySpotList) {
locations.append(terminalHistorySpot.getLng()+",");
locations.append(terminalHistorySpot.getLat()+"|");
time.append(String.valueOf(terminalHistorySpot.getTime()/1000)+",");
direction.append(terminalHistorySpot.getAzimuth()+",");
speed.append(terminalHistorySpot.getSpeed()+",");
}
String carId = userKey.substring(userKey.length()-4,userKey.length())+termCode;
//去掉拼接字符串的最后一个字符“,”或“|”
locations.deleteCharAt(locations.length()-1);
time.deleteCharAt(time.length()-1);
direction.deleteCharAt(direction.length()-1);
speed.deleteCharAt(speed.length()-1);
//拼接请求的url参数
StringBuffer parameters = new StringBuffer();
parameters.append("carid="+carId);
parameters.append("&locations="+locations);
parameters.append("&time="+time);
parameters.append("&direction="+direction);
parameters.append("&speed="+speed);
parameters.append("&output=xml");
parameters.append("&key="+userKey);
//发送http请求
String result = HttpClient.sendRequest(GAODE_URL, parameters.toString(), HttpClient.METHOD_GET);
//将请求的结果转换成json对象,并返回
JSONObject json = JSONObject.fromObject(XML.toJSONObject(result).get("response").toString());
return json;
}
/**
* 将历史轨迹按时间戳从小到大排序
* @return list
*/
public List<TerminalHistorySpot> sortList(List<TerminalHistorySpot> list) {
Collections.sort(list, new Comparator<TerminalHistorySpot>() {
/**
* int compare(TerminalLocator ter1, TerminalLocator ter2)
* 返回一个基本类型的整型 返回负数表示:ter1小于ter2 返回0表示:ter1和ter2相等 返回正数表示:ter1大于ter2
*/
public int compare(TerminalHistorySpot ter1, TerminalHistorySpot ter2) {
// 按照车辆终端定位设备时间戳从小到大进行升序排列
if (ter1.getTime() > ter2.getTime()) {
return 1;
}
if (ter1.getTime() == ter2.getTime()) {
return 0;
}
return -1;
}
});
return list;
}
/**查询多车多天的历史轨迹*/
public Map<String, Map<String, List<TerminalHistorySpot>>> queryHistoricalTrajectory(
String[] termCodes, Date startDate, Date endDate, String mapType) {
// 获得要查询的天数集合
List<Date> dateResult = getBetweenDates(startDate, endDate);
// 查询
Map<String, Map<String, List<TerminalHistorySpot>>> tcMap = loadFile(
termCodes, dateResult, mapType,startDate.getTime(),endDate.getTime());
return tcMap;
}
/**
* 查询文件数据,根据设备号分组,每组设备号根据时间进行分组
* @param termCodes 多个设备号
* @param dateResult 查询哪些天的数据
* @param mapType 数据类型 baidu,gaode
* @param startTime 开始时间
* @param endTime 结束时间
* @return
*/
public Map<String, Map<String, List<TerminalHistorySpot>>> loadFile(
String[] termCodes, List<Date> dateResult, String mapType, Long startTime, Long endTime) {
Long ss = System.currentTimeMillis();
SimpleDateFormat daySdf = new SimpleDateFormat("yyyy-MM-dd");
Map<String, Map<String, List<TerminalHistorySpot>>> tcMap = new HashMap<String, Map<String, List<TerminalHistorySpot>>>();
for (String termCode : termCodes) {
Map<String, List<TerminalHistorySpot>> dateMap = new TreeMap<String, List<TerminalHistorySpot>>();
for (Date date : dateResult) {
String day = daySdf.format(date);
// 获取文件存放地址
String path = OtherUtils.gpsHistorySpot(date);
List<String> jsonList = readLine(path + "Data" + termCode + ".txt");
List<TerminalHistorySpot> list = new ArrayList<TerminalHistorySpot>();
for (String json : jsonList) {
try {
TerminalHistorySpot ths = com.alibaba.fastjson.JSONObject.parseObject(json, TerminalHistorySpot.class);
//如果当前点的时间不在范围内则不放到list中
if (ths != null && ths.time != null && ths.time >= startTime && ths.time <= endTime) {
if(ths.getLat() <= 1 || ths.getLng() <= 1){
log.info("当前点不在国内,舍弃-spot not in China----》");
}else{
// 转换坐标
if ("baidu".equals(mapType)) {
double[] latlng = BaiduGPSCorrect.gps_encrypt(ths.getLat(), ths.getLng());
ths.setLng(latlng[1]);
ths.setLat(latlng[0]);
} else if ("gaode".equals(mapType)) {
double[] latlng = new double[2];
GpsCorrect.transform(ths.getLat(), ths.getLng(), latlng);
ths.setLng(latlng[1]);
ths.setLat(latlng[0]);
}
list.add(ths);
}
}
} catch (Exception e) {
log.error("read file latlng读取文件转换坐标异常:",e);
}
}
if(list != null && list.size() > 0){
// 按时间早晚排序坐标
TerminalHistorySpot comparator = new TerminalHistorySpot();
Collections.sort(list, comparator);
dateMap.put(day, list);
}
}
tcMap.put(termCode, dateMap);
}
log.info("历史轨迹查询 总共耗时:" + (System.currentTimeMillis() - ss));
return tcMap;
}
/**
* 获取两个日期之间的日期
* @param start 开始日期
* @param end 结束日期
* @return 日期集合
*/
public List<Date> getBetweenDates(Date start, Date end) {
try {
//将起始时间格式化为 yyyy-MM-dd 00:00:00
start = sdf.parse(sdf.format(start));
} catch (Exception e) {
e.printStackTrace();
}
List<Date> result = new ArrayList<Date>();
Calendar tempStart = Calendar.getInstance();
tempStart.setTime(start);
while(start.getTime()<=end.getTime()){
result.add(tempStart.getTime());
tempStart.add(Calendar.DAY_OF_YEAR, 1);
start = tempStart.getTime();
}
return result;
}
/**
* 按行读取文件
* @param
* @return
* @exception
*/
public List<String> readLine(String url) {
List<String> jsonList = new ArrayList<String>();
// Text文件
File file = new File(url);
if(!file.exists()){
return jsonList;
}
BufferedReader br = null;
try {
// 构造一个BufferedReader类来读取文件
br = new BufferedReader(new FileReader(file));
String s = null;
// 使用readLine方法,一次读一行
while ((s = br.readLine()) != null) {
jsonList.add(s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return jsonList;
}
}