808协议解析

部标808协议

一、通信方式

    协议采用的通信方式应符合JT/T 794中的相关规定,通信协议采用TCP或UDP,平台

作为服务器端,终端作为客户端。当数据通信链路异常时,终端可以采用SMS消息方式进

二、数据类型

协议消息中使用的数据类型见表1:

表1数据类型

数据类型

描述及要求

BYTE

无符号单字节整型(字节,8位)   

WORD

无符号双字节整型(字,16位)     

DWORD

无符号四字节整型(双字,32位)

BYTE[n]

n字节

BCD[n]

8421码,n字节

STRING

GBK编码,采用0终结符,若无数据,则放一个0终结符

传输规则

协议采用大端模式(big-endian)的网络字节序来传递字和双字。

约定如下:

——字节 (BYTE)的传输约定:按照字节流的方式传输;

——字(WORD)的传输约定:先传递高八位,再传递低八位;

——双字(DWORD)的传输约定:先传递高24位,然后传递高16位,再传递高八位,

最后传递低八位。

三、消息的组成

消息结构

每条消息由标识位、消息头、消息体和校验码组成,消息结构图如图1所示:

标识位

消息头

消息体

校验码

标识位

图1 消息结构体

JT/T 808-2011

标识位

    采用Ox7e表示,若校验码、消息头以及消息体中出现0x7e,则要进行转义处理,转义

规则定义如下:

0x7e<——>0x7d后紧跟一个0x02;

0x7d<——>0x7d后紧跟一个0x01。

    转义处理过程如下:

        发送消息时:消息封装——>计算并填充校验码——>转义;

        接收消息时:转义还原——>验证校验码——>解析消息。

      示例:

    发送一包内容为0x30 0x7e 0x08 0x7d 0x55的数据包,则经过封装如下:0x7e 0x30 7d 0x02 0x08 0x7d 0x01 0x55 0x7e。

 

解析部分

终端注册-----------------------------------------------------------
0x7e 0x1 0x0 0x0 0x21 0x1 0x41 0x46 0x66 0x53 0x47 0x0 0x29 0x0 0x2c 0x1 0x2f 0x37 0x30 0x31 0x31 0x31 0x42 0x53 0x4a 0x4d 0x31 0x31 0x2d 0x32 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x1 0xd4 0xc1 0x42 0x38 0x38 0x38 0x38 0x38 0x1e 0x7e

0x7e --标识符 
0x1 0x0   --消息头(消息ID)
0x0 0x21   --消息头(消息体属性) (二进制串: 0000 0000 0010 0001) 此消息不分包、不加密
0x1 0x41 0x46 0x66 0x53 0x47  --消息头(终端手机号)
0x0 0xf  --消息头(消息流水号)
0x0 0x2c --省域ID
0x1 0x2f --市县域ID
0x37 0x30 0x31 0x31 0x31  --制造商ID
0x42 0x53 0x4a 0x4d 0x31 0x31 0x2d 0x32   --终端型号
0x30 0x30 0x30 0x30 0x30 0x30 0x30   --终端ID
0x1 --车牌颜色(不确定是否用01 02标识,曾经解析的硬件是GBK编码的byte表示)(JT/T 415-2006 的 5.4.12)
0xd4 0xc1 0x42 0x38 0x38 0x38 0x38 0x38  --车牌GBK编码(公安交通管理部门颁发的机动车号牌)
0x38   --校验码 
0x7e   --标识符
---------------------------------------------------------------------------------------

平台---------8100  -------答应
7E 81 00 00 0A 01 41 46 66 53 47 6B 26 00 0F 00 31 32 33 34 35 36 BA 7E

7E 81 00 
00 09 --消息体长
01 41 46 66 53 47 --终端号
00 35 --消息ID

00 0b --消息体流水号
00 --应答成功
31 32 33 34 35 36 --发送鉴权码
BA
7E

设备--------------------------------102--------------------鉴权--
0x7e 0x1 0x2 0x0 0x6 0x1 0x41 0x46 0x66 0x53 0x47 0x0 0xd 0x31 0x32 0x33 0x34 0x35 0x36 0x7b 0x7e
0x7e 
0x1 0x2 
0x0 0x6 --消息体长
0x1 0x41 0x46 0x66 0x53 0x47 --终端号
0x0 0xe --消息ID

0x31 0x32 0x33 0x34 0x35 0x36 
0x78 
0x7e

