Commit c3f12a81 authored by duanruiming's avatar duanruiming

[add] 绿波城项目分支

parent 97c5d2b0
package net.wanji.datacenter.cache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.mapper.CrossDirDataHistMapper;
import net.wanji.databus.po.CrossDirDataHistPO;
import net.wanji.datacenter.common.Constants;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @date 2023/10/20 10:41
*/
@Component
@Slf4j
public class CrossDirWeekAvgFlowCache implements CommandLineRunner {
public static final Map<String, Double> crossDirWeekAvgFlowMap = new HashMap<>();
@Resource
private CrossDirDataHistMapper crossDirDataHistMapper;
private void getAvgFlow() {
LocalDate currentDate = LocalDate.now();
LocalDate lastDay = currentDate.minus(1, ChronoUnit.DAYS);
LocalDate lastWeek = currentDate.minus(1, ChronoUnit.WEEKS);
List<String> crossIds = CrossInfoCache.getSignalIds();
for (String crossId : crossIds) {
// 前一周
List<CrossDirDataHistPO> crossDirDataHistPOS = getDirDataHistPOS(lastDay, lastWeek, crossId);
calculateAvgFlow(crossDirDataHistPOS);
}
}
private static void calculateAvgFlow(List<CrossDirDataHistPO> crossDirDataHistPOS) {
if (!CollectionUtils.isEmpty(crossDirDataHistPOS)) {
Map<Integer, List<CrossDirDataHistPO>> dirDataMap = crossDirDataHistPOS.stream().collect(Collectors.groupingBy(CrossDirDataHistPO::getDirType));
if (!dirDataMap.isEmpty()) {
for (Map.Entry<Integer, List<CrossDirDataHistPO>> entry : dirDataMap.entrySet()) {
Integer dir = entry.getKey();
List<CrossDirDataHistPO> dirDataHistPOS = entry.getValue();
String currentCrossId = dirDataHistPOS.get(0).getCrossId();
OptionalDouble average = dirDataHistPOS.stream().map(CrossDirDataHistPO::getFlow).mapToInt(Integer::intValue).average();
double dirFlowAvg = 1.0;
if (average.isPresent()) {
dirFlowAvg = average.getAsDouble() == 0.0 ? 1.0 : average.getAsDouble();
}
crossDirWeekAvgFlowMap.put(currentCrossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)), dirFlowAvg);
}
}
}
}
/**
* 前一周的数据
*/
private List<CrossDirDataHistPO> getDirDataHistPOS(LocalDate lastDay, LocalDate lastWeek, String crossId) {
LambdaQueryWrapper<CrossDirDataHistPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossDirDataHistPO::getCrossId, crossId);
queryWrapper.between(CrossDirDataHistPO::getStartTime, lastWeek, lastDay);
return crossDirDataHistMapper.selectList(queryWrapper);
}
@Override
public void run(String... args) throws Exception {
try {
getAvgFlow();
} catch (Exception e) {
log.error("7天内路口方向平均流量获取失败", e);
throw new Exception(e);
}
log.info("7天内路口方向平均流量:{}", crossDirWeekAvgFlowMap);
}
}
\ No newline at end of file
package net.wanji.datacenter.cache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.mapper.CrossDirDataHistMapper;
import net.wanji.databus.po.CrossDirDataHistPO;
import net.wanji.datacenter.common.Constants;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @date 2023/10/18 15:50
*/
@Component
@Slf4j
public class CrossDirWeekMaxFlowCache implements CommandLineRunner {
public static final Map<String, Integer> crossDirWeekMaxFlowMap = new HashMap<>();
@Resource
private CrossDirDataHistMapper crossDirDataHistMapper;
private void getMaxFlow() throws Exception {
LocalDate currentDate = LocalDate.now();
LocalDate lastDay = currentDate.minus(1, ChronoUnit.DAYS);
LocalDate lastWeek = currentDate.minus(1, ChronoUnit.WEEKS);
List<String> crossIds = CrossInfoCache.getSignalIds();
for (String crossId : crossIds) {
// 前一周
LambdaQueryWrapper<CrossDirDataHistPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossDirDataHistPO::getCrossId, crossId);
queryWrapper.between(CrossDirDataHistPO::getStartTime, lastWeek, lastDay);
List<CrossDirDataHistPO> crossDirDataHistPOS = crossDirDataHistMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossDirDataHistPOS)) {
Map<Integer, List<CrossDirDataHistPO>> dirDataMap = crossDirDataHistPOS.stream().collect(Collectors.groupingBy(CrossDirDataHistPO::getDirType));
if (!dirDataMap.isEmpty()) {
for (Map.Entry<Integer, List<CrossDirDataHistPO>> entry : dirDataMap.entrySet()) {
Integer dir = entry.getKey();
List<CrossDirDataHistPO> dirDataHistPOS = entry.getValue();
String currentCrossId = dirDataHistPOS.get(0).getCrossId();
int dirFlowMax = dirDataHistPOS.stream().map(CrossDirDataHistPO::getFlow).mapToInt(Integer::intValue).max().getAsInt();
crossDirWeekMaxFlowMap.put(currentCrossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)), dirFlowMax);
}
}
}
}
}
@Override
public void run(String... args) throws Exception {
try {
getMaxFlow();
} catch (Exception e) {
log.error("7天内路口方向最大流量获取失败", e);
throw new Exception(e);
}
log.info("7天内路口方向最大流量:{}", crossDirWeekMaxFlowMap);
}
}
\ No newline at end of file
......@@ -23,6 +23,8 @@ import java.util.stream.Collectors;
public class CrossLaneInfoCache implements InitializingBean {
public static final Map<String, LaneInfoPO> laneInfoMap = new HashMap<>();
/** key crossId11, value LaneInfoPO */
public static final Map<String, LaneInfoPO> crossIdLaneId2Map = new HashMap<>();
@Resource
private LaneInfoMapper laneInfoMapper;
......@@ -34,6 +36,13 @@ public class CrossLaneInfoCache implements InitializingBean {
if (!CollectionUtils.isEmpty(laneInfoPOS)) {
Map<String, LaneInfoPO> crossMap = laneInfoPOS.stream().collect(Collectors.toMap(LaneInfoPO::getId, Function.identity(), (key1, key2) -> key2));
laneInfoMap.putAll(crossMap);
for (LaneInfoPO laneInfoPO : laneInfoPOS) {
String currentCrossId = laneInfoPO.getCrossId();
String laneId = laneInfoPO.getId();
String laneId2 = laneId.substring(laneId.length() - 2);
String dir = String.valueOf(laneInfoPO.getDir());
crossIdLaneId2Map.put(currentCrossId.concat(dir).concat(laneId2), laneInfoPO);
}
}
}
}
......
package net.wanji.datacenter.cache;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.framework.Constants;
import net.wanji.databus.dao.entity.BaseCrossSchemePO;
import net.wanji.databus.dao.entity.CrossPhaseLightsPO;
import net.wanji.databus.dao.entity.CrossPhasePO;
import net.wanji.databus.dao.mapper.BaseCrossLightsMapper;
import net.wanji.databus.dao.mapper.BaseCrossPhaseLightsMapper;
import net.wanji.databus.dao.mapper.BaseCrossPhaseMapper;
import net.wanji.databus.dao.mapper.BaseCrossSchemeMapper;
import net.wanji.databus.po.BaseCrossLightsPO;
import net.wanji.datacenter.pojo.dto.CrossSchemePhaseDirTurnDTO;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author duanruiming
* @date 2023/10/14 15:36
*/
@Component
@Slf4j
public class CrossSchemePhaseLightsCache implements CommandLineRunner {
@Resource
BaseCrossSchemeMapper baseCrossSchemeMapper;
@Resource
BaseCrossPhaseMapper baseCrossPhaseMapper;
@Resource
BaseCrossPhaseLightsMapper baseCrossPhaseLightsMapper;
@Resource
BaseCrossLightsMapper baseCrossLightsMapper;
public static final List<CrossSchemePhaseDirTurnDTO> crossSchemePhaseDirTurnDTOList = new ArrayList<>();
public void init() throws Exception {
try {
List<BaseCrossSchemePO> schemePOList = baseCrossSchemeMapper.listCrossSchemeInfo(Constants.SystemParam.NULL, Constants.SystemParam.NULL, Constants.SystemParam.NULL_INT);
if (!CollectionUtils.isEmpty(schemePOList)) {
for (BaseCrossSchemePO baseCrossSchemePO : schemePOList) {
String crossId = baseCrossSchemePO.getCrossId();
String schemeNo = baseCrossSchemePO.getSchemeNo();
Integer schemeId = baseCrossSchemePO.getId();
List<CrossPhasePO> crossPhasePOList = baseCrossPhaseMapper.selectByCrossIdAndSchemeId(crossId, schemeId);
if (!CollectionUtils.isEmpty(crossPhasePOList)) {
buildData(crossId, schemeNo, crossPhasePOList);
}
}
}
log.info("路口缓存方案相位方向转向数据:{}", crossSchemePhaseDirTurnDTOList);
} catch (Exception e) {
log.error("路口缓存方案相位方向转向关系数据初始化失败", e);
throw new Exception(e);
}
}
/**
* 构建路口方案相位方向转向实体
* @param crossId 路口编号
* @param schemeNo
* @param crossPhasePOList
*/
private void buildData(String crossId, String schemeNo, List<CrossPhasePO> crossPhasePOList) {
for (CrossPhasePO crossPhasePO : crossPhasePOList) {
Integer phaseId = crossPhasePO.getId();
String phaseNo = crossPhasePO.getPhaseNo();
Integer redTime = crossPhasePO.getRedTime();
Integer phaseTime = crossPhasePO.getPhaseTime();
Integer greenTime = crossPhasePO.getGreenTime();
List<CrossPhaseLightsPO> crossPhaseLightsPOList = baseCrossPhaseLightsMapper.selectByPhaseId(phaseId);
if (!CollectionUtils.isEmpty(crossPhaseLightsPOList)) {
for (CrossPhaseLightsPO crossPhaseLightsPO : crossPhaseLightsPOList) {
CrossSchemePhaseDirTurnDTO crossSchemePhaseDirTurnDTO = new CrossSchemePhaseDirTurnDTO();
crossSchemePhaseDirTurnDTO.setCrossId(crossId);
crossSchemePhaseDirTurnDTO.setSchemeNo(schemeNo);
crossSchemePhaseDirTurnDTO.setPhaseNo(phaseNo);
Integer lightsId = crossPhaseLightsPO.getLightsId();
BaseCrossLightsPO baseCrossLightsPO = baseCrossLightsMapper.selectById(lightsId);
Integer dir = baseCrossLightsPO.getDir();
crossSchemePhaseDirTurnDTO.setLightsDir(dir);
Integer turn = baseCrossLightsPO.getType();
if (turn == 20) {
continue;
}
crossSchemePhaseDirTurnDTO.setPhaseTime(phaseTime);
crossSchemePhaseDirTurnDTO.setGreenTime(greenTime);
crossSchemePhaseDirTurnDTO.setRedTime(redTime);
crossSchemePhaseDirTurnDTO.setLightsTurn(turn);
crossSchemePhaseDirTurnDTOList.add(crossSchemePhaseDirTurnDTO);
}
}
}
}
@Override
public void run(String... args) throws Exception {
try {
init();
} catch (Exception e) {
log.error("路口缓存方案相位方向转向数据初始化失败", e);
throw new Exception(e);
}
}
}
//package net.wanji.datacenter.cache;
//
//import lombok.extern.slf4j.Slf4j;
//import net.wanji.common.framework.Constants;
//import net.wanji.databus.dao.entity.BaseCrossSchemePO;
//import net.wanji.databus.dao.entity.CrossPhaseLightsPO;
//import net.wanji.databus.dao.entity.CrossPhasePO;
//import net.wanji.databus.dao.mapper.BaseCrossLightsMapper;
//import net.wanji.databus.dao.mapper.BaseCrossPhaseLightsMapper;
//import net.wanji.databus.dao.mapper.BaseCrossPhaseMapper;
//import net.wanji.databus.dao.mapper.BaseCrossSchemeMapper;
//import net.wanji.databus.po.BaseCrossLightsPO;
//import net.wanji.datacenter.pojo.dto.CrossSchemePhaseDirTurnDTO;
//import org.springframework.boot.CommandLineRunner;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//
//import javax.annotation.Resource;
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * @author duanruiming
// * @date 2023/10/14 15:36
// */
//@Component
//@Slf4j
//public class CrossSchemePhaseLightsCache implements CommandLineRunner {
//
// @Resource
// BaseCrossSchemeMapper baseCrossSchemeMapper;
// @Resource
// BaseCrossPhaseMapper baseCrossPhaseMapper;
// @Resource
// BaseCrossPhaseLightsMapper baseCrossPhaseLightsMapper;
// @Resource
// BaseCrossLightsMapper baseCrossLightsMapper;
//
// public static final List<CrossSchemePhaseDirTurnDTO> crossSchemePhaseDirTurnDTOList = new ArrayList<>();
//
// public void init() throws Exception {
// try {
// List<BaseCrossSchemePO> schemePOList = baseCrossSchemeMapper.listCrossSchemeInfo(Constants.SystemParam.NULL, Constants.SystemParam.NULL, Constants.SystemParam.NULL_INT);
// if (!CollectionUtils.isEmpty(schemePOList)) {
// for (BaseCrossSchemePO baseCrossSchemePO : schemePOList) {
// String crossId = baseCrossSchemePO.getCrossId();
// String schemeNo = baseCrossSchemePO.getSchemeNo();
// Integer schemeId = baseCrossSchemePO.getId();
// List<CrossPhasePO> crossPhasePOList = baseCrossPhaseMapper.selectByCrossIdAndSchemeId(crossId, schemeId);
// if (!CollectionUtils.isEmpty(crossPhasePOList)) {
// buildData(crossId, schemeNo, crossPhasePOList);
// }
// }
// }
// log.info("路口缓存方案相位方向转向数据:{}", crossSchemePhaseDirTurnDTOList);
// } catch (Exception e) {
// log.error("路口缓存方案相位方向转向关系数据初始化失败", e);
// throw new Exception(e);
// }
// }
//
// /**
// * 构建路口方案相位方向转向实体
// * @param crossId 路口编号
// * @param schemeNo
// * @param crossPhasePOList
// */
// private void buildData(String crossId, String schemeNo, List<CrossPhasePO> crossPhasePOList) {
// for (CrossPhasePO crossPhasePO : crossPhasePOList) {
// Integer phaseId = crossPhasePO.getId();
// String phaseNo = crossPhasePO.getPhaseNo();
// Integer redTime = crossPhasePO.getRedTime();
// Integer phaseTime = crossPhasePO.getPhaseTime();
// Integer greenTime = crossPhasePO.getGreenTime();
// List<CrossPhaseLightsPO> crossPhaseLightsPOList = baseCrossPhaseLightsMapper.selectByPhaseId(phaseId);
// if (!CollectionUtils.isEmpty(crossPhaseLightsPOList)) {
// for (CrossPhaseLightsPO crossPhaseLightsPO : crossPhaseLightsPOList) {
// CrossSchemePhaseDirTurnDTO crossSchemePhaseDirTurnDTO = new CrossSchemePhaseDirTurnDTO();
// crossSchemePhaseDirTurnDTO.setCrossId(crossId);
// crossSchemePhaseDirTurnDTO.setSchemeNo(schemeNo);
// crossSchemePhaseDirTurnDTO.setPhaseNo(phaseNo);
// Integer lightsId = crossPhaseLightsPO.getLightsId();
// BaseCrossLightsPO baseCrossLightsPO = baseCrossLightsMapper.selectById(lightsId);
// Integer dir = baseCrossLightsPO.getDir();
// crossSchemePhaseDirTurnDTO.setLightsDir(dir);
// Integer turn = baseCrossLightsPO.getType();
// if (turn == 20) {
// continue;
// }
// crossSchemePhaseDirTurnDTO.setPhaseTime(phaseTime);
// crossSchemePhaseDirTurnDTO.setGreenTime(greenTime);
// crossSchemePhaseDirTurnDTO.setRedTime(redTime);
// crossSchemePhaseDirTurnDTO.setLightsTurn(turn);
// crossSchemePhaseDirTurnDTOList.add(crossSchemePhaseDirTurnDTO);
// }
// }
// }
// }
//
// @Override
// public void run(String... args) throws Exception {
// try {
// init();
// } catch (Exception e) {
// log.error("路口缓存方案相位方向转向数据初始化失败", e);
// throw new Exception(e);
// }
// }
//}
package net.wanji.datacenter.cache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.mapper.CrossTurnDataHistMapper;
import net.wanji.databus.po.CrossTurnDataHistPO;
import net.wanji.datacenter.common.Constants;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @date 2023/10/19 15:33
*/
@Component
@Slf4j
public class CrossTurnWeekMaxFlowCache implements CommandLineRunner {
public static final Map<String, Integer> crossTurnWeekMaxFlowMap = new HashMap<>();
@Resource
private CrossTurnDataHistMapper crossTurnDataHistMapper;
private void getTurnMaxFlow() throws Exception {
LocalDate currentDate = LocalDate.now();
LocalDate lastDay = currentDate.minus(1, ChronoUnit.DAYS);
LocalDate lastWeek = currentDate.minus(1, ChronoUnit.WEEKS);
List<String> crossIds = CrossInfoCache.getSignalIds();
for (String crossId : crossIds) {
// 前一周
LambdaQueryWrapper<CrossTurnDataHistPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossTurnDataHistPO::getCrossId, crossId);
queryWrapper.between(CrossTurnDataHistPO::getStartTime, lastWeek, lastDay);
List<CrossTurnDataHistPO> crossTurnDataHistPOS = crossTurnDataHistMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossTurnDataHistPOS)) {
calculateData(crossId, crossTurnDataHistPOS);
}
}
}
/**
* 计算转向一周最大流量
* @param crossId
* @param crossTurnDataHistPOS
*/
private static void calculateData(String crossId, List<CrossTurnDataHistPO> crossTurnDataHistPOS) {
Map<Integer, List<CrossTurnDataHistPO>> dirDataPOsMap = crossTurnDataHistPOS.stream().collect(Collectors.groupingBy(CrossTurnDataHistPO::getInDir));
for (Map.Entry<Integer, List<CrossTurnDataHistPO>> entry : dirDataPOsMap.entrySet()) {
Integer dir = entry.getKey();
List<CrossTurnDataHistPO> dirHistPOS = entry.getValue();
if (!CollectionUtils.isEmpty(dirHistPOS)) {
Map<String, List<CrossTurnDataHistPO>> turnDataPOMap = dirHistPOS.stream().collect(Collectors.groupingBy(CrossTurnDataHistPO::getTurnType));
for (Map.Entry<String, List<CrossTurnDataHistPO>> turnEntry : turnDataPOMap.entrySet()) {
String turn = turnEntry.getKey();
List<CrossTurnDataHistPO> turnDataHistPOList = turnEntry.getValue();
if (!CollectionUtils.isEmpty(turnDataHistPOList)) {
OptionalInt max = turnDataHistPOList.stream().map(CrossTurnDataHistPO::getFlow).mapToInt(Integer::intValue).max();
if (max.isPresent()) {
String key = crossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)).concat(Constants.UNDERLINE).concat(turn);
crossTurnWeekMaxFlowMap.put(key, max.getAsInt());
}
}
}
}
}
}
@Override
public void run(String... args) throws Exception {
try {
getTurnMaxFlow();
} catch (Exception e) {
log.error("7天内路口方向转向最大流量获取失败", e);
throw new Exception(e);
}
log.info("7天内路口方向转向最大流量:{}", crossTurnWeekMaxFlowMap);
}
}
\ No newline at end of file
package net.wanji.datacenter.cache;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.framework.spring.ServiceBeanContext;
import net.wanji.datacenter.service.DataProcessService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author duanruiming
* @date 2023/03/10 14:04
*/
@Component
@Slf4j
public class DataProcessServiceRegistrator implements CommandLineRunner {
private final Map<String, DataProcessService> dataProcessServiceRegistrar = new HashMap<>();
/**
* 获取注册器
* key:主题名/类名,value: bean
*
* @return
*/
public Map<String, DataProcessService> getDataProcessServiceRegistrar() {
return dataProcessServiceRegistrar;
}
@Override
public void run(String... args) throws Exception {
Map<String, DataProcessService> map = ServiceBeanContext.getInterfaceBeanMap(DataProcessService.class);
if (!map.isEmpty()) {
dataProcessServiceRegistrar.putAll(map);
} else {
log.error("初始化数据处理注册器失败");
}
}
}
package net.wanji.datacenter.cache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.mapper.CrossDirDataHistMapper;
import net.wanji.databus.po.CrossDirDataHistPO;
import net.wanji.datacenter.common.Constants;
import net.wanji.datacenter.kafka.ProducerHandler;
import net.wanji.datacenter.pojo.dto.CrossDirFreeFlowSpeedDTO;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @date 2023/10/14 14:16
*/
@Component
@Slf4j
public class WeekDirFreeFlowSpeedCache implements CommandLineRunner {
public static final Map<String, Double> crossDirFreeFlowSpeedMap = new HashMap<>();
@Resource
private CrossDirDataHistMapper crossDirDataHistMapper;
@Resource
private ProducerHandler producerHandler;
private void getDirWeekFreeFlowSpeed() throws Exception {
LocalDate currentDate = LocalDate.now();
LocalDate lastDay = currentDate.minus(1, ChronoUnit.DAYS);
LocalDate lastWeek = currentDate.minus(1, ChronoUnit.WEEKS);
List<String> crossIds = CrossInfoCache.getSignalIds();
List<CrossDirFreeFlowSpeedDTO> crossDirFreeFlowSpeedDTOS = new ArrayList<>();
for (String crossId : crossIds) {
// 前一周
LambdaQueryWrapper<CrossDirDataHistPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossDirDataHistPO::getCrossId, crossId);
queryWrapper.between(CrossDirDataHistPO::getStartTime, lastWeek, lastDay);
List<CrossDirDataHistPO> crossDirDataHistPOS = crossDirDataHistMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossDirDataHistPOS)) {
calculateData(crossDirFreeFlowSpeedDTOS, crossId, crossDirDataHistPOS);
}
}
Map<String, List<CrossDirFreeFlowSpeedDTO>> map = new HashMap<>(1);
map.put(Constants.CROSS_FREE_FLOW_SPEED_KEY, crossDirFreeFlowSpeedDTOS);
producerHandler.send2FirstKafka(Constants.CROSS_FREE_FLOW_SPEED_TOPIC, map);
}
/**
* 计算前一周方向自由流速度85~95分位速度
* @param crossDirFreeFlowSpeedDTOS
* @param crossId
* @param crossDirDataHistPOS
*/
private static void calculateData(List<CrossDirFreeFlowSpeedDTO> crossDirFreeFlowSpeedDTOS, String crossId, List<CrossDirDataHistPO> crossDirDataHistPOS) {
Map<Integer, List<CrossDirDataHistPO>> dirDataMap = crossDirDataHistPOS.stream().collect(Collectors.groupingBy(CrossDirDataHistPO::getDirType));
if (!dirDataMap.isEmpty()) {
for (Map.Entry<Integer, List<CrossDirDataHistPO>> entry : dirDataMap.entrySet()) {
Integer dir = entry.getKey();
List<CrossDirDataHistPO> dirDataHistPOS = entry.getValue();
List<Double> weekSpeeds = dirDataHistPOS.stream().map(CrossDirDataHistPO::getSpeed).sorted().collect(Collectors.toList());
int startIndex = (int) (0.85 * weekSpeeds.size());
int endIndex = (int) (0.95 * weekSpeeds.size());
Double freeFlowSpeed = weekSpeeds.subList(startIndex, endIndex).stream().mapToDouble(Double::doubleValue).average().getAsDouble();
if (freeFlowSpeed == 0.0) {
freeFlowSpeed = 60.0;
}
crossDirFreeFlowSpeedMap.put(crossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)), freeFlowSpeed);
CrossDirFreeFlowSpeedDTO crossDirFreeFlowSpeedDTO = new CrossDirFreeFlowSpeedDTO();
crossDirFreeFlowSpeedDTO.setCrossId(crossId);
crossDirFreeFlowSpeedDTO.setDir(dir);
crossDirFreeFlowSpeedDTO.setFreeFlowSpeed(freeFlowSpeed);
crossDirFreeFlowSpeedDTOS.add(crossDirFreeFlowSpeedDTO);
}
}
}
@Override
public void run(String... args) throws Exception {
try {
getDirWeekFreeFlowSpeed();
} catch (Exception e) {
log.error("路口方向自由流速度失败", e);
throw new Exception(e);
}
log.info("路口方向自由流速度:{}", crossDirFreeFlowSpeedMap);
}
}
package net.wanji.datacenter.cache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.mapper.CrossTurnDataHistMapper;
import net.wanji.databus.po.CrossTurnDataHistPO;
import net.wanji.datacenter.common.Constants;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @date 2023/10/14 14:16
*/
@Component
@Slf4j
public class WeekTurnFreeFlowSpeedCache implements CommandLineRunner {
public static final Map<String, Double> crossTurnFreeFlowSpeedMap = new HashMap<>();
@Resource
private CrossTurnDataHistMapper crossTurnDataHistMapper;
private void getDirWeekFreeFlowSpeed() throws Exception {
LocalDate currentDate = LocalDate.now();
LocalDate lastDay = currentDate.minus(1, ChronoUnit.DAYS);
LocalDate lastWeek = currentDate.minus(1, ChronoUnit.WEEKS);
List<String> crossIds = CrossInfoCache.getSignalIds();
for (String crossId : crossIds) {
// 前一周
LambdaQueryWrapper<CrossTurnDataHistPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossTurnDataHistPO::getCrossId, crossId);
queryWrapper.between(CrossTurnDataHistPO::getStartTime, lastWeek, lastDay);
List<CrossTurnDataHistPO> crossTurnDataHistPOS = crossTurnDataHistMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossTurnDataHistPOS)) {
calculateData(crossTurnDataHistPOS);
}
}
}
/**
* 计算前一周自由流速度85~95分位速度
* @param crossTurnDataHistPOS
*/
private static void calculateData(List<CrossTurnDataHistPO> crossTurnDataHistPOS) {
Map<Integer, List<CrossTurnDataHistPO>> dirDataMap = crossTurnDataHistPOS.stream().collect(Collectors.groupingBy(CrossTurnDataHistPO::getInDir));
for (Map.Entry<Integer, List<CrossTurnDataHistPO>> dirEntry : dirDataMap.entrySet()) {
Integer dir = dirEntry.getKey();
List<CrossTurnDataHistPO> dirTurnDataHistPOS = dirEntry.getValue();
Map<String, List<CrossTurnDataHistPO>> turnDataMap = dirTurnDataHistPOS.stream().collect(Collectors.groupingBy(CrossTurnDataHistPO::getTurnType));
if (!turnDataMap.isEmpty()) {
for (Map.Entry<String, List<CrossTurnDataHistPO>> entry : turnDataMap.entrySet()) {
String turn = entry.getKey();
List<CrossTurnDataHistPO> turnDataHistPOS = entry.getValue();
String currentCrossId = turnDataHistPOS.get(0).getCrossId();
List<Double> weekTurnSpeeds = turnDataHistPOS.stream().map(CrossTurnDataHistPO::getSpeed).sorted().collect(Collectors.toList());
int startIndex = (int) (0.85 * weekTurnSpeeds.size());
int endIndex = (int) (0.95 * weekTurnSpeeds.size());
if (startIndex == endIndex) {
startIndex = startIndex - 1;
}
OptionalDouble average = weekTurnSpeeds.subList(startIndex, endIndex).stream().mapToDouble(Double::doubleValue).average();
if (average.isPresent()) {
double turnFreeFlowSpeed = average.getAsDouble();
String key = currentCrossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)).concat(Constants.UNDERLINE).concat(turn);
crossTurnFreeFlowSpeedMap.put(key, turnFreeFlowSpeed);
}
}
}
}
}
@Override
public void run(String... args) throws Exception {
try {
getDirWeekFreeFlowSpeed();
} catch (Exception e) {
log.error("路口转向自由流速度失败", e);
throw new Exception(e);
}
log.info("路口转向自由流速度:{}", crossTurnFreeFlowSpeedMap);
}
}
package net.wanji.datacenter.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* # 事件数据集文件保存配置
*/
@ConfigurationProperties(prefix = "eventsave")
@Component
@Data
public class EventSaveConfiguration {
String rootFolder;
String city;
String subType;
String nvrurl;
String positiveSample;
String negativeSample;
String trackJson;
String lightJson;
String evidence;
String image;
String video;
String vision;
String labelJson;
}
package net.wanji.datacenter.kafka;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.datacenter.constant.EventAbnormalEnum;
import net.wanji.datacenter.pojo.dto.CrossEventDTO;
import net.wanji.datacenter.pojo.dto.CrossLaneSnapshotDataDTO;
import net.wanji.datacenter.pojo.dto.CrossSnapshotDataDTO;
import net.wanji.datacenter.pojo.dto.LineCongestion;
import net.wanji.datacenter.pojo.po.PhaseEmptyResult;
import net.wanji.datacenter.service.DataProcessService;
import net.wanji.datacenter.util.RedisUtils;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.listener.KafkaListenerErrorHandler;
import org.springframework.kafka.listener.ListenerExecutionFailedException;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author duanruiming
......@@ -41,162 +26,39 @@ import java.util.concurrent.CopyOnWriteArrayList;
@Slf4j
public class ConsumerHandler implements KafkaListenerErrorHandler {
// Redis缓存过期时间
public static final int TTL_IN_MILLIS = 10 * 60 * 1000;
@Resource(name = "lanePeriodicDataProcessService")
DataProcessService lanePeriodicDataProcessService;
@Resource(name = "crossSnapshotDataProcessService")
DataProcessService crossSnapshotDataProcessService;
@Resource(name = "laneSnapshotDataProcessService")
DataProcessService laneSnapshotDataProcessService;
@Autowired
RedisUtils redisUtils;
@Resource
private DataProcessService dataProcessService;
public static final Map<String, List<CrossSnapshotDataDTO>> crossSnapshotDataMap = new ConcurrentHashMap<>();
public static final List<PhaseEmptyResult> phaseEmptyResultList = new CopyOnWriteArrayList<>();
@KafkaListener(topics = {"${kafka-consumer.crossEventIndex}"}, groupId = "group")
public void receiveCrossEventIndex(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment) throws Exception {
// 同一时间,可能发送两条数据,东西方向,转向可以忽略
PhaseEmptyResult current = JacksonUtils.getInstance().readValue((String) record.value(), PhaseEmptyResult.class);
if (!CollectionUtils.isEmpty(phaseEmptyResultList)) {
for (PhaseEmptyResult item : phaseEmptyResultList) {
String crossId = item.getCrossId();
Long startTime = item.getStartTime();
String direction = item.getDirection();
if (Objects.equals(crossId, current.getCrossId()) && Objects.equals(direction, current.getDirection())
&& current.getStartTime() - startTime < 1000 * 60 * 5) {
phaseEmptyResultList.add(current);
phaseEmptyResultList.remove(item);
}
}
}
acknowledgment.acknowledge();
}
@KafkaListener(topics = {"${kafka-consumer.lanePeriodicDataTopic}"}, groupId = "group")
public void receiveLanePeriodicData(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment) throws Exception {
Object convert = lanePeriodicDataProcessService.convert(String.valueOf(record.value()));
// 修改逻辑,将保存逻辑改为将方向,转向数据返回kafka
lanePeriodicDataProcessService.save(convert);
acknowledgment.acknowledge();
}
@KafkaListener(topics = {"${kafka-consumer.crossSnapshotDataTopic}"}, groupId = "group")
public void receiveCrossSnapshotData(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment) throws Exception {
CrossSnapshotDataDTO crossSnapshotDataDTO = (CrossSnapshotDataDTO) crossSnapshotDataProcessService.convert(String.valueOf(record.value()));
if (!crossSnapshotDataMap.isEmpty() && !CollectionUtils.isEmpty(crossSnapshotDataMap.get(record.topic()))) {
List<CrossSnapshotDataDTO> crossSnapshotDataDTOS = crossSnapshotDataMap.get(record.topic());
crossSnapshotDataDTOS.add(crossSnapshotDataDTO);
if (crossSnapshotDataDTOS.size() == 30) {
crossSnapshotDataDTOS.remove(crossSnapshotDataDTOS.get(0));
}
} else {
List<CrossSnapshotDataDTO> crossSnapshotDataDTOS = new ArrayList<>(30);
crossSnapshotDataDTOS.add(crossSnapshotDataDTO);
crossSnapshotDataMap.put(record.topic(), crossSnapshotDataDTOS);
}
acknowledgment.acknowledge();
}
@KafkaListener(topics = {"${kafka-consumer.laneSnapshotDataTopic}"}, groupId = "group")
public void receiveLaneSnapshotData(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment) throws Exception {
//String originalData = String.valueOf(record.value());
String originalData = String.valueOf(laneStr);
try {
List<CrossLaneSnapshotDataDTO> convertList = (List<CrossLaneSnapshotDataDTO>) laneSnapshotDataProcessService.convert(String.valueOf(record.value()));
if (!CollectionUtils.isEmpty(convertList)) {
laneSnapshotDataProcessService.save(convertList);
}
dataProcessService.laneSave(originalData);
} catch (Exception e) {
log.error("Kafka收到车道快照数据异常", e);
throw new Exception(e);
log.error("车道周期实时数据转换异常", e);
throw new Exception();
}
acknowledgment.acknowledge();
// 修改逻辑,将保存逻辑改为将方向,转向数据返回kafka
//acknowledgment.acknowledge();
}
@KafkaListener(topics = {"cross.event.index"}, groupId = "cross-event-index")
public void receiveCrossEventData(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment)
throws Exception {
@KafkaListener(topics = {"${kafka-consumer.crossPeriodicDataTopic}"}, groupId = "group")
public void receiveCrossPeriodicData(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment) throws Exception {
//String originalData = String.valueOf(record.value());
String originalData = String.valueOf(crossStr);
try {
ObjectMapper objectMapper = new ObjectMapper();
String recordStr = String.valueOf(record.value());
CrossEventDTO crossEventDTO = JacksonUtils.getInstance().readValue(recordStr, CrossEventDTO.class);
String msgType = crossEventDTO.getMsgType();
String crossId = crossEventDTO.getCrossId();
if (Objects.equals(msgType, EventAbnormalEnum.CROSS_UNBALANCE.getType())) {
String redisListElement = objectMapper.writeValueAsString(crossEventDTO);
// 失衡事件
// 方向缓存
Integer unbalanceDir = crossEventDTO.getUnbalanceDir();
String redisKey = crossId + ":" + unbalanceDir;
redisUtils.addToSortedSetWithExpiry(redisKey, redisListElement, TTL_IN_MILLIS);
// 路口缓存
redisUtils.addToSortedSetWithExpiry(crossId, redisListElement, TTL_IN_MILLIS);
} else if (msgType.startsWith("50")) {
// 拥堵事件
// 方向缓存
List<CrossEventDTO> details = crossEventDTO.getDetails();
for (CrossEventDTO detail : details) {
detail.setMsgType(detail.getCongestionCode());
Integer dir = detail.getDir();
String redisKey = crossId + ":" + dir;
String redisListElement = objectMapper.writeValueAsString(detail);
redisUtils.addToSortedSetWithExpiry(redisKey, redisListElement, TTL_IN_MILLIS);
}
// 路口缓存
String redisListElement = objectMapper.writeValueAsString(crossEventDTO);
redisUtils.addToSortedSetWithExpiry(crossId, redisListElement, TTL_IN_MILLIS);
} else if (Objects.equals(msgType, EventAbnormalEnum.CROSS_OVERFLOW.getType())
|| Objects.equals(msgType, EventAbnormalEnum.CROSS_DEADLOCK.getType())) {
// 溢出和死锁事件
// 方向缓存
List<CrossEventDTO> details = crossEventDTO.getDetails();
for (CrossEventDTO detail : details) {
detail.setMsgType(EventAbnormalEnum.CROSS_OVERFLOW.getType());
Integer dir = detail.getDir();
String redisKey = crossId + ":" + dir;
String redisListElement = objectMapper.writeValueAsString(detail);
redisUtils.addToSortedSetWithExpiry(redisKey, redisListElement, TTL_IN_MILLIS);
}
// 路口缓存
String redisListElement = objectMapper.writeValueAsString(crossEventDTO);
redisUtils.addToSortedSetWithExpiry(crossId, redisListElement, TTL_IN_MILLIS);
}
dataProcessService.crossSave(originalData);
} catch (Exception e) {
log.error("Kafka收到路口事件数据异常", e);
throw new Exception(e);
log.error("车道周期实时数据转换异常", e);
throw new Exception();
}
acknowledgment.acknowledge();
// 修改逻辑,将保存逻辑改为将方向,转向数据返回kafka
//acknowledgment.acknowledge();
}
@KafkaListener(topics = {"line_congestion_sink"}, groupId = "line_congestion_sink_redis_consumer")
public void receiveLineCongestionData(ConsumerRecord<Object, Object> record, Acknowledgment acknowledgment)
throws Exception {
try {
ObjectMapper objectMapper = new ObjectMapper();
String recordStr = String.valueOf(record.value());
//LineCongestion dto = JacksonUtils.getInstance().readValue(recordStr, LineCongestion.class);
//LineCongestion dto = JSONObject.parseObject(recordStr, LineCongestion.class);//objectMapper.readValue(element.toString(), LineCongestion.class);
String redisElement = recordStr; //JSONObject.toJSONString(dto, SerializerFeature.WriteNonStringValueAsString); //objectMapper.writeValueAsString(dto);
String redisKey = "line_congestion_sink";
// log.info("消费干线指标信息:{}",redisElement);
redisUtils.addToSortedSetWithExpiry(redisKey, redisElement, TTL_IN_MILLIS);
} catch (Exception e) {
log.error("Kafka收到路口事件数据异常", e);
throw new Exception(e);
}
acknowledgment.acknowledge();
}
@Override
@NonNull
......@@ -213,4 +75,7 @@ public class ConsumerHandler implements KafkaListenerErrorHandler {
return KafkaListenerErrorHandler.super.handleError(message, exception, consumer);
}
public static final String laneStr = "{\"orgCode\":\"370102\",\"timeStamp\":\"2024-11-15 15:40:00.000\",\"eventList\":[{\"crossId\":\"13MNM0B5OE0\",\"dir\":0,\"lane_num\":1,\"entry_type\":0,\"laneId\":\"1\",\"trafficFlow\":-1,\"trafficFlowA\":-1,\"trafficFlowB\":-1,\"trafficFlowC\":-1,\"trolleyEquivalent\":-1,\"laneFlowRate\":-1.0,\"meanV\":-1.0,\"vehicleNumsRatioMean\":-1.0,\"vehicleLengthRatioMean\":-1.0,\"timeOccupancy\":-1.0,\"staticQueueLengthMax\":-1.0,\"staticQueueLengthMin\":-1.0,\"dynamicQueueLengthMax\":-1.0,\"dynamicQueueLengthMin\":-1.0,\"lightGreenStartQueueLength\":-1.0,\"lightGreenFinishQueueLength\":-1.0,\"greenLightEfficiency\":-1.0,\"laneSaturationFlowRate\":-1,\"laneCapacity\":-1,\"laneSaturation\":-1.0,\"laneNoStopRate\":-1.0,\"laneOneStopRate\":-1.0,\"laneTwoStopRate\":-1.0,\"laneThreeStopRate\":-1.0,\"meanDelay\":-1.0,\"meanStopsNumber\":-1.0,\"meanLen\":0,\"timeHeadwaySectionMean\":-1.0,\"trafficInformation\":-1,\"overflowRate\":-1.0,\"nonMotorFlow\":-1.0,\"v85\":-1.0},{\"crossId\":\"13MNM0B5OR0\",\"dir\":2,\"lane_num\":2,\"entry_type\":-1,\"laneId\":\"2\",\"trafficFlow\":-1,\"trafficFlowA\":-1,\"trafficFlowB\":-1,\"trafficFlowC\":-1,\"trolleyEquivalent\":-1,\"laneFlowRate\":-1.0,\"meanV\":-1.0,\"vehicleNumsRatioMean\":-1.0,\"vehicleLengthRatioMean\":-1.0,\"timeOccupancy\":-1.0,\"staticQueueLengthMax\":-1.0,\"staticQueueLengthMin\":-1.0,\"dynamicQueueLengthMax\":-1.0,\"dynamicQueueLengthMin\":-1.0,\"lightGreenStartQueueLength\":-1.0,\"lightGreenFinishQueueLength\":-1.0,\"greenLightEfficiency\":-1.0,\"laneSaturationFlowRate\":-1,\"laneCapacity\":-1,\"laneSaturation\":-1.0,\"laneNoStopRate\":-1.0,\"laneOneStopRate\":-1.0,\"laneTwoStopRate\":-1.0,\"laneThreeStopRate\":-1.0,\"meanDelay\":-1.0,\"meanStopsNumber\":-1.0,\"meanLen\":-1.0,\"timeHeadwaySectionMean\":-1.0,\"trafficInformation\":-1,\"overflowRate\":-1.0,\"nonMotorFlow\":-1.0,\"v85\":-1.0}]}";
public static final String crossStr = "{\"orgCode\":\"370112\",\"timeStamp\":\"2024-11-15 20:10:00.000\",\"eventList\":[{\"crossId\":\"13N7H0B63Q0\",\"status\":-1,\"type\":-1,\"trafficIndex\":-1.0,\"startTime\":\"2024-11-15 20:05:00\",\"duration\":-1,\"isUnbalance\":0,\"isSpillover\":-1,\"emptyPass\":-1,\"isCongestion\":-1,\"unbalanceIndex\":null,\"spilloverIndex\":-1.0,\"congestionIndex\":-1.0,\"unbalanceDirs\":\"-1\",\"spilloverDirs\":\"-1\",\"emptyDirTurn\":\"-1\",\"congestionDirs\":\"-1\",\"flow\":-1,\"flowRate\":-1.0,\"speed\":-1.0,\"queueLength\":-1.0,\"stopTimes\":-1.0,\"delayTime\":-1,\"sturation\":-1.0,\"serviceLevel\":\"Z\",\"trafficState\":-1,\"strategy\":-1,\"strategyDuration\":-1,\"optimizeCount\":-1,\"optimizeSeconds\":-1,\"batchTime\":1731672601},{\"crossId\":\"13N920B63K0\",\"status\":-1,\"type\":-1,\"trafficIndex\":-1.0,\"startTime\":\"2024-11-15 20:05:00\",\"duration\":-1,\"isUnbalance\":0,\"isSpillover\":-1,\"emptyPass\":-1,\"isCongestion\":-1,\"unbalanceIndex\":null,\"spilloverIndex\":-1.0,\"congestionIndex\":-1.0,\"unbalanceDirs\":\"-1\",\"spilloverDirs\":\"-1\",\"emptyDirTurn\":\"-1\",\"congestionDirs\":\"-1\",\"flow\":-1,\"flowRate\":-1.0,\"speed\":-1.0,\"queueLength\":-1.0,\"stopTimes\":-1.0,\"delayTime\":-1,\"sturation\":-1.0,\"serviceLevel\":\"Z\",\"trafficState\":-1,\"strategy\":-1,\"strategyDuration\":-1,\"optimizeCount\":-1,\"optimizeSeconds\":-1,\"batchTime\":1731672601}]}";
}
package net.wanji.datacenter.kafka;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.utils.tool.JacksonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
/**
* @author duanruiming
* @date 2023/08/02 16:58
*/
@Component
@Slf4j
@SuppressWarnings("all")
public class ProducerHandler {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate1;
@Autowired
private KafkaTemplate<String, String> kafkaTemplate2;
public void send2FirstKafka(String topic, Object msg) {
Page<Object> objectPage = new Page<>();
try {
ListenableFuture<SendResult<String, String>> future = this.kafkaTemplate1.send(topic, JacksonUtils.getInstance().writeValueAsString(msg));
future.addCallback(
success -> {
},
failure -> log.error("消息发送失败:", failure));
} catch (JsonProcessingException e) {
log.error("{}主题发送kafka1消息失败:", e);
return;
}
}
public void send2SecondKafka(String topic, Object msg) {
Page<Object> objectPage = new Page<>();
try {
ListenableFuture<SendResult<String, String>> future = this.kafkaTemplate2.send(topic, JacksonUtils.getInstance().writeValueAsString(msg));
future.addCallback(
success -> {
},
failure -> log.error("消息发送失败:", failure));
} catch (JsonProcessingException e) {
log.error("{}主题发送kafka2消息失败:", e);
return;
}
}
}
//package net.wanji.datacenter.kafka;
//
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import lombok.extern.slf4j.Slf4j;
//import net.wanji.common.utils.tool.JacksonUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.kafka.core.KafkaTemplate;
//import org.springframework.kafka.support.SendResult;
//import org.springframework.stereotype.Component;
//import org.springframework.util.concurrent.ListenableFuture;
//
///**
// * @author duanruiming
// * @date 2023/08/02 16:58
// */
//@Component
//@Slf4j
//@SuppressWarnings("all")
//public class ProducerHandler {
// @Autowired
// private KafkaTemplate<String, String> kafkaTemplate1;
// @Autowired
// private KafkaTemplate<String, String> kafkaTemplate2;
//
// public void send2FirstKafka(String topic, Object msg) {
// Page<Object> objectPage = new Page<>();
// try {
// ListenableFuture<SendResult<String, String>> future = this.kafkaTemplate1.send(topic, JacksonUtils.getInstance().writeValueAsString(msg));
// future.addCallback(
// success -> {
// },
// failure -> log.error("消息发送失败:", failure));
// } catch (JsonProcessingException e) {
// log.error("{}主题发送kafka1消息失败:", e);
// return;
// }
// }
//
// public void send2SecondKafka(String topic, Object msg) {
// Page<Object> objectPage = new Page<>();
// try {
// ListenableFuture<SendResult<String, String>> future = this.kafkaTemplate2.send(topic, JacksonUtils.getInstance().writeValueAsString(msg));
// future.addCallback(
// success -> {
// },
// failure -> log.error("消息发送失败:", failure));
// } catch (JsonProcessingException e) {
// log.error("{}主题发送kafka2消息失败:", e);
// return;
// }
// }
//}
package net.wanji.datacenter.pojo.convert;
import net.wanji.common.enums.TurnConvertEnum;
import net.wanji.databus.po.*;
import net.wanji.datacenter.pojo.dto.LanePeriodicDataDTO;
import org.springframework.stereotype.Component;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Random;
/**
* @author duanruiming
* @date 2023/03/11 14:04
*/
@SuppressWarnings("all")
@Component
public class LanePeriodicDataEventListConvert {
public CrossDataRealtimePO convert2CrossDataRealTimePO(LanePeriodicDataDTO.EventList eventList, CrossBaseLaneInfoPO laneInfoPO) {
String id = laneInfoPO.getId();
String crossId = laneInfoPO.getCrossId();
// todo 路口状态
int trafficFlow = eventList.getTrafficFlow();
double meanV = eventList.getMeanV() == 0.0 ? 50.0 : eventList.getMeanV();
double staticQueueLengthMax = eventList.getStaticQueueLengthMax();
double staticQueueLengthMin = eventList.getStaticQueueLengthMin() == 0.0 ? 10 : eventList.getStaticQueueLengthMin();
double stopTimes = eventList.getMeanStopsNumber();
double meanDelay = eventList.getMeanDelay();
Integer meanDelayInt = Double.valueOf(meanDelay).intValue();
double laneSaturation = eventList.getLaneSaturation();
String dir = String.valueOf(laneInfoPO.getDir());
double overflowRate = eventList.getOverflowRate();
double greenLightEfficiency = eventList.getGreenLightEfficiency();
CrossDataRealtimePO crossDataRealTimePO = new CrossDataRealtimePO();
crossDataRealTimePO.setCrossId(crossId);
crossDataRealTimePO.setStatus(eventList.getTrafficInformation()); // 路口状态
crossDataRealTimePO.setType(1); // 1常规 2异常
crossDataRealTimePO.setDuration(5); // todo 通过第二批次判断
crossDataRealTimePO.setIsUnbalance(0);
crossDataRealTimePO.setUnbalanceIndex(0.0);
crossDataRealTimePO.setUnbalanceDirs(dir);
crossDataRealTimePO.setIsCongestion(0);
crossDataRealTimePO.setCongestionIndex(0.0); // 拥堵指数=
crossDataRealTimePO.setCongestionDirs(dir);
crossDataRealTimePO.setIsSpillover(0);
crossDataRealTimePO.setSpilloverIndex(0.0);
crossDataRealTimePO.setSpilloverDirs(dir);
crossDataRealTimePO.setTrafficIndex(1.0);// 交通指数=所有失衡拥堵溢出指数平均
crossDataRealTimePO.setFlow(trafficFlow);
crossDataRealTimePO.setFlowRate(Double.valueOf(trafficFlow / 5 * 60)); // 每个车道流率
crossDataRealTimePO.setSpeed(meanV);
crossDataRealTimePO.setQueueLength(staticQueueLengthMax);
crossDataRealTimePO.setStopTimes(stopTimes);
crossDataRealTimePO.setDelayTime(meanDelayInt);
crossDataRealTimePO.setSturation(laneSaturation);
crossDataRealTimePO.setEffusionRate(overflowRate);
crossDataRealTimePO.setGreenLightEfficiency(greenLightEfficiency);
crossDataRealTimePO.setNoStopRate(eventList.getLaneNoStopRate());
crossDataRealTimePO.setOneStopRate(eventList.getLaneOneStopRate());
crossDataRealTimePO.setTwoStopRate(eventList.getLaneTwoStopRate());
crossDataRealTimePO.setThreeStopRate(eventList.getLaneThreeStopRate());
crossDataRealTimePO.setTimeOccupancy(eventList.getTimeOccupancy());
crossDataRealTimePO.setVehicleLengthRatioMean(eventList.getVehicleLengthRatioMean());
return crossDataRealTimePO;
}
public CrossDirDataRealtimePO convert2CrossDirDataRealTimePO(LanePeriodicDataDTO.EventList eventList, CrossBaseLaneInfoPO laneInfoPO) {
String crossId = laneInfoPO.getCrossId();
// todo 路口状态
int trafficFlow = eventList.getTrafficFlow();
double meanV = eventList.getMeanV();
double staticQueueLengthMax = eventList.getStaticQueueLengthMax();
double staticQueueLengthMin = eventList.getStaticQueueLengthMin();
double stopTimes = eventList.getMeanStopsNumber();
double meanDelay = eventList.getMeanDelay();
Integer meanDelayInt = Double.valueOf(meanDelay).intValue();
double laneSaturation = eventList.getLaneSaturation();
Integer dir = laneInfoPO.getDir();
Integer type = laneInfoPO.getType();
double overflowRate = eventList.getOverflowRate();
double greenLightEfficiency = eventList.getGreenLightEfficiency();
CrossDirDataRealtimePO crossDirDataRealTimePO = new CrossDirDataRealtimePO();
// 路口方向ID(路口ID_方向_进出口_主辅路序号)
crossDirDataRealTimePO.setId(String.valueOf(dir).concat(String.valueOf(type)));
crossDirDataRealTimePO.setDirType(dir);
crossDirDataRealTimePO.setInOutType(type);
crossDirDataRealTimePO.setCrossId(crossId);
crossDirDataRealTimePO.setLength(staticQueueLengthMax);
crossDirDataRealTimePO.setStatus(eventList.getTrafficInformation());
crossDirDataRealTimePO.setTrafficIndex(0000.00);
crossDirDataRealTimePO.setCapacity(trafficFlow);
crossDirDataRealTimePO.setDuration(5);
crossDirDataRealTimePO.setFlow(trafficFlow);
crossDirDataRealTimePO.setSpeed(meanV);
crossDirDataRealTimePO.setQueueLength(staticQueueLengthMax);
crossDirDataRealTimePO.setStopTimes(stopTimes);
crossDirDataRealTimePO.setDelayTime(meanDelayInt);
crossDirDataRealTimePO.setSturation(laneSaturation);
crossDirDataRealTimePO.setEffusionRate(eventList.getOverflowRate());
crossDirDataRealTimePO.setNoStopRate(eventList.getLaneNoStopRate());
crossDirDataRealTimePO.setOneStopRate(eventList.getLaneOneStopRate());
crossDirDataRealTimePO.setTwoStopRate(eventList.getLaneTwoStopRate());
crossDirDataRealTimePO.setThreeStopRate(eventList.getLaneThreeStopRate());
crossDirDataRealTimePO.setEffusionRate(overflowRate);
crossDirDataRealTimePO.setGreenLightEfficiency(greenLightEfficiency);
return crossDirDataRealTimePO;
}
public CrossTurnDataRealtimePO convert2CrossTurnDataRealtimePO(LanePeriodicDataDTO.EventList eventList, CrossBaseLaneInfoPO laneInfoPO) {
String crossId = laneInfoPO.getCrossId();
// todo 路口状态
int trafficFlow = eventList.getTrafficFlow();
double meanV = eventList.getMeanV();
double staticQueueLengthMax = eventList.getStaticQueueLengthMax();
double stopTimes = eventList.getMeanStopsNumber();
double meanDelay = eventList.getMeanDelay();
Integer meanDelayInt = Double.valueOf(meanDelay).intValue();
double laneSaturation = eventList.getLaneSaturation();
Integer dir = laneInfoPO.getDir();
Integer type = laneInfoPO.getType();
Integer turn = laneInfoPO.getTurn();
double overflowRate = eventList.getOverflowRate();
double greenLightEfficiency = eventList.getGreenLightEfficiency();
CrossTurnDataRealtimePO crossTurnDataRealtimePO = new CrossTurnDataRealtimePO();
crossTurnDataRealtimePO.setId(crossId.concat("").concat(String.valueOf(turn)));
crossTurnDataRealtimePO.setTurnType(TurnConvertEnum.getCodeByKey(turn));
crossTurnDataRealtimePO.setInDir(dir);
Integer outdir = dir + 4 > 8 ? dir + 4 - 8 : dir + 4;
crossTurnDataRealtimePO.setOutDir(outdir);
crossTurnDataRealtimePO.setCrossId(crossId);
crossTurnDataRealtimePO.setFlow(trafficFlow);
crossTurnDataRealtimePO.setStatus(eventList.getTrafficInformation());
crossTurnDataRealtimePO.setTrafficIndex((double) new Random().nextInt(10));
crossTurnDataRealtimePO.setSpeed(meanV);
crossTurnDataRealtimePO.setInSpeed(meanV);
crossTurnDataRealtimePO.setOutSpeed(meanV);
crossTurnDataRealtimePO.setQueueLength(staticQueueLengthMax);
crossTurnDataRealtimePO.setStopTimes(stopTimes);
crossTurnDataRealtimePO.setDelayTime(meanDelayInt);
crossTurnDataRealtimePO.setSturation(laneSaturation);
crossTurnDataRealtimePO.setVehheadDist(eventList.getMeanLen());
crossTurnDataRealtimePO.setVehheadTime(eventList.getTimeHeadwaySectionMean());
crossTurnDataRealtimePO.setQuality(10.0);
crossTurnDataRealtimePO.setNoStopRate(eventList.getLaneNoStopRate());
crossTurnDataRealtimePO.setOneStopRate(eventList.getLaneOneStopRate());
crossTurnDataRealtimePO.setTwoStopRate(eventList.getLaneTwoStopRate());
crossTurnDataRealtimePO.setThreeStopRate(eventList.getLaneThreeStopRate());
crossTurnDataRealtimePO.setEffusionRate(overflowRate);
crossTurnDataRealtimePO.setGreenLightEfficiency(greenLightEfficiency);
return crossTurnDataRealtimePO;
}
public CrossLaneDataRealTimePO convert2CrossLaneDataRealTimePO(LanePeriodicDataDTO.EventList eventList, CrossBaseLaneInfoPO laneInfoPO, Date startDate) {
DecimalFormat decimalFormat = new DecimalFormat("#.##");
String crossId = laneInfoPO.getCrossId();
// todo 路口状态
int trafficFlow = eventList.getTrafficFlow();
double meanV = Double.valueOf(decimalFormat.format(eventList.getMeanV()));
double staticQueueLengthMax = Double.valueOf(decimalFormat.format(eventList.getStaticQueueLengthMax()));
double staticQueueLengthMin = Double.valueOf(decimalFormat.format(eventList.getStaticQueueLengthMin()));
double stopTimes = eventList.getMeanStopsNumber();
double meanDelay = eventList.getMeanDelay();
Integer meanDelayInt = Double.valueOf(meanDelay).intValue();
double laneSaturation = Double.valueOf(decimalFormat.format(eventList.getLaneSaturation()));
Integer batchTime = Integer.valueOf(String.valueOf(startDate.getTime()).substring(0, 10));
Double noStopRate = Double.valueOf(decimalFormat.format(eventList.getLaneNoStopRate()));
Double oneStopRate = Double.valueOf(decimalFormat.format(eventList.getLaneOneStopRate()));
Double twoStopRate = Double.valueOf(decimalFormat.format(eventList.getLaneTwoStopRate()));
Double threeStopRate = Double.valueOf(decimalFormat.format(eventList.getLaneThreeStopRate()));
Double timeHeadwaySectionMean = Double.valueOf(decimalFormat.format(eventList.getTimeHeadwaySectionMean()));
Double meanLen = Double.valueOf(decimalFormat.format(eventList.getMeanLen()));
Double overflowRate = Double.valueOf(decimalFormat.format(eventList.getOverflowRate()));
Double greenLightEfficiency = Double.valueOf(decimalFormat.format(eventList.getGreenLightEfficiency()));
Double timeOccupancy = Double.valueOf(decimalFormat.format(eventList.getTimeOccupancy()));
Double vehicleNumsRatioMean = Double.valueOf(decimalFormat.format(eventList.getVehicleNumsRatioMean()));
Double vehicleLengthRatioMean = Double.valueOf(decimalFormat.format(eventList.getVehicleLengthRatioMean()));
CrossLaneDataRealTimePO crossLaneDataRealTimePO = new CrossLaneDataRealTimePO();
crossLaneDataRealTimePO.setId(laneInfoPO.getId());
crossLaneDataRealTimePO.setCrossId(crossId);
crossLaneDataRealTimePO.setFlow(trafficFlow);
crossLaneDataRealTimePO.setSpeed(meanV);
crossLaneDataRealTimePO.setInSpeed(meanV);
crossLaneDataRealTimePO.setOutSpeed(meanV);
crossLaneDataRealTimePO.setQueueLength(staticQueueLengthMax);
crossLaneDataRealTimePO.setStopTimes(stopTimes);
crossLaneDataRealTimePO.setDelayTime(meanDelayInt);
crossLaneDataRealTimePO.setCapacity(trafficFlow);
crossLaneDataRealTimePO.setSturation(laneSaturation);
crossLaneDataRealTimePO.setVehheadDist(meanLen);
crossLaneDataRealTimePO.setVehheadTime(timeHeadwaySectionMean);
crossLaneDataRealTimePO.setQuality(10.0);
crossLaneDataRealTimePO.setNoStopRate(noStopRate);
crossLaneDataRealTimePO.setOneStopRate(oneStopRate);
crossLaneDataRealTimePO.setTwoStopRate(twoStopRate);
crossLaneDataRealTimePO.setThreeStopRate(threeStopRate);
crossLaneDataRealTimePO.setBatchTime(batchTime);
crossLaneDataRealTimePO.setStartTime(startDate);
crossLaneDataRealTimePO.setGmtCreate(new Date());
crossLaneDataRealTimePO.setGmtModified(new Date());
crossLaneDataRealTimePO.setEffusionRate(overflowRate);
crossLaneDataRealTimePO.setGreenLightEfficiency(greenLightEfficiency);
crossLaneDataRealTimePO.setTimeOccupancy(timeOccupancy);
crossLaneDataRealTimePO.setVehicleNumsRatioMean(vehicleNumsRatioMean);
crossLaneDataRealTimePO.setVehicleLengthRatioMean(vehicleLengthRatioMean);
crossLaneDataRealTimePO.setNonMotorFlow(eventList.getNonMotorFlow());
crossLaneDataRealTimePO.setV85(eventList.getV85());
crossLaneDataRealTimePO.setTrafficFlowA(eventList.getTrafficFlowA());
crossLaneDataRealTimePO.setTrafficFlowB(eventList.getTrafficFlowB());
crossLaneDataRealTimePO.setTrafficFlowC(eventList.getTrafficFlowC());
return crossLaneDataRealTimePO;
}
}
package net.wanji.datacenter.pojo.dto;
import lombok.Data;
import java.util.List;
@Data
public class CrossEventDTO {
private Integer dir;
private String rid;
//该路段的结束路口
private String crossId;
private Double index;
private String indexName;
// 501畅通 502轻微拥堵 503中度拥堵 504重度拥堵
private String congestionCode;
private String timestamp;
private Long globalTimeStamp;
private Long startTime;
private Long endTime;
private Integer duration;
// 事件序列号
private String eventSerialNumber;
// 检测时间
private Long detectTime;
private List<CrossEventDTO> details;
private String msgType;
// 失衡方向
private Integer unbalanceDir;
// 路灯结束时排队长度
private Double greenEndQueueLength;
// 非协调方向饱和度
private Double noCoordSaturation;
// 协调方向行程时间
private Double transitTime;
// 协调方向自由流时间
private Double freeTime;
}
package net.wanji.datacenter.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import net.wanji.databus.po.CrossDataRealtimePO;
import java.util.List;
/**
* @author duanruiming
* @date 2024/11/15 20:17
*/
@Data
public class CrossPeriodDataDTO {
/**
* 车道事件集合
*/
@JsonProperty("eventList")
private List<CrossDataRealtimePO> eventList;
/**
* 车道数量
*/
private Integer laneNum;
/**
* 全域编号
*/
private String orgCode;
/**
* 数据生成时间: yyyy-MM-dd HH:mm:ss:SSS
*/
private String timeStamp;
}
package net.wanji.datacenter.pojo.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
......@@ -16,7 +19,7 @@ public class LanePeriodicDataDTO {
* 车道事件集合
*/
@JsonProperty("eventList")
private List<EventList> eventList;
private List<CrossLaneDataRealTimeDTO> eventList;
/**
* 车道数量
*/
......@@ -31,164 +34,174 @@ public class LanePeriodicDataDTO {
private String timeStamp;
@Data
public static class EventList {
/**
* 最大动态排队长度
*/
@JsonProperty("dynamic_queue_length_max")
private double dynamicQueueLengthMax;
/**
* 最小动态排队长度
*/
@JsonProperty("dynamic_queue_length_min")
private double dynamicQueueLengthMin;
/**
* 绿灯有效利用率
*/
@JsonProperty("green_light_efficiency")
private double greenLightEfficiency;
/**
* 车道号(路网数据)
*/
@JsonProperty("laneId")
private String laneId;
/**
* 车道通行能力
*/
@JsonProperty("lane_capacity")
private int laneCapacity;
/**
* 车道流率
*/
@JsonProperty("lane_flow_rate")
private double laneFlowRate;
/**
* 不停车率
*/
@JsonProperty("lane_no_stop_rate")
private double laneNoStopRate;
/**
* 一次停车率
*/
@JsonProperty("lane_one_stop_rate")
private double laneOneStopRate;
/**
* 车道饱和度
*/
@JsonProperty("lane_saturation")
private double laneSaturation;
/**
* 车道饱和流率
*/
@JsonProperty("lane_saturation_flow_rate")
private int laneSaturationFlowRate;
/**
* 三次停车率
*/
@JsonProperty("lane_three_stop_rate")
private double laneThreeStopRate;
/**
* 二次停车率
*/
@JsonProperty("lane_two_stop_rate")
private double laneTwoStopRate;
/**
* 绿灯结束排队长度
*/
@JsonProperty("light_green_finish_queue_length")
private double lightGreenFinishQueueLength;
/**
* 绿灯起亮排队长度
*/
@JsonProperty("light_green_start_queue_length")
private double lightGreenStartQueueLength;
/**
* 平均延误
*/
@JsonProperty("mean_delay")
private double meanDelay;
/**
* 平均停车次数
*/
@JsonProperty("mean_stops_number")
private int meanStopsNumber;
/**
* 平均点速度
*/
@JsonProperty("mean_v")
private double meanV;
/**
* 平均车长(米)
*/
@JsonProperty("mean_len")
private double meanLen;
/**
* 最大静态排队长度
*/
@JsonProperty("static_queue_length_max")
private double staticQueueLengthMax;
/**
* 最小静态排队长度
*/
@JsonProperty("static_queue_length_min")
private double staticQueueLengthMin;
/**
* 时间占有率
*/
@JsonProperty("time_occupancy")
private double timeOccupancy;
/**
* 自然流量
*/
@JsonProperty("traffic_flow")
private int trafficFlow;
@JsonProperty("traffic_flow_A")
public static class CrossLaneDataRealTimeDTO {
// 神思-方向(0:北 1:东北 2:东 3:东南 4:南 5:西南 6:西 7:西北)
private Integer dir;
// 神思-车道顺序(面向路口从左往右)
private Integer lane_num;
// 神思-进出口类型(0:进口 1:出口 2:缓冲区)
private Integer entry_type;
@ApiModelProperty(
name = "车道编号",
notes = ""
)
private String id;
@ApiModelProperty(
name = "路口编号",
notes = ""
)
private String crossId;
@ApiModelProperty(
name = "交通流量(辆)",
notes = ""
)
private Integer flow;
@ApiModelProperty(
name = "平均速度(km/h)",
notes = ""
)
private Double speed;
@ApiModelProperty(
name = "驶入速度(km/h)",
notes = ""
)
private Double inSpeed;
@ApiModelProperty(
name = "驶出速度(km/h)",
notes = ""
)
private Double outSpeed;
@ApiModelProperty(
name = "排队长度(米)",
notes = ""
)
private Double queueLength;
@ApiModelProperty(
name = "停车次数",
notes = ""
)
private Double stopTimes;
@ApiModelProperty(
name = "延误时间",
notes = ""
)
private Integer delayTime;
@ApiModelProperty(
name = "通行能力(辆/某一时段内最大过车数),通行能力=自然流量",
notes = ""
)
private Integer capacity;
@ApiModelProperty(
name = "饱和度",
notes = ""
)
private Double sturation;
@ApiModelProperty(
name = "车头间距(米)",
notes = ""
)
private Double vehheadDist;
@ApiModelProperty(
name = "车头时距(秒)",
notes = ""
)
private Double vehheadTime;
@ApiModelProperty(
name = "可信度(0-1)",
notes = ""
)
private Double quality;
@ApiModelProperty(
name = "不停车率",
notes = ""
)
private Double noStopRate;
@ApiModelProperty(
name = "一次停车率",
notes = ""
)
private Double oneStopRate;
@ApiModelProperty(
name = "二次停车率",
notes = ""
)
private Double twoStopRate;
@ApiModelProperty(
name = "三次停车率",
notes = ""
)
private Double threeStopRate;
@ApiModelProperty(
name = "开始时间",
notes = ""
)
private Date startTime;
@ApiModelProperty(
name = "采集时间(10位时间戳)",
notes = ""
)
private Integer batchTime;
@ApiModelProperty(
name = "创建时间",
notes = ""
)
private Date gmtCreate;
@ApiModelProperty(
name = "修改时间",
notes = ""
)
private Date gmtModified;
@ApiModelProperty(
value = "溢流率",
notes = ""
)
private Double effusionRate;
@ApiModelProperty(
value = "绿灯有效利用率",
notes = ""
)
private Double greenLightEfficiency;
@ApiModelProperty(
value = "车辆负荷比",
notes = ""
)
private Double vehicleNumsRatioMean;
@ApiModelProperty(
value = "空间长度占比",
notes = ""
)
private Double vehicleLengthRatioMean;
@ApiModelProperty(
value = "时间占有率",
notes = ""
)
private Double timeOccupancy;
@ApiModelProperty(
value = "非机动车流量",
notes = ""
)
private int nonMotorFlow;
@ApiModelProperty(
value = "85位速度(km/h)",
notes = ""
)
@TableField("v_85")
private double v85;
@ApiModelProperty(
value = "大车流量",
notes = ""
)
private int trafficFlowA;
@JsonProperty("traffic_flow_B")
@ApiModelProperty(
value = "中车流量",
notes = ""
)
private int trafficFlowB;
@JsonProperty("traffic_flow_C")
@ApiModelProperty(
value = "小车流量",
notes = ""
)
private int trafficFlowC;
/**
* 小车当量
*/
@JsonProperty("trolley_equivalent")
private int trolleyEquivalent;
/**
* 平均空间密度(长度占比)
*/
@JsonProperty("vehicle_length_ratio_mean")
private double vehicleLengthRatioMean;
/**
* 平均空间密度(车辆负荷比)
*/
@JsonProperty("vehicle_nums_ratio_mean")
private double vehicleNumsRatioMean;
/*
* 平均车头时距(s)
*/
@JsonProperty("time_headway_section_mean")
private double timeHeadwaySectionMean;
/**
* 路况信息(1:畅通2:缓行3:拥堵4:未知)
*/
@JsonProperty("traffic_information")
private int trafficInformation;
/*
* 溢流率
*/
@JsonProperty("overflow_rate")
private double overflowRate;
/**
* 非机动车流量
*/
@JsonProperty("non_motor_flow")
private int nonMotorFlow;
/**
* 85位速度(km/h)
*/
@JsonProperty("v_85")
private double v85;
}
}
......@@ -7,23 +7,17 @@ package net.wanji.datacenter.service;
public interface DataProcessService {
/**
* 数据中心发送数据, 通过远程调用调用不同的服务
*
* @param convertData
*/
void send(String topic, Object convertData);
/**
* 数据中心转换数据
*
* 车道信息处理存库
* @param originalData
* @return
* @throws Exception
*/
Object convert(String originalData) throws Exception;
void laneSave(String originalData) throws Exception;
/**
* 转换后保存数据
* 路口信息处理存库
* @param originalData
* @throws Exception
*/
void save(Object convertData) throws Exception;
void crossSave(String originalData) throws Exception;
}
package net.wanji.datacenter.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.datacenter.kafka.ProducerHandler;
import net.wanji.datacenter.pojo.dto.CrossSnapshotDataDTO;
import net.wanji.datacenter.service.DataProcessService;
import org.springframework.stereotype.Service;
/**
* @author duanruiming
* @date 2023/08/04 10:24
*/
@Slf4j
@Service(value = "crossSnapshotDataProcessService")
@RequiredArgsConstructor
public class CrossSnapshotDataProcessService implements DataProcessService {
private final ProducerHandler producerHandler;
@Override
public void send(String topic, Object convertData) {
producerHandler.send2FirstKafka(topic, convertData);
}
@Override
public Object convert(String originalData) throws Exception {
return JacksonUtils.getInstance().readValue(originalData, CrossSnapshotDataDTO.class);
}
@Override
public void save(Object convertData) throws Exception {
}
}
package net.wanji.datacenter.service.impl;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.mapper.CrossDataRealtimeMapper;
import net.wanji.databus.dao.mapper.CrossLaneDataRealTimeMapper;
import net.wanji.databus.po.CrossDataRealtimePO;
import net.wanji.databus.po.CrossLaneDataRealTimePO;
import net.wanji.databus.po.LaneInfoPO;
import net.wanji.datacenter.cache.CrossLaneInfoCache;
import net.wanji.datacenter.pojo.dto.CrossPeriodDataDTO;
import net.wanji.datacenter.pojo.dto.LanePeriodicDataDTO;
import net.wanji.datacenter.service.DataProcessService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author duanruiming
* @date 2024/11/15 19:59
*/
@Service
@Slf4j
public class DataProcessServiceImpl implements DataProcessService {
@Resource
private CrossLaneDataRealTimeMapper crossLaneDataRealTimeMapper;
@Resource
private CrossDataRealtimeMapper crossDataRealtimeMapper;
/**
* 车道信息处理存库
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void laneSave(String originalData) throws Exception {
try {
Map<String, LaneInfoPO> laneInfoMap = CrossLaneInfoCache.crossIdLaneId2Map;
LanePeriodicDataDTO LanePeriodicDataDTO = JSONObject.parseObject(originalData, LanePeriodicDataDTO.class);
String timeStamp = LanePeriodicDataDTO.getTimeStamp();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
List<LanePeriodicDataDTO.CrossLaneDataRealTimeDTO> eventList = LanePeriodicDataDTO.getEventList();
List<CrossLaneDataRealTimePO> insertList = getInsertLaneList(laneInfoMap, timeStamp, dateFormat, eventList);
//crossLaneDataRealTimeMapper.insertBatch(insertList);
} catch (Exception e) {
log.error("车道数据处理入库异常", e);
throw new Exception(e);
}
}
private static List<CrossLaneDataRealTimePO> getInsertLaneList(Map<String, LaneInfoPO> laneInfoMap, String timeStamp, SimpleDateFormat dateFormat, List<LanePeriodicDataDTO.CrossLaneDataRealTimeDTO> eventList) throws ParseException {
List<CrossLaneDataRealTimePO> insertList = new ArrayList<>();
if (!CollectionUtils.isEmpty(eventList)) {
for (LanePeriodicDataDTO.CrossLaneDataRealTimeDTO crossLaneDataRealTimeDTO : eventList) {
String crossId = crossLaneDataRealTimeDTO.getCrossId();
Integer dir = crossLaneDataRealTimeDTO.getDir();
Integer laneNum = crossLaneDataRealTimeDTO.getLane_num();
// 方向=神思dir + 1;车道号=神思laneNum + 10
String key = crossId.concat(String.valueOf(dir + 1)).concat(String.valueOf(laneNum + 10));
LaneInfoPO laneInfoPO = laneInfoMap.get(key);
if (Objects.isNull(laneInfoPO)) {
continue;
}
String laneId = laneInfoPO.getId();
crossLaneDataRealTimeDTO.setId(laneId);
CrossLaneDataRealTimePO crossLaneDataRealTime = new CrossLaneDataRealTimePO();
BeanUtils.copyProperties(crossLaneDataRealTimeDTO, crossLaneDataRealTime);
Date startDate = dateFormat.parse(timeStamp);
crossLaneDataRealTime.setStartTime(startDate);
Integer batchTime = Integer.valueOf(String.valueOf(startDate.getTime()).substring(0, 10));
crossLaneDataRealTime.setBatchTime(batchTime);
insertList.add(crossLaneDataRealTime);
}
}
return insertList;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void crossSave(String originalData) throws Exception {
try {
CrossPeriodDataDTO crossPeriodDataDTO = JSONObject.parseObject(originalData, CrossPeriodDataDTO.class);
String timeStamp = crossPeriodDataDTO.getTimeStamp();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
List<CrossDataRealtimePO> eventList = crossPeriodDataDTO.getEventList();
//crossDataRealtimeMapper.insertBatch(eventList);
} catch (Exception e) {
log.error("路口实时数据存库处理异常:{}", e);
throw new RuntimeException(e);
}
}
}
package net.wanji.datacenter.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.enums.DateStyle;
import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.databus.dao.entity.*;
import net.wanji.databus.dao.mapper.*;
import net.wanji.databus.po.*;
import net.wanji.datacenter.cache.*;
import net.wanji.datacenter.common.Constants;
import net.wanji.datacenter.constant.Constant;
import net.wanji.datacenter.constant.EventAbnormalEnum;
import net.wanji.datacenter.kafka.ConsumerHandler;
import net.wanji.datacenter.kafka.ProducerHandler;
import net.wanji.datacenter.pojo.convert.LanePeriodicDataEventListConvert;
import net.wanji.datacenter.pojo.dto.CrossDataIndexDTO;
import net.wanji.datacenter.pojo.dto.CrossEventDTO;
import net.wanji.datacenter.pojo.dto.LanePeriodicDataDTO;
import net.wanji.datacenter.pojo.dto.LineCongestion;
import net.wanji.datacenter.pojo.po.PhaseEmptyResult;
import net.wanji.datacenter.service.DataProcessService;
import net.wanji.datacenter.util.RedisUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @date 2023/03/10 10:30
* @description: 车道周期实时数据加工处理服务,优化模块实时监控操作数据
*/
@Slf4j
@Service(value = "lanePeriodicDataProcessService")
@RequiredArgsConstructor
@SuppressWarnings("all")
public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
private final ConsumerHandler consumerHandler;
private final CrossBaseLaneInfoMapper crossBaseLaneInfoMapper;
private static CrossDirDataRealtimeMapper crossDirDataRealTimeMapper;
private static CrossTurnDataRealtimeMapper crossTurnDataRealTimeMapper;
private final CrossLaneDataRealTimeMapper crossLaneDataRealTimeMapper;
private static CrossDataRealtimeMapper crossDataRealTimeMapper;
private final LanePeriodicDataEventListConvert lanePeriodicDataEventListConvert;
private final ProducerHandler producerHandler;
private static GreenwaveHistMapper greenwaveHistMapper;
private static GreenwaveRealtimeMapper greenwaveRealtimeMapper;
private static GreenwaveInfoMapper greenwaveInfoMapper;
// 五分钟周期内是否有全场红
public static final ConcurrentHashMap<String, Integer> periodHaveAllRedMap = new ConcurrentHashMap<>();
private static final Map<String, String> pedestrianMap = new HashMap<String, String>();
static {
pedestrianMap.put("11", "13NF80B5QN0");
pedestrianMap.put("12", "13NF80B5QN0");
pedestrianMap.put("13", "13NF80B5QN0");
pedestrianMap.put("14", "13NF80B5QN0");
pedestrianMap.put("21", "13NGH0B5RC0");
pedestrianMap.put("22", "13NGH0B5RC0");
pedestrianMap.put("23", "13NGH0B5RC0");
pedestrianMap.put("24", "13NGH0B5RC0");
pedestrianMap.put("31", "13NI00B5RM0");
pedestrianMap.put("32", "13NI00B5RM0");
}
@Autowired
RedisUtils redisUtils;
@Autowired
public void setCrossDataRealTimeMapper(CrossDataRealtimeMapper crossDataRealTimeMapper,
CrossDirDataRealtimeMapper crossDirDataRealTimeMapper,
CrossTurnDataRealtimeMapper crossTurnDataRealTimeMapper,
GreenwaveHistMapper greenwaveHistMapper,
GreenwaveRealtimeMapper greenwaveRealtimeMapper,
GreenwaveInfoMapper greenwaveInfoMapper) {
this.crossDataRealTimeMapper = crossDataRealTimeMapper;
this.crossDirDataRealTimeMapper = crossDirDataRealTimeMapper;
this.crossTurnDataRealTimeMapper = crossTurnDataRealTimeMapper;
this.greenwaveHistMapper = greenwaveHistMapper;
this.greenwaveRealtimeMapper = greenwaveRealtimeMapper;
this.greenwaveInfoMapper = greenwaveInfoMapper;
}
@Override
public void send(String topic, Object convertData) {
producerHandler.send2FirstKafka(topic, convertData);
producerHandler.send2SecondKafka(topic, convertData);
}
@Override
public Object convert(String originalData) throws Exception {
LanePeriodicDataDTO lanePeriodicDataPO = null;
try {
lanePeriodicDataPO = JacksonUtils.getInstance().readValue(originalData, LanePeriodicDataDTO.class);
} catch (Exception e) {
log.error("车道周期实时数据转换异常", e);
throw new Exception();
}
return lanePeriodicDataPO;
}
@Override
@Transactional
public void save(Object convertData) throws Exception {
try {
LanePeriodicDataDTO lanePeriodicDataDTO = (LanePeriodicDataDTO) convertData;
int laneNum = lanePeriodicDataDTO.getLaneNum();
List<CrossDataRealtimePO> crossDataRealtimePOS = new ArrayList<>(laneNum);
List<CrossDirDataRealtimePO> crossDirDataRealtimePOS = new ArrayList<>(laneNum);
List<CrossTurnDataRealtimePO> crossTurnDataRealtimePOS = new ArrayList<>(laneNum);
List<CrossLaneDataRealTimePO> crossLaneDataRealTimePOS = new ArrayList<>(laneNum);
List<LanePeriodicDataDTO.EventList> eventLists = lanePeriodicDataDTO.getEventList();
String timeStamp = lanePeriodicDataDTO.getTimeStamp();
Date endDate = DateUtil.parse(timeStamp, DateStyle.YYYY_MM_DD_HH_MM_SS.getValue());
Date startDate = DateUtil.offsetMinute(endDate, -5);
if (CollectionUtils.isEmpty(eventLists)) {
log.error("当前车道周期实时数据车道列表为空,参数信息:", lanePeriodicDataDTO);
throw new Exception("当前车道周期实时数据车道列表为空");
}
// 通过车道编号获取车道信息
List<String> LaneIdList = eventLists.stream()
.map(LanePeriodicDataDTO.EventList::getLaneId)
.collect(Collectors.toList());
List<CrossBaseLaneInfoPO> crossBaseLaneInfoPOS = crossBaseLaneInfoMapper.selectBatchIds(LaneIdList);
DecimalFormat decimalFormat = new DecimalFormat("#.##");
// 将kafka车道数据与路口车道数据对应,获取路口编号,方向,转向,分组计算
for (LanePeriodicDataDTO.EventList laneRealTimeItem : eventLists) {
String laneId = laneRealTimeItem.getLaneId();
// 行人车道路口流量处理
pedLaneBuild(crossLaneDataRealTimePOS, startDate, laneRealTimeItem, laneId);
// 车道数据转换到方向转向路口级别
laneConvert(crossDataRealtimePOS, crossDirDataRealtimePOS, crossTurnDataRealtimePOS, crossLaneDataRealTimePOS, startDate, crossBaseLaneInfoPOS, laneRealTimeItem, laneId);
}
pushDataToKafka(crossDirDataRealtimePOS, crossLaneDataRealTimePOS, startDate, decimalFormat);
dealCrossDataRealTime(crossDataRealtimePOS, decimalFormat, producerHandler, startDate);
dealCrossDataTurnRealTime(crossTurnDataRealtimePOS, decimalFormat, producerHandler, startDate);
} catch (Exception e) {
log.error("车道周期数据消费处理异常", e);
throw new Exception(e);
}
}
/**
* kafka数据推送
* @param crossDirDataRealtimePOS
* @param crossLaneDataRealTimePOS
* @param startDate
* @param decimalFormat
* @throws Exception
*/
private void pushDataToKafka(List<CrossDirDataRealtimePO> crossDirDataRealtimePOS, List<CrossLaneDataRealTimePO> crossLaneDataRealTimePOS, Date startDate, DecimalFormat decimalFormat) throws Exception {
Map<String, List<CrossLaneDataRealTimePO>> laneDataMap = new HashMap<>();
laneDataMap.put(Constant.REAL_TIME_LANE_DATA_KEY, crossLaneDataRealTimePOS);
producerHandler.send2FirstKafka(Constant.REAL_TIME_LANE_DATA_TOPIC, laneDataMap);
producerHandler.send2SecondKafka(Constant.REAL_TIME_LANE_DATA_TOPIC, laneDataMap);
List<CrossDirDataRealtimePO> insertCrossDirDataRealtimePOS = dealCrossDataDirRealTime(crossDirDataRealtimePOS, decimalFormat, producerHandler, startDate);
Map<String, List<CrossDirDataRealtimePO>> dirDataMap = new HashMap<>();
dirDataMap.put(Constant.REAL_TIME_DIR_DATA_KEY, insertCrossDirDataRealtimePOS);
producerHandler.send2FirstKafka(Constant.REAL_TIME_DIR_DATA_TOPIC, dirDataMap);
producerHandler.send2SecondKafka(Constant.REAL_TIME_DIR_DATA_TOPIC, dirDataMap);
}
/**
* 车道数据处理到转向方向路口级别
* @param crossDataRealtimePOS
* @param crossDirDataRealtimePOS
* @param crossTurnDataRealtimePOS
* @param crossLaneDataRealTimePOS
* @param startDate
* @param crossBaseLaneInfoPOS
* @param laneRealTimeItem
* @param laneId
*/
private void laneConvert(List<CrossDataRealtimePO> crossDataRealtimePOS, List<CrossDirDataRealtimePO> crossDirDataRealtimePOS, List<CrossTurnDataRealtimePO> crossTurnDataRealtimePOS, List<CrossLaneDataRealTimePO> crossLaneDataRealTimePOS, Date startDate, List<CrossBaseLaneInfoPO> crossBaseLaneInfoPOS, LanePeriodicDataDTO.EventList laneRealTimeItem, String laneId) {
for (CrossBaseLaneInfoPO laneInfoPO : crossBaseLaneInfoPOS) {
String id = laneInfoPO.getId();
if (StringUtils.equals(laneId, id) && Objects.equals(laneInfoPO.getType(), 2)) {
crossDataRealtimePOS.add(lanePeriodicDataEventListConvert.convert2CrossDataRealTimePO(laneRealTimeItem, laneInfoPO));
crossDirDataRealtimePOS.add(lanePeriodicDataEventListConvert.convert2CrossDirDataRealTimePO(laneRealTimeItem, laneInfoPO));
crossTurnDataRealtimePOS.add(lanePeriodicDataEventListConvert.convert2CrossTurnDataRealtimePO(laneRealTimeItem, laneInfoPO));
crossLaneDataRealTimePOS.add(lanePeriodicDataEventListConvert.convert2CrossLaneDataRealTimePO(laneRealTimeItem, laneInfoPO, startDate));
}
}
}
/**
* 行人流量作为车道数据单独处理
* @param crossLaneDataRealTimePOS
* @param startDate
* @param laneRealTimeItem
* @param laneId
*/
private void pedLaneBuild(List<CrossLaneDataRealTimePO> crossLaneDataRealTimePOS, Date startDate, LanePeriodicDataDTO.EventList laneRealTimeItem, String laneId) {
if (laneId.length() == 2) {
CrossBaseLaneInfoPO laneInfoPO = new CrossBaseLaneInfoPO();
laneInfoPO.setCrossId(pedestrianMap.get(laneId));
laneInfoPO.setId(String.join(Constant.SEPARATOR_MINUS, pedestrianMap.get(laneId), laneId));
crossLaneDataRealTimePOS.add(lanePeriodicDataEventListConvert.convert2CrossLaneDataRealTimePO(laneRealTimeItem, laneInfoPO, startDate));
}
}
private static void dealCrossDataTurnRealTime(List<CrossTurnDataRealtimePO> crossTurnDataRealtimePOS, DecimalFormat decimalFormat, ProducerHandler producerHandler, Date startDate) {
// 转向数据
List<CrossTurnDataRealtimePO> insertCrossTurnDataRealtimePOS = new ArrayList<>();
Map<String, List<CrossTurnDataRealtimePO>> crossTurnDataRealTimePOSMap = crossTurnDataRealtimePOS.stream().collect(Collectors.groupingBy(CrossTurnDataRealtimePO::getCrossId));
for (Map.Entry<String, List<CrossTurnDataRealtimePO>> entry : crossTurnDataRealTimePOSMap.entrySet()) {
String crossId = entry.getKey();
List<CrossTurnDataRealtimePO> value = entry.getValue();
Map<Integer, List<CrossTurnDataRealtimePO>> crossIdMap = value.stream().collect(Collectors.groupingBy(CrossTurnDataRealtimePO::getInDir));
for (Map.Entry<Integer, List<CrossTurnDataRealtimePO>> item : crossIdMap.entrySet()) {
Integer dir = item.getKey();
List<CrossTurnDataRealtimePO> list = item.getValue();
Map<String, List<CrossTurnDataRealtimePO>> turnMap = list.stream().collect(Collectors.groupingBy(CrossTurnDataRealtimePO::getTurnType));
dealTurnData(decimalFormat, startDate, insertCrossTurnDataRealtimePOS, crossId, turnMap);
}
}
HashMap<String, List<CrossTurnDataRealtimePO>> turnDataMap = new HashMap<>();
turnDataMap.put(Constant.REAL_TIME_TURN_DATA_KEY, insertCrossTurnDataRealtimePOS);
producerHandler.send2FirstKafka(Constant.REAL_TIME_TURN_DATA_TOPIC, turnDataMap);
producerHandler.send2SecondKafka(Constant.REAL_TIME_TURN_DATA_TOPIC, turnDataMap);
}
private static void dealTurnData(DecimalFormat decimalFormat, Date startDate, List<CrossTurnDataRealtimePO> insertCrossTurnDataRealtimePOS, String crossId, Map<String, List<CrossTurnDataRealtimePO>> turnMap) {
for (Map.Entry<String, List<CrossTurnDataRealtimePO>> turnEntry : turnMap.entrySet()) {
CrossTurnDataRealtimePO crossTurnDataRealTimePO = new CrossTurnDataRealtimePO();
List<CrossTurnDataRealtimePO> sameTurnList = turnEntry.getValue();
String turnType = turnEntry.getKey();
Integer inDir = null;
Integer outDir = null;
Integer flow = 0;
Double flowRate = 0.0;
Double speed = 0.0;
Double speedAverageTurn = 0.0;
int speedLaneCount = 0;
Double turnQueueLengthMax = 0.0;
Double stopTimes = 0.0;
Integer delayTime = 0;
Double sturation = 0.0;
Double noStopRate = 0.0;
Double oneStopRate = 0.0;
Double twoStopRate = 0.0;
Double threeStopRate = 0.0;
Double vehheadDist = 0.0;
Double vehheadTime = 0.0;
Double quality = 1.0;
Double effusionRate = 0.0;
Double greenLightEfficiency = 0.0;
for (CrossTurnDataRealtimePO crossTurnDataRealtimePO : sameTurnList) {
inDir = crossTurnDataRealtimePO.getInDir();
outDir = crossTurnDataRealtimePO.getOutDir();
turnType = crossTurnDataRealtimePO.getTurnType();
if (crossTurnDataRealtimePO.getFlow() > 0 && crossTurnDataRealtimePO.getSpeed() > 0.0) {
flow += crossTurnDataRealtimePO.getFlow();
speedAverageTurn += crossTurnDataRealtimePO.getSpeed();
++speedLaneCount;
}
turnQueueLengthMax = turnQueueLengthMax >= crossTurnDataRealtimePO.getQueueLength() ? turnQueueLengthMax : crossTurnDataRealtimePO.getQueueLength();
stopTimes += crossTurnDataRealtimePO.getStopTimes();
delayTime += crossTurnDataRealtimePO.getDelayTime();
sturation += crossTurnDataRealtimePO.getSturation();
noStopRate += crossTurnDataRealtimePO.getNoStopRate();
oneStopRate += crossTurnDataRealtimePO.getOneStopRate();
twoStopRate += crossTurnDataRealtimePO.getTwoStopRate();
threeStopRate += crossTurnDataRealtimePO.getThreeStopRate();
vehheadDist += crossTurnDataRealtimePO.getVehheadDist();
vehheadTime += crossTurnDataRealtimePO.getVehheadTime();
effusionRate += crossTurnDataRealtimePO.getEffusionRate();
greenLightEfficiency = greenLightEfficiency >= crossTurnDataRealtimePO.getGreenLightEfficiency() ? greenLightEfficiency : crossTurnDataRealtimePO.getGreenLightEfficiency();
}
// 当路口出现异常情况,没有上报数据,上报数据都是0,计算车道默认1
if (speedLaneCount == 0) {
speedLaneCount = 1;
}
StringJoiner stringJoiner = new StringJoiner("");
String crossTurnId = stringJoiner.add(crossId).add(Constants.UNDERLINE).add(String.valueOf(inDir))
.add(Constants.UNDERLINE).add(turnType).toString();
crossTurnDataRealTimePO.setId(crossTurnId);
crossTurnDataRealTimePO.setCrossId(crossId);
crossTurnDataRealTimePO.setTurnType(turnType);
crossTurnDataRealTimePO.setInDir(inDir);
crossTurnDataRealTimePO.setOutDir(outDir);
crossTurnDataRealTimePO.setFlow(flow);
crossTurnDataRealTimePO.setQueueLength(Double.valueOf(decimalFormat.format(turnQueueLengthMax)));
crossTurnDataRealTimePO.setStopTimes(Double.valueOf(decimalFormat.format(stopTimes / speedLaneCount)));
crossTurnDataRealTimePO.setDelayTime(Integer.valueOf(decimalFormat.format(delayTime / speedLaneCount)));
crossTurnDataRealTimePO.setSturation(Double.valueOf(decimalFormat.format(sturation / speedLaneCount)));
crossTurnDataRealTimePO.setSpeed(Double.valueOf(decimalFormat.format(speedAverageTurn / speedLaneCount)));
crossTurnDataRealTimePO.setInSpeed(Double.valueOf(decimalFormat.format(speedAverageTurn / speedLaneCount))); //todo
crossTurnDataRealTimePO.setOutSpeed(Double.valueOf(decimalFormat.format(speedAverageTurn / speedLaneCount))); //todo
crossTurnDataRealTimePO.setNoStopRate(Math.min(Double.valueOf(decimalFormat.format(noStopRate / speedLaneCount)), 1.0));
crossTurnDataRealTimePO.setOneStopRate(Double.valueOf(decimalFormat.format(oneStopRate / speedLaneCount)));
crossTurnDataRealTimePO.setTwoStopRate(Double.valueOf(decimalFormat.format(twoStopRate / speedLaneCount)));
crossTurnDataRealTimePO.setThreeStopRate(Double.valueOf(decimalFormat.format(threeStopRate / speedLaneCount)));
crossTurnDataRealTimePO.setVehheadDist(Double.valueOf(decimalFormat.format(vehheadDist / speedLaneCount)));
crossTurnDataRealTimePO.setVehheadTime(Double.valueOf(decimalFormat.format(vehheadTime / speedLaneCount)));
crossTurnDataRealTimePO.setQuality(Double.valueOf(decimalFormat.format(quality)));
Integer batchTime = Integer.valueOf(String.valueOf(startDate.getTime()).substring(0, 10));
crossTurnDataRealTimePO.setBatchTime(batchTime);
crossTurnDataRealTimePO.setStartTime(startDate);
crossTurnDataRealTimePO.setGmtCreate(new Date());
crossTurnDataRealTimePO.setGmtModified(new Date());
crossTurnDataRealTimePO.setEffusionRate(Double.valueOf(decimalFormat.format(effusionRate / speedLaneCount)));
crossTurnDataRealTimePO.setGreenLightEfficiency(Double.valueOf(decimalFormat.format(greenLightEfficiency)));
// 默认速度
Double turnFreeFlowSpeed = WeekTurnFreeFlowSpeedCache.crossTurnFreeFlowSpeedMap.get(crossTurnId);
if (Objects.isNull(turnFreeFlowSpeed) || turnFreeFlowSpeed == 0.0) {
turnFreeFlowSpeed = 60.0;
}
if (speedAverageTurn == 0.0) {
speedAverageTurn = turnFreeFlowSpeed;
}
// 当前方向的进口延时指数 自由流速度/实际速度
Double turnDelayTimeIndex = turnFreeFlowSpeed / (speedAverageTurn / speedLaneCount);
int status = getDirStatus(turnDelayTimeIndex);
crossTurnDataRealTimePO.setStatus(status);
crossTurnDataRealTimePO.setTrafficIndex(Double.valueOf(decimalFormat.format(turnDelayTimeIndex)));
// 计算转向持续时间
if (status != 1) {
CrossTurnDataRealtimePO crossTurnDataRealTimePO4DB = getCrossTurnDataRealTimePO(crossId, turnType);
if (Objects.nonNull(crossTurnDataRealTimePO4DB)) {
Date startTime = crossTurnDataRealTimePO4DB.getStartTime();
crossTurnDataRealTimePO.setStartTime(startTime);
Date gmtCreate = crossTurnDataRealTimePO4DB.getGmtCreate();
crossTurnDataRealTimePO.setGmtCreate(gmtCreate);
}
}
insertCrossTurnDataRealtimePOS.add(crossTurnDataRealTimePO);
}
}
private List<CrossDirDataRealtimePO> dealCrossDataDirRealTime(List<CrossDirDataRealtimePO> crossDirDataRealtimePOS,
DecimalFormat decimalFormat, ProducerHandler producerHandler, Date startDate) throws Exception {
// 方向数据
List<CrossDirDataRealtimePO> insertCrossDirDataRealtimePOS = new ArrayList<>();
Map<String, List<CrossDirDataRealtimePO>> crossDirDataRealTimePOSMap = crossDirDataRealtimePOS.stream()
.collect(Collectors.groupingBy(CrossDirDataRealtimePO::getCrossId));
for (Map.Entry<String, List<CrossDirDataRealtimePO>> entry : crossDirDataRealTimePOSMap.entrySet()) {
String crossId = entry.getKey();
List<CrossDirDataRealtimePO> value = entry.getValue();
Map<Integer, List<CrossDirDataRealtimePO>> crossIdMap = value.stream()
.collect(Collectors.groupingBy(CrossDirDataRealtimePO::getDirType));
Double congestionIndex = 0.0;
Double spilloverIndex = 0.0;
Double saturationAverage = 0.0;
Double saturationSum = 0.0;
String unbalanceDirs = "";
String congestionDirs = "";
String spilloverDirs = "";
List<Double> delayTimeList = new ArrayList<>();
for (Map.Entry<Integer, List<CrossDirDataRealtimePO>> dirEntry : crossIdMap.entrySet()) {
CrossDirDataRealtimePO crossDirDataRealTimePO = new CrossDirDataRealtimePO();
Integer dir = dirEntry.getKey();
List<CrossDirDataRealtimePO> dirList = dirEntry.getValue();
// 每个方向计算交通流量累加,筛选最大停车长度
Integer flow = 0;
Double speedSum = 0.0;
int speedLaneCount = 0; // 车道速度大于0的车道数量
Double dirQueueLengthMax = 0.0;
Double dirQueueLengthMin = 0.0;
Double stopTimes = 0.0;
Integer delayTime = 0;
Integer capacity = 0;
Double noStopRate = 0.0;
Double oneStopRate = 0.0;
Double twoStopRate = 0.0;
Double threeStopRate = 0.0;
Double effusionRate = 0.0;
Double greenLightEfficiency = 0.0;
for (CrossDirDataRealtimePO crossDirDataRealtimePOEntry : dirList) {
if (crossDirDataRealtimePOEntry.getSpeed() > 0 && crossDirDataRealtimePOEntry.getFlow() > 0) {
speedSum += crossDirDataRealtimePOEntry.getSpeed();
++speedLaneCount;
}
flow += crossDirDataRealtimePOEntry.getFlow();
dirQueueLengthMax = dirQueueLengthMax >= crossDirDataRealtimePOEntry.getQueueLength() ? dirQueueLengthMax : crossDirDataRealtimePOEntry.getQueueLength();
dirQueueLengthMin = dirQueueLengthMin <= crossDirDataRealtimePOEntry.getQueueLength() ? dirQueueLengthMin : crossDirDataRealtimePOEntry.getQueueLength();
stopTimes += crossDirDataRealtimePOEntry.getStopTimes();
delayTime += crossDirDataRealtimePOEntry.getDelayTime();
noStopRate += crossDirDataRealtimePOEntry.getNoStopRate();
oneStopRate += crossDirDataRealtimePOEntry.getOneStopRate();
twoStopRate += crossDirDataRealtimePOEntry.getTwoStopRate();
threeStopRate += crossDirDataRealtimePOEntry.getThreeStopRate();
capacity += crossDirDataRealtimePOEntry.getCapacity();
effusionRate += crossDirDataRealtimePOEntry.getEffusionRate() == null ? 0.0 : crossDirDataRealtimePOEntry.getEffusionRate();
greenLightEfficiency = greenLightEfficiency >= crossDirDataRealtimePOEntry.getGreenLightEfficiency() ? greenLightEfficiency : crossDirDataRealTimePO.getGreenLightEfficiency();
}
// 通过方向七天流量最大值计算饱和度
Double dirSaturation = getDirSaturation(crossId, dir, (double) flow);
crossDirDataRealTimePO.setSturation((Double.valueOf(decimalFormat.format(dirSaturation))));
// 平均饱和度
Double dirFlowAvg = CrossDirWeekAvgFlowCache.crossDirWeekAvgFlowMap.get(crossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)));
if (Objects.nonNull(dirFlowAvg)) {
saturationAverage = flow / dirFlowAvg;
}
Double dirLoadBalance = Math.pow((dirSaturation - saturationAverage) * (dirSaturation - saturationAverage), 2);
// 所有方向饱和度平方后求和
saturationSum += (dirSaturation - saturationAverage) * (dirSaturation - saturationAverage);
StringJoiner stringJoiner = new StringJoiner("");
stringJoiner.add(crossId).add(Constants.UNDERLINE).add(String.valueOf(dir)).add(Constants.UNDERLINE).add("1").add(Constants.UNDERLINE).add("1");
crossDirDataRealTimePO.setId(stringJoiner.toString());
crossDirDataRealTimePO.setCrossId(crossId);
crossDirDataRealTimePO.setDirType(dir);
crossDirDataRealTimePO.setInOutType(1);
double length = getDirRidLength(crossId, dir);
crossDirDataRealTimePO.setLength(Double.valueOf(decimalFormat.format(length)));
crossDirDataRealTimePO.setFlow(flow);
if (speedLaneCount == 0) {
speedLaneCount = 1;
}
Double speedAverageDir = speedSum / speedLaneCount;
crossDirDataRealTimePO.setSpeed(Double.valueOf(decimalFormat.format(speedAverageDir)));
crossDirDataRealTimePO.setQueueLength(Double.valueOf(decimalFormat.format(dirQueueLengthMax)));
crossDirDataRealTimePO.setStopTimes(Double.valueOf(decimalFormat.format(stopTimes / speedLaneCount)));
crossDirDataRealTimePO.setDelayTime(Integer.valueOf(decimalFormat.format(delayTime / speedLaneCount)));
crossDirDataRealTimePO.setCapacity(capacity);
crossDirDataRealTimePO.setEffusionRate(Double.valueOf(decimalFormat.format(effusionRate / speedLaneCount)));
crossDirDataRealTimePO.setNoStopRate(Math.min(Double.valueOf(decimalFormat.format(noStopRate / speedLaneCount)), 1.0));
crossDirDataRealTimePO.setOneStopRate(Double.valueOf(decimalFormat.format(oneStopRate / speedLaneCount)));
crossDirDataRealTimePO.setTwoStopRate(Double.valueOf(decimalFormat.format(twoStopRate / speedLaneCount)));
crossDirDataRealTimePO.setThreeStopRate(Double.valueOf(decimalFormat.format(threeStopRate / speedLaneCount)));
crossDirDataRealTimePO.setStartTime(startDate);
Integer batchTime = Integer.valueOf(String.valueOf(startDate.getTime()).substring(0, 10));
crossDirDataRealTimePO.setBatchTime(batchTime);
crossDirDataRealTimePO.setGmtCreate(new Date());
crossDirDataRealTimePO.setGmtModified(new Date());
crossDirDataRealTimePO.setEffusionRate(Double.valueOf(decimalFormat.format(effusionRate / speedLaneCount)));
crossDirDataRealTimePO.setGreenLightEfficiency(Double.valueOf(decimalFormat.format(greenLightEfficiency)));
// 当前方向的进口延时指数
Double dirDelayTimeIndex = 1.0;
Integer status = 0;
dirDelayTimeIndex = getDirDelayIndex(crossId, dir, dirQueueLengthMax, dirSaturation, speedAverageDir, dirDelayTimeIndex);
delayTimeList.add(dirDelayTimeIndex);
Integer inputLaneNum = dirList.size();
Double inputLaneIndex = (double) inputLaneNum / (double) value.size();
// 拥堵指数
Double dirCongextionIndex = inputLaneIndex * (dirDelayTimeIndex);
congestionIndex += dirCongextionIndex;
if (dirDelayTimeIndex > 1.55) { // 失衡,四个方向失衡就拥堵
unbalanceDirs = unbalanceDirs.concat(String.valueOf(dir).concat(","));
congestionDirs = congestionDirs.concat(String.valueOf(dir).concat(","));
status = 1;
}
// 溢出指数
RidInfoEntity ridInfoEntity = CrossRidInfoCache.getStartRidInfoEntity(crossId, dir);
Double crossRidLength = 0.0;
Double dirSpilloverIndex = 0.0;
if (Objects.nonNull(ridInfoEntity)) {
crossRidLength = ridInfoEntity.getLength();
dirSpilloverIndex = dirQueueLengthMax / crossRidLength;
if (dirSpilloverIndex >= 0.0 && dirSpilloverIndex <= crossRidLength / 3) {
dirSpilloverIndex = 1.0;
} else if (dirSpilloverIndex > crossRidLength / 3 && dirSpilloverIndex <= crossRidLength) {
dirSpilloverIndex = 3 * dirQueueLengthMax / crossRidLength;
}
}
spilloverIndex = spilloverIndex >= dirSpilloverIndex ? spilloverIndex : dirSpilloverIndex;
Double trafficIndexDir = dirDelayTimeIndex * 0.4 + dirCongextionIndex * 0.4 + spilloverIndex * 0.2;
if (trafficIndexDir > 1.0) {
crossDirDataRealTimePO.setTrafficIndex(Double.valueOf(decimalFormat.format(trafficIndexDir)));
} else {
crossDirDataRealTimePO.setTrafficIndex(Double.valueOf(decimalFormat.format(1)));
}
crossDirDataRealTimePO.setStatus(status);
crossDirDataRealTimePO.setDuration(5);
// 修改持续时间
setDuration(startDate, crossId, crossDirDataRealTimePO, dir, status);
// 添加相位空放
setPhaseEmpty(crossId, crossDirDataRealTimePO, dir, status);
// 用路口事件数据替换部分字段
replaceDirPartFields(crossDirDataRealTimePO, startDate);
insertCrossDirDataRealtimePOS.add(crossDirDataRealTimePO);
}
CrossRealTimeCache.crossDelayTimeIndexMap.put(crossId, delayTimeList);
Double delayTimeIndexMax = 0.0;
Double delayTimeIndexMin = 0.0;
if (!CollectionUtils.isEmpty(delayTimeList)) {
delayTimeIndexMax = delayTimeList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
delayTimeIndexMin = delayTimeList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
}
if (delayTimeIndexMin <= 0.0) {
delayTimeIndexMin = 1.0;
}
// 负载均衡度
Double loadBalance = Math.sqrt(saturationSum / crossIdMap.size());
CrossDataIndexDTO crossDataIndexDTO = new CrossDataIndexDTO();
crossDataIndexDTO.setCongestionIndex(Double.valueOf(decimalFormat.format(congestionIndex)));
crossDataIndexDTO.setCongestionDirs(congestionDirs);
crossDataIndexDTO.setUnbalanceIndex(Double.valueOf(decimalFormat.format(delayTimeIndexMax / delayTimeIndexMin)));
crossDataIndexDTO.setUnbalanceDirs(unbalanceDirs);
crossDataIndexDTO.setSpillOverIndex(Double.valueOf(decimalFormat.format(spilloverIndex)));
crossDataIndexDTO.setSpillOverDirs(spilloverDirs);
crossDataIndexDTO.setLoadBalance(Double.valueOf(decimalFormat.format(loadBalance)));
CrossRealTimeCache.crossDataIndexMap.put(crossId, crossDataIndexDTO);
}
saveGreenWaveRealTime(insertCrossDirDataRealtimePOS, decimalFormat, startDate);
return insertCrossDirDataRealtimePOS;
}
private static Double getDirSaturation(String crossId, Integer dir, double flow) {
Double dirSaturation = 0.0;
Map<String, Integer> crossWeekMaxFlowMap = CrossDirWeekMaxFlowCache.crossDirWeekMaxFlowMap;
if (Objects.nonNull(crossWeekMaxFlowMap) && !crossWeekMaxFlowMap.isEmpty()) {
Integer dirMaxFlow = crossWeekMaxFlowMap.get(crossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)));
if (Objects.isNull(dirMaxFlow) || dirMaxFlow == 0) {
dirMaxFlow = 100;
}
dirSaturation = flow / dirMaxFlow;
}
return dirSaturation;
}
private static void setPhaseEmpty(String crossId, CrossDirDataRealtimePO crossDirDataRealTimePO, Integer dir, Integer status) {
List<PhaseEmptyResult> phaseEmptyResultList = ConsumerHandler.phaseEmptyResultList;
if (!CollectionUtils.isEmpty(phaseEmptyResultList) && status == 0) {
for (PhaseEmptyResult phaseEmptyResult : phaseEmptyResultList) {
if (Objects.equals(phaseEmptyResult.getCrossId(), crossId) &&
Objects.equals(phaseEmptyResult.getDirection(), String.valueOf(dir))) {
crossDirDataRealTimePO.setStatus(5);
crossDirDataRealTimePO.setStartTime(new Date(phaseEmptyResult.getStartTime()));
}
}
}
}
private static void setDuration(Date startDate, String crossId, CrossDirDataRealtimePO crossDirDataRealTimePO, Integer dir, Integer status) {
if (status != 0) {
CrossDirDataRealtimePO crossDirDataRealTimePODB = getCrossDirDataRealTimePO(crossId, dir);
if (Objects.nonNull(crossDirDataRealTimePODB) && Objects.equals(status, crossDirDataRealTimePODB.getStatus())) {
Date startTime = crossDirDataRealTimePODB.getStartTime();
crossDirDataRealTimePO.setStartTime(startTime);
Date gmtCreate = crossDirDataRealTimePODB.getGmtCreate();
crossDirDataRealTimePO.setGmtCreate(gmtCreate);
long time = startDate.getTime() - startTime.getTime();
Integer duration = (int) time / 1000 / 60 + 5;
crossDirDataRealTimePO.setDuration(duration);
}
}
}
private static Double getDirDelayIndex(String crossId, Integer dir, Double dirQueueLengthMax, Double dirSaturation, Double speedAverageDir, Double dirDelayTimeIndex) {
if (Constants.X_DIR_LIST.contains(dir)) { // 东西方向自由流计算延时指数
Map<String, Double> crossFreeFlowSpeedMap = WeekDirFreeFlowSpeedCache.crossDirFreeFlowSpeedMap;
if (!crossFreeFlowSpeedMap.isEmpty()) {
Double freeFlowSpeed = crossFreeFlowSpeedMap.get(crossId.concat(Constants.UNDERLINE).concat(String.valueOf(dir)));
if (Objects.isNull(freeFlowSpeed) || freeFlowSpeed == 0.0) {
freeFlowSpeed = 60.0;
}
if (speedAverageDir == 0.0 || dirQueueLengthMax < 20.0) { // 夜间红灯速度小,排队长度小给自由流
speedAverageDir = freeFlowSpeed;
}
dirDelayTimeIndex = freeFlowSpeed / speedAverageDir;
}
} else { // 南北通过饱和度
dirDelayTimeIndex = getDelayTimeIndex4Saturation(dirSaturation);
}
return dirDelayTimeIndex;
}
/**
* 获取路口方向的路段长度
* @param crossId
* @param dir
* @return
*/
private double getDirRidLength(String crossId, Integer dir) {
RidInfoEntity endRidInfoEntity = CrossRidInfoCache.getEndRidInfoEntity(crossId, dir);
if (Objects.nonNull(endRidInfoEntity)) {
return endRidInfoEntity.getLength();
}
return 0.0;
}
private void replaceDirPartFields(CrossDirDataRealtimePO po, Date startDate) {
String crossId = po.getCrossId();
Integer dirType = po.getDirType();
String redisKey = crossId + ":" + dirType;
// 从 Redis 里读取当前时间窗口路口事件
long startScore = startDate.getTime() + ConsumerHandler.TTL_IN_MILLIS; // score 是当前时间向后10分钟
long endScore = startScore + 5 * 60 * 1000; // 时间窗口为5分钟
Set<Object> zSetElements = redisUtils.getZsetRange(redisKey, startScore, endScore);
if (ObjectUtil.isEmpty(zSetElements)) {
return;
}
List<CrossEventDTO> crossEventDTOList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
for (Object element : zSetElements) {
try {
// 将 JSON 字符串转换成 CrossEventDTO 对象
CrossEventDTO crossEventDTO = objectMapper.readValue(element.toString(), CrossEventDTO.class);
crossEventDTOList.add(crossEventDTO);
} catch (Exception e) {
e.printStackTrace();
}
}
if (ObjectUtil.isEmpty(crossEventDTOList)) {
return;
}
// 每一种拥堵类型取最近的一条
List<CrossEventDTO> congestEvents = crossEventDTOList.stream()
.filter(crossEventDTO -> crossEventDTO.getMsgType() != null
&& crossEventDTO.getMsgType().startsWith("50"))
.collect(Collectors.groupingBy(CrossEventDTO::getMsgType))
.entrySet().stream()
.map(entry -> entry.getValue().stream()
.max(Comparator.comparingLong(CrossEventDTO::getDetectTime))
.orElse(null))
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(congestEvents)) {
return;
}
// 找出最优事件
CrossEventDTO crossEventDTO = congestEvents.stream()
// 自定义比较器,按照 msgType 优先级排序
.sorted(Comparator.comparingInt((CrossEventDTO e) -> {
switch (e.getMsgType()) {
case "504":
return 1;
case "503":
return 2;
case "502":
return 3;
case "501":
return 4;
default:
return 5;
}
})).findFirst().get();
// 替换交通状态,交通指数,开始时间,持续时长
String msgType = crossEventDTO.getMsgType();
Integer status = convertDirMsgType(msgType);
po.setStatus(status);
Double index = crossEventDTO.getIndex();
po.setTrafficIndex(index);
if (status != 1) { // 畅通事件无开始时间和持续时长
Long startTime = crossEventDTO.getStartTime();
po.setStartTime(new Date(startTime));
Integer duration = crossEventDTO.getDuration();
po.setDuration(duration);
}
}
private Integer convertDirMsgType(String msgType) {
if (msgType.equals(EventAbnormalEnum.NO_CONGEST.getType())) {
return 1;
} else if (msgType.equals(EventAbnormalEnum.LIGHT_CONGEST.getType())) {
return 2;
} else if (msgType.equals(EventAbnormalEnum.MODERATE_CONGEST.getType())) {
return 3;
} else if (msgType.equals(EventAbnormalEnum.HEAVY_CONGEST.getType())) {
return 4;
} else {
return 5;
}
}
private void saveGreenWaveRealTime(List<CrossDirDataRealtimePO> crossDirDataRealtimePOS, DecimalFormat decimalFormat, Date date) throws Exception {
try {
Map<Integer, List<GreenwaveCrossPO>> greenWaveInfoMap = CrossGreenWaveInfoCache.greenWaveInfoMap;
if (!greenWaveInfoMap.isEmpty()) {
List<GreenwaveRealtimePO> greenwaveRealtimePOS = new ArrayList<>();
List<GreenwaveHistPO> greenwaveHistPOS = new ArrayList<>();
for (Map.Entry<Integer, List<GreenwaveCrossPO>> entry : greenWaveInfoMap.entrySet()) {
List<GreenwaveCrossPO> greenWaveCrossIds = entry.getValue();
if (!CollectionUtils.isEmpty(greenWaveCrossIds)) {
double trafficIndex = 1.0;
Double speedSum = 0.0;
Double stopTimes = 0.0;
double queueLength = 0.0;
double congRate = 0.0;
double congCount = 0.0;
Date startTime = null;
Integer delayTime = 0;
Double noparkPassRate = 0.0;
Integer greenWaveId = 0;
double speedAvg = 0.0;
double stopTimeAvg = 0.0;
double noparkPassRateAvg = 1.0;
Double greenLength = 1.0;
Double freeFlowSpeed = 0.0;
Double freeFlowSpeedAvg = 0.0;
int greenwaveCount = 0;
GreenwaveRealtimePO greenwaveRealtimePO = new GreenwaveRealtimePO();
for (GreenwaveCrossPO greenWaveCrossId : greenWaveCrossIds) {
String crossId = greenWaveCrossId.getCrossId();
Integer inDir = greenWaveCrossId.getInDir();
Integer sort = greenWaveCrossId.getSort();
greenWaveId = greenWaveCrossId.getGreenId();
if (Objects.equals(sort, 1)) { // 第一个路口不需要判断
continue;
}
GreenwaveInfoPO greenwaveInfoPO = getGreenWaveInfoPO(greenWaveId);
if (Objects.nonNull(greenwaveInfoPO)) {
greenLength = greenwaveInfoPO.getLength();
}
Map<String, Double> crossFreeFlowSpeedMap = WeekDirFreeFlowSpeedCache.crossDirFreeFlowSpeedMap;
for (CrossDirDataRealtimePO dirDataRealtimePO : crossDirDataRealtimePOS) {
String crossIdDir = dirDataRealtimePO.getCrossId();
Integer dirType = dirDataRealtimePO.getDirType();
if (StringUtils.equals(crossIdDir, crossId) && Objects.equals(inDir, dirType)) {
trafficIndex = trafficIndex > dirDataRealtimePO.getTrafficIndex() ? trafficIndex : dirDataRealtimePO.getTrafficIndex();
speedSum += dirDataRealtimePO.getSpeed();
stopTimes += dirDataRealtimePO.getStopTimes();
queueLength = queueLength > dirDataRealtimePO.getQueueLength() ? queueLength : dirDataRealtimePO.getQueueLength();
delayTime += dirDataRealtimePO.getDelayTime();
noparkPassRate += dirDataRealtimePO.getNoStopRate();
++greenwaveCount;
if (dirDataRealtimePO.getStatus() >= 3) {
++congCount;
}
freeFlowSpeed = getFreeFlowSpeed(freeFlowSpeed, crossId, crossFreeFlowSpeedMap, dirType);
}
}
speedAvg = speedSum / (greenwaveCount);
freeFlowSpeedAvg = freeFlowSpeed / (greenwaveCount);
stopTimeAvg = stopTimes / (greenwaveCount);
noparkPassRateAvg = noparkPassRate / (greenwaveCount);
congRate = congCount / greenwaveCount;
}
// 计算交通指数,并设置status
setTraffixIndexAndStatus(decimalFormat, speedAvg, freeFlowSpeedAvg, greenwaveRealtimePO);
greenwaveRealtimePO.setGreenId(greenWaveId);
greenwaveRealtimePO.setStartTime(date);
greenwaveRealtimePO.setType(1);
greenwaveRealtimePO.setSpeed(speedAvg);
if (speedAvg != 0) {
greenwaveRealtimePO.setTrvalTime((int) (greenLength / speedAvg * 3.6));
} else {
greenwaveRealtimePO.setTrvalTime(0);
}
greenwaveRealtimePO.setStopTimes(stopTimeAvg);
greenwaveRealtimePO.setQueueLength(queueLength);
greenwaveRealtimePO.setCongRate(congRate);
greenwaveRealtimePO.setDelayTime(delayTime);
greenwaveRealtimePO.setNoparkPassRate(noparkPassRateAvg);
greenwaveRealtimePO.setCordQueueRatio(queueLength / greenLength); // 空间占比
greenwaveRealtimePO.setCordReliability(1.00); // 可靠性
greenwaveRealtimePO.setUncoordinatePhaseQueue(10.00); // 非协调二次排队
greenwaveRealtimePO.setGmtCreate(new Date());
greenwaveRealtimePO.setGmtModified(new Date());
greenwaveRealtimePOS.add(greenwaveRealtimePO);
replaceGreenwavePartFields(greenwaveRealtimePO);
GreenwaveHistPO greenwaveHistPO = new GreenwaveHistPO();
BeanUtils.copyProperties(greenwaveRealtimePO, greenwaveHistPO);
greenwaveHistPOS.add(greenwaveHistPO);
greenwaveRealtimeMapper.deleteOne(greenWaveId);
}
}
if (!CollectionUtils.isEmpty(greenwaveHistPOS)) {
greenwaveHistMapper.insertBatch(greenwaveHistPOS);
greenwaveRealtimeMapper.insertBatch(greenwaveRealtimePOS);
}
}
} catch (Exception e) {
log.error("插入绿波实时历史表失败:", e);
throw new Exception(e);
}
}
private static void setTraffixIndexAndStatus(DecimalFormat decimalFormat, double speedAvg, Double freeFlowSpeedAvg, GreenwaveRealtimePO greenwaveRealtimePO) {
Double greenwaveIndex = Double.valueOf(decimalFormat.format(freeFlowSpeedAvg / speedAvg));
if (greenwaveIndex >= 10) {
greenwaveRealtimePO.setTrafficIndex(10.0);
} else if (greenwaveIndex < 10 && greenwaveIndex > 1){
greenwaveRealtimePO.setTrafficIndex(greenwaveIndex);
} else {
greenwaveRealtimePO.setTrafficIndex(1.0);
}
// 根据指数设置status
int status = 1;
if (greenwaveIndex <= 1.8) {
status = 1;
} else if (greenwaveIndex > 1.8 && greenwaveIndex <= 2.5) {
status = 2;
} else if (greenwaveIndex > 2.5 && greenwaveIndex <= 3.5) {
status = 3;
} else if (greenwaveIndex > 3.5) {
status = 4;
}
greenwaveRealtimePO.setStatus(status);
}
private static Double getFreeFlowSpeed(Double freeFlowSpeed, String crossId, Map<String, Double> crossFreeFlowSpeedMap, Integer dirType) {
String key = crossId.concat(Constants.UNDERLINE).concat(String.valueOf(dirType));
if (!crossFreeFlowSpeedMap.isEmpty() && crossFreeFlowSpeedMap.containsKey(key)) {
freeFlowSpeed += crossFreeFlowSpeedMap.get(key);
if (Objects.isNull(freeFlowSpeed) || freeFlowSpeed == 0.0) {
freeFlowSpeed = 60.0;
}
}
return freeFlowSpeed;
}
private void replaceGreenwavePartFields(GreenwaveRealtimePO po) {
String redisKey = "line_congestion_sink";
Date startTime = po.getStartTime();
// 从 Redis 里读取当前时间窗口路口事件
long startScore = startTime.getTime() + ConsumerHandler.TTL_IN_MILLIS; // score 是当前时间之后10分钟
long endScore = startScore + 5 * 60 * 1000; // 时间窗口为5分钟
Set<Object> zSetElements = redisUtils.getZsetRange(redisKey, startScore, endScore);
if (ObjectUtil.isEmpty(zSetElements)) {
return;
}
List<LineCongestion> dtoList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
for (Object element : zSetElements) {
try {
// 将 JSON 字符串转换成 LineCongestion 对象
LineCongestion dto = JSONObject.parseObject(element.toString(), LineCongestion.class);//objectMapper.readValue(element.toString(), LineCongestion.class);
dtoList.add(dto);
} catch (Exception e) {
e.printStackTrace();
}
}
if (ObjectUtil.isEmpty(dtoList)) {
return;
}
// 取最新的一条
Optional<LineCongestion> latest = dtoList.stream().filter(o->Objects.equals(po.getGreenId(),o.getGreenWaveId()))
.max(Comparator.comparingLong(LineCongestion::getDetectTime));
LineCongestion lineCongestion = latest.orElse(null);
if (ObjectUtil.isEmpty(lineCongestion)) {
return;
}
// 替换指数
po.setTrafficIndex(lineCongestion.getIndex());
// 替换干线旅行时间
po.setTrvalTime(lineCongestion.getTransitTime()==null?0:lineCongestion.getTransitTime().intValue());
// 替换干线旅行速度
po.setSpeed(lineCongestion.getSpeed());
// 替换状态
String congestionType = lineCongestion.getCongestionType();
if (EventAbnormalEnum.NO_CONGEST.getType().equals(congestionType)) {
po.setStatus(1);
} else {
po.setStatus(3);
// 如果 lineCongestion 是拥堵,替换 po 开始时间,结束时间
Long congestionStartTime = lineCongestion.getStartTime();
po.setStartTime(new Date(congestionStartTime));
Integer duration = lineCongestion.getDuration();
long congestionEndMilli = congestionStartTime + duration * 60 * 1000;
po.setGmtModified(new Date(congestionEndMilli));
}
}
/**
* 获取绿波信息
*
* @param greenWaveId
* @return
*/
private static GreenwaveInfoPO getGreenWaveInfoPO(Integer greenWaveId) {
List<GreenwaveInfoPO> greenwaveInfoPOS = greenwaveInfoMapper.selectAll();
if (!CollectionUtils.isEmpty(greenwaveInfoPOS)) {
for (GreenwaveInfoPO greenwaveInfoPO : greenwaveInfoPOS) {
if (Objects.equals(greenWaveId, greenwaveInfoPO.getId())) {
return greenwaveInfoPO;
}
}
}
return null;
}
/**
* 通过饱和度计算的延时指数计算路口方向状态
*
* @param dirDelayTimeIndex
* @return
*/
private static Integer getDirStatus(Double dirDelayTimeIndex) {
Integer status = 1;
if (dirDelayTimeIndex <= 1.25) {
status = 1;
}
if (dirDelayTimeIndex > 1.25 && dirDelayTimeIndex <= 1.55) {
status = 2;
}
if (dirDelayTimeIndex > 1.55 && dirDelayTimeIndex <= 2.0) {
status = 3;
}
if (dirDelayTimeIndex > 2 && dirDelayTimeIndex <= 2.8) {
status = 4;
}
return status;
}
private static Double getDelayTimeIndex4Saturation(Double dirSaturation) {
DecimalFormat decimalFormat = new DecimalFormat("#.#");
dirSaturation = Double.valueOf(decimalFormat.format(dirSaturation));
Double index = 1.0;
if (dirSaturation < 0.6) {
index = 1.0;
}
if (dirSaturation >= 0.6 && dirSaturation < 0.7) {
index = 1.55;
}
if (dirSaturation >= 0.7 && dirSaturation < 0.8) {
index = 2.0; // 失衡
}
if (dirSaturation >= 0.8 && dirSaturation <= 0.9) {
index = 2.28;
}
if (dirSaturation > 0.9) {
index = 2.8;
}
return index;
}
/**
* 通过拥堵指数判断路口拥堵状态
*
* @param status
* @param dirCongextionIndex
* @return
*/
private static Integer getCongextionStatus(Double dirCongextionIndex) {
Integer status = 5; // 未知
if (dirCongextionIndex <= 1) {
status = 1; // 畅通
}
if (dirCongextionIndex > 1 && dirCongextionIndex <= 3) {
status = 2; // 缓行
}
if (dirCongextionIndex > 2 && dirCongextionIndex < 3) {
status = 3; // 拥堵
}
if (dirCongextionIndex >= 3) {
status = 4;
}
return status;
}
private void dealCrossDataRealTime(List<CrossDataRealtimePO> crossDataRealtimePOS, DecimalFormat decimalFormat, ProducerHandler producerHandler, Date startDate) {
// 将车道转换的数据通过路口,方向,转向维度计算,存储
List<CrossDataRealtimePO> insertCrossDataRealtimePOS = new ArrayList<>();
Map<String, List<CrossDataRealtimePO>> crossDataRealTimePOSMap = crossDataRealtimePOS.stream().collect(Collectors.groupingBy(CrossDataRealtimePO::getCrossId));
for (Map.Entry<String, List<CrossDataRealtimePO>> entry : crossDataRealTimePOSMap.entrySet()) {
String crossId = entry.getKey();
List<CrossDataRealtimePO> crossList = entry.getValue();
CrossDataRealtimePO insertCrossDataRealtimePO = new CrossDataRealtimePO();
Integer status = 0;
Integer flow = 0;
Double speed = 0.0;
Double queueLengthMax = 0.0;
Double queueLengthMin = 0.0;
Double stopTimes = 0.0;
Integer delayTime = 0;
Double sturation = 0.0;
Double noStopRate = 0.0;
Double oneStopRate = 0.0;
Double twoStopRate = 0.0;
Double threeStopRate = 0.0;
Double effusionRate = 0.0;
Double greenLightEfficiency = 0.0;
Double timeOccupancy = 0.0;
Double vehicleLengthRatioMean = 0.0;
int speedLaneCount = 0;
for (CrossDataRealtimePO crossDataRealTimePO : crossList) {
// 去除车道流量为0,并且速度为0
if (crossDataRealTimePO.getFlow() > 0 && crossDataRealTimePO.getSpeed() > 0.0) {
flow += crossDataRealTimePO.getFlow();
speed += crossDataRealTimePO.getSpeed();
++speedLaneCount;
}
queueLengthMax = queueLengthMax >= crossDataRealTimePO.getQueueLength() ? queueLengthMax : crossDataRealTimePO.getQueueLength();
queueLengthMin = queueLengthMin <= crossDataRealTimePO.getQueueLength() ? queueLengthMin : crossDataRealTimePO.getQueueLength();
stopTimes += crossDataRealTimePO.getStopTimes();
delayTime += crossDataRealTimePO.getDelayTime();
sturation += crossDataRealTimePO.getSturation();
effusionRate += crossDataRealTimePO.getEffusionRate() == null ? 0.0 : crossDataRealTimePO.getEffusionRate();
effusionRate += crossDataRealTimePO.getEffusionRate();
greenLightEfficiency = greenLightEfficiency >= crossDataRealTimePO.getGreenLightEfficiency() ? greenLightEfficiency : crossDataRealTimePO.getGreenLightEfficiency();
noStopRate += crossDataRealTimePO.getNoStopRate();
oneStopRate += crossDataRealTimePO.getOneStopRate();
twoStopRate += crossDataRealTimePO.getTwoStopRate();
threeStopRate += crossDataRealTimePO.getThreeStopRate();
timeOccupancy += crossDataRealTimePO.getTimeOccupancy();
vehicleLengthRatioMean += crossDataRealTimePO.getVehicleLengthRatioMean();
}
// 当路口出现异常情况,没有上报数据,上报数据都是0,计算车道默认1
if (speedLaneCount <= 0) {
speedLaneCount = 1;
}
insertCrossDataRealtimePO.setCrossId(crossId);
insertCrossDataRealtimePO.setFlow(flow);
insertCrossDataRealtimePO.setFlowRate(Double.valueOf(decimalFormat.format(flow * 12)));
insertCrossDataRealtimePO.setSpeed(Double.valueOf(decimalFormat.format(speed / speedLaneCount)));
insertCrossDataRealtimePO.setQueueLength(Double.valueOf(decimalFormat.format(queueLengthMax)));
insertCrossDataRealtimePO.setStopTimes(Double.valueOf(decimalFormat.format(stopTimes / speedLaneCount)));
insertCrossDataRealtimePO.setDelayTime(Integer.valueOf(decimalFormat.format(delayTime / speedLaneCount)));
insertCrossDataRealtimePO.setSturation(Double.valueOf(decimalFormat.format(sturation / speedLaneCount)));
insertCrossDataRealtimePO.setEffusionRate(Double.valueOf(decimalFormat.format(effusionRate / crossList.size())));
insertCrossDataRealtimePO.setGreenLightEfficiency(Double.valueOf(decimalFormat.format(greenLightEfficiency)));
insertCrossDataRealtimePO.setNoStopRate(Math.min(Double.valueOf(decimalFormat.format(noStopRate / speedLaneCount)), 1.0));
insertCrossDataRealtimePO.setOneStopRate(Double.valueOf(decimalFormat.format(oneStopRate / speedLaneCount)));
insertCrossDataRealtimePO.setTwoStopRate(Double.valueOf(decimalFormat.format(twoStopRate / speedLaneCount)));
insertCrossDataRealtimePO.setThreeStopRate(Double.valueOf(decimalFormat.format(threeStopRate / speedLaneCount)));
CrossDataIndexDTO crossDataIndexDTO = CrossRealTimeCache.crossDataIndexMap.get(crossId);
Double congestionIndex = crossDataIndexDTO.getCongestionIndex() < 1.0 ? 1.0 : crossDataIndexDTO.getCongestionIndex();
insertCrossDataRealtimePO.setCongestionIndex(congestionIndex > 10 ? 10 : congestionIndex);
insertCrossDataRealtimePO.setIsCongestion(0);
insertCrossDataRealtimePO.setCongestionDirs(crossDataIndexDTO.getCongestionDirs() == null ? "," : crossDataIndexDTO.getCongestionDirs());
Double unbalanceIndex = crossDataIndexDTO.getUnbalanceIndex() < 1.0 ? 1.0 : crossDataIndexDTO.getUnbalanceIndex();
insertCrossDataRealtimePO.setUnbalanceIndex(unbalanceIndex > 10 ? 10 : unbalanceIndex);
insertCrossDataRealtimePO.setIsUnbalance(0);
insertCrossDataRealtimePO.setUnbalanceDirs(crossDataIndexDTO.getUnbalanceDirs() == null ? "," : crossDataIndexDTO.getUnbalanceDirs());
Double spillOverIndex = crossDataIndexDTO.getSpillOverIndex() < 1.0 ? 1.0 : crossDataIndexDTO.getSpillOverIndex();
insertCrossDataRealtimePO.setSpilloverIndex(spillOverIndex > 10 ? 10 : spillOverIndex);
insertCrossDataRealtimePO.setIsSpillover(spillOverIndex >= 2.4 ? 1 : 0);
insertCrossDataRealtimePO.setSpilloverDirs(crossDataIndexDTO.getSpillOverDirs() == null ? "," : crossDataIndexDTO.getSpillOverDirs());
// 延时指数列表
List<Double> delayTimeIndexList = CrossRealTimeCache.crossDelayTimeIndexMap.get(crossId);
// 失衡指数列表
List<Double> unbalanceList = delayTimeIndexList.stream().filter(d -> d <= 1.55).collect(Collectors.toList());
if (unbalanceList.size() == delayTimeIndexList.size()) {
status = 0; // 所有进口小于1.55,正常;
} else {
status = 1;// 有部分进口小于1.55 失衡
insertCrossDataRealtimePO.setIsUnbalance(1);
}
// 拥堵指数列表
List<Double> congestionList = delayTimeIndexList.stream().filter(d -> d > 1.55).collect(Collectors.toList());
if (congestionList.size() == delayTimeIndexList.size()) {
status = 2; // 所有路口失衡,拥堵
insertCrossDataRealtimePO.setIsCongestion(1);
}
insertCrossDataRealtimePO.setStatus(status);
if (status == 0) {
insertCrossDataRealtimePO.setType(1);
} else {
insertCrossDataRealtimePO.setType(2);
}
Double loadBalance = crossDataIndexDTO.getLoadBalance();
insertCrossDataRealtimePO.setLoadBalance(loadBalance);
insertCrossDataRealtimePO.setGmtCreate(new Date());
insertCrossDataRealtimePO.setGmtModified(new Date());
insertCrossDataRealtimePO.setStartTime(startDate);
insertCrossDataRealtimePO.setEndTime(DateUtil.offsetMinute(startDate, 5));
Integer batchTime = Integer.valueOf(String.valueOf(startDate.getTime()).substring(0, 10));
insertCrossDataRealtimePO.setBatchTime(batchTime);
insertCrossDataRealtimePO.setTimeOccupancy(Double.valueOf(decimalFormat.format(timeOccupancy / speedLaneCount)));
insertCrossDataRealtimePO.setVehicleLengthRatioMean(Double.valueOf(decimalFormat.format(vehicleLengthRatioMean / speedLaneCount)));
// 获取未清空车道数量
Integer notClearCarNums = getNotClearCarNums(crossId);
Double clearRate = CrossRealTimeCache.crossPhaseIdClearGreenMap.get(crossId);
if (Objects.isNull(clearRate)) {
clearRate = 0.0;
}
if (notClearCarNums == 0) {
clearRate = 1.0;
}
Integer allRed = periodHaveAllRedMap.get(crossId);
if (!Objects.equals(allRed, 1)) { // 无全场红
clearRate = -1.0;
}
insertCrossDataRealtimePO.setClearRate(clearRate);
insertCrossDataRealtimePO.setNotClearCarNums(notClearCarNums);
Double trafficIndex = unbalanceIndex * 0.4 + congestionIndex * 0.4 + spillOverIndex * 0.2;
insertCrossDataRealtimePO.setTrafficIndex(Double.valueOf(decimalFormat.format(trafficIndex)));
insertCrossDataRealtimePO.setDuration(5);
if (status != 0) {
CrossDataRealtimePO crossDataRealTimePO = getCrossDataRealTimePO(crossId);
if (Objects.nonNull(crossDataRealTimePO) && Objects.equals(status, crossDataRealTimePO.getStatus())) {
Date startTime = crossDataRealTimePO.getStartTime();
insertCrossDataRealtimePO.setStartTime(startTime);
Date gmtCreate = crossDataRealTimePO.getGmtCreate();
insertCrossDataRealtimePO.setGmtCreate(gmtCreate);
long time = startDate.getTime() - startTime.getTime();
Integer duration = (int) time / 1000 / 60 + 5;
insertCrossDataRealtimePO.setDuration(duration);
}
}
periodHaveAllRedMap.remove(crossId);
// 添加相位空放
if (!CollectionUtils.isEmpty(ConsumerHandler.phaseEmptyResultList) && insertCrossDataRealtimePO.getStatus() == 1) {
for (PhaseEmptyResult phaseEmptyResult : ConsumerHandler.phaseEmptyResultList) {
if (phaseEmptyResult.getCrossId().equals(crossId)) {
insertCrossDataRealtimePO.setStatus(5);
insertCrossDataRealtimePO.setStartTime(new Date(phaseEmptyResult.getStartTime()));
}
}
}
insertCrossDataRealtimePOS.add(insertCrossDataRealtimePO);
replaceCrossPartFields(insertCrossDataRealtimePO, startDate);
}
Map<String, List<CrossDataRealtimePO>> crossDataMap = new HashMap<>();
crossDataMap.put(Constant.REAL_TIME_CROSS_DATA_KEY, insertCrossDataRealtimePOS);
producerHandler.send2FirstKafka(Constant.REAL_TIME_CROSS_DATA_TOPIC, crossDataMap);
producerHandler.send2SecondKafka(Constant.REAL_TIME_CROSS_DATA_TOPIC, crossDataMap);
}
private void replaceCrossPartFields(CrossDataRealtimePO po, Date startDate) {
String crossId = po.getCrossId();
String redisKey = crossId;
String foo;
// 从 Redis 里读取当前时间窗口路口事件
long startScore = startDate.getTime() + ConsumerHandler.TTL_IN_MILLIS; // score 是当前时间向后10分钟
long endScore = startScore + 5 * 60 * 1000; // 时间窗口为5分钟
Set<Object> zSetElements = redisUtils.getZsetRange(redisKey, startScore, endScore);
if (ObjectUtil.isEmpty(zSetElements)) {
return;
}
List<CrossEventDTO> crossEventDTOList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
for (Object element : zSetElements) {
try {
// 将 JSON 字符串转换成 CrossEventDTO 对象
CrossEventDTO crossEventDTO = objectMapper.readValue(element.toString(), CrossEventDTO.class);
crossEventDTOList.add(crossEventDTO);
} catch (Exception e) {
e.printStackTrace();
}
}
if (ObjectUtil.isEmpty(crossEventDTOList)) {
return;
}
// 每一种事件类型取最近的一条
List<CrossEventDTO> crossEvents = crossEventDTOList.stream()
.filter(crossEventDTO -> crossEventDTO.getMsgType() != null)
.collect(Collectors.groupingBy(CrossEventDTO::getMsgType))
.entrySet().stream()
.map(entry -> entry.getValue().stream()
.max(Comparator.comparingLong(CrossEventDTO::getDetectTime))
.orElse(null))
.filter(Objects::nonNull)
.sorted(Comparator.comparing(CrossEventDTO::getMsgType)) // 根据事件严重程度排序
.collect(Collectors.toList());
if (ObjectUtil.isEmpty(crossEvents)) {
return;
}
// 替换路口状态,交通指数,开始持续结束时间,是否失衡拥堵溢出,失衡拥堵溢出指数,失衡拥堵溢出方向
for (CrossEventDTO crossEvent : crossEvents) {
String msgType = crossEvent.getMsgType();
Double index = crossEvent.getIndex();
Integer status = convertCrossMsgType(msgType);
Long startTime = crossEvent.getStartTime();
Long endTime = crossEvent.getEndTime();
if (msgType.equals(EventAbnormalEnum.NO_CONGEST.getType())) { // 畅通
po.setStatus(status);
po.setTrafficIndex(index);
po.setIsUnbalance(0);
po.setIsCongestion(0);
po.setIsSpillover(0);
po.setCongestionIndex(index);
po.setUnbalanceDirs("");
po.setCongestionDirs("");
po.setSpilloverDirs("");
}
if (msgType.equals(EventAbnormalEnum.MODERATE_CONGEST.getType())
|| msgType.equals(EventAbnormalEnum.HEAVY_CONGEST.getType())) { // 拥堵
po.setStatus(status);
po.setTrafficIndex(index);
Date date = new Date(startTime);
po.setStartTime(date);
Integer duration = crossEvent.getDuration();
po.setDuration(duration);
Date date1 = new Date(endTime);
po.setEndTime(date1);
po.setIsCongestion(1);
po.setCongestionIndex(index);
po.setUnbalanceDirs("");
po.setCongestionDirs(buildEventDirs(crossEvent));
po.setSpilloverDirs("");
}
if (msgType.equals(EventAbnormalEnum.CROSS_UNBALANCE.getType())) { // 失衡
// 检查是否有拥堵
boolean hasCongest = checkHasCongest(crossEvents);
if (!hasCongest) {
// 如果之前没有拥堵,则替换为失衡状态
po.setStatus(status);
Date date = new Date(startTime);
po.setStartTime(date);
Integer duration = crossEvent.getDuration();
po.setDuration(duration);
Date date1 = new Date(endTime);
po.setEndTime(date1);
}
po.setIsUnbalance(1);
po.setUnbalanceIndex(index);
Integer unbalanceDir = crossEvent.getUnbalanceDir();
po.setUnbalanceDirs(unbalanceDir.toString());
}
if (msgType.equals(EventAbnormalEnum.CROSS_OVERFLOW.getType())) { // 溢出
po.setStatus(status);
Date date = new Date(startTime);
po.setStartTime(date);
Integer duration = crossEvent.getDuration();
po.setDuration(duration);
Date date1 = new Date(endTime);
po.setEndTime(date1);
po.setIsSpillover(1);
po.setSpilloverIndex(index);
po.setSpilloverDirs(buildEventDirs(crossEvent));
}
if (msgType.equals(EventAbnormalEnum.CROSS_DEADLOCK.getType())) { // 死锁
po.setStatus(status);
Date date = new Date(startTime);
po.setStartTime(date);
Integer duration = crossEvent.getDuration();
po.setDuration(duration);
Date date1 = new Date(endTime);
po.setEndTime(date1);
po.setIsSpillover(1);
po.setSpilloverIndex(index);
po.setSpilloverDirs(buildEventDirs(crossEvent));
}
}
}
private boolean checkHasCongest(List<CrossEventDTO> crossEvents) {
boolean hasCongest = false;
for (CrossEventDTO crossEvent : crossEvents) {
String msgType = crossEvent.getMsgType();
if (msgType.equals(EventAbnormalEnum.MODERATE_CONGEST.getType())
|| msgType.equals(EventAbnormalEnum.HEAVY_CONGEST.getType())) {
hasCongest = true;
}
}
return hasCongest;
}
private String buildEventDirs(CrossEventDTO crossEvent) {
List<CrossEventDTO> details = crossEvent.getDetails();
String dirString = details.stream()
.map(crossEventDTO -> crossEventDTO.getDir())
.filter(Objects::nonNull) // 过滤掉任何可能的 null 值
.map(String::valueOf) // 将 Integer 转换为 String
.collect(Collectors.joining(",")); // 以逗号连接
return dirString;
}
private Integer convertCrossMsgType(String msgType) {
if (msgType.equals(EventAbnormalEnum.NO_CONGEST.getType())) {
return 0;
} else if (msgType.startsWith("50")) {
return 2;
} else if (msgType.equals(EventAbnormalEnum.CROSS_UNBALANCE.getType())) {
return 1;
} else if (msgType.equals(EventAbnormalEnum.CROSS_OVERFLOW.getType())) {
return 3;
} else if (msgType.equals(EventAbnormalEnum.CROSS_DEADLOCK.getType())) {
return 4;
} else {
return 5;
}
}
/**
* 查询路口实时表是否状态一致,一致不更新开始时间
*
* @param crossId
* @return CrossDataRealtimePO
*/
private static CrossDataRealtimePO getCrossDataRealTimePO(String crossId) {
LambdaQueryWrapper<CrossDataRealtimePO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossDataRealtimePO::getCrossId, crossId);
List<CrossDataRealtimePO> crossDataRealtimePOS = crossDataRealTimeMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossDataRealtimePOS)) {
return crossDataRealtimePOS.get(0);
}
return null;
}
private static CrossDirDataRealtimePO getCrossDirDataRealTimePO(String crossId, Integer dir) {
LambdaQueryWrapper<CrossDirDataRealtimePO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossDirDataRealtimePO::getCrossId, crossId);
queryWrapper.eq(CrossDirDataRealtimePO::getDirType, dir);
List<CrossDirDataRealtimePO> crossDirDataRealtimePOS = crossDirDataRealTimeMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossDirDataRealtimePOS)) {
return crossDirDataRealtimePOS.get(0);
}
return null;
}
private static CrossTurnDataRealtimePO getCrossTurnDataRealTimePO(String crossId, String turnType) {
LambdaQueryWrapper<CrossTurnDataRealtimePO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CrossTurnDataRealtimePO::getCrossId, crossId);
queryWrapper.eq(CrossTurnDataRealtimePO::getTurnType, turnType);
List<CrossTurnDataRealtimePO> crossTurnDataRealtimePOS = crossTurnDataRealTimeMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(crossTurnDataRealtimePOS)) {
return crossTurnDataRealtimePOS.get(0);
}
return null;
}
/**
* @param crossId
* @return notClearCarNums
* @description 获取缓存中路口的绿灯未清空车辆数量
*/
private static Integer getNotClearCarNums(String crossId) {
Integer notClearCarNums = 0;
if (!CrossRealTimeCache.crossPhaseCarNumsMap.isEmpty()) {
for (Map.Entry<String, Integer> item : CrossRealTimeCache.crossPhaseCarNumsMap.entrySet()) {
String crossIdPhase = item.getKey();
if (crossIdPhase.contains(crossId)) {
notClearCarNums += item.getValue();
}
}
}
return notClearCarNums;
}
}
package net.wanji.datacenter.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.enums.DateStyle;
import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.databus.po.LaneInfoPO;
import net.wanji.datacenter.cache.CrossLaneInfoCache;
import net.wanji.datacenter.common.Constants;
import net.wanji.datacenter.pojo.dto.CrossLaneSnapshotDataDTO;
import net.wanji.datacenter.pojo.dto.LaneSnapshotDataDTO;
import net.wanji.datacenter.service.DataProcessService;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* @author duanruiming
* @date 2023/10/25 17:27
*/
@Slf4j
@Service(value = "laneSnapshotDataProcessService")
public class LaneSnapshotDataProcessService implements DataProcessService {
@Resource
RestHighLevelClient client;
@Override
public void send(String topic, Object convertData) {
}
@Override
public List<CrossLaneSnapshotDataDTO> convert(String originalData) throws Exception {
List<CrossLaneSnapshotDataDTO> result = new ArrayList<>();
try {
ObjectMapper mapper = JacksonUtils.getInstance();
LaneSnapshotDataDTO laneSnapshotDataDTO = mapper.readValue(originalData, LaneSnapshotDataDTO.class);
if (Objects.nonNull(laneSnapshotDataDTO)) {
String timeStamp = laneSnapshotDataDTO.getTimeStamp();
Date date = new SimpleDateFormat(DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()).parse(timeStamp);
Integer batchTime = Integer.valueOf(String.valueOf(date.getTime()).substring(0, 10));
List<LaneSnapshotDataDTO.EventList> eventList = laneSnapshotDataDTO.getEventList();
if (!CollectionUtils.isEmpty(eventList)) {
for (LaneSnapshotDataDTO.EventList list : eventList) {
CrossLaneSnapshotDataDTO crossLaneSnapshotDataDTO = new CrossLaneSnapshotDataDTO();
String laneId = list.getLaneId();
LaneInfoPO laneInfoPO = CrossLaneInfoCache.laneInfoMap.get(laneId);
if (Objects.nonNull(laneInfoPO)) {
crossLaneSnapshotDataDTO.setId(laneInfoPO.getCrossId().concat(timeStamp));
crossLaneSnapshotDataDTO.setCrossId(laneInfoPO.getCrossId());
crossLaneSnapshotDataDTO.setDir(laneInfoPO.getDir());
crossLaneSnapshotDataDTO.setTurn(laneInfoPO.getTurn());
crossLaneSnapshotDataDTO.setTimeStamp(batchTime);
crossLaneSnapshotDataDTO.setLaneId(laneInfoPO.getId());
crossLaneSnapshotDataDTO.setStaticQueueLength(list.getStaticQueueLength());
crossLaneSnapshotDataDTO.setTeamHeadDistance(list.getTeamHeadDistance());
crossLaneSnapshotDataDTO.setTeamTailDistance(list.getTeamTailDistance());
crossLaneSnapshotDataDTO.setDynamicQueueLength(list.getDynamicQueueLength());
crossLaneSnapshotDataDTO.setMeanSpaceHeadway(list.getMeanSpaceHeadway());
crossLaneSnapshotDataDTO.setStdSpaceHeadway(list.getStdSpaceHeadway());
crossLaneSnapshotDataDTO.setQueueNums(list.getQueueNums());
crossLaneSnapshotDataDTO.setCarNums(list.getCarNums());
crossLaneSnapshotDataDTO.setVehicleLengthRatio(list.getVehicleLengthRatio());
crossLaneSnapshotDataDTO.setVehicleNumsRatio(list.getVehicleNumsRatio());
crossLaneSnapshotDataDTO.setMeanV(list.getMeanV());
crossLaneSnapshotDataDTO.setHeadCarPosition(list.getHeadCarPosition());
crossLaneSnapshotDataDTO.setStartV(list.getStartV());
crossLaneSnapshotDataDTO.setTailCarPosition(list.getTailCarPosition());
crossLaneSnapshotDataDTO.setEndV(list.getEndV());
crossLaneSnapshotDataDTO.setOverflowNums(list.getOverflowNums());
crossLaneSnapshotDataDTO.setOverflow(list.isOverflow());
result.add(crossLaneSnapshotDataDTO);
}
}
}
}
} catch (Exception e) {
log.error("车道快照数据转换异常", e);
throw new Exception(e);
}
return result;
}
@Override
public void save(Object convertData) throws Exception {
try {
List<CrossLaneSnapshotDataDTO> list = (List<CrossLaneSnapshotDataDTO>) convertData;
for (CrossLaneSnapshotDataDTO crossLaneSnapshotDataDTO : list) {
String json = JacksonUtils.getInstance().writeValueAsString(crossLaneSnapshotDataDTO);
long timeStamp = crossLaneSnapshotDataDTO.getTimeStamp() * 1000L;
Date date = new Date(timeStamp);
String currentDateStr = new SimpleDateFormat("yyyyMMdd").format(date);
GetIndexRequest getIndexRequest = new GetIndexRequest(Constants.LANE_SNAPSHOT_DATA_ES_INDEX);
boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
if (exists) {
IndexRequest indexRequest = new IndexRequest(Constants.LANE_SNAPSHOT_DATA_ES_INDEX);
indexRequest.source(json, XContentType.JSON);
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
} else {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(Constants.LANE_SNAPSHOT_DATA_ES_INDEX);
createIndexRequest.source(json, XContentType.JSON);
CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
}
}
} catch (Exception e) {
log.error("车道快照数据存储elastic异常", e);
throw new Exception(e);
}
}
}
package net.wanji.datacenter.task;
import lombok.extern.slf4j.Slf4j;
import net.wanji.databus.dao.entity.BaseCrossSchemePO;
import net.wanji.databus.dao.entity.CrossSectionPO;
import net.wanji.databus.dao.entity.GreenwaveCrossPO;
import net.wanji.databus.dao.mapper.BaseCrossSchemeMapper;
import net.wanji.databus.dao.mapper.BaseCrossSectionMapper;
import net.wanji.datacenter.cache.*;
import net.wanji.datacenter.pojo.dto.CrossSchemePhaseDirTurnDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author duanruiming
* @description 每天凌晨更新自由流速度
* @date 2023/10/14 9:22
*/
@Component
@Slf4j
public class DataCenterTask {
@Resource
private WeekDirFreeFlowSpeedCache weekDirFreeFlowSpeedCache;
@Resource
private WeekTurnFreeFlowSpeedCache weekTurnFreeFlowSpeedCache;
@Resource
private CrossDirWeekAvgFlowCache crossDirWeekAvgFlowCache;
@Resource
private CrossDirWeekMaxFlowCache crossDirWeekMaxFlowCache;
@Resource
private BaseCrossSectionMapper baseCrossSectionMapper;
@Resource
private BaseCrossSchemeMapper baseCrossSchemeMapper;
@Scheduled(cron = "0 0 0 * * ?")
public void getWeekFreeFlowSpeed() throws Exception {
weekDirFreeFlowSpeedCache.run();
weekTurnFreeFlowSpeedCache.run();
crossDirWeekAvgFlowCache.run();
crossDirWeekMaxFlowCache.run();
}
@Scheduled(initialDelay = 1000 * 60, fixedRate = 1000 * 60 * 60)
public void getGreenWaveWidth() throws Exception {
try {
Map<Integer, List<GreenwaveCrossPO>> greenWaveInfoMap = CrossGreenWaveInfoCache.greenWaveInfoMap;
int greenwaveWidth = 100;
for (Map.Entry<Integer, List<GreenwaveCrossPO>> entry : greenWaveInfoMap.entrySet()) {
Integer greenId = entry.getKey();
Double lastCrossDistance = 0.0; // 当前路口与上一路口距离
int crossTimeOffset = 0; // 上一路口到当前路口设计速度下时间差
int greenDelayTime = 0; // 每个路口绿波开始时间
List<GreenwaveCrossPO> greenwaveCrossPOList = entry.getValue();
if (!CollectionUtils.isEmpty(greenwaveCrossPOList)) {
greenwaveWidth = calculate(greenwaveWidth, lastCrossDistance, crossTimeOffset, greenDelayTime, greenwaveCrossPOList);
}
log.info("当前绿波编号:{}, 绿波带宽:{}", greenId, greenwaveWidth);
}
} catch (Exception e) {
log.error("获取绿波带宽异常", e);
throw new Exception("获取绿波带宽异常", e);
}
}
private int calculate(int greenwaveWidth, Double lastCrossDistance, int crossTimeOffset, int greenDelayTime, List<GreenwaveCrossPO> greenwaveCrossPOList) {
for (GreenwaveCrossPO greenwaveCrossPO : greenwaveCrossPOList) {
String crossId = greenwaveCrossPO.getCrossId();
Integer sectionId = greenwaveCrossPO.getSectionId();
Integer inDir = greenwaveCrossPO.getInDir();
Integer offset = greenwaveCrossPO.getOffset();
crossTimeOffset += (int) (lastCrossDistance / (100 / 6)); // 自由流速度60
if (sectionId != null) {
CrossSectionPO crossSectionPO = baseCrossSectionMapper.selectById(sectionId);
if (Objects.nonNull(crossSectionPO)) {
Integer schemeId = crossSectionPO.getSchemeId();
BaseCrossSchemePO baseCrossSchemePO = baseCrossSchemeMapper.selectById(schemeId);
if (Objects.nonNull(baseCrossSchemePO)) {
String schemeNo = baseCrossSchemePO.getSchemeNo();
List<CrossSchemePhaseDirTurnDTO> crossSchemePhaseDirTurnDTOList = CrossSchemePhaseLightsCache.crossSchemePhaseDirTurnDTOList;
if (!CollectionUtils.isEmpty(crossSchemePhaseDirTurnDTOList)) {
// 过滤路口编号,方案号,直行或者圆饼灯,
List<CrossSchemePhaseDirTurnDTO> currenSchemeList = crossSchemePhaseDirTurnDTOList.stream().filter(po -> StringUtils.equals(crossId, po.getCrossId()) &&
StringUtils.equals(po.getSchemeNo(), schemeNo) &&
(Objects.equals(po.getLightsTurn(), 3) || Objects.equals(po.getLightsTurn(), 1))).collect(Collectors.toList());
Integer lastPhaseTime = 0; // 上一个相位的时间
for (CrossSchemePhaseDirTurnDTO dto : currenSchemeList) {
// 当前路口方案绿波方向的绿灯时间
lastPhaseTime += dto.getPhaseTime();
if (Objects.equals(inDir, dto.getLightsDir())) {
lastPhaseTime -= dto.getPhaseTime();
greenDelayTime = lastPhaseTime > greenDelayTime ? lastPhaseTime : greenDelayTime;
Integer greenWaveStartIndex = offset + greenDelayTime + crossTimeOffset;
Integer greenWaveEndIndex = offset + dto.getPhaseTime();
greenwaveWidth = Math.min(greenwaveWidth, greenWaveEndIndex - greenWaveStartIndex);
}
}
}
}
}
}
lastCrossDistance = greenwaveCrossPO.getNextCrossLen();
}
return greenwaveWidth;
}
}
//package net.wanji.datacenter.task;
//
//import lombok.extern.slf4j.Slf4j;
//import net.wanji.databus.dao.entity.BaseCrossSchemePO;
//import net.wanji.databus.dao.entity.CrossSectionPO;
//import net.wanji.databus.dao.entity.GreenwaveCrossPO;
//import net.wanji.databus.dao.mapper.BaseCrossSchemeMapper;
//import net.wanji.databus.dao.mapper.BaseCrossSectionMapper;
//import net.wanji.datacenter.cache.*;
//import net.wanji.datacenter.pojo.dto.CrossSchemePhaseDirTurnDTO;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//
//import javax.annotation.Resource;
//import java.util.List;
//import java.util.Map;
//import java.util.Objects;
//import java.util.stream.Collectors;
//
///**
// * @author duanruiming
// * @description 每天凌晨更新自由流速度
// * @date 2023/10/14 9:22
// */
//@Component
//@Slf4j
//public class DataCenterTask {
//
// @Resource
// private WeekDirFreeFlowSpeedCache weekDirFreeFlowSpeedCache;
// @Resource
// private WeekTurnFreeFlowSpeedCache weekTurnFreeFlowSpeedCache;
// @Resource
// private CrossDirWeekAvgFlowCache crossDirWeekAvgFlowCache;
// @Resource
// private CrossDirWeekMaxFlowCache crossDirWeekMaxFlowCache;
//
// @Resource
// private BaseCrossSectionMapper baseCrossSectionMapper;
// @Resource
// private BaseCrossSchemeMapper baseCrossSchemeMapper;
//
// @Scheduled(cron = "0 0 0 * * ?")
// public void getWeekFreeFlowSpeed() throws Exception {
// weekDirFreeFlowSpeedCache.run();
// weekTurnFreeFlowSpeedCache.run();
// crossDirWeekAvgFlowCache.run();
// crossDirWeekMaxFlowCache.run();
// }
//
// @Scheduled(initialDelay = 1000 * 60, fixedRate = 1000 * 60 * 60)
// public void getGreenWaveWidth() throws Exception {
// try {
// Map<Integer, List<GreenwaveCrossPO>> greenWaveInfoMap = CrossGreenWaveInfoCache.greenWaveInfoMap;
// int greenwaveWidth = 100;
// for (Map.Entry<Integer, List<GreenwaveCrossPO>> entry : greenWaveInfoMap.entrySet()) {
// Integer greenId = entry.getKey();
// Double lastCrossDistance = 0.0; // 当前路口与上一路口距离
// int crossTimeOffset = 0; // 上一路口到当前路口设计速度下时间差
// int greenDelayTime = 0; // 每个路口绿波开始时间
// List<GreenwaveCrossPO> greenwaveCrossPOList = entry.getValue();
// if (!CollectionUtils.isEmpty(greenwaveCrossPOList)) {
// greenwaveWidth = calculate(greenwaveWidth, lastCrossDistance, crossTimeOffset, greenDelayTime, greenwaveCrossPOList);
// }
// log.info("当前绿波编号:{}, 绿波带宽:{}", greenId, greenwaveWidth);
// }
// } catch (Exception e) {
// log.error("获取绿波带宽异常", e);
// throw new Exception("获取绿波带宽异常", e);
// }
// }
//
// private int calculate(int greenwaveWidth, Double lastCrossDistance, int crossTimeOffset, int greenDelayTime, List<GreenwaveCrossPO> greenwaveCrossPOList) {
// for (GreenwaveCrossPO greenwaveCrossPO : greenwaveCrossPOList) {
// String crossId = greenwaveCrossPO.getCrossId();
// Integer sectionId = greenwaveCrossPO.getSectionId();
// Integer inDir = greenwaveCrossPO.getInDir();
// Integer offset = greenwaveCrossPO.getOffset();
// crossTimeOffset += (int) (lastCrossDistance / (100 / 6)); // 自由流速度60
// if (sectionId != null) {
// CrossSectionPO crossSectionPO = baseCrossSectionMapper.selectById(sectionId);
// if (Objects.nonNull(crossSectionPO)) {
// Integer schemeId = crossSectionPO.getSchemeId();
// BaseCrossSchemePO baseCrossSchemePO = baseCrossSchemeMapper.selectById(schemeId);
// if (Objects.nonNull(baseCrossSchemePO)) {
// String schemeNo = baseCrossSchemePO.getSchemeNo();
// List<CrossSchemePhaseDirTurnDTO> crossSchemePhaseDirTurnDTOList = CrossSchemePhaseLightsCache.crossSchemePhaseDirTurnDTOList;
// if (!CollectionUtils.isEmpty(crossSchemePhaseDirTurnDTOList)) {
//
// // 过滤路口编号,方案号,直行或者圆饼灯,
// List<CrossSchemePhaseDirTurnDTO> currenSchemeList = crossSchemePhaseDirTurnDTOList.stream().filter(po -> StringUtils.equals(crossId, po.getCrossId()) &&
// StringUtils.equals(po.getSchemeNo(), schemeNo) &&
// (Objects.equals(po.getLightsTurn(), 3) || Objects.equals(po.getLightsTurn(), 1))).collect(Collectors.toList());
//
// Integer lastPhaseTime = 0; // 上一个相位的时间
// for (CrossSchemePhaseDirTurnDTO dto : currenSchemeList) {
// // 当前路口方案绿波方向的绿灯时间
// lastPhaseTime += dto.getPhaseTime();
// if (Objects.equals(inDir, dto.getLightsDir())) {
// lastPhaseTime -= dto.getPhaseTime();
// greenDelayTime = lastPhaseTime > greenDelayTime ? lastPhaseTime : greenDelayTime;
// Integer greenWaveStartIndex = offset + greenDelayTime + crossTimeOffset;
// Integer greenWaveEndIndex = offset + dto.getPhaseTime();
// greenwaveWidth = Math.min(greenwaveWidth, greenWaveEndIndex - greenWaveStartIndex);
// }
// }
// }
// }
// }
// }
// lastCrossDistance = greenwaveCrossPO.getNextCrossLen();
// }
// return greenwaveWidth;
// }
//}
package net.wanji.datacenter.task;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.enums.DateStyle;
import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.databus.vo.LightsStatusVO;
import net.wanji.datacenter.cache.CrossRealTimeCache;
import net.wanji.datacenter.cache.CrossSchemePhaseLightsCache;
import net.wanji.datacenter.kafka.ConsumerHandler;
import net.wanji.datacenter.pojo.dto.CrossSchemePhaseDirTurnDTO;
import net.wanji.datacenter.pojo.dto.CrossSnapshotDataDTO;
import net.wanji.datacenter.service.impl.LanePeriodicDataProcessServiceImpl;
import net.wanji.feign.service.UtcFeignClients;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author duanruiming
* @date 2023/03/10 14:35
*/
@Component
@Slf4j
public class DataProcessTask {
@Resource
UtcFeignClients utcFeignClients;
private final ConcurrentHashMap<String, String> startPhaseIdMap = new ConcurrentHashMap<>();
/**
* 通过实时灯态计算路口相位绿灯清空率
* 需要注意搭接相位,目前搭接相位的两个相位当作为一个相位
* 延迟30s,否则Kafka中未消费但是运行定时任务获取消息
*/
@Scheduled(initialDelay = 30 * 1000, fixedRate = 1000)
public void calculateGreenLightsClearRate() {
try {
JsonViewObject jsonViewObject = utcFeignClients.lightStatus();
if (Objects.isNull(jsonViewObject) || jsonViewObject.getCode() != 200) {
log.error("定时任务同步信号机灯态utcService调用异常");
return;
}
List<LightsStatusVO> lightsStatusVOS = JacksonUtils.getInstance().convertValue(jsonViewObject.getContent(), new TypeReference<List<LightsStatusVO>>() {});
calculateData(lightsStatusVOS);
}catch (Exception e) {
// log.error("",e);
}
}
private void calculateData(List<LightsStatusVO> lightsStatusVOS) throws Exception {
for (LightsStatusVO lightsStatusVO : lightsStatusVOS) {
String crossId = lightsStatusVO.getCrossId();
String schemeNo = lightsStatusVO.getSchemeId();
String currentPhaseId = lightsStatusVO.getPhaseId(); // 当前相位红灯说明都是红灯,全场红
long currenSignalTime = Long.parseLong(lightsStatusVO.getSchemeStartTime());
ConcurrentHashMap<String, Integer> crossIdPhaseIdClearGreenMap = CrossRealTimeCache.crossPhaseCarNumsMap;
getClearRateCache(crossId, currentPhaseId, crossIdPhaseIdClearGreenMap);
Map<String, Object> dirLampGroupMap = lightsStatusVO.getDirLampGroupMap();
// 是否是全场红
boolean isAllRed = getAllRed(dirLampGroupMap);
// 如果全场红
if (isAllRed) {
List<CrossSchemePhaseDirTurnDTO> crossSchemePhaseDirTurnDTOList = CrossSchemePhaseLightsCache.crossSchemePhaseDirTurnDTOList;
int redTime = 2;
if (!CollectionUtils.isEmpty(crossSchemePhaseDirTurnDTOList)) {
for (CrossSchemePhaseDirTurnDTO dto : crossSchemePhaseDirTurnDTOList) {
String crossIdCache = dto.getCrossId();
String schemeNoCache = dto.getSchemeNo();
String phaseNoCache = dto.getPhaseNo();
if (StringUtils.equals(crossIdCache, crossId) && StringUtils.equals(schemeNoCache, schemeNo)
&& StringUtils.equals(currentPhaseId, phaseNoCache)) {
redTime = dto.getRedTime();
}
}
// 剩余红灯时间
if (redTime >= 1) {
--redTime;
}
Integer carNums = getCarNums(crossId, currenSignalTime + redTime * 1000L);
startPhaseIdMap.putIfAbsent(crossId, currentPhaseId);
crossIdPhaseIdClearGreenMap.put(crossId.concat(currentPhaseId), carNums);
}
LanePeriodicDataProcessServiceImpl.periodHaveAllRedMap.put(crossId, 1);
}
}
}
private static boolean getAllRed(Map<String, Object> dirLampGroupMap) {
boolean isAllRed = true;
if (!dirLampGroupMap.isEmpty()) {
for (Map.Entry<String, Object> entry : dirLampGroupMap.entrySet()) {
Map<String, String> turnLightColorMap = (Map<String, String>) entry.getValue();
for (Map.Entry<String, String> colorEntry : turnLightColorMap.entrySet()) {
String lightColor = colorEntry.getValue();
// 全场红,如果有一个绿灯就不计算 20行人跳过
String key = colorEntry.getKey();
if (Objects.equals(lightColor, "green") && !StringUtils.equals(key, "20")) {
isAllRed = false;
}
}
}
}
return isAllRed;
}
private void getClearRateCache(String crossId, String currentPhaseId, Map<String, Integer> crossIdPhaseIdClearGreenMap) throws JsonProcessingException {
int phaseSize = 0;
HashMap<String, Integer> tempMap = new HashMap<>();
for (Map.Entry<String, Integer> entry : crossIdPhaseIdClearGreenMap.entrySet()) {
String crossIdPhaseNo = entry.getKey();
if (crossIdPhaseNo.contains(crossId)) {
++phaseSize;
tempMap.put(crossId, entry.getValue());
}
}
if (startPhaseIdMap.containsValue(currentPhaseId) && phaseSize >= 2) {
double clearRate = 0.0;
for (Map.Entry<String, Integer> entry : tempMap.entrySet()) {
int value = entry.getValue() > 0 ? 1 : 0;
clearRate += (double) value / phaseSize;
}
startPhaseIdMap.remove(crossId);// 只计算一次
log.info("绿灯清空率为:" + (1 - clearRate) * 100);
CrossRealTimeCache.crossPhaseIdClearGreenMap.put(crossId, 1 - clearRate);
}
}
/**
* 通过路口编号获取主题消息中的车辆数量
* @param crossId
* @return java.lang.Integer
* @description
*/
private Integer getCarNums(String crossId, Long currenSignalTime) throws Exception {
Map<String, List<CrossSnapshotDataDTO>> crossSnapshotDataMap = ConsumerHandler.crossSnapshotDataMap;
if (!crossSnapshotDataMap.isEmpty()) {
List<CrossSnapshotDataDTO> crossSnapshotDataDTOS = crossSnapshotDataMap.get("JN050001CrossSnapshotData");
if (!CollectionUtils.isEmpty(crossSnapshotDataDTOS)) {
for (CrossSnapshotDataDTO crossSnapshotDataDTO : crossSnapshotDataDTOS) {
String timeStamp = crossSnapshotDataDTO.getTimeStamp();
Date msgDate = new SimpleDateFormat(DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()).parse(timeStamp);
Long aLong = Long.valueOf(String.valueOf(currenSignalTime).substring(0, 10));
if (aLong == msgDate.getTime() / 1000) {
List<CrossSnapshotDataDTO.EventList> eventList = crossSnapshotDataDTO.getEventList();
for (CrossSnapshotDataDTO.EventList element : eventList) {
String currentCrossId = element.getCrossId();
if (StringUtils.equals(crossId, currentCrossId)) {
return element.getCarNums();
}
}
}
}
}
}
return 0;
}
}
//package net.wanji.datacenter.task;
//
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.core.type.TypeReference;
//import lombok.extern.slf4j.Slf4j;
//import net.wanji.common.enums.DateStyle;
//import net.wanji.common.framework.rest.JsonViewObject;
//import net.wanji.common.utils.tool.JacksonUtils;
//import net.wanji.databus.vo.LightsStatusVO;
//import net.wanji.datacenter.cache.CrossRealTimeCache;
//import net.wanji.datacenter.cache.CrossSchemePhaseLightsCache;
//import net.wanji.datacenter.kafka.ConsumerHandler;
//import net.wanji.datacenter.pojo.dto.CrossSchemePhaseDirTurnDTO;
//import net.wanji.datacenter.pojo.dto.CrossSnapshotDataDTO;
//import net.wanji.datacenter.service.impl.LanePeriodicDataProcessServiceImpl;
//import net.wanji.feign.service.UtcFeignClients;
//import org.apache.commons.lang.StringUtils;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//
//import javax.annotation.Resource;
//import java.text.SimpleDateFormat;
//import java.util.*;
//import java.util.concurrent.ConcurrentHashMap;
//
///**
// * @author duanruiming
// * @date 2023/03/10 14:35
// */
//@Component
//@Slf4j
//public class DataProcessTask {
//
// @Resource
// UtcFeignClients utcFeignClients;
//
// private final ConcurrentHashMap<String, String> startPhaseIdMap = new ConcurrentHashMap<>();
//
// /**
// * 通过实时灯态计算路口相位绿灯清空率
// * 需要注意搭接相位,目前搭接相位的两个相位当作为一个相位
// * 延迟30s,否则Kafka中未消费但是运行定时任务获取消息
// */
// @Scheduled(initialDelay = 30 * 1000, fixedRate = 1000)
// public void calculateGreenLightsClearRate() {
// try {
// JsonViewObject jsonViewObject = utcFeignClients.lightStatus();
// if (Objects.isNull(jsonViewObject) || jsonViewObject.getCode() != 200) {
// log.error("定时任务同步信号机灯态utcService调用异常");
// return;
// }
//
// List<LightsStatusVO> lightsStatusVOS = JacksonUtils.getInstance().convertValue(jsonViewObject.getContent(), new TypeReference<List<LightsStatusVO>>() {});
// calculateData(lightsStatusVOS);
// }catch (Exception e) {
// // log.error("",e);
// }
// }
//
// private void calculateData(List<LightsStatusVO> lightsStatusVOS) throws Exception {
// for (LightsStatusVO lightsStatusVO : lightsStatusVOS) {
// String crossId = lightsStatusVO.getCrossId();
// String schemeNo = lightsStatusVO.getSchemeId();
// String currentPhaseId = lightsStatusVO.getPhaseId(); // 当前相位红灯说明都是红灯,全场红
// long currenSignalTime = Long.parseLong(lightsStatusVO.getSchemeStartTime());
// ConcurrentHashMap<String, Integer> crossIdPhaseIdClearGreenMap = CrossRealTimeCache.crossPhaseCarNumsMap;
// getClearRateCache(crossId, currentPhaseId, crossIdPhaseIdClearGreenMap);
// Map<String, Object> dirLampGroupMap = lightsStatusVO.getDirLampGroupMap();
// // 是否是全场红
// boolean isAllRed = getAllRed(dirLampGroupMap);
// // 如果全场红
// if (isAllRed) {
// List<CrossSchemePhaseDirTurnDTO> crossSchemePhaseDirTurnDTOList = CrossSchemePhaseLightsCache.crossSchemePhaseDirTurnDTOList;
// int redTime = 2;
// if (!CollectionUtils.isEmpty(crossSchemePhaseDirTurnDTOList)) {
// for (CrossSchemePhaseDirTurnDTO dto : crossSchemePhaseDirTurnDTOList) {
// String crossIdCache = dto.getCrossId();
// String schemeNoCache = dto.getSchemeNo();
// String phaseNoCache = dto.getPhaseNo();
// if (StringUtils.equals(crossIdCache, crossId) && StringUtils.equals(schemeNoCache, schemeNo)
// && StringUtils.equals(currentPhaseId, phaseNoCache)) {
// redTime = dto.getRedTime();
// }
// }
// // 剩余红灯时间
// if (redTime >= 1) {
// --redTime;
// }
// Integer carNums = getCarNums(crossId, currenSignalTime + redTime * 1000L);
// startPhaseIdMap.putIfAbsent(crossId, currentPhaseId);
// crossIdPhaseIdClearGreenMap.put(crossId.concat(currentPhaseId), carNums);
// }
// LanePeriodicDataProcessServiceImpl.periodHaveAllRedMap.put(crossId, 1);
// }
// }
// }
//
// private static boolean getAllRed(Map<String, Object> dirLampGroupMap) {
// boolean isAllRed = true;
// if (!dirLampGroupMap.isEmpty()) {
// for (Map.Entry<String, Object> entry : dirLampGroupMap.entrySet()) {
// Map<String, String> turnLightColorMap = (Map<String, String>) entry.getValue();
// for (Map.Entry<String, String> colorEntry : turnLightColorMap.entrySet()) {
// String lightColor = colorEntry.getValue();
// // 全场红,如果有一个绿灯就不计算 20行人跳过
// String key = colorEntry.getKey();
// if (Objects.equals(lightColor, "green") && !StringUtils.equals(key, "20")) {
// isAllRed = false;
// }
// }
// }
// }
// return isAllRed;
// }
//
// private void getClearRateCache(String crossId, String currentPhaseId, Map<String, Integer> crossIdPhaseIdClearGreenMap) throws JsonProcessingException {
// int phaseSize = 0;
// HashMap<String, Integer> tempMap = new HashMap<>();
// for (Map.Entry<String, Integer> entry : crossIdPhaseIdClearGreenMap.entrySet()) {
// String crossIdPhaseNo = entry.getKey();
// if (crossIdPhaseNo.contains(crossId)) {
// ++phaseSize;
// tempMap.put(crossId, entry.getValue());
// }
// }
// if (startPhaseIdMap.containsValue(currentPhaseId) && phaseSize >= 2) {
// double clearRate = 0.0;
// for (Map.Entry<String, Integer> entry : tempMap.entrySet()) {
// int value = entry.getValue() > 0 ? 1 : 0;
// clearRate += (double) value / phaseSize;
// }
// startPhaseIdMap.remove(crossId);// 只计算一次
// log.info("绿灯清空率为:" + (1 - clearRate) * 100);
// CrossRealTimeCache.crossPhaseIdClearGreenMap.put(crossId, 1 - clearRate);
// }
// }
//
// /**
// * 通过路口编号获取主题消息中的车辆数量
// * @param crossId
// * @return java.lang.Integer
// * @description
// */
// private Integer getCarNums(String crossId, Long currenSignalTime) throws Exception {
// Map<String, List<CrossSnapshotDataDTO>> crossSnapshotDataMap = ConsumerHandler.crossSnapshotDataMap;
// if (!crossSnapshotDataMap.isEmpty()) {
// List<CrossSnapshotDataDTO> crossSnapshotDataDTOS = crossSnapshotDataMap.get("JN050001CrossSnapshotData");
// if (!CollectionUtils.isEmpty(crossSnapshotDataDTOS)) {
// for (CrossSnapshotDataDTO crossSnapshotDataDTO : crossSnapshotDataDTOS) {
// String timeStamp = crossSnapshotDataDTO.getTimeStamp();
// Date msgDate = new SimpleDateFormat(DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()).parse(timeStamp);
// Long aLong = Long.valueOf(String.valueOf(currenSignalTime).substring(0, 10));
// if (aLong == msgDate.getTime() / 1000) {
// List<CrossSnapshotDataDTO.EventList> eventList = crossSnapshotDataDTO.getEventList();
// for (CrossSnapshotDataDTO.EventList element : eventList) {
// String currentCrossId = element.getCrossId();
// if (StringUtils.equals(crossId, currentCrossId)) {
// return element.getCarNums();
// }
// }
// }
// }
// }
// }
// return 0;
// }
//}
package net.wanji.datacenter.task;
import com.github.kokorin.jaffree.ffmpeg.FFmpeg;
import com.github.kokorin.jaffree.ffmpeg.UrlInput;
import com.github.kokorin.jaffree.ffmpeg.UrlOutput;
import lombok.extern.slf4j.Slf4j;
import net.wanji.datacenter.config.EventSaveConfiguration;
import net.wanji.datacenter.mapper.EventInfoMapper;
import net.wanji.datacenter.mapper.HoloMapper;
import net.wanji.datacenter.pojo.po.DeviceCameraPO;
import net.wanji.datacenter.pojo.po.EventInfoPO;
import net.wanji.datacenter.pojo.vo.B5LabelVO;
import net.wanji.datacenter.util.RedisUtils;
import net.wanji.datacenter.util.TimeBasedKafkaConsumer;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author Kent HAN
* @date 2023/12/15 16:41
*/
@Component
@Slf4j
public class EventTask {
@Resource
private EventInfoMapper eventInfoMapper;
@Resource
private EventSaveConfiguration eventSaveConfiguration;
@Resource
private HoloMapper holoMapper;
@Resource
RedisUtils redisUtils;
@Value("${kafka.topics.matchResultTopic}")
String matchResultTopic;
@Value("${kafka.topics.lightStatusTopic}")
String lightStatusTopic;
@Value("${kafka.producer.bootstrap.servers}")
String kafkaServers;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
20,
40,
1L,
TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(50),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
/**
* 每30分钟存储事件数据集
*/
@Scheduled(fixedDelay = 30 * 60 * 1000)
public void saveEvent() {
List<EventInfoPO> eventInfoPOList = eventInfoMapper.selectHistEvent();
// 相同 eventType 只保留一条记录
List<EventInfoPO> uniqueList = eventInfoPOList.stream()
.collect(Collectors.toMap(
EventInfoPO::getType,
Function.identity(),
(existing, replacement) -> existing))
.values().stream()
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(uniqueList)) {
return;
}
// 随机选择一条记录
Random random = new Random();
EventInfoPO eventInfoPO = uniqueList.get(random.nextInt(uniqueList.size()));
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String eventType = eventInfoPO.getType();
Date startDate = eventInfoPO.getStartTime();
String startDateStr = formatter.format(startDate);
String dateFolderName = startDateStr + "_" + eventType;
String key = dateFolderName + eventSaveConfiguration.getNegativeSample();
Long count = redisUtils.getIncr(key, 1000 * 60 * 60 * 24);
String pathToDate = eventSaveConfiguration.getRootFolder() + File.separator
+ eventSaveConfiguration.getCity() + File.separator
+ eventType + File.separator
+ dateFolderName + File.separator;
// todo 暂时建立空文件夹
makeEmptyFolders(pathToDate, count);
// 保存标签
saveLabel(eventInfoPO, pathToDate, count);
// 保存轨迹
saveKafka(eventInfoPO, pathToDate, count, matchResultTopic);
// 保存灯态
saveKafka(eventInfoPO, pathToDate, count, lightStatusTopic);
// 保存录像
Long finalCount = count;
executor.submit(() -> saveNvr(eventInfoPO, pathToDate, finalCount));
// 监控线程池占用情况
log.warn("Current Pool Size: {}. Active Threads: {}. " +
"Number of Tasks Completed: {}. Number of Tasks in Queue: {}. ",
executor.getPoolSize(), executor.getActiveCount(),
executor.getCompletedTaskCount(), executor.getQueue().size());
}
private void saveNvr(EventInfoPO eventInfoPO, String pathToDate, Long count) {
String eventId = eventInfoPO.getEventId();
String crossId = eventInfoPO.getCrossId();
Date startTimeStamp = eventInfoPO.getStartTime();
Date endTimeStamp = eventInfoPO.getEndTime();
String nvrurl = eventSaveConfiguration.getNvrurl();
// 查询路口对应的相机
List<DeviceCameraPO> deviceCameraPOList = holoMapper.selectVideoUrlsByCrossId(crossId);
if (CollectionUtils.isEmpty(deviceCameraPOList)) {
return;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
String starttimeStr = sdf.format(startTimeStamp.getTime() - 30 * 1000);
String endtimeStr = sdf.format(endTimeStamp.getTime() + 30 * 1000);
for (DeviceCameraPO deviceCameraPO : deviceCameraPOList) {
if (deviceCameraPO == null) {
continue;
}
String monitorChannel = deviceCameraPO.getMonitorChannel();
String url = nvrurl + "?channel=" + monitorChannel + "&subtype=" + eventSaveConfiguration.getSubType()
+ "&starttime=" + starttimeStr + "&endtime=" + endtimeStr;
String fileName = crossId + "-" + eventId + "-" + monitorChannel;
String pathToCount = makeSavepathToCount(pathToDate, count);
String savepath = pathToCount + File.separator
+ eventSaveConfiguration.getEvidence() + File.separator
+ eventSaveConfiguration.getVideo();
makeDirIfNotExist(savepath);
try {
FFmpeg.atPath()
.addInput(UrlInput.fromUrl(url))
.addOutput(UrlOutput.toUrl(savepath + "/" + fileName + ".mp4")
.copyAllCodecs())
.execute();
} catch (Exception e) {
log.error("[" + url + "], 获取失败 !", e);
}
}
}
private void saveKafka(EventInfoPO eventInfoPO, String pathToDate, Long count, String topic) {
Date eventTimeStampStart = eventInfoPO.getStartTime();
Date eventTimeStampEnd = eventInfoPO.getEndTime();
long start = eventTimeStampStart.getTime() - 30 * 1000;
long end = eventTimeStampEnd.getTime() + 30 * 1000;
String savepath = makeSavepathToCount(pathToDate, count);
makeDirIfNotExist(savepath);
String fileName;
if (topic.equals(lightStatusTopic)) {
fileName = eventSaveConfiguration.getLightJson();
} else {
fileName = eventSaveConfiguration.getTrackJson();
}
// 消费前30秒和后30秒的 Kafka 数据,保存到硬盘
TimeBasedKafkaConsumer.consumeMessagesAroundTimestamp(kafkaServers, topic, start, end, savepath, fileName);
}
private void saveLabel(EventInfoPO eventInfoPO, String pathToDate, Long count) {
B5LabelVO vo = new B5LabelVO();
vo.setCategory(Integer.parseInt(eventInfoPO.getCategory()));
vo.setEventType(Integer.parseInt(eventInfoPO.getType()));
String globalId = eventInfoPO.getGlobalId();
if (globalId == null) {
vo.setTargetIdList(new ArrayList<>());
} else {
List<Integer> targetList = new ArrayList<>();
targetList.add(Integer.parseInt(globalId));
vo.setTargetIdList(targetList);
}
vo.setCrossId(eventInfoPO.getCrossId());
vo.setRid(eventInfoPO.getRid());
Date eventTimeStampStart = eventInfoPO.getStartTime();
Date eventTimeStampEnd = eventInfoPO.getEndTime();
vo.setStartTime(eventTimeStampStart);
vo.setEndTime(eventTimeStampEnd);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
vo.setStartTimeDate(sdf.format(eventTimeStampStart));
vo.setEndTimeDate(sdf.format(eventTimeStampEnd));
// 默认值
vo.setLabel(-1);
String pathToCount = makeSavepathToCount(pathToDate, count);
makeDirIfNotExist(pathToCount);
String fileName = eventSaveConfiguration.getLabelJson();
try (PrintWriter writer = new PrintWriter(new File(pathToCount + File.separator + fileName))) {
// 写入列名
writer.println("category,eventType,targetIdList,crossId,rid,startTime,endTime,startTimeDate,endTimeDate," +
"label,comment");
// 写入数据
writer.println(vo.getCategory() + "," + vo.getEventType() + "," + vo.getTargetIdList() + "," + vo.getCrossId() + ","
+ vo.getRid() + "," + vo.getStartTime().getTime() + "," + vo.getEndTime().getTime() + ","
+ vo.getStartTimeDate() + "," + vo.getEndTimeDate() + "," + vo.getLabel() + "," + "");
} catch (IOException e) {
e.printStackTrace();
}
}
private String makeSavepathToCount(String pathToDate, Long count) {
return pathToDate + File.separator +
eventSaveConfiguration.getNegativeSample() + File.separator
+ count;
}
private void makeEmptyFolders(String pathToDate, Long count) {
List<String> savepathList = new ArrayList<>();
String savepath1 = pathToDate + eventSaveConfiguration.getPositiveSample();
savepathList.add(savepath1);
String pathToEvidence = pathToDate
+ eventSaveConfiguration.getNegativeSample() + File.separator
+ count + File.separator
+ eventSaveConfiguration.getEvidence() + File.separator;
String savepath2 = pathToEvidence + eventSaveConfiguration.getImage();
savepathList.add(savepath2);
String savepath3 = pathToEvidence + eventSaveConfiguration.getVision();
savepathList.add(savepath3);
for (String savepath : savepathList) {
makeDirIfNotExist(savepath);
}
}
private void makeDirIfNotExist(String savepath) {
File directory = new File(savepath);
if (!directory.exists()) {
directory.mkdirs();
}
}
@Async
@Scheduled(cron="0 0 2 * * ? ")
// 每天凌晨2点清理一星期前的数据集文件
public void cleanUpSavepath() {
String savepath = eventSaveConfiguration.getRootFolder();
long currentTime = System.currentTimeMillis();
long twoMonthsInMillis = 60L * 24 * 60 * 7 * 1000; // 大约一星期的毫秒数
File directory = new File(savepath);
if (directory.exists() && directory.isDirectory()) {
deleteOldFiles(directory, currentTime, twoMonthsInMillis);
} else {
log.error("目录不存在:" + savepath);
}
}
private void deleteOldFiles(File folder, long currentTime, long threshold) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
try {
if (file.isDirectory()) {
// 先获取目录的最后修改时间
long lastModifiedTime = file.lastModified();
// 递归删除子目录内容
deleteOldFiles(file, currentTime, threshold);
// 检查子目录是否为空,如果为空则根据之前获取的修改时间决定是否删除目录
String[] subFiles = file.list();
if (subFiles != null && subFiles.length == 0 && (currentTime - lastModifiedTime) > threshold) {
file.delete(); // 删除空目录
}
} else {
// 对于文件,获取文件的最后修改时间,然后判断是否需要删除
long lastModifiedTime = file.lastModified();
if ((currentTime - lastModifiedTime) > threshold) {
file.delete(); // 删除文件
}
}
} catch (Exception e) {
log.error("删除文件失败: " + file.getAbsolutePath(), e);
}
}
}
}
}
//package net.wanji.datacenter.task;
//
//import com.github.kokorin.jaffree.ffmpeg.FFmpeg;
//import com.github.kokorin.jaffree.ffmpeg.UrlInput;
//import com.github.kokorin.jaffree.ffmpeg.UrlOutput;
//import lombok.extern.slf4j.Slf4j;
//import net.wanji.datacenter.config.EventSaveConfiguration;
//import net.wanji.datacenter.mapper.EventInfoMapper;
//import net.wanji.datacenter.mapper.HoloMapper;
//import net.wanji.datacenter.pojo.po.DeviceCameraPO;
//import net.wanji.datacenter.pojo.po.EventInfoPO;
//import net.wanji.datacenter.pojo.vo.B5LabelVO;
//import net.wanji.datacenter.util.RedisUtils;
//import net.wanji.datacenter.util.TimeBasedKafkaConsumer;
//import org.apache.commons.collections.CollectionUtils;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//import java.io.File;
//import java.io.IOException;
//import java.io.PrintWriter;
//import java.text.SimpleDateFormat;
//import java.util.ArrayList;
//import java.util.Date;
//import java.util.List;
//import java.util.Random;
//import java.util.concurrent.LinkedBlockingQueue;
//import java.util.concurrent.ThreadPoolExecutor;
//import java.util.concurrent.TimeUnit;
//import java.util.function.Function;
//import java.util.stream.Collectors;
//
///**
// * @author Kent HAN
// * @date 2023/12/15 16:41
// */
//@Component
//@Slf4j
//public class EventTask {
//
// @Resource
// private EventInfoMapper eventInfoMapper;
//
// @Resource
// private EventSaveConfiguration eventSaveConfiguration;
//
// @Resource
// private HoloMapper holoMapper;
//
// @Resource
// RedisUtils redisUtils;
//
// @Value("${kafka.topics.matchResultTopic}")
// String matchResultTopic;
//
// @Value("${kafka.topics.lightStatusTopic}")
// String lightStatusTopic;
//
// @Value("${kafka.producer.bootstrap.servers}")
// String kafkaServers;
//
// ThreadPoolExecutor executor = new ThreadPoolExecutor(
// 20,
// 40,
// 1L,
// TimeUnit.MINUTES,
// new LinkedBlockingQueue<Runnable>(50),
// new ThreadPoolExecutor.DiscardOldestPolicy()
// );
//
// /**
// * 每30分钟存储事件数据集
// */
// @Scheduled(fixedDelay = 30 * 60 * 1000)
// public void saveEvent() {
//
// List<EventInfoPO> eventInfoPOList = eventInfoMapper.selectHistEvent();
// // 相同 eventType 只保留一条记录
// List<EventInfoPO> uniqueList = eventInfoPOList.stream()
// .collect(Collectors.toMap(
// EventInfoPO::getType,
// Function.identity(),
// (existing, replacement) -> existing))
// .values().stream()
// .collect(Collectors.toList());
//
// if (CollectionUtils.isEmpty(uniqueList)) {
// return;
// }
// // 随机选择一条记录
// Random random = new Random();
// EventInfoPO eventInfoPO = uniqueList.get(random.nextInt(uniqueList.size()));
//
// SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
// String eventType = eventInfoPO.getType();
// Date startDate = eventInfoPO.getStartTime();
// String startDateStr = formatter.format(startDate);
// String dateFolderName = startDateStr + "_" + eventType;
//
// String key = dateFolderName + eventSaveConfiguration.getNegativeSample();
//
// Long count = redisUtils.getIncr(key, 1000 * 60 * 60 * 24);
//
// String pathToDate = eventSaveConfiguration.getRootFolder() + File.separator
// + eventSaveConfiguration.getCity() + File.separator
// + eventType + File.separator
// + dateFolderName + File.separator;
// // todo 暂时建立空文件夹
// makeEmptyFolders(pathToDate, count);
//
// // 保存标签
// saveLabel(eventInfoPO, pathToDate, count);
// // 保存轨迹
// saveKafka(eventInfoPO, pathToDate, count, matchResultTopic);
// // 保存灯态
// saveKafka(eventInfoPO, pathToDate, count, lightStatusTopic);
// // 保存录像
// Long finalCount = count;
// executor.submit(() -> saveNvr(eventInfoPO, pathToDate, finalCount));
// // 监控线程池占用情况
// log.warn("Current Pool Size: {}. Active Threads: {}. " +
// "Number of Tasks Completed: {}. Number of Tasks in Queue: {}. ",
// executor.getPoolSize(), executor.getActiveCount(),
// executor.getCompletedTaskCount(), executor.getQueue().size());
// }
//
// private void saveNvr(EventInfoPO eventInfoPO, String pathToDate, Long count) {
// String eventId = eventInfoPO.getEventId();
// String crossId = eventInfoPO.getCrossId();
// Date startTimeStamp = eventInfoPO.getStartTime();
// Date endTimeStamp = eventInfoPO.getEndTime();
// String nvrurl = eventSaveConfiguration.getNvrurl();
//
// // 查询路口对应的相机
// List<DeviceCameraPO> deviceCameraPOList = holoMapper.selectVideoUrlsByCrossId(crossId);
// if (CollectionUtils.isEmpty(deviceCameraPOList)) {
// return;
// }
//
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
// String starttimeStr = sdf.format(startTimeStamp.getTime() - 30 * 1000);
// String endtimeStr = sdf.format(endTimeStamp.getTime() + 30 * 1000);
//
// for (DeviceCameraPO deviceCameraPO : deviceCameraPOList) {
// if (deviceCameraPO == null) {
// continue;
// }
// String monitorChannel = deviceCameraPO.getMonitorChannel();
//
// String url = nvrurl + "?channel=" + monitorChannel + "&subtype=" + eventSaveConfiguration.getSubType()
// + "&starttime=" + starttimeStr + "&endtime=" + endtimeStr;
//
// String fileName = crossId + "-" + eventId + "-" + monitorChannel;
// String pathToCount = makeSavepathToCount(pathToDate, count);
// String savepath = pathToCount + File.separator
// + eventSaveConfiguration.getEvidence() + File.separator
// + eventSaveConfiguration.getVideo();
// makeDirIfNotExist(savepath);
//
// try {
// FFmpeg.atPath()
// .addInput(UrlInput.fromUrl(url))
// .addOutput(UrlOutput.toUrl(savepath + "/" + fileName + ".mp4")
// .copyAllCodecs())
// .execute();
// } catch (Exception e) {
// log.error("[" + url + "], 获取失败 !", e);
// }
// }
// }
//
// private void saveKafka(EventInfoPO eventInfoPO, String pathToDate, Long count, String topic) {
// Date eventTimeStampStart = eventInfoPO.getStartTime();
// Date eventTimeStampEnd = eventInfoPO.getEndTime();
// long start = eventTimeStampStart.getTime() - 30 * 1000;
// long end = eventTimeStampEnd.getTime() + 30 * 1000;
//
// String savepath = makeSavepathToCount(pathToDate, count);
// makeDirIfNotExist(savepath);
//
// String fileName;
// if (topic.equals(lightStatusTopic)) {
// fileName = eventSaveConfiguration.getLightJson();
// } else {
// fileName = eventSaveConfiguration.getTrackJson();
// }
//
// // 消费前30秒和后30秒的 Kafka 数据,保存到硬盘
// TimeBasedKafkaConsumer.consumeMessagesAroundTimestamp(kafkaServers, topic, start, end, savepath, fileName);
// }
//
// private void saveLabel(EventInfoPO eventInfoPO, String pathToDate, Long count) {
// B5LabelVO vo = new B5LabelVO();
// vo.setCategory(Integer.parseInt(eventInfoPO.getCategory()));
// vo.setEventType(Integer.parseInt(eventInfoPO.getType()));
//
// String globalId = eventInfoPO.getGlobalId();
// if (globalId == null) {
// vo.setTargetIdList(new ArrayList<>());
// } else {
// List<Integer> targetList = new ArrayList<>();
// targetList.add(Integer.parseInt(globalId));
// vo.setTargetIdList(targetList);
// }
//
// vo.setCrossId(eventInfoPO.getCrossId());
// vo.setRid(eventInfoPO.getRid());
//
// Date eventTimeStampStart = eventInfoPO.getStartTime();
// Date eventTimeStampEnd = eventInfoPO.getEndTime();
// vo.setStartTime(eventTimeStampStart);
// vo.setEndTime(eventTimeStampEnd);
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
// vo.setStartTimeDate(sdf.format(eventTimeStampStart));
// vo.setEndTimeDate(sdf.format(eventTimeStampEnd));
//
// // 默认值
// vo.setLabel(-1);
//
// String pathToCount = makeSavepathToCount(pathToDate, count);
// makeDirIfNotExist(pathToCount);
// String fileName = eventSaveConfiguration.getLabelJson();
//
// try (PrintWriter writer = new PrintWriter(new File(pathToCount + File.separator + fileName))) {
// // 写入列名
// writer.println("category,eventType,targetIdList,crossId,rid,startTime,endTime,startTimeDate,endTimeDate," +
// "label,comment");
// // 写入数据
// writer.println(vo.getCategory() + "," + vo.getEventType() + "," + vo.getTargetIdList() + "," + vo.getCrossId() + ","
// + vo.getRid() + "," + vo.getStartTime().getTime() + "," + vo.getEndTime().getTime() + ","
// + vo.getStartTimeDate() + "," + vo.getEndTimeDate() + "," + vo.getLabel() + "," + "");
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
// private String makeSavepathToCount(String pathToDate, Long count) {
// return pathToDate + File.separator +
// eventSaveConfiguration.getNegativeSample() + File.separator
// + count;
// }
//
// private void makeEmptyFolders(String pathToDate, Long count) {
// List<String> savepathList = new ArrayList<>();
//
// String savepath1 = pathToDate + eventSaveConfiguration.getPositiveSample();
// savepathList.add(savepath1);
//
// String pathToEvidence = pathToDate
// + eventSaveConfiguration.getNegativeSample() + File.separator
// + count + File.separator
// + eventSaveConfiguration.getEvidence() + File.separator;
// String savepath2 = pathToEvidence + eventSaveConfiguration.getImage();
// savepathList.add(savepath2);
//
// String savepath3 = pathToEvidence + eventSaveConfiguration.getVision();
// savepathList.add(savepath3);
//
// for (String savepath : savepathList) {
// makeDirIfNotExist(savepath);
// }
// }
//
// private void makeDirIfNotExist(String savepath) {
// File directory = new File(savepath);
// if (!directory.exists()) {
// directory.mkdirs();
// }
// }
//
// @Async
// @Scheduled(cron="0 0 2 * * ? ")
// // 每天凌晨2点清理一星期前的数据集文件
// public void cleanUpSavepath() {
// String savepath = eventSaveConfiguration.getRootFolder();
// long currentTime = System.currentTimeMillis();
// long twoMonthsInMillis = 60L * 24 * 60 * 7 * 1000; // 大约一星期的毫秒数
//
// File directory = new File(savepath);
//
// if (directory.exists() && directory.isDirectory()) {
// deleteOldFiles(directory, currentTime, twoMonthsInMillis);
// } else {
// log.error("目录不存在:" + savepath);
// }
//
// }
//
// private void deleteOldFiles(File folder, long currentTime, long threshold) {
// File[] files = folder.listFiles();
// if (files != null) {
// for (File file : files) {
// try {
// if (file.isDirectory()) {
// // 先获取目录的最后修改时间
// long lastModifiedTime = file.lastModified();
//
// // 递归删除子目录内容
// deleteOldFiles(file, currentTime, threshold);
//
// // 检查子目录是否为空,如果为空则根据之前获取的修改时间决定是否删除目录
// String[] subFiles = file.list();
// if (subFiles != null && subFiles.length == 0 && (currentTime - lastModifiedTime) > threshold) {
// file.delete(); // 删除空目录
// }
// } else {
// // 对于文件,获取文件的最后修改时间,然后判断是否需要删除
// long lastModifiedTime = file.lastModified();
// if ((currentTime - lastModifiedTime) > threshold) {
// file.delete(); // 删除文件
// }
// }
// } catch (Exception e) {
// log.error("删除文件失败: " + file.getAbsolutePath(), e);
// }
// }
// }
// }
//}
package net.wanji.datacenter.task;
class ProcessCloser implements AutoCloseable {
Process process;
public ProcessCloser(Process process) {
this.process = process;
}
@Override
public void close() {
process.destroy();
}
}
\ No newline at end of file
//package net.wanji.datacenter.task;
//
//class ProcessCloser implements AutoCloseable {
// Process process;
//
// public ProcessCloser(Process process) {
// this.process = process;
// }
//
// @Override
// public void close() {
// process.destroy();
// }
//}
\ No newline at end of file
package net.wanji.datacenter.task;
import lombok.extern.slf4j.Slf4j;
import net.wanji.datacenter.util.RedisUtils;
import org.springframework.data.redis.connection.DataType;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Set;
/**
* @author Kent HAN
* @date 2023/12/15 16:41
*/
@Component
@Slf4j
public class RedisTask {
@Resource
private RedisUtils redisUtils;
/**
* 每分钟清理路口及干线事件缓存
* @author Kent HAN
* @date 2023/12/15 16:42
*/
@Scheduled(fixedRate = 1000 * 60)
public void cleanCrossEventCache() throws Exception {
try {
Set<String> keys = redisUtils.keys();
for (String key : keys) {
if (redisUtils.keyType(key) == DataType.ZSET) {
redisUtils.removeExpiredElements(key);
}
}
} catch (Exception e) {
log.error("清理路口事件缓存失败", e);
throw new Exception(e);
}
}
}
//package net.wanji.datacenter.task;
//
//import lombok.extern.slf4j.Slf4j;
//import net.wanji.datacenter.util.RedisUtils;
//import org.springframework.data.redis.connection.DataType;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//import java.util.Set;
//
///**
// * @author Kent HAN
// * @date 2023/12/15 16:41
// */
//@Component
//@Slf4j
//public class RedisTask {
// @Resource
// private RedisUtils redisUtils;
//
// /**
// * 每分钟清理路口及干线事件缓存
// * @author Kent HAN
// * @date 2023/12/15 16:42
// */
// @Scheduled(fixedRate = 1000 * 60)
// public void cleanCrossEventCache() throws Exception {
// try {
// Set<String> keys = redisUtils.keys();
// for (String key : keys) {
// if (redisUtils.keyType(key) == DataType.ZSET) {
// redisUtils.removeExpiredElements(key);
// }
// }
// } catch (Exception e) {
// log.error("清理路口事件缓存失败", e);
// throw new Exception(e);
// }
// }
//
//}
server:
port: 33000
port: 43000
tomcat:
uri-encoding: utf-8
servlet:
......@@ -9,7 +9,7 @@ spring:
elasticsearch:
username: elastic
password: Wanji300552
uris: http://10.102.1.182:9200
uris: http://37.12.182.31:9200
application:
name: wj-datacenter-service
main:
......@@ -21,20 +21,20 @@ spring:
datasource:
master:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://10.102.1.182:3306/t_signal_control_jinan?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
url: jdbc:mysql://37.12.182.29:3306/wjdit_ecosystem_db_v1.0.0?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
# url: jdbc:mysql://10.102.1.112:53306/t_signal_control?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
username: root
password: Wanji300552
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://10.102.1.182:3306/t_signal_control_jinan?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
url: jdbc:mysql://37.12.182.29:3306/wjdit_ecosystem_db_v1.0.0?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
username: root
password: Wanji300552
driver-class-name: com.mysql.cj.jdbc.Driver
holo:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://10.102.1.182:3306/holo_roadnet?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
url: jdbc:mysql://37.12.182.29:3306/holo_roadnet?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'&useSSL=false&useCursorFetch=true
username: root
password: Wanji300552
driverClassName: com.mysql.cj.jdbc.Driver
......@@ -42,11 +42,11 @@ spring:
#生产者配置
producer:
producer1:
bootstrap-servers: 10.102.1.182:9092
bootstrap-servers: 37.12.182.31:9092
key-deserializer: org.apache.kafka.common.serialization.StringSerializer
value-deserializer: org.apache.kafka.common.serialization.StringSerializer
producer2:
bootstrap-servers: 10.102.1.181:9092
bootstrap-servers: 37.12.182.31:9093
key-deserializer: org.apache.kafka.common.serialization.StringSerializer
value-deserializer: org.apache.kafka.common.serialization.StringSerializer
#消费者配置
......@@ -59,12 +59,12 @@ spring:
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
group-id: group
bootstrap-servers: 10.102.1.182:9092
bootstrap-servers: 37.12.182.31:9093
listener:
concurrency: 3
ack-mode: manual_immediate
redis:
host: 10.102.1.182
host: 37.12.182.29
port: 6379
password: Wanji300552
jedis:
......@@ -108,7 +108,8 @@ threadPoolConfig:
allowCoreTimeOut: false
kafka-consumer:
lanePeriodicDataTopic: JN050001LanePeriodicData
lanePeriodicDataTopic: cross_period_lane_data
crossPeriodicDataTopic: cross_period_data
laneSnapshotDataTopic: JN050001LaneSnapshotData
crossSnapshotDataTopic: JN050001CrossSnapshotData
crossEventIndex: phase.emptiness.topic
......@@ -131,7 +132,7 @@ eventsave:
kafka:
producer:
bootstrap.servers: 10.102.1.182:9092 # kafka连接地址
bootstrap.servers: 37.12.182.31:9092 # kafka连接地址
acks: 0
retries: 0
batch.size: 102400
......
......@@ -6,7 +6,7 @@ spring:
cloud:
nacos:
config:
server-addr: 172.17.0.1:8848
server-addr: 37.12.182.29:8848
file-extension: yaml
group: wanji
namespace: wanji
......
spring:
profiles:
active: dev
\ No newline at end of file
active: greencity
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment