版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/P923284735/article/details/89643291
解析工具类
package com.jeesite.modules.utils;
import java.text.DecimalFormat;
import org.apache.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
/**
* @Desc 解析GPS发送数据工具类
* @author PGQing
*/
@Slf4j
public class HexMathUtils {
/**
* @Desc 1.将收到的GPS定位数据解析成JSON格式
* @param hex
* @return
* @throws Exception
*/
public static JSONObject formatHexStr(String hexStr) throws Exception {
log.info("准备解析的数据:\n" + hexStr);
JSONObject result = new JSONObject();
try {
if (StringUtils.isNotBlank(hexStr) && hexStr.replaceAll(" ", "").length() == 110) {
JSONObject info = new JSONObject();
// 去空
String content = hexStr.replaceAll(" ", "");
// 长度
info.put("length", content.getBytes("UTF-8").length / 2);
// 消息头
info.put("head", content.substring(0, 2));
// 消息长度
info.put("length", content.substring(2, 4));
// 消息ID
info.put("id", content.substring(4, 6));
// 设备编号
info.put("no", content.substring(6, 14));
// 消息体
info.put("body", content.substring(14, 106));
// 校验位
info.put("bit", content.substring(106));
// 解析设备编号、消息体
result = formatJSONObject(info);
log.info("解析数据为:\n" + result.toJSONString());
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @Desc 2.解析消息体以及设备编号信息
* @param hexObj
* @return
*/
public static JSONObject formatJSONObject(JSONObject hexObj) {
JSONObject obj = new JSONObject();
try {
if (!hexObj.isEmpty()) {
// 解析设备编号
String no = hexObj.getString("no");
if (StringUtils.isNotBlank(no)) {
long sbbh = Long.parseLong(no, 16);// 16进制转换为10进制
no = String.valueOf(sbbh);
String endStr = "";
// 如果不够10位,最高位补0
for (int i = 0; i < 10 - no.length(); i++) {
endStr += "0";
}
no = "CNTL" + endStr + no;
obj.put("no", no);
}
// 解析消息体
String body = hexObj.getString("body");
if (StringUtils.isNotBlank(body)) {
JSONObject bodyObj = formatHexBodyStr(body);
obj.put("body", bodyObj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
/**
* @Desc 3.解析消息体中的经纬度、设备报警信息
* @param hex
* @return
*/
public static JSONObject formatHexBodyStr(String hexBodyStr) {
JSONObject result = new JSONObject();
try {
if (StringUtils.isNotBlank(hexBodyStr)) {
// 去空
String content = hexBodyStr.replaceAll(" ", "");
// 解析设备状态及报警信息
String msg1 = content.substring(0, 2);
int msgResult1 = Integer.parseInt(msg1, 16);// 16进制转换为10进制
msg1 = Integer.toBinaryString(msgResult1);// 10进制转换为2进制
String msg2 = content.substring(2, 4);
int msgResult2 = Integer.parseInt(msg2, 16);
msg2 = Integer.toBinaryString(msgResult2);
result.put("msg", msg1 + msg2);
// 纬度
String lng = content.substring(2 * 2, 2 * 2 + 8);
// 度
int a = Integer.parseInt(lng.substring(0, 2), 16);// 首位,16进制转换为10进制为度
// 分
int a1 = Integer.parseInt(lng.substring(2, 4), 16);// 分,第1位
int a2 = Integer.parseInt(lng.substring(4, 6), 16);// 分,第2位
int a3 = Integer.parseInt(lng.substring(6, 8), 16);// 分,第3位
// 将分转换为度
double a4 = Double.parseDouble("0." + addZero(a1) + addZero(a2) + addZero(a3));
int a5 = new Double(String.valueOf(a4 * 1000000)).intValue();
DecimalFormat df = new DecimalFormat("0.00");
String a6 = df.format((float) a5 / 60);
String a7 = String.valueOf((int) (new Double(a6) * 100));
// 补位
for(int j=0;j<(6-a7.length());j++) {
a7 = "0"+a7;
}
String tempLng = String.valueOf(a) + "." + a7;
result.put("lat", tempLng);
// 经度
String lat = content.substring(6 * 2, 6 * 2 + 10);
// 度
int c = Integer.parseInt(lat.substring(0, 2), 16);// 第1个字节,16进制转换为10进制为度
int d = Integer.parseInt(lat.substring(2, 4), 16);// 第2个字节,16进制转换为10进制为度
// 分
int d1 = Integer.parseInt(lat.substring(4, 6), 16);// 分,第1位
int d2 = Integer.parseInt(lat.substring(6, 8), 16);// 分,第2位
int d3 = Integer.parseInt(lat.substring(8, 10), 16);// 分,第3位
double d4 = Double.parseDouble("0." + addZero(d1) + addZero(d2) + addZero(d3));
int d5 = new Double(String.valueOf(d4 * 1000000)).intValue();
DecimalFormat df1 = new DecimalFormat("0.00");
String d6 = df1.format((float) d5 / 60);
double d7 = Double.parseDouble(d6);
String d8 = String.valueOf((int) (d7 * 10 * 10));
// 补位
for(int l=0;l<(6-d8.length());l++) {
d8="0"+d8;
}
String tempLat = String.valueOf(c) + "" + String.valueOf(d) + "."+ d8;
result.put("lng", tempLat);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 0.byte[]数组转换为16进制的字符串
*
* @param bytes 要转换的字节数组
* @return 转换后的结果
*
*/
public static String bytesToHexString(byte[] bytes) {
StringBuffer sf = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sf.append('0');
}
sf.append(hex);
}
return sf.toString();
}
/**
* 补位
* @param num
* @return
*/
public static String addZero(int num) {
String result = "";
if(num<10) {
result="0"+num;
}else {
result = String.valueOf(num);
}
return result;
}
// 测试方法
public static void main(String[] args) throws Exception {
// String hexStr = "AA37C400D4889100622604411901123845530EF3000000CB16000306000000070509111706130C0C050509C15A18001304160D0D320973";
String hexStr = "AA37C400D6D690006224395E0C01121A11120EA1002100054D001A02000000050311130616160101180303C15A0D0013041B10013508B6";
HexMathUtils.formatHexStr(hexStr).toJSONString();
}
}
注意:一般设备发我们发的数据都是ASCII编码的数据,我们用Socket通讯收到的数据通过数据流读取到后就是字节了,所以我们直接将读取到的字节转换为16进制的字符串,然后在调用我的测试方法,就可以了。
读取数据的线程的部分代码,如下:
@Override
public void run() {
try {
int len = 0;
byte[] bytes = new byte[1024];
byte [] bytes1 = null;
String temp = null;
while ((len = is.read(bytes))!=-1) {
bytes1 = new byte[len];
System.arraycopy(bytes, 0, bytes1, 0, len);
// 将1024长度的数组的可用内容复制出来,因为读取到的数据不一定有1024那么长,会有默认值0。
temp = HexMathUtils.bytesToHexString(bytes1);
// 发送GPS信息请求
Map<String, String> map = new HashMap<>();
map.put("param", temp);
HttpUtils.send("http://localhost:8085/jyzs/socket/saveInfo", map, 10);
}
} catch (Exception e) {
e.printStackTrace();
}
}
到这里基本上就写完了。关键的代码都贴上了,尤其是工具类的解析代码!