使用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’)就可以了。其對照列表如下: