首先感谢:https://www.cnblogs.com/mangojun/p/10558069.html
本文参考了该博主部分代码
最近在写一个zigbee的程序,终端发送采用了json格式打包。
上位机使用了树莓派,直接使用python编程,第一次尝试树莓派接收数据,仍旧采用了类似于C语言的数据处理方式。
数据处理过程:
1、首先通过进程,将数据接受进一个bytearray的数组中
2、在数组中查找 { ,因为我的格式比较简单,发送上来的数据都只有一组大括号,所以处理起来相对容易一些。
3、在数组中查找 }
4、若找到 { } ,且右括号的位置在后面,则提取出来json数据,并将这部分数据从数组中清除
5、若找到 { ,没有右括号,则说明还没接收到一个完整的数据
6、若找到 } , 没有左括号,说明 } 前面的数据是错误数据,直接丢弃。
数据处理后,可直接使用json库进行处理,处理时注意采用try的方式,因为只判断了 { } ,可能内部格式存在问题的时候,会出现异常。
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 5 08:43:36 2021
@author: huangcw
"""
import serial
import time
import json
from datetime import datetime
import threading
class SerialPort:
def __init__(self, port, buand):
self.data_bytes=bytearray()
self.is_exit = False
self.port = serial.Serial(port, buand)
self.port.close()
if not self.port.isOpen():
self.port.open()
def port_open(self):
if not self.port.isOpen():
self.port.open()
def port_close(self):
self.port.close()
def send_data(self):
self.port.write('')
def read_data(self):
"""
从串口读取数据,并放到缓冲区中
"""
while not self.is_exit:
count = self.port.inWaiting()
if count > 0:
rec_str = self.port.read(count)
self.data_bytes=self.data_bytes+rec_str
def frame_process(self):
"""
提取json格式数据,若收到的数据中包含完整的json数据,每调用一次返回一条json数据。
注意:仅支持一层 { }的json数据格式。
"""
self.head = -1
self.tail = -1
self.head = self.data_bytes.find(b'{')
self.tail = self.data_bytes.find(b'}')
if(self.head != -1): #有json的头
if(self.tail != -1): #有尾
if(self.tail < self.head): #尾靠前,说明前面不是一个完整的报文,需要扔掉
self.data_bytes[0:self.tail+1]=b''
return -2
if(self.tail > self.head): # 有头有尾,且头在尾前面
self.rtn = self.data_bytes[self.head:self.tail+1]
self.data_bytes[self.head:self.tail+1]=b''
return self.rtn
# 有头没有尾,说明还没有接收完一帧,不处理
else:
return -1
# 没头,说明没接收到一帧,不处理
else:
return -1
serialPort = 'COM13' # 串口
baudRate = 115200 # 波特率
if __name__ == '__main__':
#打开串口
mSerial = SerialPort(serialPort, baudRate)
#开始数据读取线程
t1 = threading.Thread(target=mSerial.read_data)
t1.setDaemon(True)
t1.start()
frame_cnt = 0
frame_error_cnt = 0
try:
while True:
rtn = mSerial.frame_process()
if rtn != -1 and rtn != -2:
frame_cnt = frame_cnt + 1
print("正确帧:{} 错误帧:{} 新数据:{}".format(frame_cnt,frame_error_cnt,rtn))
elif rtn == -2:
frame_error_cnt = frame_error_cnt +1
except KeyboardInterrupt:
if mSerial.port_open():
mSerial.port_close()
运行效果: