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.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.constant.enums.VmsTosOrderStatusEnum;
import com.ssi.entity.VmsHangerStatusInfo;
import com.ssi.mapper.VmsHangerStatusInfoMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.response.SSIResponse;
import com.ssi.service.VmsHangerStatusInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.Map;
/**
* 吊具状态服务实现类
*/
@Service("vmsHangerStatusInfoService")
public class VmsHangerStatusInfoServiceImpl extends ServiceImpl<VmsHangerStatusInfoMapper, VmsHangerStatusInfo> implements VmsHangerStatusInfoService {
@Autowired
private RedisDataModel redisDataModel;
@Value("${order.latestOrderKeyPrefix:harbor:command:status}")
private String latestOrderKeyPrefix;
@Value("${harbor.vehicle.confirm_status_prefix}")
private String harborVehicleConfirmStatusPrefix;
@Value("${harbor.crane.realTimeInfoKeyPrefix}")
private String craneRealTimeInfoKeyPrefix;
@Override
public IPage<VmsHangerStatusInfo> queryPage(int current, int size, VmsHangerStatusInfo vmsHangerStatusInfo) {
IPage<VmsHangerStatusInfo> page = new Page<>(current, size);
QueryWrapper<VmsHangerStatusInfo> wrapper = new QueryWrapper<>();
return this.page(page,wrapper);
}
/**
* 查询车辆装卸箱时吊具状态信息
*/
@Override
public SSIResponse getHangerStatusByVin(String vin) {
String orderKey = String.format("%s:%s", latestOrderKeyPrefix, vin);
Map<String, Object> map = redisDataModel.getJson2Map(orderKey);
if(map != null){
int status = (int) map.get("status");
if(VmsTosOrderStatusEnum.isLoadUnloadStatus(status)){
String portCode = (String) map.get("portCode");
if(portCode == null){
return SSIResponse.no("未查询到吊具状态信息");
}
Map<String, Object> hangerStatusMap = redisDataModel.getJson2Map(String.format("%s:%s", craneRealTimeInfoKeyPrefix, portCode));
hangerStatusMap.put("orderStatus",status);
String confirmStatusKey = String.format("%s:%s", harborVehicleConfirmStatusPrefix, vin);
Map<String, Object> confirmStatusMap = redisDataModel.getJson2Map(confirmStatusKey);
hangerStatusMap.putAll(confirmStatusMap);
return SSIResponse.ok(hangerStatusMap);
}else{
return SSIResponse.no("等待车辆停稳锁死");
}
}
return SSIResponse.no("未查询到车辆任务");
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsIndividuationConfig;
import com.ssi.entity.VmsTerminalVersion;
import com.ssi.response.SSIPage;
import com.ssi.service.VmsIndividuationConfigService;
import com.ssi.mapper.VmsIndividuationConfigMapper;
import com.ssi.utils.QueryUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
*
*/
@Service
public class VmsIndividuationConfigServiceImpl extends ServiceImpl<VmsIndividuationConfigMapper, VmsIndividuationConfig>
implements VmsIndividuationConfigService{
@Override
public SSIPage queryPage(VmsIndividuationConfig params) {
IPage<VmsIndividuationConfig> page = this.page(
new Page<>(params.getPageIndex(),params.getPageSize()),
new LambdaQueryWrapper<VmsIndividuationConfig>()
.like(StringUtils.isNotBlank(params.getConfigKey()),VmsIndividuationConfig::getConfigKey,params.getConfigKey())
.eq(VmsIndividuationConfig::getStatus,1)
.orderByDesc(VmsIndividuationConfig::getCreateTime)
);
return new SSIPage(page);
}
@Override
public List<VmsIndividuationConfig> listByParent(String name) {
return this.baseMapper.listByParent(name);
}
}
package com.ssi.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsKpiAnalysis;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.vo.KpiCostTimeVo;
import com.ssi.mapper.VmsKpiAnalysisMapper;
import com.ssi.response.SSIResponse;
import com.ssi.service.VmsKpiAnalysisService;
import com.ssi.service.VmsVehicleService;
import com.ssi.utils.DateUtils;
import com.ssi.utils.PoiUtils;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author Admin
* @description 针对表【vms_kpi_analysis】的数据库操作Service实现
* @createDate 2023-02-28 14:17:30
*/
@Slf4j
@Service
public class VmsKpiAnalysisServiceImpl extends ServiceImpl<VmsKpiAnalysisMapper, VmsKpiAnalysis>
implements VmsKpiAnalysisService{
@Autowired
private VmsVehicleService vmsVehicleService;
@Override
public List<JSONObject> staticsWorkTime(KpiCostTimeVo kpiCostTimeVo) {
return this.baseMapper.staticsWorkTime(kpiCostTimeVo);
}
@Override
public List<JSONObject> taskAnalysis(KpiCostTimeVo kpiCostTimeVo) {
kpiCostTimeVo.setVehicleTaskLabels(Arrays.asList(TaskType.LOAD_TASK.code,TaskType.UNLOAD_TASK.code));
List<VmsKpiAnalysis> vmsKpiAnalyses = this.baseMapper.taskAnalysis(kpiCostTimeVo);
if(CollectionUtils.isEmpty(vmsKpiAnalyses)){
return Collections.emptyList();
}
// List<VmsKpiAnalysis> mergedList = componentWholeOrder(vmsKpiAnalyses);
//计算统计数据
return kaiCalculate(vmsKpiAnalyses);
}
@Override
public VmsKpiAnalysis staticsSpeciParam(KpiCostTimeVo qryKpi) {
return this.baseMapper.staticsSpeciParam(qryKpi);
}
@Override
public JSONObject taskIndexAnalysis(KpiCostTimeVo qryKpi) {
qryKpi.setVehicleTaskLabels(Arrays.asList(TaskType.LOAD_TASK.code,TaskType.UNLOAD_TASK.code,TaskType.COMPETE_TASK.code));
List<VmsKpiAnalysis> vmsKpiAnalyses = this.baseMapper.taskAnalysis(qryKpi);
JSONObject result = new JSONObject();
if(CollectionUtils.isEmpty(vmsKpiAnalyses)){
return result;
}
List<VmsKpiAnalysis> mergedList = componentWholeOrder(vmsKpiAnalyses);
result.put("totalTask",mergedList.size());
Map<Integer, List<VmsKpiAnalysis>> lableCollect = mergedList.stream().collect(Collectors.groupingBy(VmsKpiAnalysis::getVehicleTaskLabel, Collectors.toList()));
result.put("loadTask",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?lableCollect.get(TaskType.LOAD_TASK.code).size():0);
result.put("loadNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?lableCollect.get(TaskType.LOAD_TASK.code).size():0);
result.put("loadStandNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?lableCollect.get(TaskType.LOAD_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getStandardBoxNum).sum():0);
result.put("loadAvaTime",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?new BigDecimal(lableCollect.get(TaskType.LOAD_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getWorkTime).sum()/lableCollect.get(TaskType.LOAD_TASK.code).size()).setScale(2,RoundingMode.HALF_UP):0);
result.put("unloadTask",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?lableCollect.get(TaskType.UNLOAD_TASK.code).size():0);
result.put("unloadNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?lableCollect.get(TaskType.UNLOAD_TASK.code).size():0);
result.put("unloadStandNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?lableCollect.get(TaskType.UNLOAD_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getStandardBoxNum).sum():0);
result.put("unloadAvaTime",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?new BigDecimal(lableCollect.get(TaskType.UNLOAD_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getWorkTime).sum()/lableCollect.get(TaskType.UNLOAD_TASK.code).size()).setScale(2,RoundingMode.HALF_UP):0);
result.put("competeTask",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?lableCollect.get(TaskType.COMPETE_TASK.code).size():0);
result.put("competeNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?lableCollect.get(TaskType.COMPETE_TASK.code).size():0);
result.put("competeStandNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?lableCollect.get(TaskType.COMPETE_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getStandardBoxNum).sum():0);
result.put("competeAvaTime",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?new BigDecimal(lableCollect.get(TaskType.COMPETE_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getWorkTime).sum()/lableCollect.get(TaskType.COMPETE_TASK.code).size()).setScale(2,RoundingMode.HALF_UP):0);
return result;
}
@Override
public SSIResponse getTaskTrend(Integer timeType, Integer groupType) {
assert timeType!=null:"时间不能为空";
assert groupType!=null:"分组类型不能为空";
int deltDate = timeType==2?7:timeType==3?30:1;
LocalDateTime startTime = LocalDateTime.of(
LocalDateTime.now().minus(deltDate, ChronoUnit.DAYS).toLocalDate(), LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(
LocalDateTime.now().minus(1, ChronoUnit.DAYS).toLocalDate(), LocalTime.MAX);
List<VmsKpiAnalysis> taskTrends = this.baseMapper.getTaskTrend(startTime.toInstant(ZoneOffset.of("+8")).toEpochMilli(), endTime.toInstant(ZoneOffset.of("+8")).toEpochMilli());
List<VmsKpiAnalysis> vmsKpiAnalyses = componentWholeOrder(taskTrends);
//分组
Map<String, List<VmsKpiAnalysis>> groupMap = vmsKpiAnalyses.stream().collect(Collectors.groupingBy(vmsKpiAnalysis -> {
if (groupType == 1) {
String portCode = vmsKpiAnalysis.getPortCode();
return StringUtils.isNotBlank(portCode)?portCode:"other";
} else if (groupType == 2) {
String voyageNo = vmsKpiAnalysis.getVoyageNo();
return StringUtils.isNotBlank(voyageNo)?voyageNo:"other";
} else if (groupType == 3) {
Long collectTime = vmsKpiAnalysis.getCollectTime();
Date date = new Date(collectTime);
if (timeType == 1) {
return DateUtils.format(date, "HH");
}
return DateUtils.format(date, DateUtils.DATE_PATTERN);
}
VmsVehicle one = vmsVehicleService.lambdaQuery().eq(VmsVehicle::getVin, vmsKpiAnalysis.getVin()).one();
return Objects.isNull(one)?vmsKpiAnalysis.getVin():one.getVehicleNum();
}, Collectors.toList()));
List<JSONObject> jsonObjects = calTaskTrend(groupMap);
if(groupType==3){//时间填充坐标轴
fillTimeLine(startTime,endTime,jsonObjects);
}
jsonObjects.sort(Comparator.comparing(a -> a.getString("xAis")));
return SSIResponse.ok(jsonObjects);
}
@Override
public void exportExcel(KpiCostTimeVo kpiCostTimeVo, HttpServletResponse response) {
List<VmsKpiAnalysis> vmsKpiAnalyses = this.baseMapper.taskAnalysis(kpiCostTimeVo);
String fileName = "KPI数据详情" + DateUtils.format(new Date(), 2) + ".xls";
PoiUtils.exportExcel(vmsKpiAnalyses, null,
"orderList", VmsKpiAnalysis.class,
fileName, true, response);
}
@Override
public List<String> getVoyageNo() {
return this.baseMapper.getVoyageNo();
}
private void fillTimeLine(LocalDateTime startTime, LocalDateTime endTime, List<JSONObject> jsonObjects) {
String formatter = "yyyy-MM-dd";
if(startTime.toLocalDate().compareTo(endTime.toLocalDate())==0){
formatter = "HH";
}
do{
String format = startTime.format(DateTimeFormatter.ofPattern(formatter));
Boolean xAis = jsonObjects.stream().filter(jsonObject -> jsonObject.getString("xAis").equalsIgnoreCase(format)).findAny().isPresent();
log.info("~~{} 存在吗 {}",format,xAis);
if(!xAis){
JSONObject tmpObj = new JSONObject();
tmpObj.put("xAis",format);
tmpObj.put("loadNum",0);
tmpObj.put("unloadNum",0);
tmpObj.put("competeNum",0);
tmpObj.put("loadAvaTime",0);
tmpObj.put("unloadAvaTime",0);
tmpObj.put("competeAvaTime",0);
jsonObjects.add(tmpObj);
}
if(startTime.toLocalDate().compareTo(endTime.toLocalDate())==0){
startTime = startTime.plusHours(1l);
}else {
startTime = startTime.plusDays(1l);
}
}while (startTime.compareTo(endTime)<0);
}
private List<JSONObject> calTaskTrend(Map<String, List<VmsKpiAnalysis>> groupMap) {
List<JSONObject> jsonObjects = new ArrayList<>();
for (Map.Entry<String, List<VmsKpiAnalysis>> entry:groupMap.entrySet()){
JSONObject jsonObject = new JSONObject();
jsonObject.put("xAis",entry.getKey());
List<VmsKpiAnalysis> mergedList = entry.getValue();
Map<Integer, List<VmsKpiAnalysis>> lableCollect = mergedList.stream().collect(Collectors.groupingBy(VmsKpiAnalysis::getVehicleTaskLabel, Collectors.toList()));
jsonObject.put("loadNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?lableCollect.get(TaskType.LOAD_TASK.code).size():0);
jsonObject.put("unloadNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?lableCollect.get(TaskType.UNLOAD_TASK.code).size():0);
jsonObject.put("competeNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?lableCollect.get(TaskType.COMPETE_TASK.code).size():0);
jsonObject.put("loadAvaTime",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?new BigDecimal(lableCollect.get(TaskType.LOAD_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getWorkTime).sum()/lableCollect.get(TaskType.LOAD_TASK.code).size()).setScale(2,RoundingMode.HALF_UP):0);
jsonObject.put("unloadAvaTime",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?new BigDecimal(lableCollect.get(TaskType.UNLOAD_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getWorkTime).sum()/lableCollect.get(TaskType.UNLOAD_TASK.code).size()).setScale(2,RoundingMode.HALF_UP):0);
jsonObject.put("competeAvaTime",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?new BigDecimal(lableCollect.get(TaskType.COMPETE_TASK.code).stream().mapToDouble(VmsKpiAnalysis::getWorkTime).sum()/lableCollect.get(TaskType.COMPETE_TASK.code).size()).setScale(2,RoundingMode.HALF_UP):0);
jsonObject.put("loadStandNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.LOAD_TASK.code))?lableCollect.get(TaskType.LOAD_TASK.code).stream().filter(e->Objects.nonNull(e.getStandardBoxNum())).mapToDouble(VmsKpiAnalysis::getStandardBoxNum).sum():0);
jsonObject.put("unloadStandNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.UNLOAD_TASK.code))?lableCollect.get(TaskType.UNLOAD_TASK.code).stream().filter(e->Objects.nonNull(e.getStandardBoxNum())).mapToDouble(VmsKpiAnalysis::getStandardBoxNum).sum():0);
jsonObject.put("competeStandNum",CollectionUtils.isNotEmpty(lableCollect.get(TaskType.COMPETE_TASK.code))?lableCollect.get(TaskType.COMPETE_TASK.code).stream().filter(e->Objects.nonNull(e.getStandardBoxNum())).mapToDouble(VmsKpiAnalysis::getStandardBoxNum).sum():0);
jsonObjects.add(jsonObject);
}
return jsonObjects;
}
private List<JSONObject> kaiCalculate(List<VmsKpiAnalysis> mergedList) {
List<JSONObject> resultList = new ArrayList<>();
if(CollectionUtils.isEmpty(mergedList)){
return resultList;
}
Map<String, List<VmsKpiAnalysis>> vinListMap = mergedList.stream().collect(Collectors.groupingBy(VmsKpiAnalysis::getVin, Collectors.toList()));
for (Map.Entry<String, List<VmsKpiAnalysis>> entry : vinListMap.entrySet()){
//平均收箱里程, 平均送箱里程, 单圈里程 重载率(%)空载率(%)
List<VmsKpiAnalysis> tmpList = entry.getValue();
double receiveMile = tmpList.stream().filter(vmsKpiAnalysis -> vmsKpiAnalysis.getTaskType() == TaskType.LOAD_TASK.code).mapToDouble(VmsKpiAnalysis::getMileage).sum();
double senMile = tmpList.stream().filter(vmsKpiAnalysis -> vmsKpiAnalysis.getTaskType() == TaskType.UNLOAD_TASK.code).mapToDouble(VmsKpiAnalysis::getMileage).sum();
double receiveTime = tmpList.stream().filter(vmsKpiAnalysis -> vmsKpiAnalysis.getTaskType() == TaskType.LOAD_TASK.code).mapToDouble(VmsKpiAnalysis::getWorkTime).sum();
double senTime = tmpList.stream().filter(vmsKpiAnalysis -> vmsKpiAnalysis.getTaskType() == TaskType.UNLOAD_TASK.code).mapToDouble(VmsKpiAnalysis::getWorkTime).sum();
double total = receiveMile+senMile;
JSONObject jsonObject = new JSONObject();
VmsVehicle one = vmsVehicleService.lambdaQuery().eq(VmsVehicle::getVin, entry.getKey()).one();
jsonObject.put("vin",Objects.nonNull(one)?one.getVehicleNum():entry.getKey());
jsonObject.put("avgReciveMile", new BigDecimal(receiveMile/tmpList.size()).setScale(2, RoundingMode.HALF_UP));
jsonObject.put("avgSendMile", new BigDecimal(senMile/tmpList.size()).setScale(2, RoundingMode.HALF_UP));
jsonObject.put("singleMile", new BigDecimal(total/tmpList.size()).setScale(2, RoundingMode.HALF_UP));
jsonObject.put("loadRatio", new BigDecimal(receiveTime/(receiveTime+senTime)).setScale(2, RoundingMode.HALF_UP));
jsonObject.put("unloadRatio", new BigDecimal(senTime/(receiveTime+senTime)).setScale(2, RoundingMode.HALF_UP));
resultList.add(jsonObject);
}
return resultList;
}
/**
*
* @param vmsKpiAnalyses 未组装任务列表
* @return 组装好的任务列表
*/
private List<VmsKpiAnalysis> componentWholeOrder(List<VmsKpiAnalysis> vmsKpiAnalyses) {
List<VmsKpiAnalysis> mergedList = new ArrayList<>();
Map<String,VmsKpiAnalysis> tmpMap = new HashMap<>();
for (VmsKpiAnalysis vmsKpiAnalysis: vmsKpiAnalyses) {
VmsKpiAnalysis oldKpi = tmpMap.get(vmsKpiAnalysis.getVin());
if(Objects.isNull(oldKpi)){
tmpMap.put(vmsKpiAnalysis.getVin(),vmsKpiAnalysis);
continue;
}
//任务合并逻辑
int mergeFlag = mergeTaskInfo(mergedList, oldKpi, vmsKpiAnalysis);
if(mergeFlag==0){
tmpMap.remove(vmsKpiAnalysis.getVin());
}
//处理任务异常逻辑
if(mergeFlag==1){
tmpMap.put(vmsKpiAnalysis.getVin(),vmsKpiAnalysis);
}
}
//处理剩余数据
tmpMap.forEach((k,v)->{
if((v.getVehicleTaskLabel()==TaskType.LOAD_TASK.code&&v.getPortType()==1)
||(v.getVehicleTaskLabel()==TaskType.UNLOAD_TASK.code&&v.getPortType()==2)
||(v.getVehicleTaskLabel()==TaskType.COMPETE_TASK.code&&v.getPortType()==2)
){
mergedList.add(v);
}
});
return mergedList;
}
/**
*
* @param mergedList
* @param oldKpi
* @param vmsKpiAnalysis
* @return 0: 完成任务链,List新增任务,移除tmpMap; 1: 任务变更,List新增任务,覆盖旧任务;2:任务周期中,无需操作
*/
private int mergeTaskInfo(List<VmsKpiAnalysis> mergedList, VmsKpiAnalysis oldKpi, VmsKpiAnalysis vmsKpiAnalysis) {
//非当前任务||旧任务为结束任务
if(oldKpi.getVehicleTaskLabel()!=vmsKpiAnalysis.getVehicleTaskLabel()
||(oldKpi.getVehicleTaskLabel()==TaskType.LOAD_TASK.code&&oldKpi.getPortType()==1)
||(oldKpi.getVehicleTaskLabel()==TaskType.UNLOAD_TASK.code&&oldKpi.getPortType()==2)
||(oldKpi.getVehicleTaskLabel()==TaskType.COMPETE_TASK.code&&oldKpi.getPortType()==2)
){
mergedList.add(oldKpi);
return 1;
}
//当前任务||新任务为起始任务, 多个起始任务统计为一个任务,
oldKpi.setMileage(oldKpi.getMileage()+vmsKpiAnalysis.getMileage());
oldKpi.setEnergyConsumption(oldKpi.getEnergyConsumption()+vmsKpiAnalysis.getEnergyConsumption());
oldKpi.setWorkTime(oldKpi.getWorkTime()+ vmsKpiAnalysis.getWorkTime());
oldKpi.setVehicleTaskLabel(vmsKpiAnalysis.getVehicleTaskLabel());
oldKpi.setPortType(vmsKpiAnalysis.getPortType());
if(StringUtils.isNotBlank(vmsKpiAnalysis.getPortCode())&&vmsKpiAnalysis.getPortType()==1) oldKpi.setPortCode(vmsKpiAnalysis.getPortCode());
if(StringUtils.isNotBlank(vmsKpiAnalysis.getVoyageNo())) oldKpi.setVoyageNo(vmsKpiAnalysis.getVoyageNo());
//相同任务类型, 判断是否为完整任务链
if((oldKpi.getVehicleTaskLabel()==TaskType.LOAD_TASK.code&&vmsKpiAnalysis.getPortType()==1)
||(oldKpi.getVehicleTaskLabel()==TaskType.UNLOAD_TASK.code&&vmsKpiAnalysis.getPortType()==2)
||(oldKpi.getVehicleTaskLabel()==TaskType.COMPETE_TASK.code&&vmsKpiAnalysis.getPortType()==2)
){
mergedList.add(oldKpi);
return 0;
}else {
return 2;
}
}
enum TaskType{
LOAD_TASK(1),
UNLOAD_TASK(2),
COMPETE_TASK(3);
private Integer code;
TaskType(Integer code) {
this.code = code;
}
public Integer getCode() {
return code;
}
}
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ssi.entity.VmsTosOrders;
import com.ssi.model.RedisDataModel;
import com.ssi.response.SSIResponse;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.mapper.VmsOrdersVehicleAlterMapper;
import com.ssi.entity.VmsOrdersVehicleAlter;
import com.ssi.service.VmsOrdersVehicleAlterService;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service("ordersVehicleAlterService")
public class VmsOrdersVehicleAlterServiceImpl extends ServiceImpl<VmsOrdersVehicleAlterMapper, VmsOrdersVehicleAlter> implements VmsOrdersVehicleAlterService {
@Autowired
private RedisDataModel redisDataModel;
@Value("${order.latestOrderKeyPrefix:harbor:command:status}")
private String latestOrderKeyPrefix;
/**
* 确认任务车辆
*/
@Override
public SSIResponse changeOrdersVehicle(String taskNo, String vin) {
int count = this.count(new LambdaQueryWrapper<VmsOrdersVehicleAlter>().eq(VmsOrdersVehicleAlter::getTaskNo, taskNo));
if(count > 0){
return SSIResponse.no("该任务已确认,请勿重复确认");
}
//获取任务原vin
String originalVin = null;
Set<String> keys = redisDataModel.keys(latestOrderKeyPrefix + "*");
List<String> list = redisDataModel.mget(keys.toArray(new String[keys.size()]));
if (CollectionUtils.isNotEmpty(keys)) {
if (CollectionUtils.isNotEmpty(list)) {
List<VmsTosOrders> res = list.stream().map(s -> JSON.parseObject(s,VmsTosOrders.class)).collect(Collectors.toList());
for(VmsTosOrders vmsTosOrders : res){
if(vmsTosOrders.getTaskNo().equals(taskNo)){
originalVin = vmsTosOrders.getVin();
}
}
}
}
VmsOrdersVehicleAlter vmsOrdersVehicleAlter = new VmsOrdersVehicleAlter();
vmsOrdersVehicleAlter.setTaskNo(taskNo);
vmsOrdersVehicleAlter.setVin(vin);
vmsOrdersVehicleAlter.setOriginalVin(originalVin);
this.save(vmsOrdersVehicleAlter);
return SSIResponse.ok();
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsPositionInfo;
import com.ssi.service.VmsPositionInfoService;
import com.ssi.mapper.VmsPositionInfoMapper;
import org.springframework.stereotype.Service;
/**
*
*/
@Service
public class VmsPositionInfoServiceImpl extends ServiceImpl<VmsPositionInfoMapper, VmsPositionInfo>
implements VmsPositionInfoService{
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.ssi.constant.URL;
import com.ssi.entity.vo.VmsRoadDeviceVo;
import com.ssi.mapper.VmsRoadDeviceMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.response.SSIPage;
import com.ssi.utils.RestTemplateUtil;
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 java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.utils.QueryUtils;
import com.ssi.entity.VmsRoadDevice;
import com.ssi.service.VmsRoadDeviceService;
/**
* 路侧设备服务实现类
*/
@Service("roadDeviceService")
public class VmsRoadDeviceServiceImpl extends ServiceImpl<VmsRoadDeviceMapper, VmsRoadDevice> implements VmsRoadDeviceService {
@Autowired
private RedisDataModel redisDataModel;
@Value("${road-device.video-platform-url}")
private String videoPlatformUrl;
@Value("${road-device.need-get-video}")
private boolean needGetVideo;
@Value("${harbor.v2x.rsm}")
private String rsmPrefix;
@Value("${BridgeCrane-url}")
private String bcUrl;// 桥吊 url
/**
* 路侧设备分页数据
* @param params
* @return
*/
@Override
public SSIPage queryPage(Map<String, Object> params) {
String deviceNum = (String) params.get("deviceNum");
String deviceType = (String) params.get("deviceType");
Integer onlineStatus = (Integer) params.get("onlineStatus");
Integer workStatus = (Integer) params.get("workStatus");
IPage<VmsRoadDevice> page = this.page(
new QueryUtils<VmsRoadDevice>().getPage(params),
new LambdaQueryWrapper<VmsRoadDevice>().like(StringUtils.isNotBlank(deviceNum), VmsRoadDevice::getDeviceNum, deviceNum)
.eq(StringUtils.isNotBlank(deviceType), VmsRoadDevice::getDeviceType, deviceType)
.eq(onlineStatus != null, VmsRoadDevice::getOnlineStatus, onlineStatus)
.eq(workStatus != null, VmsRoadDevice::getWorkStatus, workStatus)
);
if(needGetVideo){
page.getRecords().parallelStream().forEach(vmsRoadDevice -> {
getVideoPlayUrl(vmsRoadDevice);
});
}
page.getRecords().parallelStream().forEach(vmsRoadDevice -> {
if(StringUtils.startsWith(vmsRoadDevice.getType(),"C")){
Map m = getBridgeCrane(StringUtils.substring(vmsRoadDevice.getType(),1,4));
vmsRoadDevice.setLat(Double.valueOf(m.get("latitude")+""));
vmsRoadDevice.setLon(Double.valueOf(m.get("longitude")+""));
}
});
return new SSIPage(page);
}
private Map getBridgeCrane(String number){
JSONObject jsonObject = new JSONObject();
jsonObject.put("craneNum", number);
jsonObject.put("laneNum", 4);
jsonObject.put("containerSize", 1);
jsonObject.put("containerPosition", 2);
String result = "";
try {
result = RestTemplateUtil.post(bcUrl, jsonObject.toString(), null);
} catch (Exception e) {
result = null;
}
if(result!=null){
Map m = JSONObject.parseObject(result,Map.class);
return m;
}
return new HashMap<>();
}
private void getVideoPlayUrl(VmsRoadDevice vmsRoadDevice) {
vmsRoadDevice.setVideoOnline(false);
List<String> playVideoAddressList = Lists.newArrayList();
try {
String videoAddress = vmsRoadDevice.getVideoAddress();
if(StringUtils.isNotBlank(videoAddress)){
List<String> videoAddressList = Arrays.asList(videoAddress.split(","));
videoAddressList.stream().forEach(curAddr -> {
String playVideoAddress = getPlayVideoAddress(curAddr);
if(StringUtils.isNotBlank(playVideoAddress)){
playVideoAddressList.add(playVideoAddress);
}
});
}
if(!playVideoAddressList.isEmpty()){
vmsRoadDevice.setVideoOnline(true);
vmsRoadDevice.setPlayVideoAddress(playVideoAddressList);
}
} catch (Exception e) {
log.error("路测设备请求视频地址接口失败:vmsRoadDevice:"+JSONObject.toJSONString(vmsRoadDevice));
}
}
private String getPlayVideoAddress(String videoAddress) {
boolean rtspAddr = videoAddress.startsWith("rtsp:");
if(rtspAddr){
String checkResult = RestTemplateUtil.get(String.format("%s/%s%s", videoPlatformUrl, URL.ROAD_DEVICE_CHECKONLINE, videoAddress),null);
JSONObject checkResultJson = JSONObject.parseObject(checkResult);
if(0 == checkResultJson.getInteger("code")){
Boolean online = checkResultJson.getJSONObject("data").getBoolean("online");
if(online){
String urlResult = RestTemplateUtil.get(String.format("%s/%s%s", videoPlatformUrl, URL.ROAD_DEVICE_RTSPSTART, videoAddress),null);
JSONObject urlResultJson = JSONObject.parseObject(urlResult);
if(0 == urlResultJson.getInteger("code")
|| 201 == urlResultJson.getInteger("code")){
return urlResultJson.getJSONObject("data").toJSONString();
}
}
}
}
boolean rtmpAddr = videoAddress.startsWith("rtmp:");
if(rtmpAddr){
String checkResult = RestTemplateUtil.get(String.format("%s/%s%s", videoPlatformUrl, URL.RTMP_CHECKONLINE, videoAddress),null);
JSONObject checkResultJson = JSONObject.parseObject(checkResult);
if(0 == checkResultJson.getInteger("code")){
Boolean online = checkResultJson.getJSONObject("data").getBoolean("online");
if(online){
String urlResult = RestTemplateUtil.get(String.format("%s/%s%s", videoPlatformUrl, URL.RTMP_PLAY, videoAddress),null);
JSONObject urlResultJson = JSONObject.parseObject(urlResult);
if(0 == urlResultJson.getInteger("code")
|| 201 == urlResultJson.getInteger("code")){
return urlResultJson.getJSONObject("data").toJSONString();
}
}
}
}
return null;
}
/**
* 获取视频播放地址
* @return
*/
@Override
public List<VmsRoadDeviceVo> videoPlayUrlList(){
List<VmsRoadDevice> list = this.list();
List<VmsRoadDeviceVo> collect = list.stream().flatMap(vmsRoadDevice -> {
getVideoPlayUrl(vmsRoadDevice);
List<String> playVideoAddress = vmsRoadDevice.getPlayVideoAddress();
if(playVideoAddress != null){
return playVideoAddress.stream().map(url -> {
VmsRoadDeviceVo vmsRoadDeviceVo = new VmsRoadDeviceVo();
vmsRoadDeviceVo.setDeviceName(vmsRoadDevice.getDeviceName());
vmsRoadDeviceVo.setUrl(url);
return vmsRoadDeviceVo;
});
}
return Stream.empty();
}).collect(Collectors.toList());
return collect;
}
/**
* 路测安全消息信息
*/
@Override
public Map getRsmInfo(Long id) {
Map<String, Object> map = redisDataModel.getJson2Map(rsmPrefix + ":" + id);
return map;
}
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.*;
import com.ssi.entity.vo.CargoShipConfigDto;
import com.ssi.mapper.VmsShipsDrawingMapper;
import com.ssi.response.SSIPage;
import com.ssi.response.SSIResponse;
import com.ssi.service.CargoShipConfigInfoService;
import com.ssi.service.VmsShipsDrawingService;
import com.ssi.utils.AuthorizationUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 船模图
*/
@Service("shipsDrawingService")
@DS("oracle")
public class VmsShipsDrawingServiceImpl extends ServiceImpl<VmsShipsDrawingMapper, VmsShipsDrawing> implements VmsShipsDrawingService {
@Autowired
private CargoShipConfigInfoService cargoShipConfigInfoService;
@Override
public VmsShipsDrawing getVmsShipsDrawing(Map<String, Object> params) {
//参数解析
String shipCod = String.valueOf(params.get("shipCod"));
String voyageNo = String.valueOf(params.get("voyageNo"));
String workStatus = String.valueOf(params.get("workStatus"));
String[] bayNo = parseBayId(String.valueOf(params.get("bayNo")));
Map<String, VmsShipNcl> shipBayNcl = new HashMap<>(0);
if("1".equals(workStatus)){
shipBayNcl = getShipBayNcl(voyageNo, bayNo[0]);
if(!bayNo[0].equals(bayNo[1])){
shipBayNcl.putAll(getShipBayNcl(voyageNo, bayNo[1]));
}
}
VmsShipsDrawing shipDraw = new VmsShipsDrawing();
searchShipUDrawByBayNo(shipDraw, shipCod, bayNo, shipBayNcl);
searchShipDDrawByBayNo(shipDraw, shipCod, bayNo, shipBayNcl);
return shipDraw;
}
private Map<String, VmsShipNcl> getShipBayNcl(String voyageNo, String shortBayNo){
//贝位处于工作状态
List<VmsShipNcl> vmsShipNcls = this.baseMapper.queryShipNclByShortBayNo(voyageNo, shortBayNo);
Map<String, VmsShipNcl> bayNclMap;
if(vmsShipNcls != null){
int size = vmsShipNcls.size();
bayNclMap = new HashMap<>(size);
VmsShipNcl vmsShipNcl;
for (int i = 0; i < size; i++) {
vmsShipNcl = vmsShipNcls.get(i);
//强制上船状态解析
if(vmsShipNcl.getAllowFlag() != null){
if("Y".equalsIgnoreCase(vmsShipNcl.getAllowFlag())){
//强制上船
vmsShipNcl.setCommStatus("7");
}else if("N".equalsIgnoreCase(vmsShipNcl.getAllowFlag())){
//禁止上船
vmsShipNcl.setCommStatus("8");
}
}
bayNclMap.put(vmsShipNcl.getBayNo(), vmsShipNcl);
}
}else{
bayNclMap = new HashMap<>(0);
}
return bayNclMap;
}
public void searchShipUDrawByBayNo(VmsShipsDrawing shipDraw, String shipCod, String[] bayNo, Map<String, VmsShipNcl> shipBayNcl){
List<VmsShipsDrawing> layNoU = this.baseMapper.queryShipDrawBylayNo(shipCod,"U", bayNo[0]);
if(layNoU == null){return;}
shipDraw.setU(layNoU);
List<String> layNolist = new ArrayList<>();
int maxRow = 0;
for(VmsShipsDrawing layNo : layNoU) {
// 添加列编号
layNolist.add(layNo.getLayNo());
List<VmsShipsDrawing> rowNoList = this.baseMapper.queryShipDrawByRowNo(shipCod, "U", bayNo[0], layNo.getLayNo());
if(rowNoList == null){
continue;
}
int size = rowNoList.size();
if(size > maxRow){
maxRow = size;
}
layNo.setU(rowNoList);
// 根据船号 U舱体,贝号,层号 获取 箱体的信息
for(VmsShipsDrawing row : rowNoList) {
VmsShipNcl vmsShipNcl = shipBayNcl.get(String.format("%s%s%s", bayNo[0], row.getRowNo(), layNo.getLayNo()));
if(vmsShipNcl == null){
vmsShipNcl = shipBayNcl.get(String.format("%s%s%s", bayNo[1], row.getRowNo(), layNo.getLayNo()));
}
if(vmsShipNcl != null){
List<VmsShipNcl> tempnclList1 = row.getShipNcl();
if(tempnclList1 == null){
tempnclList1 = new ArrayList<>();
row.setShipNcl(tempnclList1);
}
tempnclList1.add(vmsShipNcl);
row.setWorkStatus(1);
}
}
}
shipDraw.setUlayNoList(layNolist);
shipDraw.setUmaxRow(maxRow);
}
public void searchShipDDrawByBayNo(VmsShipsDrawing shipDraw, String shipCod, String[] bayNo, Map<String, VmsShipNcl> shipBayNcl){
List<VmsShipsDrawing> layNoD = this.baseMapper.queryShipDrawBylayNo(shipCod,"D", bayNo[0]);
if(layNoD == null){return;}
shipDraw.setD(layNoD);
List<String> layNolist = new ArrayList<>();
int maxRow = 0;
for(VmsShipsDrawing layNo : layNoD) {
// 添加列编号
layNolist.add(layNo.getLayNo());
List<VmsShipsDrawing> rowNoList = this.baseMapper.queryShipDrawByRowNo(shipCod, "D", bayNo[0], layNo.getLayNo());
if(rowNoList == null){
continue;
}
int size = rowNoList.size();
if(size > maxRow){
maxRow = size;
}
layNo.setD(rowNoList);
// 根据船号 U舱体,贝号,层号 获取 箱体的信息
for(VmsShipsDrawing row : rowNoList) {
VmsShipNcl vmsShipNcl = shipBayNcl.get(String.format("%s%s%s", bayNo[0], row.getRowNo(), layNo.getLayNo()));
if(vmsShipNcl == null){
vmsShipNcl = shipBayNcl.get(String.format("%s%s%s", bayNo[1], row.getRowNo(), layNo.getLayNo()));
}
if(vmsShipNcl != null){
List<VmsShipNcl> tempnclList1 = row.getShipNcl();
if(tempnclList1 == null){
tempnclList1 = new ArrayList<>();
row.setShipNcl(tempnclList1);
}
tempnclList1.add(vmsShipNcl);
row.setWorkStatus(1);
}
}
}
shipDraw.setDlayNoList(layNolist);
shipDraw.setDmaxRow(maxRow);
}
public VmsShipsDrawing test(String shipCod,String bayNo,String voyageNo) {
VmsShipsDrawing shipDraw=new VmsShipsDrawing();
List<VmsShipsDrawing> shipMaplist=this.baseMapper.findShipMap(shipCod,bayNo); // 根据船号和贝号 获取所有的箱体信息
List<VmsShipNcl> shipNclList=this.baseMapper.findShipNcl(voyageNo,bayNo); // 根据船号和贝号 获取所有的箱体信息
List<VmsShipsDrawing> layNoU=new ArrayList();
List<VmsShipsDrawing> layNoD=new ArrayList();
VmsShipsDrawing layNo;
VmsShipsDrawing rowNo;
Map<String ,VmsShipsDrawing> keyMap=new HashMap<String ,VmsShipsDrawing >();
for(VmsShipsDrawing smp:shipMaplist) {
if(smp.getDeckId().equals("D")) {
rowNo=new VmsShipsDrawing();
rowNo.setBayNo(smp.getBayNo());
rowNo.setLayNo(smp.getLayNo());
rowNo.setRowNo(smp.getRowNo());
// rowNo.setShipsmp(shipsmp);
String tempBayNo=bayNo+smp.getLayNo()+smp.getRowNo();
// String temp=bayNo+ncl.getLayNo()+
List<VmsShipNcl> teml=new ArrayList<VmsShipNcl>();
for(VmsShipNcl ncl: shipNclList) {
if(tempBayNo.equals(ncl.getBayNo())) {
teml.add(ncl);
rowNo.setShipNcl(teml);
}
}
if (!keyMap.containsKey(smp.getLayNo())) {
layNo= new VmsShipsDrawing();
List<VmsShipsDrawing> childrenList = new ArrayList<VmsShipsDrawing>();
layNo.setLayNo(smp.getLayNo());
layNo.setD(childrenList);
keyMap.put(smp.getLayNo(), layNo);
// if() {
//
// }
}
keyMap.get(smp.getLayNo()).getD().add(rowNo);
// layNoU.add(sd);
// shipDraw.setBayNo(bayNo);
}
}
// VmsShipsDrawing tt= (VmsShipsDrawing) keyMap.values();
List<VmsShipsDrawing> cc=new ArrayList<VmsShipsDrawing>();
for(VmsShipsDrawing tt :keyMap.values()) {
cc.add(tt);
}
shipDraw.setD(cc);
// shipDraw.setD(keyMap.values());
return shipDraw;
}
@Override
public SSIPage getVmsShipsDrawingBayNo(Map<String, Object> params) {
// TODO Auto-generated method stub
Integer pageSize = params.get("pageSize") == null ? 10 : (Integer) params.get("pageSize");
Integer pageIndex = params.get("pageIndex") == null ? 1 : (Integer) params.get("pageIndex");
params.put("shipCod", (String) params.get("shipCod"));
params.put("bayNo", (String) params.get("bayNo"));
IPage<VmsShipsDrawing> page = new Page<>(pageIndex, pageSize);
page= this.baseMapper.queryShipDrawByCode(page,params);
List<VmsShipsDrawing> records = page.getRecords();
if(records != null && !records.isEmpty()){
//获取需作业的贝位列表, 将偶数贝 减一 调整为 奇数贝
Map<String, String> workBayIdMap = getWorkBayIdMap(String.valueOf(params.get("voyageNo")));
//更新船图贝位状态信息
records.forEach(record ->{
String bayNo = workBayIdMap.get(record.getBayNo());
if(bayNo != null){
record.setWorkStatus(1);
record.setBayNo(bayNo);
}else{
record.setWorkStatus(0);
}
});
}
return new SSIPage(page);
}
private Map<String, String> getWorkBayIdMap(String voyageNo){
List<String> workBays = this.baseMapper.queryShipWorkBay(voyageNo);
Map<String, String> workBayIdMap = new HashMap<>();
String bayId;
//获取需作业的贝位列表, 将偶数贝 减一 调整为 奇数贝
for (String workBay : workBays) {
try {
int bayNum = Integer.parseInt(workBay);
if(bayNum % 2 == 0){
//偶数贝,大箱,
bayNum = bayNum - 1;
bayId = String.format("%03d", bayNum);
workBayIdMap.put(bayId, String.format("%s:%s", bayId, workBay));
}else if(!workBayIdMap.containsKey(workBay)){
//避免顺序问题,导致奇数贝覆盖了偶数贝信息
workBayIdMap.put(workBay, workBay);
}
} catch (NumberFormatException e) {
log.error(String.format("贝位编号转整数失败:%s", workBay), e);
}
}
return workBayIdMap;
}
private String[] parseBayId(String bayIdStr){
String[] bayId = new String[2];
if(StringUtils.isNotBlank(bayIdStr)){
String[] bayIds = bayIdStr.split(":");
if(bayIds.length > 1){
bayId = bayIds;
}else{
bayId[0] = bayIds[0];
bayId[1] = bayIds[0];
}
}
return bayId;
}
@Override
public List<VmsCable> getCableList() {
// TODO Auto-generated method stub
List<VmsCable> cablist=this.baseMapper.cableList(); // 根据船号和贝号 获取所有的箱体信息
return cablist;
}
@Override
public List<VmsShipInfo> getShipInfoCoor() {
// TODO Auto-generated method stub
List<VmsShipInfo> cablist=this.baseMapper.queryshipInfoCoor(); // 根据船号和贝号 获取所有的箱体信息
List<CargoShipConfigDto> cargoShipConfigDtos = cargoShipConfigInfoService.queryOnWorkingList();
List<String> defaultConfigs = cargoShipConfigDtos.stream().map(CargoShipConfigDto::getName).collect(Collectors.toList());
cablist.parallelStream().forEach(shipInfoCoor -> {
shipInfoCoor.setHasConfig(0);
if(defaultConfigs.contains(shipInfoCoor.getShipNam())){
shipInfoCoor.setHasConfig(1);
}
});
return cablist;
}
@Override
public SSIPage queryPage(Map<String, Object> params) {
Integer pageSize = params.get("pageSize") == null ? 10 : (Integer) params.get("pageSize");
Integer pageIndex = params.get("pageIndex") == null ? 1 : (Integer) params.get("pageIndex");
params.put("voyageNo", (String) params.get("voyageNo"));
params.put("shipCod", (String) params.get("shipCod"));
IPage<VmsShipInfo> page = new Page<>(pageIndex, pageSize);
page = this.getBaseMapper().queryshipInfoList(page, params);
return new SSIPage(page);
}
@Override
public SSIResponse<?> saveShipTx(DcvAllowGoShipLaneTxVo vo) {
// TODO Auto-generated method stub
List<DcvAllowGoShipLaneTx> tempList=vo.getShipList();
JSONObject curUser = AuthorizationUtils.getCurUser();
// Integer userId = (Integer) curUser.get("userId");
String username ="";
if(null!=curUser) {
username = (String) curUser.get("username");
}
List<String> t=new ArrayList<String>();
for(DcvAllowGoShipLaneTx temp : tempList) {
temp.setRecUser(username);
temp.getCntr();
t.add(temp.getCntr());
VmsShipNcl tempncl= this.getBaseMapper().queryShipNclByCntr(temp.getCntr());
temp.setBayNo(tempncl.getBayNo());
}
// List<VmsShipNcl> tempNcl= this.getBaseMapper().queryShipNclByCntr(t);
// tempList=new ArrayList<DcvAllowGoShipLaneTx>();
// for(VmsShipNcl c : tempNcl ) {
// DcvAllowGoShipLaneTx tx=new DcvAllowGoShipLaneTx();
// tx.setAllowFlag(list.get(0).getAllowFlag());
// tx.setRecUser(username);
// tx.setCntr(c.getCntr());
// tx.setBayNo(c.getBayNo());
// tempList.add(tx);
// }
int result = 0;
if(Objects.nonNull(vo.getDeleteItem())&&1 == vo.getDeleteItem()){//删除对应船贝位设置
this.baseMapper.deleteBatch(tempList);
}else{
result= this.getBaseMapper().saveBatch(tempList);
}
// int result=this.getBaseMapper().updateShipTx(list);
// if(result!=1) {
// result=this.getBaseMapper().saveShipTx(list);
// }
return SSIResponse.ok(result);
}
@Override
public Map getPileInfo(String portCode) {
// TODO Auto-generated method stub
Map map= this.baseMapper.getPileInfo(portCode);
return map;
}
@Override
public String getShipWorkingBay(String voyageNo, String portCode) {
// TODO Auto-generated method stub
String bayNo = this.baseMapper.getShipWorkingBay(voyageNo, portCode);
return bayNo;
}
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ssi.constant.VehicleConstant;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.dto.VmsVehicleDto;
import com.ssi.entity.vo.VideoMonitorParams;
import com.ssi.mapper.VmsTerminalMapper;
import com.ssi.mapper.VmsVehicleMapper;
import com.ssi.mqtt.MQTTPublishClient;
import com.ssi.response.AccessResponse;
import com.ssi.response.SSIPage;
import com.ssi.response.SSIResponse;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ssi.utils.QueryUtils;
import com.ssi.entity.VmsTerminal;
import com.ssi.service.VmsTerminalService;
import org.springframework.web.client.RestTemplate;
/**
* 终端服务实现类
*/
@Service("terminalService")
public class VmsTerminalServiceImpl extends ServiceImpl<VmsTerminalMapper, VmsTerminal> implements VmsTerminalService {
@Value("${command-url}")
private String commandUrl;
@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 RestTemplate restTemplate;
@Autowired
private VmsVehicleMapper vmsVehicleMapper;
/**
* 终端分页数据
* @param params
* @return
*/
@Override
public SSIPage queryPage(Map<String, Object> params) {
String terminalNum = (String) params.get("terminalNum");
IPage<VmsTerminal> page = this.page(
new QueryUtils<VmsTerminal>().getPage(params),
new LambdaQueryWrapper<VmsTerminal>().like(StringUtils.isNotBlank(terminalNum), VmsTerminal::getTerminalNum, terminalNum)
.orderByDesc(VmsTerminal::getCreateTime)
);
return new SSIPage(page);
}
@Override
public SSIResponse saveTerminal(VmsTerminal vmsTerminal) {
Map<String, Object> repeatMap = checkRepeat(vmsTerminal);
if ((Boolean) repeatMap.get("repeat")) {
return SSIResponse.no((String) repeatMap.get("repeatInfo"));
}
this.saveOrUpdate(vmsTerminal);
return SSIResponse.ok();
}
private Map<String, Object> checkRepeat(VmsTerminal vmsTerminal) {
Map<String, Object> repeatMap = Maps.newHashMap();
repeatMap.put("repeat", true);
List<VmsTerminal> list = this.list();
Map<String, VmsTerminal> simMap = Maps.newHashMap();
Map<String, VmsTerminal> tNumMap = Maps.newHashMap();
Map<String, VmsTerminal> tTypeMap = Maps.newHashMap();
Map<String, VmsTerminal> iccidMap = Maps.newHashMap();
list.parallelStream().forEach(vmsTerminal1 -> {
simMap.put(vmsTerminal1.getSim(), vmsTerminal1);
tNumMap.put(vmsTerminal1.getTerminalNum(), vmsTerminal1);
tTypeMap.put(vmsTerminal1.getTerminalType(), vmsTerminal1);
iccidMap.put(vmsTerminal1.getIccid(), vmsTerminal1);
});
VmsTerminal repeatSim = simMap.get(vmsTerminal.getSim());
VmsTerminal repeatTnum = tNumMap.get(vmsTerminal.getTerminalNum());
VmsTerminal repeatTtype = tTypeMap.get(vmsTerminal.getTerminalType());
VmsTerminal repeatIccid = iccidMap.get(vmsTerminal.getIccid());
if (repeatSim != null) {
if (vmsTerminal.getId() == null || (vmsTerminal.getId() != null && vmsTerminal.getId() != repeatSim.getId())) {
repeatMap.put("repeatInfo", "sim卡号不能重复");
return repeatMap;
}
}
if (repeatTnum != null) {
if (vmsTerminal.getId() == null || (vmsTerminal.getId() != null && vmsTerminal.getId() != repeatTnum.getId())) {
repeatMap.put("repeatInfo", "终端编号不能重复");
return repeatMap;
}
}
if (repeatTtype != null) {
if (vmsTerminal.getId() == null || (vmsTerminal.getId() != null && vmsTerminal.getId() != repeatTtype.getId())) {
repeatMap.put("repeatInfo", "终端型号不能重复");
return repeatMap;
}
}
if (repeatIccid != null) {
if (vmsTerminal.getId() == null || (vmsTerminal.getId() != null && vmsTerminal.getId() != repeatIccid.getId())) {
repeatMap.put("repeatInfo", "iccid不能重复");
return repeatMap;
}
}
repeatMap.put("repeat", false);
return repeatMap;
}
@Override
public SSIResponse videoMonitor(String vin) {
VmsVehicleDto vehicle = vmsVehicleMapper.queryVehicleByVin(vin);
if(vehicle == null){
return SSIResponse.no("车辆不存在");
}
//发起mqtt请求,请求后视摄像头
MQTTPublishClient mqttClientSend = new MQTTPublishClient(mqttAddress, mqttServerId,mqttCAPath,mqttName,mqttPassword,mqttUrl);
mqttClientSend.mqttRequest(vehicle, VehicleConstant.START_PUSHER);
String videoTerminalNum = vehicle.getVideoTerminalNum();
VmsTerminal vmsTerminal = this.lambdaQuery().eq(VmsTerminal::getTerminalNum, videoTerminalNum).one();
if(vmsTerminal != null){
List<Object> result = Lists.newArrayList();
String sim = vmsTerminal.getSim();
VideoMonitorParams.VideoMonitorParamsBuilder builder = VideoMonitorParams.builder().sim(sim).dataType(1).controlType(0).hdType(0);
for (int i = 0; i < 3; i++) {
VideoMonitorParams params = builder.channel(i + 1).build();
AccessResponse accessResponse = restTemplate.postForObject(commandUrl + "/media/9101", params, AccessResponse.class);
if(accessResponse.isSuccess()){
Map data = (Map) accessResponse.getData();
data.put("channel",i + 1);
result.add(data);
}else{
Map data = new HashMap();
data.put("result",0);
result.add(data);
}
}
return SSIResponse.ok(result);
}else{
return SSIResponse.no("车辆视频卡终端不在线");
}
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ssi.mapper.VmsTerminalVersionMapper;
import com.ssi.response.SSIPage;
import com.ssi.utils.QueryUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Map;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsTerminalVersion;
import com.ssi.service.VmsTerminalVersionService;
/**
* 终端版本服务实现类
*/
@Service("terminalVersionService")
public class VmsTerminalVersionServiceImpl extends ServiceImpl<VmsTerminalVersionMapper, VmsTerminalVersion> implements VmsTerminalVersionService {
@Override
public SSIPage queryPage(Map<String, Object> params) {
Integer publishStatus = (Integer) params.get("publishStatus");
IPage<VmsTerminalVersion> page = this.page(
new QueryUtils<VmsTerminalVersion>().getPage(params),
new LambdaQueryWrapper<VmsTerminalVersion>()
.lt(publishStatus != null && publishStatus == 0, VmsTerminalVersion::getPublishTime, new Date())
.ge(publishStatus != null && publishStatus == 1, VmsTerminalVersion::getPublishTime, new Date())
.orderByDesc(VmsTerminalVersion::getPublishTime)
);
return new SSIPage(page);
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsTosOrders;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.VmsTosOrderDailyKpi;
import com.ssi.entity.vo.VehicleKpiVo;
import com.ssi.mapper.VmsTosOrderDailyKpiMapper;
import com.ssi.service.VmsTosOrderDailyKpiService;
import com.ssi.service.VmsTosOrdersService;
import com.ssi.service.VmsVehicleService;
import com.ssi.utils.DateUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
/**
* @description:
* @author: dt
* @create: 2022-10-28 16:58
*/
@Service
public class VmsTosOrderDailyKpiServiceImpl extends ServiceImpl<VmsTosOrderDailyKpiMapper, VmsTosOrderDailyKpi> implements VmsTosOrderDailyKpiService {
private final Logger log = LoggerFactory.getLogger(VmsTosOrderDailyKpiServiceImpl.class);
private VmsTosOrdersService vmsTosOrdersService;
private VmsVehicleService vmsVehicleService;
private StringRedisTemplate redisTemplate;
/**
* redis key
*/
@Value("${harbor.order.dailyKpi:harbor:order:dailyKpi}")
private String redisDailyKpiKey;
public VmsTosOrderDailyKpiServiceImpl(VmsTosOrdersService vmsTosOrdersService, VmsVehicleService vmsVehicleService, StringRedisTemplate redisTemplate) {
this.vmsTosOrdersService = vmsTosOrdersService;
this.vmsVehicleService = vmsVehicleService;
this.redisTemplate = redisTemplate;
}
/**
* 预处理任务
* @param vins
* @return
*/
@Override
public Boolean analysisTosOrderDailyKpi(String vins) {
LambdaQueryWrapper<VmsVehicle> vmsVehicleLambdaQueryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotEmpty(vins)) {
vmsVehicleLambdaQueryWrapper.in(VmsVehicle::getVin, vins.split(","));
}
List<VmsVehicle> vehicles = vmsVehicleService.list(vmsVehicleLambdaQueryWrapper.eq(VmsVehicle::getStatus, 0));
if (CollectionUtils.isEmpty(vehicles)) {
log.info("预处理每日 KPI 任务,查询的车辆信息为空...");
return false;
}
LocalDateTime now = LocalDateTime.now();
vehicles.parallelStream().forEach(vehicle -> {
String updateTime = redisTemplate.<String, String>boundHashOps(redisDailyKpiKey).get(vehicle.getVin());
log.info("------ 开始处理 vin = "+ vehicle.getVin()+", updateTime = "+ updateTime +", 时间 = "+ LocalDateTime.now().toString() +" ------");
LambdaQueryWrapper<VmsTosOrders> vmsTosOrdersLambdaQueryWrapper = new LambdaQueryWrapper<VmsTosOrders>()
.eq(VmsTosOrders::getVin, vehicle.getVin());
if (StringUtils.isNotEmpty(updateTime)) {
vmsTosOrdersLambdaQueryWrapper.ge(StringUtils.isNotEmpty(updateTime), VmsTosOrders::getUpdateTime, LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(updateTime)),
ZoneId.systemDefault()))
.lt(StringUtils.isNotEmpty(updateTime), VmsTosOrders::getUpdateTime, now);
}
List<VmsTosOrders> vmsTosOrders = vmsTosOrdersService.list(
vmsTosOrdersLambdaQueryWrapper.in(VmsTosOrders::getVehicleTaskLabel, 1 , 2, 3)
.in(VmsTosOrders::getTaskLocationType,1,5));
if (CollectionUtils.isNotEmpty(vmsTosOrders)) {
Map<String, List<VmsTosOrders>> vmsTosOrderMap = vmsTosOrders.stream().filter(vmsTosOrder -> Objects.nonNull(vmsTosOrder.getStartTime()))
.collect(Collectors.groupingBy(vmsTosOrder -> getDateHourKey(vmsTosOrder)));
vmsTosOrderMap.forEach((k,v) -> {
VmsTosOrderDailyKpi vmsTosOrderDailyKpi = getVmsTosOrderDailyKpi(k, v, vehicle);
saveOrUpdateVmsTosOrderDailyKpi(vmsTosOrderDailyKpi);
});
} else {
log.info("vin = "+ vehicle.getVin()+", updateTime = "+ updateTime+", 未查询到相关指令数据!");
}
redisTemplate.boundHashOps(redisDailyKpiKey).put(vehicle.getVin(), String.valueOf(now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
log.info("------ 结束处理 vin = "+ vehicle.getVin() +", 时间 = "+ LocalDateTime.now().toString() +" ------");
});
return true;
}
/**
* 得到分组的 key
* @param vmsTosOrders
* @return
*/
private String getDateHourKey(VmsTosOrders vmsTosOrders) {
return DateUtils.format(vmsTosOrders.getStartTime(), "yyyy-MM-dd HH");
}
/**
* 生成任务分析的结果类
* @param vmsTosOrders
* @return
*/
private VmsTosOrderDailyKpi getVmsTosOrderDailyKpi(String key, List<VmsTosOrders> vmsTosOrders, VmsVehicle vehicle) {
VmsTosOrderDailyKpi vmsTosOrderDailyKpi = new VmsTosOrderDailyKpi();
vmsTosOrderDailyKpi.setVin(vehicle.getVin());
vmsTosOrderDailyKpi.setVehicleNum(vehicle.getVehicleNum());
String[] dates = key.split(" ");
vmsTosOrderDailyKpi.setAnalysisDate(dates[0]);
vmsTosOrderDailyKpi.setAnalysisHour(Integer.parseInt(dates[1]));
getContainers(vmsTosOrders, vmsTosOrderDailyKpi);
getFinishedOrderNum(vmsTosOrders, vmsTosOrderDailyKpi);
getOrderNum(vmsTosOrders, vmsTosOrderDailyKpi);
return vmsTosOrderDailyKpi;
}
/**
* 填充 containerNum 和 containerIds
* @param vmsTosOrders
* @return
*/
private void getContainers(List<VmsTosOrders> vmsTosOrders,VmsTosOrderDailyKpi vmsTosOrderDailyKpi) {
Set<String> containerIds = vmsTosOrders.stream().filter(vmsTosOrder -> (Objects.equals(1, vmsTosOrder.getTaskLocationType()) && Objects.equals(2, vmsTosOrder.getVehicleTaskLabel())) ||
(Objects.equals(5, vmsTosOrder.getTaskLocationType()) && Objects.equals(1, vmsTosOrder.getVehicleTaskLabel()))).map(VmsTosOrders::getContainerId)
.filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
vmsTosOrderDailyKpi.setContainerIds(String.join(",", containerIds));
}
/**
* 填充结束任务
* @param vmsTosOrders
* @param vmsTosOrderDailyKpi
*/
private void getFinishedOrderNum(List<VmsTosOrders> vmsTosOrders,VmsTosOrderDailyKpi vmsTosOrderDailyKpi) {
String finishOrderIds = vmsTosOrders.stream().filter(vmsTosOrder -> Objects.equals(37, vmsTosOrder.getStatus()))
.map(vmsTosOrder -> String.valueOf(vmsTosOrder.getId())).collect(Collectors.joining(","));
vmsTosOrderDailyKpi.setFinishedOrderIds(finishOrderIds);
}
/**
* 填充任务数量
* @param vmsTosOrders
* @param vmsTosOrderDailyKpi
*/
private void getOrderNum(List<VmsTosOrders> vmsTosOrders,VmsTosOrderDailyKpi vmsTosOrderDailyKpi) {
String orderIds = vmsTosOrders.stream().map(vmsTosOrder -> String.valueOf(vmsTosOrder.getId()))
.collect(Collectors.joining(","));
vmsTosOrderDailyKpi.setOrderIds(orderIds);
}
/**
* 保存或更新
* @param vmsTosOrderDailyKpi
* @return
*/
private Boolean saveOrUpdateVmsTosOrderDailyKpi(VmsTosOrderDailyKpi vmsTosOrderDailyKpi) {
VmsTosOrderDailyKpi orderDailyKpi = this.getOne(new LambdaQueryWrapper<VmsTosOrderDailyKpi>()
.eq(VmsTosOrderDailyKpi::getAnalysisDate, vmsTosOrderDailyKpi.getAnalysisDate())
.eq(VmsTosOrderDailyKpi::getVin, vmsTosOrderDailyKpi.getVin())
.eq(VmsTosOrderDailyKpi::getAnalysisHour, vmsTosOrderDailyKpi.getAnalysisHour()));
if (Objects.nonNull(orderDailyKpi)) {
String containerIds = Arrays.stream((orderDailyKpi.getContainerIds() + "," + vmsTosOrderDailyKpi.getContainerIds()).split(",")).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.joining(","));
vmsTosOrderDailyKpi.setContainerIds(containerIds);
String finishedOrderIds = Arrays.stream((orderDailyKpi.getFinishedOrderIds() + "," + vmsTosOrderDailyKpi.getFinishedOrderIds()).split(",")).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.joining(","));
vmsTosOrderDailyKpi.setFinishedOrderIds(finishedOrderIds);
String orderIds = Arrays.stream((orderDailyKpi.getOrderIds() + "," + vmsTosOrderDailyKpi.getOrderIds()).split(",")).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.joining(","));
vmsTosOrderDailyKpi.setOrderIds(orderIds);
return this.update(vmsTosOrderDailyKpi, new LambdaUpdateWrapper<VmsTosOrderDailyKpi>()
.eq(VmsTosOrderDailyKpi::getAnalysisDate, vmsTosOrderDailyKpi.getAnalysisDate())
.eq(VmsTosOrderDailyKpi::getVin, vmsTosOrderDailyKpi.getVin())
.eq(VmsTosOrderDailyKpi::getAnalysisHour, vmsTosOrderDailyKpi.getAnalysisHour()));
} else {
return this.save(vmsTosOrderDailyKpi);
}
}
/**
* 查询分析好的 order kpi 任务
* @param day
* @param vehicleNum
* @return
*/
@Override
public List<Map<String, String>> getOrderDailyKpi(String day, String vehicleNum) {
List<VmsVehicle> vehicles = vmsVehicleService.list(new LambdaQueryWrapper<VmsVehicle>()
.eq(VmsVehicle::getStatus, 0)
.like(StringUtils.isNotBlank(vehicleNum), VmsVehicle::getVehicleNum, vehicleNum)
.orderByAsc(VmsVehicle::getVehicleNum));
if (CollectionUtils.isNotEmpty(vehicles)) {
String[] vins = vehicles.stream().map(VmsVehicle::getVin).toArray(String[]::new);
List<VmsTosOrderDailyKpi> orderDailyKpis = this.list(new LambdaQueryWrapper<VmsTosOrderDailyKpi>()
.eq(VmsTosOrderDailyKpi::getAnalysisDate, day)
.in(VmsTosOrderDailyKpi::getVin, vins));
Map<String, List<VmsTosOrderDailyKpi>> orderDailyKpiMap = orderDailyKpis.stream().collect(Collectors.groupingBy(VmsTosOrderDailyKpi::getVin));
List<Map<String, String>> resultList = vehicles.stream().map(vmsVehicle -> {
try {
VehicleKpiVo vehicleKpiVo = new VehicleKpiVo(vmsVehicle.getVin(),vmsVehicle.getVehicleNum());
vehicleKpiVo.setDate(day);
List<VmsTosOrderDailyKpi> vmsTosOrderDailyKpis = orderDailyKpiMap.get(vmsVehicle.getVin());
vehicleKpiVo.fillDataForOrderDailyKpi(vmsTosOrderDailyKpis);
Map<String, String> map = vehicleKpiVo.toMap();
if (CollectionUtils.isNotEmpty(vmsTosOrderDailyKpis)) {
int containerNum = vmsTosOrderDailyKpis.stream().map(VmsTosOrderDailyKpi::getContainerIds).filter(StringUtils::isNotEmpty)
.flatMap(containerIds -> Arrays.stream(containerIds.split(",")))
.collect(Collectors.toSet()).size();
map.put("containerNum", String.valueOf(containerNum));
} else {
map.put("containerNum", "0");
}
return map;
} catch (Exception e) {
log.error("获取daily kpi异常", e);
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toList());
return resultList;
}
return null;
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsTosOrdersAnalysis;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.vo.TaskAnalysisVo;
import com.ssi.mapper.VmsTosOrdersAnalysisMapper;
import com.ssi.mapper.VmsTosOrdersMapper;
import com.ssi.mapper.VmsVehicleMapper;
import com.ssi.service.VmsTosOrdersAnalysisService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.List;
/**
* 任务分析实现类
*/
@Service("vmsTosOrdersAnalysisService")
public class VmsTosOrdersAnalysisServiceImpl extends ServiceImpl<VmsTosOrdersAnalysisMapper, VmsTosOrdersAnalysis> implements VmsTosOrdersAnalysisService {
@Autowired
private VmsTosOrdersMapper vmsTosOrdersMapper;
@Autowired
private VmsVehicleMapper vmsVehicleMapper;
@Override
public IPage<VmsTosOrdersAnalysis> queryPage(int current, int size, VmsTosOrdersAnalysis vmsTosOrdersAnalysis) {
IPage<VmsTosOrdersAnalysis> page = new Page<>(current, size);
QueryWrapper<VmsTosOrdersAnalysis> wrapper = new QueryWrapper<>();
return this.page(page, wrapper);
}
/**
* 根据时间段执行任务分析
* @param startTime
* @param endTime
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void runTosAnalysisTask(LocalDateTime startTime, LocalDateTime endTime) {
Long startTimeStamp = startTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
List<TaskAnalysisVo> taskNumTimeByDay = vmsTosOrdersMapper.getTaskNumTimeByDay(startTime, endTime,startTimeStamp);
LocalDate startDate = startTime.toLocalDate();
LocalDate endDate = endTime.toLocalDate();
List<VmsVehicle> vehicleList = vmsVehicleMapper.selectList(new LambdaQueryWrapper<VmsVehicle>()
.eq(VmsVehicle::getStatus, 0));
for (LocalDate ld = startDate; ld.compareTo(endDate) <= 0; ld = ld.plusDays(1)) {
LocalDate ld1 = ld;
lambdaUpdate().set(VmsTosOrdersAnalysis::getDeleted, 1)
.eq(VmsTosOrdersAnalysis::getAnalysisDate, ld1)
.update();
for (int i = 0; i < vehicleList.size(); i++) {
VmsVehicle v = vehicleList.get(i);
String vin = v.getVin();
boolean present = taskNumTimeByDay.stream().anyMatch(vo -> vo.getVin().equals(vin) && ld1.isEqual(vo.getDate()));
if (!present) {
VmsTosOrdersAnalysis analysis = new VmsTosOrdersAnalysis();
analysis.setAnalysisDate(ld);
analysis.setVin(vin);
getBaseMapper().insert(analysis);
}
}
}
if (CollectionUtils.isNotEmpty(taskNumTimeByDay)) {
taskNumTimeByDay.forEach(this::accept);
}
}
/**
* 重新计算任务数据
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void reAnalysis(LocalDate date) {
LocalDateTime startTime = LocalDateTime.of(date, LocalTime.MIN);
Long startTimeStamp = startTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
List<TaskAnalysisVo> taskNumTimeByDay = vmsTosOrdersMapper.getTaskNumTimeByDay(startTime, endTime,startTimeStamp);
if (CollectionUtils.isNotEmpty(taskNumTimeByDay)) {
//原始数据未删除的情况下,可以进行重新分析
lambdaUpdate().set(VmsTosOrdersAnalysis::getDeleted, 1)
.eq(VmsTosOrdersAnalysis::getAnalysisDate, date)
.update();
List<VmsVehicle> vehicleList = vmsVehicleMapper.selectList(new LambdaQueryWrapper<VmsVehicle>()
.eq(VmsVehicle::getStatus, 0));
for (int i = 0; i < vehicleList.size(); i++) {
String vin = vehicleList.get(i).getVin();
boolean present = taskNumTimeByDay.stream().anyMatch(vo -> vo.getVin().equals(vin));
if (!present) {
VmsTosOrdersAnalysis analysis = new VmsTosOrdersAnalysis();
analysis.setAnalysisDate(date);
analysis.setVin(vin);
getBaseMapper().insert(analysis);
}
}
taskNumTimeByDay.forEach(this::accept);
}
}
private void accept(TaskAnalysisVo dayHourTrend) {
VmsTosOrdersAnalysis analysis = new VmsTosOrdersAnalysis();
analysis.setAnalysisDate(dayHourTrend.getDate());
analysis.setVin(dayHourTrend.getVin());
analysis.setLoadContainerNum(dayHourTrend.getLoadContainerNum());
analysis.setLoadContainerTime(dayHourTrend.getLoadContainerTime());
analysis.setUnloadContainerNum(dayHourTrend.getUnloadContainerNum());
analysis.setUnloadContainerTime(dayHourTrend.getUnloadContainerTime());
analysis.setHandleContainerNum(dayHourTrend.getHandleContainerNum());
analysis.setHandleContainerTime(dayHourTrend.getHandleContainerTime());
getBaseMapper().insert(analysis);
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.constant.enums.VmsTosOrderStatusEnum;
import com.ssi.entity.VmsTosOrders;
import com.ssi.entity.VmsTosOrdersOee;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.vo.TaskKPIVo;
import com.ssi.entity.vo.TaskStatusHistory;
import com.ssi.entity.vo.VmsTosOrdersKPIVo;
import com.ssi.mapper.VmsTosOrdersOeeMapper;
import com.ssi.mapper.VmsVehicleMapper;
import com.ssi.model.VehicleElasticSearchModel;
import com.ssi.service.VmsTosOrdersOeeService;
import com.ssi.service.VmsTosOrdersService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
/**
* OEE分析任务实现类
*/
@Service("vmsTosOrdersOeeService")
@Slf4j
public class VmsTosOrdersOeeServiceImpl extends ServiceImpl<VmsTosOrdersOeeMapper, VmsTosOrdersOee> implements VmsTosOrdersOeeService {
@Autowired
private VmsTosOrdersService vmsTosOrdersService;
@Autowired
private VehicleElasticSearchModel vehicleElasticSearchModel;
@Autowired
private VmsVehicleMapper vmsVehicleMapper;
/**
* 根据时间段执行OEE分析
* @param startTime
* @param endTime
*/
@Override
public void runTosOeeTask(LocalDateTime startTime, LocalDateTime endTime) {
List<VmsTosOrders> list = vmsTosOrdersService.lambdaQuery()
.eq(VmsTosOrders::getDeleted, 0)
.in(VmsTosOrders::getStatus, VmsTosOrderStatusEnum.FINISH_CONFIRM.getCode(),VmsTosOrderStatusEnum.ARRIVED_DESTINATION.getCode(),
VmsTosOrderStatusEnum.VEHICLE_LOCKUP.getCode(),VmsTosOrderStatusEnum.FINISH_CRANE_CONFIRM.getCode(),
VmsTosOrderStatusEnum.FINISH_DRIVER_CONFIRM.getCode())
.in(VmsTosOrders::getVehicleTaskLabel, 1, 2, 3)
.ge(VmsTosOrders::getCollectTime, Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()).getTime())
.lt(VmsTosOrders::getCollectTime, Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()).getTime())
.list();
if (CollectionUtils.isNotEmpty(list)) {
list.stream().forEach(vmsTosOrders -> {
try {
String taskNo = vmsTosOrders.getTaskNo();
Integer count = this.lambdaQuery()
.eq(VmsTosOrdersOee::getTaskNo, taskNo)
.eq(VmsTosOrdersOee::getDeleted, 0)
.ge(VmsTosOrdersOee::getCollectTime, Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()).getTime())
.lt(VmsTosOrdersOee::getCollectTime, Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()).getTime())
.count();
if (count == 0) {
VmsTosOrdersOee vmsTosOrdersOee = new VmsTosOrdersOee();
vmsTosOrders.setId(null);
BeanUtils.copyProperties(vmsTosOrdersOee, vmsTosOrders);
String vin = vmsTosOrders.getVin();
VmsVehicle vmsVehicle = vmsVehicleMapper.selectOne(new LambdaQueryWrapper<VmsVehicle>().eq(VmsVehicle::getVin, vin));
vmsTosOrdersOee.setVehicleNum(vmsVehicle.getVehicleNum());
int year = startTime.getYear();
List<TaskStatusHistory> taskStatusHistoryList = vehicleElasticSearchModel.searchTaskHistory(taskNo, String.valueOf(year));
Long collectTime = vmsTosOrders.getCollectTime();
Long lastCollectTime = collectTime;
for (int j = 0; j < taskStatusHistoryList.size(); j++) {
Integer status = taskStatusHistoryList.get(j).getStatus();
Long currentCollectTime = taskStatusHistoryList.get(j).getCollectTime();
if (VmsTosOrderStatusEnum.OBU_RECEIVED.getCode() == status) {//车辆接受 43;
//指令等待时间 = 车辆接收时间 - collect_time
vmsTosOrdersOee.setInstructionWaitingTime(calTime(lastCollectTime, currentCollectTime));
lastCollectTime = currentCollectTime;
}
if (VmsTosOrderStatusEnum.START_TASK.getCode() == status) {//车辆开始行驶 65;
//作业准备时间 = 任务开始(开始行驶)-车辆接受
vmsTosOrdersOee.setHomeworkPreparationTime(calTime(lastCollectTime, currentCollectTime));
lastCollectTime = currentCollectTime;
}
if (VmsTosOrderStatusEnum.ARRIVED_DESTINATION.getCode() == status) {//到达目的地 3;
//移动到取箱点时间 = 到达目的地或者车辆停稳锁死-任务开始或车辆接受时间(任务开始时间为空)
vmsTosOrdersOee.setMoveTheBoxTime(calTime(lastCollectTime, currentCollectTime));
lastCollectTime = currentCollectTime;
}
if (VmsTosOrderStatusEnum.VEHICLE_LOCKUP.getCode() == status) {//车辆停稳锁死 49;
if (vmsTosOrdersOee.getMoveTheBoxTime() == null) {
vmsTosOrdersOee.setMoveTheBoxTime(calTime(lastCollectTime, currentCollectTime));
}
lastCollectTime = currentCollectTime;
}
if (VmsTosOrderStatusEnum.FINISH_CONFIRM.getCode() == status) {//三重确认完成 37;
//取箱点等待时间 = 三重确认完成-到达目的地或者车辆停稳锁死
vmsTosOrdersOee.setPickingTime(calTime(lastCollectTime, currentCollectTime));
}
}
this.save(vmsTosOrdersOee);
}
} catch (Exception e) {
log.error("runTosOeeTask出错,vmsTosOrders.TaskNo:" + vmsTosOrders.getTaskNo(), e);
}
});
}
}
/**
* 任务KPI-效率OEE分析
*/
@Override
public List taskOee(VmsTosOrdersKPIVo vmsTosOrders) {
if (vmsTosOrders.getStartTime() == null && vmsTosOrders.getEndTime() == null) {
LocalDateTime startTime = LocalDateTime.of(LocalDateTime.now().minus(3, ChronoUnit.DAYS).toLocalDate(), LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(LocalDateTime.now().minus(1, ChronoUnit.DAYS).toLocalDate(), LocalTime.MAX);
vmsTosOrders.setStartTime(startTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
vmsTosOrders.setEndTime(endTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
List<TaskKPIVo> taskKPIVos = this.getBaseMapper().taskOee(vmsTosOrders);
return taskKPIVos;
}
private long calTime(Long startDate, Long endDate) {
if (startDate == null || endDate == null) {
return 0;
}
long diff = endDate - startDate;
return diff > 0 ? diff : 0;
}
}
package com.ssi.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.export.ExcelBatchExportService;
import cn.afterturn.easypoi.handler.impl.ExcelDataHandlerDefaultImpl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ssi.constant.VehicleConstant;
import com.ssi.constant.enums.VmsTosOrderStatusEnum;
import com.ssi.entity.*;
import com.ssi.entity.dto.VehicleTerminalData;
import com.ssi.entity.dto.VmsTosOrdersDto;
import com.ssi.entity.dto.kpi.VehicleDateStageDto;
import com.ssi.entity.dto.kpi.VmsTosOrdersKpiDto;
import com.ssi.entity.vo.*;
import com.ssi.mapper.*;
import com.ssi.model.RedisDataModel;
import com.ssi.model.VehicleElasticSearchModel;
import com.ssi.response.AccessResponse;
import com.ssi.response.SSIPage;
import com.ssi.response.SSIResponse;
import com.ssi.service.VmsCranePadBindService;
import com.ssi.service.VehicleTroubleService;
import com.ssi.service.VmsVehicleService;
import com.ssi.utils.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.elasticsearch.action.search.*;
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.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.service.VmsTosOrdersService;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 任务服务实现类
*/
@Service("vmsTosOrdersService")
public class VmsTosOrdersServiceImpl extends ServiceImpl<VmsTosOrdersMapper, VmsTosOrders> implements VmsTosOrdersService {
private static Logger log = LoggerFactory.getLogger(VmsTosOrdersServiceImpl.class);
@Autowired
VmsTaskJourneyInfoMapper taskJourneyInfoMapper;
@Autowired
private VehicleTroubleService vehicleTroubleService;
@Autowired
private RestHighLevelClient restHighLevelClient;
@Autowired
private VmsCranePadBindService vmsCranePadBindService;
@Autowired
private VmsVehicleService vmsVehicleService;
@Autowired
private RedisDataModel redisDataModel;
@Autowired
private VehicleTroubleHistoryMapper vehicleTroubleHistoryMapper;
@Autowired
private VehicleElasticSearchModel vehicleElasticSearchModel;
@Autowired
private VehicleDataUtil vehicleDataUtil;
@Autowired
private VmsTosOrdersAnalysisMapper vmsTosOrdersAnalysisMapper;
@Autowired
private VmsTosOrdersMapper vmsTosOrdersMapper;
@Autowired
private RestTemplate restTemplate;
@Autowired
private VehicleRemoteInstructionMapper vehicleRemoteInstructionMapper;
@Value("${analysis.vehicle-data.es-index-name}")
private String esVehicleDataIndexName;
@Value("${analysis.vehicle-data.index-rule:year}")
private String indexRule;
@Value("${order.latestOrderKeyPrefix:harbor:command:status}")
private String latestOrderKeyPrefix;
@Value("${vehicle.cache.key:ivccs:vms:vehicle:cache}")
private String vehicleCacheKey;
@Value("${command-url}")
private String commandUrl;
private ThreadLocal<VehicleDateStageDto> threadStage = new ThreadLocal<VehicleDateStageDto>();
@Override
public Map<String, VmsTosOrders> getAllVehicleLatestWork() {
Map<String, VmsTosOrders> resultMap = Maps.newHashMap();
List<VmsTosOrders> list = this.list();
list.parallelStream().forEach(vmsTosOrders -> {
VmsTosOrders tempOrders = resultMap.get(vmsTosOrders.getVin());
if (tempOrders == null || tempOrders.getReceiveTime().getTime() < vmsTosOrders.getReceiveTime().getTime()) {
resultMap.put(vmsTosOrders.getVin(), vmsTosOrders);
}
});
return resultMap;
}
/**
* 获取车辆当前任务
* @param vin 车辆vin
*/
@Override
public Map<String, Object> getOrdersByVin(String vin) {
Map<String, Object> resultMap = Maps.newHashMap();
Map<String, Object> json2Map = redisDataModel.getJson2Map(String.format("%s:%s", latestOrderKeyPrefix, vin));
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(json2Map));
VmsTosOrders vmsTosOrders = JSONObject.toJavaObject(jsonObject, VmsTosOrders.class);
if (vmsTosOrders != null) {
resultMap.put("vmsTosOrders", vmsTosOrders);
resultMap.put("workStatus", !VehicleUtil.isTaskOver(vmsTosOrders.getStatus()) ? 0 : 1);
// resultMap.put("taskAssociation", vmsTosOrders.getTaskAssociation());
resultMap.put("taskType", vmsTosOrders.getTaskType());
if (!VehicleUtil.isTaskOver(vmsTosOrders.getStatus())) {
if (!(vmsTosOrders.getStartTime() == null)) {
resultMap.put("workTime", System.currentTimeMillis() - vmsTosOrders.getStartTime().getTime());
}
}
} else {
resultMap.put("workStatus", 1);
}
return resultMap;
}
/**
* 车辆行程查询
* @param vin 车辆vin
* @param startTime 查询起始时间
* @param stopTime 查询截止时间
* @param faultGrade 故障等级
*/
@Override
public SSIResponse getVehicleTrip(String vin, Long startTime, Long stopTime, String faultGrade) {
Date startDate = startTime == null ? null : new Date(startTime);
Date stopDate = stopTime == null ? null : new Date(stopTime);
List<VmsTosOrders> list = baseMapper.getVehicleTrip(vin, startDate, stopDate);
Map<String, Object> params = new HashMap<>();
params.put("startTime", startDate);
params.put("stopTime", stopDate);
params.put("faultGrade", faultGrade);
List<String> vins = new ArrayList<>();
vins.add(vin);
params.put("vins", vins);
List<VmsVehicleAlertHistoryVo> vehicleAlertHistoryList = vehicleTroubleHistoryMapper.getAlertHistoryList(params);
//异常过滤任务
List<VmsTosOrders> resultList = filterOrders(list, faultGrade, vehicleAlertHistoryList);
//查询里程能耗信息
resultList.parallelStream().forEach(vmsTosOrders -> {
VmsTaskJourneyInfo vmsTaskJourneyInfo = taskJourneyInfoMapper.selectOne(new LambdaQueryWrapper<VmsTaskJourneyInfo>()
.eq(VmsTaskJourneyInfo::getTaskId, vmsTosOrders.getTaskNo()));
changeUnit(vmsTaskJourneyInfo);
//计算百公里能耗
calcHundredEnergy
(vmsTaskJourneyInfo);
vmsTosOrders.setVmsTaskJourneyInfo(vmsTaskJourneyInfo);
});
return SSIResponse.ok(resultList);
}
private void changeUnit(VmsTaskJourneyInfo vmsTaskJourneyInfo) {
if (vmsTaskJourneyInfo == null) {
return;
}
//mile单位已经是千米了,不用再除以1000
/*if(vmsTaskJourneyInfo.getMile() != null){
vmsTaskJourneyInfo.setMile(vmsTaskJourneyInfo.getMile().divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
}*/
if (vmsTaskJourneyInfo.getTimeConsuming() != null) {
BigDecimal timeSeconds = new BigDecimal(vmsTaskJourneyInfo.getTimeConsuming()).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_CEILING);
vmsTaskJourneyInfo.setTime(formatTime(timeSeconds));
}
}
private List<VmsTosOrders> filterOrders(List<VmsTosOrders> list, String faultGrade, List<VmsVehicleAlertHistoryVo> alertList) {
//时长一分钟以内的任务过滤掉
list = list.stream().filter(vmsTosOrders -> {
Date startTime = vmsTosOrders.getStartTime();
Date endTime = vmsTosOrders.getEndTime();
if (startTime != null && endTime != null) {
return vmsTosOrders.getEndTime().getTime() - vmsTosOrders.getStartTime().getTime() > 60000;
}
return true;
}).collect(Collectors.toList());
if (StringUtils.isBlank(faultGrade)) {
return list;
} else {
if (alertList == null || alertList.isEmpty()) {
return new ArrayList<VmsTosOrders>();
}
}
List<VmsTosOrders> resultList = Lists.newArrayList();
list.stream().forEach(vmsTosOrders -> {
if (vmsTosOrders.getStartTime() == null || vmsTosOrders.getEndTime() == null) {
return;
}
if (vmsTosOrders.getStartTime().getTime() > alertList.get(0).getAlarmTime().getTime()) {
//任务结束时间大于最大异常开始时间
} else if (vmsTosOrders.getEndTime().getTime() < alertList.get(alertList.size() - 1).getAlarmTime().getTime()) {
//任务结束时间小于最小异常开始时间
} else {
resultList.add(vmsTosOrders);
}
});
return resultList;
}
/**
* 根据时间查询车辆能耗里程
*/
@Override
public SSIResponse getMileTimeByTime(String vin, Long startTime, Long stopTime) {
VmsTaskJourneyInfo vmsTaskJourneyInfo = execAnalysisForVmsTosOrders(vin, startTime, stopTime);
return SSIResponse.ok(vmsTaskJourneyInfo);
}
private VmsTaskJourneyInfo execAnalysisForVmsTosOrders(String vin, Long startTime, Long stopTime) {
VmsTaskJourneyInfo vmsTaskJourneyInfo = new VmsTaskJourneyInfo();
try {
vmsTaskJourneyInfo.setMileVal(0D);
vmsTaskJourneyInfo.setEnergyConsumingVal(0D);
vmsTaskJourneyInfo.setTimeConsuming(0L);
calc(vmsTaskJourneyInfo, vin, startTime, stopTime);
//单位转换
changeUnit(vmsTaskJourneyInfo);
vmsTaskJourneyInfo.setMile(new BigDecimal(vmsTaskJourneyInfo.getMileVal()).setScale(2, BigDecimal.ROUND_UP));
vmsTaskJourneyInfo.setEnergyConsuming(new BigDecimal(vmsTaskJourneyInfo.getEnergyConsumingVal()).setScale(2,
BigDecimal.ROUND_HALF_UP));
calcHundredEnergy(vmsTaskJourneyInfo);
} catch (Exception e) {
log.error("Fail to analysis vmstoorders.", e);
}
return vmsTaskJourneyInfo;
}
private void calc(VmsTaskJourneyInfo vmsTaskJourneyInfo, String vin, Long startTime, Long stopTime) throws IOException {
Gson gson = new GsonBuilder().create();
int size = 10000;
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(10L));
SearchResponse response = getSearchResponse(vin, startTime, stopTime, size, scroll);
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) {
calcMile(vmsTaskJourneyInfo, lastVehicleTerminalData, currentVehicleTerminalData);
caclTime(vmsTaskJourneyInfo, lastVehicleTerminalData, currentVehicleTerminalData);
calcEnergy(vmsTaskJourneyInfo, 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 calcHundredEnergy(VmsTaskJourneyInfo vmsTaskJourneyInfo) {
if (vmsTaskJourneyInfo != null && vmsTaskJourneyInfo.getEnergyConsuming() != null &&
vmsTaskJourneyInfo.getMile() != null && vmsTaskJourneyInfo.getMile().doubleValue() > 0) {
vmsTaskJourneyInfo.setHundredEnergyConsuming(vmsTaskJourneyInfo.getEnergyConsuming()
.divide(vmsTaskJourneyInfo.getMile(), 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
}
}
private void calcMile(VmsTaskJourneyInfo vmsTaskJourneyInfo, 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) {
// vmsTaskJourneyInfo.setMileVal(vmsTaskJourneyInfo.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);
vmsTaskJourneyInfo.setMileVal(vmsTaskJourneyInfo.getMileVal() + mile);
}
}
private void caclTime(VmsTaskJourneyInfo vmsTaskJourneyInfo, VehicleTerminalData lastVehicleTerminalData, VehicleTerminalData currentVehicleTerminalData) {
long time = currentVehicleTerminalData.getCollectTime() - lastVehicleTerminalData.getCollectTime();
vmsTaskJourneyInfo.setTimeConsuming(vmsTaskJourneyInfo.getTimeConsuming() + time);
}
private void calcEnergy(VmsTaskJourneyInfo vmsTaskJourneyInfo, VehicleTerminalData lastVehicleTerminalData,
VehicleTerminalData currentVehicleTerminalData) {
double energyConsuming = calcEnergy(lastVehicleTerminalData, currentVehicleTerminalData);
vmsTaskJourneyInfo.setEnergyConsumingVal(energyConsuming + vmsTaskJourneyInfo.getEnergyConsumingVal());
}
public static double calcEnergy(VehicleTerminalData lastVehicleTerminalData,
VehicleTerminalData currentVehicleTerminalData) {
double totalElectricity = lastVehicleTerminalData.getTotalElectricity();
double totalVoltage = lastVehicleTerminalData.getTotalVoltage();
if (totalElectricity == -1 || totalVoltage == -1) {
return 0;
}
return Math.abs((totalElectricity * totalVoltage) / 1000 *
(Double.parseDouble(String.valueOf(currentVehicleTerminalData.getCollectTime()
- lastVehicleTerminalData.getCollectTime())) / (1000 * 60 * 60)));
}
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) 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));
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);
}
@Override
public SSIPage queryPage(VmsTosOrdersVo ordersVo) {
String vehicleNum = ordersVo.getVehicleNum();
if (StringUtils.isNotBlank(vehicleNum)) {
VmsVehicle vehicle = vmsVehicleService.lambdaQuery().eq(VmsVehicle::getVehicleNum, vehicleNum).one();
if (vehicle == null) {
return new SSIPage(new Page<>());
}
String vin = vehicle.getVin();
ordersVo.setVin(vin);
}
IPage<VmsTosOrders> iPage = new Page<VmsTosOrders>(ordersVo.getPageIndex(), ordersVo.getPageSize());
IPage<VmsTosOrders> page = baseMapper.pageQuery(iPage,ordersVo);
List<VmsTosOrders> records = page.getRecords();
if (CollectionUtils.isEmpty(records)) {
return new SSIPage(page);
}
records.forEach(vmsTosOrders -> {
try {
vmsTosOrders.setStartTimeStamp(vmsTosOrders.getStartTime().getTime()/1000);
String costTime = getCostTime(vmsTosOrders);
vmsTosOrders.setCostTime(costTime);
Map<String, Object> map = redisDataModel.hgetJson2Map(vehicleCacheKey, vmsTosOrders.getVin());
vmsTosOrders.setVehicleNum((String) map.get("vehicleNum"));
String description = vehicleDataUtil.generateTaskLocationDescription(vmsTosOrders.getTaskLocationType(), vmsTosOrders.getVehicleLocation());
vmsTosOrders.setLocationDescription(description);
//添加lockLabel
Map<String, Object> orderMap = redisDataModel.getJson2Map(String.format("%s:%s", latestOrderKeyPrefix, vmsTosOrders.getVin()));
vmsTosOrders.setLockLabel(Objects.isNull(orderMap.get("lockLabel"))?null:(Integer)orderMap.get("lockLabel"));
} catch (Exception e) {
log.error("获取时间、车辆编号、地点描述异常:", e);
}
});
return new SSIPage(page);
}
/**
* 搬运集装箱的列表
*/
@Override
public SSIPage queryPageByAllStatus(VmsTosOrdersVo ordersVo) {
//查询车辆任务数据
List<VmsTosOrdersDto> ordersDtosList = vmsTosOrdersMapper.queryPageByAllStatus(ordersVo);
IPage<VmsTosOrdersKpiDto> vmsPage = new Page<>(ordersVo.getPageIndex(), ordersVo.getPageSize());
if (CollectionUtils.isEmpty(ordersDtosList)) {
return new SSIPage(vmsPage);
}
//查询任务的所有状态信息
List<String> taskNoList = ordersDtosList.stream().map(vmsTosOrders->vmsTosOrders.getTaskNo()).collect(Collectors.toList());
String year = DateUtils.format(ordersVo.getQueryStartTime(), "yyyy");
Map<String,List<TaskStatusHistory>> statusMap = vehicleElasticSearchModel.searchTaskHistory(taskNoList, year);
//封装大任务方法
List<VmsTosOrdersKpiDto> kpiOrderList = getVmsTosOrdersKpiDtos(ordersDtosList, statusMap);
//将队列逆序
Collections.reverse(kpiOrderList);
vmsPage.setRecords(kpiOrderList);
// threadStage.remove();
return new SSIPage(vmsPage);
}
/**
* 任务封装逻辑
* @param ordersDtosList
* @param statusMap
* @return
*/
public List<VmsTosOrdersKpiDto> getVmsTosOrdersKpiDtos(List<VmsTosOrdersDto> ordersDtosList, Map<String, List<TaskStatusHistory>> statusMap) {
/**
* 封装KPI数据
*/
List<VmsTosOrdersKpiDto> kpiOrderList = new ArrayList<>(); //结果集
VmsTosOrdersKpiDto kpiParentDto = new VmsTosOrdersKpiDto(); //大任务信息
kpiParentDto.setCollectTime(ordersDtosList.get(0).getCollectTime());
List<VmsTosOrdersDto> orderList = new ArrayList<>(); //大任务下子任务集合
List<VehicleDateStageDto> dateList = new ArrayList<>(); //大任务下步骤时间
VehicleDateStageDto dateStageDto = null;
int startPortType = 0;
int lastPortType = 0;//记录前一条记录的portType
int lastVehicleTaskLabel = 0;//记录前一条记录的任务标签 装船or卸船
int appControl = 0;
for(int i =0 ;i < ordersDtosList.size();i++){
VmsTosOrdersDto vmsTosOrdersDto = ordersDtosList.get(i);
//装船任务,任务从堆场作业开始;卸船任务,任务从桥吊开始;搬移任务,从第一个PortCode开始
if (vmsTosOrdersDto.getVehicleTaskLabel() == 1){//装船
startPortType = 2;//起点为场吊
}else if (vmsTosOrdersDto.getVehicleTaskLabel() == 2){//卸船
startPortType = 1;//起点轮胎吊
}
//APP控制
if(vmsTosOrdersDto.getAppControl()==1){
appControl = 1;
}
//封装当前任务的状态链
List<TaskStatusHistory> list = statusMap.get(vmsTosOrdersDto.getTaskNo());
if (CollectionUtils.isEmpty(list)) {
continue;
}
//转换状态链,并判断是否有车辆启动状态, 这个方法的代码似乎有些问题
TaskStatusHistory startTask = this.transferTaskStatus(list);
vmsTosOrdersDto.setStatusHistoryList(list);
//封装当前子任务的描述、耗时
long endTime = list.get(list.size()-1).getCollectTime();//最后状态的时间
vmsTosOrdersDto.setCostTime(getCostTime(vmsTosOrdersDto.getCollectTime(),endTime));//最后状态时间-任务指令时间
String description = vehicleDataUtil.generateTaskLocationDescription(vmsTosOrdersDto.getTaskLocationType(), vmsTosOrdersDto.getVehicleLocation());
vmsTosOrdersDto.setLocationDescription(description);
//大任务处理 非第一次进入, 结束上一个大任务,并开始新的大任务,根据任务的起点portType和任务类型标签VehicleTaskLabel来判断
/** 例如
* portType VehicleTaskLabel
* 1 2 |
* 1 2 | 大任务一
* 2 2 |————————
* 1 2 |
* 1 2 |大任务二
* 2 2 |——————
* 1 2 |
* 1 2 |大任务三
* 1 2 |
* 2 2 |______
*/
if ((vmsTosOrdersDto.getPortType() == startPortType
&& lastPortType != vmsTosOrdersDto.getPortType() && lastPortType != 0)
|| (lastVehicleTaskLabel != vmsTosOrdersDto.getVehicleTaskLabel() && lastVehicleTaskLabel != 0)){
//保存上一个大任务
kpiParentDto.setCostTime(getCostTime(kpiParentDto.getCollectTime(),kpiParentDto.getEndTime()));
dateList.add(dateStageDto);
kpiParentDto.setStatusDateList(dateList);
kpiParentDto.setVmsOrderList(orderList);
kpiOrderList.add(kpiParentDto);
//新建一个大任务
kpiParentDto = new VmsTosOrdersKpiDto();
//新建任务列表
orderList= new ArrayList<>();
//新建时间列表
dateList = new ArrayList<>();
//大任务开始时间
kpiParentDto.setCollectTime(vmsTosOrdersDto.getCollectTime());
kpiParentDto.setTaskNo(vmsTosOrdersDto.getTaskNo());
kpiParentDto.setContainerId(vmsTosOrdersDto.getContainerId());
kpiParentDto.setContainerSize(vmsTosOrdersDto.getContainerSize());
kpiParentDto.setContainerWeight(vmsTosOrdersDto.getContainerWeight());
kpiParentDto.setVehicleNum(vmsTosOrdersDto.getVehicleNum());
kpiParentDto.setVehicleTaskLabel(vmsTosOrdersDto.getVehicleTaskLabel());
kpiParentDto.setTaskSource(vmsTosOrdersDto.getTaskSource());
kpiParentDto.setAppControl(appControl);
}
//新建一个子任务时间对象,并赋值子任务开始时间
if (vmsTosOrdersDto.getPortType() != lastPortType){
if (dateStageDto != null && vmsTosOrdersDto.getPortType() != startPortType){
dateList.add(dateStageDto);
}
dateStageDto = new VehicleDateStageDto();
dateStageDto.setReceiveTosDate(vmsTosOrdersDto.getCollectTime());
}
//赋值子任务车辆启动时间
if (startTask != null){
dateStageDto.setVehicleStartDate(startTask.getCollectTime());
}
//赋值子任务结束时间
if ((i < ordersDtosList.size() -1
&& ordersDtosList.get(i+1).getPortType() != vmsTosOrdersDto.getPortType()
&& vmsTosOrdersDto.getEndTime() != null) || i == ordersDtosList.size() -1){
dateStageDto.setFinishDate(vmsTosOrdersDto.getEndTime() != null?vmsTosOrdersDto.getEndTime().getTime():null);
}
//设置大任务信息(存在第二段任务,将第一段任务覆盖)
if (vmsTosOrdersDto.getPortType() != startPortType){
kpiParentDto.setContainerId(vmsTosOrdersDto.getContainerId());
kpiParentDto.setContainerSize(vmsTosOrdersDto.getContainerSize());
kpiParentDto.setContainerWeight(vmsTosOrdersDto.getContainerWeight());
kpiParentDto.setVehicleNum(vmsTosOrdersDto.getVehicleNum());
kpiParentDto.setVehicleTaskLabel(vmsTosOrdersDto.getVehicleTaskLabel());
kpiParentDto.setAppControl(appControl);
}else{
kpiParentDto.setTaskNo(vmsTosOrdersDto.getTaskNo());
kpiParentDto.setTaskSource(vmsTosOrdersDto.getTaskSource());
}
kpiParentDto.setEndTime(endTime);
orderList.add(vmsTosOrdersDto);
lastPortType = vmsTosOrdersDto.getPortType();
lastVehicleTaskLabel = vmsTosOrdersDto.getVehicleTaskLabel();
}
kpiParentDto.setCostTime("0");
//保存最后一个大任务
if(Objects.nonNull(kpiParentDto.getCollectTime())&&Objects.nonNull(kpiParentDto.getEndTime())){
kpiParentDto.setCostTime(getCostTime(kpiParentDto.getCollectTime(),kpiParentDto.getEndTime()));
}
if(Objects.nonNull(dateStageDto)){
dateList.add(dateStageDto);
}
kpiParentDto.setStatusDateList(dateList);
kpiParentDto.setVmsOrderList(orderList);
kpiOrderList.add(kpiParentDto);
return kpiOrderList;
}
//根据状态模板转化
private TaskStatusHistory transferTaskStatus(List<TaskStatusHistory> list) {
int transferNum = 0;
TaskStatusHistory startTask = null;
for(Integer status : VehicleConstant.statusTemp){
TaskStatusHistory historyStatus = null;
if (transferNum < list.size()){
historyStatus = list.get(transferNum);
if (historyStatus.getStatus() == VehicleConstant.START_TASK){
startTask = historyStatus;
}
if (historyStatus.getStatus() == VehicleConstant.TASK_FAIL && transferNum < list.size()-1){
list.remove(0);
}
//任务终止、取消成功状态,直接返回
if (historyStatus.getStatus() == VehicleConstant.TASK_FAIL || historyStatus.getStatus() == VehicleConstant.TASK_CANCEL_SUCCESS
|| historyStatus.getStatus() == VehicleConstant.FORCE_CANCEL_SUCCESS){
break;
}
//状态不存在于模板中,跳过该状态
if (!VehicleConstant.statusTemp.contains(historyStatus.getStatus())){
transferNum ++;
if (transferNum >= list.size()){
continue;
}
historyStatus = list.get(transferNum);//???跳过当前状态,进入下一状态
}
//当前状态与模板一致
if (historyStatus.getStatus() == status){
transferNum ++;
continue;
}
}
//构建缺失的状态数据
TaskStatusHistory transferStatus = new TaskStatusHistory();
VmsTosOrderStatusEnum anEnum = VmsTosOrderStatusEnum.find(status);//获取当前状态的状态描述
if (anEnum != null) {
transferStatus.setStatusDescription(anEnum.getDescription());
}
transferStatus.setStatus(status);
if (transferNum -1 >= 0){
historyStatus = list.get(transferNum-1);
}
transferStatus.setVehicleNum(historyStatus.getVehicleNum());
transferStatus.setCollectTime(historyStatus.getCollectTime());
transferStatus.setSn(historyStatus.getSn());
transferStatus.setVin(historyStatus.getVin());
transferStatus.setExisted(false);
list.add(transferNum,transferStatus);
transferNum ++;
}
return startTask;
}
@Override
public void export(VmsTosOrdersVo vmsTosOrdersVo, HttpServletResponse response) {
int exportType = vmsTosOrdersVo.getExportType();
List<VmsTosOrders> list;
ExcelDataHandlerDefaultImpl<Object> excelDataHandler = new ExcelDataHandlerDefaultImpl<Object>() {
@Override
public String[] getNeedHandlerFields() {
return new String[]{"作业时间","指令来源","APP介入"};
}
@Override
public Object exportHandler(Object obj, String name, Object value) {
if ("作业时间".equals(name)) {
VmsTosOrders order = (VmsTosOrders) obj;
return getCostTime(order);
}
if("指令来源".equals(name)){
if(1 == (Integer) value){
return "TOS下发";}
else if (2 == (Integer) value){
return "手动下发";}
else if (3 == (Integer) value){
return "VMS下发";}
}
if("APP介入".equals(name)){
return 1 == (Integer) value?"是":"否";
}
return super.exportHandler(obj, name, value);
}
};
if (vmsTosOrdersVo.getStartTime() == null){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH,-3);
vmsTosOrdersVo.setStartTime(calendar.getTime());
}
if (exportType == 0) {
SSIPage ssiPage = queryPage(vmsTosOrdersVo);
list = (List<VmsTosOrders>) ssiPage.getList();
PoiUtils.exportExcel(excelDataHandler, list, "任务清单", "ChargeOrder", VmsTosOrders.class, "任务清单" + ".xls", true, response);
} else {
vmsTosOrdersVo.setPageIndex(1);
vmsTosOrdersVo.setPageSize(1000000);
SSIPage ssiPage = queryPage(vmsTosOrdersVo);
list = (List<VmsTosOrders>) ssiPage.getList();
PoiUtils.exportExcel(excelDataHandler, list, "任务清单", "ChargeOrder", VmsTosOrders.class, "任务清单" + ".xls", true, response);
// ExcelBatchExportService batchExportService = new ExcelBatchExportService();
// ExportParams exportParams = new ExportParams("任务清单", "任务清单");
// exportParams.setDataHandler(excelDataHandler);
// exportParams.setMaxNum(1000000);
// batchExportService.init(exportParams, VmsTosOrdersVo.class);
// this.getBaseMapper().getListAsStream(vmsTosOrdersVo, resultContext -> {
// VmsTosOrders orders = resultContext.getResultObject();
// batchExportService.appendData(Arrays.asList(orders));
// });
// Workbook workbook = batchExportService.closeExportBigExcel();
// PoiUtils.downLoadExcel("任务清单.xlsx", response, workbook);
}
}
private String formatTime(BigDecimal seconds) {
int sec = seconds.intValue();
if (sec < 0) {
return "0秒";
}
StringBuilder sb = new StringBuilder();
if (sec < 60) {
sb.append(seconds + "秒");
} else if (sec >= 60 && sec < 3600) {
int m = sec / 60;
int s = sec % 60;
sb.append(m + "分");
if (s > 0) {
sb.append(s + "秒");
}
} else {
int h = sec / 3600;
int m = (sec % 3600) / 60;
int s = (sec % 3600) % 60;
sb.append(h + "小时");
if (m > 0) {
sb.append(m + "分");
}
if (s > 0) {
sb.append(s + "秒");
}
}
return sb.toString();
}
/**
* 根据异常报警查询行程
*/
@Override
public SSIResponse getTripByAlert(String vin, String alertId) {
VmsVehicleAlertHistory alertHistory = vehicleTroubleService.getById(alertId);
if (alertHistory == null) {
return SSIResponse.ok();
}
List<VmsTosOrders> list = this.list(new LambdaQueryWrapper<VmsTosOrders>()
.eq(StringUtils.isNotBlank(vin), VmsTosOrders::getVin, vin)
.le(alertHistory.getAlarmTime() != null, VmsTosOrders::getStartTime, alertHistory.getAlarmTime())
.ge(alertHistory.getAlarmTime() != null, VmsTosOrders::getEndTime, alertHistory.getAlarmTime())
.orderByDesc(VmsTosOrders::getStartTime));
if (list != null && !list.isEmpty()) {
return SSIResponse.ok(list.get(0));
}
return SSIResponse.ok();
}
/**
* 获得各业务箱数
*/
@Override
@Cached(name = "vmsTosOrdersServiceImpl:queryContainerNumOneDay", expire = 60, timeUnit = TimeUnit.SECONDS)
@CacheRefresh(refresh = 30, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.SECONDS)
public SSIResponse queryContainerNumOneDay(LocalDateTime startTime, LocalDateTime endTime) {
List<TaskAnalysisVo> list = this.getBaseMapper().queryContainerNumByDay(startTime, endTime);
if (CollectionUtils.isEmpty(list)) {
TaskAnalysisVo vo = new TaskAnalysisVo();
vo.setDate(startTime.toLocalDate());
vo.setHandleContainerNum(0);
vo.setLoadContainerNum(0);
vo.setUnloadContainerNum(0);
return SSIResponse.ok(vo);
}
return SSIResponse.ok(list.get(0));
}
@Override
@Cached(name = "vmsTosOrdersServiceImpl:queryContainerNum", expire = 60, timeUnit = TimeUnit.SECONDS)
@CacheRefresh(refresh = 30, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.SECONDS)
public SSIResponse queryContainerNum() {
TaskAnalysisVo vo = this.getBaseMapper().queryContainerNum(null,null,null);
return SSIResponse.ok(vo);
}
/**
* 获得最近n天各业务箱数
*/
@Override
@Cached(name = "vmsTosOrdersServiceImpl:queryContainerNumByDay", expire = 60, timeUnit = TimeUnit.SECONDS)
@CacheRefresh(refresh = 30, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.SECONDS)
public SSIResponse queryContainerNumByDay(LocalDateTime startTime, LocalDateTime endTime) throws Exception {
if (startTime.isAfter(endTime)) {
return SSIResponse.no("查询起始时间需在结束时间之前");
}
List<TaskAnalysisVo> list = vmsTosOrdersAnalysisMapper.getTaskTrendByDay(startTime, endTime);
List<DayHourTrend> resList = TaskAnalysisVo.fillBlankDay(list, TaskAnalysisVo.class, startTime, endTime);
return SSIResponse.ok(resList);
}
/**
* 获得各业务运输效率
*/
@Override
@Cached(name = "vmsTosOrdersServiceImpl:queryContainerAvgTimeOneDay", expire = 60, timeUnit = TimeUnit.SECONDS)
@CacheRefresh(refresh = 30, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.SECONDS)
public SSIResponse queryContainerAvgTimeOneDay(LocalDateTime startTime, LocalDateTime endTime) {
List<TaskAnalysisVo> list = this.getBaseMapper().queryContainerAvgTimeByDay(startTime, endTime);
if (CollectionUtils.isEmpty(list)) {
TaskAnalysisVo vo = new TaskAnalysisVo();
vo.setDate(startTime.toLocalDate());
vo.setHandleContainerAvgTime(0d);
vo.setLoadContainerAvgTime(0d);
vo.setUnloadContainerAvgTime(0d);
return SSIResponse.ok(vo);
}
return SSIResponse.ok(list.get(0));
}
@Override
@Cached(name = "vmsTosOrdersServiceImpl:queryContainerAvgTime", expire = 60, timeUnit = TimeUnit.SECONDS)
@CacheRefresh(refresh = 30, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.SECONDS)
public SSIResponse queryContainerAvgTime() {
TaskAnalysisVo vo = this.getBaseMapper().queryContainerAvgTime(null,null,null);
return SSIResponse.ok(vo);
}
@Override
public SSIResponse getNumByVin(String vin) {
Map<String, Integer> resultMap = new HashMap<>();
AtomicInteger loadingGoodsNum = new AtomicInteger(0);
AtomicInteger unloadingGoodsNum = new AtomicInteger(0);
AtomicInteger arrangeGoodsNum = new AtomicInteger(0);
List<VmsTosOrders> list = this.list(new LambdaQueryWrapper<VmsTosOrders>().eq(VmsTosOrders::getVin, vin));
list.parallelStream().forEach(vmsTosOrders -> {
if (vmsTosOrders.getTaskType() != null && vmsTosOrders.getVehicleTaskLabel() != null) {
Integer containerNum = vmsTosOrders.getContainerNum() != null ? vmsTosOrders.getContainerNum() : 0;
Integer vehicleTaskLabel = vmsTosOrders.getVehicleTaskLabel();
Integer taskType = vmsTosOrders.getTaskType();
if (vehicleTaskLabel == 2 && taskType == 1) {
unloadingGoodsNum.getAndAdd(containerNum);
} else if (vehicleTaskLabel == 1 && taskType == 2) {
loadingGoodsNum.getAndAdd(containerNum);
} else if (vehicleTaskLabel == 3 && taskType == 1) {
arrangeGoodsNum.getAndAdd(containerNum);
}
}
});
resultMap.put("loadingGoodsNum", loadingGoodsNum.intValue());
resultMap.put("unloadingGoodsNum", unloadingGoodsNum.intValue());
resultMap.put("arrangeGoodsNum", arrangeGoodsNum.intValue());
return SSIResponse.ok(resultMap);
}
/**
* 获取当前pad对应桥吊可选车辆
*/
@Override
public SSIResponse getVehicleByPadMac(String padMac, String taskNo) {
// List<VehicleOrderVo> list = baseMapper.getVehicleByPadMac(padMac);
// VehicleOrderVo cur = null;
// for (int i = 0; i < list.size(); i++) {
// if (taskNo.equals(list.get(i).getTaskNo())) {
// cur = list.get(i);
// list.remove(i);
// }
// }
// list.add(0, cur);
// return SSIResponse.ok(list);
List<VmsVehicle> normalVehicle = vmsVehicleService.getNormalVehicle();
Map<String, VmsVehicle> vinMap = normalVehicle.stream().collect(Collectors.toMap(VmsVehicle::getVin, Function.identity()));
List<VmsCranePadBind> padBindList = vmsCranePadBindService.list(new LambdaQueryWrapper<VmsCranePadBind>().eq(VmsCranePadBind::getPadMac, padMac));
String craneNo = padBindList.get(0).getCraneNo();
//判断港机类型
Integer taskLocationType = padBindList.get(0).getCraneType() == 1 ? 5 : 1;
//获取当前所有任务
Set<String> keys = redisDataModel.keys(latestOrderKeyPrefix + "*");
List<String> orderList = redisDataModel.mget(keys.toArray(new String[keys.size()]));
List<VehicleOrderVo> vehicleOrderVos = Lists.newArrayList();
if (CollectionUtils.isNotEmpty(keys)) {
if (CollectionUtils.isNotEmpty(orderList)) {
List<VmsTosOrders> res = orderList.stream().map(s -> JSON.parseObject(s, VmsTosOrders.class))
.filter(vmsTosOrders -> {
if (craneNo.equals(vmsTosOrders.getPortCode()) && !VehicleUtil.isTaskOver(vmsTosOrders.getStatus())
&& vmsTosOrders.getTaskLocationType() == taskLocationType) {
return true;
}
return false;
}).collect(Collectors.toList());
if (!res.isEmpty()) {
res = res.stream().sorted(Comparator.comparing(VmsTosOrders::getCollectTime)).collect(Collectors.toList());
res.stream().forEach(vmsTosOrders -> {
VmsVehicle vmsVehicle = vinMap.get(vmsTosOrders.getVin());
if (vmsVehicle == null) {
return;
}
VehicleOrderVo vehicleOrderVo = new VehicleOrderVo();
BeanUtils.copyProperties(vmsVehicle, vehicleOrderVo);
vehicleOrderVo.setStartTime(vmsTosOrders.getStartTime());
vehicleOrderVo.setTaskNo(vmsTosOrders.getTaskNo());
vehicleOrderVos.add(vehicleOrderVo);
});
VehicleOrderVo cur = null;
for (int i = 0; i < vehicleOrderVos.size(); i++) {
if (taskNo.equals(vehicleOrderVos.get(i).getTaskNo())) {
cur = vehicleOrderVos.get(i);
vehicleOrderVos.remove(i);
}
}
if (cur != null) {
vehicleOrderVos.add(0, cur);
}
}
}
}
return SSIResponse.ok(vehicleOrderVos);
}
/**
* 查询任务状态历史
*/
@Override
public SSIResponse getTaskHistory(String taskNo) {
List<VmsTosOrders> orders = this.lambdaQuery().eq(VmsTosOrders::getTaskNo, taskNo)
// .eq(VmsTosOrders::getDeleted, 0)
.list();
if (CollectionUtils.isEmpty(orders)) {
return SSIResponse.no("任务不存在");
}
Date collectTime = new Date(orders.get(0).getCollectTime());
String year = DateUtils.format(collectTime, "yyyy");
List<TaskStatusHistory> list = vehicleElasticSearchModel.searchTaskHistory(taskNo, year);
if (CollectionUtils.isNotEmpty(list)) {
list.forEach(taskStatusHistory -> {
Map<String, Object> map = redisDataModel.hgetJson2Map(vehicleCacheKey, taskStatusHistory.getVin());
String num = (String) map.get("vehicleNum");
taskStatusHistory.setVehicleNum(num);
});
}
return SSIResponse.ok(list);
}
/**
* 进行中的任务列表
*/
@Override
public SSIPage listInProcess(VmsTosOrdersVo vmsTosOrdersVo) {
if (vmsTosOrdersVo == null) {
vmsTosOrdersVo = new VmsTosOrdersVo();
}
String vehicleNum = vmsTosOrdersVo.getVehicleNum();
if (StringUtils.isNotBlank(vehicleNum)) {
VmsVehicle vehicle = vmsVehicleService.lambdaQuery().eq(VmsVehicle::getVehicleNum, vehicleNum).one();
if (vehicle == null) {
return new SSIPage(new Page<>());
}
vmsTosOrdersVo.setVin(vehicle.getVin());
}
LocalDateTime dateTime = LocalDateTime.now().minus(24, ChronoUnit.HOURS);
Date startTime = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
IPage<VmsTosOrders> page = this.lambdaQuery()
.eq(vmsTosOrdersVo.getTaskType() != null, VmsTosOrders::getTaskType, vmsTosOrdersVo.getTaskType())
.eq(vmsTosOrdersVo.getStatus() != null, VmsTosOrders::getStatus, vmsTosOrdersVo.getStatus())
.eq(VmsTosOrders::getDeleted, 0)
.like(StringUtils.isNotBlank(vmsTosOrdersVo.getTaskNo()), VmsTosOrders::getTaskNo, vmsTosOrdersVo.getTaskNo())
.like(StringUtils.isNotBlank(vmsTosOrdersVo.getVin()), VmsTosOrders::getVin, vmsTosOrdersVo.getVin())
.ge(VmsTosOrders::getCollectTime, startTime)
.notIn(VmsTosOrders::getStatus, 35, 36, 37)
.orderByDesc(VmsTosOrders::getCollectTime)
.page(new Page<>(vmsTosOrdersVo.getPageIndex(), vmsTosOrdersVo.getPageSize()));
List<VmsTosOrders> records = page.getRecords();
if (CollectionUtils.isNotEmpty(records)) {
records.forEach(vmsTosOrders -> {
try {
String costTime = getCostTime(vmsTosOrders);
vmsTosOrders.setCostTime(costTime);
Map<String, Object> map = redisDataModel.hgetJson2Map(vehicleCacheKey, vmsTosOrders.getVin());
String num = (String) map.get("vehicleNum");
vmsTosOrders.setVehicleNum(num);
} catch (Exception e) {
log.error("获取时间、车辆编号异常:", e);
}
});
}
return new SSIPage(page);
}
private String getCostTime(long startTime, long endTime) {
Date startDate = new Date(startTime);
Date endDate = new Date(endTime);
return getCostTime(startDate, endDate);
}
private String getCostTime(VmsTosOrders vmsTosOrders) {
Date startTime = new Date(vmsTosOrders.getCollectTime());
Date endTime = vmsTosOrders.getEndTime();
if (endTime == null) {
endTime = vmsTosOrders.getUpdateTime();
}
if (startTime == null) {
return "";
}
long diff = 0;
if (endTime != null) {
diff = endTime.getTime() - startTime.getTime();
}
BigDecimal timeSeconds = new BigDecimal(diff).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_HALF_UP);
vmsTosOrders.setCostTimeSeconds(timeSeconds.intValue());
return formatTime(timeSeconds);
}
private String getCostTime(Date startTime, Date endTime) {
if (startTime == null) {
return "";
}
long diff = 0;
if (endTime != null) {
diff = endTime.getTime() - startTime.getTime();
}
BigDecimal timeSeconds = new BigDecimal(diff).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_HALF_UP);
String time = formatTime(timeSeconds);
return time;
}
/**
* 实时任务列表
*/
@Override
public SSIPage realTimeTasks(VmsTosOrdersVo vmsTosOrdersVo) {
Page<VmsVehicle> page = vmsVehicleService.page(new Page<>(vmsTosOrdersVo.getPageIndex(), vmsTosOrdersVo.getPageSize()),
new LambdaQueryWrapper<VmsVehicle>().eq(VmsVehicle::getStatus, 0));
List<VmsVehicle> vehicles = page.getRecords();
if (CollectionUtils.isNotEmpty(vehicles)) {
List<Map<String, Object>> list = vehicles.stream().map(vmsVehicle -> {
Map<String, Object> map = redisDataModel.getJson2Map(String.format("%s:%s", latestOrderKeyPrefix, vmsVehicle.getVin()));
if (map != null) {
String description = vehicleDataUtil.generateTaskLocationDescription(map);
map.put("locationDescription", description);
Date collectTime = null;
if (map.get("collectTime") != null) {
collectTime = new Date((long) map.get("collectTime"));
}
Date endTime = null;
if (map.get("endTime") != null) {
endTime = new Date((long) map.get("endTime"));
}
map.put("costTime", getCostTime(collectTime, endTime));
map.put("vehicleNum", vmsVehicle.getVehicleNum());
VmsVehicleRemoteInstruction queryEntity = new VmsVehicleRemoteInstruction();
queryEntity.setInstructionType("APP");
queryEntity.setResult((byte)1);
queryEntity.setTaskId(map.get("taskNo")+","+map.get("taskNoMapping"));
Integer count = vehicleRemoteInstructionMapper.selectCount(new QueryWrapper<>(queryEntity));
map.put("appControl",0);
if(count>0){
map.put("appControl",1);
}
if(Objects.isNull(map.get("taskSource"))){
map.put("taskSource",1);
}
} else {
map = new HashMap<>();
map.put("vehicleNum", vmsVehicle.getVehicleNum());
map.put("collectTime", 0L);
}
return map;
}).sorted((o1, o2) -> (long) o1.get("collectTime") > (long) o2.get("collectTime") ? -1 : 1)
.collect(Collectors.toList());
return new SSIPage(list, (int) page.getTotal(), (int) page.getSize(), (int) page.getCurrent());
}
return new SSIPage(null, (int) page.getTotal(), (int) page.getSize(), (int) page.getCurrent());
}
/**
* 获取某一天的任务KPI
*/
@Override
public List getDailyKpi(LocalDateTime startTime, LocalDateTime endTime, String vehicleNum) {
List<VmsVehicle> vehicles = vmsVehicleService.list(new LambdaQueryWrapper<VmsVehicle>()
.eq(VmsVehicle::getStatus, 0)
.like(StringUtils.isNotBlank(vehicleNum), VmsVehicle::getVehicleNum, vehicleNum)
.orderByAsc(VmsVehicle::getVehicleNum));
List<VehicleKpiVo.HourKpi> list = getBaseMapper().getDailyKpi(startTime, endTime);
List<Map<String, Object>> containerList = getBaseMapper().getContainNum(startTime,endTime);
Map<String, String> containerMap = new HashedMap();
for (Map<String, Object> map : containerList) {
containerMap.put(String.valueOf(map.get("vin")),String.valueOf(map.get("count")));
}
if (CollectionUtils.isNotEmpty(vehicles)) {
List<Map> resList = vehicles.stream().map(vmsVehicle -> {
try {
String vNum = vmsVehicle.getVehicleNum();
String vin = vmsVehicle.getVin();
VehicleKpiVo vehicleKpiVo = new VehicleKpiVo(vin, vNum);
vehicleKpiVo.setDate(startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
vehicleKpiVo.fillData(list);
Map<String, String> map = vehicleKpiVo.toMap();
map.put("containerNum",containerMap.get(vin) != null ? containerMap.get(vin) : "0");
return map;
} catch (Exception e) {
log.error("获取daily kpi异常", e);
}
return null;
}).filter(map -> map != null).collect(Collectors.toList());
return resList;
}
return null;
}
@Override
public List taskKPI(VmsTosOrdersKPIVo vmsTosOrders) throws Exception {
//任务KPI-效率OEE分析
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<TaskKPIVo> resLists = new ArrayList<>();
if (vmsTosOrders.getStartTime() == null || vmsTosOrders.getEndTime() == null) {
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 1, 23, 59, 59);//昨天的时间
long nowStartTime = calendar.getTime().getTime();//毫秒级时间戳
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 3, 00, 00, 00);//三天前的时间
long nowEndTime = calendar.getTime().getTime();//毫秒级时间戳
resLists = vmsTosOrdersMapper.taskKPI(vmsTosOrders, String.valueOf(nowStartTime), String.valueOf(nowEndTime));//查询 任务KPI-效率OEE分析
} else {
resLists = vmsTosOrdersMapper.taskKPI(vmsTosOrders, null, null);//查询 任务KPI-效率OEE分析
}
List<TaskKPIVo> rest = new ArrayList<>();
for (int i = 0; i < resLists.size(); i++) {
TaskKPIVo taskKPIVo = new TaskKPIVo();
taskKPIVo.setVin(resLists.get(i).getVin());//VIN
taskKPIVo.setVehicleNum(resLists.get(i).getVehicleNum());//车辆编号
taskKPIVo.setTaskNo(resLists.get(i).getTaskNo());//任务编号
Date collectTimeYear = format.parse(resLists.get(i).getInstructionWaitingTime());
String year = DateUtils.format(collectTimeYear, "yyyy");
List<TaskStatusHistory> list = vehicleElasticSearchModel.searchTaskHistory(resLists.get(i).getTaskNo(), year);
Date collectTime = format.parse(resLists.get(i).getInstructionWaitingTime());
Long vehicleReceivingTime = null;//车辆接收时间
Long taskBegins = null;//任务开始
Long destination = null;//到达目的地
Long vehicleStoppingLocking = null;//车辆停稳锁死
Long threeConfirmedCompletion = null;//三重确认完成
for (int j = 0; j < list.size(); j++) {
if (list.get(j).getStatus() == 43) {//车辆接受 43;
vehicleReceivingTime = list.get(j).getCollectTime();
}
if (list.get(j).getStatus() == 15) {//任务开始 15;
taskBegins = list.get(j).getCollectTime();
}
if (list.get(j).getStatus() == 3) {//到达目的地 3;
destination = list.get(j).getCollectTime();
}
if (list.get(j).getStatus() == 49) {//车辆停稳锁死 49;
vehicleStoppingLocking = list.get(j).getCollectTime();
}
if (list.get(j).getStatus() == 37) {//三重确认完成 37;
threeConfirmedCompletion = list.get(j).getCollectTime();
}
}
//指令等待时间 = 车辆接收时间 - collect_time
if (vehicleReceivingTime == null) {
taskKPIVo.setInstructionWaitingTime("0");
} else {
long diff1 = vehicleReceivingTime - collectTime.getTime();
String instruc = String.valueOf(diff1 / (60 * 1000) % 60);
taskKPIVo.setInstructionWaitingTime(isNumeric(instruc) ? instruc : "0");
}
//作业准备时间 = 任务开始-车辆接受
if (vehicleReceivingTime == null || taskBegins == null) {
taskKPIVo.setHomeworkPreparationTime("0");
} else {
long diff2 = taskBegins - vehicleReceivingTime;
String homework = String.valueOf(diff2 / (60 * 1000) % 60);
taskKPIVo.setHomeworkPreparationTime(isNumeric(homework) ? homework : "0");
}
//移动到去箱点时间 = 到达目的地或者车辆停稳锁死-任务开始
if (taskBegins == null) {
taskKPIVo.setMoveTheBoxTime("0");
} else {
if (vehicleStoppingLocking != null) {//车辆停稳锁死
long diff3 = vehicleStoppingLocking - taskBegins;
String moveThe = String.valueOf(diff3 / (60 * 1000) % 60);
taskKPIVo.setMoveTheBoxTime(isNumeric(moveThe) ? moveThe : "0");
} else if (destination != null) {//到达目的地
long diff3 = destination - taskBegins;
String moveThe = String.valueOf(diff3 / (60 * 1000) % 60);
taskKPIVo.setMoveTheBoxTime(isNumeric(moveThe) ? moveThe : "0");
} else {
// long diff3 = taskBegins.getTime();
// String moveThe = String.valueOf(diff3 / (60 * 1000) % 60);
// taskKPIVo.setMoveTheBoxTime(isNumeric(moveThe)? moveThe : "0");
taskKPIVo.setMoveTheBoxTime("0");
}
}
//取箱点等待时间 = 三重确认完成-到达目的地或者车辆停稳锁死
if (threeConfirmedCompletion == null) {
taskKPIVo.setPickingTime("0");
} else {
if (vehicleStoppingLocking != null) {//车辆停稳锁死
long diff4 = threeConfirmedCompletion - vehicleStoppingLocking;
String pickingTime = String.valueOf(diff4 / (60 * 1000) % 60);
taskKPIVo.setPickingTime(isNumeric(pickingTime) ? pickingTime : "0");
} else if (destination != null) {//到达目的地
long diff4 = threeConfirmedCompletion - destination;
String pickingTime = String.valueOf(diff4 / (60 * 1000) % 60);
taskKPIVo.setPickingTime(isNumeric(pickingTime) ? pickingTime : "0");
} else {
// long diff4 = threeConfirmedCompletion.getTime();
// String pickingTime = String.valueOf(diff4 / (60 * 1000) % 60);
// taskKPIVo.setPickingTime(isNumeric(pickingTime)? pickingTime : "0");
taskKPIVo.setPickingTime("0");
}
}
taskKPIVo.setBoxQuantity(resLists.get(i).getBoxQuantity());
rest.add(taskKPIVo);
}
return rest;
}
/**
* 判断是否为数字,包含负数情况
*
* @param str
* @return
*/
private boolean isNumeric(String str) {
Boolean flag = false;
String tmp;
if (StringUtils.isNotBlank(str)) {
if (str.startsWith("-")) {
tmp = str.substring(1);
flag = false;
return flag;
} else {
tmp = str;
}
flag = tmp.matches("^[0.0-9.0]+$");
}
return flag;
}
/**
* 车管平台强制取消
*/
@Override
public SSIResponse forceCancel(String taskNo) {
log.info("强制取消任务,任务编号:{}", taskNo);
VmsTosOrders order = lambdaQuery().eq(VmsTosOrders::getTaskNo, taskNo).one();
if (order == null) {
return SSIResponse.no("任务不存在");
}
String vin = order.getVin();
String url = commandUrl + "/command/force/cancel";
HashMap<String, Object> param = new HashMap<>();
param.put("vin", vin);
param.put("taskNo", taskNo);
param.put("taskOperation", 2);
AccessResponse accessResponse = restTemplate.postForObject(url, param, AccessResponse.class);
log.info("强制取消任务,任务编号:" + taskNo + ",返回结果:" + JSON.toJSONString(accessResponse));
if (accessResponse.isSuccess()) {
Map data = (Map) accessResponse.getData();
Integer res = (Integer) data.get("result");
if (res == 1) {
return SSIResponse.ok("取消成功");
} else if (res == 2) {
return SSIResponse.no("取消失败");
}
} else {
String msg = accessResponse.getStatus().getDetails();
return SSIResponse.no(msg);
}
return SSIResponse.no("取消成功");
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsTosOrders;
import com.ssi.entity.VmsTosOriginalOrders;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.vo.VmsTosOrdersVo;
import com.ssi.model.RedisDataModel;
import com.ssi.response.SSIPage;
import com.ssi.service.VmsTosOriginalOrdersService;
import com.ssi.mapper.VmsTosOriginalOrdersMapper;
import com.ssi.service.VmsVehicleService;
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.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
*
*/
@Service
public class VmsTosOriginalOrdersServiceImpl extends ServiceImpl<VmsTosOriginalOrdersMapper, VmsTosOriginalOrders>
implements VmsTosOriginalOrdersService{
@Autowired
private VmsVehicleService vmsVehicleService;
@Autowired
private RedisDataModel redisDataModel;
@Value("${order.latestOrderKeyPrefix:harbor:command:status}")
private String latestOrderKeyPrefix;
@Value("${vehicle.cache.key:ivccs:vms:vehicle:cache}")
private String vehicleCacheKey;
@Override
public SSIPage queryPageByCondition(VmsTosOrdersVo ordersVo) {
List<VmsVehicle> vehicles = vmsVehicleService.list();
Map<String, String> vin2Num = vehicles.stream().collect(Collectors.toMap(VmsVehicle::getVin, VmsVehicle::getVehicleNum));
String vehicleNum = ordersVo.getVehicleNum();
if (StringUtils.isNotBlank(vehicleNum)) {
Map.Entry<String, String> currentEntry = vin2Num.entrySet().stream().filter(e -> e.getValue().equalsIgnoreCase("vehicleNum")).findAny().orElse(null);
if (currentEntry == null) {
return new SSIPage(new Page<>());
}
String vin = currentEntry.getKey();
ordersVo.setVin(vin);
}
IPage<VmsTosOriginalOrders> iPage = new Page<>(ordersVo.getPageIndex(), ordersVo.getPageSize());
IPage<VmsTosOriginalOrders> page = baseMapper.pageQuery(iPage,ordersVo);
List<VmsTosOriginalOrders> records = page.getRecords();
if (CollectionUtils.isEmpty(records)) {
return new SSIPage(page);
}
records.forEach(vmsTosOrders -> {
try {
vmsTosOrders.setStartTimeStamp(vmsTosOrders.getStartTime().getTime()/1000);
String costTime = getCostTime(vmsTosOrders);
vmsTosOrders.setCostTime(costTime);
vmsTosOrders.setVehicleNum(vin2Num.get(vmsTosOrders.getVin()));
//添加lockLabel
Map<String, Object> orderMap = redisDataModel.getJson2Map(String.format("%s:%s", latestOrderKeyPrefix, vmsTosOrders.getVin()));
vmsTosOrders.setLockLabel(Objects.isNull(orderMap.get("lockLabel"))?null:(Integer)orderMap.get("lockLabel"));
} catch (Exception e) {
log.error("获取时间、车辆编号、地点描述异常:", e);
}
});
return new SSIPage(page);
}
private String getCostTime(VmsTosOriginalOrders vmsTosOrders) {
Date startTime = new Date(vmsTosOrders.getCollectTime());
Date endTime = vmsTosOrders.getEndTime();
if (endTime == null) {
endTime = vmsTosOrders.getUpdateTime();
}
if (startTime == null) {
return "";
}
long diff = 0;
if (endTime != null) {
diff = endTime.getTime() - startTime.getTime();
}
BigDecimal timeSeconds = new BigDecimal(diff).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_HALF_UP);
vmsTosOrders.setCostTimeSeconds(timeSeconds.intValue());
return formatTime(timeSeconds);
}
private String formatTime(BigDecimal seconds) {
int sec = seconds.intValue();
if (sec < 0) {
return "0秒";
}
StringBuilder sb = new StringBuilder();
if (sec < 60) {
sb.append(seconds + "秒");
} else if (sec >= 60 && sec < 3600) {
int m = sec / 60;
int s = sec % 60;
sb.append(m + "分");
if (s > 0) {
sb.append(s + "秒");
}
} else {
int h = sec / 3600;
int m = (sec % 3600) / 60;
int s = (sec % 3600) % 60;
sb.append(h + "小时");
if (m > 0) {
sb.append(m + "分");
}
if (s > 0) {
sb.append(s + "秒");
}
}
return sb.toString();
}
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.constant.URL;
import com.ssi.constant.enums.TrafficLightEnum;
import com.ssi.entity.VmsTrafficLightInfo;
import com.ssi.mapper.VmsTrafficLightInfoMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.response.SSIPage;
import com.ssi.service.VmsTrafficLightInfoService;
import com.ssi.utils.RestTemplateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.util.Asserts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
/**
*
*/
@Service
@Slf4j
public class VmsTrafficLightInfoServiceImpl extends ServiceImpl<VmsTrafficLightInfoMapper, VmsTrafficLightInfo>
implements VmsTrafficLightInfoService{
@Autowired
private RedisDataModel redisDataModel;
private ReentrantLock lock = new ReentrantLock();
@Value("${map-edit-url}")
private String mapEditUrl;
@Override
public SSIPage queryPage(VmsTrafficLightInfo req) {
IPage<VmsTrafficLightInfo> page = new Page(req.getPageIndex(), req.getPageSize());
IPage<VmsTrafficLightInfo> quryResult = this.baseMapper.selectPage(page, new QueryWrapper<VmsTrafficLightInfo>()
.eq(Objects.nonNull(req.getStatus()), "status", req.getStatus())
.eq(StringUtils.isNotBlank(req.getCrossId()), "cross_id", req.getCrossId()));
//查询接入接口
List<VmsTrafficLightInfo> records = quryResult.getRecords();
for (VmsTrafficLightInfo info: records) {
/* Map<String, Object> map = redisDataModel.hgetJson2Map("ivccs:vms:traffic:light", info.getCrossId());
if(MapUtils.isEmpty(map)){
continue;
}
List<JSONObject> lists = (List<JSONObject>)map.get("list");*/
List<JSONObject> lists = new ArrayList<>();
fillLights("北向",lists);
fillLights("南向",lists);
fillLights("东向",lists);
fillLights("西向",lists);
info.setLights(lists);
}
return new SSIPage(quryResult);
}
private void fillLights(String faceDirect, List<JSONObject> lists) {
JSONObject jsonObject = new JSONObject();
List<TrafficLightEnum> enums = TrafficLightEnum.getEnumsByPhaseNoFlagName(faceDirect);
jsonObject.put("direction",faceDirect);
for (int i = 0; i < enums.size(); i++) {
jsonObject.put(enums.get(i).getDirectName(),enums.get(i).getPhaseNo());
}
lists.add(jsonObject);
}
@Override
public String manual(VmsTrafficLightInfo req) {
if(!lock.tryLock()){
return "操作频繁,请稍后";
}
try {
Asserts.notNull(req.getCrossId(), "CrossId");
String lamps = req.getLampNos();
lamps = getLamps(req, lamps);
VmsTrafficLightInfo one = this.lambdaQuery().eq(VmsTrafficLightInfo::getCrossId, req.getCrossId()).eq(VmsTrafficLightInfo::getIsLock, 1).one();
if (Objects.nonNull(one)) {
//解锁操作
boolean b = sendRequest(req.getCrossId(), 0, null);
if (!b) {
return "解锁失败";
}
try {
Thread.sleep(3000);//
} catch (Exception e) {
log.error("解锁等待出现异常:", e);
}
}
//人工控制
boolean b = sendRequest(req.getCrossId(), 1, lamps);
if (!b) {
return "控制失败";
}
Map<String, List> saveObj = new HashMap<>();
saveObj.put("list",StringUtils.isNotBlank(lamps)?Arrays.asList(lamps.split(",")):Collections.EMPTY_LIST);
redisDataModel.hset("ivccs:vms:traffic:light", req.getCrossId(),JSON.toJSONString(saveObj));
//锁 定
VmsTrafficLightInfo updateEntity = new VmsTrafficLightInfo();
updateEntity.setCrossId(req.getCrossId());
updateEntity.setIsLock((byte) 1);
this.saveOrUpdate(updateEntity);
return null;
}catch (Exception e){
return "控制失败";
}finally {
lock.unlock();
}
}
private String getLamps(VmsTrafficLightInfo req, final String lamps) {
String newLamps = lamps;
Map<String, Object> map = redisDataModel.hgetJson2Map("ivccs:vms:traffic:light", req.getCrossId());
if(!MapUtils.isEmpty(map)&&CollectionUtils.isNotEmpty((List<String>)map.get("list"))){
List<String> olamps = (List<String>)map.get("list");
if(req.getFlag()==2){
olamps.add(req.getLampNos());
}else {
olamps.removeIf(e->e.equalsIgnoreCase(lamps));
}
newLamps = StringUtils.join(olamps,",") ;
}else if(req.getFlag()==0){
newLamps = "";
}
return newLamps;
}
private boolean sendRequest(String crossId,Integer enable,String objData){
JSONObject object = new JSONObject();
object.put("controlType",4);
object.put("custom",1);
object.put("planId",1);
object.put("delay",0);
object.put("sys","UICP");
object.put("crossId",crossId);
object.put("enable",enable);
object.put("objData",objData);
log.info(String.format("控制交通灯保存请求发送:----%s", object.toJSONString()));
String result = RestTemplateUtil.post(String.format("%s%s","http://10.11.10.32:8090/", URL.TRAFFIC_LIGHT), object.toJSONString() , null);
log.info(String.format("控制交通灯保存请求结果:----%s", result));
JSONObject qryResult = JSON.parseObject(result);
if(qryResult.getString("code").equalsIgnoreCase("1")){
return false;
}
return true;
}
}
package com.ssi.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssi.entity.VmsVehicleAlertProcess;
import com.ssi.service.VmsVehicleAlertProcessService;
import com.ssi.mapper.VmsVehicleAlertProcessMapper;
import org.springframework.stereotype.Service;
/**
*
*/
@Service
public class VmsVehicleAlertProcessServiceImpl extends ServiceImpl<VmsVehicleAlertProcessMapper, VmsVehicleAlertProcess>
implements VmsVehicleAlertProcessService{
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSON;
import com.ssi.entity.VmsVehicleFreeTime;
import com.ssi.entity.dto.VmsVehicleFreeTimeDto;
import com.ssi.entity.dto.VmsVehicleVinFreeTimeDto;
import com.ssi.service.VmsVehicleFreeTimeService;
import com.ssi.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
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.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
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.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import reactor.util.function.Tuple2;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @description: 车辆空闲时间 service
* @author: dt
* @create: 2022-11-09 18:28
*/
@Service
@Slf4j
public class VmsVehicleFreeTimeServiceImpl implements VmsVehicleFreeTimeService {
/**
* es 每个批次查询的条数
*/
public static final int SEARCH_SIZE = 10000;
/**
* es 游标生效时间
*/
public final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(10L));
/**
* es 索引名
*/
@Value("${vehicle-trip.es-index-name:vms_vehicle_trip}")
private String tripIndexName;
/**
* es
*/
private RestHighLevelClient restHighLevelClient;
public VmsVehicleFreeTimeServiceImpl(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
}
/**
* 查询车辆空闲时间
* @param vmsVehicleVinFreeTimeDto
* @return
*/
@Override
public VmsVehicleVinFreeTimeDto getVehicleFreeTime(VmsVehicleVinFreeTimeDto vmsVehicleVinFreeTimeDto) {
if (CollectionUtils.isEmpty(vmsVehicleVinFreeTimeDto.getVmsVehicleFreeTimeDtos())) {
return null;
}
try{
SearchResponse response = this.getSearchResponse(vmsVehicleVinFreeTimeDto, SEARCH_SIZE, scroll, SortOrder.ASC);
String scrollId = response.getScrollId();
SearchHit[] searchHits = response.getHits().getHits();
while (searchHits != null && searchHits.length > 0) {
for (SearchHit hit : searchHits) {
String sourceAsString = hit.getSourceAsString();
if (StringUtils.isNotEmpty(sourceAsString)) {
VmsVehicleFreeTime vmsVehicleFreeTime = JSON.parseObject(sourceAsString, VmsVehicleFreeTime.class);
vmsVehicleVinFreeTimeDto.getVmsVehicleFreeTimeDtos().forEach(vmsVehicleFreeTimeDto -> {
calcFreeTime(vmsVehicleFreeTime, vmsVehicleFreeTimeDto);
});
}
}
if (searchHits.length == SEARCH_SIZE) {
response = this.getNextScrollResponse(scrollId, scroll);
searchHits = response.getHits().getHits();
} else {
break;
}
}
}catch (Exception e) {
log.error("查询统计车辆空闲时间出错", e);
}
return vmsVehicleVinFreeTimeDto;
}
/**
* 计算空闲时间
* @param vmsVehicleFreeTime
* @param vmsVehicleFreeTimeDto
*/
public void calcFreeTime(VmsVehicleFreeTime vmsVehicleFreeTime, VmsVehicleFreeTimeDto vmsVehicleFreeTimeDto) {
Long startTime = 0L;
Long endTime = 0L;
// 时间不在该范围内
if (vmsVehicleFreeTime.getStartTime() > vmsVehicleFreeTimeDto.getEndTime() || vmsVehicleFreeTime.getEndTime() < vmsVehicleFreeTimeDto.getStartTime()) {
return;
}
// 确定开始时间
if (vmsVehicleFreeTime.getStartTime() < vmsVehicleFreeTimeDto.getStartTime()) {
startTime = vmsVehicleFreeTimeDto.getStartTime();
}
if (vmsVehicleFreeTime.getStartTime() > vmsVehicleFreeTimeDto.getStartTime()) {
startTime = vmsVehicleFreeTime.getStartTime();
}
// 确定结束时间
if (vmsVehicleFreeTime.getEndTime() < vmsVehicleFreeTimeDto.getEndTime()) {
endTime = vmsVehicleFreeTime.getEndTime();
}
if (vmsVehicleFreeTime.getEndTime() > vmsVehicleFreeTimeDto.getEndTime()) {
endTime = vmsVehicleFreeTimeDto.getEndTime();
}
// 计算空闲时间
vmsVehicleFreeTimeDto.setFreeTime(Objects.nonNull(vmsVehicleFreeTimeDto.getFreeTime()) ? vmsVehicleFreeTimeDto.getFreeTime() + (endTime-startTime) : (endTime-startTime));
}
/**
*
* @param vmsVehicleVinFreeTimeDto
* @param size
* @param scroll
* @param sortOrder
* @return
* @throws IOException
*/
public SearchResponse getSearchResponse(VmsVehicleVinFreeTimeDto vmsVehicleVinFreeTimeDto, int size, Scroll scroll,
SortOrder sortOrder) throws IOException {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("vin", vmsVehicleVinFreeTimeDto.getVin());
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
boolBuilder.must(matchQueryBuilder);
vmsVehicleVinFreeTimeDto.getVmsVehicleFreeTimeDtos().forEach(vmsVehicleFreeTimeDto -> {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("startTime");
rangeQueryBuilder.gte(vmsVehicleFreeTimeDto.getStartTime());
rangeQueryBuilder.lte(vmsVehicleFreeTimeDto.getEndTime());
boolBuilder.should(rangeQueryBuilder);
});
log.info("查询 es 条件:\n"+ boolBuilder.toString());
FieldSortBuilder fieldSortBuilder = new FieldSortBuilder("startTime").order(sortOrder);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(size);
sourceBuilder.query(boolBuilder);
sourceBuilder.sort(fieldSortBuilder);
sourceBuilder.timeout(new TimeValue(600, TimeUnit.SECONDS));
Map<String, Long> timeMap = getMinStartTimeAndMaxEndTime(vmsVehicleVinFreeTimeDto);
String[] indexNames = getAllIndexNamesByYear(timeMap.get("startTime"), timeMap.get("endTime"));
log.info("查询的索引: "+ Arrays.toString(indexNames));
SearchRequest searchRequest = new SearchRequest(indexNames, sourceBuilder);
searchRequest.scroll(scroll);
return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
}
/**
* 判断获取时间最大值和最小值
* @param vmsVehicleVinFreeTimeDto
* @return
*/
private Map<String, Long> getMinStartTimeAndMaxEndTime(VmsVehicleVinFreeTimeDto vmsVehicleVinFreeTimeDto) {
Map<String, Long> map = new HashMap<String, Long>(2);
vmsVehicleVinFreeTimeDto.getVmsVehicleFreeTimeDtos().forEach(vmsVehicleFreeTimeDto -> {
Long startTime = map.getOrDefault("startTime", 0L);
Long endTime = map.getOrDefault("endTime", 0L);
if (startTime > vmsVehicleFreeTimeDto.getStartTime()) {
map.put("startTime", vmsVehicleFreeTimeDto.getStartTime());
}
if (endTime < vmsVehicleFreeTimeDto.getEndTime()) {
map.put("endTime", vmsVehicleFreeTimeDto.getStartTime());
}
});
return map;
}
/**
* 得到下一个游标的数据
* @param scrollId
* @param scroll
* @return
* @throws IOException
*/
public SearchResponse getNextScrollResponse(String scrollId, Scroll scroll) throws IOException {
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(scroll);
return restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
}
/**
* 清楚游标
* @param scrollId
* @throws IOException
*/
public void clearScroll(String scrollId) throws IOException {
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
}
/**
* type: 0:year,1:yearmonth
*
* @param startTime
* @param endTime
* @return
* @throws IOException
*/
private String[] getAllIndexNamesByYear(long startTime, long endTime) throws IOException {
GetIndexRequest request = new GetIndexRequest(tripIndexName + "*");
request.humanReadable(true);
GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
String[] indices = response.getIndices();
int startYear = Integer.parseInt(DateUtils.getYear(startTime));
int endYear = Integer.parseInt(DateUtils.getYear(endTime));
List<String> result = new ArrayList<>();
for (String indexName : indices) {
String suffix = StringUtils.substringAfter(indexName, tripIndexName + "_");
if (NumberUtils.isDigits(suffix)) {
int suffixYearMonth = Integer.parseInt(suffix);
if (suffixYearMonth >= startYear && suffixYearMonth <= endYear) {
result.add(indexName);
}
}
}
return result.toArray(new String[0]);
}
}
package com.ssi.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ssi.constant.VehicleConstant;
import com.ssi.entity.VmsAlertThreshold;
import com.ssi.entity.VmsAlertThresholdNew;
import com.ssi.entity.VmsTosOrders;
import com.ssi.entity.VmsVehicle;
import com.ssi.entity.vo.*;
import com.ssi.mapper.VmsVehicleMapper;
import com.ssi.model.RedisDataModel;
import com.ssi.model.TelecontrolModel;
import com.ssi.model.VehicleElasticSearchModel;
import com.ssi.model.VehicleLatestDataModel;
import com.ssi.response.SSIPage;
import com.ssi.response.SSIResponse;
import com.ssi.service.VmsAlertThresholdNewService;
import com.ssi.service.VmsAlertThresholdService;
import com.ssi.service.VmsTosOrdersService;
import com.ssi.service.VmsVehicleService;
import com.ssi.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.tools.Tool;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 车辆服务实现类
*/
@Service("vehicleService")
@Slf4j
public class VmsVehicleServiceImpl extends ServiceImpl<VmsVehicleMapper, VmsVehicle> implements VmsVehicleService {
@Value("${ivccs.vehicle.latestData.redis.prefix:ivccs:vms:vehicle:latest}")
private String latestRedisKeyPrefix;
@Value("${vehicle.status.redis.keyPrefixOn}")
private String statusRedisKeyPrefix;
@Value("${vehicle.list.redis.keyPrefix:harbor:vehicle:list}")
private String vehicleListKeyPrefix;
@Value("${vehicle.latestData.redis.postfix:harbor_D00A}")
private String realPostfix;
@Value("${order.latestOrderKeyPrefix:harbor:command:status}")
private String latestOrderKeyPrefix;
@Value("${harbor.remote.emergencyParking}")
private String emergencyParkingKeyPrefix;
@Value("${harbor.vehicle.confirm_status_prefix}")
private String harborVehicleConfirmStatusPrefix;
@Value("${harbor.vehicle.onstatusKey:harbor:vehicle:onstatus}")
private String onstatusKey;
@Autowired
private RedisDataModel redisDataModel;
@Autowired
private VmsTosOrdersService vmsTosOrdersService;
@Autowired
private VmsAlertThresholdService vmsAlertThresholdService;
@Autowired
private VmsAlertThresholdNewService vmsAlertThresholdNewService;
@Autowired
private VehicleLatestDataModel vehicleLatestDataModel;
@Autowired
private VehicleDataUtil vehicleDataUtil;
@Autowired
private TelecontrolModel telecontrolModel;
@Autowired
private VehicleElasticSearchModel vehicleElasticSearchModel;
private final String CACHE_NAME = "vehicle:vehicleInfo";
@Override
public SSIPage queryPage(Map<String, Object> params) {
String vehicleNum = (String) params.get("vehicleNum");
Integer vehicleStatus = (Integer) params.get("vehicleStatus");
Integer vehicleType = (Integer) params.get("vehicleType");
IPage<VmsVehicle> page = this.page(new QueryUtils<VmsVehicle>().getPage(params),
new LambdaQueryWrapper<VmsVehicle>()
.like(StringUtils.isNotBlank(vehicleNum), VmsVehicle::getVehicleNum, vehicleNum)
.eq(vehicleStatus != null, VmsVehicle::getStatus, vehicleStatus)
.eq(vehicleType != null, VmsVehicle::getVehicleType, vehicleType)
.orderByAsc(VmsVehicle::getVehicleNum));
List<VmsVehicle> records = page.getRecords();
List<VehicleOrderVo> vehicleOrderVos = new ArrayList<>();
if(CollectionUtils.isNotEmpty(records)){
records.stream().forEach(vehicle ->{
VehicleOrderVo vehicleOrderVo = new VehicleOrderVo();
BeanUtils.copyProperties(vehicle,vehicleOrderVo);
Map<String, Object> map = handleVehicleData(vehicle.getVin());
vehicleOrderVo.setSoc(Objects.isNull(map.get("soc"))?Integer.valueOf(-1):(Integer) map.get("soc"));
vehicleOrderVo.setOnlineStatus((Integer)map.get("state"));
vehicleOrderVos.add(vehicleOrderVo);
});
}
return new SSIPage(vehicleOrderVos,(int)page.getTotal(),(int)page.getSize(),(int)page.getCurrent());
}
@Override
public List<VmsVehicle> getNormalVehicle() {
// 先从缓存中取
String vehicleString = redisDataModel.get(String.format("%s", vehicleListKeyPrefix));
if (StringUtils.isNotBlank(vehicleString)) {
return this.toListOfObject(vehicleString, VmsVehicle.class);
}
LambdaQueryWrapper<VmsVehicle> wrapper = new LambdaQueryWrapper<VmsVehicle>().eq(VmsVehicle::getStatus, 0)
.in(VmsVehicle::getVehicleType, 1, 2);
List<VmsVehicle> vehicleList = this.list(wrapper);
if (CollectionUtils.isNotEmpty(vehicleList)) {
redisDataModel.set(String.format("%s", vehicleListKeyPrefix), JSON.toJSONString(vehicleList),
(long) VehicleConstant.DEFAULT_EXPIRATION_TIME);
}
return vehicleList;
}
public static <T> List<T> toListOfObject(String json, Class<T> clazz) {
ObjectMapper om = new ObjectMapper();
// 反序列化时,忽略Javabean中不存在的属性,而不是抛出异常
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 忽略入参没有任何属性导致的序列化报错
om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
try {
Class<T[]> arrayClass = (Class<T[]>) Class.forName("[L" + clazz.getName() + ";");
return Lists.newArrayList(om.readValue(json, arrayClass));
} catch (IOException | ClassNotFoundException e) {
log.error("json={}, clazz={}", json, clazz, e);
}
return null;
}
@Override
public List<VmsVehicle> getNormalVehicleByVehicleNum(String vehicleNum, Integer vehicleType) {
LambdaQueryWrapper<VmsVehicle> wrapper = new LambdaQueryWrapper<VmsVehicle>().eq(VmsVehicle::getStatus, 0)
.in(VmsVehicle::getVehicleType, 1, 2);
if (StringUtils.isNotBlank(vehicleNum)) {
wrapper.like(VmsVehicle::getVehicleNum, vehicleNum);
}
List<VmsVehicle> vehicleList = this.list(wrapper);
return vehicleList;
}
@Cached(name = CACHE_NAME, expire = 120, timeUnit = TimeUnit.MINUTES)
@CacheRefresh(refresh = 1, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.MINUTES)
@Override
public List<VmsVehicle> listAndCache() {
return this.list(new LambdaQueryWrapper<VmsVehicle>().eq(VmsVehicle::getStatus, 0));
}
/**
* 车辆监控列表接口
*/
@Override
public SSIResponse listForMonitor(List<VmsVehicle> vehicleList) {
VmsAlertThreshold info = new VmsAlertThreshold();
info.setParamKey("wait_overtime_energy_key");
VmsAlertThreshold current = vmsAlertThresholdService.getOne(new LambdaQueryWrapper<>(info));
// VehicleVo vehicleVo = new VehicleVo();
List<VehicleVo.vehicleTemp> vehicleTempList = Lists.newArrayList();
vehicleList.stream().forEach(vehicle -> {
Map<String, Object> realMap = handleVehicleData(vehicle, current);
VehicleVo.vehicleTemp vehicleTemp = vehicleDataUtil.toVehicleTemp(realMap);
vehicleTempList.add(vehicleTemp);
});
Collections.sort(vehicleTempList, new Comparator<VehicleVo.vehicleTemp>() {
@Override
public int compare(VehicleVo.vehicleTemp x, VehicleVo.vehicleTemp y) {
if (x.getOnlineStatus() < y.getOnlineStatus()) {
return 1;
} else if (x.getOnlineStatus() == y.getOnlineStatus()) {
if (x.getWorkStatus() < y.getWorkStatus()) {
return 1;
} else if (x.getWorkStatus() == y.getWorkStatus()) {
return x.getVehicleNum().compareTo(y.getVehicleNum());
} else {
return -1;
}
} else {
return -1;
}
}
});
// vehicleVo.setVehicleList(vehicleTempList);
return SSIResponse.ok(vehicleTempList);
}
@Override
public SSIResponse vehicleStatusForMonitor(List<VmsVehicle> vehicleList) {
VehicleStatusVo vehicleStatusVo = vehicleStatusDist(vehicleList);
return SSIResponse.ok(vehicleStatusVo);
}
@Override
public VehicleStatusVo vehicleStatusDist(List<VmsVehicle> vehicleList) {
VehicleStatusVo vehicleStatusVo = new VehicleStatusVo();
AtomicInteger parkNum = new AtomicInteger(0);
AtomicInteger loadingGoodsNum = new AtomicInteger(0);
AtomicInteger unloadingGoodsNum = new AtomicInteger(0);
AtomicInteger arrangeGoodsNum = new AtomicInteger(0);
AtomicInteger chargeNum = new AtomicInteger(0);
AtomicInteger temporaryParkNum = new AtomicInteger(0);
AtomicInteger offlineNum = new AtomicInteger(0);
vehicleList.parallelStream().forEach(vehicle -> {
Map<String, Object> realMap = redisDataModel
.getJson2Map(String.format("%s:%s-%s", latestRedisKeyPrefix, vehicle.getVin(), realPostfix));
// 不在线
if (realMap == null) {
offlineNum.incrementAndGet();
return;
}
//String onlineStatus = redisDataModel.get(String.format("%s:%s", statusRedisKeyPrefix, vehicle.getVin()));
//离线状态
String onlineStatus = redisDataModel.get(String.format("%s:%s", onstatusKey, vehicle.getVin()));
if (onlineStatus == null && StringUtils.isBlank(onlineStatus)|| !onlineStatus.equals("1")) {
realMap.put("state", 0);
offlineNum.incrementAndGet();
return;
} else {
realMap.put("state", Integer.parseInt(onlineStatus));
}
// int online = vehicleDataUtil.checkOnline(realMap.get("state") == null ? 0 : (Integer) realMap.get("state"),
// (Long) realMap.get("collectTime"));
// if (online == 0) {
// offlineNum.incrementAndGet();
// return;
// }
// 在线
VmsTosOrders vmsTosOrders = getLatestOrderByVin(vehicle.getVin());
if (vmsTosOrders != null && !VehicleUtil.isTaskOver(vmsTosOrders.getStatus())) {
if (vmsTosOrders.getVehicleTaskLabel() == null) {
log.error(String.format("车辆:%s:%s最新任务 车辆任务标签 为null, 任务信息如下:\n %s", vehicle.getVehicleNum(),
vehicle.getVin(), vmsTosOrders));
return;
}
switch (vmsTosOrders.getVehicleTaskLabel()) {
case 1:
loadingGoodsNum.incrementAndGet();
break;
case 2:
unloadingGoodsNum.incrementAndGet();
break;
case 3:
arrangeGoodsNum.incrementAndGet();
break;
case 4:
parkNum.incrementAndGet();
break;
case 5:
chargeNum.incrementAndGet();
break;
case 6:
temporaryParkNum.incrementAndGet();
break;
}
} else {
parkNum.incrementAndGet();
}
});
vehicleStatusVo.setVehicleNum(vehicleList.size());
vehicleStatusVo.setLoadingGoodsNum(loadingGoodsNum.get());
vehicleStatusVo.setUnloadingGoodsNum(unloadingGoodsNum.get());
vehicleStatusVo.setArrangeGoodsNum(arrangeGoodsNum.get());
vehicleStatusVo.setOfflineNum(offlineNum.get());
vehicleStatusVo.setParkNum(parkNum.get());
vehicleStatusVo.setChargeNum(chargeNum.get());
vehicleStatusVo.setTemporaryParkNum(temporaryParkNum.get());
vehicleStatusVo.setOtherOrdersNum(vehicleStatusVo.getOfflineNum() + vehicleStatusVo.getParkNum()
+ vehicleStatusVo.getChargeNum() + vehicleStatusVo.getTemporaryParkNum());
DecimalFormat df = new DecimalFormat("######0.00");
vehicleStatusVo.setLoadingGoodsPer(
df.format(vehicleStatusVo.getLoadingGoodsNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setUnloadingGoodsPer(
df.format(vehicleStatusVo.getUnloadingGoodsNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setArrangeGoodsPer(
df.format(vehicleStatusVo.getArrangeGoodsNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setOfflinePer(
df.format(vehicleStatusVo.getOfflineNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setParkPer(
df.format(vehicleStatusVo.getParkNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setChargePer(
df.format(vehicleStatusVo.getChargeNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setTemporaryParkPer(
df.format(vehicleStatusVo.getTemporaryParkNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
vehicleStatusVo.setOtherOrdersPer(
df.format(vehicleStatusVo.getOtherOrdersNum() * 1.0 / vehicleStatusVo.getVehicleNum() * 100) + "%");
return vehicleStatusVo;
}
@Override
public SSIResponse saveVehicle(VmsVehicle vehicle) {
Map<String, Object> repeatMap = checkRepeat(vehicle);
if ((Boolean) repeatMap.get("repeat")) {
return SSIResponse.no((String) repeatMap.get("repeatInfo"));
}
this.saveOrUpdate(vehicle);
return SSIResponse.ok();
}
private Map<String, Object> checkRepeat(VmsVehicle vehicle) {
Map<String, Object> repeatMap = Maps.newHashMap();
repeatMap.put("repeat", true);
List<VmsVehicle> list = new ArrayList<VmsVehicle>();
if (null != vehicle.getId()) {
LambdaQueryWrapper<VmsVehicle> wrapper = new LambdaQueryWrapper<VmsVehicle>().ne(VmsVehicle::getId,vehicle.getId());
list = this.list(wrapper);
} else {
list = this.list();
}
Map<String, VmsVehicle> vNumMap = Maps.newHashMap();
Map<String, VmsVehicle> vTnumMap = Maps.newHashMap();
Map<String, VmsVehicle> chassisMap = Maps.newHashMap();
Map<String, VmsVehicle> platNumMap = Maps.newHashMap();
Map<String, VmsVehicle> vinMap = Maps.newHashMap();
list.parallelStream().forEach(vehicle1 -> {
vNumMap.put(vehicle1.getVehicleNum(), vehicle1);
vTnumMap.put(vehicle1.getTerminalNum(), vehicle1);
chassisMap.put(vehicle1.getChassisNum(), vehicle1);
platNumMap.put(vehicle1.getPlateNo(), vehicle1);
vinMap.put(vehicle1.getVin(), vehicle1);
});
VmsVehicle repeatVnum = vNumMap.get(vehicle.getVehicleNum());
VmsVehicle repeatVtnum = vTnumMap.get(vehicle.getTerminalNum());
VmsVehicle repeatChassis = chassisMap.get(vehicle.getChassisNum());
VmsVehicle repeatPlatNum = platNumMap.get(vehicle.getPlateNo());
VmsVehicle repeatVinNum = platNumMap.get(vehicle.getVin());
if (repeatVnum != null) {
if (vehicle.getVehicleNum() == null
|| (vehicle.getVehicleNum() != null && vehicle.getVehicleNum() != repeatVnum.getVehicleNum())) {
repeatMap.put("repeatInfo", "车辆编号不能重复");
return repeatMap;
}
}
if (repeatVtnum != null) {
if (vehicle.getTerminalNum() == null
|| (vehicle.getTerminalNum() != null && vehicle.getTerminalNum() != repeatVtnum.getTerminalNum())) {
repeatMap.put("repeatInfo", "一个终端只能绑定一个车辆");
return repeatMap;
}
}
if (repeatChassis != null) {
if (vehicle.getChassisNum() == null
|| (vehicle.getChassisNum() != null && vehicle.getChassisNum() != repeatChassis.getChassisNum())) {
repeatMap.put("repeatInfo", "底盘号不能重复");
return repeatMap;
}
}
if (repeatPlatNum != null) {
if (vehicle.getPlateNo() == null
|| (vehicle.getPlateNo() != null && vehicle.getPlateNo() != repeatPlatNum.getPlateNo())) {
repeatMap.put("repeatInfo", "车牌号不能重复");
return repeatMap;
}
}
if (repeatVinNum != null) {
if (vehicle.getVin() == null || (vehicle.getVin() != null && vehicle.getVin() != repeatVinNum.getVin())) {
repeatMap.put("repeatInfo", "VIN不能重复");
return repeatMap;
}
}
repeatMap.put("repeat", false);
return repeatMap;
}
private Map<String, Object> handleVehicleData(String vin){
if(StringUtils.isBlank(vin)){
return Collections.emptyMap();
}
Map<String, Object> realMap = redisDataModel
.getJson2Map(String.format("%s:%s-%s", latestRedisKeyPrefix, vin, realPostfix));
if (realMap == null) {
realMap = vehicleElasticSearchModel.searchLatestVehicleData(vin);
}
if (realMap == null) {
realMap = Maps.newHashMap();
}
String onlineStatus = redisDataModel.get(String.format("%s:%s", "harbor:vehicle:online",vin));
if (onlineStatus==null && StringUtils.isBlank(onlineStatus) || !onlineStatus.equals("1")) {
realMap.put("state", 0);
} else {
realMap.put("state", Integer.parseInt(onlineStatus));
}
return realMap;
}
private Map<String, Object> handleVehicleData(VmsVehicle vehicle, VmsAlertThreshold current) {
Map<String, Object> realMap = redisDataModel
.getJson2Map(String.format("%s:%s-%s", latestRedisKeyPrefix, vehicle.getVin(), realPostfix));
if (realMap == null) {
realMap = vehicleElasticSearchModel.searchLatestVehicleData(vehicle.getVin());
}
if (realMap == null) {
realMap = Maps.newHashMap();
}
VmsTosOrdersVo latestOrders = getLatestOrderByVin(vehicle.getVin());
realMap.put("vehicleNum", vehicle.getVehicleNum());
realMap.put("vehicleType",vehicle.getVehicleType());
realMap.put("vin", vehicle.getVin());
// 查询在线状态
//String onlineStatus = redisDataModel.get(String.format("%s:%s", statusRedisKeyPrefix, vehicle.getVin()));
String onlineStatus = redisDataModel.get(String.format("%s:%s", "harbor:vehicle:onstatus", vehicle.getVin()));
if (onlineStatus==null && StringUtils.isBlank(onlineStatus) || !onlineStatus.equals("1")) {
realMap.put("state", 0);
} else {
realMap.put("state", Integer.parseInt(onlineStatus));
}
if (latestOrders == null || latestOrders.getStatus() == 35 || latestOrders.getStatus() == 36
|| latestOrders.getStatus() == 37 || latestOrders.getStatus() == 41) {
realMap.put("workStatus", 0);
} else {
realMap.put("orderData", latestOrders);
realMap.put("workStatus", 1);
// 是否超时
if (latestOrders.getStartTime() == null) {
realMap.put("waitOvertimeStatus", 0);
} else {
Long startTime = latestOrders.getStartTime().getTime();
long time;
time = startTime + Integer.parseInt(current.getParamValue()) * 60 * 1000;
if (time < System.currentTimeMillis()) {
realMap.put("waitOvertimeStatus", 1);
} else {
realMap.put("waitOvertimeStatus", 0);
}
}
}
VmsAlertThreshold info = new VmsAlertThreshold();
info.setParamKey("low_energy_key");
VmsAlertThreshold vmsAlertThreshold = vmsAlertThresholdService.getOne(new LambdaQueryWrapper<>(info));
realMap.put("lowEnergy", Integer.parseInt(vmsAlertThreshold.getParamValue()));
// 添加紧急停车状态
Map<String, Object> emergencyStatusMap = redisDataModel
.getJson2Map(String.format("%s:%s", emergencyParkingKeyPrefix, vehicle.getVin()));
if (emergencyStatusMap != null) {
Object emergencyStatus = emergencyStatusMap.get("emergencyStatus");
realMap.put("emergencyType", emergencyStatus);
} else {
realMap.put("emergencyType", 2);
}
// 三重确认状态添加
Map<String, Object> threeConfirmStatus = redisDataModel
.getJson2Map(String.format("%s:%s", harborVehicleConfirmStatusPrefix, vehicle.getVin()));
realMap.put("threeConfirmStatus", threeConfirmStatus);
return realMap;
}
private VmsTosOrdersVo getLatestOrderByVin(String vin) {
// List<VmsTosOrders> list = vmsTosOrdersService.list(new LambdaQueryWrapper<VmsTosOrders>()
// .eq(VmsTosOrders::getVin, vin)
// .orderByDesc(VmsTosOrders::getReceiveTime));
// VmsTosOrders latestOrders = list == null || list.isEmpty() ? null:list.get(0);
// return latestOrders;
Map<String, Object> json2Map = redisDataModel.getJson2Map(String.format("%s:%s", latestOrderKeyPrefix, vin));
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(json2Map));
VmsTosOrdersVo vmsTosOrders = JSONObject.toJavaObject(jsonObject, VmsTosOrdersVo.class);
return vmsTosOrders;
}
/**
* 运力分析
*/
@Override
public SSIResponse transportCapacity() {
List<VmsVehicle> vehicleList = this.getNormalVehicle();
VmsAlertThreshold current = vmsAlertThresholdService.getOne(new LambdaQueryWrapper<>());
Double socSum = 0.0;
Integer vehicleSum = 0;
TransportCapacityAnalysisVo capacityAnalysisVo = new TransportCapacityAnalysisVo();
for (VmsVehicle vehicle : vehicleList) {
Map<String, Object> realMap = handleVehicleData(vehicle, current);
int online = vehicleDataUtil.checkOnline(realMap.get("state") == null ? 0 : (Integer) realMap.get("state"),
(Long) realMap.get("collectTime"));
if (online == 1) {
vehicleSum++;
Integer workStatus = (Integer) realMap.get("workStatus");
Integer faultStatus = realMap.get("equipStatus") == null ? 1
: (Integer) realMap.get("equipStatus") == 1 ? 1 : 0;
Integer chargingStatus = (Integer) realMap.get("chargingStatus");
chargingStatus = chargingStatus == null ? 0 : chargingStatus;
Integer soc = (Integer) realMap.get("soc");
if (soc == null) {
soc = 0;
}
// 车辆任务超时也算入运力里
Object waitOvertimeStatus = realMap.get("waitOvertimeStatus");
if (waitOvertimeStatus == null) {
waitOvertimeStatus = 0;
}
// chargingStatus 3:未充电,4:充电完成
// if ((workStatus != 1 || (int)waitOvertimeStatus == 1) && faultStatus != 1 && (chargingStatus == 3 || chargingStatus == 4)) {
capacityAnalysisVo.rangeMatch(soc);
socSum = socSum + soc;
// }
}
}
Double transportCapacity = vehicleSum != 0 ? socSum / vehicleSum : 0;
BigDecimal bg = new BigDecimal(transportCapacity).setScale(1, BigDecimal.ROUND_HALF_UP);
capacityAnalysisVo.setTransportCapacity(bg);
return SSIResponse.ok(capacityAnalysisVo);
}
/**
* 获取当前定位周边车辆
*/
@Override
public List<VehicleControlStatusVo> getVehicleByLocation(String location, final Integer distance) {
log.info(String.format("%s:%s,%s:%s", "根据经纬度获取车辆接口调用:经纬度", location, "遥控距离", distance));
List<VehicleControlStatusVo> resultList = Lists.newArrayList();
String[] split = location.split(",");
double[] curLoc = new double[] { Double.parseDouble(split[0]), Double.parseDouble(split[1]) };
List<VmsVehicle> list = this.list(new LambdaQueryWrapper<VmsVehicle>().orderByAsc(VmsVehicle::getVehicleNum));
list.stream().forEach(vehicle -> {
Map<String, Object> realMap = redisDataModel
.getJson2Map(String.format("%s:%s-%s", latestRedisKeyPrefix, vehicle.getVin(), realPostfix));
// 查询在线状态
if (realMap != null && !realMap.isEmpty() && realMap.get("longitude") != null
&& realMap.get("latitude") != null) {
String onlineStatus = redisDataModel
.get(String.format("%s:%s", statusRedisKeyPrefix, vehicle.getVin()));
if (StringUtils.isBlank(onlineStatus)) {
realMap.put("state", 0);
} else {
realMap.put("state", Integer.parseInt(onlineStatus));
}
int online = vehicleDataUtil.checkOnline(
realMap.get("state") == null ? 0 : (Integer) realMap.get("state"),
(Long) realMap.get("collectTime"));
if (online == 1) {
Double longitude = ConfigUtils.getAsDoubleWithDefault(realMap, "longitude", 0.0);
Double latitude = ConfigUtils.getAsDoubleWithDefault(realMap, "latitude", 0.0);
double vehicleDistance = GpsUtil.getDistance(curLoc[0], curLoc[1], latitude, longitude);
if (vehicleDistance * 1000 < distance) {
// 接管状态
Map controlStatus = telecontrolModel.getControlStatus(vehicle.getVin());
VehicleControlStatusVo vehicleControlStatusVo = new VehicleControlStatusVo();
BeanUtils.copyProperties(vehicle, vehicleControlStatusVo);
if (controlStatus != null) {
vehicleControlStatusVo.setAppControl((Integer) controlStatus.get("appControl"));
vehicleControlStatusVo.setAppActive((Integer) controlStatus.get("appActive"));
vehicleControlStatusVo.setAppMac((String) controlStatus.get("appMac"));
}
// 紧停状态
Map emergencyStatusMap = telecontrolModel.getEmergencyStatus(vehicle.getVin());
Integer emergencyStatus = 2;
if (emergencyStatusMap != null) {
emergencyStatus = (Integer) emergencyStatusMap.get("emergencyStatus");
}
vehicleControlStatusVo.setEmergencyStatus(emergencyStatus);
// 切换自动驾驶状态
Map autoPilotMap = telecontrolModel.getAutoPilotStatus(vehicle.getVin());
Integer autoPilotStatus = 4;
if (autoPilotMap != null) {
autoPilotStatus = (Integer) autoPilotMap.get("autopilot");
}
vehicleControlStatusVo.setAutopilot(autoPilotStatus);
int soc = ConfigUtils.getAsIntegerWithDefault(realMap, "soc", 0);
vehicleControlStatusVo.setSoc(soc);
resultList.add(vehicleControlStatusVo);
}
}
}
});
return resultList;
}
@Override
public Map getVmsCranePosMapInfo(String name) {
Map map = this.baseMapper.getVmsCranePosMapInfo(name);
return map;
}
@Override
public List<Map> getVmsVehicle() {
// TODO Auto-generated method stub
List<Map>result=this.baseMapper.getVmsVehicle();
return result;
}
}
package com.ssi.service.impl;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ssi.model.RedisConfigModel;
import com.ssi.service.WebSocketDataBackService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/10/16 17:51
*/
@Service
@Slf4j
public class WebSocketDataBackServiceImpl implements WebSocketDataBackService {
private static final Object LOCK = new Object();
@Value("${meilan.history.esIndex:vms_history_data}")
private String indexBase;
@Value("${meilan.history.config.group:playBack}")
private String redisConfigGroup;
@Value("${meilan.history.playBack.normal:false}")
private boolean playBackNormal;
@Value("${meilan.history.playBack.delay:1000}")
private long delay;
@Value("${meilan.history.playBack.open.randomDelay:true}")
private boolean randomDelay;
@Value("${meilan.history.playBack.open.randomDelayScale:0.05}")
private double randomDelayScale;
@Value("${meilan.history.playBack.open.randomDelayScenesId:6,8,9}")
private String randomDelayScenesId;
@Value("${LinuxFile.playBackFolder}")
private String playBackFolder;
@Autowired
private RedisConfigModel redisConfigModel;
@Autowired
protected TransportClient transportClient;
@Autowired
private ExecutorService executorService;
private Map<String, WebSocketDataEsBackor> backorMap = Maps.newConcurrentMap();
@Override
public int playBack(String sessionId,
String backorId,
String scenesId,
Set<String> vins,
Long startTime,
Long stopTime) {
synchronized (LOCK) {
int status;
if (!backorMap.containsKey(backorId)) {
if(!backorId.contains("v2x")) {
WebSocketDataEsBackor webSocketDataEsBackor = initPlayBackor(backorId, scenesId, vins, sessionId);
webSocketDataEsBackor.setRandomDelay(randomDelay);
webSocketDataEsBackor.setRandomDelayScale(randomDelayScale);
webSocketDataEsBackor.setRandomDelayScenesId(randomDelayScenesId);
backorMap.put(backorId, webSocketDataEsBackor);
final BackCondition backConditionBean = getBackCondition(scenesId, startTime, stopTime);
if (backConditionBean != null) {
log.info(String.format("启动回放任务: (%s, %s, %s)", sessionId, backorId, vins));
executorService.execute(() -> {
webSocketDataEsBackor.playBack(backConditionBean.startTime,
backConditionBean.stopTime, backConditionBean.delay, playBackNormal);
});
status = 0;
} else {
status = 1;
backorMap.remove(backorId);
log.warn(String.format("无回放数据时间段: (%s, %s, %s)", sessionId, backorId, vins));
}
}else{
WebSocketDataFileBackor webSocketDataFileBackor = initPlayFileBackor(backorId, scenesId, vins, sessionId);
webSocketDataFileBackor.setRandomDelay(randomDelay);
webSocketDataFileBackor.setRandomDelayScale(randomDelayScale);
webSocketDataFileBackor.setRandomDelayScenesId(randomDelayScenesId);
backorMap.put(backorId, webSocketDataFileBackor);
final BackCondition backConditionBean = getBackCondition(scenesId, startTime, stopTime);
webSocketDataFileBackor.setPath(backConditionBean.getPath());
if(StringUtils.isNotBlank(backConditionBean.getVins())){
vins.addAll(Arrays.asList(backConditionBean.getVins().split(",")));
}
if (backConditionBean != null) {
log.info(String.format("启动回放任务: (%s, %s, %s)", sessionId, backorId, vins));
executorService.execute(() -> {
webSocketDataFileBackor.playBack(backConditionBean.startTime,
backConditionBean.stopTime, backConditionBean.delay, playBackNormal);
});
status = 0;
} else {
status = 1;
backorMap.remove(backorId);
log.warn(String.format("无回放数据时间段: (%s, %s, %s)", sessionId, backorId, vins));
}
}
} else {
status = 2;
log.info(String.format("已存在回放任务: (%s, %s, %s),无需重复启动。", sessionId, backorId, vins));
backorMap.get(backorId).sessions.add(sessionId);
}
return status;
}
}
@Override
public void close(String sessionId,
String backorId) {
synchronized (LOCK) {
WebSocketDataEsBackor webSocketDataEsBackor = backorMap.get(backorId);
if (webSocketDataEsBackor != null) {
if (sessionId.equals(webSocketDataEsBackor.mainSession)) {
webSocketDataEsBackor.shutDown();
backorMap.remove(backorId);
} else {
webSocketDataEsBackor.sessions.remove(sessionId);
}
}
}
}
private BackCondition getBackCondition(String scenesId,
Long startTime,
Long stopTime){
BackCondition backCondition = getRedisBackCondition(scenesId);
if (backCondition == null && startTime != null && stopTime != null) {
backCondition = new BackCondition(scenesId, startTime, stopTime, this.delay);
}
return backCondition;
}
private WebSocketDataEsBackor initPlayBackor(String backorId, String scenesId, Set<String> vins, String sessionId) {
Set<String> sessions = Sets.newConcurrentHashSet();
sessions.add(sessionId);
return new WebSocketDataEsBackor(backorId, scenesId, this,
vins, sessionId, sessions, transportClient, indexBase,playBackFolder);
}
private WebSocketDataFileBackor initPlayFileBackor(String backorId, String scenesId, Set<String> vins, String sessionId) {
Set<String> sessions = Sets.newConcurrentHashSet();
sessions.add(sessionId);
return new WebSocketDataFileBackor(backorId, scenesId, this,
vins, sessionId, sessions);
}
private BackCondition getRedisBackCondition(String scenesId){
BackCondition backCondition = null;
String config = redisConfigModel.getConfig(redisConfigGroup, scenesId);
if(config != null){
String[] backConditions = config.split("#");
int length = backConditions.length;
if(length == 2 || length == 3 || length == 5){
try {
long startTime = Long.parseLong(backConditions[0]);
long stopTime = Long.parseLong(backConditions[1]);
Long delay = this.delay;
if(length == 3){
delay = Long.parseLong(backConditions[2]);
}
backCondition = new BackCondition(scenesId, startTime, stopTime, delay);
if(length == 5 ){
backCondition.setPath(backConditions[3]);
backCondition.setVins(backConditions[4]);
}
log.info(String.format("redis配置中场景%s的回放时间配置:%s", scenesId, backCondition));
} catch (NumberFormatException e) {
log.error(String.format("回放条件解析失败:%s", config));
}
}else{
log.error(String.format("redis配置中场景%s的回放时间配置错误:%s", scenesId, config));
}
}else{
log.warn(String.format("redis配置中无此场景id的回放时间配置:%s", scenesId));
}
return backCondition;
}
private class BackCondition{
private String scenesId;
private long startTime;
private long stopTime;
private long delay;
private String path;
private String vins;
public BackCondition( String scenesId, long startTime, long stopTime, long delay){
this.scenesId = scenesId;
this.startTime = startTime;
this.stopTime = stopTime;
this.delay = delay;
}
@Override
public String toString() {
return String.format("(%s, %s, %s, %s)", scenesId, startTime, stopTime, delay);
}
public String getScenesId() {
return scenesId;
}
public void setScenesId(String scenesId) {
this.scenesId = scenesId;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getStopTime() {
return stopTime;
}
public void setStopTime(long stopTime) {
this.stopTime = stopTime;
}
public long getDelay() {
return delay;
}
public void setDelay(long delay) {
this.delay = delay;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getVins() {
return vins;
}
public void setVins(String vins) {
this.vins = vins;
}
}
}
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.utils.ElasticSearchUtil;
import com.ssi.websocket.WebBackSocketService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.joda.time.DateTime;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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 WebSocketDataEsBackor {
Set<String> sessions;
String mainSession;
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 playBackFolder;
public WebSocketDataEsBackor(String backorId,
String scenesId,
WebSocketDataBackServiceImpl webSocketDataBackService,
Set<String> vins,
String mainSession,
Set<String> sessions,
TransportClient transportClient,
String indexBase,
String playBackFolder){
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<>();
this.playBackFolder = playBackFolder;
}
public WebSocketDataEsBackor() {
}
public void playBack(Long startTime, Long stopTime, long delay, boolean normal){
try {
//初始化结果容器
Map<String, List<Map<String, Object>>> records = Maps.newHashMap();
for(String vin : vins){
records.put(vin, Lists.newLinkedList());
}
Map<String, List<Map<String, Object>>> res = getRecordsFromFile(startTime,stopTime);
if(res == null){
getRecords(startTime, stopTime, records);
if(!records.isEmpty()){
//这个地方把数据保存到文件
String filePath = playBackFolder + "/" + startTime + "-" + stopTime + ".json";
JSON.writeJSONString(new FileOutputStream(filePath),records);
}
}else{
records = res;
}
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);
}
}
Map<String, List<Map<String, Object>>> getRecordsFromFile(Long startTime,Long stopTime) throws Exception{
String filePath = playBackFolder + "/" + startTime + "-" + stopTime + ".json";
boolean exists = new File(filePath).exists();
if(!exists){
return null;
}
Map<String, List<Map<String, Object>>> records = JSON.parseObject(new FileInputStream(filePath), Map.class);
return records;
}
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));
List<String> recordList = Lists.newArrayList();
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);
recordList.add(recordJson);
}else {
return;
}
}
WebBackSocketService.messageBroadcast(backorId, Sets.newHashSet(sessions), recordList);
//计算休眠时间
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){
SearchRequestBuilder searchRequestBuilder = getSearchRequestBuilder(startTime, stopTime);
if(searchRequestBuilder == null){
resultContain.clear();
return;
}
log.info(String.format("开始查询车辆%s的数据, 查询索引为:%s.",
vins, Arrays.asList(searchRequestBuilder.request().indices())));
searchRequestBuilder.setFetchSource(new String[]{"timestamp", "value"}, null);
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.termQuery("key", "all"));
RangeQueryBuilder rangeQueryBuilder = ElasticSearchUtil.createRangeQueryBuilder("timestamp", startTime, stopTime);
queryBuilder.must(rangeQueryBuilder);
SearchResponse searchResponse = searchRequestBuilder.setQuery(queryBuilder)
.setScroll(TimeValue.timeValueMinutes(5))
.addSort("timestamp", SortOrder.ASC)
.setSize(1000)
.get();
SearchHits hits = searchResponse.getHits();
SearchHit[] hitsHits = hits.getHits();
Object line;
Map<String, Object> record;
Map<String, Object> sourceAsMap;
while (hitsHits.length > 0) {
for (int i = 0; i < hitsHits.length; i++) {
sourceAsMap = hitsHits[i].getSourceAsMap();
line = sourceAsMap.get("value");
if(line != null){
record = jsonToMap(line.toString());
if(record != null){
checkAndPushResultContain(record, sourceAsMap.get("timestamp"), resultContain);
}
}
}
searchResponse = transportClient.prepareSearchScroll(searchResponse.getScrollId())
.setScroll(TimeValue.timeValueMinutes(5)).get();
hitsHits = searchResponse.getHits().getHits();
}
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));
}
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("timestamp", time);
resultContain.add(res);
}
});
}
private SearchRequestBuilder getSearchRequestBuilder(Long startTime, Long stopTime) {
SearchRequestBuilder searchRequestBuilder;
if(stopTime >= 1570982400000L) {
String startDay = new DateTime(startTime).toString("yyyyMMdd");
String stopDay = new DateTime(stopTime).toString("yyyyMMdd");
boolean exists = transportClient.admin().indices()
.exists(new IndicesExistsRequest()
.indices(new String[]{String.format("%s_%s", indexBase, startDay), String.format("%s_%s", indexBase, stopDay)}))
.actionGet()
.isExists();
if(!exists){
return null;
}
if(startDay.equals(stopDay)){
searchRequestBuilder = transportClient.prepareSearch(String.format("%s_%s", indexBase, startDay));
}else{
searchRequestBuilder = transportClient.prepareSearch(String.format("%s_%s", indexBase, startDay),
String.format("%s_%s", indexBase, stopDay));
}
}else{
searchRequestBuilder = transportClient.prepareSearch(String.format("%s_exception_2019", indexBase));
}
return searchRequestBuilder;
}
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;
}
}
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