|
@@ -0,0 +1,647 @@
|
|
|
+package com.tidecloud.dataacceptance.codec;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.nio.ByteBuffer;
|
|
|
+import java.nio.channels.FileChannel;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import javax.xml.bind.DatatypeConverter;
|
|
|
+
|
|
|
+import org.apache.commons.lang.ArrayUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import com.tidecloud.dataacceptance.common.BCD8421Operater;
|
|
|
+import com.tidecloud.dataacceptance.common.BitOperator;
|
|
|
+import com.tidecloud.dataacceptance.common.Constants;
|
|
|
+import com.tidecloud.dataacceptance.common.NumUtil;
|
|
|
+import com.tidecloud.dataacceptance.entity.CanDevice;
|
|
|
+import com.tidecloud.dataacceptance.entity.LocationInfoUploadMsg;
|
|
|
+import com.tidecloud.dataacceptance.entity.LocationSelfInfoUploadMsg;
|
|
|
+import com.tidecloud.dataacceptance.entity.PackageData;
|
|
|
+import com.tidecloud.dataacceptance.entity.PackageData.MsgHeader;
|
|
|
+import com.tidecloud.dataacceptance.entity.TerminalRegisterMsg;
|
|
|
+import com.tidecloud.dataacceptance.entity.TerminalRegisterMsg.TerminalRegInfo;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author: chudk
|
|
|
+ * @date: 2017年11月8日 下午4:09:15
|
|
|
+ */
|
|
|
+public class MsgDecoder {
|
|
|
+
|
|
|
+ private static final String DATA_PATH = "/home/service/collector_6707/rawdata/";
|
|
|
+// private static final String DATA_PATH = "D:\\var\\log\\tidecloud\\";
|
|
|
+ private static File WRITE_FILE = null;
|
|
|
+ private static Boolean ISINIT = true;
|
|
|
+ private static final Integer TEN_M = 10485760;
|
|
|
+ private static final String PREFIX_NAME = "can.";
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(MsgDecoder.class);
|
|
|
+ private static Map<String, Map<Integer, CanDevice>> canDeviceMap = new HashMap<>();
|
|
|
+
|
|
|
+ private BitOperator bitOperator;
|
|
|
+ private BCD8421Operater bcd8421Operater;
|
|
|
+
|
|
|
+ public MsgDecoder() {
|
|
|
+ this.bitOperator = new BitOperator();
|
|
|
+ this.bcd8421Operater = new BCD8421Operater();
|
|
|
+ }
|
|
|
+
|
|
|
+ public PackageData bytes2PackageData(byte[] data) {
|
|
|
+ PackageData ret = new PackageData();
|
|
|
+
|
|
|
+ // 0. 终端套接字地址信息
|
|
|
+ // ret.setChannel(msg.getChannel());
|
|
|
+
|
|
|
+ // 1. 16byte 或 12byte 消息头
|
|
|
+ MsgHeader msgHeader = this.parseMsgHeaderFromBytes(data);
|
|
|
+ ret.setMsgHeader(msgHeader);
|
|
|
+
|
|
|
+ int msgBodyByteStartIndex = 12;
|
|
|
+ // 2. 消息体
|
|
|
+ // 有子包信息,消息体起始字节后移四个字节:消息包总数(word(16))+包序号(word(16))
|
|
|
+ if (msgHeader.isHasSubPackage()) {
|
|
|
+ msgBodyByteStartIndex = 16;
|
|
|
+ }
|
|
|
+
|
|
|
+ byte[] tmp = new byte[msgHeader.getMsgBodyLength()];
|
|
|
+ System.arraycopy(data, msgBodyByteStartIndex, tmp, 0, tmp.length);
|
|
|
+ ret.setMsgBodyBytes(tmp);
|
|
|
+
|
|
|
+ // 3. 去掉分隔符之后,最后一位就是校验码
|
|
|
+ // int checkSumInPkg =
|
|
|
+ // this.bitOperator.oneByteToInteger(data[data.length - 1]);
|
|
|
+ int checkSumInPkg = data[data.length - 1];
|
|
|
+ int calculatedCheckSum = this.bitOperator.getCheckSum4JT808(data, 0, data.length - 1);
|
|
|
+ ret.setCheckSum(checkSumInPkg);
|
|
|
+ if (checkSumInPkg != calculatedCheckSum) {
|
|
|
+ log.warn("检验码不一致,msgid:{},pkg:{},calculated:{}", msgHeader.getMsgId(), checkSumInPkg, calculatedCheckSum);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private MsgHeader parseMsgHeaderFromBytes(byte[] data) {
|
|
|
+ MsgHeader msgHeader = new MsgHeader();
|
|
|
+
|
|
|
+ // 1. 消息ID word(16)
|
|
|
+ // byte[] tmp = new byte[2];
|
|
|
+ // System.arraycopy(data, 0, tmp, 0, 2);
|
|
|
+ // msgHeader.setMsgId(this.bitOperator.twoBytesToInteger(tmp));
|
|
|
+ msgHeader.setMsgId(this.parseIntFromBytes(data, 0, 2));
|
|
|
+
|
|
|
+ // 2. 消息体属性 word(16)=================>
|
|
|
+ // System.arraycopy(data, 2, tmp, 0, 2);
|
|
|
+ // int msgBodyProps = this.bitOperator.twoBytesToInteger(tmp);
|
|
|
+ int msgBodyProps = this.parseIntFromBytes(data, 2, 2);
|
|
|
+ msgHeader.setMsgBodyPropsField(msgBodyProps);
|
|
|
+ // [ 0-9 ] 0000,0011,1111,1111(3FF)(消息体长度)
|
|
|
+ msgHeader.setMsgBodyLength(msgBodyProps & 0x3ff);
|
|
|
+ // [10-12] 0001,1100,0000,0000(1C00)(加密类型)
|
|
|
+ msgHeader.setEncryptionType((msgBodyProps & 0x1c00) >> 10);
|
|
|
+ // [ 13_ ] 0010,0000,0000,0000(2000)(是否有子包)
|
|
|
+ msgHeader.setHasSubPackage(((msgBodyProps & 0x2000) >> 13) == 1);
|
|
|
+ // [14-15] 1100,0000,0000,0000(C000)(保留位)
|
|
|
+ msgHeader.setReservedBit(((msgBodyProps & 0xc000) >> 14) + "");
|
|
|
+ // 消息体属性 word(16)<=================
|
|
|
+
|
|
|
+ // 3. 终端手机号 bcd[6]
|
|
|
+ // tmp = new byte[6];
|
|
|
+ // System.arraycopy(data, 4, tmp, 0, 6);
|
|
|
+ // msgHeader.setTerminalPhone(this.bcd8421Operater.bcd2String(tmp));
|
|
|
+ msgHeader.setTerminalPhone(this.parseBcdStringFromBytes(data, 4, 6));
|
|
|
+
|
|
|
+ // 4. 消息流水号 word(16) 按发送顺序从 0 开始循环累加
|
|
|
+ // tmp = new byte[2];
|
|
|
+ // System.arraycopy(data, 10, tmp, 0, 2);
|
|
|
+ // msgHeader.setFlowId(this.bitOperator.twoBytesToInteger(tmp));
|
|
|
+ msgHeader.setFlowId(this.parseIntFromBytes(data, 10, 2));
|
|
|
+
|
|
|
+ // 5. 消息包封装项
|
|
|
+ // 有子包信息
|
|
|
+ if (msgHeader.isHasSubPackage()) {
|
|
|
+ // 消息包封装项字段
|
|
|
+ msgHeader.setPackageInfoField(this.parseIntFromBytes(data, 12, 4));
|
|
|
+ // byte[0-1] 消息包总数(word(16))
|
|
|
+ // tmp = new byte[2];
|
|
|
+ // System.arraycopy(data, 12, tmp, 0, 2);
|
|
|
+ // msgHeader.setTotalSubPackage(this.bitOperator.twoBytesToInteger(tmp));
|
|
|
+ msgHeader.setTotalSubPackage(this.parseIntFromBytes(data, 12, 2));
|
|
|
+
|
|
|
+ // byte[2-3] 包序号(word(16)) 从 1 开始
|
|
|
+ // tmp = new byte[2];
|
|
|
+ // System.arraycopy(data, 14, tmp, 0, 2);
|
|
|
+ // msgHeader.setSubPackageSeq(this.bitOperator.twoBytesToInteger(tmp));
|
|
|
+ msgHeader.setSubPackageSeq(this.parseIntFromBytes(data, 12, 2));
|
|
|
+ }
|
|
|
+ return msgHeader;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected String parseStringFromBytes(byte[] data, int startIndex, int lenth) {
|
|
|
+ return this.parseStringFromBytes(data, startIndex, lenth, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String parseStringFromBytes(byte[] data, int startIndex, int lenth, String defaultVal) {
|
|
|
+ try {
|
|
|
+ byte[] tmp = new byte[lenth];
|
|
|
+ System.arraycopy(data, startIndex, tmp, 0, lenth);
|
|
|
+ return new String(tmp, Constants.GBK_CHARSET);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析字符串出错:{}", e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ return defaultVal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String parseBcdStringFromBytes(byte[] data, int startIndex, int lenth) {
|
|
|
+ return this.parseBcdStringFromBytes(data, startIndex, lenth, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String parseBcdStringFromBytes(byte[] data, int startIndex, int lenth, String defaultVal) {
|
|
|
+ try {
|
|
|
+ byte[] tmp = new byte[lenth];
|
|
|
+ System.arraycopy(data, startIndex, tmp, 0, lenth);
|
|
|
+ return this.bcd8421Operater.bcd2String(tmp);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析BCD(8421码)出错:{}", e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ return defaultVal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int parseIntFromBytes(byte[] data, int startIndex, int length) {
|
|
|
+ return this.parseIntFromBytes(data, startIndex, length, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int parseIntFromBytes(byte[] data, int startIndex, int length, int defaultVal) {
|
|
|
+ try {
|
|
|
+ // 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
|
|
|
+ final int len = length > 4 ? 4 : length;
|
|
|
+ byte[] tmp = new byte[len];
|
|
|
+ System.arraycopy(data, startIndex, tmp, 0, len);
|
|
|
+ return bitOperator.byteToInteger(tmp);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析整数出错:{}", e.getMessage());
|
|
|
+ return defaultVal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public TerminalRegisterMsg toTerminalRegisterMsg(PackageData packageData) {
|
|
|
+ TerminalRegisterMsg ret = new TerminalRegisterMsg(packageData);
|
|
|
+ byte[] data = ret.getMsgBodyBytes();
|
|
|
+
|
|
|
+ TerminalRegInfo body = new TerminalRegInfo();
|
|
|
+
|
|
|
+ // 1. byte[0-1] 省域ID(WORD)
|
|
|
+ // 设备安装车辆所在的省域,省域ID采用GB/T2260中规定的行政区划代码6位中前两位
|
|
|
+ // 0保留,由平台取默认值
|
|
|
+ body.setProvinceId(this.parseIntFromBytes(data, 0, 2));
|
|
|
+
|
|
|
+ // 2. byte[2-3] 设备安装车辆所在的市域或县域,市县域ID采用GB/T2260中规定的行 政区划代码6位中后四位
|
|
|
+ // 0保留,由平台取默认值
|
|
|
+ body.setCityId(this.parseIntFromBytes(data, 2, 2));
|
|
|
+
|
|
|
+ // 3. byte[4-8] 制造商ID(BYTE[5]) 5 个字节,终端制造商编码
|
|
|
+ // byte[] tmp = new byte[5];
|
|
|
+ body.setManufacturerId(this.parseStringFromBytes(data, 4, 5));
|
|
|
+
|
|
|
+ // 4. byte[9-28] 终端型号(BYTE[8]) 八个字节, 此终端型号 由制造商自行定义 位数不足八位的,补空格。
|
|
|
+ body.setTerminalType(this.parseStringFromBytes(data, 9, 20));
|
|
|
+
|
|
|
+ // 5. byte[29-35] 终端ID(BYTE[7]) 七个字节, 由大写字母 和数字组成, 此终端 ID由制造 商自行定义
|
|
|
+ body.setTerminalId(this.parseStringFromBytes(data, 29, 7));
|
|
|
+
|
|
|
+ // 6. byte[36-37] 车牌颜色(BYTE) 车牌颜 色按照JT/T415-2006 中5.4.12 的规定
|
|
|
+ body.setLicensePlateColor(this.parseIntFromBytes(data, 36, 1));
|
|
|
+ // 7. byte[25-x] 车牌(STRING) 公安交 通管理部门颁 发的机动车号牌
|
|
|
+// body.setLicensePlate(this.parseStringFromBytes(data, 25, data.length - 25));
|
|
|
+
|
|
|
+ ret.setTerminalRegInfo(body);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public LocationSelfInfoUploadMsg toSelfLocationInfoUploadMsg(PackageData packageData) throws Exception{
|
|
|
+ LocationSelfInfoUploadMsg ret = new LocationSelfInfoUploadMsg(packageData);
|
|
|
+ final byte[] data = ret.getMsgBodyBytes();
|
|
|
+ String dataStr = DatatypeConverter.printHexBinary(data);
|
|
|
+ log.info("data is [{}]", dataStr);
|
|
|
+// 1. byte[0-2] 子协议
|
|
|
+ int subProtocal = this.parseIntFromBytes(data, 0, 3);
|
|
|
+// 1. byte[3-4] 压缩前数据的长度
|
|
|
+ int beforeComparssLength = this.parseIntFromBytes(data, 2, 2);
|
|
|
+// 2. byte[5-x] 压缩后的数据
|
|
|
+ byte[] realData = Arrays.copyOfRange(data, 5, data.length);
|
|
|
+// realData = JT808ProtocolUtils.doEscape4Receive(realData, 0, realData.length);
|
|
|
+// CanDevice canDevice = new CanDevice();
|
|
|
+// String deviceId = ret.getMsgHeader().getTerminalPhone();
|
|
|
+// canDevice.setDeviceId(deviceId);
|
|
|
+// try {
|
|
|
+// while (realData.length > 0) {
|
|
|
+//// 3. byte[0-1] 数据类型
|
|
|
+// int realDataLength = realData.length;
|
|
|
+// int dataType = this.parseIntFromBytes(realData, 0, 1);
|
|
|
+// if (realDataLength >= 5 && Constants.TYPE_OF_TIME.equals(dataType)) {
|
|
|
+// byte[] subDate = Arrays.copyOfRange(realData, 1, 5);
|
|
|
+// int timestamp = BitOperator.bytesToInt(subDate);
|
|
|
+// canDevice.setDate(timestamp);
|
|
|
+// realData = Arrays.copyOfRange(realData, 5, realData.length);
|
|
|
+// } else if (realDataLength >= 21 && Constants.TYPE_OF_GPS.equals(dataType)) {
|
|
|
+// byte[] gpsByteArray = Arrays.copyOfRange(realData, 2, realData.length);
|
|
|
+// realData = Arrays.copyOfRange(realData, 21, realData.length);
|
|
|
+// } else if (realDataLength >=6 && Constants.TYPE_OF_AD_OIL.equals(dataType)) {
|
|
|
+// realData = Arrays.copyOfRange(realData, 6, realData.length);
|
|
|
+// } else if (realDataLength >= 24 && Constants.TYPE_OF_MILEAGE.equals(dataType)) {
|
|
|
+// realData = Arrays.copyOfRange(realData, 24, realData.length);
|
|
|
+// }else if (realDataLength >= 10 && Constants.TYPE_OF_SWT.equals(dataType)) {
|
|
|
+// realData = Arrays.copyOfRange(realData, 10, realData.length);
|
|
|
+// } else if (realDataLength >= 19 && Constants.TYPE_OF_EXT.equals(dataType)) {
|
|
|
+// realData = Arrays.copyOfRange(realData, 19, realData.length);
|
|
|
+// } else if (realDataLength >= 4 && Constants.TYPE_OF_SPEED.equals(dataType)) {
|
|
|
+// realData = Arrays.copyOfRange(realData, 4, realData.length);
|
|
|
+// } else if (realDataLength >= 7 && Constants.TYPE_OF_DRIVER_DATA.equals(dataType)) {
|
|
|
+// int len = parseIntFromBytes(realData, 1, 1);
|
|
|
+// realData = Arrays.copyOfRange(realData, len + 1, realData.length);
|
|
|
+// } else if (realDataLength >= 7 && Constants.TYPE_OF_CAN_DATA.equals(dataType)) {
|
|
|
+// int subType = this.parseIntFromBytes(realData, 2, 1);
|
|
|
+// int timeDiff = this.parseIntFromBytes(realData, 1, 1);
|
|
|
+// byte[] subData = Arrays.copyOfRange(realData, 3, 7);
|
|
|
+// int value = BitOperator.bytesToInt(subData);
|
|
|
+// CanDevice canDeviceInMap = setCanDevcieFiled(deviceId, canDevice.getDate(), timeDiff);
|
|
|
+// if (Constants.SUB_TYPE_OF_TURNSPEED.equals(subType)) {
|
|
|
+// canDeviceInMap.setTurnSpeed(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_TORQUE.equals(subType)) {
|
|
|
+//// subData = Arrays.copyOfRange(realData, 3, 8);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_VOLTAGE.equals(subType)) {
|
|
|
+// canDeviceInMap.setVoltage(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_OILTEMPERTURE.equals(subType)) {
|
|
|
+// canDeviceInMap.setOilTemperture(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_ENGINEOILPRESSURE.equals(subType)) {
|
|
|
+// canDeviceInMap.setEngineOilPressure(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_AIRPRESSURE.equals(subType)) {
|
|
|
+// canDeviceInMap.setAirPressure(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_AIRINTEMPERTURE.equals(subType)) {
|
|
|
+// canDeviceInMap.setAirInTemperture(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_CANSPEED.equals(subType)) {
|
|
|
+// canDeviceInMap.setCanSpeed(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_COOLANTTEMPERTURE.equals(subType)) {
|
|
|
+// canDeviceInMap.setCoolantTemperture(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_OIL.equals(subType)) {
|
|
|
+// canDeviceInMap.setOil(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_RUNTIME.equals(subType)) {
|
|
|
+// canDeviceInMap.setRunTime(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_DM1FAULTCODE.equals(subType)) {
|
|
|
+// canDeviceInMap.setDm1FaultCode(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else if (Constants.SUB_TYPE_OF_TRANSIENTOIL.equals(dataType)) {
|
|
|
+// canDeviceInMap.setTransientOil(value);
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// } else {
|
|
|
+// realData = Arrays.copyOfRange(realData, 7, realData.length);
|
|
|
+// }
|
|
|
+// }else {
|
|
|
+// break;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } catch (IllegalArgumentException e) {
|
|
|
+// log.error(e.getMessage(), e);
|
|
|
+// }
|
|
|
+//// 写入文件
|
|
|
+// Map<Integer, CanDevice> timeDiffCanDevcieMap = canDeviceMap.get(deviceId);
|
|
|
+// if (timeDiffCanDevcieMap != null && !timeDiffCanDevcieMap.isEmpty()) {
|
|
|
+// Set<Integer> timeStamps = timeDiffCanDevcieMap.keySet();
|
|
|
+// for (Integer timeStamp : timeStamps) {
|
|
|
+// CanDevice canDeviceWrite = timeDiffCanDevcieMap.get(timeStamp);
|
|
|
+// dataStorage(CanDevice.buildCanDeviceStr(canDeviceWrite));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// timeDiffCanDevcieMap.remove(deviceId);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private CanDevice setCanDevcieFiled(String deviceId, Integer date, int timeDiff) {
|
|
|
+ Integer timeStamp = date - timeDiff;
|
|
|
+ Map<Integer, CanDevice> timeDiffCanDeviceMap = canDeviceMap.get(deviceId);
|
|
|
+ if (timeDiffCanDeviceMap == null) {
|
|
|
+ timeDiffCanDeviceMap = new HashMap<>();
|
|
|
+ CanDevice canDevice = new CanDevice();
|
|
|
+ timeDiffCanDeviceMap.put(timeStamp, canDevice);
|
|
|
+ canDeviceMap.put(deviceId, timeDiffCanDeviceMap);
|
|
|
+ canDevice.setDeviceId(deviceId);
|
|
|
+ canDevice.setDate(timeStamp);
|
|
|
+ return canDevice;
|
|
|
+ } else {
|
|
|
+ CanDevice canDeviceInMap = timeDiffCanDeviceMap.get(timeStamp);
|
|
|
+ if (canDeviceInMap == null) {
|
|
|
+ canDeviceInMap = new CanDevice();
|
|
|
+ timeDiffCanDeviceMap.put(timeStamp, canDeviceInMap);
|
|
|
+ canDeviceInMap.setDeviceId(deviceId);
|
|
|
+ canDeviceInMap.setDate(timeStamp);
|
|
|
+ }
|
|
|
+ return canDeviceInMap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public LocationInfoUploadMsg toLocationInfoUploadMsg(PackageData packageData) {
|
|
|
+ LocationInfoUploadMsg ret = new LocationInfoUploadMsg(packageData);
|
|
|
+ final byte[] data = ret.getMsgBodyBytes();
|
|
|
+ // 1. byte[0-3] 报警标志(DWORD(32))
|
|
|
+ ret.setWarningFlagField(this.parseIntFromBytes(data, 0, 3));
|
|
|
+ // 2. byte[4-7] 状态(DWORD(32))
|
|
|
+ int states = this.parseIntFromBytes(data, 4, 4);
|
|
|
+ ret.setStatusField(states);
|
|
|
+ // 3. byte[8-11] 纬度(DWORD(32)) 以度为单位的纬度值乘以10^6,精确到百万分之一度
|
|
|
+ ret.setLatitude(this.parseIntFromBytes(data, 8, 4));
|
|
|
+ // 4. byte[12-15] 经度(DWORD(32)) 以度为单位的经度值乘以10^6,精确到百万分之一度
|
|
|
+ ret.setLongitude(this.parseIntFromBytes(data, 12, 4));
|
|
|
+ // 5. byte[16-17] 高程(WORD(16)) 海拔高度,单位为米( m)
|
|
|
+ ret.setElevation(this.parseIntFromBytes(data, 16, 2));
|
|
|
+ // byte[18-19] 速度(WORD) 1/10km/h
|
|
|
+ ret.setSpeed(this.parseIntFromBytes(data, 18, 2));
|
|
|
+ // byte[20-21] 方向(WORD) 0-359,正北为 0,顺时针
|
|
|
+ ret.setDirection(this.parseIntFromBytes(data, 20, 2));
|
|
|
+ // byte[22-] 时间(BCD[6]) YY-MM-DD-hh-mm-ss
|
|
|
+ // GMT+8 时间,本标准中之后涉及的时间均采用此时区
|
|
|
+ // ret.setTime(this.par);
|
|
|
+ byte[] tmp = new byte[6];
|
|
|
+ System.arraycopy(data, 22, tmp, 0, 6);
|
|
|
+ String time = this.parseBcdStringFromBytes(data, 22, 6);
|
|
|
+ ret.setTime(time);
|
|
|
+
|
|
|
+ byte[] additionalInfo = Arrays.copyOfRange(data, 28, data.length);
|
|
|
+// String printHexBinary = DatatypeConverter.printHexBinary(additionalInfo);
|
|
|
+// log.info("acceptance original data [{}]", printHexBinary);
|
|
|
+// // byte[30-33] 里程
|
|
|
+// ret.setMileage(this.parseIntFromBytes(data, 30, 4));
|
|
|
+// // byte[36-37] 油量
|
|
|
+// ret.setOil(this.parseIntFromBytes(data, 36, 2));
|
|
|
+// // acc 状态 0:关 1:开
|
|
|
+// ret.setAccState(states & 0x01);
|
|
|
+// // gps定位状态 0:未定位 1:定位开
|
|
|
+// ret.setGpsState(states & 0x02);
|
|
|
+ setAdditionalInfo(ret, additionalInfo);
|
|
|
+ ret.setDeviceId(packageData.getMsgHeader().getTerminalPhone());
|
|
|
+ dataStorage(LocationInfoUploadMsg.buildLocationInfo2Str(ret));
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setAdditionalInfo(LocationInfoUploadMsg ret, byte[] additionalInfo) {
|
|
|
+ while (additionalInfo.length > 0) {
|
|
|
+ int type = this.parseIntFromBytes(additionalInfo, 0, 1);
|
|
|
+ int length = this.parseIntFromBytes(additionalInfo, 1, 1);
|
|
|
+ if (Constants.LocationPackage.TYPE_OF_MILEAGE.equals(type)) {
|
|
|
+ ret.setMileage(this.parseIntFromBytes(additionalInfo, 2, length));
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_OIL.equals(type)) {
|
|
|
+ ret.setOil(this.parseIntFromBytes(additionalInfo, 2, length));
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_SPEED.equals(type)) {
|
|
|
+ ret.setSpeed(this.parseIntFromBytes(additionalInfo, 2, length));
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_WARN_ID.equals(type)) {
|
|
|
+ ret.setSpeed(this.parseIntFromBytes(additionalInfo, 2, length));
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_RUN_WARN.equals(type)) {
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_ADDITIONAL_STATE.equals(type)) {
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_IO_STATE.equals(type)) {
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_SIMULATION.equals(type)) {
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_SIGNAL_STRENGTH.equals(type)) {
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_SATELLITE.equals(type)) {
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_CUSTOM.equals(type)) {
|
|
|
+ byte[] subAdditionalInfo = Arrays.copyOfRange(additionalInfo, 2, length);
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ while (subAdditionalInfo.length > 0) {
|
|
|
+ int subLength = this.parseIntFromBytes(subAdditionalInfo, 0, 2);
|
|
|
+ if (Constants.LocationPackage.LENGTH_OF_OIL.equals(subLength)) {
|
|
|
+// int oilInteger = this.parseIntFromBytes(subAdditionalInfo, 4, 2);
|
|
|
+// int oilDouble = this.parseIntFromBytes(subAdditionalInfo, 6, 1);
|
|
|
+ ret.setFuel(getFuel(Arrays.copyOfRange(subAdditionalInfo, 4, 10)));
|
|
|
+
|
|
|
+ }
|
|
|
+ if (additionalInfo.length >= 2 + subLength) {
|
|
|
+ subAdditionalInfo = Arrays.copyOfRange(subAdditionalInfo, 2 + subLength, subAdditionalInfo.length);
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_CUSTOM_WAGNRUI.equals(type)) {
|
|
|
+ byte[] subAdditionalInfo = Arrays.copyOfRange(additionalInfo, 2, length+2);
|
|
|
+ additionalInfo = Arrays.copyOfRange(additionalInfo, length + 2, additionalInfo.length);
|
|
|
+ while (subAdditionalInfo.length > 0) {
|
|
|
+ int subCmd = this.parseIntFromBytes(subAdditionalInfo, 0, 1);
|
|
|
+ int subLength = this.parseIntFromBytes(subAdditionalInfo, 1, 1);
|
|
|
+ if (Constants.LocationPackage.TYPE_OF_CUSTOM_0XFC_0X01.intValue() == subCmd) {
|
|
|
+ //网锐油耗仪扩展报警
|
|
|
+ if (subLength == 0x02) {
|
|
|
+ int status = parseIntFromBytes(subAdditionalInfo,2,2);
|
|
|
+ // 异常油耗报警
|
|
|
+ int oilExceptWarning = (status & 0x01);
|
|
|
+ ret.setOilExceptWarning(oilExceptWarning);
|
|
|
+ // 超时怠速报警
|
|
|
+ int timeoutWaitWarning = (status & 0x02) >> 1;
|
|
|
+ ret.setTimeoutWaitWarning(timeoutWaitWarning);
|
|
|
+ //油耗仪故障报警
|
|
|
+ int oilDeviceWarning = (status & 0x04) >> 2;
|
|
|
+ ret.setOilDeviceWarning(oilDeviceWarning);
|
|
|
+ }
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_CUSTOM_0XFC_0X02.intValue() == subCmd) {
|
|
|
+ //各类累计时长 单位:秒
|
|
|
+ if (subLength == 0x0C) {
|
|
|
+ //byte[] accumulatedFdjWorkTimeArr = Arrays.copyOfRange(subAdditionalInfo, 2, 4);
|
|
|
+ int accumulatedFdjWorkTime = parseIntFromBytes(subAdditionalInfo,2,4);
|
|
|
+ ret.setAccumulatedFdjWorkTime(accumulatedFdjWorkTime);
|
|
|
+ //byte[] accumulatedWorkTimeArr = Arrays.copyOfRange(subAdditionalInfo, 6, 10);
|
|
|
+ int accumulatedWorkTime = parseIntFromBytes(subAdditionalInfo,6,4);
|
|
|
+ ret.setAccumulatedWorkTime(accumulatedWorkTime);
|
|
|
+ //byte[] accumulatedWaitWorkTimeArr = Arrays.copyOfRange(subAdditionalInfo, start, start+8*4);
|
|
|
+ int accumulatedWaitWorkTime = parseIntFromBytes(subAdditionalInfo,10,4);
|
|
|
+ ret.setAccumulatedWaitWorkTime(accumulatedWaitWorkTime);
|
|
|
+ }
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_CUSTOM_0XFC_0X03.intValue() == subCmd) {
|
|
|
+ //各类累计油耗 单位: 毫升
|
|
|
+ if (subLength == 0x0C) {
|
|
|
+ //byte[] accumulatedOilConsumeArr = Arrays.copyOfRange(subAdditionalInfo, start, start+8*4);
|
|
|
+ int accumulatedOilConsume = parseIntFromBytes(subAdditionalInfo,2,4);
|
|
|
+ ret.setAccumulatedOilConsume(accumulatedOilConsume);
|
|
|
+ //byte[] accumulatedWorkOilConsumeArr = Arrays.copyOfRange(subAdditionalInfo, start, start+8*4);
|
|
|
+ int accumulatedWorkOilConsume = parseIntFromBytes(subAdditionalInfo,6,4);
|
|
|
+ ret.setAccumulatedWorkOilConsume(accumulatedWorkOilConsume);
|
|
|
+ //byte[] accumulatedWaitOilConsumeArr = Arrays.copyOfRange(subAdditionalInfo, start, start+8*4);
|
|
|
+ int accumulatedWaitOilConsume= parseIntFromBytes(subAdditionalInfo,10,4);
|
|
|
+ ret.setAccumulatedWaitOilConsume(accumulatedWaitOilConsume);
|
|
|
+ }
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_CUSTOM_0XFC_0X04.intValue() == subCmd) {
|
|
|
+ //各类瞬时油耗 单位: 毫升/100KM 毫升/小时
|
|
|
+ if (subLength == 0x08) {
|
|
|
+ //byte[] OilConsumeOf100KMArr = Arrays.copyOfRange(subAdditionalInfo, start, start+8*4);
|
|
|
+ int oilConsumeOf100KM = parseIntFromBytes(subAdditionalInfo,2,4);
|
|
|
+ ret.setOilConsumeOf100KM(oilConsumeOf100KM);
|
|
|
+ //byte[] OilConsumeOf1HourArr = Arrays.copyOfRange(subAdditionalInfo, start, start+8*4);
|
|
|
+ int oilConsumeOf1Hour = parseIntFromBytes(subAdditionalInfo,6,4);
|
|
|
+ ret.setOilConsumeOf1Hour(oilConsumeOf1Hour);
|
|
|
+
|
|
|
+ }
|
|
|
+ } else if (Constants.LocationPackage.TYPE_OF_CUSTOM_0XFC_0X05.intValue() == subCmd) {
|
|
|
+ if (subLength == 0x02) {
|
|
|
+ //byte[] openStatusArr = Arrays.copyOfRange(subAdditionalInfo, 2, 2);
|
|
|
+ int status = parseIntFromBytes(subAdditionalInfo,2,2);
|
|
|
+
|
|
|
+ // [ 0-0 ] 0000,0000,0000,0001(0x01)(开机状态)
|
|
|
+ int openStatus = (status & 0x01);
|
|
|
+ ret.setOpenStatus(openStatus);
|
|
|
+ // [1-1] 0000,0000,0000,0010(0x02)(运行状态)
|
|
|
+ int runningStatus = (status & 0x02) >> 1;
|
|
|
+ ret.setRunningStatus(runningStatus);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (subAdditionalInfo.length >= 2 + subLength) {
|
|
|
+ subAdditionalInfo = Arrays.copyOfRange(subAdditionalInfo, 2 + subLength, subAdditionalInfo.length);
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getFuel(byte[] copyOfRange) {
|
|
|
+ String printHexBinary = DatatypeConverter.printHexBinary(copyOfRange);
|
|
|
+ System.out.println(printHexBinary);
|
|
|
+ String fuel = "";
|
|
|
+ for (byte b : copyOfRange) {
|
|
|
+ if (Constants.LocationPackage.POINT.equals(b)) {
|
|
|
+ fuel += ".";
|
|
|
+ }else {
|
|
|
+ fuel += b & 0xf;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println(fuel);
|
|
|
+ return fuel;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ for (int i = 0; i < 1000; i++) {
|
|
|
+ LocationInfoUploadMsg infoUploadMsg = new LocationInfoUploadMsg();
|
|
|
+ infoUploadMsg.setDeviceId("14142184169");
|
|
|
+ infoUploadMsg.setTime("180119160845");
|
|
|
+ infoUploadMsg.setLatitude(34000000);
|
|
|
+ infoUploadMsg.setLongitude(12000000);
|
|
|
+ infoUploadMsg.setSpeed(11);
|
|
|
+ infoUploadMsg.setMileage(133);
|
|
|
+ infoUploadMsg.setOil(14);
|
|
|
+ infoUploadMsg.setFuel("13");
|
|
|
+ dataStorage(LocationInfoUploadMsg.buildLocationInfo2Str(infoUploadMsg));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static FileChannel fc = null;
|
|
|
+
|
|
|
+ private static synchronized FileChannel getFileChannel(File file) {
|
|
|
+ if (fc == null) {
|
|
|
+ try {
|
|
|
+ FileOutputStream fos = new FileOutputStream(file, true);
|
|
|
+ fc = fos.getChannel();
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fc;
|
|
|
+ }
|
|
|
+ private static synchronized void dataStorage(String deviceStr) {
|
|
|
+ File path = new File(DATA_PATH);
|
|
|
+ File[] listFiles = path.listFiles();
|
|
|
+ if (ISINIT) {
|
|
|
+ for (File sonFile : listFiles) {
|
|
|
+ String name = sonFile.getName();
|
|
|
+ if (name != null && name.startsWith(PREFIX_NAME)) {
|
|
|
+ long len = sonFile.length();
|
|
|
+ if (len < TEN_M) {
|
|
|
+ WRITE_FILE = sonFile;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ISINIT = false;
|
|
|
+ }
|
|
|
+ if (WRITE_FILE == null || WRITE_FILE.length() > TEN_M) {
|
|
|
+ String fileName = DATA_PATH + PREFIX_NAME + new SimpleDateFormat("yyMMddHHmmss").format(new Date());
|
|
|
+ WRITE_FILE = new File(fileName);
|
|
|
+ writeDevice2File(WRITE_FILE, deviceStr);
|
|
|
+ log.info("touch new file :" + deviceStr + "timestamp:" + new SimpleDateFormat("yyMMddHHmmss").format(new Date()));
|
|
|
+ }else{
|
|
|
+ writeDevice2File(WRITE_FILE, deviceStr);
|
|
|
+ log.info("write data into file : " + deviceStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// public static void writeDevice2File(File file, String deviceStr){
|
|
|
+// Integer length = deviceStr.getBytes().length;
|
|
|
+// try {
|
|
|
+// OutputStream outputStream = new FileOutputStream(file, true);
|
|
|
+// outputStream.write(NumUtil.int2bytes(length));;
|
|
|
+// outputStream.write(deviceStr.getBytes());
|
|
|
+// outputStream.flush();
|
|
|
+// outputStream.close();
|
|
|
+// } catch (IOException e) {
|
|
|
+// log.error(e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public static void writeDevice2File(File file, String deviceStr){
|
|
|
+ FileOutputStream fos = null;
|
|
|
+ try {
|
|
|
+ fos = new FileOutputStream(file, true);
|
|
|
+ Integer length = deviceStr.getBytes().length;
|
|
|
+ byte[] lengthBytes = NumUtil.int2bytes(length);
|
|
|
+ byte[] deviceBytes = deviceStr.getBytes();
|
|
|
+ byte[] dataBytes = ArrayUtils.addAll(lengthBytes, deviceBytes);
|
|
|
+
|
|
|
+ FileChannel fc = fos.getChannel();
|
|
|
+
|
|
|
+ ByteBuffer bbf = ByteBuffer.wrap(dataBytes);
|
|
|
+ // bbf.flip();
|
|
|
+ fc.write(bbf) ;
|
|
|
+ fc.close();
|
|
|
+ fos.flush();
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ } finally {
|
|
|
+ if (fos != null) {
|
|
|
+ try {
|
|
|
+ fos.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|