1.SDK下载

JT707SDK(JT707SDK_V2.rar) 下载地址
JT707SDK测试工具(JT707SDK_Test.rar) 下载地址
如果需要测试工具及SDK开发源码,请与商务申请


2.集成开发说明

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

JT707SDK(Jt707DataParser.dll)及测试工具(Test.exe)是基于C#语言,.NET Framework 4.6.1目标框架开发的。该SDK的集成开发环境也是需要依赖于C#语言以及.NET Framework 4.6.1目标框架。

2.2.集成说明

(1)将Jt707DataParser.dll引入到自己的网关程序中,引入方法如下:
鼠标右键项目下的”引用”,选择”添加引用(R)…”

选择下图中”浏览(B)…”,找到你解压JT707SDK_V2.rar后的文件夹,选中Jt707DataParser.dll与对应的Json字符串序列化/反序列化包Newtonsoft.Json.dll即可完成对SDK的引用
(2)调用Jt707DataParser.dll中的解析方法receiveData
receiveData()是一个重载方法,你可以传入16进制字符串或者byte[],一般我们网关程序接收到的设备数据是以二进制流进行传输的,所以我们这里建议使用此重载方法receiveData(byte[] bytes);
当然如果你想通过16进制字符串进行测试,也可以使用receiveData(string strData);
strData:就是我们接收到的设备数据转成16进制后的字符串

2.3.核心代码

Jt707DataParser.dll
(1)解析类DataParser.cs

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Jt707DataParser
{
    public class DataParser
    {
        private static byte[] endbytes = null;// 上一次未处理的剩余字节

        /// <summary>
        /// 解析16进制原始数据
        /// </summary>
        /// <param name="strData"></param>
        /// <returns></returns>
        public static string receiveData(string strData)
        {
            byte[] bytes = Common.HexStringToBytes(strData);
            return receiveData(bytes);
        }

        /// <summary>
        /// 解析2进制原始数据
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string receiveData(byte[] bytes)
        {
            byte[] newBytes = null;
            if (endbytes != null && endbytes.Length > 0)
            {
                newBytes = new byte[endbytes.Length + bytes.Length];
                bytes = Common.CombineBytes(endbytes, bytes);
            }
            else
            {
                newBytes = new byte[bytes.Length];
                newBytes = bytes;
            }
            int i = 0;//初始化byte[]下标
            byte[] parserBytes = null;//去除正确包头之前的数据后的数据
            foreach (var item in newBytes)
            {
                if (item == 0x7E)
                {
                    parserBytes = new byte[newBytes.Length - i];
                    parserBytes = newBytes.Skip(i).Take(newBytes.Length - i).ToArray();
                    return parserLocation(parserBytes);
                }
                else if (item == '(')
                {
                    parserBytes = new byte[newBytes.Length - i];
                    parserBytes = newBytes.Skip(i).Take(newBytes.Length - i).ToArray();
                    return parserCommand(parserBytes);
                }
                i++;
            }
            return null;
        }

        private static string parserLocation(byte[] bytes)
        {
            byte[] frame = PacketUtil.decodePacket(bytes);
            if (frame == null)
            {
                endbytes = bytes;
                return null;
            }
            string hexFrame = Common.ByteToHexStr(frame);
            //定义定位数据实体类
            Result model = new Result();
            //消息ID
            int msgId = Common.SwapUInt16(BitConverter.ToUInt16(frame, 1));
            //消息体属性
            int msgBodyAttr = Common.SwapUInt16(BitConverter.ToUInt16(frame, 3));
            //消息体长度
            int msgBodyLen = msgBodyAttr & 0x03FF;
            byte[] terminalNumArr = frame.Skip(5).Take(6).ToArray();
            model.DeviceID = Common.ByteToHexStr(terminalNumArr).TrimStart('0');
            //消息流水号
            int msgFlowId = Common.SwapUInt16(BitConverter.ToUInt16(frame, 11));
            //消息体
            byte[] msgBodyArr = frame.Skip(13).Take(msgBodyLen).ToArray();
            if (msgId == 0x0200)
            {
                //解析消息体
                LocationData locationData = PacketUtil.parseLocationBody(msgBodyArr);
                locationData.Index = msgFlowId;
                locationData.DataLength = msgBodyLen;
                model.MsgType = "Location";
                model.DataBody = locationData;
                string replyMsg = PacketUtil.replyBinaryMessage(terminalNumArr, msgFlowId);
                model.ReplyMsg = replyMsg;
            }
            else
            {
                model.MsgType = "heartbeat";
            }
            return JsonConvert.SerializeObject(model);
        }

        /// <summary>
        /// 解析指令数据
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        private static string parserCommand(byte[] bytes)
        {
            Result result = new Result();
            byte[] newBytes = null;
            int tailIndex = Common.BytesIndexOf(bytes, 0x29) + 1;
            if (tailIndex > 0)
            {
                if (bytes.Length > tailIndex)
                {
                    endbytes = bytes.Skip(tailIndex).Take(bytes.Length - tailIndex).ToArray();
                }
                newBytes = bytes.Skip(0).Take(tailIndex).ToArray();
            }
            else
            {
                endbytes = new byte[bytes.Length];
                endbytes = bytes;
            }
            if (newBytes != null && newBytes.Length > 0)
            {
                //转换成()带括号的数据
                string msgAscii = Common.ByteToASCII(newBytes);
                //按逗号拆分字符串
                char[] p = new char[] { ',' };
                //返回的数组中,包含空字符串
                string[] msgArrays = msgAscii.Replace("(", "").Replace(")", "").Split(p, StringSplitOptions.None);
                result.DeviceID = msgArrays[0];
                string msgType = string.Empty;
                if (msgArrays.Length > 5)
                {
                    msgType = msgArrays[3] + msgArrays[4];
                }
                else
                {
                    return null;
                }
                result.MsgType = msgType;
                result.DataBody = msgAscii;
                string replyMsg = string.Empty;
                if (msgType.Equals("BASE2") && msgArrays[5].ToUpper().Equals("TIME"))
                {
                    replyMsg = PacketUtil.replyBASE2Message(msgArrays);
                }
                result.ReplyMsg = replyMsg;
                return JsonConvert.SerializeObject(result);
            }
            else
            {
                return null;
            }
        }
    }
}

(2)公共方法类:Common.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Jt707DataParser
{
    public class Common
    {

        /// <summary>
        /// 16进制格式字符串转字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public static byte[] HexStringToBytes(string hexString)
        {
            hexString = Regex.Replace(hexString, @".{2}", "$0 ");
            //以 ' ' 分割字符串,并去掉空字符
            string[] chars = hexString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            byte[] returnBytes = new byte[chars.Length];
            //逐个字符变为16进制字节数据
            for (int i = 0; i < chars.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(chars[i], 16);
            }
            return returnBytes;
        }

        /// <summary>
        /// 合并数组
        /// </summary>
        /// <param name="bytes1"></param>
        /// <param name="bytes2"></param>
        /// <returns></returns>
        public static byte[] CombineBytes(byte[] bytes1, byte[] bytes2)
        {
            List<byte> tmp = new List<byte>(bytes1.Length + bytes2.Length);
            tmp.AddRange(bytes1);
            tmp.AddRange(bytes2);
            byte[] merged = tmp.ToArray();
            return merged;
        }

        /// <summary>
        /// 报告指定的 System.Byte[] 在此实例中的第一个匹配项的索引。
        /// </summary>
        /// <param name="srcBytes">被执行查找的 System.Byte[]。</param>
        /// <param name="searchBytes">要查找的 System.Byte[]。</param>
        /// <returns>如果找到该字节数组,则为 searchBytes 的索引位置;如果未找到该字节数组,则为 -1。如果 searchBytes 为 null 或者长度为0,则返回值为 -1。</returns>
        public static int BytesIndexOf(byte[] srcBytes, byte searchBytes)
        {
            if (srcBytes == null) { return -1; }
            if (srcBytes.Length == 0) { return -1; }
            for (int i = 0; i < srcBytes.Length; i++)
            {
                if (srcBytes[i] == searchBytes)
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 16进制字符串转ASCII
        /// </summary>
        /// <param name="Data"></param>
        /// <param name="istrans"></param>
        /// <returns></returns>
        public static string HexStrToAsciiString(string Data, bool istrans)
        {
            if (istrans)
            {
                Data = Regex.Replace(Data, @"(?is)(?<=^([0-9a-f]{2})+)(?!$)", " ");
                Data = Data.Replace("3D 00", "3D ").Replace("3D 11", "2C ").Replace("3D 14", "28 ").Replace("3D 15", "29 ").Replace(" ", "");
            }
            int count = Data.Length / 2;
            string strContent = "";
            char[] num = new char[count];
            for (int i = 0; i < count; i++)
            {
                string str = Data.Substring(i * 2, 2);
                byte by = Convert.ToByte(Convert.ToInt32(str, 16));
                num[i] = Convert.ToChar(by);
                strContent += num[i].ToString();
            }
            return strContent;
        }

        /// <summary>
        /// 二进制转ASCII
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public static string ByteToASCII(byte[] bt)
        {
            string lin = "";
            for (int i = 0; i < bt.Length; i++)
            {
                lin = lin + bt[i] + " ";
            }
            string[] ss = lin.Trim().Split(new char[] { ' ' });
            char[] c = new char[ss.Length];
            int a;
            for (int i = 0; i < c.Length; i++)
            {
                a = Convert.ToInt32(ss[i]);
                c[i] = Convert.ToChar(a);
            }

            string b = new string(c);
            return b;
        }

        /// <summary>
        /// 时间格式转换
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static DateTime GetDataTime(byte[] bytes)
        {
            return DateTime.ParseExact(ByteToHexStr(bytes), "yyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
        }

        public static DateTime GetDataTime(string strdate)
        {
            return DateTime.ParseExact(strdate, "yyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
        }

        /// <summary>
        /// 获取二进制第index位的值
        /// </summary>
        /// <param name="number"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static int getBitValue(long number, int index)
        {
            return (number & (1 << index)) > 0 ? 1 : 0;
        }

        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="byteDatas"></param>
        /// <returns></returns>
        public static string ByteToHexStr(byte[] byteDatas)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < byteDatas.Length; i++)
            {
                builder.Append(string.Format("{0:X2}", byteDatas[i]));
            }
            return builder.ToString().Trim();
        }

        public static ushort SwapUInt16(ushort v)
        {
            return (ushort)(((v & 0xff) << 8) | ((v >> 8) & 0xff));
        }

        public static uint SwapUInt32(uint v)
        {
            return (uint)(((SwapUInt16((ushort)v) & 0xffff) << 0x10) |
                           (SwapUInt16((ushort)(v >> 0x10)) & 0xffff));
        }

        /// <summary>
        /// Short转Bytes
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static byte[] ShortToBytes(short number)
        {
            byte byte2 = (byte)(number >> 8);
            byte byte1 = (byte)(number & 255);
            byte[] bytes = new byte[2];
            bytes[0] = byte1;
            bytes[1] = byte2;
            return bytes.Reverse().ToArray();
        }

        /// <summary>
        /// 随机short
        /// </summary>
        /// <returns></returns>
        public static short RandomNumber(int min, int max)
        {
            Random rd = new Random();
            return (short)rd.Next(min, max);
        }

        /// <summary>
        /// 计算校验码
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte xor(List<byte> bytes)
        {
            int checksum = 0;
            foreach (byte b in bytes)
            {
                checksum ^= b;
            }
            return (byte)(checksum & 0xff);
        }

        /// <summary>
        /// 转义
        /// </summary>
        /// <param name="inBytes"></param>
        /// <returns></returns>
        public static byte[] escape(List<byte> inBytes)
        {
            List<byte> outBytes = new List<byte>();
            foreach (byte b in inBytes)
            {
                if (b == 0x7E)
                {
                    outBytes.AddRange(HexStringToBytes("7D02"));
                }
                else if (b == 0x7D)
                {
                    outBytes.AddRange(HexStringToBytes("7D01"));
                }
                else
                {
                    outBytes.Add(b);
                }
            }
            return outBytes.ToArray();
        }
    }
}

(3)解包工具类PacketUtil.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Jt707DataParser
{
    public class PacketUtil
    {

        public static byte[] decodePacket(byte[] bytes)
        {
            //查找消息尾
            byte[] msgBodyNoHeader = bytes.Skip(1).Take(bytes.Length - 1).ToArray();
            int tailIndex = Common.BytesIndexOf(msgBodyNoHeader, 0x7E);
            if (tailIndex <= 0)
            {
                return null;
            }
            return unescape(bytes, tailIndex).ToArray();
        }
        /// <summary>
        /// 反转义
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="bodyLen"></param>
        /// <returns></returns>
        public static List<byte> unescape(byte[] bytes, int bodyLen)
        {
            int i = 0;
            List<byte> frame = new List<byte>();
            while (i < bodyLen)
            {
                byte b = bytes[i];
                if (b == 0x7D)
                {
                    byte nextByte = bytes[i + 1];
                    if (nextByte == 0x01)
                    {
                        frame.Add(0x7D);
                    }
                    else if (nextByte == 0x02)
                    {
                        frame.Add(0x7E);
                    }
                    else
                    {
                        //异常数据
                        frame.Add(b);
                        frame.Add(nextByte);
                    }
                    i += 2;
                }
                else
                {
                    frame.Add(b);
                    i++;
                }
            }
            return frame;
        }

        /// <summary>
        /// 解析定位消息体
        /// </summary>
        /// <param name="msgBodyBuf"></param>
        /// <returns></returns>
        public static LocationData parseLocationBody(byte[] msgBodyBuf)
        {
            //报警标志
            long alarmFlag = Common.SwapUInt32(BitConverter.ToUInt32(msgBodyBuf, 0));
            //状态
            long status = Common.SwapUInt32(BitConverter.ToUInt32(msgBodyBuf, 4));
            //纬度
            double lat = Common.SwapUInt32(BitConverter.ToUInt32(msgBodyBuf, 8)) * 0.000001;
            //经度
            double lon = Common.SwapUInt32(BitConverter.ToUInt32(msgBodyBuf, 12)) * 0.000001;
            //海拔高度,单位为米
            int altitude = Common.SwapUInt16(BitConverter.ToUInt16(msgBodyBuf, 16));
            //速度
            double speed = Common.SwapUInt16(BitConverter.ToUInt16(msgBodyBuf, 18)) * 0.1;
            //方向
            int direction = Common.SwapUInt16(BitConverter.ToUInt16(msgBodyBuf, 20));
            //定位时间
            DateTime gpsZonedDateTime = Common.GetDataTime(msgBodyBuf.Skip(22).Take(6).ToArray());
            //根据状态位的值判断是否南纬和西经
            if (Common.getBitValue(status, 2) == 1)
            {
                lat = -lat;
            }
            if (Common.getBitValue(status, 3) == 1)
            {
                lon = -lon;
            }
            //定位状态
            int locationType = Common.getBitValue(status, 18);
            if (locationType == 0)
            {
                locationType = Common.getBitValue(status, 1);
            }
            if (locationType == 0)
            {
                locationType = Common.getBitValue(status, 6) > 0 ? 2 : 0;
            }

            LocationData locationData = new LocationData();
            locationData.GpsTime = gpsZonedDateTime;
            locationData.Latitude = lat;
            locationData.Longitude = lon;
            locationData.LocationType = locationType;
            locationData.Speed = (int)speed;
            locationData.Direction = direction;
            //处理附加信息
            if (msgBodyBuf.Length > 28)
            {
                byte[] extraBytes = msgBodyBuf.Skip(28).Take(msgBodyBuf.Length - 28).ToArray();
                parseExtraInfo(extraBytes, locationData);
            }
            return locationData;
        }

        /// <summary>
        /// 解析附加信息
        /// </summary>
        /// <param name="msgBody"></param>
        /// <param name="location"></param>
        private static void parseExtraInfo(byte[] msgBody, LocationData location)
        {
            byte[] extraInfoBuf = null;
            while (msgBody.Length > 1)
            {
                int extraInfoId = msgBody[0];
                int extraInfoLen = msgBody[1];
                if (msgBody.Length - 2 < extraInfoLen)
                {
                    break;
                }
                extraInfoBuf = msgBody.Skip(2).Take(extraInfoLen).ToArray();
                msgBody = msgBody.Skip(2 + extraInfoLen).Take(msgBody.Length - (2 + extraInfoLen)).ToArray();
                switch (extraInfoId)
                {
                    case 0x0F:
                        //解析温度数据
                        double temperature = -1000.0;
                        temperature = parseTemperature(Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 0)));
                        location.Temperature=(int)temperature;
                        break;
                    //无线通信网络信号强度
                    case 0x30:
                        int fCellSignal = extraInfoBuf[0];
                        location.GSMSignal = fCellSignal;
                        break;
                    //卫星数
                    case 0x31:
                        int fGPSSignal = extraInfoBuf[0];
                        location.GpsSignal = fGPSSignal;
                        break;
                    //电池电量百分比
                    case 0xD4:
                        int fBattery = extraInfoBuf[0];
                        location.Battery = fBattery;
                        break;
                    //电池电压
                    case 0xD5:
                        int fVoltage = Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 0));
                        location.Voltage = fVoltage * 0.01;
                        break;
                    case 0xDA:
                        //剪绳次数
                        int fTimes = Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 0));
                        //状态位
                        int status = extraInfoBuf[2];
                        //锁状态
                        int fLockStatus = (status & 0x01)== 1 ? 0 : 1;
                        //运动状态
                        int fRunStatus = (status & 0x02) > 0 ? 1 : 0;
                        //Sim卡状态
                        int fSimStatus = (status & 0x04) > 0 ? 1 : 0;
                        //唤醒源
                        int fWakeSource = ((status >> 3) & 0x07);
                        location.LockStatus =fLockStatus;
                        location.LockRope=fLockStatus;
                        location.UnLockTime=fTimes;
                        location.RunStatus=fRunStatus;
                        location.SimStatus=fSimStatus;
                        location.Awaken = fWakeSource;
                        break;
                    case 0xDB:
                        //定位数据发送条数
                        int sendCount = Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 0));
                        location.SendDataCount=sendCount;
                        break;
                    case 0xF8:
                        //温度值
                        int temp = Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 0));
                        if (temp == 0xffff)
                        {
                            location.Temperature=-1000;
                        }
                        else
                        {
                            temp = (temp / 10) - 50;
                            location.Temperature=temp;
                        }
                        break;
                    case 0xFD:
                        //小区码信息
                        int mcc = Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 0));
                        location.MCC = mcc;
                        int mnc = extraInfoBuf[2];
                        location.MNC = mnc;
                        long cellId = Common.SwapUInt32(BitConverter.ToUInt32(extraInfoBuf, 3));
                        location.CELLID = cellId;
                        int lac = Common.SwapUInt16(BitConverter.ToUInt16(extraInfoBuf, 7));
                        location.LAC = lac;
                        break;
                    case 0xFE:
                        long mileage = Common.SwapUInt32(BitConverter.ToUInt32(extraInfoBuf, 0));
                        location.Mileage = mileage;
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>
        /// 温度解析
        /// </summary>
        /// <param name="temperatureInt"></param>
        /// <returns></returns>
        private static double parseTemperature(int temperatureInt)
        {
            if (temperatureInt == 0xFFFF)
            {
                return -1000;
            }
            double temperature = ((short)(temperatureInt << 4) >> 4) * 0.1;
            if ((temperatureInt >> 12) > 0)
            {
                temperature = -temperature;
            }
            return temperature;
        }

        /// <summary>
        /// 回复内容
        /// </summary>
        /// <param name="terminalNumArr"></param>
        /// <param name="msgFlowId"></param>
        /// <returns></returns>
        public static string replyBinaryMessage(byte[] terminalNumArr, int msgFlowId)
        {
            List<byte> byteList = new List<byte>();
            byteList.AddRange(Common.HexStringToBytes("8001"));
            byteList.AddRange(Common.HexStringToBytes("0005"));
            byteList.AddRange(terminalNumArr);
            byteList.AddRange(Common.ShortToBytes(Common.RandomNumber(0, 65534)));
            byteList.AddRange(Common.ShortToBytes((short)msgFlowId));
            byteList.AddRange(Common.HexStringToBytes("0200"));
            byteList.Add(0x00);
            byteList.Add(Common.xor(byteList));
            byte[] bytes = Common.escape(byteList);
            List<byte> replyList = new List<byte>();
            replyList.Add(0x7E);
            replyList.AddRange(bytes);
            replyList.Add(0x7E);
            return Common.ByteToHexStr(replyList.ToArray());
        }

        /// <summary>
        /// 授时
        /// </summary>
        /// <param name="itemList"></param>
        /// <returns></returns>
        public static string replyBASE2Message(string[] itemList)
        {
            try
            {
                string strBase2Reply = string.Format("({0},{1},{2},{3},{4},{5})", itemList[0], itemList[1]
                        , itemList[2], itemList[3], itemList[4], DateTime.UtcNow.ToString("yyyyMMddHHmmss"));
                return strBase2Reply;
            }
            catch (Exception e)
            {
                return "";
            }
        }
    }
}

2.4.返回消息及说明

(1)心跳数据
原始数据:

7E00020000770191203915FFF2E47E

返回消息:

{"DeviceID":"770191203915","MsgType":"heartbeat"}

返回消息描述

{"DeviceID":设备ID,"MsgType":消息类型(heartbeat:心跳)}

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

7E02000047770191203915000D000000000104100201588F7D0206CA3F580000001C000121072201060230011F310106D40164D5020050DA03000105DB02000CDC0400000000FD0901CC00000010922866F80203421B7E

返回消息:

{
    "DeviceID": "770191203915",
    "DataBody": {
        "GpsTime": "2021-07-22T01:06:02Z",
        "Temperature": 33,
        "MNC": 0,
        "UnLockTime": 1,
        "RunStatus": 0,
        "Index": 13,
        "Latitude": 22.581118,
        "Awaken": 0,
        "SimStatus": 1,
        "Direction": 1,
        "Battery": 100,
        "GpsSignal": 6,
        "Voltage": 0.8,
        "Speed": 2,
        "LockStatus": 0,
        "Mileage": 0,
        "MCC": 460,
        "Longitude": 113.917784,
        "LAC": 10342,
        "DataLength": 71,
        "CELLID": 4242,
        "LockRope": 0,
        "LocationType": 1,
        "SendDataCount": 12,
        "GSMSignal": 31
    },
    "ReplyMsg": "7e80010005770191203915ee25000d020000ab7e",
    "MsgType": "Location"
}

返回消息描述

{
    "DeviceID": 终端ID,
    "DataBody": {
        "Index": 数据流水号,
        "DataLength": 数据长度,字节数,
        "GpsTime": 定位数据时间(UTC时间),
        "Latitude": 纬度(WGS84),
        "Longitude": 经度(WGS84),
        "Temperature": 温度值,33标识的当前温度是33℃,
        "UnLockTime": 剪绳开锁次数,
        "RunStatus": 运动状态(1:运动;0:静止),
        "Awaken": 0:RTC上报  1:剪绳上报,2:插绳上报  3:开盖上报  4:关盖上报  5:充电/配置/模拟剪绳上报,
        "SimStatus": SIM卡类型 0:eSIM卡;1:Micro SIM卡槽,
        "Direction": 正北为0,顺时针0-359,
        "Battery": 电量值(0~100%),
        "GpsSignal": GPS当前接收到的卫星颗数,
        "Voltage": 电压值,单位V,
        "Speed": 速度,单位km/h,
        "LockStatus": 锁状态(0:关;1:开),
        "LockRope": 锁绳状态(0:插入;1:拔出),
        "Mileage": 里程值,单位km,
        "MCC": 小区码信息MCC,
        "MNC": 小区码信息MNC,
        "LAC": 小区码信息LAC,
        "CELLID": 小区码信息CI,
        "LocationType": 定位方式(0:不定位;1:GPS定位;2:基站定位),
        "SendDataCount": 发送数据的条数,
        "GSMSignal": GSM信号值
    },
    "ReplyMsg": 需要回复终端的内容(为空则表示不需要回复),
    "MsgType": 数据类型(Location:定位数据)
}

(3)指令数据解析
原始数据:

283737303139313230333930362c312c3030312c424153452c362c352c33302c3529

返回消息:

{
    "DeviceID": "770191203906",
    "DataBody": "(770191203906,1,001,BASE,6,5,30,5)",
    "ReplyMsg": "",
    "MsgType": "BASE6"
}

返回消息描述

{
    "DeviceID": 设备ID,
    "DataBody": 消息体内容,
    "ReplyMsg": 回复设备的消息(为空则表示不需要回复),
    "MsgType": 指令类型
}

3.指令消息

3.1.查询终端基本信息

消息体内容(DataBody):

(700160818000,1,001,BASE,1,20150418_G300,0,BeiHuan,1137B03SIM900M64_ST_MMS, 89860042191130272549,12345678965433224653,012207005620932,460,00,4243,6877)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,1 指令类型(BASE1)
3 20150418_G300 当前设备的版本号。
4 0,BeiHuan 前面的0表示英文,1表示其它语言的Unicode码,ASCII码表示,如:报警62A5 8B66上传是8个字节。此处为英语,名称为BeiHuan
5 1137B03SIM900M64_ST_MMS GSM模块版本。
6 89860042191130272549 eSIM卡的CCID。
7 460,00,4243,6877 网络信息:460 移动国家代码,即MCC信息,此处表示中国;00电信运营商网络号码,MNC信息(中国移动为00,中国联通为01);4243 基站编号CELL ID信息;6877 位置区域码LAC信息。CELL ID与LAC为十六进制,即4243转为十进制为16963。

