Python-十六进制数据传递与接收

实际应用场景

python客户端与服务端(c程序)进行通讯,需接收服务端发来的16进制码流,并对16进制数据进行解码,得到相应字段的数据,并可以将数据打包成对应格式的码流发送给服务端,多字节整数传输采用网络字节序。

1.1 网络字节序

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian(大端)排序方式。

为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下

Character      Byte order          Size               Alignment

@(默认)            本机              本机              本机,凑够4字节

=                 本机                标准              none,按原字节数

<                 小端                标准              none,按原字节数

>                 大端                标准              none,按原字节数

!              network(大端)         标准              none,按原字节数

1.2 python struct的模块

作用:按照指定格式将Python数据转换为字符串,该字符串为字节流,如网络传输时,不能传输int,此时先将int转化为字节流,然后再发送;
按照指定格式将字节流转换为Python指定的数据类型;
处理二进制数据,如果用struct来处理文件的话,需要用’wb’,’rb’以二进制(字节流)写,读的方式来处理文件;
处理c语言中的结构体;

struct中两个重要的函数:

(1)pack(fmt,v1,v2…):打包函数

返回值类型:string

按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回.

(2)unpack(fmt,v1,v2…..):解包函数

返回值类型:tuple

按照给定的格式(fmt)解析字节流,并返回解析结果

2.消息发送的格式

消息采用消息头+消息体格式。

UINT8         1字节            8位无符号整形      
UINT16        2字节            16位无符号整形         
UINT32        4字节            32位无符号整形
UINT64        8字节            64位无符号整形

1.消息头

字段                  类型                  说明

消息编号            UINT8                    -

保留                  UINT8                用0填充

消息体长度           UINT16      不包括消息头的长度,范围:0 -- 65535

1.1消息编号

编号            消息                    用途                     说明

0xe1     W_HEARTBEAT               心跳消息                消息体长度为0

0xq1      QUERY_SM                  查询SM请求            消息体长度为0

0xq2     QUERYSM_RPT             查询SM数据上报        

0xs1     SCAN_PL                    扫描PL请求            消息体长度为0

0xs2     SCANPL_ACK                扫描PL请求应答

1.2消息体格式

(1)心跳消息(W_HEARTBEAT) 每30秒发送一次,无消息体

(2)QUERY_SM 查询SM数据请求 无消息体

(3)QUERYSM_RPT 查询SM数据应答 消息体长度为27

  字段           长度      类型           说明

reserved         6         CHAR            ——

strName            16         CHAR           字符串

RS                 4         INT32           信号强度(-140~-44dBm)
                                              0:RS值无效

Rs_si           1              BYTE            0:SI
                                               1:RS

(4)SCAN_PL 扫描PL请求 消息体长度为0

(5)SCANPL_ACK 扫描PL请求应答

 字段                长度      类型           说明

reserved         4         UINT32            ——

result             2         UINT16           0:成功,1:失败

count             2         UINT16           info数量

info            13 * 10     info[10]     最多10个info列表

5-1) info消息体

字段                长度          类型             说明

ID                     4            UINT32              ID值

Num                 6            CHAR              号码

fn                 2            UINT16              fn频率

power               1            UINT8              功率

3.代码示例如下

3.1 发送程序(打包程序):

def th_heart():
    while True:
        logging.info('SEND W_HEARTBEAT')
        cmd_word = 0xe1
        tx_buf = struct.pack('

3.2 接收程序(解包程序):

if temp.find('0xq2') >=0:
    logging.info('QUERYSM_RPT')
    header,b,b_len,reserved,strName,RS,Rs_si = struct.unpack(">2BH6s16siB", body)
    strName = strName[0:-1]
    logging.info("header:%s, b:%s, b_len:%s,reserved:%s, strName:%s, RS:%s, Rs_si:%s" % (header, b, b_len, reserved, strName, RS, Rs_si))
    sm_rpt(moduleId, strName)

if temp.find('0xs2') >= 0:
    logging.info('SCANPL_ACK')
    header, b, b_len, reserved, result, count = struct.unpack(">2BHIHH", body[0:12])
    ID,Num,fn,power = struct.unpack(">I6sHB", body[12:25])
    logging.info("reserved:%s, result:%s, count:%s" %(reserved,result,count))
    logging.info("ID:%s, Num:%s, fn:%s, power:%s" % (ID, Num, fn, power))
    pl_rpt(moduleId, ID, Num,fn,power)    

更多博客内容详见我的博客 Wang's Blog

你可能感兴趣的:(Python,十六进制,数据传输)