为基于网络udp通信的固件协议进行测试,用QT编写测试工具。其间遇到了一些问题,并逐个解决。特记录在此。
1. 因为基于网络协议,所以需要获取IP,方便发送并接收UDP数据。但因虚拟网卡等,所以需要筛选IP。
QHostAddress addr; QList<QHostAddress> list = QNetworkInterface::allAddresses(); foreach (addr, list) { if(addr.protocol() == QAbstractSocket::IPv4Protocol){ if (addr.toString().contains("192.168")){ address = QHostAddress(addr.toString()); } } }
而在发送命令时,若是以广播方式发送,则也需要考虑使用哪块网卡进行广播。因此要先绑定ip。
udpCMDSocket = new QUdpSocket(this); udpCMDSocket->bind(QHostAddress(ip)); udpCMDSocket->writeDatagram(cmd.toLocal8Bit(), HubAddr, port);
2. 当在主UI上临时需要做高占用的任务如while循环时,可以用QApplication::processEvents()来响应界面上的待处理事件。
while (!binFile.atEnd() { QByteArray byte = binFile.read(len); 。。。 sendCMD2Port(cmd, HubAddr, port); Sleep(interval); QApplication::processEvents(); }
3. 打开文件,若已有路径显示已有路径
QString tmpBinfile; if (BinFilePath.size() == 0) tmpBinfile = QFileDialog::getOpenFileName(this, tr("Open Bin File"), ".", tr("Bin File(*.bin)")); else tmpBinfile = QFileDialog::getOpenFileName(this, tr("Open Bin File"), BinFilePath, tr("Bin File(*.bin)"));
4. 读取文件,生成QListWidget,并排序
bool CaseInsSort(const QString &info1, const QString &info2) { return info1.toLower() < info2.toLower(); } void loadCases() { QFile file(filename); if (file.open(QFile::ReadWrite|QIODevice::Text)){ QTextStream data(&file); QStringList fonts; QString line1; QString line2; while (!data.atEnd()){ line1 = data.readLine(); line2 = data.readLine(); fonts<<line1; caseHash.insert(line1,line2); } qSort(fonts.begin(), fonts.end(), CaseInsSort); caseList->addItems(fonts);//把各行添加到listwidget file.close(); } }
5. QListWidgetItem改名
void renameCase() { QListWidgetItem *caseItem = caseList->currentItem(); if (caseItem){ caseList->openPersistentEditor(caseItem); } }
6. 发送UDP命令
void sendCMD2Port(QString cmd, QHostAddress HubAddr, int port) { udpCMDSocket = new QUdpSocket(this); udpCMDSocket->writeDatagram(cmd.toLocal8Bit(), HubAddr, port); udpCMDSocket->close(); }
7. 监听线程独立于主线程,包括对监听数据处理都在run中
void listenPortThread::run()
{
QUdpSocket udpListenSocket;
bool result = udpListenSocket.bind(address, port,QUdpSocket::ShareAddress);//绑定到指定的端口号
if(!result)//若绑定不成功,给出出错信息
{
udpListenSocket.close();
stop();
return;
}
islisten = true;
m_bStop = false;
while(!m_bStop)
{
QByteArray array;
QHostAddress address;
quint16 port;
if (islisten){
while (udpListenSocket.hasPendingDatagrams()) {
array.resize(udpListenSocket.pendingDatagramSize());//根据可读数据来设置空间大小
udpListenSocket.readDatagram(array.data(),array.size(),&address,&port); //读取数据
QString str = array;
。。。
8.单次定时器控制,判断是否在时限内收到回复。到时间在timeout函数中判断。
QTimer::singleShot(1500,this,SLOT(timeout())); sendCMD2Port(cmd, HubAddr, port);
9. 解析收到的json回复,通过关键字查询结果
bool listenPortThread::parseJson(QByteArray array, QString *sendID, QString *result, QString key){ QJsonParseError jsonError; QJsonDocument doucment = QJsonDocument::fromJson(array, &jsonError); // 转化为 JSON 文档 if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误 if (doucment.isObject()) { // JSON 文档为对象 QJsonObject object = doucment.object(); // 转化为对象 if (!key.isEmpty() && object.contains(key)){ QJsonValue Jvalue = object.value(key); if (Jvalue.isString()) { QString strvalue = Jvalue.toString(); *result = strvalue; } }
10. 返回的json数据,包括base64数据时,解码并还原为float
QJsonValue Jdata = object1.value("data"); if (Jdata.isString()) { QString strdata = Jdata.toString(); QByteArray Hex = QByteArray::fromBase64(strdata.toLatin1()).toHex(); QString calidata = ""; for (int i=0; i<12; i++){ QString str =Hex.mid(i*8+6,2)+Hex.mid(i*8+4,2)+Hex.mid(i*8+2,2)+Hex.mid(i*8,2); //低位到高位 int iHex = str.toUInt(0,16); float fHex = *(float*)&iHex ; calidata += QString("%1, ").arg(fHex); } *result = calidata; }
11. 在pro文件中通过VERSION设定APP版本号,并在程序中获取APP版本号
VERSION = 0.0.0.1
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
In the main.cpp:
#include <QApplication>
QCoreApplication::setApplicationVersion(QString(APP_VERSION));
Wherever else in your sources, e.g. in the imaginary controller.cpp:
#include <QApplication>
QString yourAppVersion = QCoreApplication::applicationVersion();
12. 发布release版本程序,自动打包QT所需动态库
Windows开发环境下windeployqt工具 (如果你已经将Qt的bin目录加入PATH环境,那么你可以直接在命令行使用windeployqt调用.)。首先,将项目中的release文件中的可执行文件拷到一个新建的文件夹中,例如project.exe,用Qt自带的生成必备的dll文件的程序windeployqt,来把必要的动态库拷到该文件夹中,打开命令行,输入windeployqtproject.exe,这时候大部分的dll文件都自动拷贝过来了,但是如果项目还用了一些其他的SDK,比如OpenCV,Chartdir51等等,就需要手动将所需dll拷贝过来,如果不知道还需要哪些软件,可以用Dependency Walker来查看缺少哪些dll文件。
注意:如果发布的应用是Qt Quick Application应用,那么命令行需要加上QML的安装目录。命令中的D:\Qt\Qt5.5.1\qml是qml的安装目录,请换成你自己的qml安装目录!!!!!
windeployqt hello.exe --qmldir D:\Qt\Qt5.5.1\qml
接下来要高大上的朋友就可以用Enigma VirtualBox软件虚拟化工具将多个文件封装到应用程序主文件,从而制作成为单执行文件的绿色软件。
相关推荐
一个基于Qt的串口通信协议解析和串口通信的程序,能实现串口的读写,和自定串口协议的解析,十分方便。
Ymodem固件更新上位机,串口程序(c++),qt5.11.0 mingw32位. 实现的上位机,没有在正规的Ymodem下位机上尝试过。看网络资料,起始包的里的文件长度是16进制字符串,本程序用的是10进制字符串。有点类似超级终端。
qt5的硬件信息获取,在qt5.11下,直接打开项目,然后构建,再运行即可
Qt Modbus协议使用
使用QT C++ 检测系统的计算机名称、cpu、显卡、内存、操作系统、几个屏幕以及每个屏幕的分辨率、硬盘信息、IP、MAC地址、公网IP、以及是否能够联网等信息 详情与效果图见博客:...
本demo模拟了TCP通信中发送端和接收端的行为,并利用序列化和反序列化的思想,自定义协议来解决TCP的粘包和拆包问题。
资源名:QT用SNAP7协议和西门子PLC 通讯实例源码.zip 资源类型:程序源代码 源码说明:该程序是 QT用SNAP7写的 和西门子PLC 通讯的例子 ,可编辑。可打开。支持 对西门子PLC 任意区域 读写 bit,byte,word/Dword,...
Qt5案例之利用QProcess获取计算机硬件信息,介绍利用QProcess获取计算机的CPU、主板、硬盘等电脑相关硬件信息。windows提供了“wmic”(Windows Management Instrumentation,Windows管理工具),提供了从命令行接口...
Qt下,做一个界面软件来控制单片机的协议,控制LED,时钟,超声波,温度监测。
qt uvc摄像头测试,测试没问题,查看设备号,在代码里修改对应的/dev/video
QT5的UDP多播测试代码 QT5.12,带界面,按钮,测试,有助于理解组播的
Qt 写的一个测试小程序,用来实时监测电脑所有的U盘或者移动磁盘的个数及容量。启动软件时获取电脑所有的移动磁盘,并分别存储各个移动磁盘的可用容量和总容量。并且监控U盘的拔插,实时更新当前电脑U盘个数及他们的...
1、支持串口协议ModbusRTU,软件启动自动加载可用串口 2、支持网络通讯协议ModbusTCP,自动识别可用IP地址 3、支持保存寄存器读写测试,地址可任意...9、使用Qt开发,可编译到多个平台 10、如需要其它功能可进行定制
Qt6案例之利用QProcess获取计算机硬件信息,介绍利用QProcess获取计算机的CPU、主板、硬盘等电脑相关硬件信息。windows提供了“wmic”(Windows Management Instrumentation,Windows管理工具),提供了从命令行接口...
基于Qt开发环境,C++语言,利用TCP网络协议编写了客户端和服务器端的程序,可以实现客户端向服务器端发送数据。
qt乱码问题解决
Qt正则表达式测试工具,可以直接测试正则表达式是否正确。注意:工具中测试好的表达式,写到代码里面需要加转义字符
基于qt4-5的,基于开源modbus协议,基于qt串口,可以配置为linux或windows平台编译都可以,作为串口,网络通讯的学习也是一个不错的资源
linux+QT下基于RTP协议的实时视频传输客户端和服务端,使用JRTPLIB库,客户端能够主动的发现在线的服务器,服务器也能够知道那些客户端需要视频流。服务器加入了opencv的人脸识别
解压后点击.pro文件,打开编译后可直接运行,可根据自己需要修改相应的源码以适应实际的需求。