3.2.授时(同步GMT时间)

消息体内容(DataBody):

(700160818000,1,001,BASE,2,20111018123820)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,2 指令类型(BASE2)
3 20111018123820 设置的时间(yyyyMMddHHmmss)

3.3.恢复终端出厂默认值

消息体内容(DataBody):

(700160818000,1,001,BASE,4,1)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,4 指令类型(BASE4)
3 1 1表示全部信息恢复为出厂默认值;2表示除通信主从IP外,其它信息全部恢复为出厂默认值;3表示除通信主从IP、VIP号码外,其它信息全部恢复为出厂默认值

3.4.查询/设置上传间隔和休眠定时唤醒间隔

消息体内容(DataBody):

(700160818000,1,001,BASE,6,60,30,30)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,6 指令类型(BASE6)
3 60 上传间隔(静止态),以分钟为单位。此值默认为30分钟。最小值为30,最大值为1440(24小时)。
4 30 固定为30,未使用
5 30 上传间隔(运动态),以分钟为单位。此值默认为30分钟。最小值为30,最大值为1440(24小时)。

3.5.时差设置

消息体内容(DataBody):

(2310915002,1,001,BASE,8, 480)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,8 指令类型(BASE8)
3 480 时差值,此处单位为分钟

3.6.查询/设置主从IP地址与端口号、APN及用户名与密码等参数

