[python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)
星期一, 20. 八月 2018 01:53上午 - beautifulzzzz
1、前言
做类似zigbee、ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原因,而且有些深层次问题隐藏在弱网环境中、或大量测试中,因在上位机上用脚本实现自动化挂机测试便显得尤为重要。
本文介绍一种用python写的基于串口通信的上位机自动测试程序框架(简陋框架)。
2、代码框架介绍
如下:整个代码包含两层app+bsp,其中:
- bsp层放硬件相关的代码(比如linux系统用python2.7写的串口驱动类);
- app层中包含两个应用程序
app_app_auto_test_0xda_0xdb_adapter
和app_app_auto_test_off_line
;
其中应用程序是基于bsp中的代码实现的,进入每个独立的应用程序文件夹,运行make all则可以运行~
➜ mesh_test_toos git:(master) ✗ tree
.
├── app
│ ├── app_app_auto_test_0xda_0xdb_adapter
│ │ ├── app_auto_test.py
│ │ ├── app_frame.py
│ │ ├── main.py
│ │ └── makefile
│ └── app_app_auto_test_off_line
│ ├── app_frame.py
│ ├── app_frame.pyc
│ ├── main.py
│ └── makefile
└── bsp
├── bsp_serial.py
├── bsp_serial.pyc
├── bsp_system.py
└── bsp_system.pyc
4 directories, 12 files
3、bsp代码介绍
bsp_system.py: 该文件目前只放了一个获取当前时间戳的函数,精确到毫秒:
#!/usr/bin/env python
# coding=utf-8
import time
def get_time_stamp():
ct = time.time()
local_time = time.localtime(ct)
data_head = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
data_secs = (ct - long(ct)) * 1000
time_stamp = "[%s.%03d] " % (data_head, data_secs)
return time_stamp
version = '0.1'
bsp_serial.py: 该文件在pyserial上封装了一个bsp_serial类,该类包含下面几个成员函数:
- 实例化函数:自动读取系统中所有串口,如果有多个则会让你选择一个,并进行打开,产生一个ser成员变量
- iswaiting函数:读取之前要先调用该函数,看看是否有数据
- read函数:读取一字节
- write函数:写一个数组的数据
- close函数:关闭函数
A demo for read:
ser1 = bsp_serial.bsp_serial(9600)
while 1<2:
if ser1.iswaiting() > 0:
x = ser1.read()
print x
note: If you want to write datas when reading, you should use the thread (next will show you) !
4、app_app_auto_test_off_line demo介绍
该脚本为自动测试无线网络中的某一个节点的长挂机情况下是否有掉线情况:
该网络中有一个mesh灯节点和一个和PC相连的dongle mesh节点,由于ble mesh的特性:
处于同一mesh网络中的节点中维护一个全部节点的在线/离线状态的表
因此如果想实现监听灯节点的在线/离线状态,只需要周期性地从dongle节点中读取状态表即可!这里每隔15S dongle节点将状态表以图中所示FRAME的格式传给PC:
- head为帧头,固定的
- cmd为帧命令,同步状态表时其值为0x07
- length为数据长度,这里为8
- data1、data2为数据,每4个字节表示一个节点的状态,第1字节表示节点ID,第二字节为0表示离线
- check为校验,为除该位其它位数据和模256
app_frame.py 中实现的则是用于解析数据包的类:
#!/usr/bin/env python
# coding=utf-8
import sys
import termios
class FRAME:
HEAD1=0
HEAD2=1
VERSION=2
CMD=3
LEN1=4
LEN2=5
LEN_HEAD=6
MAX_DATA_BUF_SIZE = 1000
def __init__(self,fun_analysis):
self.data_buf = ""
self.fun_analysis = fun_analysis
'''
judge frame is ok
'''
def frame_ok(self,str):
start_pos = 0
fram_len = 0
end_pos = 0
str_len = len(str)
while start_pos<str_len:
pos = start_pos
if((ord(str[pos]) == 0x55) and (pos!=str_len-1) and (ord(str[pos+1]) == 0xAA)):
break
start_pos = start_pos+1
if(start_pos == str_len):#no find
return (-1,start_pos,end_pos)
if(start_pos + FRAME.LEN_HEAD < str_len):
#print str_len,start_pos,FRAME.LEN2
fram_len = ord(str[start_pos+FRAME.LEN2])
end_pos = start_pos + FRAME.LEN_HEAD +fram_len
#print fram_len,end_pos
if(end_pos < str_len):
return (0,start_pos,end_pos)
return (-2,start_pos,end_pos)
'''
insert data to frame fifo
'''
def insert_data(self,data):
self.data_buf+=data
if len(self.data_buf) > self.MAX_DATA_BUF_SIZE:
self.data_buf = ""
'''
analysis frame and perform
'''
def run(self):
while 1<2:
(ret,start_pos,end_pos) = self.frame_ok(self.data_buf)
#print (ret,start_pos,end_pos)
if(ret == 0):
self.fun_analysis(self.data_buf[start_pos:end_pos+1])
self.data_buf = self.data_buf[end_pos:]
FRAME类的实例化函数需要注册一个命令解析函数fun_analysis;frame_ok用于判断数据包是否正确;insert_data用于将串口收到的数据插入到FIFO中,接收插入数据和处理分开;run函数用于不断从FIFO中取出数据并判断是否是一个有效数据包,并进而调用fun_analysis进行解析及后续处理。
note: run函数需要独占一个线程!
则在main.py中分别开两个线程 —— 串口接收线程和帧RUN线程:
import threading
import app_frame
import sys
sys.path.append('../../bsp')
import bsp_serial
import bsp_system
def init():
#......(略)
def analysis_cmd(str):
#......(略)
def ser_receive():
global ser1
global frame
while 1<2:
if ser1.iswaiting() > 0:
x = ser1.read()
frame.insert_data(x)
total_num = 0
fail_times = 0
ser1 = bsp_serial.bsp_serial(9600)
frame = app_frame.FRAME(analysis_cmd)
try:
init()
threads = []
t1 = threading.Thread(target=ser_receive)
t2 = threading.Thread(target=frame.run)
threads.append(t1)
threads.append(t2)
for t in threads:
t.setDaemon(True)
t.start()
t.join()
except Exception, e:
ser1.close() # close port
print("safe exit"+str(e))
- 串口接收线程不断读取串口数据,并插入到帧对象的FIFO中
- 帧RUN函数不断解析FIFO中的数据,若检测到一个有效数据包,则调用analysis_cmd处理
最终效果如下:
5、app_app_auto_test_0xda_0xdb_adapter demo介绍
这个例子和上面的很像,用于测试一条GET STATE命令的成功率:
- 1)整个mesh网路的架构还是dongle+1个node灯;
- 2)PC通过串口发请求命令给dongle;
- 3)dongle收到cmd1立刻通过串口应答该命令,并向灯节点请求状态;
- 4)灯收到请求将状态返回给dongle,dongle再通过串口给PC;
可见:自动化测试整个流程不像DEMO1中的那么简单,这里有多次应答,因此我们必须注意设置timeout!
因此在app_auto_test.py实现如下:
#...略
class AUTO_PROCESS:
START=0
PROCESS1=1
PROCESS2=2
FINISH=3
def __init__(self,ser):
self.auto = AUTO_PROCESS.START
self.ser = ser
def analysis_cmd(self,str):
#...略
if cmd1 == 0x08:
print "\033[1;34m>> \033[0m",
self.auto = self.PROCESS2
def run(self):
#...略
all_times = 0
fail1_times = 0
fail2_times = 0
while 1<2:
if self.auto == self.START:
all_times = all_times + 1
time.sleep(2)
self.ser.write(cmd_get_status_all)
self.auto = AUTO_PROCESS.PROCESS1
time.sleep(2)
elif self.auto == self.PROCESS1:
fail1_times = fail1_times + 1
print "fail %d" %self.auto
self.auto = self.START
elif self.auto == self.PROCESS2:
fail2_times = fail2_times + 1
print "fail %d" %self.auto
self.auto = self.START
else:
print "success %d total:%d fail1:%d fail2:%d" %(self.auto,all_times,fail1_times,fail2_times)
self.auto = self.START
FRAME的analysis_cmd函数用于解析串口返回的命令,来判断改变成员变量auto的值;run函数用于主动发送请求并等待返回,如果超时未收到返回,则会改变auto为失败,并打印结果。
链接
- 工程GITHUB地址:https://github.com/nbtool/auto_test_tool
@beautifulzzzz
智能硬件、物联网,热爱技术,关注产品
博客:http://blog.beautifulzzzz.com
园友交流群:414948975
[python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)的更多相关文章
- Raspberry pi 使用python+pySerial实现串口通信(转)
Raspberry pi 使用python+pySerial实现串口通信 转:http://blog.csdn.net/homeway999/article/details/8642353 目录( ...
- 物联网框架ServerSuperIO.Core(.netcore)跨平台,一套设备驱动通吃嵌入式、上位机、云服务
1. 概述... 2 2. ServerSuperIO.Core跨平台开发环境... 2 3. ServerSuperIO.Core特点... 2 4. Ser ...
- 【专题教程第8期】基于emWin模拟器的USB BULK上位机开发,仅需C即可,简单易实现
说明:1.如果你会emWin话的,就可以轻松制作上位机.做些通信和控制类上位机,比使用C#之类的方便程度一点不差,而且你仅会C语言就可以.2.并且成功将emWin人性化,可以做些Windows系统上的 ...
- 基于QT的全自动超声波焊接机上位机追溯系统(已经在设备上应用)
应用说明: 本上位机程序是我在做锂电池产线项目的时候开发的,用于采集设备数据以及实现设备自动控制,下位机采用基恩士PLC,超声波机采用上海一家的超声波焊接机,实现电芯极耳的自动焊接,上位在设备焊接过程 ...
- 基于串口通信做my_printf时遇到的坑儿
首先,完成了串口向终端putty的打印函数ConsolePrint(),但该函数只能打印字符串,无法像stdio库中的printf函数一样打印整数和浮点数等. 因此,我先是使用了标准库stdio中的s ...
- VS2013+MFC串口控件的简单上位机
因为做东西,正好用到这里.所以就上传了文件分享一下. 利用VS带的MFC库,用起来还是比较方便的.空间的程序构架都是自动生成的,具体的程序自己加进去就行. 里面有整个的工程 还带有一个生成的EXE文件 ...
- 基于FPGA的电压表与串口通信(上)
实验原理 该实验主要为利用TLC549采集模拟信号,然后将模拟信号的数字量通过串口发送到PC上上位机进行显示,使用到的TLC549驱动模块在进阶实验已经使用到了,串口模块在基础实验也已经使用到了,本实 ...
- 张高兴的 .NET Core IoT 入门指南:(五)串口通信入门
在开始之前,首先要说明的是串口通信所用到的 SerialPort 类并不包含在 System.Device.Gpio NuGet 包中,而是在 System.IO.Ports NuGet 包中.之所以 ...
- 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现
目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...
随机推荐
- I2C与SMBus
关于I2C与SMBus,许多人很少去谈论与了解两者的细节差异,包括很多国外的简报,文章也经常将两者混写.交杂描述.交替运用. 确实,在一般运用下,I2C Bus与SMBus没有太大的差别,从实际接线上 ...
- java利用反射动态加载方法
@参考文章 根据特定字符串加载相应的方法,有人用if else,有人用switch.参数少了或情况少了还好,很多方法真要命,不要紧,java反射拯救你 import java.lang.reflect ...
- AWR不能自动生成快照
尝试手工生成,报错sysaux表空间满. BEGIN DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT (); END; 检查DBA_HIST_SNAPSHOT和dba ...
- FPGA學習筆記(肆)--- Star Test Bench Template Writer
上一篇testbench我自己也沒怎麽搞懂,再來一篇學習特權同學的方法. 課程:Lesson 7 BJ EPM240学习板实验1——分频计数实验 鏈接:https://www.youtube.com/ ...
- Numpy 创建数组
ndarray 数组除了可以使用底层 ndarray 构造器来创建外, 也可以通过以下几种方式来创建. numpy.empty numpy.empty 方法用来创建一个指定形状(shape),数据类型 ...
- WebDriver中的操作使用
1.WebDriver中使用jquery假如设定jquery包的路径为path,则程序如下: String jquery=null; FileInputStream input = new FileI ...
- TwinStickShooter的一些问题
TwinStickShooter模板应该是比较好的了解UE基本Pawn和Projectile的一个C++例子.以下是一些问题. 一.这个模板以纯C++编写,没有蓝图,所以第一步,我想测试下如何引用蓝图 ...
- Koa源码分析(三) -- middleware机制的实现
Abstract 本系列是关于Koa框架的文章,目前关注版本是Koa v1.主要分为以下几个方面: Koa源码分析(一) -- generator Koa源码分析(二) -- co的实现 Koa源码分 ...
- 将 Desktop Central 与帮助台和 OS Deployer 集成
将 Desktop Central 与帮助台和 OS Deployer 集成 Desktop Central 可以与以下应用程序集成: 帮助台 OS Deployer Asset Explorer 与 ...
- (PMP)第4章-----项目整合管理
4.1 制定项目章程 输入 工具与技术 输出 1.商业文件 (商业论证,效益管理计划) 1.专家判断 1.项目章程 2.协议 2.数据收集 (头脑风暴,焦点小组,访谈) 2.假设日志 3.事业环境因素 ...