1.Jar package download
jt701-sdk-1.0.0.jar Download
If you need Jar package development source code, please contact the business application
2.Integrated Development Instructions
2.1.Integrated development language and framework description
jt701-sdk-1.0.0.jar is based on the Java language,SpringBoot2.x frame,use netty,fastjson,lombok
BaseEnum:base enumeration
Constant:custom constant
AlarmTypeEnum:Alarm enumeration
EventTypeEnum:event enumeration
LocationData:Location entity class
LockEvent:lock event entity class
Result:result entity class
SensorData:Slave data entity class
CommonUtil:public method class
NumberUtil:digital manipulation tools
ParserUtil:Parser method tool class
DataParser:Parser main method
2.2.Integration Instructions
Introduce jt701-sdk-1.0.0.jar into your gateway program as follows:
Introduce the jar package in pom.xml
<dependency>
<groupId>com.jointech.sdk</groupId>
<artifactId>jt701-sdk</artifactId>
<version>1.0.0</version>
</dependency>
Call jt701-sdk-1.0.0.jar, the receiveData() method in the DataParser class
receiveData() method is overloaded
/**
* Parse Hex string raw data
* @param strData hexadecimal string
* @return
*/
public static Object receiveData(String strData)
{
ByteBuf msgBodyBuf = ByteBufAllocator.DEFAULT.heapBuffer(strData.length()/2);
msgBodyBuf.writeBytes(CommonUtil.hexStr2Byte(strData));
return receiveData(msgBodyBuf);
}
/**
* Parse byte[] raw data
* @param bytes
* @return
*/
private static Object receiveData(byte[] bytes)
{
ByteBuf msgBodyBuf =ByteBufAllocator.DEFAULT.heapBuffer(bytes.length);
msgBodyBuf.writeBytes(bytes);
return receiveData(msgBodyBuf);
}
/**
* Parse ByteBuf raw data
* @param in
* @return
*/
private static Object receiveData(ByteBuf in)
{
Object decoded = null;
in.markReaderIndex();
int header = in.readByte();
if (header == Constant.TEXT_MSG_HEADER) {
in.resetReaderIndex();
decoded = ParserUtil.decodeTextMessage(in);
} else if (header == Constant.BINARY_MSG_HEADER) {
in.resetReaderIndex();
decoded = ParserUtil.decodeBinaryMessage(in);
} else {
return null;
}
return JSONArray.toJSON(decoded).toString();
}
2.3.core code
Parsing method tool class ParserUtil
package com.jointech.sdk.jt701.utils;
import com.jointech.sdk.jt701.constants.Constant;
import com.jointech.sdk.jt701.model.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* <p>Description: Analysis method tool class</p>
* @author HyoJung
* @date 20210526
*/
public class ParserUtil {
private ParserUtil()
{}
/**
* Parse command response data
* @param in rawdata
* @return
*/
public static Result decodeTextMessage(ByteBuf in)
{
//Define the location data entity class
Result model = new Result();
//packet head(
in.readByte();
//Field list
List<String> itemList = new ArrayList<String>();
//Transparent binary data
ByteBuf msgBody = null;
while (in.readableBytes() > 0) {
//The 7th field of wireless gateway data upload (WLNET5, WLNET7) and the following are binary data
if (itemList.size() >= 6 && Objects.equals("WLNET", itemList.get(3)) && Constant.WLNET_TYPE_LIST.contains(itemList.get(4))) {
//Length up to the end ")"
int lastItemLen = in.readableBytes() - 1;
//unescape
msgBody = Unpooled.buffer(lastItemLen);
CommonUtil.unescape(in, msgBody, lastItemLen);
in.readByte();
} else {
//Query the subscript of comma to intercept data
int index = in.bytesBefore(Constant.TEXT_MSG_SPLITER);
int itemLen = index > 0 ? index : in.readableBytes() - 1;
byte[] byteArr = new byte[itemLen];
in.readBytes(byteArr);
in.readByte();
itemList.add(new String(byteArr));
}
}
//WLNET message type is composite
String msgType = itemList.get(1);
if (itemList.size() >= 5 && (Objects.equals("WLNET", itemList.get(3))||Objects.equals("OTA", itemList.get(3)))) {
msgType = itemList.get(3) + itemList.get(4);
}
Object dataBody=null;
if(msgType.equals("WLNET5")) {
SensorData sensorData=parseWlnet5(msgBody);
dataBody=sensorData;
model.setReplyMsg(replyMessage(msgType,sensorData.getIndex()));
}else if(msgType.equals("P45")) {
dataBody=parseP45(itemList);
model.setReplyMsg(replyMessage(msgType,itemList));
}else {
if(itemList.size()>0)
{
dataBody="(";
for(String item :itemList) {
dataBody+=item+",";
}
dataBody=CommonUtil.trimEnd(dataBody.toString(),",");
dataBody += ")";
}
}
model.setDeviceID(itemList.get(0));
model.setMsgType(msgType);
model.setDataBody(dataBody);
return model;
}
/**
* Parse slave data
* @param byteBuf
* @return
*/
private static SensorData parseWlnet5(ByteBuf byteBuf) {
SensorData sensorData = new SensorData();
//positioning time
byte[] timeArr = new byte[6];
byteBuf.readBytes(timeArr);
String bcdTimeStr = ByteBufUtil.hexDump(timeArr);
ZonedDateTime gpsZonedDateTime = parseBcdTime(bcdTimeStr);
//latitude
byte[] latArr = new byte[4];
byteBuf.readBytes(latArr);
String latHexStr = ByteBufUtil.hexDump(latArr);
BigDecimal latFloat = new BigDecimal(latHexStr.substring(2, 4) + "." + latHexStr.substring(4)).divide(new BigDecimal("60"), 6, RoundingMode.HALF_UP);
double lat = new BigDecimal(latHexStr.substring(0, 2)).add(latFloat).doubleValue();
//longitude
byte[] lngArr = new byte[5];
byteBuf.readBytes(lngArr);
String lngHexStr = ByteBufUtil.hexDump(lngArr);
BigDecimal lngFloat = new BigDecimal(lngHexStr.substring(3, 5) + "." + lngHexStr.substring(5, 9)).divide(new BigDecimal("60"), 6, RoundingMode.HALF_UP);
double lng = new BigDecimal(lngHexStr.substring(0, 3)).add(lngFloat).doubleValue();
//bit indication
int bitFlag = Byte.parseByte(lngHexStr.substring(9, 10), 16);
//Positioning status
int locationType = (bitFlag & 0x01) > 0 ? 1 : 0;
//north latitude, south latitude
if ((bitFlag & 0b0010) == 0) {
lat = -lat;
}
//East longitude and West longitude
if ((bitFlag & 0b0100) == 0) {
lng = -lng;
}
//Speed
int speed = (int) (byteBuf.readUnsignedByte() * 1.85);
//Header(direction)
int direction = byteBuf.readUnsignedByte() * 2;
//slave time
byte[] slaveMachineTimeArr = new byte[6];
byteBuf.readBytes(slaveMachineTimeArr);
String slaveMachineBcdTimeStr = ByteBufUtil.hexDump(slaveMachineTimeArr);
ZonedDateTime slaveMachineZonedDateTime = parseBcdTime(slaveMachineBcdTimeStr);
//slave sensor ID
byte[] slaveMachineIdArr = new byte[5];
byteBuf.readBytes(slaveMachineIdArr);
String slaveMachineId = ByteBufUtil.hexDump(slaveMachineIdArr).toUpperCase();
//slave data serial number
int flowId = byteBuf.readUnsignedByte();
//slave sensor battery level
String voltage = new BigDecimal(byteBuf.readUnsignedShort()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP).toString();
//slave sensor battery percertage
int power = byteBuf.readUnsignedByte();
//RSSI
int rssi = byteBuf.readUnsignedByte();
//sensor type
int sensorType = byteBuf.readUnsignedByte();
//temperature value
double temperature = -1000.0;
//Humidity value
int humidity = 0;
//Event type
int eventType = -1;
//Device status
int terminalStatus = -1;
//unlock&lock times
int lockTimes = -1;
if (sensorType == 1) {
//temperature
temperature = parseTemperature(byteBuf.readShort());
//Humidity
humidity = byteBuf.readUnsignedByte();
//Gateway saves the number of data
int itemCount = byteBuf.readUnsignedShort();
//gateway status
int gatewayStatus = byteBuf.readUnsignedByte();
} else if (sensorType == 4) {
//event
int event = byteBuf.readUnsignedShort();
//Judgment event
if (NumberUtil.getBitValue(event, 0) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_0.getValue());
} else if (NumberUtil.getBitValue(event, 1) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_1.getValue());
} else if (NumberUtil.getBitValue(event, 2) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_2.getValue());
} else if (NumberUtil.getBitValue(event, 3) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_3.getValue());
} else if (NumberUtil.getBitValue(event, 4) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_4.getValue());
} else if (NumberUtil.getBitValue(event, 5) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_5.getValue());
} else if (NumberUtil.getBitValue(event, 6) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_6.getValue());
} else if (NumberUtil.getBitValue(event, 7) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_7.getValue());
} else if (NumberUtil.getBitValue(event, 8) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_8.getValue());
} else if (NumberUtil.getBitValue(event, 9) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_9.getValue());
}else if (NumberUtil.getBitValue(event, 14) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_14.getValue());
}
//Device status
terminalStatus = byteBuf.readUnsignedShort();
//unlock times
lockTimes = byteBuf.readUnsignedShort();
//gateway status
int gatewayStatus = byteBuf.readUnsignedByte();
}else if (sensorType == 5||sensorType == 6)
{
//event
int event = byteBuf.readUnsignedShort();
//Judgment event
if (NumberUtil.getBitValue(event, 0) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_15.getValue());
} else if (NumberUtil.getBitValue(event, 1) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_16.getValue());
} else if (NumberUtil.getBitValue(event, 2) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_17.getValue());
} else if (NumberUtil.getBitValue(event, 3) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_6.getValue());
} else if (NumberUtil.getBitValue(event, 4) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_18.getValue());
} else if (NumberUtil.getBitValue(event, 5) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_19.getValue());
} else if (NumberUtil.getBitValue(event, 6) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_3.getValue());
} else if (NumberUtil.getBitValue(event, 7) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_0.getValue());
} else if (NumberUtil.getBitValue(event, 8) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_1.getValue());
} else if (NumberUtil.getBitValue(event, 9) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_20.getValue());
}else if (NumberUtil.getBitValue(event, 10) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_21.getValue());
}else if (NumberUtil.getBitValue(event, 11) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_22.getValue());
}else if (NumberUtil.getBitValue(event, 12) == 1) {
eventType = Integer.parseInt(EventTypeEnum.LockEvent_5.getValue());
}
//Device status
terminalStatus = byteBuf.readUnsignedShort();
//unlock times
lockTimes = byteBuf.readUnsignedShort();
//gateway status
int gatewayStatus = byteBuf.readUnsignedByte();
}
sensorData.setGpsTime(gpsZonedDateTime.toString());
sensorData.setLatitude(lat);
sensorData.setLongitude(lng);
sensorData.setLocationType(locationType);
sensorData.setSpeed(speed);
sensorData.setDirection(direction);
sensorData.setSensorID(slaveMachineId);
sensorData.setLockStatus(NumberUtil.getBitValue(terminalStatus, 0));
sensorData.setLockRope(NumberUtil.getBitValue(terminalStatus, 0));
sensorData.setLockTimes(lockTimes);
sensorData.setIndex(flowId);
sensorData.setVoltage(voltage);
sensorData.setPower(power);
sensorData.setRSSI(rssi);
sensorData.setDateTime(slaveMachineZonedDateTime.toString());
sensorData.setSensorType(sensorType);
sensorData.setTemperature(temperature);
sensorData.setHumidity(humidity);
sensorData.setEvent(eventType);
return sensorData;
}
/**
* Parse P45
* @param itemList
* @return
*/
private static LockEvent parseP45(List<String> itemList)
{
LockEvent model = new LockEvent();
model.DateTime= parseBcdTime(itemList.get(2) + itemList.get(3)).toString();
model.Latitude = Double.valueOf(itemList.get(4));
if (itemList.get(5).equals("S"))
{
model.Latitude = -model.Latitude;
}
model.Longitude = Double.valueOf(itemList.get(6));
if (itemList.get(5).equals("W"))
{
model.Longitude = -model.Longitude;
}
model.LocationType= itemList.get(8).equals("V") ? 0 : 1;
model.Speed= Double.valueOf(itemList.get(9)).intValue();
model.Direction = Integer.valueOf(itemList.get(10));
model.Event = Integer.valueOf(itemList.get(11));
//unlock verification
int status= Integer.valueOf(itemList.get(12));
model.RFIDNo = itemList.get(13);
//Dynamic password unlock
if (model.Event == 6)
{
if (status == 0)
{
//Incorrect unlock code
model.Status = 0;
}
else if (status > 0 && status <= 10)
{
//normal unlock
model.Status = 1;
//Fence ID when unlocking inside the fence
model.UnlockFenceID = status;
}
else if (status == 98)
{
//normal unlock
model.Status = 1;
}
else if (status == 99)
{
//The device has enabled unlocking within the fence, and the current unlocking is not within the fence, refusing to unlock
model.Status = 3;
}
}
else if (model.Event == 4)
{
if (Integer.valueOf(itemList.get(14)) == 0)
{
//Incorrect unlock code
model.Status = 0;
}
else
{
//normal unlock
model.Status = 1;
}
}
model.PsdErrorTimes = Integer.valueOf(itemList.get(15));
model.Index = Integer.valueOf(itemList.get(16));
if (itemList.size() > 17)
{
model.Mileage = Integer.valueOf(itemList.get(16));
}
return model;
}
/**
* Parse slave data temperature
*
* @param temperatureInt
* @return
*/
private static double parseTemperature(int temperatureInt) {
if (temperatureInt == 0xFFFF) {
return 9999.9;
}
double temperature = ((short) (temperatureInt << 4) >> 4) * 0.1;
if ((temperatureInt >> 12) > 0) {
temperature = -temperature;
}
return temperature;
}
/**
* Convert GPS time
*
* @param bcdTimeStr
* @return
*/
public static ZonedDateTime parseBcdTime(String bcdTimeStr) {
if(bcdTimeStr.equals("000000000000"))
{
//The default time given is January 1, 2000 00:00:00
bcdTimeStr="010100000000";
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyHHmmss");
LocalDateTime localDateTime = LocalDateTime.parse(bcdTimeStr, formatter);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneOffset.UTC);
return zonedDateTime;
}
/**
* Parse location data
* @param in
* @return
*/
public static Result decodeBinaryMessage(ByteBuf in)
{
//protocol header
in.readByte();
//DeviceID
byte[] terminalNumArr = new byte[5];
in.readBytes(terminalNumArr);
String terminalNum = ByteBufUtil.hexDump(terminalNumArr);
//Protocol version
int version = in.readUnsignedByte();
short tempByte = in.readUnsignedByte();
//Device type
int terminalType = tempByte >> 4;
//data type
int dataType = tempByte & 0b00001111;
//Data length
int dataLen = in.readUnsignedShort();
//GPS g time
byte[] timeArr = new byte[6];
in.readBytes(timeArr);
String bcdTimeStr = ByteBufUtil.hexDump(timeArr);
ZonedDateTime gpsZonedDateTime = parseBcdTime(bcdTimeStr);
//latitude
byte[] latArr = new byte[4];
in.readBytes(latArr);
String latHexStr = ByteBufUtil.hexDump(latArr);
double lat = 0.0;
BigDecimal latFloat = new BigDecimal(latHexStr.substring(2, 4) + "." + latHexStr.substring(4)).divide(new BigDecimal("60"), 6, RoundingMode.HALF_UP);
lat = new BigDecimal(latHexStr.substring(0, 2)).add(latFloat).doubleValue();
//longitude
byte[] lngArr = new byte[5];
in.readBytes(lngArr);
String lngHexStr = ByteBufUtil.hexDump(lngArr);
double lng=0.0;
BigDecimal lngFloat = new BigDecimal(lngHexStr.substring(3, 5) + "." + lngHexStr.substring(5, 9)).divide(new BigDecimal("60"), 6, RoundingMode.HALF_UP);
lng = new BigDecimal(lngHexStr.substring(0, 3)).add(lngFloat).doubleValue();
//bit indication
int bitFlag = Byte.parseByte(lngHexStr.substring(9, 10), 16);
//Positioning status
int locationType = (bitFlag & 0x01) > 0 ? 1 : 0;
//north latitude, south latitude
if ((bitFlag & 0b0010) == 0) {
lat = -lat;
}
//East longitude and West longitude
if ((bitFlag & 0b0100) == 0) {
lng = -lng;
}
//Speed
int speed = (int) (in.readUnsignedByte() * 1.85);
//Header(direction)
int direction = in.readUnsignedByte() * 2;
//Mileage
long mileage = in.readUnsignedInt();
//Number of GPS satellites
int gpsSignal = in.readByte();
//Bind vehicle ID
long vehicleId = in.readUnsignedInt();
//Device status
int terminalStatus = in.readUnsignedShort();
//Whether the base station is located
if (NumberUtil.getBitValue(terminalStatus, 0) == 1) {
locationType = 2;
}
//Battery indicator
int batteryPercent = in.readUnsignedByte();
//2G CELL ID
int cellId2G = in.readUnsignedShort();
//LAC
int lac = in.readUnsignedShort();
//GSM Signal quality
int cellSignal = in.readUnsignedByte();
//fence Alarm ID
int regionAlarmId = in.readUnsignedByte();
//Device status3
int terminalStatus3 = in.readUnsignedByte();
//Wakeup source
int fWakeSource=(terminalStatus3 & 0b0000_1111);
//reserved
in.readShort();
//IMEI No.
byte[] imeiArr = new byte[8];
in.readBytes(imeiArr);
String imei = ByteBufUtil.hexDump(imeiArr);
//3G CELL ID High 16 bits
int cellId3G = in.readUnsignedShort();
int cellId=0;
if(cellId3G>0){
cellId=(cellId3G<<16)+cellId2G;
}else{
cellId=cellId2G;
}
//MCC
int mcc = in.readUnsignedShort();
//MNC
int mnc = in.readUnsignedByte();
//Data serial number
int flowId = in.readUnsignedByte();
//Parse alarm
int fAlarm=parseLocationAlarm(terminalStatus);
LocationData location=new LocationData();
location.setProtocolType(version);
location.setDeviceType(terminalType);
location.setDataType(dataType);
location.setDataLength(dataLen);
location.setGpsTime(gpsZonedDateTime.toString());
location.setLatitude(lat);
location.setLongitude(lng);
location.setLocationType(locationType);
location.setSpeed(speed);
location.setDirection(direction);
location.setMileage(mileage);
location.setGpsSignal(gpsSignal);
location.setGSMSignal(cellSignal);
location.setAlarm(fAlarm);
location.setAlarmArea(regionAlarmId);
location.setBattery(batteryPercent);
location.setLockStatus(NumberUtil.getBitValue(terminalStatus, 7) == 1 ? 0 : 1);
location.setLockRope(NumberUtil.getBitValue(terminalStatus, 6) == 1 ? 0 : 1);
location.setBackCover(NumberUtil.getBitValue(terminalStatus, 13));
location.setMCC(mcc);
location.setMNC(mnc);
location.setLAC(lac);
location.setCELLID(cellId);
location.setIMEI(imei);
location.setAlarm(fWakeSource);
location.setIndex(flowId);
//Define the location data entity class
Result model = new Result();
model.setDeviceID(terminalNum);
model.setMsgType("Location");
model.setDataBody(location);
if (version < 0x19) {
model.setReplyMsg("(P35)");
} else {
model.setReplyMsg(String.format("(P69,0,%s)",flowId));
}
return model;
}
/**
* Analyze and locate alarms
* @param terminalStatus
* @return
*/
private static int parseLocationAlarm(int terminalStatus)
{
//Trigger alarm or not
int fAlarm = -1;
//Acknowledge or not
if (NumberUtil.getBitValue(terminalStatus, 5) == 1) {
//Judgment alarm
if (NumberUtil.getBitValue(terminalStatus, 1) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_9.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 2) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_10.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 3) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_1.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 4) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_2.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 8) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_3.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 9) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_4.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 10) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_5.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 11) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_6.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 12) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_7.getValue());
} else if (NumberUtil.getBitValue(terminalStatus, 14) == 1) {
fAlarm = Integer.parseInt(AlarmTypeEnum.LOCK_ALARM_8.getValue());
} else {
fAlarm = -1;
}
}
return fAlarm;
}
/**
* Command response reply
* @param msgType
* @param itemList
* @return
*/
private static String replyMessage(String msgType,List<String> itemList)
{
String replyContent = null;
switch (msgType)
{
case "P22":
ZonedDateTime currentDateTime = ZonedDateTime.now(ZoneOffset.UTC);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyHHmmss");
replyContent = String.format("(P22,%s)", currentDateTime.format(formatter));
break;
case "P43":
if (itemList.get(2).equals("0")) {
//reset Password
replyContent = String.format("(P44,1,888888)");
}
break;
case "P45":
replyContent = String.format("(P69,0,%s)", itemList.get(16));
break;
case "P52":
if (itemList.get(2).equals("2")) {
replyContent = String.format("(P52,2,%s)", itemList.get(3));
}
break;
default:
break;
}
return replyContent;
}
/**
* Command response reply
* @param msgType
* @param index
* @return
*/
public static String replyMessage(String msgType, int index)
{
String replyContent = null;
switch (msgType)
{
case "WLNET5":
case "WLNET7":
replyContent = String.format("(P69,0,{0})", index);
break;
default:
break;
}
return replyContent;
}
}
public method class CommonUtil
package com.jointech.sdk.jt701.utils;
import io.netty.buffer.ByteBuf;
import java.nio.ByteBuffer;
/**
* <p>Description:Used to store some public methods encountered in parsing </p>
*
* @author lenny
* @version 1.0.1
* @date 20210328
*/
public class CommonUtil {
private CommonUtil()
{
}
/**
* Unescaped text to transparently transmit data
*
* @param in
* @param frame
* @param bodyLen
*/
public static void unescape(ByteBuf in, ByteBuf frame, int bodyLen) {
int i = 0;
while (i < bodyLen) {
int b = in.readUnsignedByte();
if (b == 0x3D) {
int nextByte = in.readUnsignedByte();
if (nextByte == 0x14) {
frame.writeByte(0x3D ^ 0x14);
} else if (nextByte == 0x15) {
frame.writeByte(0x3D ^ 0x15);
} else if (nextByte == 0x00) {
frame.writeByte(0x3D ^ 0x00);
} else if (nextByte == 0x11) {
frame.writeByte(0x3D ^ 0x11);
} else {
frame.writeByte(b);
frame.writeByte(nextByte);
}
i += 2;
} else {
frame.writeByte(b);
i++;
}
}
}
/**
* remove last character from string
* @param inStr input string
* @param suffix characters to remove
* @return
*/
public static String trimEnd(String inStr, String suffix) {
while(inStr.endsWith(suffix)){
inStr = inStr.substring(0,inStr.length()-suffix.length());
}
return inStr;
}
/**
* Hexadecimal to byte[]
* @param hex
* @return
*/
public static byte[] hexStr2Byte(String hex) {
ByteBuffer bf = ByteBuffer.allocate(hex.length() / 2);
for (int i = 0; i < hex.length(); i++) {
String hexStr = hex.charAt(i) + "";
i++;
hexStr += hex.charAt(i);
byte b = (byte) Integer.parseInt(hexStr, 16);
bf.put(b);
}
return bf.array();
}
}
Parse constants
package com.jointech.sdk.jt701.constants;
import java.util.Arrays;
import java.util.List;
/**
* constant definition
* @author HyoJung
* @date 20210526
*/
public class Constant {
private Constant(){}
/**
* binary message header
*/
public static final byte BINARY_MSG_HEADER = '$';
/**
* text message header
*/
public static final byte TEXT_MSG_HEADER = '(';
/**
* text message trailer
*/
public static final byte TEXT_MSG_TAIL = ')';
/**
* text message separator
*/
public static final byte TEXT_MSG_SPLITER = ',';
/**
* Instructions for transparently transmitting binary data
*/
public static final List<String> WLNET_TYPE_LIST = Arrays.asList("5", "7");
}
2.4.Return message and description
(1)positioning data
Raw data:
2480405002251911003426032118530329532416031008941d0000000018070c0000000020e04f8b0c56001f00020f0f0f0f0f0f0f0f0f0f00f2028f0157
Return message:
{
"DeviceID": "8040500225",
"DataBody": {
"GpsTime": "2021-03-26T18:53:03Z",
"MNC": 1,
"BackCover": 1,
"Index": 87,
"Latitude": -29.88736,
"Awaken": 0,
"Direction": 0,
"Battery": 79,
"GpsSignal": 12,
"DataType": 1,
"AlarmArea": 0,
"Speed": 0,
"LockStatus": 0,
"Mileage": 6151,
"IMEI": "0f0f0f0f0f0f0f0f",
"MCC": 655,
"Longitude": 31.014902,
"LAC": 22016,
"DeviceType": 1,
"ProtocolType": 25,
"Alarm": 2,
"DataLength": 52,
"CELLID": 15895308,
"LockRope": 0,
"LocationType": 1,
"GSMSignal": 31
},
"ReplyMsg": "(P69,0,87)",
"MsgType": "Location"
}
Return message description
{
"DeviceID":DeviceID
"MsgType":message type, Here is: Location, which means location data,
"DataBody":message body
{
"ProtocolType": Protocol version,
"DeviceType": Device type,
"DataType": Data type number (1 means the real-time binary positioning data, 2 means alarm data, 3 means blind area regular binary positioning data, 4 means second-new binary positioning data)
"DataLength": Datalength,
"GpsTime": Positioning time (GMT time),
"Latitude": Latitude (dd.dddd format),
"Longitude": Longitude (dd.dddd format),
"LocationType": Positioning type (0: no positioning; 1: GPS positioning; 2: base station positioning),
"Speed": Speed (unit: km/h),
"Direction": Direction (0~360; 0 and 360 indicate true north direction),
"Mileage": Current mileage value (unit: km),
"GpsSignal": Number of GPS satellites,
"GSMSignal": GSM signal value,
"Alarm": Alarm type ( - 1: No alarm information; 1: Lock rope cut; 2: Vibration; 3: Long time unlocking; 4: Unlock password is wrong for 5 consecutive times; 5: Swipe illegal card; 6: Low battery; 7: Back cover opening ; 8: Motor struck; 9: Enter fence alarm; 10: Exit fence alarm),
"AlarmArea": If the alarm is related to the area, the value here is the area ID,
"Battery": Battery value ( 0~100; 255: charging),
"LockStatus": Lock motor status (1: ON; 0: OFF),
"LockRope": Lock rope status (1: unplugged; 0: inserted),
"BackCover": Back cover status (1: closed; 0: open),
"MCC": country code,
"MNC": carrier code,
"LAC": location area code,
"CELLID": base station number,
"IMEI": IMEI number, all 0F is invalid,
"Awaken": wakeup source ( 0 restart,
1: RTC wake-up, 2: Vibrate, 3: Open back cover, 4: insert/pull out lock rope, 5: Connect external power, 6: Swipe card, 7: Door sensor, 8: VIP SMS, 9: Non-VIP SMS or spam),
"Index": Data serial number
},
"ReplyMsg":Reply content (if it is an empty string, the platform no need to reply to this message)
}
(2)Sensors collect data(WLNET5)
Raw data(SensorType=1):
28383035303530303037332c312c3134312c574c4e45542c352c322c260321184709649672953949673d1408ff002603211847181020110986660133623c0100d71b00000029
Return message(SensorType=1):
{
"DeviceID": "8050500073",
"DataBody": {
"SensorID": "1020110986",
"SensorType": 1,
"Speed": 471,
"GpsTime": "2021-03-26T18:47:09Z",
"Temperature": 21.5,
"LockStatus": 1,
"Index": 102,
"Latitude": -65.612158,
"Direction": 0,
"Longitude": -395.61215,
"DateTime": "2021-03-26T18:47:18Z",
"RSSI": 60,
"Humidity": 27,
"Voltage": "3.07",
"LockTimes": -1,
"Event": -1,
"LockRope": 1,
"LocationType": 0,
"Power": 98
},
"ReplyMsg": "(P69,0,102)",
"MsgType": "WLNET5"
}
Raw data(SensorType=4):
28373030303331333330392C312C3038312C574C4E45542C352C322C05082115430722348250113550300F0000050821154304E0171E086925018D4E690400400000002A0029
Return message(SensorType=4):
{
"DeviceID": "7000313309",
"MsgType": "WLNET5",
"DataBody": {
"GpsTime": "2021-08-05T15:43:07",
"Latitude": 22.580416666666668,
"Longitude": 113.91716666666667,
"LocationType": 1,
"Speed": 0,
"Direction": 0,
"SensorID": "E0171E0869",
"LockStatus": 0,
"LockRope": 0,
"LockTimes": 42,
"Index": 37,
"Voltage": "3.97",
"Power": 78,
"RSSI": -105,
"DateTime": "2021-08-05T15:43:04",
"SensorType": 4,
"Temperature": 0.0,
"Humidity": 0,
"Event": 6
},
"ReplyMsg": "(P69,0,37)"
}
Return message description
{
"DeviceID": DeviceID,
"MsgType": message type, Here is: WLNET5, which means that the sensor transparently transmits data,
"DataBody": message body
{
"GpsTime": Positioning time (GMT time),
"Latitude": Latitude (dd.dddd format),
"Longitude": Longitude (dd.dddd format),
"LocationType": Positioning type (0: no positioning; 1: GPS positioning; 2: base station positioning),
"Speed": Speed (unit: km/h); 0xFF means invalid speed,
"Direction": direction (0~360; 0 and 360 indicate true north direction),
"SensorID":sensor ID,
"LockStatus": This is only valid if the slave type SensorType=4; 1: unlocked; 0: locked,
"LockRope": This is only valid if the slave type SensorType=4; 1: the lock rope is pulled out; 0: the lock rope is inserted,
"LockTimes": Number of unlocks (this value is only valid if SensorType=4),
"Index": data serial number,
"Voltage": Voltage value (unit: V),
"Power": Sensor power (0~100; 255: charging),
"RSSI":RSSI signal strength, the closer the negative number is to 0, the better the signal,
"DateTime": Data collection time (GMT time),
"SensorType": Sensor type (1: temperature and humidity sensor (JT126); 4: slave JT709;),
"Temperature":Temperature value (only valid if SensorType=1),
"Humidity": Humidity value (only valid if SensorType=1),
"Event": Event type (-1: no slave event; 0: lock event; 1: Bluetooth unlock event; 2: NFC unlock event; 3: Lora unlock event; 4: slave lock clipping alarm event; 5: key-press wake-up event; 6 : Timing reporting event; 7: Charging reporting event)
},
"ReplyMsg": Reply content (if it is an empty string, no need to reply to the message from platform))
}
(3)Lock event reporting data(P45)
Rawdata:
28373839303632393238342c5034352c3236303332312c3139343933392c32362e3237323033352c4e2c35302e3632313433352c452c412c302e30352c302c342c312c303030303030303030302c312c302c3129
Return messsage:
{
"DeviceID": "7890629284",
"MsgType": "P45",
"DataBody": {
"DateTime": "2021-03-26T19:49:39",
"Latitude": 26.272035,
"Longitude": 50.621435,
"LocationType": 1,
"Speed": 0,
"Direction": 0,
"Event": 4,
"Status": 1,
"UnlockFenceID": -1,
"RFIDNo": "0000000000",
"PsdErrorTimes": 0,
"Index": 1,
"Mileage": 0
},
"ReplyMsg": "(P69,0,1)"
}
Return message description:
{
"DeviceID": Device ID,
"MsgType": The message type, here is: P45, which means the switch lock event data upload,
"DataBody": message body
{
"DateTime": event time (GMT time),
"Latitude": Latitude (dd.dddd format),
"Longitude": Longitude (dd.dddd format),
"LocationType": Positioning type (0: no positioning; 1: GPS positioning; 2: base station positioning),
"Speed": Speed (unit: km/h),
"Direction": direction (0~360; 0 and 360 indicate true north direction),
"Event": Event type (1: means swiping authorization card; 2: means swiping illegal card; 3: means swiping vehicle ID card binding; 4: means unlocking with password; 5: means terminal automatic lock record; 6: in dynamic password fence unlock; 7: Bluetooth unlock),
"Status": Unlock verification (0: the unlock password is incorrect; 1: normal unlock; 2: because the fence is unlocked, it is not unlocked in the fence, and the unlock is rejected),
"UnlockFenceID": (-1: Unlocking has nothing to do with the fence; 1~10: Identifies the corresponding unlocking fence ID),
"RFIDNo": Swipe card number; if not "0000000000", it is invalid,
"PsdErrorTimes": Number of incorrect unlock passwords,
"Index": data serial number,
"Mileage": Current mileage value (unit: km)
},
"ReplyMsg": Reply content (if it is an empty string, there is no need to reply to the message)
}
(4)Other commands reply data
Raw data:
28373839303632393238342c50333529
return message:
{
"DeviceID": "7890629284",
"MsgType": "P35",
"DataBody": "(7890629284,P35)",
"ReplyMsg": ""
}
Return message description:
{
"DeviceID": Device ID,
"MsgType": Message type (see more message types and descriptions, please refer to 3. Message types and message body content description),
"DataBody": The content of the message body (except for the location data: Location; the sensor transparent transmission data: WLNET5; the lock event report: P45; the ASCII strings of the command content are directly returned here),
"ReplyMsg": (If it is an empty string, there is no need to reply to the message)
}