消息体内容(DataBody):

(700160818000,1,001,BASE,10,211.154.112.98,1088,211.154.112.98,1088,CMNET,abc,123456)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,10 指令类型(BASE10)
3 211.154.112.98 主IP(域名)
4 1088 主端口
5 211.154.112.98 从IP(域名)
6 1088 从端口
7 CMNET APN名称
8 abc 用户名
9 123456 密码

3.7.查询/设置关闭基站定位功能

消息体内容(DataBody):

(700160818000,1,001,BASE,29, 1)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,29 指令类型(BASE29)
3 1 1表示开启基站定位功能,0关闭基站定位功能。

3.8.查询/设置/删除设备工作闹钟

消息体内容(DataBody):

(700160818000,1,001, BASE,32,1,8:9:10,12:13:14)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,32 指令类型(BASE32)
3 1 1则表明当前闹钟有效,0表明当前闹钟无效。
4 8:9:10 8: 设置一个设备闹钟的小时;9: 设置一个设备闹钟的分钟;10:设置一个设备闹钟的秒钟
5 12:13:14 12: 设置一个设备闹钟的小时;13: 设置一个设备闹钟的分钟;14:设置一个设备闹钟的秒钟

3.9.查询/设置追踪模式

消息体内容(DataBody):

(700160818000,1,001,BASE,33,1,5,43200)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,33 指令类型(BASE33)
3 1 1表示有效追踪模式,0表示失效追踪模式
4 5 5表示追踪上传间隔,分钟为单位
5 43200 43200表示追踪时间段,分钟为单位

3.10.查询/设置当前simCard

消息体内容(DataBody)示例1:

(700160818000,1,001,BASE,36,2)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,36 指令类型(BASE36)
3 2 表示当前卡为卡2

消息体内容(DataBody)示例2:
(700160818000,1,001,BASE,36,454030220234116,89852031600002341160,454030220234117,89852031600002341161)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,36 指令类型(BASE36)
3 454030220234116 当前卡1的IMSI
4 89852031600002341160 当前卡1的ICCID
5 454030220234117 当前卡2的IMSI
6 89852031600002341161 当前卡2的ICCID

3.11.查询/设置进行 OTA的FTP服务器的IP地址(或域名)和端口号

消息体内容(DataBody):

(700160818000,1,001,BASE,37,1,ftpupdate.jointcontrols.cn,2021)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 BASE,37 指令类型(BASE37)
3 1 1表示设置,0表示查询(如果查询后面可以不接地址和断口号)
4 ftpupdate.jointcontrols.cn OTA的FTP服务器的IP地址
5 2021 OTA的FTP服务器的端口

3.12.通知设备无线模块升级

消息体内容(DataBody):

(2011091502,1,001,DEBUG,13,190508,180405)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 DEBUG,13 指令类型(DEBUG13)
3 190508 请求升级的软件日期版本
4 180405 软件当前正在运行的软件日期版本

3.13.通知设备MCU升级

消息体内容(DataBody):

(700160818000,1,001,OTA,1,1,20120102)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 OTA,1 指令类型(OTA1)
3 1 1:表示同意升级,只有当设备的当前版本号低于要升级的版本号的时候才返回1.若设备返回0表示拒绝升级,即设备当前的Firmware版本和升级的Firmware版本相同或者更高。服务器只有在收到同意升级以后才发送第一个Firmware数据包.
4 20120102 当前设备的Firmware版本号.

3.14.发送Firmware数据包

消息体内容(DataBody):

(700160818000,1,001,OTA,2,0,200,100)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 OTA,2 指令类型(OTA2)
3 0 1表示保存成功,0表示保存失败,如果失败重发.
4 200 接收到的Firmware数据包序号.
5 100 下一条需要发送的数据包序号.

3.15.取消Firmware升级

消息体内容(DataBody):

(700160818000,1,001,OTA,3,1,20120222)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 OTA,3 指令类型(OTA3)
3 1 1表示取消成功,0表示取消失败。如果该指令的版本号和正在升级的固件版本号不符的话就可能取消失败.
4 20120222 设备正在升级的版本号

3.16.完成Firmware传输

消息体内容(DataBody):

(700160818000,1,001,OTA,4,1)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 OTA,4 指令类型(OTA4)
3 1 该参数可以为1或者为0,1表示接受该指令,并根据指令执行。0表示:接受的数据不完全,拒绝升级.

3.17.查询发送下条Firmware数据包序号

消息体内容(DataBody):

(700160818000,1,001,OTA,5,1,200)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 OTA,5 指令类型(OTA5)
3 1 1:代表目前正在接收的固件和查询的相同,0表示目前接收的固件和查询的不同.
4 200 如果查询的固件版本号比设备的版本号新的话,该参数表示下一条需要发送的序号。如果查询的版本号和正在升级的版本号不同的话,则该参数为1.即代表需要重新下载现在查询的固件.

3.18.查询当前stm32固件的版本号

消息体内容(DataBody):

(700160818000,1,001,OTA,6,JT707A_V103R001)

消息体内容描述:

序号 示例 说明
1 700160818000 设备ID
2 OTA,6 指令类型(OTA6)
3 JT707A_V103R001 固件版本号
文档更新时间: 2024-10-15 17:45   作者:admin