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/utils/SpringUtils.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils
;
import
org.apache.commons.collections.MapUtils
;
import
org.apache.commons.lang3.tuple.MutableTriple
;
import
org.apache.commons.lang3.tuple.Triple
;
import
org.springframework.beans.BeansException
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContextAware
;
import
org.springframework.stereotype.Component
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
@Component
public
class
SpringUtils
implements
ApplicationContextAware
{
private
static
ApplicationContext
applicationContext
;
private
static
Map
<
String
,
Map
<
String
,
Object
>>
localCache
=
new
ConcurrentHashMap
<>();
@Override
public
void
setApplicationContext
(
ApplicationContext
applicationContextParam
)
throws
BeansException
{
applicationContext
=
applicationContextParam
;
}
public
static
Object
getObject
(
String
id
)
{
Object
object
=
null
;
object
=
applicationContext
.
getBean
(
id
);
return
object
;
}
public
static
<
T
>
T
getObject
(
Class
<
T
>
tClass
)
{
return
applicationContext
.
getBean
(
tClass
);
}
public
static
Object
getBean
(
String
tClass
)
{
return
applicationContext
.
getBean
(
tClass
);
}
public
static
void
setLocalCache
(
String
topic
,
String
key
,
Object
value
)
{
Map
<
String
,
Object
>
valMap
=
localCache
.
get
(
topic
);
synchronized
(
SpringUtils
.
class
){
if
(
MapUtils
.
isNotEmpty
(
valMap
)){
valMap
.
put
(
key
,
value
);
}
else
{
localCache
.
put
(
topic
,
new
HashMap
<
String
,
Object
>(){{
put
(
key
,
value
);}});
}
}
}
public
static
Object
getValue
(
String
topic
,
String
key
){
Map
<
String
,
Object
>
valMap
=
localCache
.
get
(
topic
);
if
(
MapUtils
.
isNotEmpty
(
valMap
)){
return
valMap
.
get
(
key
);
}
return
null
;
}
public
static
void
clearStatus
(
String
topic
,
String
key
){
Map
<
String
,
Object
>
valMap
=
localCache
.
get
(
topic
);
if
(
MapUtils
.
isNotEmpty
(
valMap
)){
valMap
.
remove
(
key
);
}
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/TestGetBean.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileReader
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.io.Reader
;
import
java.sql.Connection
;
import
java.sql.DriverManager
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.ResultSetMetaData
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.Vector
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.kafka.core.KafkaTemplate
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.ssi.constant.URL
;
import
com.ssi.entity.VmsShipNcl
;
import
com.ssi.entity.dto.VmsTosOrdersDto
;
import
com.ssi.response.SSIResponse
;
public
class
TestGetBean
{
private
Connection
connection
;
private
PreparedStatement
UserQuery
;
/* mysql url的连接字符串 */
// private static String url = "jdbc:mysql://127.0.0.1:3306/rad?useUnicode=true&characterEncoding=UTF-8";
private
static
String
url
=
"jdbc:oracle:thin:@//172.16.1.239:1521/test2.coscoyh.com.cn"
;
// 账号 172.16.1.239:1521/test2.coscoyh.com.cn
private
static
String
user
=
"XMYH_DCV"
;
// 密码
private
static
String
password
=
"coscoyh"
;
private
Vector
<
String
>
vector
=
new
Vector
<
String
>();
// mysql jdbc的java包驱动字符串
// private String driverClassName = "com.mysql.jdbc.Driver";
private
String
driverClassName
=
"oracle.jdbc.OracleDriver"
;
// 数据库中的表名
String
table
=
"sys_logs"
;
// 数据库的列名称
private
String
[]
colnames
;
// 列名数组
// 列名类型数组
private
String
[]
colTypes
;
public
TestGetBean
()
{
try
{
// 驱动注册
Class
.
forName
(
driverClassName
);
if
(
connection
==
null
||
connection
.
isClosed
())
// 获得链接
connection
=
DriverManager
.
getConnection
(
url
,
user
,
password
);
}
catch
(
ClassNotFoundException
ex
)
{
ex
.
printStackTrace
();
System
.
out
.
println
(
"Oh,not"
);
}
catch
(
SQLException
e
)
{
e
.
printStackTrace
();
System
.
out
.
println
(
"Oh,not"
);
}
}
public
Connection
getConnection
()
{
return
connection
;
}
public
void
setConnection
(
Connection
connection
)
{
this
.
connection
=
connection
;
}
public
void
doAction
()
{
String
sql
=
"select * from "
+
table
;
try
{
PreparedStatement
statement
=
connection
.
prepareStatement
(
sql
);
// 获取数据库的元数据
ResultSetMetaData
metadata
=
statement
.
getMetaData
();
// 数据库的字段个数
int
len
=
metadata
.
getColumnCount
();
// 字段名称
colnames
=
new
String
[
len
+
1
];
// 字段类型 --->已经转化为java中的类名称了
colTypes
=
new
String
[
len
+
1
];
for
(
int
i
=
1
;
i
<=
len
;
i
++)
{
// System.out.println(metadata.getColumnName(i)+":"+metadata.getColumnTypeName(i)+":"+sqlType2JavaType(metadata.getColumnTypeName(i).toLowerCase())+":"+metadata.getColumnDisplaySize(i));
// metadata.getColumnDisplaySize(i);
colnames
[
i
]
=
metadata
.
getColumnName
(
i
);
// 获取字段名称
System
.
out
.
println
(
colnames
[
i
]);
colTypes
[
i
]
=
sqlType2JavaType
(
metadata
.
getColumnTypeName
(
i
));
// 获取字段类型
System
.
out
.
println
(
metadata
.
getColumnTypeName
(
i
));
System
.
out
.
println
(
colTypes
[
i
]);
}
}
catch
(
SQLException
e
)
{
e
.
printStackTrace
();
}
}
/*
* mysql的字段类型转化为java的类型
*/
private
String
sqlType2JavaType
(
String
sqlType
)
{
if
(
sqlType
.
equalsIgnoreCase
(
"bit"
))
{
return
"boolean"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"tinyint"
))
{
return
"byte"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"smallint"
))
{
return
"short"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"int"
))
{
return
"int"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"bigint"
))
{
return
"long"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"float"
))
{
return
"float"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"decimal"
)
||
sqlType
.
equalsIgnoreCase
(
"numeric"
)
||
sqlType
.
equalsIgnoreCase
(
"real"
)
||
sqlType
.
equalsIgnoreCase
(
"money"
)
||
sqlType
.
equalsIgnoreCase
(
"smallmoney"
))
{
return
"double"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"varchar"
)
||
sqlType
.
equalsIgnoreCase
(
"char"
)
||
sqlType
.
equalsIgnoreCase
(
"nvarchar"
)
||
sqlType
.
equalsIgnoreCase
(
"nchar"
)
||
sqlType
.
equalsIgnoreCase
(
"text"
))
{
return
"String"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"datetime"
)
||
sqlType
.
equalsIgnoreCase
(
"date"
))
{
return
"Date"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"image"
))
{
return
"Blod"
;
}
else
if
(
sqlType
.
equalsIgnoreCase
(
"timestamp"
))
{
return
"Timestamp"
;
}
return
null
;
}
/*
* 获取整个类的字符串并且输出为java文件
*/
public
StringBuffer
getClassStr
()
{
// 输出的类字符串
StringBuffer
str
=
new
StringBuffer
(
""
);
// 获取表类型和表名的字段名
this
.
doAction
();
// 校验
if
(
null
==
colnames
&&
null
==
colTypes
)
return
null
;
// 拼接
str
.
append
(
"public class "
+
GetTuoFeng
(
table
)
+
" {\r\n"
);
// 拼接属性
for
(
int
index
=
1
;
index
<
colnames
.
length
;
index
++)
{
str
.
append
(
getAttrbuteString
(
colnames
[
index
],
colTypes
[
index
]));
}
// 拼接get,Set方法
for
(
int
index
=
1
;
index
<
colnames
.
length
;
index
++)
{
str
.
append
(
getGetMethodString
(
colnames
[
index
],
colTypes
[
index
]));
str
.
append
(
getSetMethodString
(
colnames
[
index
],
colTypes
[
index
]));
}
str
.
append
(
"}\r\n"
);
// 输出到文件中
// File file = new File("E:/mengwx/【源码】mysql版本_spring4.0/FHMYSQL/src/com/fh/entity/"+GetTuoFeng(table)+".java");
// BufferedWriter write = null;
//
// try {
// write = new BufferedWriter(new FileWriter(file));
// write.write(str.toString());
// write.close();
// } catch (IOException e) {
//
// e.printStackTrace();
// if (write != null)
// try {
// write.close();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
// }
return
str
;
}
/*
* 获取字段字符串
*/
public
StringBuffer
getAttrbuteString
(
String
name
,
String
type
)
{
if
(!
check
(
name
,
type
))
{
System
.
out
.
println
(
"类中有属性或者类型为空"
);
return
null
;
}
;
String
format
=
String
.
format
(
" private %s %s;\n\r"
,
new
String
[]
{
type
,
name
});
return
new
StringBuffer
(
format
);
}
/*
* 校验name和type是否合法
*/
public
boolean
check
(
String
name
,
String
type
)
{
if
(
""
.
equals
(
name
)
||
name
==
null
||
name
.
trim
().
length
()
==
0
)
{
return
false
;
}
if
(
""
.
equals
(
type
)
||
type
==
null
||
type
.
trim
().
length
()
==
0
)
{
return
false
;
}
return
true
;
}
/*
* 获取get方法字符串
*/
private
StringBuffer
getGetMethodString
(
String
name
,
String
type
)
{
if
(!
check
(
name
,
type
))
{
System
.
out
.
println
(
"类中有属性或者类型为空"
);
return
null
;
}
;
String
Methodname
=
"get"
+
GetTuoFeng
(
name
);
String
format
=
String
.
format
(
" public %s %s(){\n\r"
,
new
Object
[]
{
type
,
Methodname
});
format
+=
String
.
format
(
" return this.%s;\r\n"
,
new
Object
[]
{
name
});
format
+=
" }\r\n"
;
return
new
StringBuffer
(
format
);
}
// 将名称首字符大写
private
String
GetTuoFeng
(
String
name
)
{
name
=
name
.
trim
();
if
(
name
.
length
()
>
1
)
{
name
=
name
.
substring
(
0
,
1
).
toUpperCase
()
+
name
.
substring
(
1
);
}
else
{
name
=
name
.
toUpperCase
();
}
return
name
;
}
/*
* 获取字段的get方法字符串
*/
private
Object
getSetMethodString
(
String
name
,
String
type
)
{
if
(!
check
(
name
,
type
))
{
System
.
out
.
println
(
"类中有属性或者类型为空"
);
return
null
;
}
;
String
Methodname
=
"set"
+
GetTuoFeng
(
name
);
String
format
=
String
.
format
(
" public void %s(%s %s){\n\r"
,
new
Object
[]
{
Methodname
,
type
,
name
});
format
+=
String
.
format
(
" this.%s = %s;\r\n"
,
new
Object
[]
{
name
,
name
});
format
+=
" }\r\n"
;
return
new
StringBuffer
(
format
);
}
// public static void main(String[] args) {
// TestGetBean bean = new TestGetBean();
// System.err.println(bean.getClassStr());
// JSONObject param = new JSONObject();
// Integer []aa= {22};
// String []bb= {"19","20"};
// param.put("ids",aa);//区域类型。1桥下,2桥后
// param.put("priority", 1);
// String paramData = JSONObject.toJSONString(param);
// System.out.println("绘制地图区域保存请求发送------"+ paramData);
// String result = RestTemplateUtil.post("http://10.11.10.1:8030/vehicleBuffer/priority" , paramData, null);
// System.out.print(String.format("绘制地图区域保存返回结果:----%s", result));
// JSONObject param = new JSONObject();
// String tempIds="19,2";
//
// List<Integer> tempId = new ArrayList<>();
//
// String[] ids = tempIds.split(",");
// for (String id : ids){
// tempId.add(Integer.parseInt(id));
//
// }
//
// String paramData = JSONObject.toJSONString(tempId);
// System.out.println("绘制地图区域保存请求发送------"+ paramData);
// String result = RestTemplateUtil.post("http://10.11.10.1:8030/vehicleBuffer/delete" , paramData, null);
// System.out.print(String.format("绘制地图区域保存返回结果:----%s", result));
// System.out.println(StringUtils.isNumeric("12,"));
// String Str1 = "P1156756";
// List t = new ArrayList();
// System.out.println(t.size() < 0);
//// VmsShipNcl t=new VmsShipNcl();
// String arg = "";
// System.out.println(JsonUtil.jsonToMap(arg));
// System.out.println();
// param.put("seq",456);//编号
// param.put("lng1",11.11);
// param.put("lat1",12.23);
// param.put("lng2",23.23);
// param.put("lat2",23.2);
// param.put("lng3",23.3);
// param.put("lat3",23.7);
// param.put("lng4",26.2);
// param.put("lat4",24.5);
// param.put("field","F");//场区(E/F)
// param.put("placeType",2);//区域类型。1桥下,2桥后
// param.put("id",19);//区域类型。1桥下,2桥后
// param.put("name","2223");//名称
// param.put("type",1);//类型。1缓冲区;2停车区;3:充电区
// param.put("state",1);//状态。0可用;1不可用(初始状态);2已计划;3有车
//
// String paramData = JSONObject.toJSONString(param);
// System.out.print(String.format("绘制地图区域保存请求发送:----%s", paramData));
// String result = RestTemplateUtil.post("http://10.11.10.1:8030/vehicleBuffer/edit" , paramData, null);
//// String result = RestTemplateUtil.post(String.format("%s%s", "http://10.11.10.1:8030/vehicleBuffer/edit", URL.MAP_EDIT_URL), paramData, null);
// System.out.print("绘制地图区域保存返回结果:------------"+result);
// }
public
void
testkafa
(
VmsTosOrdersDto
dto
)
{
// KafkaTemplate<String, String> kafkaTemplate =new KafkaTemplate<String, String>( );
JSONObject
param
=
new
JSONObject
();
Date
date
=
new
Date
();
param
.
put
(
"taskNo"
,
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
));
// 任务编号
param
.
put
(
"seq"
,
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
));
// 序号
param
.
put
(
"taskAssociation"
,
""
);
// 任务关联
param
.
put
(
"vin"
,
dto
.
getVin
());
// 车辆编号
param
.
put
(
"taskLocationType"
,
dto
.
getTaskLocationType
());
// 任务类型 作业位置类型
// 1-去堆场(装箱或卸箱);2-去停车点(上扭锁,解扭锁,停车);3-去固定停车区;4-去临时停车区;5-去桥吊(装箱或卸箱);6-去充电
param
.
put
(
"taskType"
,
dto
.
getTaskType
());
// 作业类型 1-装箱,2-卸箱
param
.
put
(
"vehicleTaskType"
,
dto
.
getVehicleTaskType
());
// 车辆任务类型 对应着前台 集装箱类型
param
.
put
(
"portCode"
,
dto
.
getPortCode
());
// 港机编码
if
(
dto
.
getPortCode
().
substring
(
0
,
1
).
equals
(
"1"
))
{
param
.
put
(
"portType"
,
"1"
);
// 港机类型
}
else
{
param
.
put
(
"portType"
,
"2"
);
// 港机类型
}
param
.
put
(
"vehicleLocation"
,
dto
.
getVehicleLocation
());
// 车辆任务目标地点 对应前台 堆场贝位
param
.
put
(
"cartonConditon"
,
"0"
);
// 辆当前装箱状态
param
.
put
(
"containerId"
,
dto
.
getContainerId
());
// 集装箱ID
if
(
dto
.
getVehicleTaskType
().
equals
(
"1"
))
{
param
.
put
(
"containerType"
,
"40"
);
// 集装箱类型
}
else
{
param
.
put
(
"containerType"
,
"20"
);
// 集装箱类型
}
param
.
put
(
"containerWeight"
,
"1"
);
// 集装箱重量
// param.put("containerPosition","");//集装箱车上位置
// param.put("overSign","");// 作业完成信号
param
.
put
(
"collectTime"
,
date
);
// 作业时间
// param.put("voyuageNo","");//艘次编号
param
.
put
(
"lockLabel"
,
dto
.
getLockLabel
());
// 扭锁标签
if
(
dto
.
getTaskLocationType
().
equals
(
"1"
))
{
param
.
put
(
"containerLabel"
,
"1"
);
}
else
{
param
.
put
(
"containerLabel"
,
"2"
);
}
String
paramData
=
JSONObject
.
toJSONString
(
param
);
// log.info(String.format("绘制地图区域保存请求发送:----%s", paramData));
// this.kafkaTemplate.send(topic, key, data);
}
public
static
void
main
(
String
[]
args
)
{
String
mapdata
=
"P1223456780"
;
System
.
out
.
println
(
Integer
.
valueOf
(
mapdata
.
substring
(
1
)));
// String path="D:\\code/lsz.geojson";
//// String path = JsonTest.class.getClassLoader().getResource("students.json").getPath();
// String s = readJsonFile(path);
// JSONObject jobj = JSON.parseObject(s);
// JSONArray student = jobj.getJSONArray("features");//构建JSONArray数组
// for (int i = 0 ; i < student.size();i++){
// JSONObject key = (JSONObject)student.get(i);
// int stuId= (Integer)key.get("id");
// Object stuName= (Object)key.get("geometry");
//// int stuAge= (Integer)key.get("stuAge");
// JSONObject jsonObject = JSONObject.parseObject(stuName.toString());
//
// for(String str:jsonObject.keySet()) {
// if(str.equals("coordinates")) {
//// jsonObject.get(str);
// System.out.println(stuId+"----"+jsonObject.get(str));
// }
// }
//
// }
// System.out.println(readJsonFile("D:\\code/lsz.geojson"));
}
public
static
String
readJsonFile
(
String
fileName
)
{
String
jsonStr
=
""
;
try
{
File
jsonFile
=
new
File
(
fileName
);
FileReader
fileReader
=
new
FileReader
(
jsonFile
);
Reader
reader
=
new
InputStreamReader
(
new
FileInputStream
(
jsonFile
),
"utf-8"
);
int
ch
=
0
;
StringBuffer
sb
=
new
StringBuffer
();
while
((
ch
=
reader
.
read
())
!=
-
1
)
{
sb
.
append
((
char
)
ch
);
}
fileReader
.
close
();
reader
.
close
();
jsonStr
=
sb
.
toString
();
return
jsonStr
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
return
null
;
}
}
}
\ No newline at end of file
ivccs-vmm-backservice/src/main/java/com/ssi/utils/ToolUtils.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils
;
public
class
ToolUtils
{
/**
* 转换异常信息为字符串
*
* @param exceptionName 异常名称
* @param exceptionMessage 异常信息
* @param elements 堆栈信息
*/
public
static
String
stackTraceToString
(
String
exceptionName
,
String
exceptionMessage
,
StackTraceElement
[]
elements
)
{
StringBuffer
strbuff
=
new
StringBuffer
();
for
(
StackTraceElement
stet
:
elements
)
{
strbuff
.
append
(
stet
+
"\n"
);
}
String
message
=
exceptionName
+
":"
+
exceptionMessage
+
"\n\t"
+
strbuff
.
toString
();
return
message
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/VehicleDataUtil.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils
;
import
com.ssi.constant.enums.TaskLocationTypeEnum
;
import
com.ssi.constant.enums.TaskTypeEnum
;
import
com.ssi.entity.vo.VehicleVo
;
import
com.ssi.entity.vo.VmsTosOrdersVo
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
java.util.Map
;
@Component
@Slf4j
public
class
VehicleDataUtil
{
@Value
(
"${client.onlineTime}"
)
private
Long
onlineTime
;
public
Integer
checkOnline
(
Integer
state
,
Long
collectime
)
{
/** 检查终端状态*/
boolean
dataOnline
=
(
collectime
!=
null
&&
System
.
currentTimeMillis
()
-
collectime
<
onlineTime
);
boolean
isOnline
=
dataOnline
&&
state
==
1
;
return
isOnline
?
1
:
0
;
}
public
VehicleVo
.
vehicleTemp
toVehicleTemp
(
Map
<
String
,
Object
>
realDataMap
)
{
VehicleVo
.
vehicleTemp
vehicleTemp
=
new
VehicleVo
().
new
vehicleTemp
();
vehicleTemp
.
setVehicleNum
(
realDataMap
.
get
(
"vehicleNum"
)
==
null
?
null
:
(
String
)
realDataMap
.
get
(
"vehicleNum"
));
vehicleTemp
.
setVehicleType
(
realDataMap
.
get
(
"vehicleType"
)
==
null
?
0
:
(
Integer
)
realDataMap
.
get
(
"vehicleType"
));
vehicleTemp
.
setVin
(
realDataMap
.
get
(
"vin"
)
==
null
?
null
:
(
String
)
realDataMap
.
get
(
"vin"
));
vehicleTemp
.
setSoc
((
Integer
)
realDataMap
.
get
(
"soc"
));
vehicleTemp
.
setFaultStatus
(
realDataMap
.
get
(
"equipStatus"
)
==
null
?
1
:
(
Integer
)
realDataMap
.
get
(
"equipStatus"
)
==
1
?
1
:
0
);
if
(
vehicleTemp
.
getFaultStatus
()
==
1
)
{
vehicleTemp
.
setFaultLevel
(
"一级故障"
);
}
vehicleTemp
.
setWorkStatus
(
realDataMap
.
get
(
"workStatus"
)
==
null
?
0
:
(
Integer
)
realDataMap
.
get
(
"workStatus"
));
Integer
onlineStatus
=
checkOnline
(
realDataMap
.
get
(
"state"
)
==
null
?
0
:
(
Integer
)
realDataMap
.
get
(
"state"
)
,
(
Long
)
realDataMap
.
get
(
"collectTime"
));
vehicleTemp
.
setOnlineStatus
(
onlineStatus
);
vehicleTemp
.
setWaitOvertimeStatus
(
realDataMap
.
get
(
"waitOvertimeStatus"
)
==
null
?
0
:
(
Integer
)
realDataMap
.
get
(
"waitOvertimeStatus"
));
vehicleTemp
.
setLowEnergyStatus
(
realDataMap
.
get
(
"lowEnergy"
)
==
null
||
realDataMap
.
get
(
"soc"
)
==
null
?
0
:
(
Integer
)
realDataMap
.
get
(
"soc"
)
<
(
Integer
)
realDataMap
.
get
(
"lowEnergy"
)
?
1
:
0
);
if
(
onlineStatus
==
1
)
{
VmsTosOrdersVo
vmsTosOrders
=
(
VmsTosOrdersVo
)
realDataMap
.
get
(
"orderData"
);
if
(
vmsTosOrders
!=
null
)
{
//加个判断subTaskType 0:缓冲区,1 2:扭锁站 其他不改变
String
description
=
""
;
if
(
vmsTosOrders
.
getSubTaskType
()==
null
){
description
=
generateOrderDescription
(
vmsTosOrders
);
}
else
{
if
(
vmsTosOrders
.
getSubTaskType
()
==
0
){
description
=
"去缓冲区"
;
}
else
if
(
vmsTosOrders
.
getSubTaskType
()
==
1
||
vmsTosOrders
.
getSubTaskType
()==
2
){
description
=
"去扭锁站"
;
}
else
{
description
=
generateOrderDescription
(
vmsTosOrders
);
}
}
vmsTosOrders
.
setOrderDescription
(
description
);
vehicleTemp
.
setOrderData
(
vmsTosOrders
);
}
}
vehicleTemp
.
setEmergencyType
(
realDataMap
.
get
(
"emergencyType"
)
==
null
?
2
:
(
Integer
)
realDataMap
.
get
(
"emergencyType"
));
vehicleTemp
.
setThreeConfirmStatus
((
Map
)
realDataMap
.
get
(
"threeConfirmStatus"
));
return
vehicleTemp
;
}
public
String
generateOrderDescription
(
VmsTosOrdersVo
vmsTosOrders
)
{
if
(
vmsTosOrders
!=
null
)
{
try
{
Integer
taskLocationType
=
vmsTosOrders
.
getTaskLocationType
();
String
containerId
=
vmsTosOrders
.
getContainerId
();
Integer
taskType
=
vmsTosOrders
.
getTaskType
();
String
vehicleLocation
=
vmsTosOrders
.
getVehicleLocation
();
return
generateOrderDescription
(
taskLocationType
,
taskType
,
vehicleLocation
,
containerId
);
}
catch
(
Exception
e
)
{
log
.
error
(
"生成任务信息描述异常"
,
e
);
}
}
return
null
;
}
public
String
generateOrderDescription
(
Map
taskOrderInfo
)
{
if
(
taskOrderInfo
!=
null
)
{
try
{
Integer
taskLocationType
=
(
Integer
)
taskOrderInfo
.
get
(
"taskLocationType"
);
Integer
taskType
=
(
Integer
)
taskOrderInfo
.
get
(
"taskType"
);
String
vehicleLocation
=
(
String
)
taskOrderInfo
.
get
(
"vehicleLocation"
);
String
containerId
=
(
String
)
taskOrderInfo
.
get
(
"containerId"
);
return
generateOrderDescription
(
taskLocationType
,
taskType
,
vehicleLocation
,
containerId
);
}
catch
(
Exception
e
)
{
log
.
error
(
"生成任务信息描述异常"
,
e
);
}
}
return
null
;
}
public
String
generateTaskLocationDescription
(
Map
taskOrderInfo
)
{
if
(
taskOrderInfo
!=
null
)
{
try
{
Integer
taskLocationType
=
(
Integer
)
taskOrderInfo
.
get
(
"taskLocationType"
);
String
vehicleLocation
=
(
String
)
taskOrderInfo
.
get
(
"vehicleLocation"
);
return
generateTaskLocationDescription
(
taskLocationType
,
vehicleLocation
);
}
catch
(
Exception
e
)
{
log
.
error
(
"生成任务地点描述异常"
,
e
);
}
}
return
null
;
}
/**
* taskLocationType:任务类型, 1-去堆场(装箱或卸箱);2-去停车点(上扭锁,解扭锁,停车);3-去固定停车区; 4-去临时停车区;5-去桥吊(装箱或卸箱);6-去充电
* taskType:作业类型,1:装箱,2:卸箱,3:充电,4:上扭锁,5:解扭锁,6:停车,7掉头
*/
private
String
generateOrderDescription
(
Integer
taskLocationType
,
Integer
taskType
,
String
vehicleLocation
,
String
containerId
)
{
TaskLocationTypeEnum
taskLocationTypeEnum
=
TaskLocationTypeEnum
.
find
(
taskLocationType
);
TaskTypeEnum
taskTypeEnum
=
TaskTypeEnum
.
find
(
taskType
);
String
str1
=
null
;
String
str2
=
null
;
if
(
StringUtils
.
isNotBlank
(
vehicleLocation
)
&&
vehicleLocation
.
length
()
>=
6
)
{
str1
=
vehicleLocation
.
substring
(
0
,
3
);
str2
=
vehicleLocation
.
substring
(
3
,
6
);
}
StringBuilder
sb
=
new
StringBuilder
();
switch
(
taskLocationType
)
{
case
1
:
sb
.
append
(
"去"
+
str1
+
"堆场"
+
str2
+
"贝位"
);
// .append("将集装箱").append(containerId)
// .append(taskTypeEnum.getDescription());
break
;
case
2
:
// sb.append(taskLocationTypeEnum.getDescription())
// .append(taskTypeEnum.getDescription());
// break;
case
3
:
case
4
:
case
6
:
sb
.
append
(
taskLocationTypeEnum
.
getDescription
());
break
;
case
5
:
sb
.
append
(
"去"
+
str1
+
"桥吊"
+
str2
+
"车道"
);
// .append("将集装箱").append(containerId)
// .append(taskTypeEnum.getDescription());
break
;
}
return
sb
.
toString
();
}
public
String
generateTaskLocationDescription
(
Integer
taskLocationType
,
String
vehicleLocation
)
{
TaskLocationTypeEnum
taskLocationTypeEnum
=
TaskLocationTypeEnum
.
find
(
taskLocationType
);
String
str1
=
null
;
String
str2
=
null
;
if
(
StringUtils
.
isNotBlank
(
vehicleLocation
))
{
str1
=
vehicleLocation
.
substring
(
0
,
3
);
str2
=
vehicleLocation
.
substring
(
3
,
6
);
}
StringBuilder
sb
=
new
StringBuilder
();
switch
(
taskLocationType
)
{
case
1
:
sb
.
append
(
str1
+
"堆场"
+
str2
+
"贝位"
);
break
;
case
2
:
case
3
:
case
4
:
case
6
:
sb
.
append
(
taskLocationTypeEnum
.
getDescription
());
break
;
case
5
:
sb
.
append
(
str1
+
"桥吊"
+
str2
+
"车道"
);
break
;
}
return
sb
.
toString
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/VehicleUtil.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils
;
import
com.ssi.constant.VehicleConstant
;
public
class
VehicleUtil
{
public
static
boolean
isTaskOver
(
int
status
)
{
if
(
status
==
VehicleConstant
.
FINISH_CHARGING
||
status
==
VehicleConstant
.
FINISH_PACKING
||
status
==
VehicleConstant
.
FINISH_CONFIRM
)
{
return
true
;
}
return
false
;
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/Coordtransform.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
com.ssi.utils.GpsUtil
;
/**
*
* -----------------------------------------------------------------------------------------
* 坐标系 |解释 |使用地图
* -----------------------------------------------------------------------------------------
* WGS84 |地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取 |GPS/谷歌地图卫星
* |的经纬度为WGS84地理坐标系,最基础的坐标,谷歌地图在非中国地区使用的坐标系 |
* -----------------------------------------------------------------------------------------
* GCJ02 |火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。 |腾讯(搜搜)地图,
* |并要求在中国使用的地图产品使用的都必须是加密后的坐标, |阿里云地图,高德地图,
* |而这套WGS84加密后的坐标就是gcj02。 |谷歌国内地图
* -----------------------------------------------------------------------------------------
* BD09 |百度坐标系,百度在GCJ02的基础上进行了二次加密, |百度地图
* |官方解释是为了进一步保护用户隐私 |
* -----------------------------------------------------------------------------------------
* 小众坐标系 |类似于百度地图,在GCJ02基础上使用自己的加密算法进行二次加密的坐标系 |搜狗地图、图吧地图 等
* -----------------------------------------------------------------------------------------
* 墨卡托坐标 |墨卡托投影以整个世界范围,赤道作为标准纬线,本初子午线作为中央经线,
* |两者交点为坐标原点,向东向北为正,向西向南为负。
* |南北极在地图的正下、上方,而东西方向处于地图的正右、左。
*
* 你可以通过这个工具类将上述坐标系进行互相转换。
*
* 百度地图地图投影采用的依然是Web Mercator投影,地图瓦片的切片规则遵循TMS标准,瓦片坐标原点在经纬度为0的附近,
* 但却做了一定的偏移处理,经测算此偏移量约为(-865,15850),
* 即地图瓦片(0, 0)是从Web Mercator投影坐标系的(-865,15850)点开始的。
*
* 顺便提供百度地图的地图等级从18级到1级
* 18级,1个像素代表1米,17级,1个像素代表2米,16级代表4米,依此类推
* Author: kong
*/
public
class
Coordtransform
{
public
static
double
baiduChange
=
(
Math
.
PI
*
3000.0
)
/
180.0
;
public
static
double
ee
=
0.00669342162296594323
;
//偏心率平方
public
static
double
a
=
6378245.0
;
// # 长半轴
/**
* 长半径a=6378137 米
*/
public
static
double
EARTH_RADIUS
=
6378137
;
/**
* 短半径b=6356752.3142
*/
public
static
double
b
=
6356752.3142
;
/**
* 扁率f=1/298.2572236
*/
public
static
double
f
=
1
/
298.2572236
;
/**
* 已知一点经纬度,方位角,距离,求另一点经纬度
* 通过三角函数求终点坐标-球面坐标系
* </summary>
* <param name="angle">角度</param>
*<param name="startPoint">起点</param>
* <param name="distance">距离(米)</param>
* <returns>终点坐标</returns>
*/
public
static
double
[]
getEndPointByTrigonometric
(
double
angle
,
double
[]
startPoint
,
double
distance
)
{
double
lon
=
startPoint
[
0
];
double
lat
=
startPoint
[
1
];
double
alpha1
=
rad
(
angle
);
double
sinAlpha1
=
Math
.
sin
(
alpha1
);
double
cosAlpha1
=
Math
.
cos
(
alpha1
);
double
tanU1
=
(
1
-
f
)
*
Math
.
tan
(
rad
(
lat
));
double
cosU1
=
1
/
Math
.
sqrt
((
1
+
tanU1
*
tanU1
));
double
sinU1
=
tanU1
*
cosU1
;
double
sigma1
=
Math
.
atan2
(
tanU1
,
cosAlpha1
);
double
sinAlpha
=
cosU1
*
sinAlpha1
;
double
cosSqAlpha
=
1
-
sinAlpha
*
sinAlpha
;
double
uSq
=
cosSqAlpha
*
(
EARTH_RADIUS
*
EARTH_RADIUS
-
b
*
b
)
/
(
b
*
b
);
double
A
=
1
+
uSq
/
16384
*
(
4096
+
uSq
*
(-
768
+
uSq
*
(
320
-
175
*
uSq
)));
double
B
=
uSq
/
1024
*
(
256
+
uSq
*
(-
128
+
uSq
*
(
74
-
47
*
uSq
)));
double
cos2SigmaM
=
0
;
double
sinSigma
=
0
;
double
cosSigma
=
0
;
double
sigma
=
distance
/
(
b
*
A
),
sigmaP
=
2
*
Math
.
PI
;
while
(
Math
.
abs
(
sigma
-
sigmaP
)
>
1
e
-
12
)
{
cos2SigmaM
=
Math
.
cos
(
2
*
sigma1
+
sigma
);
sinSigma
=
Math
.
sin
(
sigma
);
cosSigma
=
Math
.
cos
(
sigma
);
double
deltaSigma
=
B
*
sinSigma
*
(
cos2SigmaM
+
B
/
4
*
(
cosSigma
*
(-
1
+
2
*
cos2SigmaM
*
cos2SigmaM
)
-
B
/
6
*
cos2SigmaM
*
(-
3
+
4
*
sinSigma
*
sinSigma
)
*
(-
3
+
4
*
cos2SigmaM
*
cos2SigmaM
)));
sigmaP
=
sigma
;
sigma
=
distance
/
(
b
*
A
)
+
deltaSigma
;
}
double
tmp
=
sinU1
*
sinSigma
-
cosU1
*
cosSigma
*
cosAlpha1
;
double
lat2
=
Math
.
atan2
(
sinU1
*
cosSigma
+
cosU1
*
sinSigma
*
cosAlpha1
,
(
1
-
f
)
*
Math
.
sqrt
(
sinAlpha
*
sinAlpha
+
tmp
*
tmp
));
double
lambda
=
Math
.
atan2
(
sinSigma
*
sinAlpha1
,
cosU1
*
cosSigma
-
sinU1
*
sinSigma
*
cosAlpha1
);
double
C
=
f
/
16
*
cosSqAlpha
*
(
4
+
f
*
(
4
-
3
*
cosSqAlpha
));
double
L
=
lambda
-
(
1
-
C
)
*
f
*
sinAlpha
*
(
sigma
+
C
*
sinSigma
*
(
cos2SigmaM
+
C
*
cosSigma
*
(-
1
+
2
*
cos2SigmaM
*
cos2SigmaM
)));
double
[]
endPoint
=
new
double
[
2
];
endPoint
[
0
]=
lon
+
deg
(
L
);
endPoint
[
1
]=
deg
(
lat2
);
return
endPoint
;
}
/**
* 度换成弧度
* @param d 度
* @return 弧度
*/
public
static
double
rad
(
double
d
)
{
return
d
*
Math
.
PI
/
180.0
;
}
/**
* 弧度换成度
* @param x 弧度
* @return 度
*/
public
static
double
deg
(
double
x
)
{
return
x
*
180
/
Math
.
PI
;
}
/**
* 百度坐标系(BD-09)转火星坐标系(GCJ-02)
* 百度——>谷歌、高德
*
* @param lng_BD 百度坐标经度
* @param lat_BD 百度坐标纬度
* @return 转换后的坐标列表形式
*/
public
static
double
[]
BD09toGCJ02
(
double
lng_BD
,
double
lat_BD
)
{
double
[]
GCJ02
=
new
double
[
2
];
double
x
=
lng_BD
-
0.0065
;
double
y
=
lat_BD
-
0.006
;
double
z
=
Math
.
sqrt
(
x
*
x
+
y
*
y
)
-
0.00002
*
Math
.
sin
(
y
*
baiduChange
);
double
theta
=
Math
.
atan2
(
y
,
x
)
-
0.000003
*
Math
.
cos
(
x
*
baiduChange
);
double
gg_lng
=
z
*
Math
.
cos
(
theta
);
double
gg_lat
=
z
*
Math
.
sin
(
theta
);
GCJ02
[
0
]
=
gg_lng
;
GCJ02
[
1
]
=
gg_lat
;
return
GCJ02
;
}
/**
* 火星坐标系(GCJ-02)转百度坐标系(BD-09)
* 谷歌、高德——>百度
*
* @param lng_GCJ
* @param lat_GCJ
* @return 转换后的坐标列表形式
*/
public
static
double
[]
GCJ02toBD09
(
double
lng_GCJ
,
double
lat_GCJ
)
{
double
[]
BD09
=
new
double
[
2
];
// """
// 实现GCJ02向BD09坐标系的转换
// :param lng: GCJ02坐标系下的经度
// :param lat: GCJ02坐标系下的纬度
// :return: 转换后的BD09下经纬度
// """
double
z
=
Math
.
sqrt
(
lng_GCJ
*
lng_GCJ
+
lat_GCJ
*
lat_GCJ
)
+
0.00002
*
Math
.
sin
(
lat_GCJ
*
Math
.
PI
);
double
theta
=
Math
.
atan2
(
lat_GCJ
,
lng_GCJ
)
+
0.000003
*
Math
.
cos
(
lng_GCJ
*
Math
.
PI
);
double
bd_lng
=
z
*
Math
.
cos
(
theta
)
+
0.0065
;
double
bd_lat
=
z
*
Math
.
sin
(
theta
)
+
0.006
;
BD09
[
0
]
=
bd_lng
;
BD09
[
1
]
=
bd_lat
;
return
BD09
;
}
/**
* GCJ02(火星坐标系)转GPS84
*
* @param lng_gcj 火星坐标系的经度
* @param lat_gcj 火星坐标系纬度
* @return 转换后的坐标列表形式
*/
public
static
double
[]
GCJ02toWGS84
(
double
lng_gcj
,
double
lat_gcj
)
{
double
[]
wgs84
=
new
double
[
2
];
if
(
outOfChina
(
lng_gcj
,
lat_gcj
))
{
return
new
double
[]{
lng_gcj
,
lat_gcj
};
}
// if out_of_china(lng, lat):
// return [lng, lat]
double
dlat
=
transformlat
(
lng_gcj
-
105.0
,
lat_gcj
-
35.0
);
double
dlng
=
transformlng
(
lng_gcj
-
105.0
,
lat_gcj
-
35.0
);
double
radlat
=
lat_gcj
/
180.0
*
Math
.
PI
;
double
magic
=
Math
.
sin
(
radlat
);
magic
=
1
-
ee
*
magic
*
magic
;
double
sqrtmagic
=
Math
.
sqrt
(
magic
);
dlat
=
(
dlat
*
180.0
)
/
((
a
*
(
1
-
ee
))
/
(
magic
*
sqrtmagic
)
*
Math
.
PI
);
dlng
=
(
dlng
*
180.0
)
/
(
a
/
sqrtmagic
*
Math
.
cos
(
radlat
)
*
Math
.
PI
);
double
mglat
=
lat_gcj
+
dlat
;
double
mglng
=
lng_gcj
+
dlng
;
return
new
double
[]{
lng_gcj
*
2
-
mglng
,
lat_gcj
*
2
-
mglat
};
}
/**
* GPS84转GCJ02(火星坐标系)
*
* @param lng_wgs WGS84坐标系的经度
* @param lat_wgs WGS84坐标系纬度
* @return 转换后的GCJ02下经纬度
*/
public
static
double
[]
WGS84toGCJ02
(
double
lng_wgs
,
double
lat_wgs
)
{
if
(
outOfChina
(
lng_wgs
,
lat_wgs
))
{
return
new
double
[]{
lng_wgs
,
lat_wgs
};
}
double
[]
GCJ02
=
new
double
[
2
];
double
dlat
=
transformlat
(
lng_wgs
-
105.0
,
lat_wgs
-
35.0
);
double
dlng
=
transformlng
(
lng_wgs
-
105.0
,
lat_wgs
-
35.0
);
double
radlat
=
lat_wgs
/
180.0
*
Math
.
PI
;
double
magic
=
Math
.
sin
(
radlat
);
magic
=
1
-
ee
*
magic
*
magic
;
double
sqrtmagic
=
Math
.
sqrt
(
magic
);
dlat
=
(
dlat
*
180.0
)
/
((
a
*
(
1
-
ee
))
/
(
magic
*
sqrtmagic
)
*
Math
.
PI
);
dlng
=
(
dlng
*
180.0
)
/
(
a
/
sqrtmagic
*
Math
.
cos
(
radlat
)
*
Math
.
PI
);
double
gcj_lng
=
lat_wgs
+
dlat
;
double
gcj_lat
=
lng_wgs
+
dlng
;
GCJ02
[
1
]
=
gcj_lng
;
GCJ02
[
0
]
=
gcj_lat
;
return
GCJ02
;
}
/**
* GPS84 转 墨卡托坐标
*
* @param lng GPS84的经度
* @param lat GPS84纬度
* @return 转换后的坐标列表形式
*/
public
static
double
[]
WGS84toMercator
(
double
lng
,
double
lat
)
{
double
x
=
lng
*
20037508.342789
/
180
;
double
y
=
Math
.
log
(
Math
.
tan
((
90
+
lat
)
*
Math
.
PI
/
360
))
/
(
Math
.
PI
/
180
);
y
=
y
*
20037508.342789
/
180
;
return
new
double
[]{
x
,
y
};
}
/**
* 百度坐标系转成通用墨卡托坐标
*
* @param lng
* @param lat
* @return
*/
public
static
double
[]
bdtoMercator
(
double
lng
,
double
lat
)
{
double
[]
gcj02
=
BD09toGCJ02
(
lng
,
lat
);
double
[]
wgs84
=
GCJ02toWGS84
(
gcj02
[
0
],
gcj02
[
1
]);
double
[]
mercator
=
WGS84toMercator
(
wgs84
[
0
],
wgs84
[
1
]);
return
mercator
;
}
private
static
double
transformlat
(
double
lng
,
double
lat
)
{
double
ret
=
-
100.0
+
2.0
*
lng
+
3.0
*
lat
+
0.2
*
lat
*
lat
+
0.1
*
lng
*
lat
+
0.2
*
Math
.
sqrt
(
Math
.
abs
(
lng
));
ret
+=
(
20.0
*
Math
.
sin
(
6.0
*
lng
*
Math
.
PI
)
+
20.0
*
Math
.
sin
(
2.0
*
lng
*
Math
.
PI
))
*
2.0
/
3.0
;
ret
+=
(
20.0
*
Math
.
sin
(
lat
*
Math
.
PI
)
+
40.0
*
Math
.
sin
(
lat
/
3.0
*
Math
.
PI
))
*
2.0
/
3.0
;
ret
+=
(
160.0
*
Math
.
sin
(
lat
/
12.0
*
Math
.
PI
)
+
320
*
Math
.
sin
(
lat
*
Math
.
PI
/
30.0
))
*
2.0
/
3.0
;
return
ret
;
}
private
static
double
transformlng
(
double
lng
,
double
lat
)
{
double
ret
=
300.0
+
lng
+
2.0
*
lat
+
0.1
*
lng
*
lng
+
0.1
*
lng
*
lat
+
0.1
*
Math
.
sqrt
(
Math
.
abs
(
lng
));
ret
+=
(
20.0
*
Math
.
sin
(
6.0
*
lng
*
Math
.
PI
)
+
20.0
*
Math
.
sin
(
2.0
*
lng
*
Math
.
PI
))
*
2.0
/
3.0
;
ret
+=
(
20.0
*
Math
.
sin
(
lng
*
Math
.
PI
)
+
40.0
*
Math
.
sin
(
lng
/
3.0
*
Math
.
PI
))
*
2.0
/
3.0
;
ret
+=
(
150.0
*
Math
.
sin
(
lng
/
12.0
*
Math
.
PI
)
+
300.0
*
Math
.
sin
(
lng
/
30.0
*
Math
.
PI
))
*
2.0
/
3.0
;
return
ret
;
}
/**
* 判断是否在国内,不在国内不做偏移
*
* @param lng
* @param lat
* @return
*/
public
static
boolean
outOfChina
(
double
lng
,
double
lat
)
{
return
!(
lng
>
73.66
&&
lng
<
135.05
&&
lat
>
3.86
&&
lat
<
53.55
);
}
public
static
boolean
outOfChinaByMercator
(
double
x
,
double
y
)
{
return
!(
x
>
8199793.7
&&
x
<
1.5E7
&&
y
>
430018.7
&&
y
<
7085388.2
);
}
public
static
void
main
(
String
[]
args
)
{
double
distance
=
GpsUtil
.
getDistance
(
24.455743
,
117.967768
,
24.455735
,
117.967811
);
System
.
out
.
println
(
distance
*
1000
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/GridFreeEvent.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
java.io.Serializable
;
public
class
GridFreeEvent
implements
Serializable
{
private
String
vid
;
private
MercatorGrid
grid
;
public
GridFreeEvent
(
String
vid
,
MercatorGrid
grid
)
{
this
.
vid
=
vid
;
this
.
grid
=
grid
;
}
public
String
getVid
()
{
return
vid
;
}
public
MercatorGrid
getGrid
()
{
return
grid
;
}
@Override
public
String
toString
()
{
final
StringBuffer
sb
=
new
StringBuffer
(
"GridFreeEvent{"
);
sb
.
append
(
"vid='"
).
append
(
vid
).
append
(
'\''
);
sb
.
append
(
"grid='"
).
append
(
grid
).
append
(
'\''
);
sb
.
append
(
'}'
);
return
sb
.
toString
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/MercatorGrid.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.Serializable
;
import
java.util.concurrent.ConcurrentLinkedQueue
;
/**
* 网格对象:
* 包含网格标识点MercatorPoint,订阅用户队列、当前占用用户
* 后续考虑采用触发器的形式 在让给下一个用户时直接告知下一个用户可以开始操作了
*
*/
public
class
MercatorGrid
implements
Serializable
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
private
final
MercatorPoint
point
;
//用户占用等待队列
private
final
ConcurrentLinkedQueue
<
String
>
userWaitQueue
;
//当前用户
private
volatile
String
currentUser
;
public
MercatorGrid
(
MercatorPoint
point
){
assert
point
!=
null
:
"网格标识点不能为空!"
;
this
.
point
=
point
;
this
.
userWaitQueue
=
new
ConcurrentLinkedQueue
<>();
}
/**
* 预定此网格
* @param user id
* @return
*/
public
boolean
reserve
(
String
user
){
String
currentUser
=
getCurrentUser
();
if
(!
user
.
equals
(
currentUser
))
{
boolean
offer
=
this
.
userWaitQueue
.
offer
(
user
);
//当前用户为null时,设置为此用户
getCurrentUser
();
logger
.
debug
(
String
.
format
(
"%s 预定占用网格 %s 成功,当前等待用户数:%s"
,
user
,
point
,
userWaitQueue
.
size
()));
return
offer
;
}
return
true
;
}
public
boolean
cancelReserve
(
String
user
){
this
.
userWaitQueue
.
remove
(
user
);
logger
.
debug
(
String
.
format
(
"取消%s 预定占用网格 %s 成功,当前等待用户数:%s"
,
user
,
point
,
userWaitQueue
.
size
()));
return
false
;
}
/**
* 获取当前用户
* @return
*/
public
String
getCurrentUser
(){
if
(
this
.
currentUser
==
null
){
synchronized
(
MercatorGrid
.
class
)
{
if
(
this
.
currentUser
==
null
)
{
this
.
currentUser
=
this
.
userWaitQueue
.
poll
();
}
}
}
return
this
.
currentUser
;
}
/**
* 释放当前用户, 让给下一个用户
* @param currentUser
* @return
*/
public
boolean
freeToNext
(
String
currentUser
){
if
(
currentUser
.
equals
(
this
.
currentUser
)){
synchronized
(
MercatorGrid
.
class
){
if
(
currentUser
.
equals
(
this
.
currentUser
)){
this
.
currentUser
=
this
.
userWaitQueue
.
poll
();
logger
.
debug
(
String
.
format
(
"%s 释放网格 %s 成功,当前用户变更为:%s, 目前等待用户数"
,
currentUser
,
point
,
this
.
currentUser
,
userWaitQueue
.
size
()));
return
true
;
}
}
}
logger
.
error
(
String
.
format
(
"%s 非网格 %s 当前用户 %s,无法释放!"
,
currentUser
,
point
,
this
.
currentUser
));
return
false
;
}
public
MercatorPoint
getPoint
()
{
return
this
.
point
.
clone
();
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
return
false
;
MercatorGrid
that
=
(
MercatorGrid
)
o
;
return
point
.
equals
(
that
.
point
);
}
@Override
public
int
hashCode
()
{
return
point
!=
null
?
point
.
hashCode
()
:
0
;
}
@Override
public
String
toString
()
{
final
StringBuffer
sb
=
new
StringBuffer
(
"MercatorGrid{"
);
sb
.
append
(
"point="
).
append
(
point
);
sb
.
append
(
", userWaitQueueSize="
).
append
(
userWaitQueue
.
size
());
sb
.
append
(
", currentUser='"
).
append
(
currentUser
).
append
(
'\''
);
sb
.
append
(
'}'
);
return
sb
.
toString
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/MercatorNet.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.Serializable
;
import
java.util.*
;
/**
* 四个顶点,按指定距离划分格子,生成网
* @author jechedo
* @time 2022/12/1
*/
public
class
MercatorNet
implements
Serializable
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
private
final
MercatorPoint
pointA
;
private
final
MercatorPoint
pointB
;
private
final
MercatorPoint
pointC
;
private
final
MercatorPoint
pointD
;
private
final
int
gridDistance
;
private
final
Map
<
MercatorPoint
,
MercatorGrid
>
gridsMap
;
/**
* @param pointA
* @param pointB
* @param pointC
* @param pointD
* @param gridDistance 网格距离, 单位:米
*/
public
MercatorNet
(
MercatorPoint
pointA
,
MercatorPoint
pointB
,
MercatorPoint
pointC
,
MercatorPoint
pointD
,
int
gridDistance
){
assert
gridDistance
>
0
:
"gridDistance 必须为大于0的值。"
;
this
.
pointA
=
pointA
;
this
.
pointB
=
pointB
;
this
.
pointC
=
pointC
;
this
.
pointD
=
pointD
;
this
.
gridDistance
=
gridDistance
;
this
.
gridsMap
=
new
HashMap
<>();
//生成网格
createNet
();
}
/**
* 生成网格
*
*/
private
void
createNet
(){
this
.
gridsMap
.
putAll
(
searchGrids
(
this
.
pointA
,
this
.
pointB
,
this
.
pointC
,
this
.
pointD
));
}
private
Map
<
MercatorPoint
,
MercatorGrid
>
searchGrids
(
MercatorPoint
pointA
,
MercatorPoint
pointB
,
MercatorPoint
pointC
,
MercatorPoint
pointD
){
//根据四个顶点坐标,求网格x与y的最大最小值
List
<
Double
>
xs
=
new
ArrayList
<>();
xs
.
add
(
pointA
.
getX
());
xs
.
add
(
pointB
.
getX
());
xs
.
add
(
pointC
.
getX
());
xs
.
add
(
pointD
.
getX
());
//向上取整, 获取能整除gridDistance 且距离x最大值最近 又大于x最大值的值
double
maxX
=
Math
.
ceil
(
Collections
.
max
(
xs
)
/
gridDistance
)
*
gridDistance
;
//向下取整, 获取能整除gridDistance 且距离x最小值最近 又小于x最小值的值
double
minX
=
Math
.
floor
(
Collections
.
min
(
xs
)
/
gridDistance
)
*
gridDistance
;
List
<
Double
>
ys
=
new
ArrayList
<>();
ys
.
add
(
pointA
.
getY
());
ys
.
add
(
pointB
.
getY
());
ys
.
add
(
pointC
.
getY
());
ys
.
add
(
pointD
.
getY
());
//向上取整, 获取能整除gridDistance 且距离y最大值最近 又大于y最大值的值
double
maxY
=
Math
.
ceil
(
Collections
.
max
(
ys
)
/
gridDistance
)
*
gridDistance
;
//向下取整, 获取能整除gridDistance 且距离y最小值最近 又小于y最小值的值
double
minY
=
Math
.
floor
(
Collections
.
min
(
ys
)
/
gridDistance
)
*
gridDistance
;
return
searchGrids
(
maxX
,
minX
,
maxY
,
minY
);
}
private
Map
<
MercatorPoint
,
MercatorGrid
>
searchGrids
(
double
maxX
,
double
minX
,
double
maxY
,
double
minY
){
Map
<
MercatorPoint
,
MercatorGrid
>
gridsMap
=
new
HashMap
<>();
//x方向 网格个数
double
gridXNum
=
(
maxX
-
minX
)
/
this
.
gridDistance
;
//x方向 网格个数
double
gridYNum
=
(
maxY
-
minY
)
/
this
.
gridDistance
;
//生成网格, 取网格左下角的点的坐标作为网格标识
double
x
;
double
y
;
MercatorPoint
point
;
for
(
int
i
=
0
;
i
<
gridXNum
;
i
++)
{
x
=
minX
+
this
.
gridDistance
*
i
;
for
(
int
j
=
0
;
j
<
gridYNum
;
j
++)
{
y
=
minY
+
this
.
gridDistance
*
j
;
point
=
new
MercatorPoint
(
x
,
y
);
//设置网格状态
gridsMap
.
put
(
point
,
getMercatorGrid
(
point
));
}
}
return
gridsMap
;
}
public
int
getNetGridSize
(){
return
this
.
gridsMap
.
size
();
}
public
Collection
<
MercatorGrid
>
getChildGrids
(
MercatorPoint
pointA
,
MercatorPoint
pointB
,
MercatorPoint
pointC
,
MercatorPoint
pointD
){
return
searchGrids
(
pointA
,
pointB
,
pointC
,
pointD
).
values
();
}
public
Collection
<
MercatorGrid
>
getChildGrids
(
double
maxX
,
double
minX
,
double
maxY
,
double
minY
){
maxX
=
Math
.
ceil
(
maxX
/
gridDistance
)
*
gridDistance
;
minX
=
Math
.
floor
(
minX
/
gridDistance
)
*
gridDistance
;
maxY
=
Math
.
ceil
(
maxY
/
gridDistance
)
*
gridDistance
;
minY
=
Math
.
floor
(
minY
/
gridDistance
)
*
gridDistance
;
return
searchGrids
(
maxX
,
minX
,
maxY
,
minY
).
values
();
}
public
MercatorGrid
getMercatorGrid
(
MercatorPoint
point
){
return
this
.
gridsMap
.
getOrDefault
(
point
,
new
MercatorGrid
(
point
));
}
public
static
void
main
(
String
[]
args
)
{
double
[]
a
=
Coordtransform
.
WGS84toMercator
(
117.964504
,
24.454129
);
MercatorPoint
pointA
=
new
MercatorPoint
(
a
[
0
],
a
[
1
]);
double
[]
b
=
Coordtransform
.
WGS84toMercator
(
117.98918
,
24.449011
);
MercatorPoint
pointB
=
new
MercatorPoint
(
b
[
0
],
b
[
1
]);
double
[]
c
=
Coordtransform
.
WGS84toMercator
(
117.990382
,
24.453953
);
MercatorPoint
pointC
=
new
MercatorPoint
(
c
[
0
],
c
[
1
]);
double
[]
d
=
Coordtransform
.
WGS84toMercator
(
117.965813
,
24.458992
);
MercatorPoint
pointD
=
new
MercatorPoint
(
d
[
0
],
d
[
1
]);
MercatorNet
mercatorNet
=
new
MercatorNet
(
pointA
,
pointB
,
pointC
,
pointD
,
5
);
Collection
<
MercatorGrid
>
grids
=
mercatorNet
.
getChildGrids
(
1.3132610797736611E7
,
1.3132030377911612E7
,
2809111.607682695
,
2808734.2196206213
);
grids
.
forEach
((
grid
->
{
grid
.
reserve
(
"912"
);
System
.
out
.
println
(
mercatorNet
.
getMercatorGrid
(
grid
.
getPoint
())
+
" -- "
+
grid
);
}));
System
.
out
.
println
(
mercatorNet
.
getNetGridSize
()
+
" -- "
+
grids
.
size
());
/* System.out.println( " ---" );
double[] aa = Coordtransform.WGS84toMercator(117.967487, 24.456316);
MercatorPoint pointAA = new MercatorPoint(aa[0], aa[1]);
System.out.println(pointAA);
double[] bb = Coordtransform.WGS84toMercator(117.97225, 24.455418);
MercatorPoint pointBB = new MercatorPoint(bb[0], bb[1]);
System.out.println(pointBB);
double[] cc = Coordtransform.WGS84toMercator(117.971735, 24.45323);
MercatorPoint pointCC = new MercatorPoint(cc[0], cc[1]);
System.out.println(pointCC);
double[] dd = Coordtransform.WGS84toMercator(117.967036, 24.454148);
MercatorPoint pointDD = new MercatorPoint(dd[0], dd[1]);
System.out.println(pointDD);*/
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/MercatorPoint.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
java.io.Serializable
;
/**
* 网格标识点对象:
* x,y 为 墨卡托坐标
*/
public
class
MercatorPoint
implements
Serializable
{
private
double
x
;
private
double
y
;
public
MercatorPoint
(
double
x
,
double
y
){
assert
Coordtransform
.
outOfChinaByMercator
(
x
,
y
):
"坐标点位必须在中国国内。"
;
this
.
x
=
x
;
this
.
y
=
y
;
}
public
double
getX
()
{
return
x
;
}
public
double
getY
()
{
return
y
;
}
public
MercatorPoint
clone
(){
return
new
MercatorPoint
(
x
,
y
);
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
return
false
;
MercatorPoint
that
=
(
MercatorPoint
)
o
;
if
(
Double
.
compare
(
that
.
x
,
x
)
!=
0
)
return
false
;
return
Double
.
compare
(
that
.
y
,
y
)
==
0
;
}
@Override
public
int
hashCode
()
{
int
result
;
long
temp
;
temp
=
Double
.
doubleToLongBits
(
x
);
result
=
(
int
)
(
temp
^
(
temp
>>>
32
));
temp
=
Double
.
doubleToLongBits
(
y
);
result
=
31
*
result
+
(
int
)
(
temp
^
(
temp
>>>
32
));
return
result
;
}
@Override
public
String
toString
()
{
final
StringBuffer
sb
=
new
StringBuffer
(
"["
);
sb
.
append
(
"x="
).
append
(
x
);
sb
.
append
(
", y="
).
append
(
y
);
sb
.
append
(
']'
);
return
sb
.
toString
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/MercatorVehicle.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
com.google.common.eventbus.EventBus
;
import
com.google.common.eventbus.Subscribe
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.Serializable
;
import
java.util.*
;
/**
* 车辆数据,即网格用户
*/
public
class
MercatorVehicle
implements
Serializable
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
private
final
String
vid
;
private
final
EventBus
eventBus
;
private
Set
<
MercatorGrid
>
grids
=
new
HashSet
<>();
//车辆实时数据
private
MercatorPoint
point
;
private
List
<
MercatorGrid
>
waitGrids
=
new
ArrayList
<>();
private
Integer
versionNo
;
private
long
timeStamp
;
private
double
speed
;
private
boolean
isActive
=
false
;
public
MercatorVehicle
(
EventBus
eventBus
,
String
vid
,
Collection
<
MercatorGrid
>
grids
,
MercatorPoint
point
,
double
speed
,
long
timeStamp
){
this
.
vid
=
vid
;
this
.
eventBus
=
eventBus
;
update
(
grids
,
point
,
speed
,
timeStamp
);
}
public
int
waitGridSize
(){
return
this
.
waitGrids
.
size
();
}
public
boolean
update
(
Collection
<
MercatorGrid
>
grids
,
MercatorPoint
point
,
double
speed
,
long
timeStamp
){
int
waitGridSize
=
waitGridSize
();
//无等待 则可执行更新
if
(
waitGridSize
>
0
){
freeAllWaitGrids
();
}
Iterator
<
MercatorGrid
>
iterator
=
this
.
grids
.
iterator
();
MercatorGrid
next
;
while
(
iterator
.
hasNext
()){
next
=
iterator
.
next
();
if
(!
grids
.
contains
(
next
)){
//注销占用,让位给下一约定车辆, 并移除
if
(
next
.
freeToNext
(
this
.
vid
)){
String
currentUser
=
next
.
getCurrentUser
();
if
(
currentUser
!=
null
)
{
//通知对应车辆
this
.
eventBus
.
post
(
new
GridFreeEvent
(
this
.
vid
,
next
));
}
}
iterator
.
remove
();
}
}
StringBuilder
sb
=
new
StringBuilder
();
grids
.
forEach
(
grid
->
{
if
(
this
.
grids
.
add
(
grid
)){
//添加成功,则为新占用网格
grid
.
reserve
(
vid
);
String
currentUser
=
grid
.
getCurrentUser
();
//检查网格当前用户是否为本车, 不是本车则将网格记录到等待队列
if
(!
this
.
vid
.
equals
(
currentUser
)){
sb
.
append
(
currentUser
).
append
(
" "
);
this
.
waitGrids
.
add
(
grid
);
// this.eventBus.post(new GridFreeEvent(currentUser, grid));
}
}
});
this
.
point
=
point
;
this
.
speed
=
speed
;
this
.
timeStamp
=
timeStamp
;
logger
.
info
(
String
.
format
(
"车辆%s更新网格集合成功,占用网格数:%s, 等待网格数:%s, speed:%s, timeStamp: %s,等待网格占有者:[%s]."
,
this
.
vid
,
this
.
grids
.
size
(),
waitGridSize
(),
speed
,
timeStamp
,
sb
));
return
true
;
}
public
void
freeWaitGrid
(
String
frontVid
,
MercatorGrid
grid
){
this
.
waitGrids
.
remove
(
grid
);
if
(!
this
.
grids
.
contains
(
grid
))
grid
.
freeToNext
(
this
.
vid
);
if
(
waitGridSize
()==
0
){
this
.
isActive
=
true
;
}
logger
.
info
(
String
.
format
(
"车辆%s 释放网格%s,当前车辆%s占用,移出等待集合, 当前等待网格数:%s"
,
frontVid
,
grid
,
this
.
vid
,
waitGridSize
()));
}
public
void
freeOwnedGrids
(){
this
.
grids
.
forEach
((
grid
)->{
if
(!
this
.
waitGrids
.
contains
(
grid
)){
grid
.
freeToNext
(
vid
);
}
});
grids
.
clear
();
}
public
void
freeAllWaitGrids
(){
this
.
waitGrids
.
forEach
((
grid
)->{
if
(
vid
.
equalsIgnoreCase
(
grid
.
getCurrentUser
())){
grid
.
freeToNext
(
vid
);
}
else
{
grid
.
cancelReserve
(
vid
);
}
});
this
.
waitGrids
.
clear
();
}
public
void
freeAll
(){
Iterator
<
MercatorGrid
>
iterator
=
this
.
grids
.
iterator
();
MercatorGrid
next
;
while
(
iterator
.
hasNext
()){
next
=
iterator
.
next
();
if
(
this
.
waitGrids
.
contains
(
next
)){
next
.
cancelReserve
(
this
.
vid
);
}
else
{
if
(
next
.
freeToNext
(
this
.
vid
)){
String
currentUser
=
next
.
getCurrentUser
();
if
(
currentUser
!=
null
)
{
//通知对应车辆
this
.
eventBus
.
post
(
new
GridFreeEvent
(
this
.
vid
,
next
));
}
}
}
iterator
.
remove
();
}
this
.
waitGrids
.
clear
();
}
public
String
getVid
()
{
return
vid
;
}
public
int
getGridsSize
()
{
return
grids
.
size
();
}
public
Integer
getVersionNo
()
{
return
versionNo
;
}
public
void
setVersionNo
(
Integer
versionNo
)
{
this
.
versionNo
=
versionNo
;
}
public
boolean
isActive
()
{
return
isActive
;
}
public
void
setActive
(
boolean
active
)
{
isActive
=
active
;
}
@Override
public
String
toString
()
{
final
StringBuffer
sb
=
new
StringBuffer
(
"MercatorVehicle{"
);
sb
.
append
(
"vid='"
).
append
(
vid
).
append
(
'\''
);
sb
.
append
(
'}'
);
return
sb
.
toString
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/grid/RealTimeVehicleSchedule.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.grid
;
import
com.google.common.eventbus.EventBus
;
import
com.google.common.eventbus.Subscribe
;
import
com.ssi.entity.dto.Point
;
import
com.ssi.kafka.listener.VehicleRealTimeInfoListener
;
import
com.ssi.utils.FieldUtil
;
import
com.ssi.utils.SpringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.*
;
public
class
RealTimeVehicleSchedule
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
private
volatile
static
RealTimeVehicleSchedule
VEHICLE_SCHEDULE
;
/** 地图角度修正系数,原北向为0,实际东向为0, 逆时针为正*/
private
static
final
double
deltAngle
=
450.0
;
private
final
MercatorNet
mercatorNet
;
private
final
Map
<
String
,
MercatorVehicle
>
vehicleMap
;
private
final
EventBus
eventBus
;
private
RealTimeVehicleSchedule
(){
this
.
mercatorNet
=
createTestNet
();
this
.
vehicleMap
=
new
HashMap
<>();
this
.
eventBus
=
new
EventBus
(
"GridFree"
);
//注册监听到eventBus
this
.
eventBus
.
register
(
this
);
}
private
MercatorNet
createTestNet
(){
//测试用 从高德地图中拾取的厦门远海的四个顶点坐标
double
[]
wgs84
=
Coordtransform
.
GCJ02toWGS84
(
117.964504
,
24.454129
);
double
[]
a
=
Coordtransform
.
WGS84toMercator
(
wgs84
[
0
],
wgs84
[
1
]);
MercatorPoint
pointA
=
new
MercatorPoint
(
a
[
0
],
a
[
1
]);
wgs84
=
Coordtransform
.
GCJ02toWGS84
(
117.98918
,
24.449011
);
double
[]
b
=
Coordtransform
.
WGS84toMercator
(
wgs84
[
0
],
wgs84
[
1
]);
MercatorPoint
pointB
=
new
MercatorPoint
(
b
[
0
],
b
[
1
]);
wgs84
=
Coordtransform
.
GCJ02toWGS84
(
117.990382
,
24.453953
);
double
[]
c
=
Coordtransform
.
WGS84toMercator
(
wgs84
[
0
],
wgs84
[
1
]);
MercatorPoint
pointC
=
new
MercatorPoint
(
c
[
0
],
c
[
1
]);
wgs84
=
Coordtransform
.
GCJ02toWGS84
(
117.965813
,
24.458992
);
double
[]
d
=
Coordtransform
.
WGS84toMercator
(
wgs84
[
0
],
wgs84
[
1
]);
MercatorPoint
pointD
=
new
MercatorPoint
(
d
[
0
],
d
[
1
]);
return
new
MercatorNet
(
pointA
,
pointB
,
pointC
,
pointD
,
2
);
}
public
static
RealTimeVehicleSchedule
getInstance
(){
if
(
VEHICLE_SCHEDULE
==
null
)
{
synchronized
(
RealTimeVehicleSchedule
.
class
){
if
(
VEHICLE_SCHEDULE
==
null
){
VEHICLE_SCHEDULE
=
new
RealTimeVehicleSchedule
();
}
}
}
return
VEHICLE_SCHEDULE
;
}
/**
* 车辆实时数据
* @param vehicleDataMap key:车辆唯一标识, value:实时数据
* 其中实时数据需包含字段有:location[longitude、latitude]、speed、direction, collectTime,isOnline
*/
public
void
pushRealTimeVehicleData
(
Map
<
String
,
Map
<
String
,
Object
>>
vehicleDataMap
){
if
(
vehicleDataMap
!=
null
){
Set
<
Map
.
Entry
<
String
,
Map
<
String
,
Object
>>>
entrySet
=
vehicleDataMap
.
entrySet
();
String
vid
;
Map
<
String
,
Object
>
data
;
for
(
Map
.
Entry
<
String
,
Map
<
String
,
Object
>>
entry
:
entrySet
)
{
data
=
entry
.
getValue
();
vid
=
String
.
format
(
"%s-%s"
,
data
.
get
(
"vehicleNum"
),
entry
.
getKey
());
//处理9子开头的车,并排除950
if
(
!
vid
.
startsWith
(
"9"
)
||
vid
.
startsWith
(
"950"
)
||
!
data
.
containsKey
(
"location"
)){
continue
;
}
updateOrCreateVehicle
(
vid
,
data
);
}
}
}
/**
*
* @param vehicleDataMap
*/
public
void
pushSingleVehicleData
(
Map
<
String
,
Object
>
vehicleDataMap
){
if
(
vehicleDataMap
!=
null
){
String
vid
=
String
.
format
(
"%s-%s"
,
vehicleDataMap
.
get
(
"vehicleNum"
),
vehicleDataMap
.
get
(
"vin"
));
//处理9子开头的车,并排除950
if
(
!
vid
.
startsWith
(
"9"
)
||
vid
.
startsWith
(
"950"
)
||
!
vehicleDataMap
.
containsKey
(
"location"
)){
return
;
}
updateOrCreateVehicle
(
vid
,
vehicleDataMap
);
}
}
private
void
updateOrCreateVehicle
(
String
vid
,
Map
<
String
,
Object
>
data
){
Object
collectTime
=
data
.
get
(
"collectTime"
);
Object
direction
=
data
.
get
(
"direction"
);
Object
speed
=
data
.
get
(
"speed"
);
data
.
put
(
"closeArea"
,
""
);
String
isOnline
=
String
.
valueOf
(
data
.
get
(
"isOnline"
));
Integer
versionNo
=
(
Integer
)
data
.
get
(
"versionNo"
);
try
{
VehicleRealTimeInfoListener
listener
=
SpringUtils
.
getObject
(
VehicleRealTimeInfoListener
.
class
);
double
sp
=
Double
.
parseDouble
(
String
.
valueOf
(
speed
));
double
[]
location
=
(
double
[])
data
.
get
(
"location"
);
double
direc
=
Double
.
parseDouble
(
String
.
valueOf
(
direction
))
/
100
;
MercatorPoint
point
=
getPoint
(
location
[
0
],
location
[
1
]);
MercatorVehicle
vehicle
=
this
.
vehicleMap
.
get
(
vid
);
Collection
<
MercatorGrid
>
grids
=
null
;
if
(
vehicle
==
null
){
if
(
"1"
.
equals
(
isOnline
)
&&
sp
>
0
)
{
grids
=
getGrids
(
data
,
location
[
0
],
location
[
1
],
deltAngle
-
direc
);
vehicle
=
new
MercatorVehicle
(
this
.
eventBus
,
vid
,
grids
,
point
,
Double
.
parseDouble
(
String
.
valueOf
(
speed
)),
Long
.
parseLong
(
String
.
valueOf
(
collectTime
)));
vehicle
.
setVersionNo
(
versionNo
);
this
.
vehicleMap
.
put
(
vid
,
vehicle
);
}
}
else
{
//在线,且运动中,则进行网格占用更新,否则全部释放
if
(
"1"
.
equals
(
isOnline
)
&&
(
sp
>
0
||
vehicle
.
waitGridSize
()>
0
||
vehicle
.
isActive
()))
{
grids
=
getGrids
(
data
,
location
[
0
],
location
[
1
],
deltAngle
-
direc
);
vehicle
.
update
(
grids
,
point
,
Double
.
parseDouble
(
String
.
valueOf
(
speed
)),
Long
.
parseLong
(
String
.
valueOf
(
collectTime
)));
vehicle
.
setVersionNo
(
versionNo
);
if
(
sp
>
0
)
vehicle
.
setActive
(
false
);
}
else
{
//非等待中车辆
//车辆已下线 或车辆已停车 释放所有网格
vehicle
.
freeAll
();
}
}
if
(
Objects
.
isNull
(
vehicle
)){
return
;
}
listener
.
invokeForOrder
(
vehicle
);
if
(
vehicle
.
waitGridSize
()>
0
||(
sp
==
0
&&!
vehicle
.
isActive
()&&!
listener
.
isContainVin
(
vid
))){
//解决关联方停止车辆速度为0,未下命令但为停止状态,
//车辆暂停任务释放已拥有区域,解决死锁和区域资源占用
vehicle
.
freeOwnedGrids
();
data
.
put
(
"closeArea"
,
""
);
}
}
catch
(
Exception
e
){
logger
.
error
(
String
.
format
(
"创建或更新 %s 的MercatorVehicle对象失败:"
+
"speed: %s, direction: %s, collectTime: %s"
,
vid
,
speed
,
direction
,
collectTime
),
e
);
}
}
private
Collection
<
MercatorGrid
>
getGrids
(
Map
<
String
,
Object
>
data
,
double
lng
,
double
lat
,
double
direc
){
double
[]
startPoint
=
{
lng
,
lat
};
double
[]
delt
=
adapterAreaSize
(
startPoint
,
direc
);
//寻找车辆当前点,沿车头方向10米的点
double
[]
pointO
=
Coordtransform
.
getEndPointByTrigonometric
(
direc
,
startPoint
,
1
);
//pointO,沿车头方向20米的点
double
[]
pointE
=
Coordtransform
.
getEndPointByTrigonometric
(
direc
,
pointO
,
delt
[
1
]);
//pointO,沿车头方向垂直90°方向5米的点,
double
[]
pointA
=
Coordtransform
.
getEndPointByTrigonometric
(
direc
+
90
,
pointO
,
delt
[
0
]);
double
[]
mercatorA
=
Coordtransform
.
WGS84toMercator
(
pointA
[
0
],
pointA
[
1
]);
//pointO,沿车头方向垂直270°方向5米的点,
double
[]
pointD
=
Coordtransform
.
getEndPointByTrigonometric
(
direc
+
270
,
pointO
,
delt
[
0
]);
double
[]
mercatorD
=
Coordtransform
.
WGS84toMercator
(
pointD
[
0
],
pointD
[
1
]);
//pointE,沿车头方向垂直90°方向5米的点,
double
[]
pointB
=
Coordtransform
.
getEndPointByTrigonometric
(
direc
+
90
,
pointE
,
delt
[
0
]);
double
[]
mercatorB
=
Coordtransform
.
WGS84toMercator
(
pointB
[
0
],
pointB
[
1
]);
//pointE,沿车头方向垂直270°方向5米的点,
double
[]
pointC
=
Coordtransform
.
getEndPointByTrigonometric
(
direc
+
270
,
pointE
,
delt
[
0
]);
double
[]
mercatorC
=
Coordtransform
.
WGS84toMercator
(
pointC
[
0
],
pointC
[
1
]);
List
<
String
>
closeArea
=
new
ArrayList
<>();
closeArea
.
add
(
pointA
[
0
]+
","
+
pointA
[
1
]);
closeArea
.
add
(
pointB
[
0
]+
","
+
pointB
[
1
]);
closeArea
.
add
(
pointC
[
0
]+
","
+
pointC
[
1
]);
closeArea
.
add
(
pointD
[
0
]+
","
+
pointD
[
1
]);
data
.
put
(
"closeArea"
,
closeArea
);
/* //测试用
startPoint = Coordtransform.WGS84toGCJ02(startPoint[0], startPoint[1]);
pointA = Coordtransform.WGS84toGCJ02(pointA[0], pointA[1]);
pointB = Coordtransform.WGS84toGCJ02(pointB[0], pointB[1]);
pointC = Coordtransform.WGS84toGCJ02(pointC[0], pointC[1]);
pointD = Coordtransform.WGS84toGCJ02(pointD[0], pointD[1]);
System.out.println(String.format("%s: [%s,%s],[%s,%s],[%s,%s],[%s,%s],[%s,%s]", vid, startPoint[0], startPoint[1], pointA[0], pointA[1], pointB[0], pointB[1], pointC[0], pointC[1], pointD[0], pointD[1]));
*/
//根据车头前方的矩形安全区域的四个顶点墨卡托坐标 查找所占用的网格
return
this
.
mercatorNet
.
getChildGrids
(
new
MercatorPoint
(
mercatorA
[
0
],
mercatorA
[
1
]),
new
MercatorPoint
(
mercatorB
[
0
],
mercatorB
[
1
]),
new
MercatorPoint
(
mercatorC
[
0
],
mercatorC
[
1
]),
new
MercatorPoint
(
mercatorD
[
0
],
mercatorD
[
1
]));
}
private
double
[]
adapterAreaSize
(
double
[]
startPoint
,
double
direction
)
{
//判断直行的角度范围
boolean
isStraight
=
(
direction
>
276
&&
direction
<
285
)
||
(
direction
>
367
&&
direction
<
376
)
||
(
direction
>
96
&&
direction
<
105
)
||
(
direction
>
187
&&
direction
<
196
);
if
(
FieldUtil
.
isCrossArea
(
new
Point
(
startPoint
[
0
],
startPoint
[
1
]))){
return
new
double
[]{
2
,
5
};
}
else
if
(!
isStraight
&&
FieldUtil
.
isSpecialArea
(
new
Point
(
startPoint
[
0
],
startPoint
[
1
]))){
return
new
double
[]{
7
,
32
};
}
else
if
(!
isStraight
){
return
new
double
[]{
7
,
22
};
}
return
new
double
[]{
2
,
16
};
}
private
MercatorPoint
getPoint
(
double
longitude
,
double
latitude
){
double
[]
mercator
=
Coordtransform
.
WGS84toMercator
(
longitude
,
latitude
);
return
new
MercatorPoint
(
mercator
[
0
],
mercator
[
1
]);
}
public
void
clearOutVersionVehicle
(
Integer
versionNo
){
assert
versionNo
>-
1
:
"版本号不能小于0"
;
List
<
String
>
outVersionList
=
new
ArrayList
<>();
this
.
vehicleMap
.
forEach
((
k
,
v
)
->
{
if
(
v
.
getVersionNo
()<
versionNo
-
240
){
outVersionList
.
add
(
k
);
}
});
for
(
String
vin:
outVersionList
){
MercatorVehicle
remove
=
vehicleMap
.
remove
(
vin
);
remove
.
freeAll
();
}
}
@Subscribe
public
void
listener
(
GridFreeEvent
event
){
String
vid
=
event
.
getGrid
().
getCurrentUser
();
MercatorVehicle
vehicle
=
this
.
vehicleMap
.
get
(
vid
);
if
(
vehicle
!=
null
){
vehicle
.
freeWaitGrid
(
event
.
getVid
(),
event
.
getGrid
());
}
else
{
event
.
getGrid
().
freeToNext
(
vid
);
}
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/telaidian/AESOperator.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.telaidian
;
import
sun.misc.BASE64Decoder
;
import
sun.misc.BASE64Encoder
;
import
javax.crypto.Cipher
;
import
javax.crypto.spec.IvParameterSpec
;
import
javax.crypto.spec.SecretKeySpec
;
/**
* AES工具
*/
public
class
AESOperator
{
private
static
final
String
DEFAULT_CIPHER_ALGORITHM
=
"AES/CBC/PKCS5Padding"
;
/**
* @param src
* @param AESSecret
* @param AESSecretIv
* @return
* @throws Exception
*/
public
static
String
encrypt
(
String
src
,
String
AESSecret
,
String
AESSecretIv
)
throws
Exception
{
Cipher
cipher
=
Cipher
.
getInstance
(
DEFAULT_CIPHER_ALGORITHM
);
SecretKeySpec
secretKeySpec
=
new
SecretKeySpec
(
AESSecret
.
getBytes
(),
"AES"
);
IvParameterSpec
iv
=
new
IvParameterSpec
(
AESSecretIv
.
getBytes
());
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
secretKeySpec
,
iv
);
byte
[]
encrypted
=
cipher
.
doFinal
(
src
.
getBytes
(
"utf-8"
));
return
new
BASE64Encoder
().
encode
(
encrypted
).
replaceAll
(
"\r|\n"
,
""
);
}
/**
* 解密
*
* @param src
* @return
* @throws Exception
*/
public
static
String
decrypt
(
String
src
,
String
AESSecret
,
String
AESSecretIV
)
throws
Exception
{
SecretKeySpec
secretKeySpec
=
new
SecretKeySpec
(
AESSecret
.
getBytes
(
"ASCII"
),
"AES"
);
Cipher
cipher
=
Cipher
.
getInstance
(
DEFAULT_CIPHER_ALGORITHM
);
IvParameterSpec
iv
=
new
IvParameterSpec
(
AESSecretIV
.
getBytes
());
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
secretKeySpec
,
iv
);
return
new
String
(
cipher
.
doFinal
(
new
BASE64Decoder
().
decodeBuffer
(
src
)),
"utf-8"
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/telaidian/ConnectorStatusInfo.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.telaidian
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
lombok.Getter
;
import
lombok.Setter
;
@Getter
@Setter
public
class
ConnectorStatusInfo
{
/**
* 0:离网
* 1:空闲
* 2:占用(未充电)
* 3:占用(充电中)
* 4:占用(预约锁定)
* 255:故障
*/
public
final
static
int
STATUS_0
=
0
;
public
final
static
int
STATUS_1
=
1
;
public
final
static
int
STATUS_2
=
2
;
public
final
static
int
STATUS_3
=
3
;
public
final
static
int
STATUS_4
=
4
;
public
final
static
int
STATUS_255
=
255
;
/**
* 0:未知
* 10:空闲
* 50:占用
*/
public
final
static
int
PARKSTATUS_0
=
0
;
public
final
static
int
PARKSTATUS_10
=
10
;
public
final
static
int
PARKSTATUS_50
=
50
;
/**
* 0:未知
* 10:已解锁
* 50:已上锁
*/
public
final
static
int
LOCKSTATUS_0
=
0
;
public
final
static
int
LOCKSTATUS_10
=
10
;
public
final
static
int
LOCKSTATUS_50
=
50
;
private
String
ConnectorID
;
private
Integer
Status
;
private
Integer
ParkStatus
;
private
Integer
LockStatus
;
@JsonIgnore
public
boolean
isAway
()
{
return
Status
==
STATUS_0
;
}
@JsonIgnore
public
boolean
isFree
()
{
return
Status
==
STATUS_1
;
}
@JsonIgnore
public
boolean
isOccupation
()
{
return
Status
==
STATUS_2
;
}
@JsonIgnore
public
boolean
isCharging
()
{
return
Status
==
STATUS_3
;
}
@JsonIgnore
public
boolean
isReserveLocked
()
{
return
Status
==
STATUS_4
;
}
@JsonIgnore
public
boolean
isTrouble
()
{
return
Status
==
STATUS_255
;
}
@JsonIgnore
public
boolean
isUnconnectedStatus
()
{
return
isAway
()
||
isFree
();
}
@JsonIgnore
public
boolean
isConnectedStatus
()
{
return
!
isUnconnectedStatus
();
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/telaidian/DeviceStatusSchedule.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.telaidian
;
import
com.alibaba.fastjson.JSONObject
;
import
com.google.gson.*
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.stereotype.Component
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* 充电设备状态刷新调度任务
*/
@Component
@ConditionalOnProperty
(
prefix
=
"app.context.charging-schedule"
,
value
=
"enable"
,
matchIfMissing
=
true
)
public
class
DeviceStatusSchedule
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
public
static
final
String
LOG_PREFIX_TELAIDIAN
=
"[Telaidian]"
;
private
static
final
String
CHARGING_PILE_INFO_REDIS_PREFIX
=
"harbor:charging:pile:info:"
;
private
boolean
lock
=
false
;
@Autowired
private
Gson
gson
;
private
JsonParser
jsonParser
=
new
JsonParser
();
@Autowired
private
TelaidianRequestTpl
telaidianRequestTpl
;
@Autowired
/**
* 调度任务
*/
// @Scheduled(cron = "${telaidian.status-refresh.cron}")
private
void
refreshDeviceStatus
()
{
if
(
lock
)
{
return
;
}
try
{
lock
=
true
;
JSONObject
statusMap
=
queryDeviceStatus
();
if
(
"0"
.
equalsIgnoreCase
(
statusMap
.
getString
(
"Ret"
)))
{
List
<
ConnectorStatusInfo
>
connectorStatusInfoList
=
new
ArrayList
<>();
String
data
=
statusMap
.
getString
(
"Data"
);
JsonObject
jsonObject
=
jsonParser
.
parse
(
data
).
getAsJsonObject
();
JsonArray
stationStatusArray
=
jsonObject
.
getAsJsonArray
(
"StationStatusInfos"
);
if
(
stationStatusArray
!=
null
)
{
for
(
JsonElement
stationStatusEl
:
stationStatusArray
)
{
JsonArray
connectorStatusArray
=
stationStatusEl
.
getAsJsonObject
().
getAsJsonArray
(
"ConnectorStatusInfos"
);
if
(
connectorStatusArray
!=
null
)
{
for
(
JsonElement
connectorStatusEl
:
connectorStatusArray
)
{
ConnectorStatusInfo
connectorStatusInfo
=
gson
.
fromJson
(
connectorStatusEl
.
getAsJsonObject
(),
ConnectorStatusInfo
.
class
);
connectorStatusInfoList
.
add
(
connectorStatusInfo
);
}
}
}
}
updateChargingPileInfoInRedis
(
connectorStatusInfoList
);
// logger.debug(LOG_PREFIX_TELAIDIAN + appContext.objToJsonStr(connectorStatusInfoList));
}
else
{
logger
.
warn
(
LOG_PREFIX_TELAIDIAN
+
gson
.
toJson
(
statusMap
));
}
}
catch
(
Exception
e
)
{
logger
.
error
(
LOG_PREFIX_TELAIDIAN
+
"Fail to refresh device status from telaidian."
,
e
);
}
finally
{
lock
=
false
;
}
}
/**
* 更新状态
*
* @param connectorStatusInfoList
* @throws Exception
*/
private
void
updateChargingPileInfoInRedis
(
List
<
ConnectorStatusInfo
>
connectorStatusInfoList
)
throws
Exception
{
for
(
ConnectorStatusInfo
connectorStatusInfo
:
connectorStatusInfoList
)
{
}
}
/**
* 查询状态
*
* @return
* @throws Exception
*/
private
JSONObject
queryDeviceStatus
()
throws
Exception
{
String
methodName
=
"query_station_status"
;
Map
<
String
,
Object
>
paramMap
=
new
HashMap
<>();
List
<
String
>
stationIdList
=
new
ArrayList
<>();
stationIdList
.
add
(
"3502050037"
);
paramMap
.
put
(
"StationIDs"
,
stationIdList
);
return
telaidianRequestTpl
.
queryData
(
paramMap
,
methodName
,
3
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/utils/telaidian/HMacMD5.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.telaidian
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
/**
* HMacMD5工具
*/
public
class
HMacMD5
{
/**
* 计算参数的md5信息
*
* @param str 待处理的字节数组
* @return md5摘要信息
* @throws NoSuchAlgorithmException
*/
private
static
byte
[]
md5
(
byte
[]
str
)
throws
NoSuchAlgorithmException
{
MessageDigest
md
=
MessageDigest
.
getInstance
(
"MD5"
);
md
.
update
(
str
);
return
md
.
digest
();
}
/**
* 将待加密数据data,通过密钥key,使用hmac-md5算法进行加密,然后返回加密结果。 参照rfc2104 HMAC算法介绍实现。
*
* @param key 密钥
* @param data 待加密数据
* @return 加密结果
* @throws NoSuchAlgorithmException
*/
public
static
byte
[]
getHmacMd5Bytes
(
byte
[]
key
,
byte
[]
data
)
throws
NoSuchAlgorithmException
{
/*
* HmacMd5 calculation formula: H(K XOR opad, H(K XOR ipad, text))
* HmacMd5 计算公式:H(K XOR opad, H(K XOR ipad, text))
* H代表hash算法,本类中使用MD5算法,K代表密钥,text代表要加密的数据 ipad为0x36,opad为0x5C。
*/
int
length
=
64
;
byte
[]
ipad
=
new
byte
[
length
];
byte
[]
opad
=
new
byte
[
length
];
for
(
int
i
=
0
;
i
<
64
;
i
++)
{
ipad
[
i
]
=
0x36
;
opad
[
i
]
=
0x5C
;
}
byte
[]
actualKey
=
key
;
// Actual key.
byte
[]
keyArr
=
new
byte
[
length
];
// Key bytes of 64 bytes length
/*
* If key's length is longer than 64,then use hash to digest it and use
* the result as actual key. 如果密钥长度,大于64字节,就使用哈希算法,计算其摘要,作为真正的密钥。
*/
if
(
key
.
length
>
length
)
{
actualKey
=
md5
(
key
);
}
for
(
int
i
=
0
;
i
<
actualKey
.
length
;
i
++)
{
keyArr
[
i
]
=
actualKey
[
i
];
}
/*
* append zeros to K 如果密钥长度不足64字节,就使用0x00补齐到64字节。
*/
if
(
actualKey
.
length
<
length
)
{
for
(
int
i
=
actualKey
.
length
;
i
<
keyArr
.
length
;
i
++)
keyArr
[
i
]
=
0x00
;
}
/*
* calc K XOR ipad 使用密钥和ipad进行异或运算。
*/
byte
[]
kIpadXorResult
=
new
byte
[
length
];
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
kIpadXorResult
[
i
]
=
(
byte
)
(
keyArr
[
i
]
^
ipad
[
i
]);
}
/*
* append "text" to the end of "K XOR ipad" 将待加密数据追加到K XOR ipad计算结果后面。
*/
byte
[]
firstAppendResult
=
new
byte
[
kIpadXorResult
.
length
+
data
.
length
];
for
(
int
i
=
0
;
i
<
kIpadXorResult
.
length
;
i
++)
{
firstAppendResult
[
i
]
=
kIpadXorResult
[
i
];
}
for
(
int
i
=
0
;
i
<
data
.
length
;
i
++)
{
firstAppendResult
[
i
+
keyArr
.
length
]
=
data
[
i
];
}
/*
* calc H(K XOR ipad, text) 使用哈希算法计算上面结果的摘要。
*/
byte
[]
firstHashResult
=
md5
(
firstAppendResult
);
/*
* calc K XOR opad 使用密钥和opad进行异或运算。
*/
byte
[]
kOpadXorResult
=
new
byte
[
length
];
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
kOpadXorResult
[
i
]
=
(
byte
)
(
keyArr
[
i
]
^
opad
[
i
]);
}
/*
* append "H(K XOR ipad, text)" to the end of "K XOR opad" 将H(K XOR
* ipad, text)结果追加到K XOR opad结果后面
*/
byte
[]
secondAppendResult
=
new
byte
[
kOpadXorResult
.
length
+
firstHashResult
.
length
];
for
(
int
i
=
0
;
i
<
kOpadXorResult
.
length
;
i
++)
{
secondAppendResult
[
i
]
=
kOpadXorResult
[
i
];
}
for
(
int
i
=
0
;
i
<
firstHashResult
.
length
;
i
++)
{
secondAppendResult
[
i
+
keyArr
.
length
]
=
firstHashResult
[
i
];
}
/*
* H(K XOR opad, H(K XOR ipad, text)) 对上面的数据进行哈希运算。
*/
byte
[]
hmacMd5Bytes
=
md5
(
secondAppendResult
);
return
hmacMd5Bytes
;
}
public
static
String
getHmacMd5Str
(
String
key
,
String
data
)
{
String
result
=
""
;
try
{
byte
[]
keyByte
=
key
.
getBytes
(
"UTF-8"
);
byte
[]
dataByte
=
data
.
getBytes
(
"UTF-8"
);
byte
[]
hmacMd5Byte
=
getHmacMd5Bytes
(
keyByte
,
dataByte
);
StringBuffer
md5StrBuff
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
hmacMd5Byte
.
length
;
i
++)
{
if
(
Integer
.
toHexString
(
0xFF
&
hmacMd5Byte
[
i
]).
length
()
==
1
)
md5StrBuff
.
append
(
"0"
).
append
(
Integer
.
toHexString
(
0xFF
&
hmacMd5Byte
[
i
]));
else
md5StrBuff
.
append
(
Integer
.
toHexString
(
0xFF
&
hmacMd5Byte
[
i
]));
}
result
=
md5StrBuff
.
toString
().
toUpperCase
();
}
catch
(
Exception
e
)
{
// logger.error("error getHmacMd5Str()",e);
e
.
printStackTrace
();
}
return
result
;
}
}
\ No newline at end of file
ivccs-vmm-backservice/src/main/java/com/ssi/utils/telaidian/TelaidianRequestTpl.java
0 → 100644
View file @
07602a7b
package
com.ssi.utils.telaidian
;
import
com.alibaba.fastjson.JSONObject
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonObject
;
import
com.google.gson.JsonParser
;
import
org.apache.commons.lang3.time.DateFormatUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.MediaType
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.client.RestClientException
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
/**
* 特来电请求工具模板
*/
@Component
public
class
TelaidianRequestTpl
{
protected
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
@Autowired
private
RestTemplate
restTemplate
;
private
int
tokenCount
=
0
;
@Autowired
private
Gson
gson
;
private
JsonParser
parser
=
new
JsonParser
();
@Value
(
"${telaidian.operator-id-telaidian}"
)
private
String
operatorIdOfTelaidian
;
@Value
(
"${telaidian.operator-id-xmg}"
)
private
String
operatorIdOfXmg
;
@Value
(
"${telaidian.assign-key}"
)
private
String
assignKey
;
@Value
(
"${telaidian.operator-secret}"
)
private
String
operatorSecret
;
@Value
(
"${telaidian.AES-key}"
)
private
String
AESSecretOfXmg
;
@Value
(
"${telaidian.AES-vector}"
)
private
String
AESSecretIVOfXmg
;
@Value
(
"${telaidian.AES-key}"
)
private
String
AESSecretOfTelaidian
;
@Value
(
"${telaidian.AES-vector}"
)
private
String
AESSecretIVOfTelaidian
;
@Value
(
"${telaidian.base-url}"
)
private
String
baseUrl
;
/**
* 获取token
*
* @param url
* @return
* @throws Exception
*/
public
String
getToken
(
String
url
)
throws
Exception
{
Map
<
String
,
Object
>
paramMap
=
new
HashMap
<>();
paramMap
.
put
(
"OperatorID"
,
operatorIdOfXmg
);
paramMap
.
put
(
"OperatorSecret"
,
operatorSecret
);
Map
<
String
,
Object
>
returnBody
=
sendRest
(
gson
.
toJson
(
paramMap
),
null
,
url
);
if
(!(
"0"
).
equals
(
String
.
valueOf
(
returnBody
.
get
(
"Ret"
))))
{
logger
.
warn
(
DeviceStatusSchedule
.
LOG_PREFIX_TELAIDIAN
+
gson
.
toJson
(
returnBody
));
throw
new
Exception
(
"Fail to get token from telaidian."
);
}
String
data
=
AESOperator
.
decrypt
(
returnBody
.
get
(
"Data"
).
toString
(),
AESSecretOfXmg
,
AESSecretIVOfXmg
);
JsonObject
jsonObject
=
parser
.
parse
(
data
).
getAsJsonObject
();
if
(
jsonObject
.
get
(
"SuccStat"
)
!=
null
&&
jsonObject
.
get
(
"SuccStat"
).
getAsDouble
()
!=
0.0
)
{
logger
.
warn
(
DeviceStatusSchedule
.
LOG_PREFIX_TELAIDIAN
+
jsonObject
.
toString
());
throw
new
Exception
(
"Fail to get token from telaidian."
);
}
return
jsonObject
.
get
(
"AccessToken"
).
getAsString
();
}
/**
* 执行发送请求
*
* @param params
* @param token
* @param url
* @return
* @throws Exception
*/
public
Map
<
String
,
Object
>
sendRest
(
String
params
,
String
token
,
String
url
)
throws
Exception
{
String
Data
=
AESOperator
.
encrypt
(
params
,
AESSecretOfXmg
,
AESSecretIVOfXmg
);
String
TimeStamp
=
DateFormatUtils
.
format
(
new
Date
(),
"yyyyMMddHHmmss"
);
String
Seq
=
"0001"
;
HttpHeaders
headers
=
new
HttpHeaders
();
MediaType
type
=
MediaType
.
parseMediaType
(
"application/json; charset=UTF-8"
);
headers
.
setContentType
(
type
);
headers
.
add
(
"Accept"
,
MediaType
.
APPLICATION_JSON
.
toString
());
headers
.
add
(
"Authorization"
,
token
==
null
?
"Bearer Token"
:
"Bearer "
+
token
);
JsonObject
jsonObj
=
new
JsonObject
();
jsonObj
.
addProperty
(
"OperatorID"
,
operatorIdOfXmg
);
jsonObj
.
addProperty
(
"Data"
,
Data
);
jsonObj
.
addProperty
(
"TimeStamp"
,
TimeStamp
);
jsonObj
.
addProperty
(
"Seq"
,
Seq
);
jsonObj
.
addProperty
(
"Sig"
,
getSig
(
Data
,
TimeStamp
,
Seq
));
logger
.
debug
(
DeviceStatusSchedule
.
LOG_PREFIX_TELAIDIAN
+
"接口["
+
url
+
"]下发报文:"
+
jsonObj
.
toString
()
+
",下发的token为:"
+
token
);
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
jsonObj
.
toString
(),
headers
);
Object
obj
=
null
;
try
{
obj
=
restTemplate
.
postForObject
(
url
,
requestEntity
,
Object
.
class
);
}
catch
(
RestClientException
e
)
{
logger
.
error
(
DeviceStatusSchedule
.
LOG_PREFIX_TELAIDIAN
+
"访问错误:"
+
e
.
getMessage
());
}
if
(
obj
instanceof
String
)
{
Map
<
String
,
Object
>
map
=
new
HashMap
<>();
map
=
gson
.
fromJson
(
obj
.
toString
(),
map
.
getClass
());
if
(
map
.
get
(
"Ret"
).
toString
().
equals
(
"0.0"
))
{
map
.
put
(
"Ret"
,
"0"
);
}
return
map
;
}
else
{
Map
<
String
,
Object
>
object
=
restTemplate
.
postForObject
(
url
,
requestEntity
,
LinkedHashMap
.
class
);
return
object
;
}
}
/**
* 获取请求签名
*
* @param Data
* @param TimeStamp
* @param Seq
* @return
*/
private
String
getSig
(
String
Data
,
String
TimeStamp
,
String
Seq
)
{
StringBuilder
builder
=
new
StringBuilder
();
builder
.
append
(
operatorIdOfXmg
).
append
(
Data
).
append
(
TimeStamp
).
append
(
Seq
);
return
HMacMD5
.
getHmacMd5Str
(
assignKey
,
builder
.
toString
());
}
/**
* 查询数据
*
* @param params
* @param methodName
* @param retryNums
* @return
* @throws Exception
*/
public
JSONObject
queryData
(
String
params
,
String
methodName
,
int
retryNums
)
throws
Exception
{
JSONObject
result
=
new
JSONObject
();
if
(
retryNums
<=
0
)
{
logger
.
error
(
DeviceStatusSchedule
.
LOG_PREFIX_TELAIDIAN
+
"token连续3次认证失败."
);
throw
new
Exception
(
"token连续3次认证失败."
);
}
String
token
=
getToken
(
baseUrl
+
"query_token"
);
Map
<
String
,
Object
>
qryResult
=
sendRest
(
params
,
token
,
baseUrl
+
methodName
);
/* retry */
String
retStr
=
qryResult
.
get
(
"Ret"
).
toString
();
if
(
"4002"
.
equals
(
retStr
))
{
return
queryData
(
params
,
methodName
,
retryNums
-
1
);
}
if
(!
"0"
.
equals
(
retStr
))
{
result
.
put
(
"Ret"
,
retStr
);
result
.
put
(
"Msg"
,
qryResult
.
get
(
"Msg"
).
toString
());
return
result
;
}
String
data
=
AESOperator
.
decrypt
(
qryResult
.
get
(
"Data"
).
toString
(),
AESSecretOfXmg
,
AESSecretIVOfXmg
);
result
.
put
(
"Ret"
,
"0"
);
result
.
put
(
"Data"
,
data
);
return
result
;
}
public
JSONObject
queryData
(
Map
<
String
,
Object
>
paramMap
,
String
methodName
,
int
retryNums
)
throws
Exception
{
return
queryData
(
gson
.
toJson
(
paramMap
),
methodName
,
retryNums
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/websocket/AbnormalWebSocketServer.java
0 → 100644
View file @
07602a7b
package
com.ssi.websocket
;
import
com.alibaba.fastjson.JSON
;
import
com.ssi.entity.FaultRecord
;
import
org.apache.commons.collections4.map.PassiveExpiringMap
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
javax.websocket.*
;
import
javax.websocket.server.ServerEndpoint
;
import
java.io.IOException
;
import
java.util.Date
;
import
java.util.concurrent.CopyOnWriteArraySet
;
/**
*
* 异常推送websocket
*/
@ServerEndpoint
(
"/abnormalWebSocket"
)
@Component
public
class
AbnormalWebSocketServer
{
private
final
static
Logger
log
=
LoggerFactory
.
getLogger
(
AbnormalWebSocketServer
.
class
);
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private
static
int
onlineCount
=
0
;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private
static
CopyOnWriteArraySet
<
AbnormalWebSocketServer
>
webSocketSet
=
new
CopyOnWriteArraySet
<
AbnormalWebSocketServer
>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private
Session
session
;
//忽略消息存储map
private
PassiveExpiringMap
<
String
,
Date
>
ignoreMap
=
new
PassiveExpiringMap
<>(
180
*
1000
);
/**
* 连接建立成功调用的方法
*/
@OnOpen
public
void
onOpen
(
Session
session
)
{
this
.
session
=
session
;
webSocketSet
.
add
(
this
);
//加入set中
addOnlineCount
();
//在线数加1
log
.
info
(
"有新窗口开始监听:"
+
session
.
getId
()
+
",当前在线人数为"
+
getOnlineCount
());
try
{
sendMessage
(
"连接成功"
);
}
catch
(
IOException
e
)
{
log
.
error
(
"websocket IO异常"
);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public
void
onClose
()
{
webSocketSet
.
remove
(
this
);
//从set中删除
subOnlineCount
();
//在线数减1
log
.
info
(
"有一连接关闭!当前在线人数为"
+
getOnlineCount
());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public
void
onMessage
(
String
message
,
Session
session
)
{
log
.
info
(
"收到来自窗口"
+
session
.
getId
()
+
"的信息:"
+
message
);
FaultRecord
faultRecord
=
JSON
.
parseObject
(
message
,
FaultRecord
.
class
);
addIgnoreMessage
(
faultRecord
);
}
public
void
addIgnoreMessage
(
FaultRecord
faultRecord
){
String
vin
=
faultRecord
.
getVin
();
String
fmi
=
faultRecord
.
getFmi
();
String
spn
=
faultRecord
.
getSpn
();
String
key
=
vin
+
":"
+
fmi
+
":"
+
spn
;
ignoreMap
.
put
(
key
,
new
Date
());
}
public
boolean
ignoreMessage
(
FaultRecord
faultRecord
){
String
vin
=
faultRecord
.
getVin
();
String
fmi
=
faultRecord
.
getFmi
();
String
spn
=
faultRecord
.
getSpn
();
String
key
=
vin
+
":"
+
fmi
+
":"
+
spn
;
if
(!
ignoreMap
.
isEmpty
()){
Date
date
=
ignoreMap
.
get
(
key
);
if
(
date
!=
null
){
ignoreMap
.
put
(
key
,
date
);
return
true
;
}
}
return
false
;
}
/**
* @param session
* @param error
*/
@OnError
public
void
onError
(
Session
session
,
Throwable
error
)
{
log
.
error
(
"发生错误"
,
error
);
}
/**
* 实现服务器主动推送
*/
public
void
sendMessage
(
String
message
)
throws
IOException
{
this
.
session
.
getBasicRemote
().
sendText
(
message
);
}
public
static
synchronized
int
getOnlineCount
()
{
return
onlineCount
;
}
public
static
synchronized
void
addOnlineCount
()
{
AbnormalWebSocketServer
.
onlineCount
++;
}
public
static
synchronized
void
subOnlineCount
()
{
AbnormalWebSocketServer
.
onlineCount
--;
}
public
static
void
sendInfo
(
String
message
)
{
log
.
info
(
"异常推送websocket收到信息:"
+
message
);
//群发消息
for
(
AbnormalWebSocketServer
item
:
webSocketSet
)
{
try
{
item
.
sendMessage
(
message
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
public
static
void
sendFaultRecord
(
FaultRecord
faultRecord
)
{
//群发消息
for
(
AbnormalWebSocketServer
item
:
webSocketSet
)
{
try
{
if
(!
item
.
ignoreMessage
(
faultRecord
)){
item
.
sendMessage
(
JSON
.
toJSONString
(
faultRecord
));
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/websocket/CraneAppWebSocketServer.java
0 → 100644
View file @
07602a7b
package
com.ssi.websocket
;
import
com.alibaba.fastjson.JSONObject
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.ssi.entity.VmsCranePadBind
;
import
com.ssi.service.VmsCranePadBindService
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
javax.websocket.*
;
import
javax.websocket.server.PathParam
;
import
javax.websocket.server.ServerEndpoint
;
import
java.io.IOException
;
import
java.util.concurrent.CopyOnWriteArraySet
;
/**
* 吊具APP任务推送websocket
* @author zhangly
* @since 2020-02-10
* 相当于ws协议的Controller
*/
@ServerEndpoint
(
"/craneAppWebSocketServer/{padMac}"
)
@Component
public
class
CraneAppWebSocketServer
{
private
final
static
Logger
log
=
LoggerFactory
.
getLogger
(
CraneAppWebSocketServer
.
class
);
@Autowired
private
VmsCranePadBindService
vmsCranePadBindService
;
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private
static
int
onlineCount
=
0
;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private
static
CopyOnWriteArraySet
<
CraneAppWebSocketServer
>
webSocketSet
=
new
CopyOnWriteArraySet
<
CraneAppWebSocketServer
>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private
Session
session
;
//接收sid
private
String
sid
=
""
;
private
String
padMac
=
""
;
private
String
craneNo
=
""
;
/**
* 连接建立成功调用的方法
*/
@OnOpen
public
void
onOpen
(
Session
session
,
@PathParam
(
"sid"
)
String
sid
,
@PathParam
(
"padMac"
)
String
padMac
)
{
this
.
session
=
session
;
webSocketSet
.
add
(
this
);
//加入set中
addOnlineCount
();
//在线数加1
log
.
info
(
"有新窗口开始监听:"
+
sid
+
",当前在线人数为"
+
getOnlineCount
());
this
.
sid
=
sid
;
this
.
padMac
=
padMac
;
try
{
sendMessage
(
"连接成功"
);
}
catch
(
IOException
e
)
{
log
.
error
(
"websocket IO异常"
);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public
void
onClose
()
{
webSocketSet
.
remove
(
this
);
//从set中删除
subOnlineCount
();
//在线数减1
log
.
info
(
"有一连接关闭!当前在线人数为"
+
getOnlineCount
());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public
void
onMessage
(
String
message
,
Session
session
)
{
JSONObject
messageJson
=
JSONObject
.
parseObject
(
message
);
String
padMac
=
messageJson
.
getString
(
"padMac"
);
//群发消息
for
(
CraneAppWebSocketServer
item
:
webSocketSet
)
{
try
{
if
(
item
.
session
.
getId
().
equals
(
session
.
getId
())){
VmsCranePadBind
crane
=
vmsCranePadBindService
.
getOne
(
new
LambdaQueryWrapper
<
VmsCranePadBind
>()
.
eq
(
VmsCranePadBind:
:
getPadMac
,
padMac
));
this
.
craneNo
=
crane
.
getCraneNo
();
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
/**
* @param session
* @param error
*/
@OnError
public
void
onError
(
Session
session
,
Throwable
error
)
{
log
.
error
(
"发生错误"
);
error
.
printStackTrace
();
}
/**
* 实现服务器主动推送
*/
public
void
sendMessage
(
String
message
)
throws
IOException
{
this
.
session
.
getBasicRemote
().
sendText
(
message
);
}
public
static
synchronized
int
getOnlineCount
()
{
return
onlineCount
;
}
public
static
CopyOnWriteArraySet
<
CraneAppWebSocketServer
>
getWebSocketSet
(){
return
webSocketSet
;
}
public
String
getCraneNo
(){
return
this
.
craneNo
;
}
public
String
getPadMac
(){
return
this
.
padMac
;
}
public
static
synchronized
void
addOnlineCount
()
{
CraneAppWebSocketServer
.
onlineCount
++;
}
public
static
synchronized
void
subOnlineCount
()
{
CraneAppWebSocketServer
.
onlineCount
--;
}
public
void
sendInfo
()
{
log
.
info
(
"桥吊APP推送任务信息:"
);
}
}
ivccs-vmm-backservice/src/main/java/com/ssi/websocket/CraneInfoWebSocketServer.java
0 → 100644
View file @
07602a7b
package
com.ssi.websocket
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
javax.websocket.*
;
import
javax.websocket.server.ServerEndpoint
;
import
java.io.IOException
;
import
java.util.concurrent.CopyOnWriteArraySet
;
/**
* 吊具实时信息websocket
*/
@ServerEndpoint
(
"/craneWebSocket"
)
@Component
public
class
CraneInfoWebSocketServer
{
private
final
static
Logger
log
=
LoggerFactory
.
getLogger
(
CraneInfoWebSocketServer
.
class
);
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private
static
int
onlineCount
=
0
;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private
static
CopyOnWriteArraySet
<
CraneInfoWebSocketServer
>
webSocketSet
=
new
CopyOnWriteArraySet
<
CraneInfoWebSocketServer
>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private
Session
session
;
private
String
craneNo
;
/**
* 连接建立成功调用的方法
*/
@OnOpen
public
void
onOpen
(
Session
session
)
{
this
.
session
=
session
;
webSocketSet
.
add
(
this
);
//加入set中
addOnlineCount
();
//在线数加1
log
.
info
(
"CraneWebSocketServer有新窗口开始监听:"
+
session
.
getId
()
+
",当前在线人数为"
+
getOnlineCount
());
try
{
sendMessage
(
"连接成功"
);
}
catch
(
IOException
e
)
{
log
.
error
(
"CraneWebSocketServer websocket IO异常"
);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public
void
onClose
()
{
webSocketSet
.
remove
(
this
);
//从set中删除
subOnlineCount
();
//在线数减1
log
.
info
(
"CraneWebSocketServer有一连接关闭!当前在线人数为"
+
getOnlineCount
());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public
void
onMessage
(
String
message
,
Session
session
)
{
log
.
info
(
"CraneWebSocketServer收到来自窗口"
+
session
.
getId
()
+
"的信息:"
+
message
);
this
.
craneNo
=
message
;
}
/**
* @param session
* @param error
*/
@OnError
public
void
onError
(
Session
session
,
Throwable
error
)
{
log
.
error
(
"CraneInfoWebSocketServer发生错误"
,
error
);
}
/**
* 实现服务器主动推送
*/
public
void
sendMessage
(
String
message
)
throws
IOException
{
this
.
session
.
getBasicRemote
().
sendText
(
message
);
}
public
static
synchronized
int
getOnlineCount
()
{
return
onlineCount
;
}
public
static
synchronized
void
addOnlineCount
()
{
CraneInfoWebSocketServer
.
onlineCount
++;
}
public
static
synchronized
void
subOnlineCount
()
{
CraneInfoWebSocketServer
.
onlineCount
--;
}
public
static
CopyOnWriteArraySet
<
CraneInfoWebSocketServer
>
getWebSocketSet
()
{
return
webSocketSet
;
}
public
String
getCraneNo
()
{
return
craneNo
;
}
}
Prev
1
…
17
18
19
20
21
22
23
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