python客户端与服务端(c程序)进行通讯,需接收服务端发来的16进制码流,并对16进制数据进行解码,得到相应字段的数据,并可以将数据打包成对应格式的码流发送给服务端,多字节整数传输采用网络字节序。
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian(大端)排序方式。
为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下
Character Byte order Size Alignment
@(默认) 本机 本机 本机,凑够4字节
= 本机 标准 none,按原字节数
< 小端 标准 none,按原字节数
> 大端 标准 none,按原字节数
! network(大端) 标准 none,按原字节数
作用:按照指定格式将Python数据转换为字符串,该字符串为字节流,如网络传输时,不能传输int,此时先将int转化为字节流,然后再发送;
按照指定格式将字节流转换为Python指定的数据类型;
处理二进制数据,如果用struct来处理文件的话,需要用’wb’,’rb’以二进制(字节流)写,读的方式来处理文件;
处理c语言中的结构体;
struct中两个重要的函数:
(1)pack(fmt,v1,v2…):打包函数
返回值类型:string
按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回.
(2)unpack(fmt,v1,v2…..):解包函数
返回值类型:tuple
按照给定的格式(fmt)解析字节流,并返回解析结果
消息采用消息头+消息体格式。
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.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)