使用Python写上位机软件时,若通过网口向硬件端发送命令参数对仪器进行控制,此时需要将多个参数打包为字节流数据后进行网络传输,可以使用模块struct和socket完成。
具体实现代码如下:
1 # -*- coding: utf-8 -*-# 2 3 #------------------------------------------------------------------------------- 4 # Name: 发送参数包 5 # Description: 整个包大小为64Byte,包头为0X”FAA5 FBB5 FCC4 FDD5”,包尾为0X”5FA5 5FB5 5FC5 5FD5 ”,中间不足部分补0 6 # Author: lgk 7 # Date: 2018/6/13 8 #------------------------------------------------------------------------------- 9 10 import socket 11 import struct 12 import ctypes 13 import binascii 14 import re 15 16 #字节顺序定义 17 byteOrders = {'Native order':'@', 18 'Native standard':'=', 19 'Little-endian':'<', 20 'Big-endian':'>', 21 'Network order':'!'} 22 23 byteOrder = 'Little-endian' 24 25 #发送的参数定义(有符号整型数字) 26 cmdType = 1 # 1 Byte 27 sigType = 2 # 1 Byte 28 startFreq = 40 # 4 Byte 29 stopFreq = 400 # 4 Byte 30 deltFreq = 10 # 4 Byte 31 pulseNum = 37 # 2 Byte 32 pulseWidth = 0 # 4 Byte 33 PRF = 25000000 # 4 Byte 34 receiverFreq = 1000 # 4 Byte 35 36 headInfo = [0xFA, 0xA5, 0xFB, 0xB5, 0xFC, 0xC5, 0xFD, 0xD5] 37 tailInfo = [0x5F, 0xA5, 0x5F, 0xB5, 0x5F, 0xC5, 0x5F, 0xD5] 38 39 fmt_head = fmt_tail = struct.Struct(byteOrders[byteOrder] + "8B") 40 fmt_body = struct.Struct(byteOrders[byteOrder] + "2b3i1h3i") 41 bufferLength = 64 42 43 sendBuffer = ctypes.create_string_buffer(bufferLength) #创建发送缓冲区 44 45 #将待发送的参数打包到缓冲区 46 fmt_head.pack_into(sendBuffer, 0, *headInfo) 47 fmt_tail.pack_into(sendBuffer, bufferLength-fmt_tail.size, *tailInfo) 48 fmt_body.pack_into(sendBuffer, fmt_head.size, cmdType, sigType, startFreq, stopFreq, deltFreq, pulseNum, pulseWidth, PRF, receiverFreq) 49 50 def getSendInfo(info): 51 # t = '' 52 # for i in range(len(info) / 2): 53 # t += info[2 * i:2 * (i + 1)] + ' ' 54 # t = t.strip().upper() 55 p = re.compile('.{1,2}') #匹配任意字符1-2次 56 t = ' '.join(p.findall(info.upper())) 57 return t 58 59 #打印出字节流的16进制信息 60 #FA A5 FB B5 FC C5 FD D5 01 02 28 00 00 00 90 01 00 00 0A 00 00 00 25 00 00 00 00 00 40 78 7D 01 E8 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5F A5 5F B5 5F C5 5F D5 61 print(getSendInfo(binascii.hexlify(sendBuffer))) 62 63 #通过socket发送到服务器端 64 HOST = '192.168.1.122' 65 PORT = 8001 66 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 67 s.connect((HOST, PORT)) 68 s.send(sendBuffer) 69 s.close()
其中,struct中支持的格式如下图所示:
打包的后的字节顺序默认上是由操作系统的决定的,struct模块提供了自定义字节顺序的功能,可以指定大端存储、小端存储等特定的字节顺序,对于底层通信的字节顺序是十分重要,不同的字节顺序和存储方式也会导致字节大小的不同。在format字符串前面加上特定的符号即可以表示不同的字节顺序存储方式,例如采用小端存储 s = struct.Struct(‘<I3sf’)就可以了。其对照列表如下: