1.Jar包下载

jt701-sdk-1.0.0.jar 下载地址
如果需要Jar包开发源码,请与商务申请


2.集成开发说明

2.1.集成开发语言及框架说明

jt701-sdk-1.0.0.jar是基于Java语言,SpringBoot2.x框架,使用到了netty,fastjson,lombok

BaseEnum:基础枚举
Constant:自定义常量
AlarmTypeEnum:报警枚举
EventTypeEnum:事件枚举
LocationData:定位实体类
LockEvent:锁事件实体类
Result:结果实体类
SensorData:从机数据实体类
CommonUtil:公共方法类
NumberUtil:数字操作工具类
ParserUtil:解析方法工具类
DataParser:解析主方法

2.2.集成说明

将jt701-sdk-1.0.0.jar引入到自己的网关程序中,引入方法如下:
在pom.xml引入jar包

        <dependency>
            <groupId>com.jointech.sdk</groupId>
            <artifactId>jt701-sdk</artifactId>
            <version>1.0.0</version>
        </dependency>

调用jt701-sdk-1.0.0.jar,DataParser类中receiveData()方法
receiveData()方法是重载方法

    /**
     * 解析Hex字符串原始数据
     * @param strData 16进制字符串
     * @return
     */
    public static Object receiveData(String strData)
    {
        ByteBuf msgBodyBuf = ByteBufAllocator.DEFAULT.heapBuffer(strData.length()/2);
        msgBodyBuf.writeBytes(CommonUtil.hexStr2Byte(strData));
        return receiveData(msgBodyBuf);
    }

    /**
     * 解析byte[]原始数据
     * @param bytes
     * @return
     */
    private static Object receiveData(byte[] bytes)
    {
        ByteBuf msgBodyBuf =ByteBufAllocator.DEFAULT.heapBuffer(bytes.length);
        msgBodyBuf.writeBytes(bytes);
        return receiveData(msgBodyBuf);
    }

    /**
     * 解析ByteBuf原始数据
     * @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.核心代码

解析方法工具类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: 解析方法工具类</p>
 * @author HyoJung
 * @date 20210526
 */
public class ParserUtil {
    private ParserUtil()
    {}

    /**
     * 解析指令数据
     * @param in 原始数据
     * @return
     */
    public static Result decodeTextMessage(ByteBuf in)
    {
        //定义定位数据实体类
        Result model = new Result();
        //包头(
        in.readByte();
        //字段列表
        List<String> itemList = new ArrayList<String>();
        //透传的二进制数据
        ByteBuf msgBody = null;
        while (in.readableBytes() > 0) {
            //无线网关数据上传(WLNET5、WLNET7)第7个字段以及后面为二进制数据
            if (itemList.size() >= 6 && Objects.equals("WLNET", itemList.get(3)) && Constant.WLNET_TYPE_LIST.contains(itemList.get(4))) {
                //到结尾")"前的长度
                int lastItemLen = in.readableBytes() - 1;
                //反转义
                msgBody = Unpooled.buffer(lastItemLen);
                CommonUtil.unescape(in, msgBody, lastItemLen);
                in.readByte();
            } else {
                //查询逗号的下标截取数据
                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消息类型为组合
        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;
    }

    /**
     * 解析从机数据
     * @param byteBuf
     * @return
     */
    private static SensorData parseWlnet5(ByteBuf byteBuf) {
        SensorData sensorData = new SensorData();
        //定位时间
        byte[] timeArr = new byte[6];
        byteBuf.readBytes(timeArr);
        String bcdTimeStr = ByteBufUtil.hexDump(timeArr);
        ZonedDateTime gpsZonedDateTime = parseBcdTime(bcdTimeStr);
        //纬度
        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();
        //经度
        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();
        //位指示
        int bitFlag = Byte.parseByte(lngHexStr.substring(9, 10), 16);
        //定位状态
        int locationType = (bitFlag & 0x01) > 0 ? 1 : 0;
        //北纬、南纬
        if ((bitFlag & 0b0010) == 0) {
            lat = -lat;
        }
        //东经、西经
        if ((bitFlag & 0b0100) == 0) {
            lng = -lng;
        }
        //速度
        int speed = (int) (byteBuf.readUnsignedByte() * 1.85);
        //方向
        int direction = byteBuf.readUnsignedByte() * 2;

        //从机时间
        byte[] slaveMachineTimeArr = new byte[6];
        byteBuf.readBytes(slaveMachineTimeArr);
        String slaveMachineBcdTimeStr = ByteBufUtil.hexDump(slaveMachineTimeArr);
        ZonedDateTime slaveMachineZonedDateTime = parseBcdTime(slaveMachineBcdTimeStr);
        //从机ID
        byte[] slaveMachineIdArr = new byte[5];
        byteBuf.readBytes(slaveMachineIdArr);
        String slaveMachineId = ByteBufUtil.hexDump(slaveMachineIdArr).toUpperCase();
        //从机数据流水号
        int flowId = byteBuf.readUnsignedByte();
        //从机电压
        String voltage = new BigDecimal(byteBuf.readUnsignedShort()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP).toString();
        //从机电量
        int power = byteBuf.readUnsignedByte();
        //RSSI
        int rssi = byteBuf.readUnsignedByte();
        //传感器类型
        int sensorType = byteBuf.readUnsignedByte();
        //温度值
        double temperature = -1000.0;
        //湿度值
        int humidity = 0;
        //事件类型
        int eventType = -1;
        //设备状态
        int terminalStatus = -1;
        //开关锁次数
        int lockTimes = -1;
        if (sensorType == 1) {
            //温度
            temperature = parseTemperature(byteBuf.readShort());
            //湿度
            humidity = byteBuf.readUnsignedByte();
            //网关保存数据条数
            int itemCount = byteBuf.readUnsignedShort();
            //网关状态
            int gatewayStatus = byteBuf.readUnsignedByte();
        } else if (sensorType == 4) {
            //事件
            int event = byteBuf.readUnsignedShort();
            //判断事件
            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());
            }
            //设备状态
            terminalStatus = byteBuf.readUnsignedShort();
            //开关锁次数
            lockTimes = byteBuf.readUnsignedShort();
            //网关状态
            int gatewayStatus = byteBuf.readUnsignedByte();
        }else if (sensorType == 5||sensorType == 6)
        {
            //事件
            int event = byteBuf.readUnsignedShort();
            //判断事件
            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());
            }
            //设备状态
            terminalStatus = byteBuf.readUnsignedShort();
            //开关锁次数
            lockTimes = byteBuf.readUnsignedShort();
            //网关状态
            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;
    }

    /**
     * 解析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));
        //开锁验证
        int status= Integer.valueOf(itemList.get(12));
        model.RFIDNo = itemList.get(13);
        //动态密码开锁
        if (model.Event == 6)
        {
            if (status == 0)
            {
                //开锁密码不正确
                model.Status = 0;
            }
            else if (status > 0 && status <= 10)
            {
                //正常开锁
                model.Status = 1;
                //围栏内开锁时候的围栏ID
                model.UnlockFenceID = status;
            }
            else if (status == 98)
            {
                //正常开锁
                model.Status = 1;
            }
            else if (status == 99)
            {
                //设备开启了围栏内开锁,且当前开锁并未在围栏内,拒绝开锁
                model.Status = 3;
            }
        }
        else if (model.Event == 4)
        {
            if (Integer.valueOf(itemList.get(14)) == 0)
            {
                //开锁密码不正确
                model.Status = 0;
            }
            else
            {
                //正常开锁
                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;
    }

    /**
     * 解析从机数据温度
     *
     * @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;
    }

    /**
     * 转换GPS时间
     *
     * @param bcdTimeStr
     * @return
     */
    public static ZonedDateTime parseBcdTime(String bcdTimeStr) {
        if(bcdTimeStr.equals("000000000000"))
        {
            //默认给出时间为2000年1月1日 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;
    }

    /**
     * 解析定位数据
     * @param in
     * @return
     */
    public static Result decodeBinaryMessage(ByteBuf in)
    {
        //协议头
        in.readByte();
        //终端号码
        byte[] terminalNumArr = new byte[5];
        in.readBytes(terminalNumArr);
        String terminalNum = ByteBufUtil.hexDump(terminalNumArr);
        //协议版本号
        int version = in.readUnsignedByte();
        short tempByte = in.readUnsignedByte();
        //终端类型号
        int terminalType = tempByte >> 4;
        //数据类型号
        int dataType = tempByte & 0b00001111;
        //数据长度
        int dataLen = in.readUnsignedShort();
        //定位时间
        byte[] timeArr = new byte[6];
        in.readBytes(timeArr);
        String bcdTimeStr = ByteBufUtil.hexDump(timeArr);
        ZonedDateTime gpsZonedDateTime = parseBcdTime(bcdTimeStr);
        //纬度
        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();
        //经度
        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();
        //位指示
        int bitFlag = Byte.parseByte(lngHexStr.substring(9, 10), 16);
        //定位状态
        int locationType = (bitFlag & 0x01) > 0 ? 1 : 0;
        //北纬、南纬
        if ((bitFlag & 0b0010) == 0) {
            lat = -lat;
        }
        //东经、西经
        if ((bitFlag & 0b0100) == 0) {
            lng = -lng;
        }
        //速度
        int speed = (int) (in.readUnsignedByte() * 1.85);
        //方向
        int direction = in.readUnsignedByte() * 2;
        //里程
        long mileage = in.readUnsignedInt();
        //GPS卫星个数
        int gpsSignal = in.readByte();
        //绑定车辆ID
        long vehicleId = in.readUnsignedInt();
        //终端状态
        int terminalStatus = in.readUnsignedShort();
        //是否基站定位
        if (NumberUtil.getBitValue(terminalStatus, 0) == 1) {
            locationType = 2;
        }
        //电量指示
        int batteryPercent = in.readUnsignedByte();
        //2G CELL ID
        int cellId2G = in.readUnsignedShort();
        //LAC
        int lac = in.readUnsignedShort();
        //GSM信号质量
        int cellSignal = in.readUnsignedByte();
        //区域报警ID
        int regionAlarmId = in.readUnsignedByte();
        //设备状态3
        int terminalStatus3 = in.readUnsignedByte();
        //唤醒源
        int fWakeSource=(terminalStatus3 & 0b0000_1111);
        //预留
        in.readShort();
        //IMEI号
        byte[] imeiArr = new byte[8];
        in.readBytes(imeiArr);
        String imei = ByteBufUtil.hexDump(imeiArr);
        //3G CELL ID 高16位
        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();
        //流水号
        int flowId = in.readUnsignedByte();
        //解析报警
        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);
        //定义定位数据实体类
        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;
    }

    /**
     * 解析定位报警
     * @param terminalStatus
     * @return
     */
    private static int parseLocationAlarm(int terminalStatus)
    {
        //是否报警
        int fAlarm = -1;
        //是否应答确认
        if (NumberUtil.getBitValue(terminalStatus, 5) == 1) {
            //判断报警
            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;
    }

    /**
     * 指令应答回复
     * @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")) {
                    //密码重置
                    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;
    }

    /**
     * 指令应答回复
     * @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;
    }
}

公共方法类CommonUtil

package com.jointech.sdk.jt701.utils;

import io.netty.buffer.ByteBuf;

import java.nio.ByteBuffer;

/**
 * <p>Description: 用来存储一些解析中遇到的公共方法</p>
 *
 * @author lenny
 * @version 1.0.1
 * @date 20210328
 */
public class CommonUtil {
    private CommonUtil()
    {

    }

    /**
     * 反转义文本透传数据
     *
     * @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++;
            }
        }
    }

    /**
     * 去掉字符串最后一个字符
     * @param inStr 输入的字符串
     * @param suffix 需要去掉的字符
     * @return
     */
    public static String trimEnd(String inStr, String suffix) {
        while(inStr.endsWith(suffix)){
            inStr = inStr.substring(0,inStr.length()-suffix.length());
        }
        return inStr;
    }

    /**
     * 16进制转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();
    }
}

解析常量Constant

package com.jointech.sdk.jt701.constants;

import java.util.Arrays;
import java.util.List;

/**
 * 常量定义
 * @author HyoJung
 * @date 20210526
 */
public class Constant {
    private Constant(){}
    /**
     * 二进制消息包头
     */
    public static final byte BINARY_MSG_HEADER = '$';

    /**
     * 文本消息包头
     */
    public static final byte TEXT_MSG_HEADER = '(';

    /**
     * 文本消息包尾
     */
    public static final byte TEXT_MSG_TAIL = ')';

    /**
     * 文本消息分隔符
     */
    public static final byte TEXT_MSG_SPLITER = ',';

    /**
     * 透传二进制数据的指令
     */
    public static final List<String> WLNET_TYPE_LIST = Arrays.asList("5", "7");
}

2.4.返回消息及说明

(1)定位数据
原始数据:

2480405002251911003426032118530329532416031008941d0000000018070c0000000020e04f8b0c56001f00020f0f0f0f0f0f0f0f0f0f00f2028f0157

返回消息:

{
    "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"
}

返回消息描述

{
    "DeviceID":设备ID
    "MsgType":消息类型, 此处为: Location,表示定位数据,
    "DataBody":消息体内容 
    {
        "ProtocolType": 协议版本号,
        "DeviceType": 终端类型号,
        "DataType": 数据类型号( 1 表明最新二进制定位数据, 2 表示报警数据, 3 表示盲区常规二进制定位数据, 4 表示次新二进制定位数据),
        "DataLength": 数据长度,
        "GpsTime": 定位时间( GMT时间),
        "Latitude": 纬度(dd.dddd格式),
        "Longitude": 经度(dd.dddd格式),
        "LocationType": 定位类型( 0: 不定位; 1: GPS定位; 2: 基站定位),
        "Speed": 速度( 单位: km / h),
        "Direction": 方向( 0~360; 0 与360表示正北方向),
        "Mileage": 当前里程值(单位:km),
        "GpsSignal": GPS卫星个数,
        "GSMSignal": GSM信号值,
        "Alarm": 报警类型( - 1: 无告警信息; 1: 锁绳剪断; 2: 震动; 3: 长时间开锁; 4: 开锁密码连续5次错误; 5: 刷非法卡; 6: 低电量; 7: 开后盖; 8: 卡锁; 9: 进区域报警; 10: 出区域报警),
        "AlarmArea": 如果告警与区域有关, 则此处值为区域的ID,
        "Battery": 电量值( 0~100; 255: 充电中),
        "LockStatus": 锁电机状态( 1: 开; 0: 关),
        "LockRope": 锁绳状态( 1: 拔出; 0: 插入),
        "BackCover": 后盖状态( 1: 关闭; 0: 开启),
        "MCC": 国家代码,
        "MNC": 运营商代码,
        "LAC": 位置区域码,
        "CELLID": 基站编号,
        "IMEI": IMEI号码, 全是0F无效,
        "Awaken": 唤醒源( 0 重启,
        1: RTC唤醒, 2: 震动, 3: 开后盖, 4: 锁绳, 5: 接外电, 6: 刷卡, 7: 门磁, 8: VIP短信, 9: 非VIP短信或垃圾短信),
        "Index": 数据流水号
    },
    "ReplyMsg":回复内容( 如果为空字符串, 则不需要给终端回复内容)
}

(2)传感器采集数据(WLNET5)
原始数据(SensorType=1):

28383035303530303037332c312c3134312c574c4e45542c352c322c260321184709649672953949673d1408ff002603211847181020110986660133623c0100d71b00000029

返回消息(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"
}

原始数据(SensorType=4):

28373030303331333330392C312C3038312C574C4E45542C352C322C05082115430722348250113550300F0000050821154304E0171E086925018D4E690400400000002A0029

返回消息(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)"
}

返回消息描述

{
    "DeviceID": 设备ID,
    "MsgType": 消息类型, 此处为: WLNET5,表示传感器透传数据,
    "DataBody": 消息体内容
    {
        "GpsTime": 定位时间(GMT时间),
        "Latitude": 纬度(dd.dddd格式),
        "Longitude": 经度(dd.dddd格式),
        "LocationType": 定位类型( 0: 不定位; 1: GPS定位; 2: 基站定位),
        "Speed": 速度( 单位: km / h);0xFF表示速度无效,
        "Direction": 方向( 0~360; 0 与360表示正北方向),
        "SensorID": 传感器ID,
        "LockStatus": 如果从机类型SensorType=4,此是才有效;1:开锁;0:关锁,
        "LockRope": 如果从机类型SensorType=4,此是才有效;1:锁绳拔出;0:锁绳插入,
        "LockTimes": 开锁次数(如果SensorType=4此值才有效),
        "Index": 数据流水号,
        "Voltage": 电压值(单位:V),
        "Power": 传感器电量(0~100;255: 充电中),
        "RSSI": RSSI信号强度,是负数越接近0信号越好,
        "DateTime": 数据采集时间(GMT时间),
        "SensorType": 传感器类型(1:温湿度传感器(JT126);4:从机JT709;),
        "Temperature":温度值(如果SensorType=1此值才有效),
        "Humidity": 湿度值(如果SensorType=1此值才有效),
        "Event": 事件类型(-1:无从机事件;0:关锁事件;1:蓝牙开锁事件;2:NFC开锁事件;3:Lora开锁事件;4:从机锁剪断报警事件;5:按键唤醒事件;6:定时上报事件;7:充电上报事件)
    },
    "ReplyMsg": 回复内容(如果为空字符串,则不需要给终端回复内容)
}

(3)锁事件上报数据(P45)
原始数据:

28373839303632393238342c5034352c3236303332312c3139343933392c32362e3237323033352c4e2c35302e3632313433352c452c412c302e30352c302c342c312c303030303030303030302c312c302c3129

返回消息:

{
    "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)"
}

返回消息描述:

{
    "DeviceID": 设备ID,
    "MsgType": 消息类型, 此处为: P45,表示开关锁事件数据上传,
    "DataBody": 消息体内容
    {
        "DateTime": 事件时间(GMT时间),
        "Latitude": 纬度(dd.dddd格式),
        "Longitude": 经度(dd.dddd格式),
        "LocationType": 定位类型( 0: 不定位; 1: GPS定位; 2: 基站定位),
        "Speed": 速度( 单位: km / h),
        "Direction": 方向( 0~360; 0 与360表示正北方向),
        "Event": 事件类型(1:表示刷授权卡;2:表示刷非法卡;3:表示刷车辆ID卡绑定;4:表示为凭密码开锁;5:表示终端自动关锁记录;6: 动态密码围栏内开锁;7: 蓝牙开锁),
        "Status": 开锁验证(0:开锁密码不正确;1:正常开锁;2:因为开启了围栏开锁,未在围栏内开锁,开锁被拒绝),
        "UnlockFenceID": (-1:开锁与围栏无关;1~10:标识对应的开锁围栏ID),
        "RFIDNo": 刷卡卡号;如果未“0000000000”,则无效,
        "PsdErrorTimes": 开锁密码错误次数,
        "Index": 数据流水号,
        "Mileage": 当前里程值(单位:km)
    },
    "ReplyMsg": 回复内容(如果为空字符串,则不需要给终端回复内容)
}

(4)其他指令回复数据
原始数据:

28373839303632393238342c50333529

返回消息:

{
    "DeviceID": "7890629284",
    "MsgType": "P35",
    "DataBody": "(7890629284,P35)",
    "ReplyMsg": ""
}

返回消息描述:

{
    "DeviceID": 设备ID,
    "MsgType": 消息类型(参见更多的消息类型及其描述,请参阅3.消息类型及消息体内容描述),
    "DataBody": 消息体内容(除定位数据:Location;传感器透传数据:WLNET5;锁事件上报:P45外;其他此处均直接返回指令内容的ASCII字符串),
    "ReplyMsg": 回复内容(如果为空字符串,则不需要给终端回复内容)
}

3.消息类型及消息体内容描述

3.1.P01:查询终端当前的版本号

消息体内容:(示例)
(7591225008,P01,JT701D_20200720_China_Jointech_SIM7600,77%)
消息体内容描述:
7591225008:设备ID
P01:消息类型
JT701D_20200720_China_Jointech_SIM7600:协议版本
77%:当前设备电量

P03:低电休眠控制

消息体内容:(示例)
(7560704001,P03,1,30)
消息体描述:
7560704001:设备ID
P03:消息类型
1:生效;0:不生效
30:设置电量低于30的时候进入休眠,默认31%,可设定范围5%~90%

P04:设置/查询数据上传间隔和休眠自动唤醒间隔

消息体内容:(示例)
(7570101998,P04,30,30)
消息体描述:
7570101998:设备ID
P04:消息类型
30:数据上传间隔,单位秒钟,默认30秒,取值范围5-600
30:休眠自动唤醒间隔,单位分钟,默认30分钟,取值范围30-1440

P06:设置/查询监控中心IP与端口、APN

消息体内容:(示例)
(7570101998,P06,211.162.111.225,10906,CMNET,user,password,1)
消息体描述:
7570101998:设备ID
P06:消息类型
211.162.111.225:监控中心的IP地址
10906:监控中心端口地址,最大65530
CMNET:接入点名称(最长50个字节)
User:APN用户名(最长50个字节)
Password:APN密码(最长50个字节)
1:0表示卡1,1表示卡2

P10:设置/查询终端使用地点与国际标准时间的时差

消息体内容:(示例)
(7570101998,P10,480)
消息体描述:
7570101998:设备ID
P10:消息类型
480:时差值,以分钟为单位.如北京时间与标准时时差为8小时,即为480分钟,取值范围-12*60-13*60,默认0

P11:设置/查询VIP手机号码

消息体内容:(示例)
(7570101998,P11,1,8613910102345)
消息体描述:
7570101998:设备ID
P11:消息类型
1:VIP手机号码索引,取值为1-5,允许有五组VIP手机号码
8613910102345:手机号码,不能超过15位数字,前面需加国际区号,中国为86或者+86.

P12:设置/查询VIP号码是否允许报警

消息体内容:(示例)
(7570101998,P12,1,1,1,1,1)
消息体描述:
7570101998:设备ID
P12:消息类型
1,1,1,1,1:分别对应5个VIP号码是否允许报警;1表示允许对应的VIP号码报警,0表示不允许此VIP号码报警

P13:恢复出厂设置

消息体内容:(示例)
(7570101998,P13)
消息体描述:
7570101998:设备ID
P13:消息类型

P14:读取终端的IMEI号

消息体内容:(示例)
(7570101998,P14,012207004451636)
消息体描述:
7570101998:设备ID
P14:消息类型
012207004451636:终端的IMEI号

P15:终端重启指令

消息体内容:(示例)
(7570101998,P15)
消息体描述:
7570101998:设备ID
P15:消息类型

P22:GPS无效的时候,监控中心对终端授时

消息体内容:(示例)
(7570101998,P22,1)
消息体描述:
7570101998:设备ID
P22:消息类型
1:1表示授时成功,0表示失败,2表示主动请求授时

P22:设置/取消短信、电话可唤醒工作模式

消息体内容:(示例)
(7570101998,P23,1)
消息体描述:
7570101998:设备ID
P23:消息类型
1:1表示设置成功,0表示设置失败.

P24:区域是否有效,及区域名称设置指令

消息体内容:(示例)
(7570101998,P24,10,1,area10)
消息体描述:
7570101998:设备ID
P24:消息类型
10:表示第10个区域.
1:表示有效 ,0表示无效
area10:表示区域名称,最大长度为16个字节.

P29:设置或者查询区域的详细节点信息

消息体内容:(示例)
(7570101998,P29,8,15,1,10,11323.1234…)
消息体描述:
7570101998:设备ID
P29:消息类型
8:表示第八个区域
15:表示总点数
1:表示当前页
10:表示当前页的点数.余下的为各个点的经度与纬度

P30:清除相关的区域

消息体内容:(示例)
(7570101998,P30,1)
消息体描述:
7570101998:设备ID
P30:消息类型
1:1表示清除成功,0表示清除失败.

P31:区域信息设置完毕

消息体内容:(示例)
(7570101998,P31)
消息体描述:
7570101998:设备ID
P31:消息类型

P32:主动进入休眠指令

消息体内容:(示例)
(7570101998,P32)
消息体描述:
7570101998:设备ID
P32:消息类型

P37:查询/设置G-sensor相关参数

消息体内容:(示例)
(7570101998,P37,500)
消息体描述:
7570101998:设备ID
P37:消息类型
500:运动检测门限值,范围是63到500,单位是mg;如果设置为0则为关闭G-sensor相关全部功能;关闭G-sensor功能后,如需重新开启G-sensor功能只需重新设置有效的G-sensor参数即可.默认值126

P38:开锁报警时间间隔设置指令

消息体内容:(示例)
(7570101998,P38,120)
消息体描述:
7570101998:设备ID
P38:消息类型
120:开锁报警时间间隔设置,即从锁电机处于开锁状态时刻算起,如果该状态持续保持超过120分钟,则可触发开锁报警,范围是3到180,单位是分钟;默认为120分钟.

P40:查询/设置GPRS通道和短消息通道的报警开关

消息体内容:(示例)
(7570101998,P40,1,1,1,1,1,1,1,1,1,1,1)
消息体描述:
7570101998:设备ID
P40:消息类型
1,1,1,1,1,1,1,1,1,1,1:从左至右依次为锁挂绳剪断报警、刷非法卡报警、开锁状态保持一段时间报警、指令开锁密码连续输错5次报警、震动报警、进区域报警、出区域报警的开关、低电报警、开后盖报警、卡锁报警;每个报警开关参数可以取值为0,1,2,3,并且可以任意组合,0表示GPRS和SMS报警都关闭,1表示只开启GPRS报警,2表示只开启SMS报警,3表示GPRS和SMS报警都开启.

P41:增删开锁授权号指令

消息体内容:(示例1)
(7570101998,P41,1,30)
消息体描述:
7570101998:设备ID
P41:消息类型
1:1表示增加授权卡号操作;2表示删除授权号,3表示删除所有的授权号
30:30表示当前已存授权卡号总个数;

消息体内容:(示例2)
(7570101998,P41,2,3,0013953759, 0013953758, 0013953757)
消息体描述:
7570101998:设备ID
P41:消息类型
2:查询第2组数据;一共分3组,分别为1~3,查询时每次最多返回20个ID号
3:3表示有3个ID号
0013953759, 0013953758, 0013953757表示该组存储的授权号列表

P42:现场刷卡授权模式配置指令

消息体内容:(示例1)
(7570101998,P42,0)
消息体描述:
7570101998:设备ID
P42:消息类型
1:1表示打开批量增加终端开锁授权号功能, 0表示关闭批量增加终端开锁授权号功能。

消息体内容:(示例2)
(7570101998,P41,2,0013953759,0013953751)
消息体描述:
7570101998:设备ID
P42:消息类型
2:表示终端已存了2个开锁授权号.
0013953759,0013953751:授权卡号.

P44:远程开锁密码修改指令

消息体内容:(示例1)
(7570101998,P44,1)
消息体描述:
7570101998:设备ID
P44:消息类型
1:1:表示修改密码是否成功,1表示成功,0表示失败。

消息体内容:(示例2)
(7570101998,P44,888888)
消息体描述:
7570101998:设备ID
P44:消息类型
888888:当前的设备可开锁的动态密码

P50:电源开关生效控制设置

消息体内容:(示例)
(7570101998,P50,1)
消息体描述:
7570101998:设备ID
P44:消息类型
1:1表示开关有效,默认是1;0表示停用开关.

P52:动态密码指令

消息体内容:(示例1)
(7570101998,P52,0,405935,326387)
消息体描述:
7570101998:设备ID
P52:消息类型
0:指令操作;查询当前产生的动态密码和当前用来开锁的动态密码
405935:表示,还没有被系统确认的动态密码
326387:表示目前用来开锁的动态密码

消息体内容:(示例2)
(7570101998,P52,1,1,0)
消息体描述:
7570101998:设备ID
P52:消息类型
1:1表示设置动态密码功能
1:1查询是否开启动态密码功能;0:表示关闭动态密码功能
0:1表示动态密码开锁必须在区域内才能开锁,即表明如果想要开锁,必须设置区域,0表示动态密码开锁跟区域无关,只要符合动态密码开锁的其它条件就可以开锁

消息体内容:(示例3)
(7570101998,P52,2,405935)
消息体描述:
7570101998:设备ID
P52:消息类型
2:回复上传的动态密码确认指令
405935:需要被确认的动态密码

消息体内容:(示例4)
(7570101998,P52,3,1,0)
消息体描述:
7570101998:设备ID
P52:消息类型
3:发送动态密码开锁
1:1,代表成功,0是失败
0:代表失败次数

P54:查询/设置是否关闭休眠模式指令(设备不休眠)

消息体内容:(示例)
(7570101998,P54,0,0)
消息体描述:
7570101998:设备ID
P54:消息类型
0:0 查询;1 设置
0:0 需要休眠 , 1 开启不休眠

P58:查询和设置RFID卡是否关联电子围栏 (默认关联电子围栏)

消息体内容:(示例)
(7570101998,P58,1,1)
消息体描述:
7570101998:设备ID
P58:消息类型
1:1表示设置,0表示查询
1:1:关联电子围栏,必须在区域内才能刷卡开锁;0表示刷卡开锁跟区域无关,只要符刷卡开锁的条件就可以开锁

P61:设置或查询电量低报警提示的阀值

消息体内容:(示例)
(7570101998,P61,30)
消息体描述:
7570101998:设备ID
P61:消息类型
30:当前阀值

P62:设置或查询里程统计相关参数

消息体内容:(示例)
(7570101998,P62,1,10)
消息体描述:
7570101998:设备ID
P62:消息类型
1:操作参数类型;1:设置一个速度值,低于这个速度里程不会统计;2:同步当前设备里程值
10:当操作参数类型为1,此时为速度值,单位km/h;当操作参数类型为2,此时为里程值,单位km

P63:静态飘移处理功能设置

消息体内容:(示例)
(7570101998,P63,1)
消息体描述:
7570101998:设备ID
P63:消息类型
1:1开启,0关闭(默认)

P68:查询SIM卡的IMSI/ICCID号

消息体内容:(示例)
(7570101998,P65,2,898600220909A0206023)
消息体描述:
7570101998:设备ID
P65:消息类型
2:1:查询IMSI, 2:查询ICCID
898600220909A0206023:SIM卡的IMSI/ICCID号

P70:启用/关闭VIP号码功能

消息体内容:(示例)
(7570101998,P70,1)
消息体描述:
7570101998:设备ID
P70:消息类型
1:0:关闭状态;1:开启状态

WLNET1:查询/设置要监听的从机设备ID号

消息体内容:(示例)
(700160818000,1,001,WLNET,1,20,0217270000,,,,,,,,,)
消息体描述:
700160818000:设备ID
WLNET,1:组合消息类型WLNET1
20:表示当前配置20个从机设备ID号,如果为配置0个ID号表示清除所有配置的ID号
0217270000,,,,,,,,,:从机ID号

WLNET2:查询/设置从机工作时间间隔

消息体内容:(示例)
(700160818000,1,001,WLNET,2,20)
消息体描述:
700160818000:设备ID
WLNET,2:组合消息类型WLNET2
20:20:从机工作时间间隔为20分钟,单位分钟,最小1分钟,最大1440一天,默认5分钟

WLNET3:查询/设置从机发送功率

消息体内容:(示例)
(700160818000,1,001,WLNET,3,2)
消息体描述:
700160818000:设备ID
WLNET,3:组合消息类型WLNET3
2:从机从机发送功率,1~3分别是低中高三个发送功率模式,默认是1低功率

WLNET4:查询/设置从机发送功率

消息体内容:(示例)
(700160818000,1,001,WLNET,4,170828,170829)
消息体描述:
700160818000:设备ID
WLNET,4:组合消息类型WLNET4
170828:网关版本
170829:传感器的软件版本

WLNET6:查询/设置从机温度门限参数

消息体内容:(示例)
(700160818000,1,001,WLNET,6,1,2,10,120,30,15,12)
消息体描述:
700160818000:设备ID
WLNET,6:组合消息类型WLNET6
1:指令功能:0表示查询;1:表示设置
2:参数类型:1表示温度相关参数,2表示设置数据上传方式
10:低温门限值:默认0值无效,温度以1度为单位10~175有效,-40~125度,门限值 – 50 = 实际值,如10- 50 = -40℃。
120:高温门限值:默认0值无效,温度以1度为单位10~175有效,-40~125度,门限值 – 50 = 实际值,如120- 50 = 70℃
30:温度变化时间值:多长时间内温度变化多少的时间值,单位分钟,默认0值无效,一般20~60参考值,最大240,4小时
15:温度变化值:默认0值无效,15表示1.5度,最大250、25度,也就是如30分钟内变化1.5度就报警
12:每天定点上传多少个点:默认0值当前一个点,12表示每天12个点2小时一个点,最多24个点,一般12或24个点参考值

文档更新时间: 2021-08-13 14:58   作者:admin