Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wj-datacenter-platform
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jinan
wj-datacenter-platform
Commits
c3f12a81
Commit
c3f12a81
authored
Nov 15, 2024
by
duanruiming
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[add] 绿波城项目分支
parent
97c5d2b0
Changes
28
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
1177 additions
and
3485 deletions
+1177
-3485
CrossDirWeekAvgFlowCache.java
.../net/wanji/datacenter/cache/CrossDirWeekAvgFlowCache.java
+0
-86
CrossDirWeekMaxFlowCache.java
.../net/wanji/datacenter/cache/CrossDirWeekMaxFlowCache.java
+0
-71
CrossLaneInfoCache.java
...n/java/net/wanji/datacenter/cache/CrossLaneInfoCache.java
+9
-0
CrossSchemePhaseLightsCache.java
...t/wanji/datacenter/cache/CrossSchemePhaseLightsCache.java
+109
-109
CrossTurnWeekMaxFlowCache.java
...net/wanji/datacenter/cache/CrossTurnWeekMaxFlowCache.java
+0
-89
DataProcessServiceRegistrator.java
...wanji/datacenter/cache/DataProcessServiceRegistrator.java
+0
-42
WeekDirFreeFlowSpeedCache.java
...net/wanji/datacenter/cache/WeekDirFreeFlowSpeedCache.java
+0
-99
WeekTurnFreeFlowSpeedCache.java
...et/wanji/datacenter/cache/WeekTurnFreeFlowSpeedCache.java
+0
-94
EventSaveConfiguration.java
...a/net/wanji/datacenter/config/EventSaveConfiguration.java
+0
-29
ConsumerHandler.java
...main/java/net/wanji/datacenter/kafka/ConsumerHandler.java
+21
-156
ProducerHandler.java
...main/java/net/wanji/datacenter/kafka/ProducerHandler.java
+53
-53
LanePeriodicDataEventListConvert.java
...center/pojo/convert/LanePeriodicDataEventListConvert.java
+0
-217
CrossEventDTO.java
...ain/java/net/wanji/datacenter/pojo/dto/CrossEventDTO.java
+0
-59
CrossPeriodDataDTO.java
...ava/net/wanji/datacenter/pojo/dto/CrossPeriodDataDTO.java
+33
-0
LanePeriodicDataDTO.java
...va/net/wanji/datacenter/pojo/dto/LanePeriodicDataDTO.java
+170
-157
DataProcessService.java
...java/net/wanji/datacenter/service/DataProcessService.java
+7
-13
CrossSnapshotDataProcessService.java
...acenter/service/impl/CrossSnapshotDataProcessService.java
+0
-36
DataProcessServiceImpl.java
...wanji/datacenter/service/impl/DataProcessServiceImpl.java
+98
-0
LanePeriodicDataProcessServiceImpl.java
...nter/service/impl/LanePeriodicDataProcessServiceImpl.java
+0
-1375
LaneSnapshotDataProcessService.java
...tacenter/service/impl/LaneSnapshotDataProcessService.java
+0
-124
DataCenterTask.java
...c/main/java/net/wanji/datacenter/task/DataCenterTask.java
+117
-117
DataProcessTask.java
.../main/java/net/wanji/datacenter/task/DataProcessTask.java
+168
-168
EventTask.java
...ce/src/main/java/net/wanji/datacenter/task/EventTask.java
+322
-322
ProcessCloser.java
...rc/main/java/net/wanji/datacenter/task/ProcessCloser.java
+14
-14
RedisTask.java
...ce/src/main/java/net/wanji/datacenter/task/RedisTask.java
+42
-42
application-local.yaml
...acenter-service/src/main/resources/application-local.yaml
+12
-11
bootstrap-greencity.yml
...center-service/src/main/resources/bootstrap-greencity.yml
+1
-1
bootstrap.yml
wj-datacenter-service/src/main/resources/bootstrap.yml
+1
-1
No files found.
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/CrossDirWeekAvgFlowCache.java
deleted
100644 → 0
View file @
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
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/CrossDirWeekMaxFlowCache.java
deleted
100644 → 0
View file @
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.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
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/CrossLaneInfoCache.java
View file @
c3f12a81
...
...
@@ -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
);
}
}
}
}
...
...
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/CrossSchemePhaseLightsCache.java
View file @
c3f12a81
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);
//
}
//
}
//
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/CrossTurnWeekMaxFlowCache.java
deleted
100644 → 0
View file @
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.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
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/DataProcessServiceRegistrator.java
deleted
100644 → 0
View file @
97c5d2b0
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
(
"初始化数据处理注册器失败"
);
}
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/WeekDirFreeFlowSpeedCache.java
deleted
100644 → 0
View file @
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
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
);
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/cache/WeekTurnFreeFlowSpeedCache.java
deleted
100644 → 0
View file @
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.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
);
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/config/EventSaveConfiguration.java
deleted
100644 → 0
View file @
97c5d2b0
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
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/kafka/ConsumerHandler.java
View file @
c3f12a81
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
receiveCross
EventData
(
ConsumerRecord
<
Object
,
Object
>
record
,
Acknowledgment
acknowledgment
)
throws
Exception
{
@KafkaListener
(
topics
=
{
"
${kafka-consumer.crossPeriodicDataTopic}"
},
groupId
=
"group
"
)
public
void
receiveCross
PeriodicData
(
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}]}"
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/kafka/ProducerHandler.java
View file @
c3f12a81
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;
//
}
//
}
//
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/pojo/convert/LanePeriodicDataEventListConvert.java
deleted
100644 → 0
View file @
97c5d2b0
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
;
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/pojo/dto/CrossEventDTO.java
deleted
100644 → 0
View file @
97c5d2b0
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
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/pojo/dto/CrossPeriodDataDTO.java
0 → 100644
View file @
c3f12a81
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
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/pojo/dto/LanePeriodicDataDTO.java
View file @
c3f12a81
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
;
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/service/DataProcessService.java
View file @
c3f12a81
...
...
@@ -7,23 +7,17 @@ package net.wanji.datacenter.service;
public
interface
DataProcessService
{
/**
* 数据中心发送数据, 通过远程调用调用不同的服务
*
* @param convertData
*/
void
send
(
String
topic
,
Object
convertData
);
/**
* 数据中心转换数据
*
* 车道信息处理存库
* @param originalData
* @
retur
n
* @
throws Exceptio
n
*/
Object
convert
(
String
originalData
)
throws
Exception
;
void
laneSave
(
String
originalData
)
throws
Exception
;
/**
* 转换后保存数据
* 路口信息处理存库
* @param originalData
* @throws Exception
*/
void
save
(
Object
convert
Data
)
throws
Exception
;
void
crossSave
(
String
original
Data
)
throws
Exception
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/service/impl/CrossSnapshotDataProcessService.java
deleted
100644 → 0
View file @
97c5d2b0
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
{
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/service/impl/DataProcessServiceImpl.java
0 → 100644
View file @
c3f12a81
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
);
}
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/service/impl/LanePeriodicDataProcessServiceImpl.java
deleted
100644 → 0
View file @
97c5d2b0
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
;
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/service/impl/LaneSnapshotDataProcessService.java
deleted
100644 → 0
View file @
97c5d2b0
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
);
}
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/task/DataCenterTask.java
View file @
c3f12a81
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;
//
}
//
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/task/DataProcessTask.java
View file @
c3f12a81
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;
//
}
//
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/task/EventTask.java
View file @
c3f12a81
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);
//
}
//
}
//
}
//
}
//
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/task/ProcessCloser.java
View file @
c3f12a81
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
wj-datacenter-service/src/main/java/net/wanji/datacenter/task/RedisTask.java
View file @
c3f12a81
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);
//
}
//
}
//
//
}
wj-datacenter-service/src/main/resources/application-local.yaml
View file @
c3f12a81
server
:
port
:
3
3000
port
:
4
3000
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
...
...
wj-datacenter-service/src/main/resources/bootstrap-
jinan
.yml
→
wj-datacenter-service/src/main/resources/bootstrap-
greencity
.yml
View file @
c3f12a81
...
...
@@ -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
...
...
wj-datacenter-service/src/main/resources/bootstrap.yml
View file @
c3f12a81
spring
:
profiles
:
active
:
dev
\ No newline at end of file
active
:
greencity
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment