Pythonによるシリアルデータの解析とパッケージ化

概観

しばらく前にプロジェクトを作成しました。システムはシリアルポートを使用してMCUと対話します。システム側のコードは、双方が合意したデータパケットプロトコルに従ってデータを解析および送信するためのコードを記述していますが、MCU側はコードを完了していないため、それらを待つことができませんコードのデバッグが完了すると、オンラインで関連情報を参照した後、プロジェクトの進行が遅れます。最後に、Pythonスクリプトを使用してシミュレーションテストのデータ分析とパッケージ化を完了することにしました。また、インターネットで多くの情報を確認し、最終的にシミュレーションデータを実現してコードのデバッグを完了しました。このスクリプトは、主にPythonシリアル(シリアルポート操作)の2つのモジュールを使用しますそして、構造体(C言語のバイト文字列にパックされます)。いくつかの簡単な説明:

シリアルモジュール

メインユーザーのシリアルポート操作、ネットワークにはたくさんの情報があります、ここにコメント用のコードがあります

class ComThread:
 def __init__(self, Port='COM56'): #打开COM56
  self.l_serial = None 
  self.alive = False
  self.waitEnd = None
  self.port = Port
  self.ID = None
  self.data = None

 def waiting(self):
  if not self.waitEnd is None:
   self.waitEnd.wait()

 def SetStopEvent(self):
  if not self.waitEnd is None:
   self.waitEnd.set()
  self.alive = False
  self.stop()

 def start(self):
  self.l_serial = serial.Serial()
  self.l_serial.port = self.port
  self.l_serial.baudrate = 115200 #串口波特率
  self.l_serial.timeout = 2 #超时时间
  self.l_serial.open()
  if self.l_serial.isOpen():
   self.waitEnd = threading.Event()
   self.alive = True
   self.thread_read = None
   self.thread_read = threading.Thread(target=self.FirstReader)
   self.thread_read.setDaemon(1)
   self.thread_read.start()
   return True
  else:
   return False

 def SendDate(self,i_msg,send):
  #lmsg = ''
  isOK = False
  #发送数据到相应的处理组件
  print(i_msg)
  send_buf = nwy_create_send_msg(i_msg, send)
  self.l_serial.write(send_buf)
  print("send success")
  return True
 def FirstReader(self):
  while self.alive:
   time.sleep(0.1)
   data = ''
   data = data.encode('utf-8')
   n = self.l_serial.inWaiting()
   if n:
    data = data + self.l_serial.read(n)
    print(len(data))#打印收到的数据
    print(data.hex()) #按照十六进制打印

 def stop(self):
  self.alive = False
  self.thread_read.join()
  if self.l_serial.isOpen():
   self.l_serial.close()
   
def quit(signum, frame):
 print("Bye Bye!")
 sys.exit(0)

#调用串口,测试串口
def main():
 rt = ComThread()
 rt.sendport = '**1*80*'
 try:
  if  rt.start():
   signal.signal(signal.SIGINT, quit)
   print(rt.l_serial.name)
   #rt.waiting()
   #print("The data is:%s,The Id is:%s"%(rt.data,rt.ID))
   #t.stop()
  else:
   pass
 except Exception as se:
  print(str(se))
  print ('End OK .')
 return rt

if __name__ == '__main__':
 mSerial = main()
 while True:
  time.sleep(1)

構造体モジュール

シリアルデータ分析。ここでは、分析にアンパックを使用していません。これは、現在の定義による分析です。

def parse_read_data(data, len):
 print(data)
 print(len)
 #check head
 if 0x0F != data[0]:#判断数据头
  print ("head is not 0x0F data head is " + hex(data[0]))
  return False
 #get msg id 
 msg_id = data[1] << 8 | data[2] #获取消息ID
 msg_len = data[3] << 8 | data[4] #获取数据长度
 data_crc = data[7+msg_len] #获取数据的校验和
 Cal_crc = Calculation_crc(data[1:len-2]) #计算数据的校验和
 if data_crc != Cal_crc: #判断数据的校验和
  print ("crc error ")
  return False
 print ("data is good")
  #do something 
 #处理数据 
 return True

送信するデータを固定形式のバイト文字列にパックします。具体的なパッキングは、実際のプロトコルに従ってパックする必要があります。strcutの詳細な説明は多すぎるため、ここでは繰り返しません。

def create_send_msg(i_msg, send):
 msg_len = len(send)
 msg_len_2 = ~msg_len
 #下面就类似于c预言的printf 不过可以查查struct中对应的类型
 # !表示大端
 # H unsigned short
 # h singned short 这里用h主要是长度的反码如果有无符号会提示存不下,所以用有符号
 # %ds 这个比较特殊,s为字节串,长度为%d 
 # B byte
 psh = struct.pack('!HHh%ds'%len(send), i_msg, msg_len, msg_len_2,send)
 # 计算crc
 crc = Calculation_crc(psh)
  # c语言的结构体定义如下
 # struct{
 #  unsigned char  header
 #  unsigned short msgid
 #  unsigned short msglen
 #  signed short   unmsglen
 #  char *data
 #  unsigned char   crc
 #  unsigned char   end
 # }
 pshhh = struct.pack('!BHHh%dsBB' %len(send), MSG_HEADER, i_msg, msg_len, msg_len_2,send, crc, MSG_END)
 return pshhh

完全なサンプルコードは次のとおりです

import struct
import binascii
import sys
import signal
import threading
import time
import serial
import random
MSG_HEADER=0x0F
MSG_END=0xF0
MCU_MSG_ID=0x0001

def create_send_msg(i_msg, send):
 msg_len = len(send)
 msg_len_2 = ~msg_len
 #下面就类似于c预言的printf 不过可以查查struct中对应的类型
 # !表示大端
 # H unsigned short
 # h singned short 这里用h主要是长度的反码如果有无符号会提示存不下,所以用有符号
 # %ds 这个比较特殊,s为字节串,长度为%d 
 # B byte
 psh = struct.pack('!HHh%ds'%len(send), i_msg, msg_len, msg_len_2,send)
 # 计算crc
 crc = Calculation_crc(psh)
  # c语言的结构体定义如下
 # struct{
 #  unsigned char  header
 #  unsigned short msgid
 #  unsigned short msglen
 #  signed short   unmsglen
 #  char *data
 #  unsigned char   crc
 #  unsigned char   end
 # }
 pshhh = struct.pack('!BHHh%dsBB' %len(send), MSG_HEADER, i_msg, msg_len, msg_len_2,send, crc, MSG_END)
 return pshhh

def send_mcu_data(data):
 msg = "FF000000FFECFFD7FC03000000000000"; #模拟的一包数据
 by = binascii.a2b_hex(msg)
 mSerial.SendDate(MCU_MSG_ID, by)
 return

#计算校验和  
def Calculation_crc(data): 
 crc = 0
 for i in range(len(data)): 
  crc ^= data[i]
 return crc

def parse_read_data(data, len):
 print(data)
 print(len)
 #check head
 if 0x0F != data[0]:#判断数据头
  print ("head is not 0x0F data head is " + hex(data[0]))
  return False
 #get msg id 
 msg_id = data[1] << 8 | data[2] #获取消息ID
 msg_len = data[3] << 8 | data[4] #获取数据长度
 data_crc = data[7+msg_len] #获取数据的校验和
 Cal_crc = Calculation_crc(data[1:len-2]) #计算数据的校验和
 if data_crc != Cal_crc: #判断数据的校验和
  print ("crc error ")
  return False
 print ("data is good")
  #do something 
 #处理数据 
 return True
class ComThread:
 def __init__(self, Port='COM56'):
  self.l_serial = None
  self.alive = False
  self.waitEnd = None
  self.port = Port
  self.ID = None
  self.data = None
 def waiting(self):
  if not self.waitEnd is None:
   self.waitEnd.wait()
 def SetStopEvent(self):
  if not self.waitEnd is None:
   self.waitEnd.set()
  self.alive = False
  self.stop()

 def start(self):
  self.l_serial = serial.Serial()
  self.l_serial.port = self.port
  self.l_serial.baudrate = 230400
  self.l_serial.timeout = 2
  self.l_serial.open()
  if self.l_serial.isOpen():
   self.waitEnd = threading.Event()
   self.alive = True
   self.thread_read = None
   self.thread_read = threading.Thread(target=self.FirstReader)
   self.thread_read.setDaemon(1)
   self.thread_read.start()
   return True
  else:
   return False
 def SendDate(self,i_msg,send):
  send_buf = create_send_msg(i_msg, send)
  self.l_serial.write(send_buf)
  print("send success")
  return True

 def FirstReader(self):
  while self.alive:
   time.sleep(0.1)
   data = ''
   data = data.encode('utf-8')
   n = self.l_serial.inWaiting()
   if n:
    data = data + self.l_serial.read(n)
    #print(len(data))
    #print(data.hex())
    parse_read_data(data, len(data))
 def stop(self):
  self.alive = False
  self.thread_read.join()
  if self.l_serial.isOpen():
   self.l_serial.close()
  def quit(signum, frame):
 print("Bye Bye!")
 sys.exit(0)
#调用串口,测试串口
def main():
 rt = ComThread()
 rt.sendport = '**1*80*'
 try:
  if  rt.start():
   signal.signal(signal.SIGINT, quit)
   print(rt.l_serial.name)
  else:
   pass
 except Exception as se:
  print(str(se))
  print ('End OK .')
 return rt
if __name__ == '__main__':
 mSerial = main()
 while True:
  time.sleep(1)
  #发送给系统数据
  send_mcu_data(mSerial)

上記は私の共有です、あなたが探索する必要がある場合は、qq 991410485を追加できます

おすすめ

転載: blog.csdn.net/weixin_35933684/article/details/108288943