Commit 07602a7b authored by kang.nie@inzymeits.com's avatar kang.nie@inzymeits.com
Browse files

提交代码

parent e0c7be76
package com.ssi.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ssi.websocket.WebBackSocketService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.client.transport.TransportClient;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
* Description:
* 用于读取kafka数据回放
* @author LiXiaoCong
* @version 2019/10/12 12:47
*/
@Slf4j
public class WebSocketDataFileBackor extends WebSocketDataEsBackor{
private String backorId;
private String scenesId;
private WebSocketDataBackServiceImpl webSocketDataBackService;
private Set<String> vins;
private TransportClient transportClient;
private String indexBase;
private Map<String, Map<String, Object>> latestMap;
private Map<String, String> latestJson;
private AtomicBoolean closed = new AtomicBoolean(false);
private boolean randomDelay;
private double randomDelayScale;
private String randomDelayScenesId;
private String path;
public WebSocketDataFileBackor(String backorId,
String scenesId,
WebSocketDataBackServiceImpl webSocketDataBackService,
Set<String> vins,
String mainSession,
Set<String> sessions){
this.backorId = backorId;
this.scenesId = scenesId;
this.webSocketDataBackService = webSocketDataBackService;
this.vins = vins;
this.mainSession = mainSession;
this.sessions = sessions;
this.transportClient = transportClient;
this.indexBase = indexBase;
this.latestMap = new HashMap<>();
this.latestJson = new HashMap<>();
}
public WebSocketDataFileBackor() {
}
public void playBack(Long startTime, Long stopTime, long delay, boolean normal){
try {
//初始化结果容器
Map<String, List<Map<String, Object>>> records = Maps.newHashMap();
vins.forEach(vin ->{
records.put(vin, Lists.newLinkedList());
});
getRecords(startTime, stopTime, records);
Iterator<Map.Entry<String, List<Map<String, Object>>>> iterator = records.entrySet().iterator();
while (iterator.hasNext()){
if(iterator.next().getValue().size() == 0){
iterator.remove();
}
}
if(!records.isEmpty()) {
if(normal) {
playBackByNormal(records, delay);
}/*else if(randomDelay && randomDelayScenesId != null){
playBackInThread(records, delay);
}*/ else {
playBack(records, delay);
}
}else{
log.warn(String.format("车辆%s的数据查询成功,时间段:[%s, %s], 无数据, 无需回放。", vins, startTime, stopTime));
}
} catch (Exception e) {
log.warn(String.format("车辆%s的数据回放失败,时间段:[%s, %s]。", vins, startTime, stopTime), e);
shutDown();
WebBackSocketService.messageBroadcast(backorId, Sets.newHashSet(this.sessions), Lists.newArrayList(), true);
}
}
private void playBack(Map<String, List<Map<String, Object>>> data, long delay){
log.info(String.format("开始回放车辆%s的数据.", vins));
String recordJson;
long sleepTime;
Map<String, Object> map;
//获取最多数据集合个数
Set<Map.Entry<String, List<Map<String, Object>>>> entries = data.entrySet();
Map<String, Integer> sizeMap = Maps.newHashMap();
Integer max = entries.stream().map(entry ->{
int size = entry.getValue().size();
sizeMap.put(entry.getKey(), size);
return size;
}).max(Integer::compareTo).get();
Integer vinSize;
for (int i = 0; i < max; i++) {
long t = System.currentTimeMillis();
log.info(String.format("开始%s的第%s次推送数据:%s", backorId, i + 1, t));
for (Map.Entry<String, List<Map<String, Object>>> entry : entries){
vinSize = sizeMap.get(entry.getKey());
vinSize = (i >= vinSize) ? (vinSize - 1) : i;
map = entry.getValue().get(vinSize);
if(!closed.get()) {
int i1 = checkRandomDelay(map);
recordJson = JSON.toJSONString(map);
this.latestJson.put(entry.getKey(), recordJson);
WebBackSocketService.messageBroadcast(backorId, Sets.newHashSet(sessions), recordJson);
}else {
return;
}
}
//计算休眠时间
sleepTime = delay - (System.currentTimeMillis() - t);
sleep(sleepTime > 0 ? sleepTime : 1000L);
}
pushLast();
log.info(String.format("回放车辆数据完成:%s, 回放数据记录情况:%s。", vins, sizeMap));
}
/**
* 仅适合车辆少的情况, 用于测试
* @param data
* @param delay
*/
private void playBackInThread(Map<String, List<Map<String, Object>>> data, long delay){
log.info(String.format("开始使用多线程回放车辆%s的数据.", vins));
CountDownLatch countDownLatch = new CountDownLatch(data.size());
data.forEach((vin, records) ->{
new Thread(() -> {
try {
String recordJson;
long sleepTime;
long t = System.currentTimeMillis();
log.info(String.format("开始%s的车辆%s推送数据: %s", backorId, vin, t));
for (Map<String, Object> map : records){
if(!closed.get()) {
int i1 = checkRandomDelay(map);
recordJson = JSON.toJSONString(map);
this.latestJson.put(vin, recordJson);
WebBackSocketService.messageBroadcast(backorId, Sets.newHashSet(sessions), recordJson);
if(i1 > 100){
sleep(i1);
}
}else {
return;
}
//计算休眠时间
sleepTime = delay - (System.currentTimeMillis() - t);
sleep(sleepTime > 0 ? sleepTime : 1000L);
}
} finally {
countDownLatch.countDown();
}
}).start();
});
try {
countDownLatch.await();
} catch (InterruptedException e) {
}
pushLast();
List<String> collect = data.entrySet()
.stream()
.map(entry -> String.format("%s:%s", entry.getKey(), entry.getValue().size()))
.collect(Collectors.toList());
log.info(String.format("回放车辆数据完成:%s, 回放数据记录情况:%s。", vins, collect));
}
private int checkRandomDelay(Map<String, Object> map){
int delay = 0;
if(randomDelay && randomDelayScenesId.equals(scenesId)){
double random = Math.random();
if(random < randomDelayScale){
map.put("netError", true);
delay = (int) (random * 100000);
log.warn(String.format("触发随机延迟:%s, 延迟时长:%s。", map, delay));
}
}
return delay;
}
private void playBackByNormal(Map<String, List<Map<String, Object>>> data, long delay){
log.info(String.format("开始使用队列回放车辆%s的数据.", vins));
String json;
long sleepTime;
LinkedList<Map<String, Object>> res;
Map<String, Object> map;
boolean empty;
Iterator<Map.Entry<String, List<Map<String, Object>>>> iterator;
Map.Entry<String, List<Map<String, Object>>> entry;
int i = 0;
while (!data.isEmpty()){
long t = System.currentTimeMillis();
log.info(String.format("开始%s的第%s次推送数据:%s", backorId, i++, t));
iterator = data.entrySet().iterator();
while (iterator.hasNext()){
entry = iterator.next();
res = (LinkedList<Map<String, Object>>) entry.getValue();
map = res.poll();
empty = res.isEmpty();
if(map != null){
if(!closed.get()) {
checkRandomDelay(map);
json = JSON.toJSONString(map);
if(empty){
json = String.format("#%s", json);
}
WebBackSocketService.messageBroadcast(backorId, Sets.newHashSet(sessions), json);
}else {
return;
}
}
if(empty){
log.info(String.format("车辆%s的数据回放完成。", entry.getKey()));
this.latestJson.put(entry.getKey(), null);
iterator.remove();
}
}
//计算休眠时间
sleepTime = delay - (System.currentTimeMillis() - t);
sleep(sleepTime > 0 ? sleepTime : 1000L);
}
pushLast();
log.info(String.format("回放车辆数据完成:%s。", vins));
}
void getRecords(Long startTime,
Long stopTime,
Map<String, List<Map<String, Object>>> resultContain){
try {
FileReader fr = new FileReader(path);
BufferedReader bf = new BufferedReader(fr);
StringBuffer line =new StringBuffer();
String templine = bf.readLine();
while(templine!=null){
line.append(templine);
templine = bf.readLine();
}
String json = line.toString().replaceAll("\r\n","");
bf.close();
fr.close();
List<HashMap> records = JSON.parseArray(json,HashMap.class);
for(Map<String,Object> record:records) {
String vin = record.keySet().iterator().next();
Map<String,Object> value = (Map<String,Object>)record.get(vin);
Object time = value.get("collectTime");
checkAndPushResultContain(record, time, resultContain);
}
List<String> collect = resultContain.entrySet()
.stream()
.map(entry -> String.format("%s:%s", entry.getKey(), entry.getValue().size()))
.collect(Collectors.toList());
log.info(String.format("车辆%s的数据查询成功,时间段:[%s, %s], 数据量:%s", vins, startTime, stopTime, collect));
}catch (Exception e){
log.error("读取文件失败!!!",e);
}
}
private void checkAndPushResultContain(Map<String, Object> record,
Object time,
Map<String, List<Map<String, Object>>> resultContains){
resultContains.forEach((vin, resultContain) ->{
Object map = record.get(vin);
if(map != null && isValid(vin, map)){
Map<String, Object> res = (Map<String, Object>) map;
res.put("time", time);
resultContain.add(res);
}
});
}
private Map<String, Object> jsonToMap(String json){
Map<String, Object> map = null;
try {
map = JSON.parseObject(json, new TypeReference<Map<String, Object>>() {
});
} catch (Exception e) {
log.error(String.format("json数据转换Map失败:%s", json), e);
}
return map;
}
public void shutDown() {
this.closed.set(true);
}
private boolean isValid(String vin, Object record){
boolean valid;
try {
Map<String, Object> map = (Map<String, Object>) record;
valid = ("在线".equals(map.get("clientStatus")));
if(valid){
Map<String, Object> preMap = this.latestMap.get(vin);
if(preMap != null){
String prelocation = String.format("%s,%s", preMap.get("latitude"), preMap.get("longitude"));
String location = String.format("%s,%s", map.get("latitude"), map.get("longitude"));
double speed = Double.parseDouble(map.getOrDefault("speed", "0").toString());
valid = !(prelocation.equals(location) && speed != 0);
}
if(valid) {
this.latestMap.put(vin, map);
}
}
} catch (Exception e) {
log.error("数据检查异常。", e);
valid = false;
}
return valid;
}
private void sleep(long time){
try {
Thread.sleep(time);
} catch (InterruptedException e) { }
}
private void pushLast(){
this.latestJson.forEach((key, json) ->{
if(!closed.get()) {
HashSet<String> sessions = Sets.newHashSet(this.sessions);
WebBackSocketService.messageBroadcast(backorId, sessions, json, true);
log.info(String.format("推送%s的车辆%s的最后一条数据。", sessions, key));
}else{
return;
}
});
shutDown();
}
public void setRandomDelay(boolean randomDelay) {
this.randomDelay = randomDelay;
}
public void setRandomDelayScale(double randomDelayScale) {
this.randomDelayScale = randomDelayScale;
}
public void setRandomDelayScenesId(String randomDelayScenesId) {
this.randomDelayScenesId = randomDelayScenesId;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
package com.ssi.service.platform;
import java.util.Map;
import java.util.Set;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/10/17 10:17
*/
public interface RedisConfigService {
void setConfig(String group, String key, String value);
String getConfigWithDefault(String group, String key, String defaultValue);
String getConfig(String group, String key);
Map<String, String> getConfigs(String group, Set<String> keys);
void deteles(String group, String... keys);
}
package com.ssi.service.platform;
/**
* description:
*
* @author WangHD
* @version 1.0
* @date 2020/3/20 0020 9:57
*/
public interface VehicleLatestDataService {
Object getOnlineData(String key);
Object getVehicleStatus(String vin, Integer status);
}
package com.ssi.service.platform;
import java.util.Map;
public interface VehicleMonitorService {
Object getCarHistoryVideoList(String vin);
Object getCarVideoList(String vin);
Map<String, Object> getOfflineVehicleList(String vehicleCompany, String vehicleType, Integer offlineDays, int page, int size);
Object getCarVideoPlayingList(String vin);
}
package com.ssi.service.platform;
import com.ssi.entity.ScrollTrackLocationEntity;
import com.ssi.response.SSIResponse;
import java.util.Map;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/9/26 19:23
*/
public interface VehicleTrackService {
SSIResponse scrollTrack(ScrollTrackLocationEntity scrollTrackLocationEntity);
SSIResponse smallTrack(String vin,
Long startTime,
Long stopTime,
String posType);
}
\ No newline at end of file
package com.ssi.service.platform;
import java.util.Map;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/9/20 11:45
*/
public interface WebSocketDataService {
Map<String, Map<String, Object>> realTimeDataAll();
Map<String, Map<String, Object>> getVehicleRunData();
}
package com.ssi.service.platform.impl;
import com.ssi.model.RedisConfigModel;
import com.ssi.service.platform.RedisConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Set;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/10/17 10:24
*/
@Service
@Slf4j
public class RedisConfigServiceImpl implements RedisConfigService {
@Autowired
private RedisConfigModel redisConfigModel;
@Override
public void setConfig(String group, String key, String value) {
if (group != null) {
redisConfigModel.setConfig(group, key, value);
} else {
redisConfigModel.setConfig(key, value);
}
}
@Override
public String getConfigWithDefault(String group, String key, String defaultValue) {
if (group != null) {
return redisConfigModel.getConfigWithDefault(group, key, defaultValue);
} else {
return redisConfigModel.getConfigWithDefault(key, defaultValue);
}
}
@Override
public String getConfig(String group, String key) {
if (group != null) {
return redisConfigModel.getConfig(group, key);
} else {
return redisConfigModel.getConfig(key);
}
}
@Override
public Map<String, String> getConfigs(String group, Set<String> keys) {
if (group != null) {
return redisConfigModel.getConfigs(group, keys);
} else {
return redisConfigModel.getConfigs(keys);
}
}
@Override
public void deteles(String group, String... keys) {
if (group != null) {
redisConfigModel.deteles(group, keys);
} else {
redisConfigModel.deteles(keys);
}
}
}
package com.ssi.service.platform.impl;
import com.ssi.model.VehicleLatestDataModel;
import com.ssi.service.platform.VehicleLatestDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* description:
*
* @author WangHD
* @version 1.0
* @date 2020/3/20 0020 9:57
*/
@Service
public class VehicleLatestDataServiceImpl implements VehicleLatestDataService {
@Autowired
private VehicleLatestDataModel vehicleLatestDataModel;
@Override
public Object getOnlineData(String key) {
return vehicleLatestDataModel.getOnlineData(key);
}
@Override
public Object getVehicleStatus(String vin, Integer status) {
return vehicleLatestDataModel.getVehicleStatus(vin, status);
}
}
package com.ssi.service.platform.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ssi.kafka.model.KafkaRecordModel;
import com.ssi.mapper.VehicleVideoMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.model.VehicleBaseInfoModel;
import com.ssi.model.VehicleElasticSearchModel;
import com.ssi.service.platform.VehicleMonitorService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
public class VehicleMonitorServiceImpl implements VehicleMonitorService {
@Value("${v2x.rsu.transform.video.request:http://172.16.15.26:10080/rtspstart}")
private String videoTransformRquestUrl;
@Value("${v2x.history.video.request:http://172.16.15.26:10080/historyvideo}")
private String videoListformRquestUrl;
@Autowired
private VehicleVideoMapper vehicleVideoMapper;
@Autowired
private RestTemplate restTemplate;
@Autowired
private RedisDataModel redisDataModel;
@Autowired
private VehicleBaseInfoModel vehicleBvaseInfoModel;
@Value("${command.url:http://172.16.15.13:8040/}")
private String commandUrl;
@Autowired
private VehicleElasticSearchModel vehicleElasticSearchModel;
@Value("${meilan.data.esIndex:v2x_meilan_vehicle}")
private String meilanDataIndex;
@Value("${meilan.data.esIndex.timeField:collectTime}")
private String timeField;
@Value("${rtmp.video.lan.url:rtmp://192.168.6.25:1935/}")
private String rtmpBaseLanUrl;
@Value("${flv.video.lan.url:http://192.168.6.25:8080/}")
private String flvBaseLanUrl;
@Value("${video.online.keyPrefix:v2x:meilan:video:}")
private String videoPrefixKey;
@Autowired
private KafkaRecordModel kafkaRecordModel;
@Override
public Object getCarHistoryVideoList(String vin) {
return getHistoryVideoList(vin);
}
@Override
public Object getCarVideoList(String vin) {
return getCarVideoList(vin, rtmpBaseLanUrl, flvBaseLanUrl);
}
@Override
public Map<String, Object> getOfflineVehicleList(String vehicleCompany, String vehicleType, Integer offlineDays, int page, int size) {
Map<String, Object> searchResult = vehicleElasticSearchModel.getOfflineVehicleList(meilanDataIndex, timeField, vehicleCompany, vehicleType, offlineDays, page, size);
List<Map<String, Object>> records = (List<Map<String, Object>>) searchResult.get("records");
List<Map<String, Object>> result = records.stream().map(r -> {
Long collectTime = (Long) r.get(timeField);
Integer days = Double.valueOf((System.currentTimeMillis() - collectTime) / (24 * 60 * 60 * 1000)).intValue();
r.put("offlineDays", days);
return r;
}).collect(Collectors.toList());
searchResult.put("records", result);
return searchResult;
}
@Override
public Object getCarVideoPlayingList(String vin) {
List<Object> result = Lists.newArrayList();
for (int i = 1; i <= 4; i++) {
try {
Object videoUrl = playingCarVideo(vin, i);
result.add(videoUrl);
} catch (Exception e) {
log.error("获取视频失败!", e);
}
}
return result;
}
public Object getHistoryVideoList(String vin) {
List results = Lists.newArrayList();
try {
String url = String.format("%s?vin=%s", videoListformRquestUrl, vin);
//激活回放流
String responseString = restTemplate.getForObject(url, String.class);
log.info(responseString);
results = getVideoHistoryList(vin);
} catch (RestClientException e) {
log.error(String.format("调用接口失败:\n %s", vin), e);
}
return results;
}
public Object playingCarVideo(String vin, Integer channel) {
Map<String, Object> result = Maps.newHashMap();
try {
Map<String, Object> vehicleInfo = vehicleBvaseInfoModel.getVehicleBaseInfo(vin);
if (vehicleInfo != null) {
String url = String.format("%s/media/9101", commandUrl);
JSONObject jo = new JSONObject();
jo.put("sim", vehicleInfo.get("sim"));
jo.put("channel", channel);
jo.put("dataType", 1);
jo.put("controlType", 0);
jo.put("hdType", 0);
String responseString = restTemplate.postForObject(url, jo, String.class);
JSONObject resJo = JSON.parseObject(responseString);
String code = resJo.getString("code");
if ("0".equals(code)) {
JSONObject dataJo = resJo.getJSONObject("data");
result.put("vin", vin);
result.put("sim", vehicleInfo.get("sim"));
result.put("channel", channel);
result.put("rtmpUrl", dataJo.getString("playUrl"));
result.put("sn", dataJo.getString("sn"));
result.put("result", dataJo.getString("result"));
} else {
//JSONObject dataJo = resJo.getJSONObject("data");
result.put("vin", vin);
result.put("channel", channel);
result.put("sim", vehicleInfo.get("sim"));
}
}
} catch (Exception e) {
log.error(String.format("调用接口失败:\n %s", vin), e);
}
return result;
}
private List getVideoHistoryList(String vin) {
List<Map<String, Object>> videolist = vehicleVideoMapper.getHistoryVideoByVin(vin);
return videolist;
}
public List<Map<String, Object>> getCarVideoList(String vin, String rtmpBase, String flvBase) {
List<Map<String, Object>> result = Lists.newArrayList();
if (StringUtils.isNotBlank(vin)) {
result = vehicleVideoMapper.getVideoListByVins(Arrays.asList(vin.split(",")));
}
if (!result.isEmpty()) {
result = result.parallelStream().map(video -> {
String url = String.valueOf(video.get("url"));
if (url != null && url.indexOf("sdp") == -1) {
Map<String, Object> videoMsg = videoMsgByRedis(url);
if (videoMsg != null) {
String rtmpUrl = (String) videoMsg.remove("rtmpUrl");
String flvUrl = (String) videoMsg.remove("flvUrl");
if (rtmpUrl.indexOf("dfcv") > -1) {
rtmpUrl = String.format("%s%s", rtmpBase, rtmpUrl.substring(rtmpUrl.indexOf("dfcv")));
}
if (flvUrl.indexOf("dfcv") > -1) {
flvUrl = String.format("%s%s", flvBase, flvUrl.substring(flvUrl.indexOf("dfcv")));
}
video.put("url", rtmpUrl);
video.put("flvUrl", flvUrl);
video.putAll(videoMsg);
} else {
video.put("url", String.format("%s%s", rtmpBase, url));
video.put("flvUrl", String.format("%s%s.flv", flvBase, url));
video.put("online", "0");
}
} else {
Map<String, Object> videoMap = transfromVideoUrl(url);
if (videoMap != null && !videoMap.isEmpty()) {
video.put("url", videoMap.get("rtmp"));
video.put("flvUrl", videoMap.get("httpflv"));
video.put("online", "1");
}
}
return video;
}).collect(Collectors.toList());
}
return result;
}
public Map<String, Object> videoMsgByRedis(String videoUrl) {
String key = String.format("%s%s", videoPrefixKey, videoUrl);
return redisDataModel.getJson2Map(key);
}
public Map<String, Object> transfromVideoUrl(String rtsp) {
try {
String url = String.format("%s?rtsp=%s", videoTransformRquestUrl, rtsp);
String responseString = restTemplate.getForObject(url, String.class);
if (StringUtils.isNotBlank(responseString)) {
log.info(JSON.toJSONString(responseString));
Map<String, Object> res = JSON.parseObject(responseString, Map.class);
if (res != null) {
Object data = res.get("data");
if (data != null && data instanceof Map) {
Map map = (Map<String, Object>) data;
return map;
}
}
}
} catch (RestClientException e) {
log.error(String.format("调用接口失败:\n %s", rtsp), e);
}
return Collections.emptyMap();
}
}
\ No newline at end of file
package com.ssi.service.platform.impl;
import com.google.common.collect.Sets;
import com.ssi.entity.ScrollTrackLocationEntity;
import com.ssi.model.VehicleElasticSearchModel;
import com.ssi.response.SSIResponse;
import com.ssi.service.platform.VehicleTrackService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
* Description:
*
* @author LiXiaoCong
* @version 2020/2/8 12:56
*/
@Service
@Slf4j
public class VehicleTrackServiceImpl implements VehicleTrackService {
@Value("${analysis.vehicle-data.es-index-name:vms_igv_vehicle}")
private String dataIndex;
@Value("${analysis.vehicle-data.index-rule:year}")
private String indexRule;
@Value("${data.esIndex.timeField:receiveTime}")
private String timeField;
@Autowired
private VehicleElasticSearchModel vehicleElasticSearchModel;
// @Autowired
// private VehicleElasticRestSearchModel vehicleElasticRestSearchModel;
@Override
public SSIResponse scrollTrack(ScrollTrackLocationEntity scrollTrackLocationEntity) {
// Map<String, Object> map = vehicleElasticRestSearchModel.searchScrollTrackLocations(dataIndex, indexRule, timeField, scrollTrackLocationEntity);
return vehicleElasticSearchModel.searchScrollTrackLocations(dataIndex, indexRule, timeField, scrollTrackLocationEntity);
}
@Override
public SSIResponse smallTrack(String vin,
Long startTime,
Long stopTime,
String posType) {
// Map<String, Object> map = vehicleElasticRestSearchModel.searchAllTrackLocations(vin,
// dataIndex,
// indexRule,
// null,
// timeField,
// startTime,
// stopTime,
// posType);
Set<String> columns = Sets.newHashSet("vin", "speed",
"gear","location","longitude", "latitude","collectTime"
,"brakePedalOpen","gear","brakeStatus");
return vehicleElasticSearchModel.searchAllTrackLocations(vin,
dataIndex,
indexRule,
columns,
timeField,
startTime,
stopTime,
posType);
}
}
package com.ssi.service.platform.impl;
import com.ssi.model.WebSocketDataServiceModel;
import com.ssi.service.platform.WebSocketDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* Description:
* 从redis中获取所有车辆数据
*
* @author LiXiaoCong
* @version 2019/9/20 11:47
*/
@Service
@Slf4j
public class WebSocketDataServiceImpl implements WebSocketDataService {
@Autowired
private WebSocketDataServiceModel webSocketDataServiceModel;
@Override
public Map<String, Map<String, Object>> realTimeDataAll() {
return webSocketDataServiceModel.realTimeDataAll(true);
}
@Override
public Map<String, Map<String, Object>> getVehicleRunData() {
return webSocketDataServiceModel.getVehicleRunData();
}
}
package com.ssi.task;
import com.ssi.websocket.WebSocketServiceForScreenList;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 大屏数据刷新任务,一般每日凌晨执行
*/
@Component
@EnableScheduling
public class BigScreenRefreshTask {
//@Scheduled(cron = "0 0 0 * * ?")
@Scheduled(cron = "${task.bigScreenRefreshTask.cron}")
private void bigScreenRefresh() {
WebSocketServiceForScreenList.messageBroadcast("windowReload");
}
}
package com.ssi.task;
import com.alibaba.fastjson.JSONObject;
import com.ssi.constant.URL;
import com.ssi.entity.VmsChargingEquipmentInfo;
import com.ssi.entity.VmsTosOrders;
import com.ssi.constant.enums.ElecLevelEnum;
import com.ssi.model.RedisDataModel;
import com.ssi.model.VehicleSocketDataCacheQueueModel;
import com.ssi.service.VmsChargingEquipmentInfoService;
import com.ssi.service.VmsTosOrdersService;
import com.ssi.service.platform.WebSocketDataService;
import com.ssi.utils.RestTemplateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author SunnyHotz
* @PackageName:com.ssi.task
* @ClassName:ChargingManageTask
* @Description:
* @date 2022/7/18 11:43
*/
@Slf4j
@Component
public class ChargingManageTask {
@Value("${spring.websocket.pushInPool.enable:false}")
private boolean pushInPool;
@Value("${harbor.command.info_key:harbor:command:vin:info}")
private String infoKey;
@Value("${command-url}")
private String odbuUrl;
@Value("${order.latestOrderKeyPrefix:harbor:command:status}")
private String latestOrderKeyPrefix;
@Value("${ivccs.vehicle.latestData.redis.prefix:ivccs:vms:vehicle:latest:}")
private String lastVehicleKeyPrefix;
@Autowired
private RedisDataModel redisDataModel;
@Autowired
private WebSocketDataService webSocketDataService;
@Autowired
private VmsTosOrdersService vmsTosOrdersService;
@Autowired(required = false)
private VehicleSocketDataCacheQueueModel vehicleSocketDataCacheQueueModel;
@Autowired
private VmsChargingEquipmentInfoService chargingEquipmentInfoService;
private AtomicInteger threadNum = new AtomicInteger(0);
//前往充电车辆
private final static List<JSONObject> chargingVehicleList = new CopyOnWriteArrayList<>();
//充电中车辆
private final static List<String> onChargingVehicleList = new CopyOnWriteArrayList<>();
//需紧急充电
private final static ArrayList<Map<String, Object>> chargingE1VehicleList = new ArrayList<>();
//非紧急充电
private final static ArrayList<Map<String, Object>> chargingE2VehicleList = new ArrayList<>();
//可执行车辆
private final static ArrayList<String> usualE3VehicleList = new ArrayList<>();
//用车需求队列
private final static Deque<String> waitTaskDeque = new ArrayDeque<>();
//锁定充电桩
private final static ArrayList<String> lockedChargingEquipments = new ArrayList<>();
// @Scheduled(cron = "")
public void invokeForCharging() throws Exception {
//获取空闲的充电枪
List<VmsChargingEquipmentInfo> chargingEquipmentInfos = chargingEquipmentInfoService.qryFreeEquipment(1);
if(CollectionUtils.isEmpty(chargingEquipmentInfos)){
return;
}
//过滤已锁定充电桩
chargingEquipmentInfos = chargingEquipmentInfos.stream().filter(e -> !lockedChargingEquipments.contains(e.getEquipmentId())).distinct().collect(Collectors.toList());
//待充电车辆优先级排序,获取匹配车辆
List<Map<String, Object>> aimToChargingList = getAdapterVehicle(chargingEquipmentInfos.size());
if(CollectionUtils.isEmpty(aimToChargingList)){
return;
}
for (int i = 0; i < aimToChargingList.size(); i++) {
//下发调度去充电站指令
JSONObject jsonObject = sendTaskOrder(aimToChargingList.get(i), chargingEquipmentInfos.get(i));
if(1 == jsonObject.getIntValue("code")){
chargingVehicleList.add(jsonObject);
lockedChargingEquipments.add(chargingEquipmentInfos.get(i).getEquipmentId());
}
}
}
/**
* 定时检测需充电车辆,其实这样并不友好, 因为电量是动态变化
*/
@Scheduled(cron="0 0/1 * * * ?")
private synchronized void needChargingVehicle() {
//获取需加入充电队列的在线托盘
List<Map<String, Object>> onlineAutoVehicles = getOnlineAutoVehicle();
if (onlineAutoVehicles.isEmpty()) return;
onlineAutoVehicles.sort((o1, o2) -> {
Integer soc1 = Objects.isNull(o1.get("soc"))?Integer.valueOf(100):(Integer)o1.get("soc");
Integer soc2 = Objects.isNull(o2.get("soc"))?Integer.valueOf(100):(Integer)o2.get("soc");
return (soc1-soc2);
});
//清空缓存,重新填装
chargingE1VehicleList.clear();
chargingE2VehicleList.clear();
onlineAutoVehicles.stream().forEach(e->{
if((Integer)e.get("soc")<ElecLevelEnum.LEVEL_E1.getValue()){
chargingE1VehicleList.add(e);
}else {
chargingE2VehicleList.add(e);
}
});
}
/**
* 根绝任务统一提供车辆VIN
* @param taskNo
* @return
*/
public String getWorkableVehicle(String taskNo){
String vin =null;
if(usualE3VehicleList.size()>0){
vin = usualE3VehicleList.remove(0);
}else if(chargingE2VehicleList.size()>0){
Map<String, Object> map = chargingE2VehicleList.remove(chargingE2VehicleList.size() - 1);
vin = Objects.nonNull(map.get("vin"))?String.valueOf(map.get("vin")):"";
}else if(onChargingVehicleList.size()>0){
//查询充电桩充电量接口,获取当前电量》40 且当前电量最多的一个
vin = getMaxSocVehicle(vin);
}
//调用下电接口,并下发任务信息
return vin;
}
/**
*正式充电回调
*/
public void invokeForCharged(){
//获取当前充电车辆
Iterator<JSONObject> iterator = chargingVehicleList.iterator();
while (iterator.hasNext()){
JSONObject next = iterator.next();
//调用充电桩接口判断是否充电完成
//调用车辆远程启动
//离开充电区
}
}
private String getMaxSocVehicle(String vin) {
TreeMap<Integer, Integer> socMap = new TreeMap<>();
for (int i = 0; i < onChargingVehicleList.size(); i++) {
Map<String, Object> vehicleStatus = redisDataModel.getJson2Map(String.format("%s:%s-%s", lastVehicleKeyPrefix, onChargingVehicleList.get(i), "harbor_D00A"));
socMap.put((Integer) vehicleStatus.get("soc"),i);
}
Map.Entry<Integer, Integer> socEntry = socMap.firstEntry();
if(socEntry.getKey()>=40){
int index = socEntry.getValue();
vin = onChargingVehicleList.remove(index);
}
return vin;
}
private List<Map<String, Object>> getAdapterVehicle(Integer avaliable) {
List<Map<String, Object>> result = new ArrayList<>();
for(int i=0; i<avaliable;i++){
Map<String, Object> obj = null;
if(chargingE1VehicleList.size()>0){
obj = chargingE1VehicleList.remove(0);
}else if(chargingE2VehicleList.size()>0){
obj = chargingE2VehicleList.remove(0);
}
if(obj!=null){
result.add(obj);
}
}
return result;
}
private JSONObject sendTaskOrder(Map<String, Object> v, VmsChargingEquipmentInfo equipmentInfo) {
JSONObject param = new JSONObject();
String temp = URL.To_ODBU_URL;
param.put("vin", v.get("vin"));// 车辆编号
param.put("taskSource", 2);// 1-TOS下发;2-手动下发;3-VMS下发
param.put("taskNo", UUID.randomUUID().toString().replace("-", ""));// 任务编号
param.put("seq", v.get("seq"));// 序号
param.put("taskType", 3);// 任务编号 6 停车 3 充电
param.put("vehicleTaskLabel", 5); //车辆任务标签,1:装船;2:卸船;3:堆场间搬移;4:停车,5:充电,6:临时停车
param.put("taskLocationType", 6);// "任务类型, 1-去堆场(装箱或卸箱);2-去停车点(上扭锁,解扭锁,停车);3-去固定停车区;4-去临时停车区;5-去桥吊(装箱或卸箱);6-去充电"
param.put("taskOperation", 0); // 任务操作:0-开始 1-取消 2-强制取消
// param.put("parkingAreaNo", equipmentInfo.getEquipmentId());// 停车区编号,缓冲区编号,充电位编号
param.put("latitude", equipmentInfo.getEquipmentLat());// 目的地维度
param.put("longitude", equipmentInfo.getEquipmentLng());// 目的地经度
String result = RestTemplateUtil.post(String.format("%s%s", odbuUrl, temp), param.toString(), null);
JSONObject jsonObject = JSONObject.parseObject(result);
jsonObject.put("taskNo",param.getString("taskNo"));
jsonObject.put("vin", v.get("vin"));
return jsonObject;
}
private List<Map<String, Object>> getOnlineAutoVehicle() {
List<Map<String, Object>> resultList= new ArrayList<>();
Map<String, Map<String, Object>> messages;//全部
//获取在线车辆
messages = webSocketDataService.realTimeDataAll();
if (messages.isEmpty()) return Collections.EMPTY_LIST;
//清空非充电车辆重新填充
usualE3VehicleList.clear();
messages.entrySet().stream().filter(entry->{
if(Objects.isNull(entry.getValue())) return false;
return "1".equals(String.valueOf(entry.getValue().get("isOnline")));
}).forEach(entry -> {
String keys = String.format("%s:%s", infoKey, entry.getKey());
String vehicleMap = redisDataModel.get(keys);
if(vehicleMap != null) {
//判断redis是否存在
JSONObject obj = JSONObject.parseObject(vehicleMap);
Integer vehicleType =(Integer) obj.get("vehicleType");//1:X69B ,2:X69C,3:有人集卡两秒
if (vehicleType != 3){
//判断是否符合充电条件
if(needCharging(entry.getValue())) {
resultList.add(entry.getValue());
}else {
usualE3VehicleList.add(entry.getKey());
}
}
}
}) ;
return resultList;
}
private boolean needCharging(Map<String, Object> value) {
//当前是否安排任务
Map<String, Object> taskStatus = vmsTosOrdersService.getOrdersByVin(String.valueOf(value.get("vin")));
if(String.valueOf(taskStatus.get("workStatus")).equals("0")){
//正在执行任务,逻辑暂不处理
return false;
}
//当前是否在充电中
List<String> vins = chargingVehicleList.stream().map(e -> e.getString("vin")).collect(Collectors.toList());
if(vins.contains(String.valueOf(value.get("vin")))){
return false;
}
//电量判断
Integer powerReserve = Objects.nonNull(value.get("soc")) ? (Integer) value.get("soc") : Integer.valueOf(100);
if(powerReserve<= ElecLevelEnum.LEVEL_E2.getValue()){
return true;
}
return false;
}
class TaskInnvoker implements Runnable{
@Override
public void run() {
threadNum.incrementAndGet();
long begin = System.currentTimeMillis();
while (chargingVehicleList.size()>0){
Iterator<JSONObject> iterator = chargingVehicleList.iterator();
while (iterator.hasNext()){
JSONObject next = iterator.next();
//判断是否到达充电站
List<VmsTosOrders> orders = vmsTosOrdersService.lambdaQuery().eq(VmsTosOrders::getTaskNo, next.getString("taskNo")).list();
if(CollectionUtils.isEmpty(orders)){
continue;
}
Integer status = orders.get(0).getStatus();
//到达充电站调用充电接口
if(3==status){
//调用充电接口
//列表移除
iterator.remove();
onChargingVehicleList.add(next.getString("vin"));
}
}
if((System.currentTimeMillis() - begin) > 60*60*1000){
//超时没有达到充电桩
}
//wait
try {
Thread.currentThread().wait(30000);
}catch (Exception e){
log.error("调用充电接口出错====>",e);
}
}
threadNum.decrementAndGet();
}
}
}
package com.ssi.task;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import com.ssi.entity.dto.TelecontrolParamDto;
import com.ssi.model.RedisDataModel;
import com.ssi.model.TelecontrolModel;
import com.ssi.websocket.WebSocketServiceForDebugApp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* 会话超时执行车辆刹车,确保安全性
*/
@Component
@Slf4j
public class KeyExpiredListener extends KeyExpirationEventMessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(KeyExpiredListener.class);
@Value("${harbor.remote.overtime}")
private String debugAppOvertimePrefix;
@Value("${harbor.remote.socketOvertime}")
private String socketOvertimePrefix;
@Autowired
private TelecontrolModel telecontrolModel;
@Autowired
private RedisDataModel redisDataModel;
public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String channel = new String(message.getChannel(), StandardCharsets.UTF_8);
String key = new String(message.getBody(), StandardCharsets.UTF_8);
// if (key.startsWith(debugAppOvertimePrefix)) {
// LOGGER.info("redis key 过期:pattern={},channel={},key={}", new String(pattern), channel, key);
// String vinMac = key.replace(debugAppOvertimePrefix + ":", "");
// String[] strings = vinMac.split("&");
// String vin = strings[0];
// String appMac = strings[1];
// TelecontrolParamDto paramDto = new TelecontrolParamDto();
// paramDto.setVin(vin);
// paramDto.setAppMac(appMac);
// paramDto.setControlType(1);
// paramDto.setOperationValue(2);
// telecontrolModel.vehicleTelecontrol(paramDto);
// Map msg = new HashMap<>();
// msg.put("msgType", 1);
// msg.put("vin", vin);
// msg.put("appMac", appMac);
// msg.put("message", "超时退出接管");
// WebSocketServiceForDebugApp.messageBroadcast(vin, msg);
// }
if (key.startsWith(socketOvertimePrefix)) {
String[] arr = key.split(":");
String vin = arr[arr.length - 1];
String sessionId = arr[arr.length - 2];
log.info("判断sessionId:{},vin:{}是否超时", sessionId, vin);
String socketOvertime = redisDataModel.get(
socketOvertimePrefix + ":" + sessionId + ":" + vin);
if (StringUtils.isNotBlank(socketOvertime)) {
return;
}
LOGGER.error(String.format("会话:%s 超时.刹车:%s", sessionId, vin));
telecontrolModel.breakVehicle(vin);
}
}
}
\ No newline at end of file
package com.ssi.task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author ZhangLiYao
* @version 1.0
* @date 2020/8/6 10:00
*/
@Component
//@EnableScheduling
public class OperateDataTask {
@Autowired
private TaskOperateExecutor taskOperateExecutor;
// @Scheduled(cron = "0 0 0 * * ?")
private void opreateAnalysisOfTask() {
taskOperateExecutor.submitOpreateAnalysis();
}
}
package com.ssi.task;
import com.ssi.constant.VehicleConstant;
import com.ssi.entity.dto.VmsVehicleDto;
import com.ssi.mapper.VmsVehicleMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.mqtt.MQTTPublishClient;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Set;
/**
* 车辆下电后关闭后视视频流
*
* @author ZhangLiYao
* @version 1.0
* @date 2020/8/6 10:00
*/
@Component
@EnableScheduling
public class StopVideoTask {
@Autowired
private RedisDataModel redisDataModel;
@Value("${vehicle.video.keyPrefix:harbor:vehicle:video:status}")
private String videoStatusKey;
@Value("${vehicle.status:redis:keyPrefix:harbor:harbor:vehicle:online}")
private String vehicleStatusKey;
@Value("${mqtt.address}")
private String mqttAddress;
@Value("${mqtt.serverId}")
private String mqttServerId;
@Value("${mqtt.name}")
private String mqttName;
@Value("${mqtt.password}")
private String mqttPassword;
@Value("${mqtt.url}")
private String mqttUrl;
@Value("${mqtt.CAPath}")
private String mqttCAPath;
@Autowired
private VmsVehicleMapper vmsVehicleMapper;
@Scheduled(cron = "${task.stopVideoTask.cron}")
private void getOrdersOfTask() {
Set<String> keySet = redisDataModel.keys(videoStatusKey + "*");
if (CollectionUtils.isEmpty(keySet)) {
return;
}
for (String cacheKey : keySet) {
if (StringUtils.isBlank(cacheKey)) {
continue;
}
String videoStatus = redisDataModel.get(cacheKey);
if (VehicleConstant.VIDEO_STATUS_OFF == Integer.valueOf(videoStatus)) {
continue;
}
String vin = cacheKey.substring(22);
String online = redisDataModel.get(String.format("%s:%s", vehicleStatusKey, vin));
if (Integer.valueOf(online) == VehicleConstant.VEHICLE_STATUS_ONLINE) {
continue;
}
//车辆不在线,关闭后视推流
VmsVehicleDto vehicle = vmsVehicleMapper.queryVehicleByVin(vin);
MQTTPublishClient mqttClientSend = new MQTTPublishClient(mqttAddress, mqttServerId,
mqttCAPath, mqttName, mqttPassword, mqttUrl);
mqttClientSend.mqttRequest(vehicle, VehicleConstant.START_PUSHER);
}
}
}
package com.ssi.task;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ssi.entity.VmsChargingOrderInfo;
import com.ssi.entity.VmsChargingStation;
import com.ssi.entity.VmsChargingTotal;
import com.ssi.mapper.VmsChargingTotalMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.service.VmsChargingConnectorInfoService;
import com.ssi.service.VmsChargingEquipmentInfoService;
import com.ssi.service.VmsChargingOrderInfoService;
import com.ssi.service.VmsChargingStationService;
import com.ssi.utils.telaidian.TelaidianRequestTpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.mvel2.util.Make;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
/**
* @author SunnyHotz
* @PackageName:com.ssi.task
* @ClassName:TELDStationSyncTask
* @Description: 特来电充电桩信息及状态同步
* @date 2022/9/1 13:54
*/
@Slf4j
@Component
public class TELDStationSyncTask {
private static final ExecutorService executor = Executors.newFixedThreadPool(3);
@Autowired
private TelaidianRequestTpl telaidianRequestTpl;
@Autowired
private VmsChargingStationService vmsChargingStationService;
@Autowired
private VmsChargingEquipmentInfoService chargingEquipmentInfoService;
@Autowired
private VmsChargingConnectorInfoService chargingConnectorInfoService;
@Autowired
private VmsChargingOrderInfoService chargingOrderInfoService;
@Autowired
private VmsChargingTotalMapper chargingTotalMapper;
@Autowired
private RedisDataModel redisDataModel;
/**
* 充电桩信息维护
*/
@Scheduled(cron="0 0 0 * * ?")
public void syncEquipmentInfo(){
try {
JSONObject qryObj = new JSONObject();
qryObj.put("LastQueryTime", "");
qryObj.put("PageNo", 1);
qryObj.put("PageSize", 100);
JSONObject queryResult = telaidianRequestTpl.queryData(qryObj.toJSONString(), "query_stations_info", 1);
if (queryResult.getInteger("Ret") != 0) {
//请求异常信息,结束
log.error("TLD充电站信息请求异常:{}", queryResult.toJSONString());
return;
}
JSONObject data = queryResult.getJSONObject("Data");
//更新充电站信息
CompletableFuture<Void> future = CompletableFuture.runAsync(vmsChargingStationService.saveStationInfo(data), executor);
//更新设备信息
CompletableFuture<Void> future1 = CompletableFuture.runAsync(chargingEquipmentInfoService.saveEquipmentInfo(data), executor);
//更新充电接口信息
CompletableFuture<Void> future2 = CompletableFuture.runAsync(chargingConnectorInfoService.saveConnectorInfo(data), executor);
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future, future1,future2);
allOfFuture.get();
}catch (Exception e){
log.error("syncEquipmentInfo occur error:",e);
}
}
/**
* 定时同步设备接口状态
*/
@Scheduled(cron="0 */5 * * * ?")
public void syncConnectorStatus(){
try{
List<VmsChargingStation> list = vmsChargingStationService.list();
if(CollectionUtils.isEmpty(list)){
return;
}
List<String> collect = list.stream().map(VmsChargingStation::getStationId).collect(Collectors.toList());
JSONObject qryObj = new JSONObject();
qryObj.put("StationIDs", collect);
JSONObject queryResult = telaidianRequestTpl.queryData(qryObj.toJSONString(), "query_station_status", 1);
if (queryResult.getInteger("Ret") != 0) {
//请求异常信息,结束
log.error("TLD充电站信息请求异常:{}", queryResult.toJSONString());
return;
}
JSONObject data = queryResult.getJSONObject("Data");
JSONArray stationStatusInfos = data.getJSONArray("StationStatusInfos");
for (int i = 0; i < stationStatusInfos.size(); i++) {
chargingConnectorInfoService.updateStatus(stationStatusInfos.getJSONObject(i));
}
}catch (Exception e){
log.error("syncConnectorStatus occur error:",e);
}
}
/**
* 查询充电站订单信息
*/
@Scheduled(cron="0 */10 * * * ?")
public void qryCurrentStationOrder() {
try{
List<VmsChargingStation> list = vmsChargingStationService.list();
if(CollectionUtils.isEmpty(list)){
return;
}
List<String> collect = list.stream().map(VmsChargingStation::getStationId).collect(Collectors.toList());
for (String stationID: collect){
JSONObject qryObj = new JSONObject();
qryObj.put("StationID", stationID);
JSONObject queryResult = telaidianRequestTpl.queryData(qryObj.toJSONString(), "query_chargingorder_list", 1);
if (queryResult.getInteger("Ret") != 0) {
//请求异常信息,结束
log.error("TLD充电站当前订单请求异常:{}", queryResult.toJSONString());
return;
}
JSONObject data = queryResult.getJSONObject("Data");
JSONArray orderCodeS = data.getJSONArray("OrderCodeS");
for (int i = 0; i < orderCodeS.size(); i++) {
String orderId = orderCodeS.getString(i);
VmsChargingOrderInfo byId = chargingOrderInfoService.getById(orderId);
if(Objects.isNull(byId)){
VmsChargingOrderInfo vmsChargingOrderInfo = componentChargingOrderInfo(orderId);
chargingOrderInfoService.save(vmsChargingOrderInfo);
}
}
}
}catch (Exception e){
log.error("qryCurrentStationOrder occur error:",e);
}
}
/**
* 查询已完成充电站订单信息
*/
@Scheduled(cron="0 */30 * * * ?")
public void collectCompeletedOrders(){
try{
JSONObject qryObj = new JSONObject();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
LocalDateTime beforeTime = now.minusHours(2);
qryObj.put("QueryStartTime", df.format(beforeTime));
qryObj.put("QueryEndTime", df.format(now));
JSONObject queryResult = telaidianRequestTpl.queryData(qryObj.toJSONString(), "query_order_info", 1);
if (queryResult.getInteger("Ret") != 0) {
//请求异常信息,结束
log.error("TLD充电站已完成订单请求异常:{}", queryResult.toJSONString());
return;
}
JSONObject data = queryResult.getJSONObject("Data");
JSONArray orderInfos = data.getJSONArray("OrderInfos");
for (int i = 0; i < orderInfos.size(); i++) {
JSONObject orderObj = orderInfos.getJSONObject(i);
VmsChargingOrderInfo oldEntity = chargingOrderInfoService.getById(orderObj.getString("StartChargeSeq"));
if(Objects.isNull(oldEntity)){
oldEntity = new VmsChargingOrderInfo();
oldEntity.setStartChargeSeq(orderObj.getString("StartChargeSeq"));
}
oldEntity.setElect(orderObj.getDouble("Elect"));
oldEntity.setStartTime(orderObj.getDate("StartTime"));
oldEntity.setEndTime(orderObj.getDate("EndTime"));
chargingOrderInfoService.saveOrUpdate(oldEntity);
// if(StringUtils.isNotBlank(oldEntity.getVin())){
// saveChargingTotal(orderObj,oldEntity.getVin());
// }
}
}catch (Exception e){
log.error("collectCompeletedOrders occur error:",e);
}
}
private void saveChargingTotal(JSONObject oldEntity,String vin) {
VmsChargingTotal startChargeSeq = chargingTotalMapper.selectById(oldEntity.getString("StartChargeSeq"));
VmsChargingTotal vmsChargingTotal = new VmsChargingTotal();
vmsChargingTotal.setId(oldEntity.getString("StartChargeSeq"));
vmsChargingTotal.setChargingEnergy(oldEntity.getBigDecimal("Elect"));
vmsChargingTotal.setYear(String.valueOf(LocalDate.now().getYear()));
vmsChargingTotal.setVin(vin);
vmsChargingTotal.setStartTime(oldEntity.getDate("StartTime").getTime());
vmsChargingTotal.setEndTime(oldEntity.getDate("EndTime").getTime());
vmsChargingTotal.setDuration(vmsChargingTotal.getEndTime()-vmsChargingTotal.getStartTime());
if(Objects.isNull(startChargeSeq)){
chargingTotalMapper.insert(vmsChargingTotal);
}else {
chargingTotalMapper.updateById(vmsChargingTotal);
}
}
/**
* 请求当前订单信息
* @param orderId
* @return
*/
private VmsChargingOrderInfo componentChargingOrderInfo(String orderId) {
if(StringUtils.isBlank(orderId)){
return null;
}
VmsChargingOrderInfo defaultResult = new VmsChargingOrderInfo();
defaultResult.setStartChargeSeq(orderId);
try{
JSONObject qryObj = new JSONObject();
qryObj.put("StartChargeSeq", orderId);
JSONObject queryResult = telaidianRequestTpl.queryData(qryObj.toJSONString(), "query_equip_charge_status", 1);
if (queryResult.getInteger("Ret") != 0) {
//请求异常信息,结束
log.error("TLD充电站订单详细信息请求异常:{}", queryResult.toJSONString());
return defaultResult;
}
String data = queryResult.getString("Data");
if(StringUtils.isNotBlank(data)){
VmsChargingOrderInfo vmsChargingOrderInfo = JSONObject.parseObject(data, VmsChargingOrderInfo.class);
if(StringUtils.isNotBlank(vmsChargingOrderInfo.getVin())){
String s = redisDataModel.get("harbor:command:status:".concat(vmsChargingOrderInfo.getVin()));
JSONObject jsonObject = JSON.parseObject(s);
if(jsonObject.getInteger("chargingStatus")==1){
vmsChargingOrderInfo.setTaskNo(jsonObject.getString("taskNo"));
}
}
vmsChargingOrderInfo.setStartChargeSeq(orderId);
return vmsChargingOrderInfo;
}
}catch (Exception e){
log.error("componentChargingOrderInfo occur error:",e);
}
return defaultResult;
}
}
package com.ssi.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.VmsVehicleOperateTask;
import com.ssi.entity.dto.VehicleTerminalData;
import com.ssi.mapper.VmsVehicleOperateTaskMapper;
import com.ssi.service.VmsVehicleService;
import com.ssi.utils.DateUtils;
import com.ssi.utils.ElasticSearchUtil;
import com.ssi.utils.GpsUtil;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author ZhangLiYao
* @version 1.0
* @date 2020/8/6 10:03
*/
@Component
public class TaskOperateExecutor {
private static Logger log = LoggerFactory.getLogger(TaskOperateExecutor.class);
@Autowired
private VmsVehicleService vmsVehicleService;
@Autowired
private VmsVehicleOperateTaskMapper vmsVehicleOperateTaskMapper;
@Autowired
private RestHighLevelClient restHighLevelClient;
@Value("${analysis.vehicle-data.es-index-name}")
private String esVehicleDataIndexName;
@Value("${analysis.vehicle-data.index-rule:year}")
private String indexRule;
public void submitOpreateAnalysis() {
log.info("车辆运营数据定时任务开始执行-------");
List<VmsVehicle> list = vmsVehicleService.list();
list.stream().forEach(vehicle -> {
VmsVehicleOperateTask vmsVehicleOperateTask = getVehicleOpreate(vehicle.getVin());
int count = vmsVehicleOperateTaskMapper.selectCount(
new LambdaQueryWrapper<VmsVehicleOperateTask>()
.eq(VmsVehicleOperateTask::getVin, vehicle.getVin())
.eq(VmsVehicleOperateTask::getTaskDate, vmsVehicleOperateTask.getTaskDate()));
if (count <= 0) {
vmsVehicleOperateTaskMapper.insert(vmsVehicleOperateTask);
}
});
log.info("车辆运营数据定时任务执行完毕-------");
}
private VmsVehicleOperateTask getVehicleOpreate(String vin) {
long[] yesterday = getYesterday();
VmsVehicleOperateTask vmsVehicleOperateTask = new VmsVehicleOperateTask();
vmsVehicleOperateTask = getVehicleOpreateByTime(vin, yesterday[0], yesterday[1]);
return vmsVehicleOperateTask;
}
public VmsVehicleOperateTask getVehicleOpreateByTime(String vin, Long startTime, Long stopTime) {
VmsVehicleOperateTask vmsVehicleOperateTask = new VmsVehicleOperateTask();
vmsVehicleOperateTask.setVin(vin);
vmsVehicleOperateTask.setOperateMile(new BigDecimal(0));
vmsVehicleOperateTask.setOperateTime(new BigDecimal(0));
vmsVehicleOperateTask.setMileVal(0D);
vmsVehicleOperateTask.setTimeVal(0L);
vmsVehicleOperateTask.setTaskDate(
DateUtils.format(new Date(startTime), DateUtils.DATE_PATTERN));
try {
searchByTime(vmsVehicleOperateTask, startTime, stopTime);
} catch (IOException e) {
e.printStackTrace();
log.error("查询数据失败,vin:" + vmsVehicleOperateTask.getVin());
}
vmsVehicleOperateTask.setOperateMile(
BigDecimal.valueOf(vmsVehicleOperateTask.getMileVal()).setScale(2, BigDecimal.ROUND_UP));
vmsVehicleOperateTask.setOperateTime(BigDecimal.valueOf(vmsVehicleOperateTask.getTimeVal())
.divide(new BigDecimal(60 * 60 * 1000), 2, BigDecimal.ROUND_HALF_UP));
return vmsVehicleOperateTask;
}
private void searchByTime(VmsVehicleOperateTask vmsVehicleOperateTask, Long startTime,
Long stopTime) throws IOException {
Set<String> columns = Sets.newHashSet("vin", "location", "longitude", "latitude", "collectTime"
, "receiveTime", "speed");
Gson gson = new GsonBuilder().create();
int size = 10000;
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(10L));
SearchResponse response = getSearchResponse(vmsVehicleOperateTask.getVin(), startTime, stopTime,
size, scroll, columns);
String scrollId = response.getScrollId();
SearchHit[] searchHits = response.getHits().getHits();
VehicleTerminalData lastVehicleTerminalData = null;
while (searchHits != null && searchHits.length > 0) {
for (SearchHit hit : searchHits) {
VehicleTerminalData currentVehicleTerminalData = null;
String sourceAsString = hit.getSourceAsString();
if (sourceAsString != null) {
currentVehicleTerminalData = parseVehicleTerminalDate(gson, sourceAsString);
}
if (lastVehicleTerminalData != null && currentVehicleTerminalData != null) {
long time = currentVehicleTerminalData.getCollectTime()
- lastVehicleTerminalData.getCollectTime();
if (time <= 60000) {
caclMile(vmsVehicleOperateTask, lastVehicleTerminalData, currentVehicleTerminalData);
caclTime(vmsVehicleOperateTask, lastVehicleTerminalData, currentVehicleTerminalData);
}
}
lastVehicleTerminalData = currentVehicleTerminalData;
}
/* Next batch data. */
if (searchHits.length == size) {
response = getNextScrollResponse(scrollId, scroll);
searchHits = response.getHits().getHits();
} else {
break;
}
}
clearScroll(scrollId);
}
private void caclTime(VmsVehicleOperateTask vmsVehicleOperateTask,
VehicleTerminalData lastVehicleTerminalData, VehicleTerminalData currentVehicleTerminalData) {
long time =
currentVehicleTerminalData.getCollectTime() - lastVehicleTerminalData.getCollectTime();
vmsVehicleOperateTask.setTimeVal(vmsVehicleOperateTask.getTimeVal() + time);
}
private void caclMile(VmsVehicleOperateTask vmsVehicleOperateTask,
VehicleTerminalData lastVehicleTerminalData, VehicleTerminalData currentVehicleTerminalData) {
// Double dist = GpsUtil.getDistance(lastVehicleTerminalData.getLatitude(),
// lastVehicleTerminalData.getLongitude(), currentVehicleTerminalData.getLatitude(),
// currentVehicleTerminalData.getLongitude());
// if (dist > 0 && dist < 1 && currentVehicleTerminalData.getSpeed().compareTo(BigDecimal.ZERO)!=0) {
// vmsVehicleOperateTask.setMileVal(vmsVehicleOperateTask.getMileVal() + dist);
// }
if (lastVehicleTerminalData.getSpeed().doubleValue() >= 0.0
&& currentVehicleTerminalData.getSpeed().doubleValue() >= 0.0) {
double curSpeed = currentVehicleTerminalData.getSpeed().doubleValue();
double lastSpeed = lastVehicleTerminalData.getSpeed().doubleValue();
double avgSpeed = (lastSpeed + curSpeed) / 2;
long time =
currentVehicleTerminalData.getCollectTime() - lastVehicleTerminalData.getCollectTime();
double mile = avgSpeed / 60 / 60 * (time / 1000);
vmsVehicleOperateTask.setMileVal(vmsVehicleOperateTask.getMileVal() + mile);
}
}
private long[] getYesterday() {
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH) - 1, 0, 0, 0);
long start = calendar.getTime().getTime();
Calendar calendar2 = Calendar.getInstance();
calendar2.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH) - 1, 23, 59, 59);
long end = calendar2.getTime().getTime();
long[] result = new long[]{start, end};
return result;
}
private VehicleTerminalData parseVehicleTerminalDate(Gson gson, String jsonStr) {
try {
return gson.fromJson(jsonStr, VehicleTerminalData.class);
} catch (Throwable t) {
log.error("[Analysis Executor]Fail to convert VehicleTerminalDate vmstoorders.\n" +
jsonStr, t);
}
return null;
}
private SearchResponse getSearchResponse(String vin, Long startTime, Long stopTime, int size,
Scroll scroll, Set<String> columns) throws IOException {
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(size);
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("vin", vin);
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("collectTime");
rangeQueryBuilder.gte(startTime);
rangeQueryBuilder.lte(stopTime);
boolBuilder.must(rangeQueryBuilder);
boolBuilder.must(matchQueryBuilder);
FieldSortBuilder fieldSortBuilder = new FieldSortBuilder("collectTime");
sourceBuilder.query(boolBuilder);
sourceBuilder.sort(fieldSortBuilder);
sourceBuilder.timeout(new TimeValue(600, TimeUnit.SECONDS));
sourceBuilder.fetchSource(columns.toArray(new String[columns.size()]), null);
String[] indexs = ElasticSearchUtil.getIndexs(startTime, stopTime, esVehicleDataIndexName, 1,
true, indexRule);
SearchRequest searchRequest = new SearchRequest(indexs);
searchRequest.scroll(scroll);
searchRequest.source(sourceBuilder);
return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
}
private SearchResponse getNextScrollResponse(String scrollId, Scroll scroll) throws IOException {
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(scroll);
return restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
}
private void clearScroll(String scrollId) throws IOException {
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
}
}
package com.ssi.task;
import com.ssi.service.VmsTosOrdersAnalysisService;
import com.ssi.service.VmsTosOrdersOeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
/**
* 车辆任务分析任务
*/
@Component
@EnableScheduling
public class TosAnalysisTask {
@Autowired
private VmsTosOrdersAnalysisService vmsTosOrdersAnalysisService;
@Autowired
private VmsTosOrdersOeeService vmsTosOrdersOeeService;
/**
* 装卸箱、理货分析任务
*/
@Scheduled(cron = "${task.tosAnalysisTask.cron}")
public void runTosAnalysisTask() {
LocalDateTime startTime = LocalDateTime.of(
LocalDateTime.now().minus(1, ChronoUnit.DAYS).toLocalDate(), LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(
LocalDateTime.now().minus(1, ChronoUnit.DAYS).toLocalDate(), LocalTime.MAX);
vmsTosOrdersAnalysisService.runTosAnalysisTask(startTime, endTime);
}
/**
* 任务执行OEE分析任务
*/
@Scheduled(cron = "${task.tosOeeTask.cron}")
public void runTosOeeTask() {
LocalDateTime endTime = LocalDateTime.now();
LocalDateTime startTime = endTime.minus(24, ChronoUnit.HOURS);
vmsTosOrdersOeeService.runTosOeeTask(startTime, endTime);
}
}
package com.ssi.task;
import com.ssi.service.VmsTosOrderDailyKpiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @description: Order Daily Kpi 定时任务
* @author: dt
* @create: 2022-10-31 16:40
*/
@Component
@EnableScheduling
public class VmsTosOrderDailyKpiTask {
private final Logger logger = LoggerFactory.getLogger(VmsTosOrderDailyKpiTask.class);
private VmsTosOrderDailyKpiService vmsTosOrderDailyKpiService;
public VmsTosOrderDailyKpiTask(VmsTosOrderDailyKpiService vmsTosOrderDailyKpiService) {
this.vmsTosOrderDailyKpiService = vmsTosOrderDailyKpiService;
}
/**
* 定期每隔多长时间执行任务
*/
@Scheduled(fixedDelay = 1000*60*10)
public void analysisTosOrderDailyKpi() {
logger.info("------ 执行 kpi 分析任务开始,时间: "+ LocalDateTime.now().toString()+" ------");
vmsTosOrderDailyKpiService.analysisTosOrderDailyKpi(null);
logger.info("------ 执行 kpi 分析任务结束,时间: "+ LocalDateTime.now().toString()+" ------");
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment