Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
聂康
ivccs
Commits
07602a7b
Commit
07602a7b
authored
Apr 18, 2023
by
kang.nie@inzymeits.com
Browse files
提交代码
parent
e0c7be76
Changes
479
Hide whitespace changes
Inline
Side-by-side
ivccs-vmm-backservice/src/main/java/com/ssi/mapper/VmsVehicleAlertProcessMapper.java
0 → 100644
View file @
07602a7b
package
com.ssi.mapper
;
import
com.ssi.entity.VmsVehicleAlertProcess
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* @Entity com.ssi.entity.VmsVehicleAlertProcess
*/
public
interface
VmsVehicleAlertProcessMapper
extends
BaseMapper
<
VmsVehicleAlertProcess
>
{
}
ivccs-vmm-backservice/src/main/java/com/ssi/mapper/VmsVehicleMapper.java
0 → 100644
View file @
07602a7b
package
com.ssi.mapper
;
import
com.ssi.entity.VmsVehicle
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.ssi.entity.dto.VmsVehicleDto
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.time.LocalDateTime
;
import
java.util.List
;
import
java.util.Map
;
/**
* 车辆表
*
* @author zhang liyao
* @email
* @date 2020-07-08 15:38:37
*/
@Mapper
public
interface
VmsVehicleMapper
extends
BaseMapper
<
VmsVehicle
>
{
/**
* 根据vin获取车辆以及远控台信息
* @param vin
* @return
*/
VmsVehicleDto
queryVehicleByVin
(
@Param
(
"vin"
)
String
vin
);
Map
getVmsCranePosMapInfo
(
@Param
(
"name"
)
String
name
);
List
<
Map
>
getVmsVehicle
();
}
ivccs-vmm-backservice/src/main/java/com/ssi/mapper/VmsVehicleOperateTaskMapper.java
0 → 100644
View file @
07602a7b
package
com.ssi.mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.ssi.entity.VmsVehicleOperateTask
;
import
org.apache.ibatis.annotations.Mapper
;
/**
* 车辆运营数据统计表
*
* @author zhang liyao
* @email
* @date 2020-07-16 09:32:59
*/
@Mapper
public
interface
VmsVehicleOperateTaskMapper
extends
BaseMapper
<
VmsVehicleOperateTask
>
{
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/CraneInfoRedis.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
import
lombok.Setter
;
/**
* @author 成东
* @since 2022-02-23 16:29
*/
@NoArgsConstructor
@Getter
@Setter
public
class
CraneInfoRedis
{
private
String
portCode
;
private
Integer
portType
;
//港机类型(1:桥吊 2:场吊)
private
Long
collectTime
;
private
Object
lockStatus
;
private
Double
height
;
private
Object
hoistStatus
;
private
Double
trolleyPos
;
private
Double
mainHoistPos
;
private
Integer
twistlockLocked
;
private
Integer
pinsLanded
;
private
String
spreaderSize
;
private
Integer
trolleyForward
;
private
Integer
trolleyBackward
;
private
Integer
mainHoistUp
;
private
Integer
mainHoistDown
;
private
Integer
gantryForward
;
private
Integer
gantryBackward
;
private
Double
lon
;
private
Double
lat
;
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/ElasticSearchMetaModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Sets
;
import
lombok.extern.slf4j.Slf4j
;
import
org.elasticsearch.action.ActionFuture
;
import
org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest
;
import
org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse
;
import
org.elasticsearch.action.admin.indices.stats.IndexStats
;
import
org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest
;
import
org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse
;
import
org.elasticsearch.action.search.SearchRequestBuilder
;
import
org.elasticsearch.client.transport.TransportClient
;
import
org.elasticsearch.index.query.QueryBuilders
;
import
org.elasticsearch.index.reindex.DeleteByQueryAction
;
import
org.joda.time.DateTime
;
import
org.joda.time.DateTimeZone
;
import
org.joda.time.Days
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.*
;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/1/17 15:07
*/
@Component
@Slf4j
public
class
ElasticSearchMetaModel
{
private
final
static
DateTimeZone
TIME_ZONE
=
DateTimeZone
.
forID
(
"Asia/Shanghai"
);
@Autowired
private
TransportClient
transportClient
;
public
Map
<
String
,
IndexStats
>
getIndicesStats
()
{
ActionFuture
<
IndicesStatsResponse
>
isr
=
transportClient
.
admin
().
indices
()
.
stats
(
new
IndicesStatsRequest
().
all
());
return
isr
.
actionGet
().
getIndices
();
}
public
List
<
String
>
getIndices
()
{
return
Lists
.
newArrayList
(
getIndicesStats
().
keySet
());
}
public
boolean
exist
(
String
index
)
{
List
<
String
>
indexs
=
getIndices
();
return
indexs
==
null
?
false
:
indexs
.
contains
(
index
);
}
public
String
[]
selectExist
(
String
...
indexs
)
{
return
selectExist
(
Sets
.
newHashSet
(
indexs
));
}
public
String
[]
selectExist
(
Collection
<
String
>
indexs
)
{
List
<
String
>
all
=
getIndices
();
if
(
all
==
null
)
{
all
=
Lists
.
newArrayList
();
}
indexs
.
retainAll
(
all
);
return
indexs
.
toArray
(
new
String
[
indexs
.
size
()]);
}
public
SearchRequestBuilder
newSearchRequestBuilderInDayIndex
(
Long
startTime
,
Long
stopTime
,
String
indexBase
,
int
defaultDayPeriod
,
boolean
defaultContainsToday
)
{
return
newSearchRequestBuilderInDayIndex
(
startTime
,
stopTime
,
indexBase
,
defaultDayPeriod
,
defaultContainsToday
,
"day"
);
}
public
SearchRequestBuilder
newSearchRequestBuilderInDayIndex
(
Long
startTime
,
Long
stopTime
,
String
indexBase
,
int
defaultDayPeriod
,
boolean
defaultContainsToday
,
String
indexRule
)
{
SearchRequestBuilder
requestBuilder
=
null
;
if
(
indexRule
==
null
)
{
requestBuilder
=
transportClient
.
prepareSearch
(
indexBase
);
}
else
if
(
startTime
==
null
&&
stopTime
==
null
)
{
requestBuilder
=
transportClient
.
prepareSearch
(
String
.
format
(
"%s_2*"
,
indexBase
));
}
else
{
String
[]
indexs
=
getIndexs
(
startTime
,
stopTime
,
indexBase
,
defaultDayPeriod
,
defaultContainsToday
,
indexRule
);
if
(
indexs
.
length
>
0
)
{
log
.
info
(
String
.
format
(
"查询es的索引有:%s"
,
Lists
.
newArrayList
(
indexs
)));
requestBuilder
=
transportClient
.
prepareSearch
(
indexs
);
}
}
return
requestBuilder
;
}
public
String
[]
getIndexs
(
Long
startTime
,
Long
stopTime
,
String
indexBase
,
int
defaultDayPeriod
,
boolean
defaultContainsToday
)
{
return
getIndexs
(
startTime
,
stopTime
,
indexBase
,
defaultDayPeriod
,
defaultContainsToday
,
"day"
);
}
public
String
[]
getIndexs
(
Long
startTime
,
Long
stopTime
,
String
indexBase
,
int
defaultDayPeriod
,
boolean
defaultContainsToday
,
String
indexRule
)
{
if
(
indexRule
==
null
)
{
return
new
String
[]{
indexBase
};
}
DateTime
stopDate
;
if
(
stopTime
==
null
)
{
DateTime
now
=
DateTime
.
now
(
TIME_ZONE
);
if
(
defaultContainsToday
)
{
stopDate
=
now
;
}
else
{
stopDate
=
now
.
minusDays
(
1
);
}
}
else
{
stopDate
=
new
DateTime
(
stopTime
.
longValue
(),
TIME_ZONE
);
}
DateTime
startDate
=
(
startTime
==
null
?
stopDate
.
minusDays
(
defaultDayPeriod
)
:
new
DateTime
(
startTime
.
longValue
(),
TIME_ZONE
));
List
<
String
>
indexList
=
new
ArrayList
<>();
String
[]
indexs
;
int
days
=
Days
.
daysBetween
(
startDate
,
stopDate
).
getDays
();
Set
<
String
>
indexSet
=
new
HashSet
<>();
if
(
days
>=
0
)
{
for
(
int
i
=
0
;
i
<=
days
;
i
++)
{
try
{
switch
(
indexRule
.
toLowerCase
())
{
//按年分区
case
"year"
:
indexSet
.
add
(
String
.
format
(
"%s_%s*"
,
indexBase
,
startDate
.
plusDays
(
i
).
toString
(
"yyyy"
)));
break
;
//按月分区
case
"month"
:
indexSet
.
add
(
String
.
format
(
"%s_%s*"
,
indexBase
,
startDate
.
plusDays
(
i
).
toString
(
"yyyyMM"
)));
break
;
//按天分区
case
"day"
:
indexList
.
add
(
String
.
format
(
"%s_%s*"
,
indexBase
,
startDate
.
plusDays
(
i
).
toString
(
"yyyyMMdd"
)));
break
;
default
:
indexSet
.
add
(
indexBase
);
}
}
catch
(
Exception
e
)
{
}
}
indexList
.
addAll
(
indexSet
);
indexs
=
indexList
.
toArray
(
new
String
[
indexList
.
size
()]);
}
else
{
indexs
=
new
String
[
0
];
}
log
.
info
(
"查询索引有:indexs = "
+
Lists
.
newArrayList
(
indexs
).
toString
());
return
indexs
;
}
/**
* 清空指定索引的缓存
*
* @param indexName 索引名
* @return 清空结果
*/
public
boolean
clearIndicesCache
(
String
...
indexName
)
{
ClearIndicesCacheResponse
response
;
try
{
response
=
transportClient
.
admin
().
indices
()
.
clearCache
(
new
ClearIndicesCacheRequest
(
indexName
)
//.fieldDataCache(true)
.
queryCache
(
true
)
).
actionGet
();
if
(
response
.
getFailedShards
()
>
0
)
{
return
false
;
}
return
true
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
false
;
}
public
String
[]
deleteIndexByIds
(
List
<
Map
<
String
,
Object
>>
deleteMaps
)
{
String
[]
idArray
=
null
;
if
(
deleteMaps
!=
null
)
{
Set
<
String
>
indexs
=
Sets
.
newHashSet
();
Set
<
String
>
ids
=
Sets
.
newHashSet
();
deleteMaps
.
forEach
(
deleteMap
->
{
String
id
=
String
.
valueOf
(
deleteMap
.
get
(
"id"
));
String
index
=
String
.
valueOf
(
deleteMap
.
get
(
"index"
));
String
table
=
String
.
valueOf
(
deleteMap
.
get
(
"table"
));
if
(
id
!=
null
&&
index
!=
null
&&
table
!=
null
)
{
ids
.
add
(
id
);
indexs
.
add
(
index
);
}
});
String
[]
indices
=
indexs
.
toArray
(
new
String
[
indexs
.
size
()]);
idArray
=
ids
.
toArray
(
new
String
[
ids
.
size
()]);
if
(
indices
.
length
>
0
)
{
DeleteByQueryAction
.
INSTANCE
.
newRequestBuilder
(
transportClient
)
.
filter
(
QueryBuilders
.
termsQuery
(
"id"
,
ids
))
.
source
(
indices
)
.
get
();
clearIndicesCache
(
indices
);
}
}
return
idArray
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/ElasticSearchModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.ssi.config.ElasticsearchConfig
;
import
com.ssi.utils.GeoPosTransformUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.elasticsearch.action.search.SearchRequestBuilder
;
import
org.elasticsearch.client.transport.TransportClient
;
import
org.elasticsearch.index.query.BoolQueryBuilder
;
import
org.elasticsearch.index.query.QueryBuilders
;
import
org.elasticsearch.search.SearchHit
;
import
org.elasticsearch.search.SearchHits
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/3/1 16:56
*/
@Slf4j
public
class
ElasticSearchModel
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ElasticSearchMetaModel
.
class
);
@Autowired
protected
TransportClient
transportClient
;
@Autowired
protected
ElasticSearchMetaModel
elasticSearchMetaModel
;
@Autowired
protected
ElasticsearchConfig
elasticsearchConfig
;
protected
BoolQueryBuilder
createBooleanQueryBuilderWithChinaLocation
()
{
return
createBooleanQueryBuilderWithChinaLocation
(
"longitude"
,
"latitude"
);
}
protected
BoolQueryBuilder
createBooleanQueryBuilderWithChinaLocation
(
String
longitudeField
,
String
latitudeField
)
{
BoolQueryBuilder
boolQueryBuilder
=
QueryBuilders
.
boolQuery
();
//中国经纬度
boolQueryBuilder
.
must
(
QueryBuilders
.
rangeQuery
(
longitudeField
).
gte
(
73
).
lt
(
135
));
boolQueryBuilder
.
must
(
QueryBuilders
.
rangeQuery
(
latitudeField
).
gte
(
4
).
lt
(
53
));
return
boolQueryBuilder
;
}
protected
Map
<
String
,
Object
>
extractSearchHits
(
SearchHits
hits
)
{
return
extractSearchHits
(
hits
,
null
,
null
,
null
);
}
protected
Map
<
String
,
Object
>
extractSearchHits
(
SearchHits
hits
,
String
posType
)
{
return
extractSearchHits
(
hits
,
posType
,
"longitude"
,
"latitude"
);
}
protected
List
<
Map
<
String
,
Object
>>
extractSearchHits
(
SearchHit
[]
hits
,
String
posType
,
String
longitudeField
,
String
latitudeField
)
{
List
<
Map
<
String
,
Object
>>
maps
=
Arrays
.
stream
(
hits
).
map
(
hit
->
{
Map
<
String
,
Object
>
sourceAsMap
=
hit
.
getSourceAsMap
();
if
(
posType
!=
null
)
{
locationTypeChange
(
sourceAsMap
,
posType
,
longitudeField
,
latitudeField
);
}
return
sourceAsMap
;
}).
collect
(
Collectors
.
toList
());
return
maps
;
}
protected
Map
<
String
,
Object
>
extractSearchHits
(
SearchHits
hits
,
String
posType
,
String
longitudeField
,
String
latitudeField
)
{
Map
<
String
,
Object
>
res
;
long
totalHits
=
hits
.
getTotalHits
();
if
(
totalHits
>
0
)
{
res
=
Maps
.
newHashMapWithExpectedSize
(
3
);
res
.
put
(
"total"
,
totalHits
);
List
<
Map
<
String
,
Object
>>
maps
=
extractSearchHits
(
hits
.
getHits
(),
posType
,
longitudeField
,
latitudeField
);
res
.
put
(
"records"
,
maps
);
res
.
put
(
"size"
,
maps
.
size
());
}
else
{
res
=
emptySearchHitResult
();
}
return
res
;
}
protected
Map
<
String
,
Object
>
emptySearchHitResult
()
{
Map
<
String
,
Object
>
res
=
Maps
.
newHashMapWithExpectedSize
(
3
);
res
.
put
(
"total"
,
0
);
res
.
put
(
"records"
,
Lists
.
newArrayList
());
res
.
put
(
"size"
,
0
);
return
res
;
}
protected
void
locationTypeChange
(
Map
<
String
,
Object
>
sourceAsMap
,
String
toType
,
String
longitudeField
,
String
latitudeField
)
{
Object
longitudeObj
=
sourceAsMap
.
get
(
longitudeField
);
Object
latitudeObj
=
sourceAsMap
.
get
(
latitudeField
);
if
(
latitudeObj
!=
null
&&
longitudeObj
!=
null
)
{
double
longitude
=
Double
.
parseDouble
(
longitudeObj
.
toString
());
double
latitude
=
Double
.
parseDouble
(
latitudeObj
.
toString
());
double
[]
doubles
=
null
;
switch
(
toType
)
{
//百度
case
"bd09"
:
doubles
=
GeoPosTransformUtil
.
wgs84tobd09
(
longitude
,
latitude
);
break
;
//高德
case
"gcj02"
:
doubles
=
GeoPosTransformUtil
.
wgs84togcj02
(
longitude
,
latitude
);
break
;
}
if
(
doubles
!=
null
)
{
sourceAsMap
.
put
(
longitudeField
,
doubles
[
0
]);
sourceAsMap
.
put
(
latitudeField
,
doubles
[
1
]);
}
}
}
/**
* 移动过来的
*/
protected
SearchRequestBuilder
newSearchRequestBuilder
(
Long
startTime
,
Long
endTime
)
{
return
newSearchRequestBuilder
(
startTime
,
endTime
,
elasticsearchConfig
.
getTypeName
());
}
protected
SearchRequestBuilder
newSearchRequestBuilder
(
Long
startTime
,
Long
endTime
,
String
typeName
)
{
SearchRequestBuilder
requestBuilder
;
if
(
startTime
==
null
&&
endTime
==
null
)
{
requestBuilder
=
transportClient
.
prepareSearch
(
String
.
format
(
"%s_2*"
,
typeName
));
}
else
{
String
[]
indexs
=
getIndexs
(
startTime
,
endTime
);
if
(
indexs
.
length
==
0
)
{
requestBuilder
=
transportClient
.
prepareSearch
(
String
.
format
(
"%s_2*"
,
typeName
));
logger
.
warn
(
String
.
format
(
"在时间范围[%s,%s]内不存在%s的索引。"
,
startTime
,
endTime
,
typeName
));
}
else
{
requestBuilder
=
transportClient
.
prepareSearch
(
indexs
);
}
}
return
requestBuilder
.
setTypes
(
typeName
);
}
protected
String
[]
getIndexs
(
Long
startTime
,
Long
endTime
)
{
return
elasticSearchMetaModel
.
getIndexs
(
startTime
,
endTime
,
elasticsearchConfig
.
getTypeName
(),
7
,
true
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/RedisConfigModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.data.redis.core.HashOperations
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.stereotype.Component
;
import
java.util.Map
;
import
java.util.Set
;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/10/17 9:38
*/
@Component
@Slf4j
public
class
RedisConfigModel
{
@Autowired
private
StringRedisTemplate
stringRedisTemplate
;
@Value
(
"${cism.redis.config.prefix:cism:config}"
)
private
String
configRedisPrefix
;
@Value
(
"${cism.redis.config.group:extra}"
)
private
String
defaultGroup
;
public
void
setConfig
(
String
group
,
String
key
,
String
value
)
{
if
(
StringUtils
.
isNotBlank
(
key
)
&&
StringUtils
.
isNotBlank
(
value
))
{
stringRedisTemplate
.
opsForHash
()
.
put
(
String
.
format
(
"%s:%s"
,
configRedisPrefix
,
group
),
key
,
value
);
}
}
public
void
setConfig
(
String
key
,
String
value
)
{
setConfig
(
defaultGroup
,
key
,
value
);
}
public
void
setConfig
(
String
group
,
Map
<
String
,
String
>
configMap
)
{
if
(
configMap
!=
null
&&
!
configMap
.
isEmpty
())
{
HashOperations
<
String
,
String
,
String
>
hashOperations
=
stringRedisTemplate
.
opsForHash
();
hashOperations
.
putAll
(
String
.
format
(
"%s:%s"
,
configRedisPrefix
,
group
),
configMap
);
}
}
public
void
setConfig
(
Map
<
String
,
String
>
configMap
)
{
setConfig
(
defaultGroup
,
configMap
);
}
public
String
getConfigWithDefault
(
String
key
,
String
defaultValue
)
{
return
getConfigWithDefault
(
defaultGroup
,
key
,
defaultValue
);
}
public
String
getConfigWithDefault
(
String
group
,
String
key
,
String
defaultValue
)
{
String
value
=
getConfig
(
group
,
key
);
if
(
value
==
null
)
{
value
=
defaultValue
;
}
return
value
;
}
public
String
getConfig
(
String
group
,
String
key
)
{
if
(
StringUtils
.
isNotBlank
(
group
)
&&
StringUtils
.
isNotBlank
(
key
))
{
HashOperations
<
String
,
String
,
String
>
hashOperations
=
stringRedisTemplate
.
opsForHash
();
return
hashOperations
.
get
(
String
.
format
(
"%s:%s"
,
configRedisPrefix
,
group
),
key
);
}
else
{
return
null
;
}
}
public
String
getConfig
(
String
key
)
{
return
getConfig
(
defaultGroup
,
key
);
}
public
Map
<
String
,
String
>
getConfigs
(
Set
<
String
>
keys
)
{
return
getConfigs
(
defaultGroup
,
keys
);
}
public
Map
<
String
,
String
>
getConfigs
(
String
group
,
Set
<
String
>
keys
)
{
Map
<
String
,
String
>
configs
=
Maps
.
newHashMap
();
if
(
keys
!=
null
&&
!
keys
.
isEmpty
())
{
keys
.
forEach
(
key
->
{
String
config
=
getConfig
(
group
,
key
);
if
(
config
!=
null
)
{
configs
.
put
(
key
,
config
);
}
});
}
return
configs
;
}
public
void
deteles
(
String
group
,
String
...
keys
)
{
if
(
StringUtils
.
isNotBlank
(
group
)
&&
keys
.
length
>
0
)
{
HashOperations
<
String
,
String
,
String
>
hashOperations
=
stringRedisTemplate
.
opsForHash
();
hashOperations
.
delete
(
String
.
format
(
"%s:%s"
,
configRedisPrefix
,
group
),
keys
);
}
}
public
void
deteles
(
String
...
keys
)
{
deteles
(
defaultGroup
,
keys
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/RedisDataModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.google.common.base.Strings
;
import
com.ssi.utils.JsonUtil
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.val
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
redis.clients.jedis.GeoRadiusResponse
;
import
redis.clients.jedis.GeoUnit
;
import
redis.clients.jedis.Jedis
;
import
redis.clients.jedis.params.geo.GeoRadiusParam
;
import
redis.clients.util.Pool
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/7/12 15:37
*/
@Slf4j
public
class
RedisDataModel
{
private
Pool
pool
;
public
RedisDataModel
(
Pool
pool
)
{
this
.
pool
=
pool
;
}
public
String
get
(
String
key
)
{
String
json
=
null
;
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
json
=
jedis
.
get
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
json
;
}
public
Map
<
String
,
Object
>
getJson2Map
(
String
key
)
{
Map
<
String
,
Object
>
map
=
null
;
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
String
json
=
jedis
.
get
(
key
);
if
(!
Strings
.
isNullOrEmpty
(
json
))
{
map
=
JsonUtil
.
jsonToMap
(
json
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
map
;
}
public
Set
<
String
>
keys
(
String
key
)
{
Set
<
String
>
keys
=
null
;
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
keys
=
jedis
.
keys
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"获取所有前缀为%s的key失败。"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
keys
;
}
public
List
<
String
>
mget
(
String
...
key
)
{
List
<
String
>
keys
=
null
;
if
(
key
!=
null
)
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
keys
=
jedis
.
mget
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"获取所有前缀为%s的key失败。"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
keys
;
}
public
Map
<
String
,
Object
>
mgetForMap
(
Collection
<
String
>
key
)
{
val
value
=
mget
(
key
.
toArray
(
new
String
[
0
]));
assert
value
!=
null
;
assert
value
.
size
()
==
key
.
size
();
Map
<
String
,
Object
>
map
=
new
HashMap
<>();
int
i
=
0
;
for
(
String
k
:
key
)
{
map
.
put
(
k
,
value
.
get
(
i
));
i
++;
}
return
map
;
}
public
Map
<
String
,
Object
>
getJson2Map
(
String
key
,
String
field
)
{
Map
<
String
,
Object
>
map
=
null
;
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
//String json = jedis.hget(key, field);
String
redisKey
=
String
.
format
(
"%s,%s"
,
key
,
field
);
String
json
=
jedis
.
get
(
redisKey
);
if
(!
Strings
.
isNullOrEmpty
(
json
))
{
map
=
JsonUtil
.
jsonToMap
(
json
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s$%s失败"
,
key
,
field
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
map
;
}
public
Map
<
String
,
Object
>
hgetJson2Map
(
String
key
,
String
field
)
{
Map
<
String
,
Object
>
map
=
null
;
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
String
json
=
jedis
.
hget
(
key
,
field
);
//String redisKey = String.format("%s,%s",key,field);
// String json = jedis.get(redisKey);
if
(!
Strings
.
isNullOrEmpty
(
json
))
{
map
=
JsonUtil
.
jsonToMap
(
json
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s$%s失败"
,
key
,
field
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
map
;
}
public
void
hset
(
String
key
,
String
field
,
String
value
)
{
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
jedis
.
hset
(
key
,
field
,
value
);
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"存储%s,%s,%s失败"
,
key
,
field
,
value
),
e
);
}
finally
{
close
(
jedis
);
}
}
}
public
boolean
set
(
String
key
,
String
value
)
{
if
(!
Strings
.
isNullOrEmpty
(
key
)
&&
!
Strings
.
isNullOrEmpty
(
value
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
jedis
.
set
(
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
false
;
}
public
boolean
del
(
String
key
)
{
if
(!
Strings
.
isNullOrEmpty
(
key
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
Long
l
=
jedis
.
del
(
key
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
false
;
}
public
void
close
(
Jedis
jedis
)
{
if
(
jedis
!=
null
)
{
try
{
jedis
.
close
();
}
catch
(
Exception
e
)
{
}
}
}
public
Jedis
getJedis
()
{
Jedis
jedis
=
null
;
try
{
jedis
=
(
Jedis
)
pool
.
getResource
();
}
catch
(
Exception
e
)
{
log
.
error
(
"获取jedis实体失败。"
+
e
.
getMessage
(),
e
);
}
return
jedis
;
}
public
String
getMember
(
String
key
,
double
longitude
,
double
latitude
,
double
radius
)
{
String
memberByString
=
null
;
Jedis
jedis
=
null
;
try
{
long
l
=
System
.
currentTimeMillis
();
jedis
=
getJedis
();
GeoRadiusParam
geoRadiusParam
=
GeoRadiusParam
.
geoRadiusParam
();
geoRadiusParam
.
sortAscending
().
count
(
1
);
List
<
GeoRadiusResponse
>
georadius
=
jedis
.
georadius
(
key
,
longitude
,
latitude
,
radius
,
GeoUnit
.
M
,
geoRadiusParam
);
if
(
georadius
!=
null
&&
!
georadius
.
isEmpty
())
{
memberByString
=
georadius
.
get
(
0
).
getMemberByString
();
}
log
.
debug
(
String
.
format
(
"从redis中获取高程数据耗时:%s"
,
(
System
.
currentTimeMillis
()
-
l
)));
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
return
memberByString
;
}
public
boolean
set
(
String
key
,
String
value
,
Long
expireTime
)
{
if
(!
Strings
.
isNullOrEmpty
(
key
)
&&
!
Strings
.
isNullOrEmpty
(
value
))
{
Jedis
jedis
=
null
;
try
{
jedis
=
getJedis
();
jedis
.
set
(
key
,
value
);
jedis
.
expire
(
key
,
expireTime
.
intValue
());
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
finally
{
close
(
jedis
);
}
}
return
false
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/TelecontrolModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.alibaba.fastjson.JSONObject
;
import
com.ssi.constant.URL
;
import
com.ssi.constant.VehicleConstant
;
import
com.ssi.constant.enums.Status
;
import
com.ssi.entity.VmsTosOrders
;
import
com.ssi.entity.dto.SwitchAutoParamDto
;
import
com.ssi.entity.dto.TelecontrolParamDto
;
import
com.ssi.response.SSIResponse
;
import
com.ssi.utils.RestTemplateUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
java.util.Map
;
/**
* @author ZhangLiYao
* @version 1.0
* @date 2020/7/23 10:23
*/
@Component
@Slf4j
public
class
TelecontrolModel
{
@Value
(
"${command-url}"
)
private
String
commandUrl
;
@Value
(
"${harbor.remote.vehicle_status}"
)
private
String
remoteControlStatusKeyPrefix
;
@Value
(
"${harbor.remote.overtime}"
)
private
String
debugAppOvertimePrefix
;
@Value
(
"${harbor.remote.overtimeTime}"
)
private
long
overtimeTime
;
@Value
(
"${harbor.remote.controlInfo}"
)
private
String
controlInfo
;
@Value
(
"${harbor.remote.socketOvertime}"
)
private
String
socketOvertimePrefix
;
@Value
(
"${harbor.remote.socketOvertimeTime}"
)
private
long
socketOvertimeTime
;
@Value
(
"${harbor.remote.throttleBrakeOperationValue}"
)
private
String
throttleBrakeOperationValuePrefix
;
@Value
(
"${harbor.remote.emergencyParking}"
)
private
String
emergencyParkingKeyPrefix
;
@Value
(
"${harbor.remote.autoPilot}"
)
private
String
autoPilotKeyPrefix
;
@Value
(
"${vehicle.latestData.redis.prefix}"
)
private
String
vehicleInfo
;
@Value
(
"${order.latestOrderKeyPrefix:harbor:command:status}"
)
private
String
latestOrderKeyPrefix
;
@Autowired
private
RedisDataModel
redisDataModel
;
public
SSIResponse
vehicleTelecontrol
(
TelecontrolParamDto
telecontrolParamDto
)
{
SSIResponse
ssiResponse
=
null
;
try
{
String
error
=
handleParam
(
telecontrolParamDto
);
if
(
StringUtils
.
isNotBlank
(
error
))
{
ssiResponse
=
SSIResponse
.
no
(
error
);
return
ssiResponse
;
}
if
(!
emergencyCheck
(
telecontrolParamDto
))
{
ssiResponse
=
SSIResponse
.
no
(
"车辆紧停中,请先解除紧停再操作!"
);
return
ssiResponse
;
}
//校验退出接管时,车速和油门是否为0
if
(
this
.
checkThrottle
(
telecontrolParamDto
)){
ssiResponse
=
SSIResponse
.
no
(
"车速或油门不为0,退出接管失败!"
);
return
ssiResponse
;
}
//添加当前任务信息
this
.
addCurrentTaskInfo
(
telecontrolParamDto
);
this
.
addZeroedValue
(
telecontrolParamDto
);
String
paramData
=
JSONObject
.
toJSONString
(
telecontrolParamDto
);
log
.
info
(
String
.
format
(
"app遥控车辆指令请求发送:----%s"
,
paramData
));
String
result
=
RestTemplateUtil
.
post
(
String
.
format
(
"%s%s"
,
commandUrl
,
URL
.
TELECONTROL_URL
),
paramData
,
null
);
log
.
info
(
String
.
format
(
"app遥控车辆指令请求发送返回结果:----%s"
,
result
));
ssiResponse
=
handleResult
(
result
,
telecontrolParamDto
);
}
catch
(
Exception
e
)
{
log
.
error
(
"请求失败:"
,
e
);
ssiResponse
=
SSIResponse
.
no
(
"请求失败"
);
}
finally
{
//退出接管失败持续下发
if
(
ssiResponse
.
getCode
()
==
-
1
&&
telecontrolParamDto
.
getControlType
()
==
1
&&
telecontrolParamDto
.
getOperationValue
()
==
2
)
{
ssiResponse
=
continueCloseControl
(
telecontrolParamDto
);
}
}
this
.
handleOvertime
(
telecontrolParamDto
,
ssiResponse
);
this
.
setLastThrottleBrakeOperationValue
(
telecontrolParamDto
,
ssiResponse
);
return
ssiResponse
;
}
private
void
addCurrentTaskInfo
(
TelecontrolParamDto
telecontrolParamDto
)
{
Map
<
String
,
Object
>
json2Map
=
redisDataModel
.
getJson2Map
(
String
.
format
(
"%s:%s"
,
latestOrderKeyPrefix
,
telecontrolParamDto
.
getVin
()));
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
JSONObject
.
toJSONString
(
json2Map
));
VmsTosOrders
vmsTosOrders
=
JSONObject
.
toJavaObject
(
jsonObject
,
VmsTosOrders
.
class
);
telecontrolParamDto
.
setTaskId
(
vmsTosOrders
.
getTaskNo
().
concat
(
","
).
concat
(
vmsTosOrders
.
getTaskNoMapping
()));
}
//校验退出接管时,车速和油门是否为0
private
boolean
checkThrottle
(
TelecontrolParamDto
teleDto
)
{
if
(
teleDto
.
getControlType
()
!=
VehicleConstant
.
TELE_CONTROL_TYPE_TAKE_OVER
||
teleDto
.
getOperationValue
()
!=
2
){
return
false
;
}
String
controlCache
=
redisDataModel
.
get
(
controlInfo
+
":"
+
teleDto
.
getVin
());
if
(
StringUtils
.
isBlank
(
controlCache
)){
return
false
;
}
JSONObject
controlJson
=
JSONObject
.
parseObject
(
controlCache
);
//获取油门值
if
(
controlJson
.
get
(
"7"
)
!=
null
&&
controlJson
.
getInteger
(
"7"
)
>
0
){
return
true
;
}
//获取车速
String
vehicleCache
=
redisDataModel
.
get
(
vehicleInfo
+
":"
+
teleDto
.
getVin
()+
"-harbor_D00A"
);
if
(
StringUtils
.
isBlank
(
vehicleCache
)){
return
false
;
}
JSONObject
vehicleJson
=
JSONObject
.
parseObject
(
vehicleCache
);
if
(
vehicleJson
.
get
(
"speed"
)
!=
null
&&
vehicleJson
.
getDouble
(
"speed"
)
>
0
){
return
true
;
}
return
false
;
}
/**
* 处理回话超时
* @param telecontrolParamDto
* @param ssiResponse
*/
public
void
handleOvertime
(
TelecontrolParamDto
telecontrolParamDto
,
SSIResponse
ssiResponse
)
{
boolean
isTakeOverCommand
=
TelecontrolParamDto
.
isTakeOverCommand
(
telecontrolParamDto
);
boolean
isCancelTakeOver
=
TelecontrolParamDto
.
isCancelTakeOverCommand
(
telecontrolParamDto
);
String
vin
=
telecontrolParamDto
.
getVin
();
String
appMac
=
telecontrolParamDto
.
getAppMac
();
if
(
vin
!=
null
&&
appMac
!=
null
)
{
int
code
=
ssiResponse
.
getCode
();
if
(
isCancelTakeOver
&&
(
code
==
Status
.
SUCCESS
.
getCode
()))
{
redisDataModel
.
del
(
debugAppOvertimePrefix
+
":"
+
vin
+
":"
+
appMac
);
}
if
((!
isCancelTakeOver
&&
!
isTakeOverCommand
)
||
(
isTakeOverCommand
&&
(
code
==
Status
.
SUCCESS
.
getCode
())))
{
redisDataModel
.
set
(
debugAppOvertimePrefix
+
":"
+
vin
+
"&"
+
appMac
,
"1"
,
overtimeTime
);
}
}
}
/**
* 油门到刹车 刹车到油门 要添加置0标识
*
* @param telecontrolParamDto
*/
public
void
addZeroedValue
(
TelecontrolParamDto
telecontrolParamDto
)
{
Integer
operationType
=
telecontrolParamDto
.
getOperationType
();
// 7: 油门刹车操作
if
(
operationType
==
7
)
{
Integer
zeroed
=
telecontrolParamDto
.
getZeroed
();
//已经有置0标识值则不处理
if
(
zeroed
==
0
)
{
Integer
currentOperationValue
=
telecontrolParamDto
.
getOperationValue
();
int
lastOperationValue
=
getLastThrottleBrakeOperationValue
(
telecontrolParamDto
.
getVin
());
if
(
currentOperationValue
>
0
&&
lastOperationValue
<
0
)
{
telecontrolParamDto
.
setZeroed
(
1
);
}
if
(
currentOperationValue
<
0
&&
lastOperationValue
>
0
)
{
telecontrolParamDto
.
setZeroed
(-
1
);
}
}
}
}
/**
* 获取上一个油门刹车OperationValue的值
*
* @param vin
*/
public
int
getLastThrottleBrakeOperationValue
(
String
vin
)
{
String
val
=
redisDataModel
.
get
(
throttleBrakeOperationValuePrefix
+
":"
+
vin
);
if
(
StringUtils
.
isNotBlank
(
val
))
{
return
Integer
.
parseInt
(
val
);
}
return
0
;
}
/**
* 设置最新的油门刹车OperationValue的值
*
* @param telecontrolParamDto
*/
public
void
setLastThrottleBrakeOperationValue
(
TelecontrolParamDto
telecontrolParamDto
,
SSIResponse
ssiResponse
)
{
Integer
operationType
=
telecontrolParamDto
.
getOperationType
();
boolean
success
=
ssiResponse
.
getCode
()
==
Status
.
SUCCESS
.
getCode
();
// 7: 油门刹车操作
if
(
operationType
==
7
&&
success
)
{
String
vin
=
telecontrolParamDto
.
getVin
();
Integer
operationValue
=
telecontrolParamDto
.
getOperationValue
();
redisDataModel
.
set
(
throttleBrakeOperationValuePrefix
+
":"
+
vin
,
String
.
valueOf
(
operationValue
));
}
}
/**
* 退出接管失败再重试三次
* @param telecontrolParamDto
* @return
*/
private
SSIResponse
continueCloseControl
(
TelecontrolParamDto
telecontrolParamDto
)
{
int
tryTimes
=
3
;
int
count
=
0
;
SSIResponse
ssiResponse
=
null
;
do
{
try
{
String
paramData
=
JSONObject
.
toJSONString
(
telecontrolParamDto
);
String
result
=
RestTemplateUtil
.
post
(
String
.
format
(
"%s%s"
,
commandUrl
,
URL
.
TELECONTROL_URL
),
paramData
,
null
);
ssiResponse
=
handleResult
(
result
,
telecontrolParamDto
);
count
++;
}
catch
(
Exception
e
)
{
log
.
error
(
"重复请求请求失败:"
,
e
);
ssiResponse
=
SSIResponse
.
no
(
"请求失败"
);
}
}
while
(
ssiResponse
.
getCode
()
==
-
1
&&
count
<
tryTimes
);
return
ssiResponse
;
}
private
String
handleParam
(
TelecontrolParamDto
telecontrolParamDto
)
{
if
(
telecontrolParamDto
.
getControlType
()
==
2
&&
telecontrolParamDto
.
getOperationType
()
==
null
)
{
return
"常规操作,操作类型不能为空"
;
}
return
null
;
}
private
SSIResponse
handleResult
(
String
result
,
TelecontrolParamDto
teleDto
)
{
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
result
);
String
code
=
jsonObject
.
getJSONObject
(
"status"
).
getString
(
"code"
);
String
details
=
jsonObject
.
getJSONObject
(
"status"
).
getString
(
"details"
);
if
(!
"0000"
.
equals
(
code
))
{
log
.
error
(
details
);
return
SSIResponse
.
no
(
details
);
}
if
(
StringUtils
.
isNotBlank
(
jsonObject
.
getString
(
"data"
)))
{
String
ADCUStatus
=
jsonObject
.
getJSONObject
(
"data"
).
getString
(
"ADCUStatus"
);
if
(
"1"
.
equals
(
ADCUStatus
))
{
log
.
error
(
"ADCU正在控车"
);
return
SSIResponse
.
no
(
"ADCU正在控车"
);
}
}
if
(
teleDto
.
getControlType
()
==
VehicleConstant
.
TELE_CONTROL_TYPE_TAKE_OVER
){
String
info
=
redisDataModel
.
get
(
controlInfo
+
":"
+
teleDto
.
getVin
());
return
SSIResponse
.
ok
(
info
);
}
else
{
String
info
=
redisDataModel
.
get
(
controlInfo
+
":"
+
teleDto
.
getVin
());
JSONObject
operJson
=
null
;
if
(
StringUtils
.
isBlank
(
info
)){
operJson
=
new
JSONObject
();
}
else
{
operJson
=
JSONObject
.
parseObject
(
info
);
}
if
(
teleDto
.
getOperationType
()
==
1
||
teleDto
.
getOperationType
()
==
6
){
operJson
.
put
(
String
.
valueOf
(
6
),
2
);
}
else
if
(
teleDto
.
getOperationType
()
!=
7
||
teleDto
.
getOperationType
()
<
0
){
operJson
.
put
(
String
.
valueOf
(
teleDto
.
getOperationType
()),
teleDto
.
getOperationValue
());
}
redisDataModel
.
set
(
controlInfo
+
":"
+
teleDto
.
getVin
(),
operJson
.
toString
());
}
/* String dataResult = jsonObject.getJSONObject("data").getString("result");
if (!"1".equals(dataResult)
&& !"17".equals(dataResult)
&& !"33".equals(dataResult)
&& !"49".equals(dataResult)) {
log.error(String.format("指令执行失败"));
return SSIResponse.no("指令执行失败");
}*/
return
SSIResponse
.
ok
();
}
public
Map
getControlStatus
(
String
vin
)
{
String
key
=
String
.
format
(
"%s:%s"
,
remoteControlStatusKeyPrefix
,
vin
);
return
redisDataModel
.
getJson2Map
(
key
);
}
public
Map
getEmergencyStatus
(
String
vin
)
{
String
key
=
String
.
format
(
"%s:%s"
,
emergencyParkingKeyPrefix
,
vin
);
return
redisDataModel
.
getJson2Map
(
key
);
}
public
Map
getAutoPilotStatus
(
String
vin
)
{
String
key
=
String
.
format
(
"%s:%s"
,
autoPilotKeyPrefix
,
vin
);
return
redisDataModel
.
getJson2Map
(
key
);
}
public
SSIResponse
breakVehicle
(
String
vin
)
{
TelecontrolParamDto
paramDto
=
new
TelecontrolParamDto
();
paramDto
.
setVin
(
vin
);
paramDto
.
setControlType
(
2
);
paramDto
.
setOperationType
(
7
);
paramDto
.
setOperationValue
(-
75
);
paramDto
.
setZeroed
(-
1
);
return
vehicleTelecontrol
(
paramDto
);
}
public
void
setOrRefreshSocketOvertime
(
String
sessionId
,
String
vin
)
{
redisDataModel
.
set
(
socketOvertimePrefix
+
":"
+
sessionId
+
":"
+
vin
,
vin
,
socketOvertimeTime
);
}
public
void
deleteSocketOvertime
(
String
sessionId
,
String
vin
)
{
redisDataModel
.
del
(
socketOvertimePrefix
+
":"
+
sessionId
+
":"
+
vin
);
}
/**
* 除取消接管操作外,紧停状态下其他操作不能操作
* @param telecontrolParamDto
* @return
*/
public
boolean
emergencyCheck
(
TelecontrolParamDto
telecontrolParamDto
)
{
Integer
controlType
=
telecontrolParamDto
.
getControlType
();
Integer
operationValue
=
telecontrolParamDto
.
getOperationValue
();
//除取消接管操作外,紧停状态下其他操作不能操作
if
(!(
controlType
==
1
&&
operationValue
==
2
))
{
String
vin
=
telecontrolParamDto
.
getVin
();
String
key
=
String
.
format
(
"%s:%s"
,
emergencyParkingKeyPrefix
,
vin
);
Map
<
String
,
Object
>
eMap
=
redisDataModel
.
getJson2Map
(
key
);
if
(
eMap
!=
null
)
{
Integer
emergencyStatus
=
(
Integer
)
eMap
.
get
(
"emergencyStatus"
);
if
(
emergencyStatus
==
1
)
{
return
false
;
}
}
}
return
true
;
}
/**
* 切换自动驾驶
* @return
*/
public
SSIResponse
switchAutopilot
(
SwitchAutoParamDto
paramDto
)
{
String
result
=
RestTemplateUtil
.
post
(
String
.
format
(
"%s%s"
,
commandUrl
,
URL
.
SWITCHAUTO_URL
),
JSONObject
.
toJSONString
(
paramDto
),
null
);
return
handleResult
(
result
);
}
private
SSIResponse
handleResult
(
String
result
)
{
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
result
);
String
code
=
jsonObject
.
getJSONObject
(
"status"
).
getString
(
"code"
);
String
details
=
jsonObject
.
getJSONObject
(
"status"
).
getString
(
"details"
);
if
(!
"0000"
.
equals
(
code
))
{
log
.
error
(
details
);
return
SSIResponse
.
no
(
details
);
}
return
SSIResponse
.
ok
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/VehicleBaseInfoModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.alicp.jetcache.anno.CacheRefresh
;
import
com.alicp.jetcache.anno.Cached
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.ssi.entity.VmsVehicle
;
import
com.ssi.mapper.VehicleTboxMapper
;
import
com.ssi.mapper.VmsVehicleMapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
/**
* Description: jetcahe 一般配置在Model层或service接口层
*
* @author LiXiaoCong
* @version 2019/8/20 14:00
*/
@Component
public
class
VehicleBaseInfoModel
{
@Autowired
private
VehicleTboxMapper
vehicleTboxMapper
;
@Autowired
private
VmsVehicleMapper
vehicleMapper
;
@Cached
(
name
=
"mlVehicleBaseInfoModel:getVehicleBaseInfo"
,
expire
=
120
,
timeUnit
=
TimeUnit
.
MINUTES
)
@CacheRefresh
(
refresh
=
5
,
stopRefreshAfterLastAccess
=
1440
,
timeUnit
=
TimeUnit
.
MINUTES
)
public
Map
<
String
,
Object
>
getVehicleBaseInfo
(
@Param
(
"vin"
)
String
vin
)
{
return
vehicleTboxMapper
.
getVehicleBaseInfo
(
vin
);
}
// @Cached(name = "mlVehicleBaseInfoModel:getAllVehicleInfo", expire = 120, timeUnit = TimeUnit.MINUTES)
// @CacheRefresh(refresh = 5, stopRefreshAfterLastAccess = 1440, timeUnit = TimeUnit.MINUTES)
public
List
<
VmsVehicle
>
getAllVehicleInfo
()
{
List
<
VmsVehicle
>
list
=
vehicleMapper
.
selectList
(
null
);
return
list
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/VehicleElasticSearchModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.ssi.constant.enums.VmsTosOrderStatusEnum
;
import
com.ssi.entity.ScrollTrackLocationEntity
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.google.common.collect.Sets
;
import
com.ssi.entity.vo.TaskStatusHistory
;
import
com.ssi.response.SSIResponse
;
import
com.ssi.utils.ElasticSearchUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.elasticsearch.action.search.SearchRequestBuilder
;
import
org.elasticsearch.action.search.SearchResponse
;
import
org.elasticsearch.action.search.SearchScrollRequest
;
import
org.elasticsearch.client.RequestOptions
;
import
org.elasticsearch.common.unit.TimeValue
;
import
org.elasticsearch.index.query.BoolQueryBuilder
;
import
org.elasticsearch.index.query.QueryBuilders
;
import
org.elasticsearch.index.query.RangeQueryBuilder
;
import
org.elasticsearch.search.Scroll
;
import
org.elasticsearch.search.SearchHit
;
import
org.elasticsearch.search.SearchHits
;
import
org.elasticsearch.search.sort.FieldSortBuilder
;
import
org.elasticsearch.search.sort.SortOrder
;
import
org.springframework.stereotype.Component
;
import
java.util.*
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
/*
* 默认index 名称 和type 名称一致。
* */
@Component
@Slf4j
public
class
VehicleElasticSearchModel
extends
ElasticSearchModel
{
public
SSIResponse
searchAllTrackLocations
(
String
vin
,
String
indexName
,
String
indexRule
,
Set
<
String
>
columns
,
String
timeField
,
Long
startTime
,
Long
stopTime
,
String
posType
)
{
SearchRequestBuilder
searchRequestBuilder
=
elasticSearchMetaModel
.
newSearchRequestBuilderInDayIndex
(
startTime
,
stopTime
,
indexName
,
1
,
true
,
indexRule
);
Map
<
String
,
Object
>
res
=
Maps
.
newHashMap
();
if
(
searchRequestBuilder
!=
null
)
{
int
size
=
10000
;
SearchResponse
searchResponse
;
searchResponse
=
getSearchResponse
(
columns
,
searchRequestBuilder
,
timeField
,
vin
,
startTime
,
stopTime
,
size
);
long
total
=
0
l
;
List
<
Map
<
String
,
Object
>>
trips
=
Lists
.
newArrayList
();
SearchHits
hits
=
searchResponse
.
getHits
();
SearchHit
[]
searchHits
=
hits
.
getHits
();
//movingAveragePoints(searchHits, 10);
filterJumpPoint
(
searchHits
);
while
(
searchHits
!=
null
&&
searchHits
.
length
>
0
)
{
long
hitsTotal
=
hits
.
getTotalHits
();
List
<
Map
<
String
,
Object
>>
hitsTrip
=
Arrays
.
stream
(
searchHits
).
parallel
().
filter
(
hit
->
{
Map
<
String
,
Object
>
sourceAsMap
=
hit
.
getSourceAsMap
();
if
(
sourceAsMap
.
get
(
"abnormal"
)
!=
null
&&
(
int
)
sourceAsMap
.
get
(
"abnormal"
)
==
1
)
{
return
false
;
}
return
true
;
}).
map
(
hit
->
{
Map
<
String
,
Object
>
sourceAsMap
=
hit
.
getSourceAsMap
();
if
(
posType
!=
null
)
{
locationTypeChange
(
sourceAsMap
,
posType
,
"longitude"
,
"latitude"
);
}
return
sourceAsMap
;
}).
collect
(
Collectors
.
toList
());
trips
.
addAll
(
hitsTrip
);
if
(
searchHits
.
length
==
size
)
{
searchResponse
=
transportClient
.
prepareSearchScroll
(
searchResponse
.
getScrollId
())
.
setScroll
(
TimeValue
.
timeValueMinutes
(
5
)).
get
();
searchHits
=
searchResponse
.
getHits
().
getHits
();
}
else
{
break
;
}
}
res
.
put
(
"total"
,
total
);
res
.
put
(
"records"
,
trips
);
}
else
{
res
.
put
(
"total"
,
0L
);
res
.
put
(
"records"
,
Lists
.
newArrayList
());
}
return
SSIResponse
.
ok
(
res
.
get
(
"records"
));
// return res;
}
/**
* 移动平均轨迹平滑方法
*/
public
void
movingAveragePoints
(
SearchHit
[]
searchHits
,
int
length
)
{
for
(
int
i
=
length
-
1
;
i
<
searchHits
.
length
;
i
++)
{
Double
sumLon
=
0
d
;
Double
sumLat
=
0
d
;
for
(
int
j
=
0
;
j
<
length
;
j
++)
{
SearchHit
hit
=
searchHits
[
i
-
j
];
Map
<
String
,
Object
>
sourceAsMap
=
hit
.
getSourceAsMap
();
Double
longitude
=
Double
.
parseDouble
(
sourceAsMap
.
get
(
"longitude"
).
toString
());
Double
latitude
=
Double
.
parseDouble
(
sourceAsMap
.
get
(
"latitude"
).
toString
());
sumLon
+=
longitude
;
sumLat
+=
latitude
;
}
Double
avgLon
=
sumLon
/
length
;
Double
avgLat
=
sumLat
/
length
;
SearchHit
searchHit
=
searchHits
[
i
-
length
+
1
];
Map
<
String
,
Object
>
sourceAsMap
=
searchHit
.
getSourceAsMap
();
sourceAsMap
.
put
(
"longitude"
,
avgLon
);
sourceAsMap
.
put
(
"latitude"
,
avgLat
);
double
[]
newLocation
=
{
avgLon
,
avgLat
};
sourceAsMap
.
put
(
"location"
,
newLocation
);
}
}
/**
* 轨迹跳点过滤
*/
public
void
filterJumpPoint
(
SearchHit
[]
searchHits
)
{
SearchHit
last1
=
null
;
for
(
int
i
=
1
;
i
<
searchHits
.
length
;
i
++)
{
SearchHit
hit
=
searchHits
[
i
];
Map
<
String
,
Object
>
sourceAsMap
=
hit
.
getSourceAsMap
();
Long
collectTime
=
Long
.
parseLong
(
sourceAsMap
.
get
(
"collectTime"
).
toString
());
Double
longitude
=
Double
.
parseDouble
(
sourceAsMap
.
get
(
"longitude"
).
toString
());
Double
latitude
=
Double
.
parseDouble
(
sourceAsMap
.
get
(
"latitude"
).
toString
());
if
(
last1
==
null
)
{
last1
=
hit
;
}
else
{
Long
lastCollectTime1
=
Long
.
parseLong
(
last1
.
getSourceAsMap
().
get
(
"collectTime"
).
toString
());
long
diffTime
=
collectTime
-
lastCollectTime1
;
if
(
diffTime
==
0
)
{
diffTime
=
1000L
;
}
Double
lastlongitude1
=
Double
.
parseDouble
(
last1
.
getSourceAsMap
().
get
(
"longitude"
).
toString
());
Double
lastLatitude1
=
Double
.
parseDouble
(
last1
.
getSourceAsMap
().
get
(
"latitude"
).
toString
());
double
diffLon
=
longitude
-
lastlongitude1
;
double
diffLat
=
latitude
-
lastLatitude1
;
if
(
Math
.
abs
(
diffLat
*
1000000
)
>
15
*
diffTime
/
1000
)
{
sourceAsMap
.
put
(
"abnormal"
,
1
);
continue
;
}
if
(
Math
.
abs
(
diffLon
*
100000
)
>
1.7
*
diffTime
/
1000
)
{
sourceAsMap
.
put
(
"abnormal"
,
1
);
continue
;
}
last1
=
hit
;
}
}
}
private
SearchResponse
getSearchResponse
(
Set
<
String
>
columns
,
SearchRequestBuilder
searchRequestBuilder
,
String
timeField
,
String
vin
,
Long
startTime
,
Long
stopTime
,
int
size
)
{
if
(
columns
!=
null
&&
columns
.
size
()
>
0
)
{
//确保行程关键字段不缺失
columns
.
add
(
"id"
);
columns
.
add
(
"vin"
);
columns
.
add
(
timeField
);
columns
.
add
(
"longitude"
);
columns
.
add
(
"latitude"
);
searchRequestBuilder
.
setFetchSource
(
columns
.
toArray
(
new
String
[
columns
.
size
()]),
null
);
}
BoolQueryBuilder
queryBuilder
=
createBooleanQueryBuilderWithChinaLocation
();
queryBuilder
.
mustNot
(
QueryBuilders
.
termQuery
(
"keyOnStatus"
,
-
1
));
if
(
vin
!=
null
)
{
queryBuilder
.
must
(
QueryBuilders
.
termQuery
(
"vin"
,
vin
));
}
RangeQueryBuilder
rangeQueryBuilder
=
ElasticSearchUtil
.
createRangeQueryBuilder
(
timeField
,
startTime
,
stopTime
);
if
(
rangeQueryBuilder
!=
null
)
{
queryBuilder
.
must
(
rangeQueryBuilder
);
}
return
searchRequestBuilder
.
setQuery
(
queryBuilder
)
.
addSort
(
timeField
,
SortOrder
.
ASC
)
.
setScroll
(
TimeValue
.
timeValueMinutes
(
5
))
.
setSize
(
size
)
.
get
();
}
/**
* 深分页轨迹查询
*/
public
SSIResponse
searchScrollTrackLocations
(
String
indexName
,
String
indexRule
,
String
timeField
,
ScrollTrackLocationEntity
scrollTrackLocationEntity
)
{
Map
<
String
,
Object
>
res
=
Maps
.
newHashMap
();
long
t
=
System
.
currentTimeMillis
();
String
[]
indexs
=
elasticSearchMetaModel
.
getIndexs
(
scrollTrackLocationEntity
.
getStartTime
(),
scrollTrackLocationEntity
.
getStopTime
(),
indexName
,
1
,
true
,
indexRule
);
if
(
indexs
.
length
>
0
)
{
SearchResponse
searchResponse
;
if
(
scrollTrackLocationEntity
.
getScrollId
()
==
null
)
{
SearchRequestBuilder
requestBuilder
=
transportClient
.
prepareSearch
(
indexs
)
.
setTypes
(
indexName
);
//设置筛选条件
BoolQueryBuilder
queryBuilder
=
addQueryCondition
(
createBooleanQueryBuilderWithChinaLocation
(),
scrollTrackLocationEntity
.
getVin
(),
timeField
,
scrollTrackLocationEntity
.
getStartTime
(),
scrollTrackLocationEntity
.
getStopTime
());
queryBuilder
.
mustNot
(
QueryBuilders
.
termQuery
(
"keyOnStatus"
,
-
1
));
requestBuilder
.
setQuery
(
queryBuilder
);
//设置抓取字段
String
[]
columns
=
scrollTrackLocationEntity
.
getColumns
();
Set
<
String
>
returnColumns
=
Sets
.
newHashSet
(
"vin"
,
timeField
,
"longitude"
,
"latitude"
,
"collectTime"
);
if
(
columns
!=
null
)
{
Arrays
.
stream
(
columns
).
forEach
(
returnColumns:
:
add
);
}
requestBuilder
.
setFetchSource
(
returnColumns
.
toArray
(
new
String
[
returnColumns
.
size
()]),
null
);
//检查是否需要排序
if
(
scrollTrackLocationEntity
.
isSortByTime
())
{
requestBuilder
.
addSort
(
timeField
,
SortOrder
.
ASC
);
}
else
{
requestBuilder
.
addSort
(
FieldSortBuilder
.
DOC_FIELD_NAME
,
SortOrder
.
ASC
);
}
requestBuilder
.
setScroll
(
TimeValue
.
timeValueMinutes
(
5
));
requestBuilder
.
setSize
(
scrollTrackLocationEntity
.
getMaxSizePartition
());
searchResponse
=
requestBuilder
.
get
();
}
else
{
searchResponse
=
transportClient
.
prepareSearchScroll
(
scrollTrackLocationEntity
.
getScrollId
())
.
setScroll
(
TimeValue
.
timeValueMinutes
(
5
)).
get
();
}
List
<
Map
<
String
,
Object
>>
maps
=
Lists
.
newLinkedList
();
//遍历结果
SearchHits
hits
=
searchResponse
.
getHits
();
SearchHit
[]
hitArray
=
hits
.
getHits
();
Map
<
String
,
Object
>
sourceAsMap
;
//跳点步长
int
stepLength
=
scrollTrackLocationEntity
.
getStepLength
();
for
(
int
i
=
0
;
i
<
hitArray
.
length
;
i
=
i
+
stepLength
)
{
sourceAsMap
=
hitArray
[
i
].
getSourceAsMap
();
if
(
scrollTrackLocationEntity
.
getPosType
()
!=
null
)
{
locationTypeChange
(
sourceAsMap
,
scrollTrackLocationEntity
.
getPosType
(),
"longitude"
,
"latitude"
);
}
maps
.
add
(
sourceAsMap
);
}
if
(
maps
.
size
()
>
0
)
{
res
.
put
(
"total"
,
hits
.
totalHits
);
res
.
put
(
"records"
,
maps
);
res
.
put
(
"size"
,
maps
.
size
());
}
else
{
res
=
emptySearchHitResult
();
}
res
.
put
(
"over"
,
(
hitArray
.
length
==
0
)
||
(
hitArray
.
length
==
hits
.
totalHits
));
res
.
put
(
"scrollId"
,
searchResponse
.
getScrollId
());
}
return
SSIResponse
.
ok
(
res
);
// return res;
}
private
BoolQueryBuilder
addQueryCondition
(
BoolQueryBuilder
builder
,
String
vin
,
String
timeField
,
Long
startTime
,
Long
stopTime
)
{
if
(
vin
!=
null
)
{
builder
.
must
(
QueryBuilders
.
termsQuery
(
"vin"
,
vin
));
}
if
(
startTime
!=
null
||
stopTime
!=
null
)
{
RangeQueryBuilder
rangeQueryBuilder
=
QueryBuilders
.
rangeQuery
(
timeField
);
if
(
startTime
!=
null
)
{
rangeQueryBuilder
.
gte
(
startTime
);
}
if
(
stopTime
!=
null
)
{
rangeQueryBuilder
.
lte
(
stopTime
);
}
builder
.
must
(
rangeQueryBuilder
);
}
return
builder
;
}
public
Map
<
String
,
Object
>
getOfflineVehicleList
(
String
indexName
,
String
timeField
,
String
vehicleCompany
,
String
vehicleType
,
Integer
offlineDays
,
int
page
,
int
size
)
{
SearchRequestBuilder
searchRequestBuilder
=
transportClient
.
prepareSearch
(
String
.
format
(
"%s_latest"
,
indexName
));
RangeQueryBuilder
rangeQueryBuilder
=
null
;
BoolQueryBuilder
queryBuilder
=
createBooleanQueryBuilderWithChinaLocation
();
if
(
offlineDays
!=
null
)
{
rangeQueryBuilder
=
QueryBuilders
.
rangeQuery
(
timeField
);
Long
endTime
=
System
.
currentTimeMillis
()
-
offlineDays
*
24
*
60
*
60
*
1000
;
rangeQueryBuilder
.
lte
(
endTime
);
}
if
(
rangeQueryBuilder
!=
null
)
{
queryBuilder
.
must
(
rangeQueryBuilder
);
}
if
(
StringUtils
.
isNotBlank
(
vehicleType
))
{
queryBuilder
.
must
(
QueryBuilders
.
termQuery
(
"vehicleType"
,
vehicleType
));
}
if
(
StringUtils
.
isNotBlank
(
vehicleCompany
))
{
queryBuilder
.
must
(
QueryBuilders
.
termQuery
(
"vehicleCompany"
,
vehicleCompany
));
}
int
start
=
(
page
-
1
)
*
10
;
SearchResponse
searchResponse
=
searchRequestBuilder
.
setQuery
(
queryBuilder
)
.
addSort
(
timeField
,
SortOrder
.
ASC
)
.
setSize
(
size
)
.
setFrom
(
start
)
.
get
();
return
extractSearchHits
(
searchResponse
.
getHits
());
}
/**
* 获取任务历史数据
*/
public
List
<
TaskStatusHistory
>
searchTaskHistory
(
String
taskNo
,
String
year
)
{
SearchRequestBuilder
requestBuilder
=
transportClient
.
prepareSearch
(
"harbor_order_status_"
+
year
).
setTypes
(
"harbor_order_status"
);
BoolQueryBuilder
boolQueryBuilder
=
QueryBuilders
.
boolQuery
();
boolQueryBuilder
.
must
(
QueryBuilders
.
termQuery
(
"sn"
,
taskNo
));
boolQueryBuilder
.
must
(
QueryBuilders
.
existsQuery
(
"status"
));
Set
<
String
>
returnColumns
=
Sets
.
newHashSet
(
"vin"
,
"sn"
,
"status"
,
"collectTime"
,
"errorMessage"
);
SearchResponse
response
=
requestBuilder
.
setQuery
(
boolQueryBuilder
)
.
setFetchSource
(
returnColumns
.
toArray
(
new
String
[
returnColumns
.
size
()]),
null
)
.
addSort
(
"collectTime"
,
SortOrder
.
ASC
)
.
get
();
SearchHit
[]
hits
=
response
.
getHits
().
getHits
();
List
<
TaskStatusHistory
>
list
=
Stream
.
of
(
hits
).
map
(
hit
->
{
String
sourceAsString
=
hit
.
getSourceAsString
();
TaskStatusHistory
taskStatusHistory
=
JSON
.
parseObject
(
sourceAsString
,
TaskStatusHistory
.
class
);
VmsTosOrderStatusEnum
anEnum
=
VmsTosOrderStatusEnum
.
find
(
taskStatusHistory
.
getStatus
());
if
(
anEnum
!=
null
)
{
taskStatusHistory
.
setStatusDescription
(
anEnum
.
getDescription
());
}
return
taskStatusHistory
;
}).
collect
(
Collectors
.
toList
());
return
list
;
}
/**
* 批量获取任务历史数据
*/
public
Map
<
String
,
List
<
TaskStatusHistory
>>
searchTaskHistory
(
List
<
String
>
taskNoList
,
String
year
)
{
SearchRequestBuilder
requestBuilder
=
transportClient
.
prepareSearch
(
"harbor_order_status_"
+
year
).
setTypes
(
"harbor_order_status"
);
BoolQueryBuilder
boolQueryBuilder
=
QueryBuilders
.
boolQuery
();
boolQueryBuilder
.
must
(
QueryBuilders
.
termsQuery
(
"sn"
,
taskNoList
));
boolQueryBuilder
.
must
(
QueryBuilders
.
existsQuery
(
"status"
));
Set
<
String
>
returnColumns
=
Sets
.
newHashSet
(
"vin"
,
"sn"
,
"status"
,
"collectTime"
,
"errorMessage"
);
Scroll
scroll
=
new
Scroll
(
TimeValue
.
timeValueMinutes
(
10L
));
SearchResponse
response
=
requestBuilder
.
setQuery
(
boolQueryBuilder
)
.
setFetchSource
(
returnColumns
.
toArray
(
new
String
[
returnColumns
.
size
()]),
null
)
.
addSort
(
"collectTime"
,
SortOrder
.
ASC
)
.
setScroll
(
scroll
)
.
setSize
(
2000
)
.
get
();
//结果集为升序排序
SearchHit
[]
hits
=
response
.
getHits
().
getHits
();
Map
<
String
,
List
<
TaskStatusHistory
>>
statusMap
=
new
HashMap
<>();
boolean
needContinue
=
true
;
while
(
hits
!=
null
&&
hits
.
length
>
0
&&
needContinue
)
{
for
(
SearchHit
hit
:
hits
)
{
String
sourceAsString
=
hit
.
getSourceAsString
();
TaskStatusHistory
taskStatusHistory
=
JSON
.
parseObject
(
sourceAsString
,
TaskStatusHistory
.
class
);
VmsTosOrderStatusEnum
anEnum
=
VmsTosOrderStatusEnum
.
find
(
taskStatusHistory
.
getStatus
());
if
(
anEnum
!=
null
)
{
taskStatusHistory
.
setStatusDescription
(
anEnum
.
getDescription
());
}
else
{
//移除未知状态
continue
;
}
if
(
statusMap
.
get
(
taskStatusHistory
.
getSn
())
==
null
)
{
List
<
TaskStatusHistory
>
list
=
new
ArrayList
<>();
list
.
add
(
taskStatusHistory
);
statusMap
.
put
(
taskStatusHistory
.
getSn
(),
list
);
}
else
{
List
<
TaskStatusHistory
>
list
=
statusMap
.
get
(
taskStatusHistory
.
getSn
());
list
.
add
(
taskStatusHistory
);
statusMap
.
put
(
taskStatusHistory
.
getSn
(),
list
);
}
}
if
(
hits
.
length
==
2000
)
{
response
=
transportClient
.
prepareSearchScroll
(
response
.
getScrollId
())
.
setScroll
(
TimeValue
.
timeValueMinutes
(
5
)).
get
();
hits
=
response
.
getHits
().
getHits
();
}
else
{
needContinue
=
false
;
}
}
transportClient
.
prepareClearScroll
();
return
statusMap
;
}
/**
* 获取车辆最近车况数据
*/
public
Map
searchLatestVehicleData
(
String
vin
)
{
SearchRequestBuilder
requestBuilder
=
transportClient
.
prepareSearch
(
"vms_igv_vehicle_latest"
)
.
setTypes
(
"vms_igv_vehicle"
);
BoolQueryBuilder
boolQueryBuilder
=
QueryBuilders
.
boolQuery
();
boolQueryBuilder
.
must
(
QueryBuilders
.
termQuery
(
"vin"
,
vin
));
SearchResponse
response
=
requestBuilder
.
setQuery
(
boolQueryBuilder
)
.
get
();
SearchHit
[]
hits
=
response
.
getHits
().
getHits
();
if
(
hits
!=
null
&&
hits
.
length
>
0
)
{
SearchHit
hit
=
hits
[
0
];
String
jsonStr
=
hit
.
getSourceAsString
();
JSONObject
object
=
JSON
.
parseObject
(
jsonStr
);
return
object
;
}
return
null
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/VehicleLatestDataModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
;
import
com.google.common.base.Splitter
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.ssi.constant.RedisKey
;
import
com.ssi.constant.VehicleConstant
;
import
com.ssi.constant.enums.VmsTosOrderStatusEnum
;
import
com.ssi.entity.VmsIndividuationConfig
;
import
com.ssi.entity.dto.Point
;
import
com.ssi.mapper.VmsIndividuationConfigMapper
;
import
com.ssi.utils.ConfigUtils
;
import
com.ssi.utils.FieldUtil
;
import
com.ssi.utils.JsonUtil
;
import
com.ssi.utils.VehicleDataUtil
;
import
com.sun.prism.shader.Solid_TextureYV12_AlphaTest_Loader
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.math3.util.MathUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
java.math.BigDecimal
;
import
java.text.DecimalFormat
;
import
java.time.LocalDateTime
;
import
java.time.temporal.ChronoUnit
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* description:
*
* @author WangHD
* @version 1.0
* @date 2020/3/20 0020 9:59
*/
@Component
@EnableScheduling
@Slf4j
public
class
VehicleLatestDataModel
{
@Value
(
"${vehicle.latestData.redis.prefix:ivccs:vms:vehicle:latest}"
)
private
String
latestRedisKeyPrefix
;
@Value
(
"${vehicle.latestData.redis.postfix:harbor_D00A}"
)
private
String
latestRedisKeyPostfix
;
@Value
(
"${vehicle.latestData.redis.001postfix:harbor_D001}"
)
private
String
latestRedisKeyD001Postfix
;
@Value
(
"${vehicle.latestData.redis.002postfix:harbor_D002}"
)
private
String
latestRedisKeyD002Postfix
;
@Value
(
"${vehicle.status.redis.keyPrefix:harbor:vehicle:online}"
)
private
String
statusRedisKeyPrefix
;
@Value
(
"${order.latestOrderKeyPrefix:harbor:command:status}"
)
private
String
latestOrderKeyPrefix
;
@Value
(
"${harbor.command.vehicle_path_keyPrefix}"
)
private
String
vehiclePathKeyPrefix
;
@Value
(
"${harbor.vehicle.confirm_status_prefix}"
)
private
String
harborVehicleConfirmStatusPrefix
;
@Value
(
"${vehicle.cache.key:ivccs:vms:vehicle:cache}"
)
private
String
vehicleCacheKey
;
@Value
(
"${harbor.remote.emergencyParking}"
)
private
String
vehicleEmergencyCacheKey
;
@Value
(
"${vehicle.latestData.redis.preLocationFix}"
)
private
String
preLocationFix
;
@Value
(
"${harbor.command.info_key:harbor:command:vin:info}"
)
private
String
infoKeyPrefix
;
@Value
(
"${harbor.vehicle.onstatusKey:harbor:vehicle:onstatus}"
)
private
String
onstatusKey
;
@Value
(
"${harbor.vehicle.onlineKey:harbor:vehicle:online}"
)
private
String
onlineKey
;
@Value
(
"${harbor.command.twenty_foot:harbor:command:twenty_foot:order_latest_five}"
)
private
String
orderLatestFiveKey
;
@Value
(
"${client.onlineTime:60000}"
)
private
Long
onlineTime
;
/**
* 用于判断在这个时长里面的任务是否推送到前端
*/
@Value
(
"${client.pushTime:1800000}"
)
private
Long
pushTime
;
@Autowired
private
VehicleBaseInfoModel
vehicleInfoModel
;
@Autowired
private
RedisDataModel
singleNodeModel
;
@Autowired
private
RedisDataModel
redisDataModel
;
@Autowired
private
VehicleDataUtil
vehicleDataUtil
;
@Autowired
private
VmsIndividuationConfigMapper
individuationConfigMapper
;
private
static
Map
<
String
,
Map
<
String
,
Object
>>
vehicleStatusMap
=
Maps
.
newHashMap
();
/**
* 停车时经纬度跳变处理
*/
private
Map
<
String
,
String
>
lastMap
=
Maps
.
newConcurrentMap
();
private
static
Object
STATUS_LOCK
=
new
Object
();
public
List
<
Map
<
String
,
Object
>>
getOnlineData
(
String
key
)
{
List
<
Map
<
String
,
Object
>>
listMap
=
new
ArrayList
<>();
List
<
String
>
keyList
=
Splitter
.
on
(
","
).
omitEmptyStrings
().
trimResults
().
splitToList
(
key
);
List
<
String
>
keyList2
=
Lists
.
newArrayList
(
keyList
);
if
(!
keyList
.
isEmpty
())
{
try
{
Set
<
String
>
keySet
=
redisDataModel
.
keys
(
String
.
format
(
"%s:*"
,
latestRedisKeyPrefix
));
Set
<
String
>
filterVins
=
keySet
.
stream
()
.
map
(
r
->
r
.
replaceAll
(
String
.
format
(
"%s:*"
,
latestRedisKeyPrefix
),
""
))
.
collect
(
Collectors
.
toSet
());
//取交集 有最新数据车辆
keyList
.
retainAll
(
filterVins
);
//取差集 无最新数据车辆
keyList2
.
removeAll
(
keyList
);
if
(
keyList
.
size
()
>
0
)
{
//生成最新数据的Keys
keyList
=
keyList
.
stream
()
.
map
(
r
->
String
.
format
(
"%s:%s"
,
latestRedisKeyPrefix
,
r
))
.
collect
(
Collectors
.
toList
());
List
<
String
>
mget
=
redisDataModel
.
mget
(
keyList
.
toArray
(
new
String
[
keyList
.
size
()]));
int
size
=
mget
.
size
();
String
vin
;
Integer
status
;
Map
<
String
,
Object
>
record
;
Map
<
String
,
Object
>
statusMap
;
Map
<
String
,
Object
>
vehicleInfo
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
record
=
JsonUtil
.
jsonToMap
(
mget
.
get
(
i
));
vin
=
String
.
valueOf
(
record
.
get
(
"vin"
));
synchronized
(
STATUS_LOCK
)
{
statusMap
=
vehicleStatusMap
.
get
(
vin
);
status
=
statusMap
==
null
?
0
:
(
Integer
)
statusMap
.
getOrDefault
(
"state"
,
0
);
}
if
(
1
==
status
)
{
record
.
put
(
"isOnline"
,
"在线"
);
//在线行驶中
Double
speed
=
ConfigUtils
.
getAsDoubleWithDefault
(
record
,
"gpsSpeed"
,
0.0
);
if
(
speed
>
0.0
)
{
record
.
put
(
"isOnline"
,
"在线,行驶中"
);
}
}
else
{
record
.
put
(
"isOnline"
,
"离线"
);
}
vehicleInfo
=
vehicleInfoModel
.
getVehicleBaseInfo
(
vin
);
if
(
vehicleInfo
!=
null
)
{
record
.
put
(
"plateNo"
,
vehicleInfo
.
get
(
"plate_no"
));
record
.
put
(
"vehicleType"
,
vehicleInfo
.
get
(
"vehicle_type"
));
}
listMap
.
add
(
record
);
}
}
if
(!
keyList2
.
isEmpty
())
{
keyList2
.
stream
().
forEach
(
vin
->
{
Map
<
String
,
Object
>
record
=
Maps
.
newHashMap
();
record
.
put
(
"vin"
,
vin
);
record
.
put
(
"isOnline"
,
"离线"
);
Map
<
String
,
Object
>
vehicleInfo
=
vehicleInfoModel
.
getVehicleBaseInfo
(
vin
);
if
(
vehicleInfo
!=
null
)
{
record
.
put
(
"plateNo"
,
vehicleInfo
.
get
(
"plate_no"
));
record
.
put
(
"vehicleType"
,
vehicleInfo
.
get
(
"vehicle_type"
));
}
listMap
.
add
(
record
);
});
}
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"读取%s失败"
,
key
),
e
);
}
}
return
listMap
;
}
public
Object
getVehicleStatus
(
String
vins
,
Integer
status
)
{
List
<
Map
<
String
,
Object
>>
resultList
=
Lists
.
newArrayList
();
try
{
List
<
String
>
keys
=
getLatestDataKeys
(
vins
,
true
);
List
<
String
>
recordJsons
=
redisDataModel
.
mget
(
keys
.
toArray
(
new
String
[
keys
.
size
()]));
resultList
=
recordJsons
.
stream
().
map
(
json
->
{
Map
<
String
,
Object
>
record
=
JsonUtil
.
jsonToMap
(
json
);
String
vin
=
(
String
)
record
.
get
(
"vin"
);
Integer
online
;
synchronized
(
STATUS_LOCK
)
{
Map
<
String
,
Object
>
statusMap
=
vehicleStatusMap
.
get
(
vin
);
online
=
statusMap
==
null
?
0
:
(
Integer
)
statusMap
.
getOrDefault
(
"state"
,
0
);
}
if
(
online
==
1
)
{
Double
speed
=
ConfigUtils
.
getAsDoubleWithDefault
(
record
,
"speed"
,
0.0
);
if
(
speed
>
0.0
)
{
record
.
put
(
"vehicleStatus"
,
"在线,行驶中"
);
record
.
put
(
"vehicleStatusCode"
,
2
);
}
else
{
record
.
put
(
"vehicleStatus"
,
"在线"
);
record
.
put
(
"vehicleStatusCode"
,
1
);
}
}
else
{
record
.
put
(
"vehicleStatus"
,
"离线"
);
record
.
put
(
"vehicleStatusCode"
,
0
);
}
return
record
;
}).
collect
(
Collectors
.
toList
());
if
(
status
!=
null
&&
status
>=
0
&&
status
<=
2
)
{
resultList
=
resultList
.
stream
().
filter
(
record
->
{
Integer
vehicleStatusCode
=
ConfigUtils
.
getAsIntegerWithDefault
(
record
,
"vehicleStatusCode"
,
-
1
);
return
status
.
equals
(
vehicleStatusCode
);
}).
collect
(
Collectors
.
toList
());
}
}
catch
(
Exception
e
)
{
log
.
error
(
"查询车辆状态异常"
,
e
);
}
return
resultList
;
}
private
List
<
String
>
getLatestDataKeys
(
String
vins
,
boolean
emptyForAll
)
{
List
<
String
>
keys
=
Lists
.
newArrayList
();
if
(
StringUtils
.
isNotBlank
(
vins
))
{
String
[]
split
=
vins
.
split
(
","
);
for
(
String
vin
:
split
)
{
keys
.
add
(
String
.
format
(
"%s:%s"
,
latestRedisKeyPrefix
,
vin
.
trim
()));
}
}
if
(
keys
.
isEmpty
()
&&
emptyForAll
)
{
String
prefix
=
String
.
format
(
"%s:*"
,
latestRedisKeyPrefix
);
keys
.
addAll
(
redisDataModel
.
keys
(
prefix
));
}
return
keys
;
}
private
Map
<
String
,
Map
<
String
,
Object
>>
readLatestStatusFromRedis
(
Map
<
String
,
String
>
keysMap
)
{
Map
<
String
,
Map
<
String
,
Object
>>
res
=
Maps
.
newHashMap
();
keysMap
.
entrySet
().
parallelStream
().
forEach
(
entry
->
{
//数据获取
String
redisKey
=
entry
.
getValue
();
// Map<String, Object> record = redisModel.getJson2Map(redisKey);
Map
<
String
,
Object
>
record
=
new
HashMap
<>();
String
state
=
redisDataModel
.
get
(
redisKey
);
if
(
StringUtils
.
isNotBlank
(
state
))
{
record
.
put
(
"state"
,
Integer
.
parseInt
(
state
));
}
res
.
put
(
entry
.
getKey
(),
record
);
});
return
res
;
}
@Scheduled
(
fixedRateString
=
"${spring.websocket.scheduled.time:1000}"
)
public
Map
<
String
,
Map
<
String
,
Object
>>
allRealTimeStatus
()
{
Map
<
String
,
Map
<
String
,
Object
>>
res
;
String
prefixStatus
=
String
.
format
(
"%s:*"
,
statusRedisKeyPrefix
);
Set
<
String
>
keyStatus
=
redisDataModel
.
keys
(
prefixStatus
);
if
(
keyStatus
!=
null
&&
!
keyStatus
.
isEmpty
())
{
Map
<
String
,
String
>
keysMap
=
Maps
.
newHashMap
();
keyStatus
.
stream
().
forEach
(
key
->
{
String
vin
=
key
.
replace
(
String
.
format
(
"%s:"
,
statusRedisKeyPrefix
),
""
);
keysMap
.
put
(
vin
,
key
);
});
res
=
readLatestStatusFromRedis
(
keysMap
);
}
else
{
res
=
Maps
.
newHashMap
();
}
synchronized
(
STATUS_LOCK
)
{
vehicleStatusMap
=
res
;
}
return
res
;
}
public
Map
<
String
,
Map
<
String
,
Object
>>
allRealTimeData
(
boolean
checkRepeat
)
{
Map
<
String
,
Map
<
String
,
Object
>>
res
;
//获取所有vin
String
prefix
=
String
.
format
(
"%s:*"
,
latestRedisKeyPrefix
);
Set
<
String
>
keysUnResolveRepeat
=
redisDataModel
.
keys
(
prefix
);
Set
<
String
>
vins
=
keysUnResolveRepeat
.
stream
().
map
(
key
->
{
key
=
key
.
replace
(
String
.
format
(
"%s:"
,
latestRedisKeyPrefix
),
""
);
key
=
key
.
substring
(
0
,
key
.
indexOf
(
"-"
));
return
key
;
}).
collect
(
Collectors
.
toSet
());
//拼接所有类型key
if
(
vins
!=
null
&&
!
vins
.
isEmpty
())
{
Map
<
String
,
Map
<
String
,
String
>>
keysMap
=
Maps
.
newHashMap
();
vins
.
stream
().
forEach
(
key
->
{
//判断车辆是否禁用
Map
<
String
,
Object
>
vehicleInfoRecord
=
redisDataModel
.
hgetJson2Map
(
vehicleCacheKey
,
key
);
if
(
vehicleInfoRecord
==
null
||
vehicleInfoRecord
.
get
(
"status"
)
==
null
||
(
Integer
)
vehicleInfoRecord
.
get
(
"status"
)
==
1
){
return
;
}
Map
<
String
,
String
>
keyPreMap
=
Maps
.
newHashMap
();
keyPreMap
.
put
(
"vin"
,
key
);
keyPreMap
.
put
(
"latestKey"
,
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyPostfix
));
keyPreMap
.
put
(
"d001Key"
,
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyD001Postfix
));
keyPreMap
.
put
(
"d002Key"
,
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyD002Postfix
));
keyPreMap
.
put
(
"orderKey"
,
String
.
format
(
"%s:%s"
,
latestOrderKeyPrefix
,
key
));
keyPreMap
.
put
(
"vehiclePathKey"
,
String
.
format
(
"%s:%s"
,
vehiclePathKeyPrefix
,
key
));
keyPreMap
.
put
(
"threeConfirmStatus"
,
String
.
format
(
"%s:%s"
,
harborVehicleConfirmStatusPrefix
,
key
));
keyPreMap
.
put
(
"emergencyTypeKey"
,
String
.
format
(
"%s:%s"
,
vehicleEmergencyCacheKey
,
key
));
keyPreMap
.
put
(
"onstatusKey"
,
String
.
format
(
"%s:%s"
,
onstatusKey
,
key
));
keyPreMap
.
put
(
"onlineKey"
,
String
.
format
(
"%s:%s"
,
onlineKey
,
key
));
keyPreMap
.
put
(
"orderLatestFiveKey"
,
String
.
format
(
"%s:%s"
,
"harbor:command:twenty_foot:order_latest_five"
,
key
));
//双小箱数据
keysMap
.
put
(
key
,
keyPreMap
);
});
res
=
readLatestDataFromRedis
(
keysMap
,
checkRepeat
);
}
else
{
res
=
Maps
.
newHashMap
();
}
return
res
;
}
public
Map
<
String
,
Map
<
String
,
Object
>>
getVehicleRunData
()
{
Map
<
String
,
Map
<
String
,
Object
>>
res
=
Maps
.
newHashMap
();
//获取所有vin
String
prefix
=
String
.
format
(
"%s:*"
,
latestRedisKeyPrefix
);
Set
<
String
>
keysUnResolveRepeat
=
redisDataModel
.
keys
(
prefix
);
Set
<
String
>
vins
=
keysUnResolveRepeat
.
stream
().
map
(
key
->
{
key
=
key
.
replace
(
String
.
format
(
"%s:"
,
latestRedisKeyPrefix
),
""
);
key
=
key
.
substring
(
0
,
key
.
indexOf
(
"-"
));
return
key
;
}).
collect
(
Collectors
.
toSet
());
//拼接所有类型key
if
(
vins
!=
null
&&
!
vins
.
isEmpty
())
{
vins
.
stream
().
forEach
(
key
->
{
//判断车辆是否禁用
Map
<
String
,
Object
>
vehicleInfoRecord
=
redisDataModel
.
hgetJson2Map
(
vehicleCacheKey
,
key
);
if
(
vehicleInfoRecord
==
null
||
vehicleInfoRecord
.
get
(
"status"
)
==
null
||
(
Integer
)
vehicleInfoRecord
.
get
(
"status"
)
==
1
){
return
;
}
String
latestKey
=
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyPostfix
);
Map
<
String
,
Object
>
record
=
redisDataModel
.
getJson2Map
(
latestKey
);
String
emergencyParking
=
String
.
format
(
"%s:%s"
,
vehicleEmergencyCacheKey
,
key
);
Map
<
String
,
Object
>
emergencyStatusMap
=
redisDataModel
.
getJson2Map
(
emergencyParking
);
Integer
emergencyStatus
=
2
;
if
(
emergencyStatusMap
!=
null
)
{
emergencyStatus
=
(
Integer
)
emergencyStatusMap
.
get
(
"emergencyStatus"
);
}
if
(
record
!=
null
&&
!
record
.
isEmpty
()
&&
checkAndAppendStatus
(
record
)
==
1
)
{
record
.
put
(
"vehicleNum"
,
vehicleInfoRecord
==
null
?
null
:
vehicleInfoRecord
.
get
(
"vehicleNum"
));
record
.
put
(
"emergencyStatus"
,
emergencyStatus
);
res
.
put
(
key
,
record
);
}
});
}
return
res
;
}
public
Map
<
String
,
Map
<
String
,
Object
>>
readLatestDataFromRedis
(
Map
<
String
,
Map
<
String
,
String
>>
keysMap
,
boolean
checkRepeat
)
{
Map
<
String
,
Map
<
String
,
Object
>>
res
=
Maps
.
newHashMap
();
keysMap
.
entrySet
().
parallelStream
().
forEach
(
entry
->
{
Map
<
String
,
String
>
redisKeyMap
=
entry
.
getValue
();
String
vin
=
redisKeyMap
.
get
(
"vin"
);
String
latestKey
=
redisKeyMap
.
get
(
"latestKey"
);
String
orderKey
=
redisKeyMap
.
get
(
"orderKey"
);
String
vehiclePathKey
=
redisKeyMap
.
get
(
"vehiclePathKey"
);
String
threeConfirmStatusKey
=
redisKeyMap
.
get
(
"threeConfirmStatus"
);
String
emergencyTypeKey
=
redisKeyMap
.
get
(
"emergencyTypeKey"
);
String
obuStatus
=
redisDataModel
.
get
(
redisKeyMap
.
get
(
"onstatusKey"
));
String
onlineStatus
=
redisDataModel
.
get
(
redisKeyMap
.
get
(
"onlineKey"
));
String
craneNo
=
redisDataModel
.
get
(
RedisKey
.
VEHICLE_TO_CRANE
.
getKeyPrefix
().
concat
(
vin
));
orderLatestFiveKey
=
redisKeyMap
.
get
(
"orderLatestFiveKey"
);
String
infoKey
=
String
.
format
(
"%s:%s"
,
infoKeyPrefix
,
vin
);
String
vehicleMap
=
redisDataModel
.
get
(
infoKey
);
vehicleMap
=
StringUtils
.
isNotBlank
(
vehicleMap
)
?
vehicleMap
:
singleNodeModel
.
get
(
infoKey
);
Integer
vehicleType
=
1
;
//1:X69B ,2:X69C,3:有人集卡两秒
if
(
vehicleMap
!=
null
)
{
//判断redis是否存在,不存在则查询数据库
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
vehicleMap
);
vehicleType
=
jsonObject
.
getInteger
(
"vehicleType"
);
}
Map
<
String
,
Object
>
record
=
redisDataModel
.
getJson2Map
(
latestKey
);
//record 不为空, 且状态为在线状态
if
(
vehicleType
==
3
){
record
=
redisDataModel
.
getJson2Map
(
latestKey
);
if
(
record
!=
null
&&
!
record
.
isEmpty
()
&&
checkAndAppendStatus
(
record
)
==
1
)
{
Map
<
String
,
Object
>
newRecord
=
Maps
.
newHashMap
();
record
.
remove
(
"originalMsg"
);
Map
<
String
,
Object
>
vehicleInfoRecord
=
singleNodeModel
.
hgetJson2Map
(
vehicleCacheKey
,
vin
);
String
vehiclePath
=
null
;
if
(!
repeatCheck
(
entry
.
getKey
(),
record
,
checkRepeat
))
{
double
[]
locaction
=
parseLocation
(
record
);
if
(
locaction
!=
null
)
{
//有人集卡暂时不需要任务描述,可以不用推送到前端,减少前端缓存,以后需要可和前端商量需要的字段
newRecord
.
put
(
"isOnline"
,
1
);
newRecord
.
put
(
"clientStatus"
,
record
.
get
(
"clientStatus"
));
newRecord
.
put
(
"vin"
,
record
.
get
(
"vin"
));
newRecord
.
put
(
"vehicleType"
,
vehicleInfoRecord
==
null
?
vehicleType
:
vehicleInfoRecord
.
get
(
"vehicleType"
));
newRecord
.
put
(
"vehicleNum"
,
vehicleInfoRecord
==
null
?
null
:
vehicleInfoRecord
.
get
(
"vehicleNum"
));
newRecord
.
put
(
"latitude"
,
record
.
get
(
"latitude"
));
newRecord
.
put
(
"preLocation"
,
record
.
get
(
"preLocation"
));
newRecord
.
put
(
"longitude"
,
record
.
get
(
"longitude"
));
newRecord
.
put
(
"gear"
,
record
.
get
(
"gear"
));
newRecord
.
put
(
"altitude"
,
record
.
get
(
"altitude"
));
newRecord
.
put
(
"speed"
,
record
.
get
(
"speed"
));
newRecord
.
put
(
"location"
,
locaction
);
newRecord
.
put
(
"collectTime"
,
record
.
get
(
"collectTime"
));
newRecord
.
put
(
"soc"
,
record
.
get
(
"soc"
));
newRecord
.
put
(
"totalMile"
,
record
.
get
(
"totalMile"
));
res
.
put
(
entry
.
getKey
(),
newRecord
);
}
}
}
}
else
if
(
record
!=
null
&&
!
record
.
isEmpty
()){
Map
<
String
,
Object
>
newRecord
=
Maps
.
newHashMap
();
record
.
remove
(
"originalMsg"
);
Map
<
String
,
Object
>
orderRecord
=
redisDataModel
.
getJson2Map
(
orderKey
);
Map
<
String
,
Object
>
vehicleInfoRecord
=
redisDataModel
.
hgetJson2Map
(
vehicleCacheKey
,
vin
);
Map
<
String
,
Object
>
vehicleEmergencyRecord
=
redisDataModel
.
getJson2Map
(
emergencyTypeKey
);
Map
<
String
,
Object
>
newOrderRecord
=
new
HashMap
<>();
newRecord
.
put
(
"stopExceed"
,
0
);
if
(!
repeatCheck
(
entry
.
getKey
(),
record
,
checkRepeat
))
{
double
[]
location
=
parseLocation
(
record
);
if
(
location
==
null
){
location
=
new
double
[]{
119.968264
,
24.458783
};
//117.9682640,24.4587837
newOrderRecord
.
put
(
"msg"
,
"定位偏移,超出范围"
);
// newRecord.put("stopExceed",1);
}
if
(
orderRecord
!=
null
){
int
status
=
(
Integer
)
orderRecord
.
get
(
"status"
);
//车辆到达目的地之后不推送规划路径;判断任务是否过期,过期之后不推送路径规划
if
((
status
==
VehicleConstant
.
PATH_PLANNING
||
status
==
VehicleConstant
.
START_TASK
)
&&
(
System
.
currentTimeMillis
()
-
Long
.
valueOf
(
orderRecord
.
get
(
"collectTime"
).
toString
())
<
VehicleConstant
.
ORDER_EXPIRATION_TIME
)){
String
vehiclePath
=
redisDataModel
.
get
(
vehiclePathKey
);
//添加任务规划点
newOrderRecord
.
put
(
"vehiclePath"
,
JSONObject
.
parse
(
vehiclePath
));
}
//计算任务是否等待超时
BigDecimal
taskTime
=
calTime
(
orderRecord
.
get
(
"startTime"
),
orderRecord
.
get
(
"endTime"
));
if
((
status
==
VehicleConstant
.
OBU_RECEIVED
||
status
==
VehicleConstant
.
ADCU_RECEIVED
)
&&
taskTime
!=
null
&&
taskTime
.
compareTo
(
BigDecimal
.
valueOf
(
180
))
>
0
){
newOrderRecord
.
put
(
"msg"
,
"任务等待超时"
);
}
//判断到达目的地车辆,是否状态异常
Integer
subTaskType
=
Objects
.
isNull
(
orderRecord
.
get
(
"subTaskType"
))
?
null
:
(
Integer
)
orderRecord
.
get
(
"subTaskType"
);
Long
lastTime
=
Objects
.
nonNull
(
orderRecord
.
get
(
"updateTime"
))
?
(
Long
)
orderRecord
.
get
(
"updateTime"
)
:
null
;
Long
currentTime
=
System
.
currentTimeMillis
();
VmsIndividuationConfig
overtimeValue
=
individuationConfigMapper
.
selectOne
(
new
LambdaUpdateWrapper
<
VmsIndividuationConfig
>().
eq
(
VmsIndividuationConfig:
:
getConfigKey
,
"wait_overtime_energy_key"
));
Integer
valueType
=
300000
;
if
(
Objects
.
nonNull
(
overtimeValue
)){
valueType
=
60000
*
Integer
.
valueOf
(
overtimeValue
.
getConfigValue
());
}
/* if(status==3&¤tTime-lastTime>valueType&&(subTaskType == null || subTaskType == 3 || subTaskType == 4 || subTaskType == 6 || subTaskType == 8 || subTaskType == 10 || subTaskType == 12)){
newRecord.put("stopExceed",1);
}*/
orderRecord
.
put
(
"estimatedArriveTime"
,
LocalDateTime
.
now
().
plus
(
10
,
ChronoUnit
.
MINUTES
));
//添加任务描述
String
description
=
vehicleDataUtil
.
generateOrderDescription
(
orderRecord
);
//判断subTaskType:0去缓冲区1,2 去扭锁站 其他用查询出来的
if
(
Objects
.
nonNull
(
subTaskType
)){
//判断subTaskType redis是否存在
// int subTaskType = (Integer) orderRecord.get("subTaskType");
if
(
subTaskType
==
0
){
newOrderRecord
.
put
(
"orderDescription"
,
"去缓冲区"
);
}
else
if
(
subTaskType
==
1
||
subTaskType
==
2
){
newOrderRecord
.
put
(
"orderDescription"
,
"去扭锁站"
);
}
else
{
newOrderRecord
.
put
(
"orderDescription"
,
description
);
}
}
else
{
newOrderRecord
.
put
(
"orderDescription"
,
description
);
}
//设置双小箱任务数据取第二小箱状态 0:不生效,1生效
newOrderRecord
.
put
(
"doubleBoxStatus"
,
0
);
Object
containerInfos
=
orderRecord
.
get
(
"containerInfos"
);
if
(
Objects
.
nonNull
(
containerInfos
)){
JSONArray
containerInfos1
=
(
JSONArray
)
containerInfos
;
if
(
containerInfos1
.
size
()>
1
&&
status
==
49
&&
orderRecord
.
get
(
"taskLocationType"
)!=
null
&&(
Integer
)
orderRecord
.
get
(
"taskLocationType"
)==
1
){
//双小箱任务&&停稳锁死&&目的地是堆场
newOrderRecord
.
put
(
"doubleBoxStatus"
,
1
);
}
}
newOrderRecord
.
put
(
"containerInfos"
,
orderRecord
.
get
(
"containerInfos"
)==
null
?
new
JSONArray
():
orderRecord
.
get
(
"containerInfos"
));
newOrderRecord
.
put
(
"vehicleLocation"
,
orderRecord
.
get
(
"vehicleLocation"
)==
null
?
""
:
orderRecord
.
get
(
"vehicleLocation"
));
newOrderRecord
.
put
(
"vehicleTaskLabel"
,
orderRecord
.
get
(
"vehicleTaskLabel"
)
==
null
?
""
:
orderRecord
.
get
(
"vehicleTaskLabel"
));
newOrderRecord
.
put
(
"taskType"
,
orderRecord
.
get
(
"taskType"
)
==
null
?
""
:
orderRecord
.
get
(
"taskType"
));
newOrderRecord
.
put
(
"taskNo"
,
orderRecord
.
get
(
"taskNo"
)==
null
?
""
:
orderRecord
.
get
(
"taskNo"
));
newOrderRecord
.
put
(
"vin"
,
orderRecord
.
get
(
"vin"
)==
null
?
""
:
orderRecord
.
get
(
"vin"
));
newOrderRecord
.
put
(
"longitude"
,
orderRecord
.
get
(
"longitude"
)
==
null
?
""
:
orderRecord
.
get
(
"longitude"
));
newOrderRecord
.
put
(
"vehicleTaskType"
,
orderRecord
.
get
(
"vehicleTaskType"
)
==
null
?
""
:
orderRecord
.
get
(
"vehicleTaskType"
));
newOrderRecord
.
put
(
"targetType"
,
orderRecord
.
get
(
"targetType"
)
==
null
?
""
:
orderRecord
.
get
(
"targetType"
));
newOrderRecord
.
put
(
"lockLabel"
,
orderRecord
.
get
(
"lockLabel"
)
==
null
?
""
:
orderRecord
.
get
(
"lockLabel"
)
);
newOrderRecord
.
put
(
"status"
,
orderRecord
.
get
(
"status"
)
==
null
?
""
:
orderRecord
.
get
(
"status"
));
newOrderRecord
.
put
(
"taskLocationType"
,
orderRecord
.
get
(
"taskLocationType"
)==
null
?
""
:
orderRecord
.
get
(
"taskLocationType"
));
newOrderRecord
.
put
(
"collectTime"
,
orderRecord
.
get
(
"collectTime"
)==
null
?
""
:
orderRecord
.
get
(
"collectTime"
));
newOrderRecord
.
put
(
"taskSource"
,
orderRecord
.
get
(
"taskSource"
)==
null
?
""
:
orderRecord
.
get
(
"taskSource"
));
newOrderRecord
.
put
(
"goShipCraneLaneStatus"
,
orderRecord
.
get
(
"goShipCraneLaneStatus"
)==
null
?
""
:
orderRecord
.
get
(
"goShipCraneLaneStatus"
));
newOrderRecord
.
put
(
"msg"
,
orderRecord
.
get
(
"msg"
)==
null
?
""
:
orderRecord
.
get
(
"msg"
));
newOrderRecord
.
put
(
"parkingAreaNo"
,
orderRecord
.
get
(
"parkingAreaNo"
));
}
else
{
//没值的话也要给前端空字符串不然前端会崩
newOrderRecord
.
put
(
"vehicleLocation"
,
""
);
newOrderRecord
.
put
(
"vehicleTaskLabel"
,
""
);
newOrderRecord
.
put
(
"taskType"
,
""
);
newOrderRecord
.
put
(
"taskNo"
,
""
);
newOrderRecord
.
put
(
"vin"
,
""
);
newOrderRecord
.
put
(
"longitude"
,
""
);
newOrderRecord
.
put
(
"vehicleTaskType"
,
""
);
newOrderRecord
.
put
(
"targetType"
,
""
);
newOrderRecord
.
put
(
"lockLabel"
,
""
);
newOrderRecord
.
put
(
"status"
,
""
);
newOrderRecord
.
put
(
"taskLocationType"
,
""
);
newOrderRecord
.
put
(
"vehiclePath"
,
""
);
newOrderRecord
.
put
(
"collectTime"
,
""
);
newOrderRecord
.
put
(
"taskSource"
,
""
);
newOrderRecord
.
put
(
"containerInfos"
,
new
JSONArray
());
newOrderRecord
.
put
(
"doubleBoxStatus"
,
0
);
newOrderRecord
.
put
(
"parkingAreaNo"
,
""
);
}
//onlineStatus这个数据是在redis里面,判断是否在线方法1上线0下线
if
((
onlineStatus
!=
null
&&
onlineStatus
.
equals
(
"1"
)&&
obuStatus
!=
null
&&
obuStatus
.
equals
(
"1"
))){
newRecord
.
put
(
"isOnline"
,
1
);
}
else
{
newRecord
.
put
(
"isOnline"
,
0
);
}
newRecord
.
put
(
"clientStatus"
,
record
.
get
(
"clientStatus"
));
newRecord
.
put
(
"vin"
,
record
.
get
(
"vin"
));
newRecord
.
put
(
"craneNo"
,
StringUtils
.
isNotBlank
(
craneNo
)?
craneNo:
""
);
newRecord
.
put
(
"vehicleType"
,
vehicleInfoRecord
==
null
?
""
:
vehicleInfoRecord
.
get
(
"vehicleType"
));
newRecord
.
put
(
"vehicleNum"
,
vehicleInfoRecord
==
null
?
""
:
vehicleInfoRecord
.
get
(
"vehicleNum"
));
newRecord
.
put
(
"gear"
,
record
.
get
(
"gear"
));
newRecord
.
put
(
"altitude"
,
record
.
get
(
"altitude"
));
newRecord
.
put
(
"speed"
,
record
.
get
(
"speed"
));
//判断当前的任务时间是否超过配置的时长,超过不推送数据
newRecord
.
put
(
"direction"
,
record
==
null
?
""
:
record
.
get
(
"direction"
));
if
(!
""
.
equals
(
newOrderRecord
.
get
(
"collectTime"
))
&&
checkTime
(
newOrderRecord
)
==
1
)
{
newRecord
.
put
(
"orderData"
,
newOrderRecord
);
newRecord
.
put
(
"status"
,
VmsTosOrderStatusEnum
.
find
(
Integer
.
valueOf
(
newOrderRecord
.
get
(
"status"
)+
""
))==
null
?
""
:
VmsTosOrderStatusEnum
.
find
(
Integer
.
valueOf
(
newOrderRecord
.
get
(
"status"
)+
""
)).
getDescription
());
Integer
vehicleTaskLabel
=
(
Integer
)
newOrderRecord
.
get
(
"vehicleTaskLabel"
);
Object
o
=
Objects
.
isNull
(
vehicleTaskLabel
)
?
newRecord
.
put
(
"vinFlag"
,
1
)
:
(
1
==
vehicleTaskLabel
?
newRecord
.
put
(
"vinFlag"
,
3
)
:
(
2
==
vehicleTaskLabel
?
newRecord
.
put
(
"vinFlag"
,
4
)
:
newRecord
.
put
(
"vinFlag"
,
5
)));
}
else
{
newRecord
.
put
(
"orderData"
,
""
);
newRecord
.
put
(
"craneNo"
,
""
);
newRecord
.
put
(
"status"
,
"-"
);
//没有订单就没有订单状态
Object
o
=
(
Integer
)
newRecord
.
get
(
"isOnline"
)
==
0
?
newRecord
.
put
(
"vinFlag"
,
0
)
:
newRecord
.
put
(
"vinFlag"
,
2
);
}
newRecord
.
put
(
"collectTime"
,
record
.
get
(
"collectTime"
));
newRecord
.
put
(
"soc"
,
record
.
get
(
"soc"
));
//判断车辆的速度是否为0,速度为0的情况,判断车辆位置信息
newRecord
.
put
(
"location"
,
location
);
//以上的字段都是重新封装成前端需要的字段,如需要其他字段可在record这里面获取,orderRecord这个map里面是redis里面全部的任务信息字段
res
.
put
(
entry
.
getKey
(),
newRecord
);
}
}
});
return
res
;
}
private
BigDecimal
calTime
(
Object
startTime
,
Object
endTime
)
{
if
(
startTime
!=
null
)
{
Long
startDate
=
(
Long
)
startTime
;
BigDecimal
timeSeconds
=
null
;
if
(
endTime
==
null
){
timeSeconds
=
new
BigDecimal
(
System
.
currentTimeMillis
()
-
startDate
).
divide
(
new
BigDecimal
(
1000
),
0
,
BigDecimal
.
ROUND_CEILING
);
}
else
{
Long
endDate
=
(
Long
)
endTime
;
timeSeconds
=
new
BigDecimal
(
endDate
-
startDate
).
divide
(
new
BigDecimal
(
1000
),
0
,
BigDecimal
.
ROUND_CEILING
);
}
return
timeSeconds
;
}
return
null
;
}
private
String
formatTime
(
BigDecimal
seconds
)
{
int
sec
=
seconds
.
intValue
();
if
(
sec
<
0
){
return
"0秒"
;
}
StringBuilder
sb
=
new
StringBuilder
();
if
(
sec
<
60
)
{
sb
.
append
(
seconds
+
"秒"
);
}
else
if
(
sec
>=
60
&&
sec
<
3600
)
{
int
m
=
sec
/
60
;
int
s
=
sec
%
60
;
sb
.
append
(
m
+
"分"
);
if
(
s
>
0
){
sb
.
append
(
s
+
"秒"
);
}
}
else
{
int
h
=
sec
/
3600
;
int
m
=
(
sec
%
3600
)/
60
;
int
s
=
(
sec
%
3600
)%
60
;
sb
.
append
(
h
+
"小时"
);
if
(
m
>
0
){
sb
.
append
(
m
+
"分"
);
}
if
(
s
>
0
){
sb
.
append
(
s
+
"秒"
);
}
}
return
sb
.
toString
();
}
private
boolean
repeatCheck
(
String
vin
,
Map
<
String
,
Object
>
record
,
boolean
checkRepeat
)
{
boolean
repeat
=
false
;
if
(
checkRepeat
)
{
Object
speed
=
record
.
get
(
"speed"
);
// if(speed != null && (Float)speed <= 0){
// return false;
// }
Object
collectTime
=
record
.
get
(
"collectTime"
);
Object
latitude
=
record
.
get
(
"latitude"
);
Object
longitude
=
record
.
get
(
"longitude"
);
String
format
=
String
.
format
(
"%s,%s,%s"
,
collectTime
,
latitude
,
longitude
);
repeat
=
(
format
.
equals
(
lastMap
.
get
(
vin
)));
if
(!
repeat
)
{
lastMap
.
put
(
vin
,
format
);
}
}
// return repeat;
return
false
;
}
private
int
checkAndAppendStatus
(
Map
<
String
,
Object
>
record
)
{
Integer
status
;
synchronized
(
STATUS_LOCK
)
{
Map
<
String
,
Object
>
statusMap
=
vehicleStatusMap
.
get
(
record
.
get
(
"vin"
));
status
=
statusMap
==
null
?
-
1
:
(
Integer
)
statusMap
.
getOrDefault
(
"state"
,
-
1
);
}
Long
time
=
ConfigUtils
.
getAsLong
(
record
,
"collectTime"
);
/** 检查终端状态*/
boolean
dataOnline
=
(
time
!=
null
&&
System
.
currentTimeMillis
()
-
time
<
onlineTime
);
boolean
isOnline
=
dataOnline
;
//&& status == 1;
record
.
put
(
"clientStatus"
,
isOnline
?
"在线"
:
"离线"
);
record
.
put
(
"state"
,
isOnline
?
1
:
0
);
return
isOnline
?
1
:
0
;
}
/**
* 检查当前时间是否在半个小时内时间orderData里面的字段
* */
private
int
checkTime
(
Map
<
String
,
Object
>
record
)
{
Long
time
=
ConfigUtils
.
getAsLong
(
record
,
"collectTime"
);
/** 检查当前时间是否在半个小时内*/
boolean
dataOnline
=
(
time
!=
null
&&
System
.
currentTimeMillis
()
-
time
<
pushTime
);
return
dataOnline
?
1
:
0
;
}
private
double
[]
parseLocation
(
Map
<
String
,
Object
>
record
)
{
Double
longitude
=
ConfigUtils
.
getAsDoubleWithDefault
(
record
,
"longitude"
,
0.0
);
Double
latitude
=
ConfigUtils
.
getAsDoubleWithDefault
(
record
,
"latitude"
,
0.0
);
double
[]
location
=
null
;
//中国境内
if
(
longitude
<
135
&&
longitude
>=
73
&&
latitude
>=
4
&&
latitude
<
53
)
{
BigDecimal
longitudeDecimal
=
new
BigDecimal
(
longitude
);
longitudeDecimal
=
longitudeDecimal
.
setScale
(
6
,
BigDecimal
.
ROUND_DOWN
);
BigDecimal
latitudeDecimal
=
new
BigDecimal
(
latitude
);
latitudeDecimal
=
latitudeDecimal
.
setScale
(
6
,
BigDecimal
.
ROUND_DOWN
);
location
=
new
double
[]{
longitudeDecimal
.
doubleValue
(),
latitudeDecimal
.
doubleValue
()};
}
else
{
// log.warn(String.format("记录中的经纬度不在国内: %s", record));
}
return
location
;
}
public
String
getLatestRedisKeyPrefix
()
{
return
latestRedisKeyPrefix
;
}
public
String
getLatestRedisKeyPostfix
()
{
return
latestRedisKeyPostfix
;
}
public
String
getLatestRedisKeyD001Postfix
()
{
return
latestRedisKeyD001Postfix
;
}
public
String
getLatestRedisKeyD002Postfix
()
{
return
latestRedisKeyD002Postfix
;
}
public
RedisDataModel
getRedisModel
()
{
return
redisDataModel
;
}
public
String
getStatusRedisKeyPrefix
()
{
return
statusRedisKeyPrefix
;
}
public
VehicleBaseInfoModel
getVehicleInfoModel
()
{
return
vehicleInfoModel
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/VehicleSocketDataCacheQueueModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.google.common.collect.EvictingQueue
;
import
com.google.common.collect.Maps
;
import
com.ssi.constant.RedisKey
;
import
com.ssi.constant.enums.VmsTosOrderStatusEnum
;
import
com.ssi.entity.dto.Point
;
import
com.ssi.kafka.listener.VehicleRealTimeInfoListener
;
import
com.ssi.service.platform.WebSocketDataService
;
import
com.ssi.utils.*
;
import
com.ssi.utils.grid.RealTimeVehicleSchedule
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections.MapUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StopWatch
;
import
reactor.util.function.Tuple2
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.text.DecimalFormat
;
import
java.util.*
;
import
java.util.concurrent.*
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* Description:
*
* @author LiXiaoCong
* @version 2019/11/11 11:26
*/
@Slf4j
@Component
@ConditionalOnProperty
(
name
=
"spring.websocket.pushInPool.enable"
,
havingValue
=
"true"
)
public
class
VehicleSocketDataCacheQueueModel
{
private
static
final
Object
LOCK
=
new
Object
();
@Value
(
"${spring.websocket.scheduled.cache.max:20}"
)
private
int
maxCacheSize
;
@Value
(
"${spring.websocket.scheduled.push.threshold:1}"
)
private
int
pushThreshold
;
@Value
(
"${spring.websocket.point.degree.threshold:90.0}"
)
private
double
degreeThreshold
;
@Value
(
"${spring.websocket.scheduled.time:1000}"
)
private
int
pushRate
;
@Value
(
"${vehicle.latestData.redis.preLocationFix:ivccs:vms:vehicle:preLocation}"
)
private
String
preLocationFix
;
@Value
(
"${order.latestOrderKeyPrefix:harbor:command:status}"
)
private
String
latestOrderKeyPrefix
;
@Value
(
"${ivccs.vehicle.latestData.redis.prefix:ivccs:vms:vehicle:latest}"
)
private
String
latestRedisKeyPrefix
;
@Value
(
"${vehicle.latestData.redis.postfix:harbor_D00A}"
)
private
String
realPostfix
;
@Autowired
private
RedisDataModel
redisDataModel
;
@Autowired
private
VehicleBaseInfoModel
vehicleBaseInfoModel
;
@Autowired
private
VehicleDataUtil
vehicleDataUtil
;
@Autowired
private
WebSocketDataService
webSocketDataService
;
private
final
ExecutorService
executorService
=
new
ThreadPoolExecutor
(
1
,
1
,
0
,
TimeUnit
.
MILLISECONDS
,
new
ArrayBlockingQueue
<>(
10
),
new
ThreadPoolExecutor
.
DiscardOldestPolicy
());
private
final
Map
<
String
,
VehicleDataCachePool
>
cachePoolMaps
=
Maps
.
newConcurrentMap
();
private
final
Map
<
String
,
JSONObject
>
gpsSpeedMap
=
Maps
.
newConcurrentMap
();
@Autowired
private
VehicleRealTimeInfoListener
vehicleRealTimeInfoListener
;
private
AtomicInteger
versionNo
=
new
AtomicInteger
(
0
);
/**
* 设置车辆的最新数据
*/
@Scheduled
(
fixedRateString
=
"${spring.websocket.scheduled.pool.time:500}"
)
private
void
scheduledSendInfoMage
()
{
Map
<
String
,
Map
<
String
,
Object
>>
messages
=
webSocketDataService
.
realTimeDataAll
();
if
(
messages
!=
null
&&
messages
.
size
()
>
0
)
{
vehicleRealTimeInfoListener
.
clearOutVersionVehicle
(
versionNo
.
get
());
messages
.
forEach
((
vin
,
record
)
->
{
record
.
put
(
"versionNo"
,
versionNo
.
getAndIncrement
()<
Integer
.
MAX_VALUE
-
1
?
versionNo
.
get
():
versionNo
.
getAndSet
(
0
));
getCachePool
(
vin
).
pushData
(
record
);
});
}
}
public
Map
<
String
,
Map
<
String
,
Object
>>
getAllVehicleData
()
{
Map
<
String
,
Map
<
String
,
Object
>>
messages
=
Maps
.
newHashMap
();
this
.
cachePoolMaps
.
forEach
((
vin
,
pool
)
->
{
Map
<
String
,
Object
>
data
=
pool
.
getData
();
if
(
data
!=
null
)
{
messages
.
put
(
vin
,
data
);
}
});
return
messages
;
}
private
VehicleDataCachePool
getCachePool
(
String
vin
)
{
VehicleDataCachePool
vehicleDataCachePool
=
this
.
cachePoolMaps
.
get
(
vin
);
if
(
vehicleDataCachePool
==
null
)
{
synchronized
(
LOCK
)
{
if
(
vehicleDataCachePool
==
null
)
{
vehicleDataCachePool
=
new
VehicleDataCachePool
(
vin
);
this
.
cachePoolMaps
.
put
(
vin
,
vehicleDataCachePool
);
}
}
}
return
vehicleDataCachePool
;
}
private
class
VehicleDataCachePool
{
private
final
String
vin
;
private
final
EvictingQueue
<
Map
<
String
,
Object
>>
evictingQueue
;
private
int
dataFrequency
;
private
AtomicBoolean
canPush
=
new
AtomicBoolean
(
false
);
private
Map
<
String
,
Object
>
preMap
;
//速度不为0缓存位置信息
private
Map
<
String
,
Object
>
preWithSpeedMap
;
private
VehicleDataCachePool
(
String
vin
)
{
this
.
vin
=
vin
;
/* Temporarily not find infomation of vehicle. */
// Map<String, Object> vehicleBaseInfo = vehicleBaseInfoModel.getVehicleBaseInfo(vin);
//
// Object dataFrequency = vehicleBaseInfo.get("dataFrequency");
// if(dataFrequency != null){
// this.dataFrequency = Integer.parseInt(dataFrequency.toString());
// }else{
this
.
dataFrequency
=
1000
;
// }
if
(
this
.
dataFrequency
<
pushRate
)
{
this
.
dataFrequency
=
pushRate
;
}
this
.
evictingQueue
=
EvictingQueue
.
create
(
maxCacheSize
);
}
private
void
pushData
(
Map
<
String
,
Object
>
map
)
{
boolean
valid
=
isValid
(
map
);
//航向角计算
//addLastLocationInfo(map, valid);
calculateNextLocationByDirection
(
map
);
if
(
"ON"
.
equals
(
redisDataModel
.
get
(
RedisKey
.
DYNAMIC_FENCE_SWITCH
.
getKeyPrefix
()))){
//处理封闭区冲突
vehicleRealTimeInfoListener
.
processVehicleCloseArea
(
map
);
}
//处理异常信息
// processVehcileErrorMsg(map);
this
.
evictingQueue
.
add
(
map
);
if
(!
this
.
canPush
.
get
())
{
this
.
canPush
.
set
(
size
()
>=
pushThreshold
);
}
}
private
void
processVehcileErrorMsg
(
Map
<
String
,
Object
>
record
)
{
JSONObject
jsonObject
=
new
JSONObject
();
Double
speed
=
(
Double
)
record
.
get
(
"speed"
);
//V2X异常
String
v2xStr
=
redisDataModel
.
get
(
RedisKey
.
ERROR_V2X_INFO
.
getKeyPrefix
().
concat
(
vin
));
if
(
StringUtils
.
isNotBlank
(
v2xStr
)){
JSONObject
v2xObj
=
JSON
.
parseObject
(
v2xStr
);
if
(
System
.
currentTimeMillis
()
-
v2xObj
.
getLong
(
"time"
)<
30000
){
record
.
put
(
"vinFlag"
,
1
);
jsonObject
.
put
(
"v2xError"
,
v2xObj
.
getString
(
"description"
));
}
/* if(StringUtils.isNotBlank(v2xObj.getString("description"))){
jsonObject.put("v2xError",v2xObj.getString("description"));
}*/
}
//三级告警
String
tosStr
=
redisDataModel
.
get
(
RedisKey
.
ERROR_TOS_INFO
.
getKeyPrefix
().
concat
(
vin
));
if
(
StringUtils
.
isNotBlank
(
tosStr
)){
JSONObject
tosObj
=
JSON
.
parseObject
(
tosStr
);
jsonObject
.
put
(
"v2xError"
,
tosObj
.
getString
(
"faultName"
));
}
//平台异常
StringBuilder
sb
=
new
StringBuilder
(
""
);
Map
<
String
,
Object
>
vehicleEmergencyRecord
=
redisDataModel
.
getJson2Map
(
RedisKey
.
EMERGENCY_PARKING
.
getKeyPrefix
().
concat
(
vin
));
if
(
MapUtils
.
isNotEmpty
(
vehicleEmergencyRecord
)){
Integer
emergencyStatus
=
(
Integer
)
vehicleEmergencyRecord
.
get
(
"emergencyStatus"
);
if
(
1
==
emergencyStatus
){
record
.
put
(
"vinFlag"
,
1
);
sb
.
append
(
"车辆紧急急停 "
);
}
}
Object
stopExceed
=
record
.
get
(
"stopExceed"
);
if
(
Objects
.
nonNull
(
stopExceed
)&&
1
==
(
Integer
)
stopExceed
){
record
.
put
(
"vinFlag"
,
1
);
sb
.
append
(
"车辆停止超时 "
);
}
Object
dynamicFenceAlert
=
SpringUtils
.
getValue
(
"DYNAMIC_FENCE_ALERT"
,
vin
);
if
(
Objects
.
nonNull
(
dynamicFenceAlert
)){
record
.
put
(
"vinFlag"
,
1
);
sb
.
append
(
"封闭区触发任务暂停 "
);
}
jsonObject
.
put
(
"platError"
,
sb
.
toString
());
//TOS异常
Map
<
String
,
Object
>
json2Map
=
redisDataModel
.
getJson2Map
(
RedisKey
.
VMS_TOS_ORDER
.
getKeyPrefix
().
concat
(
vin
));
if
(
MapUtils
.
isNotEmpty
(
json2Map
)){
JSONObject
lastedOrder
=
new
JSONObject
();
lastedOrder
.
put
(
"startTime"
,
json2Map
.
get
(
"collectTime"
));
lastedOrder
.
put
(
"lockLabel"
,
json2Map
.
get
(
"lockLabel"
));
lastedOrder
.
put
(
"portCode"
,
json2Map
.
get
(
"portCode"
));
lastedOrder
.
put
(
"containerSize"
,
json2Map
.
get
(
"containerSize"
));
lastedOrder
.
put
(
"containerPosition"
,
json2Map
.
get
(
"containerPosition"
));
Integer
subTaskType
=
Objects
.
isNull
(
json2Map
.
get
(
"subTaskType"
))
?
null
:
(
Integer
)
json2Map
.
get
(
"subTaskType"
);
String
description
=
vehicleDataUtil
.
generateOrderDescription
(
json2Map
);
//判断subTaskType:0去缓冲区1,2 去扭锁站 其他用查询出来的
if
(
Objects
.
nonNull
(
subTaskType
)&&
subTaskType
==
0
){
lastedOrder
.
put
(
"orderDescription"
,
"去缓冲区"
);
}
else
if
(
Objects
.
nonNull
(
subTaskType
)&&(
subTaskType
==
1
||
subTaskType
==
2
)){
lastedOrder
.
put
(
"orderDescription"
,
"去扭锁站"
);
}
else
{
lastedOrder
.
put
(
"orderDescription"
,
description
);
}
jsonObject
.
put
(
"tosError"
,
lastedOrder
);
}
record
.
put
(
"errorMsg"
,
jsonObject
);
}
private
synchronized
void
calculateNextLocationByDirection
(
Map
<
String
,
Object
>
map
)
{
//获取航向角
if
(
Objects
.
isNull
(
map
.
get
(
"direction"
))){
return
;
}
try
{
double
direction
=
Double
.
parseDouble
(
String
.
valueOf
(
map
.
get
(
"direction"
)))/
100
;
Double
speed
=
Double
.
parseDouble
(
String
.
valueOf
(
map
.
get
(
"speed"
)));
double
[]
location
=
(
double
[])
map
.
get
(
"location"
);
int
decLabel
=
0
;
if
(
speed
<=
0
){
fixSpeedByGps
(
map
);
Double
gpsSpeed
=
Double
.
parseDouble
(
String
.
valueOf
(
map
.
get
(
"speed"
)));
if
(
gpsSpeed
<=
0
){
direction
=
168.96
;
decLabel
=
1
;
if
(
FieldUtil
.
isPortraitField
(
new
Point
(
location
[
0
],
location
[
1
]))){
direction
=
77.43
;
decLabel
=
2
;
}
}
JSONObject
old
=
gpsSpeedMap
.
get
(
vin
);
if
(
Objects
.
nonNull
(
old
)){
location
=
(
double
[])
old
.
get
(
"realLocation"
);
map
.
put
(
"location"
,
old
.
get
(
"realLocation"
));
}
}
else
{
gpsSpeedMap
.
remove
(
vin
);
}
//计算航向坐标
String
[]
strings
=
GeoPosTransformUtil
.
calLocationByDistanceAndLocationAndDirection
(
direction
,
location
[
0
],
location
[
1
],
3
);
map
.
put
(
"nextLocation"
,
strings
);
map
.
put
(
"decLabel"
,
decLabel
);
}
catch
(
Exception
e
){
log
.
info
(
"=====>{}"
,
e
.
getMessage
());
return
;
}
}
private
void
fixSpeedByGps
(
Map
<
String
,
Object
>
map
)
{
try
{
String
vin
=
String
.
valueOf
(
map
.
get
(
"vin"
));
double
[]
location
=
(
double
[])
map
.
get
(
"location"
);
long
collectTime
=
System
.
currentTimeMillis
();
//(long) map.get("collectTime");
JSONObject
old
=
gpsSpeedMap
.
get
(
vin
);
if
(
Objects
.
isNull
(
old
))
{
JSONObject
newObj
=
new
JSONObject
();
newObj
.
put
(
"realLocation"
,
location
);
newObj
.
put
(
"location"
,
location
);
newObj
.
put
(
"collectTime"
,
collectTime
);
newObj
.
put
(
"lastUpdateTime"
,
collectTime
);
gpsSpeedMap
.
put
(
vin
,
newObj
);
return
;
}
Long
oldCollectTime
=
old
.
getLong
(
"collectTime"
);
Long
lastUpdateTime
=
old
.
getLong
(
"lastUpdateTime"
);
double
[]
oldLocation
=
(
double
[])
old
.
get
(
"location"
);
BigDecimal
bigDecimal
=
null
;
if
(
collectTime
-
oldCollectTime
<
600
&&(
location
[
0
]!=
oldLocation
[
0
]||
location
[
1
]!=
oldLocation
[
1
])){
long
deltTime
=
collectTime
-
oldCollectTime
;
double
distance
=
GpsUtil
.
getDistance
(
oldLocation
[
0
],
oldLocation
[
1
],
location
[
0
],
location
[
1
]);
if
(
distance
>
0.0003
&&
deltTime
>
0
){
bigDecimal
=
new
BigDecimal
(
distance
/
(
deltTime
/
1000.0
/
3600.0
));
bigDecimal
=
bigDecimal
.
setScale
(
2
,
RoundingMode
.
HALF_UP
);
log
.
info
(
"vin:{}====>{},{},speed:{}"
,
vin
,
distance
,
deltTime
/
1000.0
/
3600.0
,
bigDecimal
.
doubleValue
());
map
.
put
(
"speed"
,
bigDecimal
.
doubleValue
());
old
.
put
(
"lastUpdateTime"
,
collectTime
);
old
.
put
(
"realLocation"
,
location
);
}
}
if
(
Objects
.
isNull
(
bigDecimal
)&&(
collectTime
-
lastUpdateTime
)>
5
*
60
*
1000
){
//速度为0计算是否超时
Object
o
=
StringUtils
.
isNotBlank
(
String
.
valueOf
(
map
.
get
(
"orderData"
)))?
map
.
put
(
"stopExceed"
,
1
)
:
null
;
}
old
.
put
(
"location"
,
location
);
old
.
put
(
"collectTime"
,
collectTime
);
}
catch
(
Exception
e
){
log
.
error
(
"fixSpeedByGps occur error:"
,
e
);
}
}
private
Map
<
String
,
Object
>
getData
()
{
Map
<
String
,
Object
>
poll
=
null
;
if
(
this
.
canPush
.
get
())
{
try
{
if
(!
this
.
evictingQueue
.
isEmpty
())
{
poll
=
this
.
evictingQueue
.
poll
();
if
(
poll
!=
null
)
{
poll
.
put
(
"poolSize"
,
size
());
checkNetError
(
poll
);
}
}
else
{
this
.
canPush
.
set
(
false
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"获取%s数据失败。"
,
vin
),
e
);
}
}
return
poll
;
}
private
int
size
()
{
return
this
.
evictingQueue
.
size
();
}
private
void
addLastLocationInfo
(
Map
<
String
,
Object
>
map
,
boolean
valid
)
{
//上一个点的坐标及前一坐标
String
location
=
redisDataModel
.
get
(
String
.
format
(
"%s:%s"
,
preLocationFix
,
map
.
get
(
"vin"
)));
Map
<
String
,
Object
>
status
=
redisDataModel
.
getJson2Map
(
String
.
format
(
"%s:%s"
,
latestOrderKeyPrefix
,
map
.
get
(
"vin"
)));
Map
<
String
,
Object
>
realMap
=
redisDataModel
.
getJson2Map
(
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
map
.
get
(
"vin"
),
realPostfix
));
map
.
put
(
"status"
,
status
==
null
?
"-"
:
VmsTosOrderStatusEnum
.
find
(
Integer
.
valueOf
(
status
.
get
(
"status"
)+
""
))==
null
?
""
:
VmsTosOrderStatusEnum
.
find
(
Integer
.
valueOf
(
status
.
get
(
"status"
)+
""
)).
getDescription
());
map
.
put
(
"direction"
,
realMap
==
null
?
"-"
:
realMap
.
get
(
"direction"
));
// 上一个点的坐标
Double
lastLongitude
=
null
;
Double
lastLatitude
=
null
;
if
(
StringUtils
.
isNotBlank
(
location
))
{
JSONObject
locationMap
=
JSON
.
parseObject
(
location
);
lastLongitude
=
locationMap
.
getDouble
(
"longitude"
);
lastLatitude
=
locationMap
.
getDouble
(
"latitude"
);
}
//当前点坐标
double
speed
=
Double
.
parseDouble
(
map
.
getOrDefault
(
"speed"
,
"0"
).
toString
());
Double
longitude
=
ConfigUtils
.
getAsDoubleWithDefault
(
map
,
"longitude"
,
null
);
Double
latitude
=
ConfigUtils
.
getAsDoubleWithDefault
(
map
,
"latitude"
,
null
);
if
(
speed
!=
0
&&
valid
)
{
if
(
longitude
!=
null
&&
latitude
!=
null
)
{
Map
<
String
,
Object
>
preWithSpeedMapTemp
=
new
HashMap
<>();
preWithSpeedMapTemp
.
put
(
"longitude"
,
longitude
);
preWithSpeedMapTemp
.
put
(
"latitude"
,
latitude
);
preWithSpeedMapTemp
.
put
(
"lastLongitude"
,
lastLongitude
);
preWithSpeedMapTemp
.
put
(
"lastLatitude"
,
lastLatitude
);
redisDataModel
.
set
(
String
.
format
(
"%s:%s"
,
preLocationFix
,
map
.
get
(
"vin"
)),
JSON
.
toJSONString
(
preWithSpeedMapTemp
));
preWithSpeedMap
=
preWithSpeedMapTemp
;
map
.
put
(
"preLocation"
,
new
double
[]{
lastLongitude
,
lastLatitude
});
}
}
else
{
if
(
preWithSpeedMap
!=
null
)
{
Double
longitude1
=
ConfigUtils
.
getAsDoubleWithDefault
(
preWithSpeedMap
,
"longitude"
,
null
);
Double
latitude1
=
ConfigUtils
.
getAsDoubleWithDefault
(
preWithSpeedMap
,
"latitude"
,
null
);
Double
longitude2
=
ConfigUtils
.
getAsDoubleWithDefault
(
preWithSpeedMap
,
"lastLongitude"
,
null
);
Double
latitude2
=
ConfigUtils
.
getAsDoubleWithDefault
(
preWithSpeedMap
,
"lastLatitude"
,
null
);
if
(
longitude1
!=
null
&&
latitude1
!=
null
)
{
map
.
put
(
"location"
,
new
double
[]{
longitude1
,
latitude1
});
}
if
(
longitude1
!=
null
&&
latitude1
!=
null
)
{
map
.
put
(
"preLocation"
,
getEndPointByTrigonometric
(
Double
.
valueOf
(
realMap
.
get
(
"direction"
)+
""
),
new
double
[]{
longitude1
,
latitude1
},
0.0001
));
}
}
}
}
private
boolean
isValid
(
Map
<
String
,
Object
>
map
)
{
boolean
valid
=
true
;
try
{
if
(
preMap
!=
null
)
{
//检查位置和速度
String
prelocation
=
String
.
format
(
"%s,%s"
,
preMap
.
get
(
"latitude"
),
preMap
.
get
(
"longitude"
));
String
location
=
String
.
format
(
"%s,%s"
,
map
.
get
(
"latitude"
),
map
.
get
(
"longitude"
));
double
speed
=
Double
.
parseDouble
(
map
.
getOrDefault
(
"speed"
,
"0"
).
toString
());
valid
=
!(
prelocation
.
equals
(
location
)
&&
speed
!=
0
);
if
(!
valid
)
{
// log.warn(String.format("车辆%s数据无效:\n (prelocation = %s, location = %s, speed = %s)",
// vin, prelocation, location, speed));
long
currentTime
=
(
long
)
map
.
get
(
"collectTime"
);
long
preTime
=
(
long
)
preMap
.
get
(
"collectTime"
);
//统计无效数据
preMap
.
put
(
"validCount"
,
(
long
)
preMap
.
getOrDefault
(
"validCount"
,
0L
)
+
(
currentTime
-
preTime
));
preMap
.
put
(
"speed"
,
speed
);
}
}
if
(
valid
)
{
preMap
=
map
;
}
}
catch
(
Exception
e
)
{
log
.
error
(
"数据检查异常。"
,
e
);
valid
=
false
;
}
return
valid
;
}
private
void
checkNetError
(
Map
<
String
,
Object
>
current
)
{
Map
<
String
,
Object
>
next
=
this
.
evictingQueue
.
peek
();
try
{
long
validCount
=
0
;
if
(
preMap
!=
null
)
{
validCount
=
(
long
)
preMap
.
getOrDefault
(
"validCount"
,
0L
);
}
if
(
next
!=
null
)
{
//检查是否存在掉包行为
long
currentTime
=
(
long
)
current
.
get
(
"collectTime"
);
long
nextTime
=
(
long
)
next
.
get
(
"collectTime"
);
//网络延迟
if
((
nextTime
-
currentTime
)
>=
this
.
dataFrequency
*
1.2
+
validCount
)
{
current
.
put
(
"netError"
,
true
);
}
}
else
if
(
validCount
<=
0
)
{
//避免一直传无效数据的情况
double
speed
=
Double
.
parseDouble
(
current
.
getOrDefault
(
"speed"
,
"0"
).
toString
());
if
(
speed
>
0
)
{
current
.
put
(
"netError"
,
true
);
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
String
.
format
(
"检查%s掉包行为失败..."
,
vin
),
e
);
}
}
}
private
static
double
[]
getEndPointByTrigonometric
(
double
angle
,
double
[]
startPoint
,
double
distance
)
{
double
[]
endPoint
=
new
double
[
2
];
//角度转弧度
double
radian
=
(
angle
*
Math
.
PI
)
/
180
;
//计算新坐标 r 就是两者的距离
endPoint
[
0
]
=
startPoint
[
0
]
+
distance
*
Math
.
cos
(
radian
);
endPoint
[
1
]
=
startPoint
[
1
]
+
distance
*
Math
.
sin
(
radian
);
return
endPoint
;
}
private
Runnable
asyncProcessRoutingConflict
(
Map
<
String
,
Map
<
String
,
Object
>>
messages
){
return
()->
vehicleRealTimeInfoListener
.
processRoutingConflict
(
messages
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/model/WebSocketDataServiceModel.java
0 → 100644
View file @
07602a7b
package
com.ssi.model
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
import
org.springframework.stereotype.Component
;
import
java.util.Collection
;
import
java.util.Map
;
/**
* Description: 股份数据增加车辆到达报警触发 arrivedStatus = 1 可能会错过
* <p>
* 修改逻辑查询逻辑: 存在变化再往后发 车辆下线不发
*
* @author LiXiaoCong
* @version 2019/9/20 11:48
*/
@Component
@EnableScheduling
@Slf4j
public
class
WebSocketDataServiceModel
{
@Value
(
"${spring.webscoket.checkRepate:false}"
)
private
boolean
checkRepate
;
@Autowired
private
VehicleLatestDataModel
vehicleLatestDataModel
;
/**
* 停车时经纬度跳变处理
*/
private
Map
<
String
,
String
>
lastMap
=
Maps
.
newConcurrentMap
();
public
Map
<
String
,
Map
<
String
,
Object
>>
realTimeData
(
Collection
<
String
>
vins
)
{
return
realTimeData
(
vins
,
checkRepate
);
}
public
Map
<
String
,
Map
<
String
,
Object
>>
realTimeData
(
Collection
<
String
>
vins
,
boolean
checkRepeat
)
{
Map
<
String
,
Map
<
String
,
Object
>>
res
;
if
(
vins
!=
null
&&
!
vins
.
isEmpty
())
{
String
latestRedisKeyPrefix
=
vehicleLatestDataModel
.
getLatestRedisKeyPrefix
();
String
latestRedisKeyPostfix
=
vehicleLatestDataModel
.
getLatestRedisKeyPostfix
();
String
latestRedisKeyD001Postfix
=
vehicleLatestDataModel
.
getLatestRedisKeyPrefix
();
String
latestRedisKeyD002Postfix
=
vehicleLatestDataModel
.
getLatestRedisKeyPrefix
();
Map
<
String
,
Map
<
String
,
String
>>
keysMap
=
Maps
.
newHashMap
();
vins
.
stream
().
forEach
(
key
->
{
Map
<
String
,
String
>
keyPreMap
=
Maps
.
newHashMap
();
keyPreMap
.
put
(
"latestKey"
,
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyPostfix
));
keyPreMap
.
put
(
"d001Key"
,
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyD001Postfix
));
keyPreMap
.
put
(
"d002Key"
,
String
.
format
(
"%s:%s-%s"
,
latestRedisKeyPrefix
,
key
,
latestRedisKeyD002Postfix
));
keysMap
.
put
(
key
,
keyPreMap
);
});
res
=
vehicleLatestDataModel
.
readLatestDataFromRedis
(
keysMap
,
checkRepeat
);
}
else
{
res
=
Maps
.
newHashMap
();
}
return
res
;
}
public
Map
<
String
,
Map
<
String
,
Object
>>
realTimeDataAll
(
boolean
checkRepeat
)
{
return
vehicleLatestDataModel
.
allRealTimeData
(
checkRepeat
);
}
public
Map
<
String
,
Map
<
String
,
Object
>>
getVehicleRunData
()
{
return
vehicleLatestDataModel
.
getVehicleRunData
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/mqtt/MQTTPublishClient.java
0 → 100644
View file @
07602a7b
package
com.ssi.mqtt
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.ssi.constant.VehicleConstant
;
import
com.ssi.entity.dto.VmsVehicleDto
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.*
;
import
org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
;
@Slf4j
public
class
MQTTPublishClient
{
//定义MQTT的ID,可以在MQTT服务配置中指定
private
String
clientid
;
private
String
mqttCAPath
;
private
String
mqttName
;
private
String
mqttPassword
;
private
String
mqttUrl
;
private
MqttClient
client
;
@Setter
@Getter
private
MqttTopic
mqttTopic
;
/**
* 构造函数
*/
public
MQTTPublishClient
(
String
host
,
String
serverId
,
String
mqttCAPath
,
String
mqttName
,
String
mqttPassword
,
String
mqttUrl
)
{
log
.
info
(
"MQTTPublishClient instance"
);
this
.
clientid
=
serverId
;
this
.
mqttCAPath
=
mqttCAPath
;
this
.
mqttName
=
mqttName
;
this
.
mqttPassword
=
mqttPassword
;
this
.
mqttUrl
=
mqttUrl
;
// MemoryPersistence设置clientid的保存形式,默认为以内存保存
try
{
if
(
client
==
null
)
{
client
=
new
MqttClient
(
host
,
clientid
,
new
MemoryPersistence
());
}
}
catch
(
MqttException
e
)
{
e
.
printStackTrace
();
}
connect
();
}
/**
* 用来连接服务器
*/
private
void
connect
()
{
MqttConnectOptions
options
=
new
MqttConnectOptions
();
options
.
setCleanSession
(
true
);
// 设置超时时间
options
.
setConnectionTimeout
(
20
);
// 设置会话心跳时间
options
.
setKeepAliveInterval
(
10
);
// options.setAutomaticReconnect(true);//设置自动重连
try
{
options
.
setSocketFactory
(
SslUtil
.
getSocketFactory
(
mqttCAPath
,
"/UserProfile/ca/client.crt"
,
"/UserProfile/ca/client.key"
,
"123456"
));
client
.
setCallback
(
new
PublishCallback
());
client
.
connect
(
options
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
public
void
mqttRequest
(
VmsVehicleDto
vehicle
,
String
cntType
)
{
try
{
//发送mqtt请求
MqttMessage
message
=
new
MqttMessage
();
JSONObject
msgObj
=
new
JSONObject
();
msgObj
.
put
(
"devType"
,
"web"
);
msgObj
.
put
(
"cntType"
,
cntType
);
JSONObject
dataObj
=
new
JSONObject
();
dataObj
.
put
(
"name"
,
mqttName
);
dataObj
.
put
(
"password"
,
mqttPassword
);
dataObj
.
put
(
"sn"
,
vehicle
.
getVinSSI
());
JSONArray
cameraArray
=
new
JSONArray
();
String
vehicleNum
=
vehicle
.
getVehicleNum
().
substring
(
vehicle
.
getVehicleNum
().
length
()
-
1
);
if
(
VehicleConstant
.
START_PUSHER
.
equals
(
cntType
))
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
JSONObject
cameraObj
=
new
JSONObject
();
cameraObj
.
put
(
"url"
,
mqttUrl
+
vehicleNum
+
"_"
+
i
);
cameraObj
.
put
(
"status"
,
"disable"
);
if
(
i
==
2
)
{
cameraObj
.
put
(
"status"
,
"enable"
);
}
cameraArray
.
add
(
cameraObj
);
}
dataObj
.
put
(
"camera"
,
cameraArray
);
msgObj
.
put
(
"startPusherData"
,
dataObj
);
}
else
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
JSONObject
cameraObj
=
new
JSONObject
();
cameraObj
.
put
(
"url"
,
""
);
cameraObj
.
put
(
"status"
,
"disable"
);
cameraArray
.
add
(
cameraObj
);
}
dataObj
.
put
(
"camera"
,
cameraArray
);
msgObj
.
put
(
"stopPusherData"
,
dataObj
);
}
message
.
setPayload
(
msgObj
.
toJSONString
().
getBytes
(
"UTF-8"
));
message
.
setQos
(
0
);
message
.
setRetained
(
false
);
this
.
publish
(
"ssiweb"
,
message
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
}
//发送消息并获取回执
void
publish
(
String
topic
,
MqttMessage
message
)
throws
MqttPersistenceException
,
MqttException
,
InterruptedException
{
log
.
info
(
"publish topic: "
+
topic
);
mqttTopic
=
client
.
getTopic
(
topic
);
MqttDeliveryToken
token
=
mqttTopic
.
publish
(
message
);
token
.
waitForCompletion
();
log
.
info
(
"message is published completely! "
+
token
.
isComplete
());
log
.
info
(
"messageId:"
+
token
.
getMessageId
());
token
.
getResponse
();
if
(
client
.
isConnected
())
{
client
.
disconnect
(
10000
);
}
log
.
info
(
"Disconnected: delivery token \""
+
token
.
hashCode
()
+
"\" received: "
+
token
.
isComplete
());
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/mqtt/MQTTSubcribeClient.java
0 → 100644
View file @
07602a7b
package
com.ssi.mqtt
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.MqttClient
;
import
org.eclipse.paho.client.mqttv3.MqttConnectOptions
;
import
org.eclipse.paho.client.mqttv3.MqttException
;
import
org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
;
@Slf4j
public
class
MQTTSubcribeClient
{
public
String
HOST
;
private
MqttClient
client
;
private
MqttConnectOptions
options
;
public
MQTTSubcribeClient
(
String
host
,
String
clientid
,
String
mqttCAPath
)
{
try
{
this
.
HOST
=
host
;
log
.
info
(
"MQTTSubcribeClient instanced"
);
// host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
client
=
new
MqttClient
(
HOST
,
clientid
,
new
MemoryPersistence
());
// MQTT的连接设置
options
=
new
MqttConnectOptions
();
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
options
.
setCleanSession
(
false
);
// 设置超时时间 单位为秒
options
.
setConnectionTimeout
(
20
);
// 设置会话心跳时间 单位为秒 服务器会每隔5秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options
.
setKeepAliveInterval
(
10
);
options
.
setAutomaticReconnect
(
true
);
//设置自动重连
// 设置回调
try
{
options
.
setSocketFactory
(
SslUtil
.
getSocketFactory
(
mqttCAPath
,
"/UserProfile/ca/client.crt"
,
"/UserProfile/ca/client.key"
,
"123456"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
client
.
setCallback
(
new
SubcribeCallBack
());
client
.
connect
(
options
);
//订阅消息
String
[]
topic1
=
{
"ssiweb"
};
client
.
subscribe
(
topic1
);
}
catch
(
MqttException
e
)
{
e
.
printStackTrace
();
}
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/mqtt/PublishCallback.java
0 → 100644
View file @
07602a7b
package
com.ssi.mqtt
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.IMqttDeliveryToken
;
import
org.eclipse.paho.client.mqttv3.MqttCallbackExtended
;
import
org.eclipse.paho.client.mqttv3.MqttMessage
;
@Slf4j
public
class
PublishCallback
implements
MqttCallbackExtended
{
@Override
public
void
connectionLost
(
Throwable
cause
)
{
// 连接丢失后,一般在这里面进行重连
log
.
info
(
"[PublishCallback] 连接断开"
);
}
@Override
public
void
deliveryComplete
(
IMqttDeliveryToken
token
)
{
log
.
info
(
"deliveryComplete---------"
+
token
.
isComplete
());
}
@Override
public
void
messageArrived
(
String
topic
,
MqttMessage
message
)
throws
Exception
{
}
@Override
public
void
connectComplete
(
boolean
b
,
String
s
)
{
log
.
info
(
"connected"
);
}
}
\ No newline at end of file
ivccs-vmm-backservice/src/main/java/com/ssi/mqtt/SslUtil.java
0 → 100644
View file @
07602a7b
package
com.ssi.mqtt
;
import
java.io.InputStreamReader
;
import
java.security.KeyStore
;
import
java.security.Security
;
import
java.security.cert.X509Certificate
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.net.ssl.TrustManagerFactory
;
import
org.bouncycastle.jce.provider.BouncyCastleProvider
;
import
org.bouncycastle.openssl.PEMReader
;
import
org.springframework.core.io.ClassPathResource
;
public
class
SslUtil
{
public
static
SSLSocketFactory
getSocketFactory
(
final
String
caCrtFile
,
final
String
crtFile
,
final
String
keyFile
,
final
String
password
)
throws
Exception
{
Security
.
addProvider
(
new
BouncyCastleProvider
());
// load CA certificate
PEMReader
reader
=
new
PEMReader
(
new
InputStreamReader
(
new
ClassPathResource
(
caCrtFile
).
getInputStream
()));
X509Certificate
caCert
=
(
X509Certificate
)
reader
.
readObject
();
reader
.
close
();
// load client certificate
// reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(crtFile)))));
// X509Certificate cert = (X509Certificate)reader.readObject();
// reader.close();
// load client private key
// reader = new PEMReader(
// new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(keyFile)))),
// new PasswordFinder() {
// @Override
// public char[] getPassword() {
// return password.toCharArray();
// }
// }
// );
// KeyPair key = (KeyPair)reader.readObject();
// reader.close();
// CA certificate is used to authenticate server
KeyStore
caKs
=
KeyStore
.
getInstance
(
KeyStore
.
getDefaultType
());
caKs
.
load
(
null
,
null
);
caKs
.
setCertificateEntry
(
"ca-certificate"
,
caCert
);
TrustManagerFactory
tmf
=
TrustManagerFactory
.
getInstance
(
TrustManagerFactory
.
getDefaultAlgorithm
());
tmf
.
init
(
caKs
);
// client key and certificates are sent to server so it can authenticate us
// KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// ks.load(null, null);
// ks.setCertificateEntry("certificate", cert);
// ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// kmf.init(ks, password.toCharArray());
// finally, create SSL socket factory
SSLContext
context
=
SSLContext
.
getInstance
(
"TLSv1.2"
);
context
.
init
(
null
,
tmf
.
getTrustManagers
(),
null
);
return
context
.
getSocketFactory
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/mqtt/SubcribeCallBack.java
0 → 100644
View file @
07602a7b
package
com.ssi.mqtt
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.IMqttDeliveryToken
;
import
org.eclipse.paho.client.mqttv3.MqttCallbackExtended
;
import
org.eclipse.paho.client.mqttv3.MqttMessage
;
@Slf4j
public
class
SubcribeCallBack
implements
MqttCallbackExtended
{
@Override
public
void
connectionLost
(
Throwable
throwable
)
{
log
.
warn
(
"client lost connection,reconnecting"
);
}
@Override
public
void
messageArrived
(
String
s
,
MqttMessage
mqttMessage
)
throws
Exception
{
try
{
// subscribe后得到的消息会执行到这里面
log
.
info
(
"接收消息主题 : "
+
s
);
log
.
info
(
"接收消息Qos : "
+
mqttMessage
.
getQos
());
log
.
info
(
"接收消息内容 : "
+
new
String
(
mqttMessage
.
getPayload
()));
String
str
=
mqttMessage
.
toString
();
log
.
info
(
"从MQTT收到的消息为:"
+
str
+
" ;TOPIC:"
+
s
);
}
catch
(
Exception
e
)
{
log
.
error
(
"SubcribeCallBack error:"
+
e
.
getMessage
());
e
.
printStackTrace
();
}
}
@Override
public
void
deliveryComplete
(
IMqttDeliveryToken
iMqttDeliveryToken
)
{
log
.
info
(
"deliveryComplete---------"
+
iMqttDeliveryToken
.
isComplete
());
}
@Override
public
void
connectComplete
(
boolean
b
,
String
s
)
{
log
.
info
(
"receive connectted"
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/mqtt/TestSSLPublish.java
0 → 100644
View file @
07602a7b
package
com.ssi.mqtt
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
org.eclipse.paho.client.mqttv3.MqttMessage
;
import
java.util.HashMap
;
import
java.util.Map
;
public
class
TestSSLPublish
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
//mqtt发送端
MQTTPublishClient
mqttClientSend
=
new
MQTTPublishClient
(
"ssl://10.11.10.28:1884"
,
"mqttx_8b1e19a2"
,
"C://Users/hekai/Desktop/ca_cidi.pem"
,
""
,
""
,
""
);
MqttMessage
message
=
new
MqttMessage
();
JSONObject
msgObj
=
new
JSONObject
();
msgObj
.
put
(
"devType"
,
"web"
);
msgObj
.
put
(
"cntType"
,
"startPusher"
);
JSONObject
dataObj
=
new
JSONObject
();
dataObj
.
put
(
"name"
,
"ssiweb"
);
dataObj
.
put
(
"password"
,
"ssiweb123456"
);
dataObj
.
put
(
"sn"
,
"CSU100FB21080030"
);
JSONObject
cameraObj
=
new
JSONObject
();
cameraObj
.
put
(
"url"
,
"rtmp://10.11.10.28/live/2_2"
);
cameraObj
.
put
(
"status"
,
"enable"
);
JSONArray
cameraArray
=
new
JSONArray
();
cameraArray
.
add
(
cameraObj
);
dataObj
.
put
(
"camera"
,
cameraArray
);
msgObj
.
put
(
"startPusherData"
,
dataObj
);
message
.
setPayload
(
msgObj
.
toJSONString
().
getBytes
(
"UTF-8"
));
message
.
setQos
(
0
);
message
.
setRetained
(
false
);
System
.
out
.
println
(
"MQTT发送消息"
);
mqttClientSend
.
publish
(
"ssiweb"
,
message
);
}
}
\ No newline at end of file
Prev
1
…
9
10
11
12
13
14
15
16
17
…
24
Next
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