-----------------------------------------------------------------------------------------
平台--------------------------801------------------------答应-
7E 80 01 00 05 01 41 46 66 53 47 73 31 00 -- 01 02 00 

7E 
80 01 
00 05
01 41 46 66 53 47
73 13  //消息头

00 03  //应答流水号
01 02  //应答ID
00     //通用应答0成功
--------------定位信息----------------
0x7e 0x2 0x0 0x0 0x40 0x1 0x41 0x46 0x66 0x53 0x47 0x0 0x7c 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x3 0x2 0x7 0xf2 0xb4 0x6 0xc9 0x72 0xf8 0x0 0x0 0x0 0x0 0x0 0x3d 0x20 0x7 0x11 0x11 0x7 0x41 0x1 0x4 0x0 0x0 0x0 0x0 0x30 0x1 0x12 0x31 0x1 0x18 0xeb 0x16 0x0 0xc 0x0 0xb2 0x89 0x86 0x4 0x42 0x19 0x19 0x91 0x5 0x37 0x95 0x0 0x6 0x0 0x89 0xff 0xff 0xff 0xff 0xae 0x7e

0x7e 
0x2 0x0 
0x0 0x40 
0x1 0x41 0x46 0x66 0x53 0x47 
0x0 0x3b 
0x0 0x0 0x0 0x0 ---报警标志
0x0 0x0 0x0 0x3 ---定位状态位 16转2进制  20 
0x2 0x7 0xf2 0xb4 ---纬度 16转10进制再乘以 10 的 6 次方   34075316   21-24
0x6 0xc9 0x72 0xf8 ---经度 16转10进制再乘以 10 的 6 次方  113865464
0x0 0x0 ---高程 海拔高度,单位米
0x0 0x0 ---速度  16转10进制除以10
0x0 0x3d ---方向  0-359,正北为0,顺时针  
0x20 0x7 0x11 0x11 0x2 0x20 时间 20年07月11日11时02分20秒
0x1 0x4 0x0 0x0 0x0 0x0 ---里程
0x30 0x1 扩展ID
0x12 0x31 0x1 0x18 0xeb 0x16 0x0 0xc 0x0 0xb2 0x89 0x86 0x4 0x42 0x19 0x19 0x91 0x5 0x37 0x95 
0x0 0x6 0x0 0x89 0xff 0xff 0xff 0xff 
0x8d 0x7e           
设备标识:0100
平台应答:7E 81 00 00 09 01 41 46 66 53 47 -- -- 00 -- 00 31 32 33 34 35 36
设备标识:0102
平台应答:7E 80 01 00 05 01 41 46 66 53 47 -- -- 00 -- 01 02 00 
设备标识:0002
平台应答:7E 80 01 00 05 01 41 46 66 53 47 -- -- 00 -- 00 02 00 
设备标识:0200
平台应答:7E 80 01 00 05 01 41 46 66 53 47 -- -- 00 -- 02 00 00
设备标识:0704
平台应答:7E 80 01 00 05 01 41 46 66 53 5f -- -- 00 -- 07 04 00

python解析示例

import socketserver
import struct
import threading
import datetime
ADDRESS = ('0.0.0.0', 9904)  # 绑定地址
import random
import ws8_bd09
g_conn_pool = []  # 连接池

class Data_format(object):
    def str_to_hex(self,str):
        str = str.replace(' ', '')
        str2 = b""  # 初始化
        while str:
            str1 = str[0:2]  # 分割字符串,获取前两个字符
            s = int(str1, 16)  # 字符串转换成16进制
            str2 += struct.pack('B', s)  # 转换成字节流,“B“为格式符,代表一个unsigned char (具体请查阅struct)
            str = str[2:]  # 分割字符串,去掉字符串前两个字符
        return str2

    def hex_to_str(self,data):
        res_data_list = [hex(x) for x in bytes(data)]
        data_str = ' '.join(res_data_list)
        return data_str

    def get_bcc(self,data):
        inputStr = data[3:]
        bcc = 0
        for i in inputStr.split(' '):
            bcc = bcc ^ int(i, 16)
        return data + " " + f'{bcc:x}'.upper() + " " + "7E"

    def data_handle(self,str):
        head_data, msg = " ", " "
        str_list = str.split(' ')
        head_id = str_list[1:3]
        if head_id == ['0x1', '0x0']:
            data = '7E 81 00 00 09 01 41 46 66 53 47 %s %s 00 %s 00 31 32 33 34 35 36' % (
            random.randint(10, 90), random.randint(10, 90), str_list[12][2:].rjust(2, '0'))
            head_data = self.get_bcc(data)
            msg = self.str_to_hex(head_data)
            # print(msg)
        if head_id == ['0x1', '0x2']:
            data = '7E 80 01 00 05 01 41 46 66 53 47 %s %s 00 %s 01 02 00' % (
                random.randint(10, 90), random.randint(10, 90), str_list[12][2:].rjust(2, '0'))
            head_data = self.get_bcc(data)
            msg = self.str_to_hex(head_data)
            # print(msg)

        if head_id == ['0x0', '0x2']:
            data = '7E 80 01 00 05 01 41 46 66 53 47 %s %s 00 %s 00 02 00' % (
                random.randint(10, 90), random.randint(10, 90), str_list[12][2:].rjust(2, '0'))
            head_data = self.get_bcc(data)
            msg = self.str_to_hex(head_data)
            # print(msg)
        if head_id == ['0x7', '0x4']:
            data = '7E 80 01 00 05 01 41 46 66 53 5f %s %s 00 %s 07 04 00' % (
                random.randint(10, 90), random.randint(10, 90), str_list[12][2:].rjust(2, '0'))
            head_data = self.get_bcc(data)
            msg = self.str_to_hex(head_data)
        if head_id == ['0x2', '0x0']:
            ret = self.format_data(str_list)
            bd09_pos = ws8_bd09.wgs84_to_bd09(ret[1]/1000000,ret[0]/1000000)
            with open('position.csv', 'a+') as a:
                a.write("%s,%s"%(bd09_pos[0],bd09_pos[1]) + '\n')
            print("定位解析:",ret)
            data = '7E 80 01 00 05 01 41 46 66 53 5f %s %s 00 %s 02 00 00' % (
                random.randint(10, 90), random.randint(10, 90), str_list[12][2:].rjust(2, '0'))
            head_data = self.get_bcc(data)
            msg = self.str_to_hex(head_data)
            # print(msg)
        return head_data, msg

    def format_data(self,data_list):
        # data_list = data.split(' ')
        latitude = int('0x'+''.join([i[2:].rjust(2, '0') for i in data_list[21:25]]),16)
        longitude = int('0x'+''.join([i[2:].rjust(2, '0') for i in data_list[25:29]]),16)
        v = int('0x'+''.join([i[2:].rjust(2, '0') for i in data_list[31:33]]),16)
        h = int('0x'+''.join([i[2:].rjust(2, '0') for i in data_list[33:35]]),16)
        Time = ''.join([i[2:].rjust(2, '0') for i in data_list[35:41]])
        return latitude,longitude,v,h,Time

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler,Data_format):

    def setup(self):
        self.request.sendall("连接服务器成功!".encode(encoding='utf8'))
        # 加入连接池
        g_conn_pool.append(self.request)

    def handle(self):
        while True:
            # try:
            bytes = self.request.recv(1024)
            if bytes == " ":
                pass
                # print(hex(bytes))
                # res_data_list = [hex(x) for x in bytes(data)]
            else:
                strBytes = self.hex_to_str(bytes)
                print("终端消息%s:%s"% (datetime.datetime.now(),strBytes))
                data = self.data_handle(strBytes)
                if data[0] == " ":
                    pass
                else:
                    print('平台答应:',data[0])
                    g_conn_pool[0].sendall(data[1])
                    # except:  # 意外掉线
                    #     self.remove()
                    #     break

    def finish(self):
        print("清除了这个客户端。")

    def remove(self):
        print("有一个客户端掉线了。")
        g_conn_pool.remove(self.request)
        self.request.close()
        


class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass


if __name__ == '__main__':


    import time
    server = ThreadedTCPServer(ADDRESS, ThreadedTCPRequestHandler)
    # 新开一个线程运行服务端
    server_thread = threading.Thread(target=server.serve_forever)
    server_thread.daemon = True
    server_thread.start()
    # 主线程逻辑
    while True:
        msg = input('')
        # msg = server.get_bcc(msg)
        # print('平台答应:',msg)
        # msg = str_to_hex(msg)
        # g_conn_pool[0].sendall(msg)

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(工具及其他)