一、前言
本编文章记录在使用嵌入式系统中的一些功能测试demo程序,大部分都是AI写的,哈哈哈,确实很有帮助,但是得根据自身设备实际情况和知道如何问AI,才能得出你想要的结果,本文就记录一些ubuntu/麒麟系统实际使用过程中测试程序。
目录
二、环境
RK3588(linux5.10.66+debian/ubuntu/麒麟是桌面文件系统)
调试笔记本window10,安装常用工具winscp,xshell,finalshell,secureRTP等等
VMware17+Ubuntu20.04源码开发环境(这里就依赖于各个硬件平台的厂家提供资料了)
QT5.7
三、正文
程序都是QT环境开发的程序,程序内容放的都是核心代码,相关头文件简单补充,或者直接参考核心代码继续询问AI即可,大部分AI都是可以解决的
统一说明main.cpp引用了全局函数MySleep(),common.h也都是头文件
main.cpp
//延时usetime:非阻塞时间 waittime:阻塞时间
void MySleep(uint usetime,ulong waittime)
{
QCoreApplication::processEvents(QEventLoop::AllEvents, usetime);//进入此函数内给之前数据usetime毫秒时间处理,处理完立马退出执行之后,超时立马退出
QThread::msleep(waittime);//阻塞延时waittime毫秒
}
common.h
#ifndef COMMON_H
#define COMMON_H
#include <QVector>
#include <QMap>
#include <QApplication>
#include <QMainWindow>
#include <QtSql>
#include <QSqlQuery>
#include <QSqlTableModel>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
#include <QPixmap>
#include <QPaintEvent>
#include <QPainter>
#include <QScrollBar>
#include <QTableWidget>
#include <QListWidgetItem>
#include <QTimer>
#include <QTime>
#include <QSystemTrayIcon>
#include <QGridLayout>
#include <QPushButton>
#include <QDoubleSpinBox>
#include <QAbstractItemView>
#include <QDoubleSpinBox>
#include <QThread>
extern void MySleep(uint usetime,ulong waittime);
#endif // COMMON_H
1.串口测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);
this->setWindowTitle("RK3588 串口接口测试软件V1.0/20241016");
//初始化串口
open_serialport(0,NULL);//初始化串口
connect(ui->pushButton_refresh,&QPushButton::clicked,[=](){//刷新串口按键回调函数
ui->comboBox->clear();
//遍历当前存在的串口端口号
if(!serial->portName().isNull())ui->comboBox->addItem(serial->portName());//显示已经开启的串口到列表
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite)){
ui->comboBox->addItem(serial.portName());
serial.close();
}
}
});
QTimer::singleShot(100,this,[=](){ui->pushButton_refresh->click();});//点击一次按键
timeserialCOM=new QTimer(this);
connect(timeserialCOM,&QTimer::timeout,[=](){
timeserialCOM->stop();
comBatAnalyze(allDataCOM);//处理串口得到的数据
});
//发送数据
connect(ui->btn_send_1,&QPushButton::clicked,[=](){
if(serial->isOpen()){
QByteArray sd=QByteArray::fromHex("11223344556677889900aabbccddeeffAABBCCDDEEFF");
serial->write(sd);
}
});
QTimer *time1=new QTimer(this);
time1->start(10);
connect(time1,&QTimer::timeout,[=](){
if(ui->checkBox_1->isChecked())ui->btn_send_1->click();
});
//清空数据
connect(ui->btn_clear_1,&QPushButton::clicked,[=](){
ui->textEdit_1->clear();
});
}
MainWindow::~MainWindow()
{
serial->clear();//先关闭之前的串口
serial->close();
delete ui;
}
//初始化/复位串口
void MainWindow::open_serialport(bool reset,QString comstr)
{
if(reset){
serial->clear();//先关闭之前的串口
serial->close();
}
serial = new QSerialPort(comstr,this);
serial->open(QIODevice::ReadWrite);//读写打开
serial->setBaudRate(QSerialPort::Baud115200); //波特率QSerialPort::Baud9600
serial->setDataBits(QSerialPort::Data8); //数据位
serial->setParity(QSerialPort::NoParity); //无奇偶校验
serial->setStopBits(QSerialPort::OneStop); //1停止位
serial->setFlowControl(QSerialPort::NoFlowControl); //无控制
connect(serial,SIGNAL(readyRead()),this,SLOT(serialRead()));//连接串口读取函数
bool open=serial->isOpen();
if(open){
ui->comboBox->setCurrentText(comstr);
if(comstr.isNull())ui->label_324->setText("当前未开启串口,请选择");
else ui->label_324->setText("当前开启串口:"+comstr);
}
else{
if(comstr.isNull())ui->label_324->setText("当前未开启串口,请选择");
else ui->label_324->setText("串口打开失败,无效或被占用");
}
}
void MainWindow::serialRead()
{
timeserialCOM->start(10);//设置判断10ms内接收完毕数据,在处理
while (!serial->atEnd()){
allDataCOM += serial->readAll().toHex();
}
}
void MainWindow::comBatAnalyze(QByteArray &allData)
{
QByteArray dataTemp;
dataTemp=allData.toUpper();
// qDebug()<<"comBatAnalyze:"<<dataTemp;
QString str;
QByteArray aaa=QByteArray::fromHex(dataTemp);
for(int i=0;i<aaa.size();i++)str.append(QString("%1 ").arg((uchar)aaa[i],2,16,QChar('0')).toUpper());
ui->textEdit_1->append(QDateTime::currentDateTime().toString("hh:mm:ss zzz : ")+str);
dataTemp.clear();//若没有需求的数据,则清除整个数据内容,重新接收判断
allData=dataTemp;
}
void MainWindow::on_comboBox_activated(const QString &arg1)
{
open_serialport(1,arg1);//重新连接选择的串口
ui->pushButton_refresh->click();//点击一次按键刷新串口资源
}
2.CAN测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);
this->setWindowTitle("RK3588 CAN接口测试软件V1.0/20240925");
#ifndef WINDOWS
//新建CAN连接//开启原生CAN2路
startcan(0);//开启CAN0
startcan(1);//开启CAN1
#endif
MySleep(1000,500);
//新建CAN连接//开启图莫斯1个CAN盒2路 CAN3 CAN4
canThread=new canRevThread(this);
connect(canThread,&canRevThread::threadRev1,this,&MainWindow::canAnalyze3);
connect(canThread,&canRevThread::threadRev2,this,&MainWindow::canAnalyze4);
canThread->start();
//发送数据
connect(ui->btn_send_1,&QPushButton::clicked,[=](){
sendcan12(0);
});
connect(ui->btn_send_2,&QPushButton::clicked,[=](){
sendcan12(1);
});
connect(ui->btn_send_3,&QPushButton::clicked,[=](){
sendcan3();
});
connect(ui->btn_send_4,&QPushButton::clicked,[=](){
sendcan4();
});
QTimer *time1=new QTimer(this);
time1->start(10);
connect(time1,&QTimer::timeout,[=](){
if(ui->checkBox_1->isChecked())ui->btn_send_1->click();
if(ui->checkBox_2->isChecked())ui->btn_send_2->click();
if(ui->checkBox_3->isChecked())ui->btn_send_3->click();
if(ui->checkBox_4->isChecked())ui->btn_send_4->click();
});
//清空数据
connect(ui->btn_clear_1,&QPushButton::clicked,[=](){
ui->textEdit_1->clear();
});
connect(ui->btn_clear_2,&QPushButton::clicked,[=](){
ui->textEdit_2->clear();
});
connect(ui->btn_clear_3,&QPushButton::clicked,[=](){
ui->textEdit_3->clear();
});
connect(ui->btn_clear_4,&QPushButton::clicked,[=](){
ui->textEdit_4->clear();
});
}
MainWindow::~MainWindow()
{
stopcan();//程序退出,关闭当前开启的CAN1/2
canThread->stopThread();//程序退出,关闭当前开启的CAN3/4
delete ui;
}
///can1/2通讯配置(系统自带CAN2路)/
//开启can1/2
void MainWindow::startcan(int v)
{
#ifndef WINDOWS
if(v == 0){
// setuid(0);
system("sudo ifconfig can0 down");
system("sudo ip link set can0 up type can bitrate 500000 triple-sampling on");
system("sudo ifconfig can0 up");
//创建套接字
//PF_CAN 为域位 同网络编程中的AF_INET 即ipv4协议
//SOCK_RAW使用的协议类型 SOCK_RAW表示原始套接字 报文头由自己创建
//CAN_RAW为使用的具体协议 为can总线协议
socket1 = ::socket(PF_CAN,SOCK_RAW,CAN_RAW);//创建套接字
struct ifreq ifr;//接口请求结构体
strcpy((char *)(ifr.ifr_name),v == 0 ? "can0" : "can1");//判断开启的是can0/1
//fcntl(socket, F_SETFL, 1); //标志FNDELAY可以保证read函数在端口上读不到字符的时候返回0
fcntl(socket1, F_SETFL, 0); //回到正常(阻塞)模式
ioctl(socket1,SIOCGIFINDEX,&ifr);//指定 CAN0/1 设备
addr1.can_family = AF_CAN;//协议类型
addr1.can_ifindex = ifr.ifr_ifindex;//can总线外设的具体索引 类似 ip地址
bind(socket1,(struct sockaddr*)&addr1,sizeof(addr1));//将套接字和canbus外设进行绑定,即套接字与 can0/1 绑定
//禁用过滤规则,进程不接收报文,只负责发送,如需接受注释掉此函数即可
//setsockopt(stSocket_LO, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
t1 = NULL;
t1 = new Thread(socket1);//开启单独线程接受监听
connect(t1,SIGNAL(message(QString,int,QString)),this,SLOT(msg1(QString,int,QString)));
t1->start();
}
else{
// setuid(0);
system("sudo ifconfig can1 down");
system("sudo ip link set can1 up type can bitrate 500000 triple-sampling on");
system("sudo ifconfig can1 up");
//创建套接字
//PF_CAN 为域位 同网络编程中的AF_INET 即ipv4协议
//SOCK_RAW使用的协议类型 SOCK_RAW表示原始套接字 报文头由自己创建
//CAN_RAW为使用的具体协议 为can总线协议
socket2 = ::socket(PF_CAN,SOCK_RAW,CAN_RAW);//创建套接字
struct ifreq ifr;//接口请求结构体
strcpy((char *)(ifr.ifr_name),v == 0 ? "can0" : "can1");//判断开启的是can0/1
//fcntl(socket, F_SETFL, 1); //标志FNDELAY可以保证read函数在端口上读不到字符的时候返回0
fcntl(socket2, F_SETFL, 0); //回到正常(阻塞)模式
ioctl(socket2,SIOCGIFINDEX,&ifr);//指定 CAN0/1 设备
addr2.can_family = AF_CAN;//协议类型
addr2.can_ifindex = ifr.ifr_ifindex;//can总线外设的具体索引 类似 ip地址
bind(socket2,(struct sockaddr*)&addr2,sizeof(addr2));//将套接字和canbus外设进行绑定,即套接字与 can0/1 绑定
//禁用过滤规则,进程不接收报文,只负责发送,如需接受注释掉此函数即可
//setsockopt(stSocket_LO, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
t2 = NULL;
t2 = new Thread(socket2);//开启单独线程接受监听
connect(t2,SIGNAL(message(QString,int,QString)),this,SLOT(msg2(QString,int,QString)));
t2->start();
}
#endif
}
void MainWindow::stopcan()
{
#ifndef WINDOWS
if(t1){//如果线程已经开启,关闭线程
t1->stop();
t1->deleteLater();
}
if(t2){//如果线程已经开启,关闭线程
t2->stop();
t2->deleteLater();
}
::close(socket1);
::close(socket2);
system("sudo ifconfig can0 down");//关闭CAN0
system("sudo ifconfig can1 down");//关闭CAN1
#endif
}
void MainWindow::sendcan12(int v)
{
#ifndef WINDOWS
struct can_frame frame;
memset(&frame,0,sizeof(struct can_frame));
if(v==0){
// frame.can_id = (0x00123456 & CAN_EFF_MASK) | CAN_EFF_FLAG;//扩展帧
frame.can_id = (0x11 & CAN_SFF_MASK);//标准帧
frame.can_dlc= 8;
frame.data[0]= 0x11;
frame.data[1]= 0xaa;
frame.data[2]= 0x11;
frame.data[3]= 0xaa;
frame.data[4]= 0x11;
frame.data[5]= 0xaa;
frame.data[6]= 0x11;
frame.data[7]= 0xaa;
}
else{
// frame.can_id = (0x00abcdef & CAN_EFF_MASK) | CAN_EFF_FLAG;//扩展帧
frame.can_id = (0x22 & CAN_SFF_MASK);//标准帧
frame.can_dlc= 8;
frame.data[0]= 0x22;
frame.data[1]= 0xbb;
frame.data[2]= 0x22;
frame.data[3]= 0xbb;
frame.data[4]= 0x22;
frame.data[5]= 0xbb;
frame.data[6]= 0x22;
frame.data[7]= 0xbb;
}
//发送can数据:方式一
//sendto(socket,&frame,sizeof(struct can_frame),0,(struct sockaddr*)&addr,sizeof(addr));
//发送can数据:方式二
if(v==0)write(socket1, &frame, sizeof(frame)); //发送 frame
else write(socket2, &frame, sizeof(frame)); //发送 frame
return;
#endif
}
//can1接收槽函数
void MainWindow::msg1(QString addr,int num,QString data)
{
QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(addr).arg(num).arg(data);
ui->textEdit_1->append(str);
}
//can2接收槽函数
void MainWindow::msg2(QString addr,int num,QString data)
{
QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(addr).arg(num).arg(data);
ui->textEdit_2->append(str);
}
///can3/4通讯配置(图莫斯1个盒2路)/
//发送can3
void MainWindow::sendcan3()
{
CAN_MSG CanMsg;
CanMsg.ExternFlag = 0;//是否是扩展帧
CanMsg.RemoteFlag = 0;//是否是远程帧
CanMsg.ID = 0x33;
CanMsg.DataLen = 8;
CanMsg.Data[0]=0x33;
CanMsg.Data[1]=0xcc;
CanMsg.Data[2]=0x33;
CanMsg.Data[3]=0xcc;
CanMsg.Data[4]=0x33;
CanMsg.Data[5]=0xcc;
CanMsg.Data[6]=0x33;
CanMsg.Data[7]=0xcc;
canThread->sendcanData(0,CanMsg);
}
//发送can4
void MainWindow::sendcan4()
{
CAN_MSG CanMsg;
CanMsg.ExternFlag = 0;//是否是扩展帧
CanMsg.RemoteFlag = 0;//是否是远程帧
CanMsg.ID = 0x44;
CanMsg.DataLen = 8;
CanMsg.Data[0]=0x44;
CanMsg.Data[1]=0xdd;
CanMsg.Data[2]=0x44;
CanMsg.Data[3]=0xdd;
CanMsg.Data[4]=0x44;
CanMsg.Data[5]=0xdd;
CanMsg.Data[6]=0x44;
CanMsg.Data[7]=0xdd;
canThread->sendcanData(1,CanMsg);
}
//处理can3数据
void MainWindow::canAnalyze3(CAN_MSG *CanMsgtmp,char dwRel)
{
for(int i = 0 ; i < dwRel ; i++){
QString address=QString().sprintf("%08X",CanMsgtmp[i].ID&0x7fffffff);
QString datastr=NULL;
for(int j=0;j<CanMsgtmp[i].DataLen;j++)
datastr.append(QString().sprintf("%02X",CanMsgtmp[i].Data[j]));
QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(address).arg(CanMsgtmp[i].DataLen).arg(datastr);
ui->textEdit_3->append(str);
}
}
//处理can4数据
void MainWindow::canAnalyze4(CAN_MSG *CanMsgtmp, char dwRel)
{
for(int i = 0 ; i < dwRel ; i++){
QString address=QString().sprintf("%08X",CanMsgtmp[i].ID&0x7fffffff);
QString datastr=NULL;
for(int j=0;j<CanMsgtmp[i].DataLen;j++)
datastr.append(QString().sprintf("%02X",CanMsgtmp[i].Data[j]));
QString str = QString("%1\r\n%2,%3,%4").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(address).arg(CanMsgtmp[i].DataLen).arg(datastr);
ui->textEdit_4->append(str);
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "common.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
private slots:
//CAN12 linux自带的socketcan
void sendcan12(int v);
void stopcan();
void startcan(int v);
void msg1(QString addr, int num, QString data);
void msg2(QString addr, int num, QString data);
//CAN34 USB扩展图莫斯can
void sendcan3();
void sendcan4();
void canAnalyze3(CAN_MSG *CanMsgtmp, char dwRel);
void canAnalyze4(CAN_MSG *CanMsgtmp, char dwRel);
private:
Ui::MainWindow *ui;
#ifndef WINDOWS
int socket1;
struct sockaddr_can addr1;//can总线的地址 同socket编程里面的 socketaddr结构体 用来设置can外设的信息
Thread *t1;
int socket2;
struct sockaddr_can addr2;//can总线的地址 同socket编程里面的 socketaddr结构体 用来设置can外设的信息
Thread *t2;
#endif
canRevThread *canThread;
};
#endif // MAINWINDOW_H
thread
cpp
#include "thread.h"
#include "mainwindow.h"
Thread::Thread(int s,QObject *parent) :
QThread(parent)
{
socket = s;
running = true;
}
void Thread::run()
{
#ifndef WINDOWS
//qDebug()<<"start can receive Thread!";
int nbytes;
// int len;
struct can_frame frame;
// struct sockaddr_can addr;
// char buf[8];
while(running){
// nbytes=recvfrom(socket,&frame,sizeof(struct can_frame),0,(struct sockaddr *)&addr,(socklen_t*)&len);
//接收can数据:方式一
// if(nbytes>0){
// memset(buf,0,8);
// strncpy(buf,(char*)frame.data,8);
// //emit message(&addr,&len);
// printf("id=%x,len=%d\n",(struct sockaddr *)&addr,(socklen_t*)&len);
// }
//接收can数据:方式二
nbytes = read(socket, &frame, sizeof(frame)); //接收报文
if(nbytes > 0){
QString address=QString().sprintf("%08X",frame.can_id&0x7fffffff);
QString data=NULL;
for(int i=0;i<frame.can_dlc;i++)
data.append(QString().sprintf("%02X",frame.data[i]));
emit message(address,frame.can_dlc,data);
// printf("iiid=%x,len=%d,data=%x%x%x%x%x%x%x%x\n",frame.can_id&0x7fffffff,frame.can_dlc,frame.data[0],frame.data[1],frame.data[2],frame.data[3],frame.data[4],frame.data[5],frame.data[6],frame.data[7]);
}
}
#endif
}
void Thread::stop()
{
running = false;
}
h
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#ifndef WINDOWS
extern "C" {
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can.h>
}
#endif
#ifndef PF_CAN
#define PF_CAN 29
#endif
#ifndef AF_CAN
#define AF_CAN PF_CAN
#endif
class Thread : public QThread
{
Q_OBJECT
public:
explicit Thread(int s,QObject *parent = 0);
signals:
void message(QString addr,int num,QString data);
public slots:
void run();
void stop();
private:
int socket;
bool running;
};
#endif // THREAD_H
usbcanthread
cpp
#include "canrevthread.h"
#include <QMessageBox>
canRevThread::canRevThread( QObject *parent):QThread(parent)
{
DevHandle=0x04ff;
stopped = 1;
bool state;
int ret;
int DevHdle[10];
//扫描查找设备
ret = USB_ScanDevice(DevHdle);
if(ret <= 0){
qDebug()<<QString().sprintf("No device connected!");
stopped=0;
return;
}
else{
qDebug()<<"handle:"<<DevHdle[0];
}
//打开设备
DevHandle=DevHdle[0];
state = USB_OpenDevice(DevHandle);
if(!state){
qDebug()<<QString().sprintf("Open device error!");
stopped=0;
return;
}
//初始化配置CAN
CAN_INIT_CONFIG CANConfig;
// CANConfig.CAN_Mode = 1;//环回模式
CANConfig.CAN_Mode = 0;//正常模式
CANConfig.CAN_ABOM = 0;//禁止自动离线
CANConfig.CAN_NART = 1;//禁止报文重传
CANConfig.CAN_RFLM = 0;//FIFO满之后覆盖旧报文
CANConfig.CAN_TXFP = 1;//发送请求决定发送顺序
//配置波特率,波特率 = 42M/(BRP*(SJW+BS1+BS2))
//can通信波特率500k
CANConfig.CAN_BRP = 4;//4
CANConfig.CAN_BS1 = 16;//16
CANConfig.CAN_BS2 = 4;//4
CANConfig.CAN_SJW = 1;//1
CANConfig.CAN_Mode |= 0x80; //使能接入内部终端电阻
ret = CAN_Init(DevHandle,0,&CANConfig);
if(ret != CAN_SUCCESS){
qDebug()<<QString().sprintf("Config CAN 3 failed!");
stopped=0;
return;
}else{
qDebug()<<QString().sprintf("Config CAN 3 Success!");
}
ret = CAN_Init(DevHandle,1,&CANConfig);
if(ret != CAN_SUCCESS){
qDebug()<<QString().sprintf("Config CAN 4 failed!");
stopped=0;
return;
}else{
qDebug()<<QString().sprintf("Config CAN 4 Success!");
}
//配置过滤器,必须配置,否则可能无法收到数据
CAN_FILTER_CONFIG CANFilter;
CANFilter.Enable = 1;
CANFilter.ExtFrame = 0; //过滤的帧类型标志,为1 代表要过滤的为扩展帧,为0 代表要过滤的为标准帧。
CANFilter.FilterIndex = 0;
CANFilter.FilterMode = 0;
CANFilter.MASK_IDE = 0;
CANFilter.MASK_RTR = 0;
CANFilter.MASK_Std_Ext = 0;
CAN_Filter_Init(DevHandle,0,&CANFilter);
CAN_Filter_Init(DevHandle,1,&CANFilter);
}
canRevThread::~canRevThread()
{
stopped = 0;
requestInterruption();
quit();
wait();
USB_CloseDevice(DevHandle);
}
void canRevThread::sendcanData(uchar index,CAN_MSG &CanD)
{
int SendedNum = CAN_SendMsg(DevHandle,index,&CanD,1);
if(SendedNum <= 0){
// qDebug()<<QString().sprintf("CAN1 send FAIL %1",SendedNum);
}
}
void canRevThread::run()
{
CAN_MSG CanMsgBuffer1[100],CanMsgBuffer2[100];//最大支持100帧
char CanNum1=0;
char CanNum2=0;
while(stopped){
CanNum1 = CAN_GetMsg(DevHandle,0,CanMsgBuffer1);
CanNum2 = CAN_GetMsg(DevHandle,1,CanMsgBuffer2);
if(CanNum1 > 0){
emit threadRev1(CanMsgBuffer1,CanNum1);
}
if(CanNum2 > 0){
emit threadRev2(CanMsgBuffer2,CanNum2);
}
msleep(5);
}
}
void canRevThread::stopThread()
{
stopped = 0;
}
h
#ifndef CANREVTHREAD_H
#define CANREVTHREAD_H
#include <QThread>
#include <QString>
#include <QDebug>
#include <QtCore/qglobal.h>
//#define OS_UNIX
#include "usb_device.h"
#include "usb2can.h"
#if defined(CANTHREAD_COMPILE_LIBRARY)
# define CANTHREAD_LIB_DECL Q_DECL_EXPORT
#elif defined(CANTHREAD_USE_LIBRARY)
# define CANTHREAD_LIB_DECL Q_DECL_IMPORT
#else
# define CANTHREAD_LIB_DECL
#endif
class CANTHREAD_LIB_DECL canRevThread: public QThread
{
Q_OBJECT
signals:
void threadRev1(CAN_MSG *data,char dwRel);
void threadRev2(CAN_MSG *data,char dwRel);
public:
canRevThread(QObject *parent);
~canRevThread();
void sendcanData(uchar index,CAN_MSG &CanD);
void run();
void stopThread();
private:
int stopped;
int DevHandle;
};
#endif
pro
QT += core gui sql network printsupport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = RK3588porttest
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += \
mainwindow.h \
common.h \
CustomWidget/Thread/thread.h \
CustomWidget/usbcanthread/canrevthread.h \
CustomWidget/usbcanthread/usb_device.h \
CustomWidget/usbcanthread/usb2can.h
SOURCES += \
main.cpp \
mainwindow.cpp \
CustomWidget/Thread/thread.cpp \
CustomWidget/usbcanthread/canrevthread.cpp
FORMS += \
mainwindow.ui
CONFIG += mobility
MOBILITY =
win32{
message($$QT_ARCH)
contains(QT_ARCH, i386) {
LIBS += -L$$PWD/CustomWidget/usbcanthread/window/ -lUSB2XXX
} else {
}
}
unix:!macx{
message($$QMAKE_HOST.arch)
unix:contains(QMAKE_HOST.arch, x86_64){
# LIBS += -L$$PWD/CustomWidget/usbcanthread/linux-A40i/ -lUSB2XXX
LIBS += -L$$PWD/CustomWidget/usbcanthread/linux-RK3588/ -lUSB2XXX -lusb-1.0
}
unix:contains(QMAKE_HOST.arch, x86){
}
unix:contains(QMAKE_HOST.arch, aarch64){
}
unix:contains(QMAKE_HOST.arch, armv7){
}
unix:contains(QMAKE_HOST.arch, mips64){
}
}
win32: DEFINES += WINDOWS
!win32: DEFINES += OS_UNIX
前两路2是调用系统自带的CAN,用socketcan,可以参考我A40i帖子中的一个CAN文章
后两路CAN是其他厂家的一个USB转CAN模块,需要匹配相关的驱动,与厂家要驱动文件,引用,可能需要重新根据系统编译一下libusb-1.0.so,才能在交叉编译环境中编译通过
3.背光测试程序(弥补系统pwm匹配异常)
麒麟系统连接edp或mipi屏幕时,会出现pwm不受控现象,麒麟系统与硬件没有完成适配兼容,因为在系统设置中调节亮度不好使
下面通过第三方软件或其他方法尝试解决此问题
1第三方软件方式
未找到合适工具,最终通过自己写程序修改亮度
2自写脚本定时设置亮度方式。
命令参考手册的亮度设置章节
ls /sys/class/backlight
cat /sys/class/backlight/backlight-edp1/brightness
echo 0 > /sys/class/backlight/backlight-edp1/brightness
echo 125 > /sys/class/backlight/backlight-edp1/brightness
echo 255 > /sys/class/backlight/backlight-edp1/brightness
写了一个test_backlight测试程序,当检测到亮度为0时自动设置亮度信息为上次配置的
缺点是会出现一下黑屏,闪一下
最佳解决方式是后期更换稳定系统
后续测试高版本的linux源码尝试
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QFile>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), currentBrightness(200)
{
// 初始化滑动条和标签
brightnessSlider = new QSlider(Qt::Horizontal, this);
brightnessSlider->setRange(0, 255);
brightnessSlider->setValue(currentBrightness);
brightnessLabel = new QLabel("亮度: " + QString::number(currentBrightness), this);
brightnessLabel->setFont(QFont("黑体",50));
// 布局
QWidget *centralWidget = new QWidget(this);
centralWidget->setMinimumSize(500,300);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->addWidget(brightnessLabel);
layout->addWidget(brightnessSlider);
centralWidget->setLayout(layout);
setCentralWidget(centralWidget);
// 连接滑动条信号
connect(brightnessSlider, &QSlider::valueChanged, this, &MainWindow::onSliderValueChanged);
// 初始化定时器
brightnessTimer = new QTimer(this);
connect(brightnessTimer, &QTimer::timeout, this, &MainWindow::checkAndRestoreBrightness);
brightnessTimer->start(1000); // 每1s检查一次
// 初始设置亮度
setBrightness(currentBrightness);
}
MainWindow::~MainWindow()
{
delete brightnessSlider;
delete brightnessLabel;
delete brightnessTimer;
}
void MainWindow::onSliderValueChanged(int value)
{
currentBrightness = value;
brightnessLabel->setText("亮度: " + QString::number(currentBrightness));
setBrightness(currentBrightness);
}
void MainWindow::checkAndRestoreBrightness()
{
int actualBrightness = getBrightness();
if (actualBrightness == 0) {
qDebug() << "亮度被重置为 0,恢复为" << currentBrightness;
setBrightness(currentBrightness);
}
}
void MainWindow::setBrightness(int value)
{
QFile brightnessFile("/sys/class/backlight/backlight-edp1/brightness");
if (brightnessFile.open(QIODevice::WriteOnly)) {
brightnessFile.write(QString::number(value).toUtf8());
brightnessFile.close();
} else {
qWarning() << "无法设置亮度,请检查权限或路径。";
}
}
int MainWindow::getBrightness()
{
QFile brightnessFile("/sys/class/backlight/backlight-edp1/brightness");
if (brightnessFile.open(QIODevice::ReadOnly)) {
QString brightnessValue = brightnessFile.readAll().trimmed();
brightnessFile.close();
return brightnessValue.toInt();
} else {
qWarning() << "无法读取亮度,请检查权限或路径。";
return -1;
}
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSlider>
#include <QLabel>
#include <QTimer>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onSliderValueChanged(int value);
void checkAndRestoreBrightness();
private:
QSlider *brightnessSlider;
QLabel *brightnessLabel;
QTimer *brightnessTimer;
int currentBrightness;
void setBrightness(int value);
int getBrightness();
};
#endif // MAINWINDOW_H
4.电量获取程序(弥补底系统版本不支持电池管理)
麒麟系统V10 2303默认不支持电源管理功能,没有电池图标右下角的显示
使用xx电源模块在国防版麒麟系统可以显示电量信息,但是国防版系统镜像不好用缺图标
最终还是使用2303系统,需要自己通过软件获取电量信息
等以后有了2403系统,就没有这个问题了
方法:
upower -e
upower -i /org/freedesktop/UPower/devices/ups_hiddev0
后续写了一个demo程序 test_power,用于监测电源模块电量信息,等以后写程序可以集成在程序之中
#include "mainwindow.h"
#include <QApplication>
#include <QMenu>
#include <QAction>
#include <QProcess>
#include <QMessageBox>
#include <QDebug>
#include <QPainter>
#include <QFontMetrics>
#include <QVBoxLayout>
#include <QWidget>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), isCharging(false), batteryPercentage(0), timeToEmpty(0)
{
// 创建托盘图标
createTrayIcon();
// 创建桌面 UI
QWidget *centralWidget = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
percentageLabel = new QLabel("电量: 未知", centralWidget);
timeToEmptyLabel = new QLabel("剩余时长: 未知", centralWidget);
layout->addWidget(percentageLabel);
layout->addWidget(timeToEmptyLabel);
centralWidget->setLayout(layout);
setCentralWidget(centralWidget);
centralWidget->show();
// 定时器,每分钟更新一次电量信息
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWindow::updateBatteryStatus);
timer->start(60000); // 每分钟更新一次
// 初始更新
updateBatteryStatus();
}
MainWindow::~MainWindow()
{
delete trayIcon;
delete timer;
}
void MainWindow::createTrayIcon()
{
trayIcon = new QSystemTrayIcon(this);
updateTrayIcon(); // 初始化图标
QMenu *menu = new QMenu(this);
QAction *quitAction = new QAction("退出", this);
connect(quitAction, &QAction::triggered, qApp, &QApplication::quit);
menu->addAction(quitAction);
trayIcon->setContextMenu(menu);
trayIcon->show();
connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::iconActivated);
}
void MainWindow::updateBatteryStatus()
{
QProcess process;
process.start("upower -i /org/freedesktop/UPower/devices/ups_hiddev0");
process.waitForFinished();
QString output = process.readAllStandardOutput();
parseBatteryStatus(output);
// 更新托盘图标和桌面 UI
updateTrayIcon();
updateDesktopUI();
}
void MainWindow::parseBatteryStatus(const QString &output)
{
QStringList lines = output.split("\n");
for (const QString &line : lines) {
if (line.contains("percentage")) {
batteryPercentage = line.split(":").last().trimmed().replace("%", "").toInt();
}
if (line.contains("time to empty")) {
timeToEmpty = line.split(":").last().trimmed().replace("hours", "").toDouble();
// 如果剩余时长为 18.2 小时,则认为充电器接入
isCharging = (timeToEmpty == 18.2);
}
}
}
void MainWindow::updateTrayIcon()
{
// 创建一个 64x64 的画布
QPixmap pixmap(64, 64);
pixmap.fill(Qt::transparent); // 透明背景
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制电池外框
painter.setPen(Qt::white);
painter.setBrush(Qt::transparent);
painter.drawRect(15, 20, 34, 20); // 电池外框
// 绘制电池正极
painter.drawRect(49, 25, 4, 10);
// 绘制电量填充
int fillWidth = static_cast<int>(32 * (batteryPercentage / 100.0));
painter.setBrush(Qt::green);
painter.drawRect(16, 21, fillWidth, 18);
// 绘制百分比文字
painter.setPen(Qt::white);
QFont font = painter.font();
font.setPixelSize(16); // 增大字体大小
painter.setFont(font);
// 计算文字居中位置
QFontMetrics metrics(font);
QString text = QString::number(batteryPercentage) + "%";
int textWidth = metrics.width(text); // 使用 width 替代 horizontalAdvance
int textHeight = metrics.height();
int textX = (pixmap.width() - textWidth) / 2;
int textY = (pixmap.height() + textHeight) / 2;
painter.drawText(textX, textY, text);
// 如果是充电状态,绘制闪电符号
if (isCharging) {
QPolygon lightning;
lightning << QPoint(32, 10) << QPoint(40, 20) << QPoint(32, 20)
<< QPoint(44, 40) << QPoint(32, 30) << QPoint(40, 30);
painter.setBrush(Qt::yellow);
painter.drawPolygon(lightning);
}
// 设置托盘图标
trayIcon->setIcon(QIcon(pixmap));
}
void MainWindow::updateDesktopUI()
{
// 更新电量百分比
percentageLabel->setText(QString("电量: %1%").arg(batteryPercentage));
// 更新剩余使用时长
if (isCharging) {
timeToEmptyLabel->setText("状态: 充电中");
} else {
timeToEmptyLabel->setText(QString("剩余时长: %1 小时").arg(timeToEmpty));
}
}
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
if (reason == QSystemTrayIcon::Trigger) {
updateBatteryStatus();
}
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QPixmap>
#include <QPainter>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void updateBatteryStatus();
void iconActivated(QSystemTrayIcon::ActivationReason reason);
private:
QSystemTrayIcon *trayIcon;
QTimer *timer;
bool isCharging;
int batteryPercentage;
double timeToEmpty; // 剩余使用时长(小时)
QLabel *percentageLabel;
QLabel *timeToEmptyLabel;
void createTrayIcon();
void updateTrayIcon();
void updateDesktopUI();
void parseBatteryStatus(const QString &output);
};
#endif // MAINWINDOW_H
5.GPIO测试程序控制状态led灯
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
static bool ledflag=false;
#ifdef WINDOWS
#else
//开机指令初始化指示灯gpio
system("echo 24 > /sys/class/gpio/export");//led1
system("echo out > /sys/class/gpio/gpio24/direction");
system("echo 27 > /sys/class/gpio/export");//led2
system("echo out > /sys/class/gpio/gpio27/direction");
QTimer *timeled=new QTimer(this);
timeled->start(500);
connect(timeled,&QTimer::timeout,[=](){
ledflag=!ledflag;
if(ledflag){
system("echo 0 > /sys/class/gpio/gpio24/value");
system("echo 1 > /sys/class/gpio/gpio27/value");
ui->label->setStyleSheet("background-color: rgb(0, 255, 0);");
ui->label_2->setStyleSheet("background-color: rgb(255, 0, 0);");
}
else{
system("echo 1 > /sys/class/gpio/gpio24/value");
system("echo 0 > /sys/class/gpio/gpio27/value");
ui->label->setStyleSheet("background-color: rgb(255, 0, 0);");
ui->label_2->setStyleSheet("background-color: rgb(0, 255, 0);");
}
qDebug()<<"ledflag:"<<QString::number(ledflag);
});//绑定定时分析数据函数槽
#endif
qDebug()<<"ledflag:"<<QString::number(ledflag);
ui->label->setStyleSheet("background-color: rgb(0, 255, 0);");
ui->label_2->setStyleSheet("background-color: rgb(255, 0, 0);");
}
MainWindow::~MainWindow()
{
delete ui;
}
6.时间测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDate>
#include <QTime>
#include <QPalette>
#include <stdio.h>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//setWindowState(Qt::WindowMaximized);
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
QPalette pal;
pal.setColor(QPalette::Text,QColor(255,0,0));
ui->year->setPalette(pal);
ui->month->setPalette(pal);
ui->day->setPalette(pal);
ui->hour->setPalette(pal);
ui->minute->setPalette(pal);
ui->second->setPalette(pal);
QDate d = QDate::currentDate();
QTime t = QTime::currentTime();
ui->year->setValue(d.year());
ui->month->setValue(d.month());
ui->day->setValue(d.day());
ui->hour->setValue(t.hour());
ui->minute->setValue(t.minute());
ui->second->setValue(t.second());
ui->year->setEnabled(false);
ui->month->setEnabled(false);
ui->day->setEnabled(false);
ui->hour->setEnabled(false);
ui->minute->setEnabled(false);
ui->second->setEnabled(false);
timer.start(1000,this);
connect(ui->exitBtn, &QPushButton::clicked, this, [=](){
close();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::timerEvent(QTimerEvent *event)
{
QDate d = QDate::currentDate();
QTime t = QTime::currentTime();
if(ui->set->text()=="set")
{
ui->year->setValue(d.year());
ui->month->setValue(d.month());
ui->day->setValue(d.day());
ui->hour->setValue(t.hour());
ui->minute->setValue(t.minute());
ui->second->setValue(t.second());
}
QWidget::timerEvent(event);
}
void MainWindow::on_set_clicked()
{
if(ui->set->text()=="set")
{
ui->set->setText("save");
ui->year->setEnabled(true);
ui->month->setEnabled(true);
ui->day->setEnabled(true);
ui->hour->setEnabled(true);
ui->minute->setEnabled(true);
ui->second->setEnabled(true);
timer.stop();
}
else
{
char buf[128];
ui->set->setText("set");
memset(buf,0,128);
sprintf(buf,"date -s '%4d-%02d-%02d %02d:%02d:%02d'",ui->year->text().toInt(),ui->month->text().toInt(),ui->day->text().toInt(),
ui->hour->text().toInt(),ui->minute->text().toInt(),ui->second->text().toInt());
system(buf);
system("hwclock -w");
ui->year->setEnabled(false);
ui->month->setEnabled(false);
ui->day->setEnabled(false);
ui->hour->setEnabled(false);
ui->minute->setEnabled(false);
ui->second->setEnabled(false);
timer.start(1000,this);
}
}
void MainWindow::closeEvent(QCloseEvent *)
{
//system("killall matrix_gui");
//system("/etc/init.d/qt.sh");
exit(0);
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QBasicTimer>
#include <QTimerEvent>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void timerEvent(QTimerEvent *event);
void closeEvent(QCloseEvent *);
private slots:
void on_set_clicked();
private:
Ui::MainWindow *ui;
QBasicTimer timer;
};
#endif // MAINWINDOW_H
7.redis通信测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 连接到 Redis 服务器,用于发布命令
publishContext = redisConnect("127.0.0.1", 6379);
if (publishContext == NULL || publishContext->err) {
if (publishContext) {
qDebug() << "Error: " << publishContext->errstr;
ui->textEdit->setText(QString("Error: %1").arg(publishContext->errstr));
redisFree(publishContext);
} else {
qDebug() << "Can't allocate redis context for publishing";
ui->textEdit->setText("Can't allocate redis context for publishing");
}
return;
}else {
ui->textEdit->append("redis 发布 connect successful");
}
// 连接到 Redis 服务器,用于订阅命令
subscribeContext = redisConnect("127.0.0.1", 6379);
if (subscribeContext == NULL || subscribeContext->err) {
if (subscribeContext) {
qDebug() << "Error: " << subscribeContext->errstr;
ui->textEdit->setText(QString("Error: %1").arg(subscribeContext->errstr));
redisFree(subscribeContext);
} else {
qDebug() << "Can't allocate redis context for subscribing";
ui->textEdit->setText("Can't allocate redis context for subscribing");
}
return;
}else {
ui->textEdit->append("redis 订阅 connect successful");
}
// 订阅结果频道
if (subscribeContext && !subscribeContext->err) {
redisReply *reply = static_cast<redisReply*>(redisCommand(subscribeContext, "SUBSCRIBE numpy_result pandas_result tensorflow_result sklearn_result matplotlib_result"));
if (reply) {
freeReplyObject(reply);
}
}
// 创建并启动 Redis 订阅线程
subscriberThread = new RedisSubscriberThread(subscribeContext, this);
connect(subscriberThread, &RedisSubscriberThread::messageReceived, this, [this](const QString &channel, const QString &message) {
ui->textEdit->append(channel + ": " + message);
});
subscriberThread->start();
}
MainWindow::~MainWindow()
{
if (publishContext) {
redisFree(publishContext);
}
if (subscribeContext) {
redisFree(subscribeContext);
}
if (subscriberThread) {
subscriberThread->quit();
subscriberThread->wait();
}
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
if (publishContext && !publishContext->err) {
redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH numpy_command run_numpy"));
if (reply) {
if (reply->type == REDIS_REPLY_ERROR) {
qDebug() << "Error publishing to Redis: " << reply->str;
} else {
qDebug() << "Message published successfully to numpy_command";
}
freeReplyObject(reply);
} else {
qDebug() << "Error: Failed to execute Redis command";
}
} else {
qDebug() << "Redis publish context is invalid";
}
}
void MainWindow::on_pushButton_2_clicked()
{
if (publishContext && !publishContext->err) {
redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH pandas_command run_pandas"));
if (reply) {
if (reply->type == REDIS_REPLY_ERROR) {
qDebug() << "Error publishing to Redis: " << reply->str;
} else {
qDebug() << "Message published successfully to pandas_command";
}
freeReplyObject(reply);
} else {
qDebug() << "Error: Failed to execute Redis command";
}
} else {
qDebug() << "Redis publish context is invalid";
}
}
void MainWindow::on_pushButton_3_clicked()
{
if (publishContext && !publishContext->err) {
redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH tensorflow_command run_tensorflow"));
if (reply) {
if (reply->type == REDIS_REPLY_ERROR) {
qDebug() << "Error publishing to Redis: " << reply->str;
} else {
qDebug() << "Message published successfully to tensorflow_command";
}
freeReplyObject(reply);
} else {
qDebug() << "Error: Failed to execute Redis command";
}
} else {
qDebug() << "Redis publish context is invalid";
}
}
void MainWindow::on_pushButton_4_clicked()
{
if (publishContext && !publishContext->err) {
redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH sklearn_command run_sklearn"));
if (reply) {
if (reply->type == REDIS_REPLY_ERROR) {
qDebug() << "Error publishing to Redis: " << reply->str;
} else {
qDebug() << "Message published successfully to sklearn_command";
}
freeReplyObject(reply);
} else {
qDebug() << "Error: Failed to execute Redis command";
}
} else {
qDebug() << "Redis publish context is invalid";
}
}
void MainWindow::on_pushButton_5_clicked()
{
if (publishContext && !publishContext->err) {
redisReply *reply = static_cast<redisReply*>(redisCommand(publishContext, "PUBLISH matplotlib_command run_matplotlib"));
if (reply) {
if (reply->type == REDIS_REPLY_ERROR) {
qDebug() << "Error publishing to Redis: " << reply->str;
} else {
qDebug() << "Message published successfully to matplotlib_command";
}
freeReplyObject(reply);
} else {
qDebug() << "Error: Failed to execute Redis command";
}
} else {
qDebug() << "Redis publish context is invalid";
}
}
void MainWindow::on_pushButton_6_clicked()
{
ui->textEdit->clear();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QMetaObject>
#include "QtHiRedis/hiredis.h" // 包含 hiredis 头文件
// 定义一个新的线程类来处理 Redis 订阅
class RedisSubscriberThread : public QThread {
Q_OBJECT
public:
RedisSubscriberThread(redisContext *context, QObject *parent = nullptr)
: QThread(parent), subscribeContext(context) {}
signals:
void messageReceived(const QString &channel, const QString &message);
protected:
void run() override {
if (subscribeContext && !subscribeContext->err) {
redisReply *reply;
while (true) {
int retval = redisGetReply(subscribeContext, (void**)&reply);
if (retval == REDIS_OK && reply != NULL && reply->type == REDIS_REPLY_ARRAY && reply->elements == 3) {
QString messageType = QString::fromUtf8(reply->element[0]->str);
if (messageType == "message") {
QString channel = QString::fromUtf8(reply->element[1]->str);
QString result = QString::fromUtf8(reply->element[2]->str);
emit messageReceived(channel, result);
}
}
if (reply) {
freeReplyObject(reply);
}
}
}
}
private:
redisContext *subscribeContext;
};
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
void on_pushButton_6_clicked();
private:
Ui::MainWindow *ui;
redisContext *publishContext; // 使用 hiredis 的上下文
redisContext *subscribeContext; // 使用 hiredis 的上下文
RedisSubscriberThread *subscriberThread;
};
#endif // MAINWINDOW_H
附件太多了,自己下载开源的,或者下载我的全套资源吧
8.温度、CPU主频测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
#ifdef WINDOWS
m_path=qApp->applicationDirPath();
#else
m_path="/media/root/sata";//sata是更改挂载点后的文件名,默认是UUID,没法通过程序去识别每个设备的硬盘
#endif
///timer定时器初始化,3秒进行一次数据分析,不管数据是否接收,定时分析数据以UDP形式发送到指定目标IP
QTimer *time1=new QTimer(this);
time1->start(3000);
connect(time1,&QTimer::timeout,[=](){
AnalyseData();
});//绑定定时分析数据函数槽
}
MainWindow::~MainWindow()
{
delete ui;
}
///******************************************************************定时分析数据**************************************************************///
//在时钟和硬盘挂载正常的情况下分析内存容量是否充足,大于80%要删除到60%以下,最少保留当天日期数据不可删除
//分析数据采集盒状态:时钟状态、时间、固态硬盘挂载状态、固态硬盘容量、CPU温度、CPU主频、采集盒版本信息,将数据打包放入待发送缓存中
//分析整车全部系统状态:xxx,将数据打包放入待发送缓存中
//
void MainWindow::AnalyseData()
{
///分析硬盘容量
ui->textEdit->clear();
qDebug()<<"\r\n";
qDebug()<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
ui->textEdit->append(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
qDebug()<<"/*****************check disk used******************/";
ui->textEdit->append("/*****************check disk used******************/");
if(QFile::exists(m_path)){//判断硬盘状态是否正常,异常后出正常也不给予正常状态,只要出现判断不到即报错,单次即一直触发,不消除故障
m_mSATAstatus=true;//mSATA挂载正常
QTime get_disk_usetime;//记录查询日志数据列表消耗时间
get_disk_usetime.start();
//计算mSATA_size,mSATA_used,mSATA_persent
QStorageInfo storage = QStorageInfo::root();
storage.refresh(); //获得最新磁盘信息
storage.device();
storage.setPath(m_path);
mSATA_size=storage.bytesTotal()/(1024*1024);//单位MByte
mSATA_used=mSATA_size-storage.bytesFree()/(1024*1024);
mSATA_persent=mSATA_used*100/mSATA_size;
qDebug()<<"mSATA used:"<<getsize(mSATA_used)<<",mSATA allsize:"<<getsize(mSATA_size);
qDebug()<<"mSATA use persent is "<<QString::number(mSATA_persent)<<"%,get mSATA used persent usetime:"<<QString::number(get_disk_usetime.elapsed())<<"ms";
ui->textEdit->append("mSATA used:"+getsize(mSATA_used)+",mSATA allsize:"+getsize(mSATA_size));
ui->textEdit->append("mSATA use persent is "+QString::number(mSATA_persent)+"%,get mSATA used persent usetime:"+QString::number(get_disk_usetime.elapsed())+"ms");
}
else{
qDebug()<<"mSATA err!";
ui->textEdit->append("mSATA err!");
m_mSATAstatus=false;//赋值硬盘错误状态
}
///获取数据采集盒状态
QString m_freq0,m_freq4,m_temp;//本机工作频率和温度
QString m_cpu0,m_cpu4;
#ifndef WINDOWS
QFile file("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq");//获取cpu工作主频
if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
m_freq0 = file.readLine();
file.close();
}
QFile file2("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq");//获取cpu工作主频
if (file2.open(QIODevice::ReadOnly | QIODevice::Text)){
m_freq4 = file2.readLine();
file2.close();
}
QFile file1("/sys/class/thermal/thermal_zone0/temp");//获取cpu工作温度
if (file1.open(QIODevice::ReadOnly | QIODevice::Text)){
m_temp = file1.readLine();
file1.close();
}
QFile file3("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies");//获取cpu主频范围
if (file3.open(QIODevice::ReadOnly | QIODevice::Text)){
m_cpu0 = file3.readLine();
file3.close();
}
QFile file4("/sys/devices/system/cpu/cpu4/cpufreq/scaling_available_frequencies");//获取cpu主频范围
if (file4.open(QIODevice::ReadOnly | QIODevice::Text)){
m_cpu4 = file4.readLine();
file4.close();
}
#else
m_freq0="99999";
m_freq4="99999";
m_temp="99.99";
m_cpu0="";
m_cpu4="";
#endif
qDebug()<<"/*****************check CPU used******************/";
qDebug()<<tr("cpu0 range %1").arg(m_cpu0);
qDebug()<<tr("cpu4 range %1").arg(m_cpu4);
qDebug()<<tr("cpu0 freq %1,cpu4 freq %2,now temp %3").arg(m_freq0).arg(m_freq4).arg(m_temp);
qDebug()<<"/*****************check end******************/";
ui->textEdit->append("/*****************check CPU used******************/");
ui->textEdit->append(tr("cpu0 range %1").arg(m_cpu0));
ui->textEdit->append(tr("cpu4 range %1").arg(m_cpu4));
ui->textEdit->append(tr("cpu0 freq %1,cpu4 freq %2,now temp %3").arg(m_freq0).arg(m_freq4).arg(m_temp));
ui->textEdit->append("/*****************check end******************/");
}
QString MainWindow::getsize(qint64 m_allsizie)
{
QString fileSize;
if (m_allsizie >= 0 && m_allsizie < 1024){
fileSize = QString::number(m_allsizie) + "Byte";
}
else if (m_allsizie >= 1024 && m_allsizie < 1024 * 1024){
fileSize = QString::number(m_allsizie / 1024.0, 'f', 2) + "KB";
}
else if (m_allsizie >= 1024 * 1024 && m_allsizie < 1024 * 1024 * 1024){
fileSize = QString::number(m_allsizie / 1024 / 1024.0, 'f', 2) + "MB";
}
else if (m_allsizie >= 1024 * 1024 * 1024){
fileSize = QString::number(m_allsizie / 1024 / 1024 / 1024.0, 'f', 2) + "GB";
}
return fileSize;
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "header.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
private slots:
void AnalyseData();
QString getsize(qint64 m_allsizie);
private:
Ui::MainWindow *ui;
bool m_mSATAstatus=false;//固态硬盘是否正常,不正常不能建立文件夹存储数据
QString m_path;//记录当前存储文件的路径,在WINDOWS的路径还是在linux中的固态硬盘中路径
qint64 mSATA_size,mSATA_used,mSATA_persent;//mSATA硬盘总容量,已经使用容量,容量使用百分比
};
#endif // MAINWINDOW_H
9.msata挂载稳定性测试程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//读取配置信息
QString line_config;
QFile file_config(qApp->applicationDirPath()+"/test_msata_config.txt");
if(file_config.open(QIODevice::ReadOnly|QIODevice::Text)){
while(!file_config.atEnd()){
line_config=file_config.readLine();
}
file_config.close();
}
else{
file_config.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream in(&file_config);
in<<"0";
line_config="0";
file_config.close();
}
qDebug()<<"config:"<<line_config;
ui->spinBox->setValue(line_config.toInt());
if(line_config=="0")ui->checkBox->setChecked(false);
else ui->checkBox->setChecked(true);
//读取配置信息
QString line_path;
QFile file_path(qApp->applicationDirPath()+"/test_msata_path.txt");
if(file_path.open(QIODevice::ReadOnly|QIODevice::Text)){
while(!file_path.atEnd()){
line_path=file_path.readLine();
}
file_path.close();
}
else{
file_path.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream in(&file_path);
in<<"/dev/sda5";
line_path="/dev/sda5";
file_path.close();
}
qDebug()<<"path:"<<line_path;
ui->lineEdit->setText(line_path);
//读取配置信息
QString line_history;
QFile file_history(qApp->applicationDirPath()+"/test_msata_history.txt");
if(file_history.open(QIODevice::ReadOnly|QIODevice::Text)){
while(!file_history.atEnd()){
line_history=file_history.readLine().replace("\n","");
qDebug()<<"history:"<<line_history;
if(line_history.contains("yes")){
QTextCharFormat fmt;
fmt.setForeground(Qt::green);
ui->textEdit->setCurrentCharFormat(fmt);
ui->textEdit->append(line_history);
}
else if(line_history.contains("err")){
QTextCharFormat fmt;
fmt.setForeground(Qt::red);
ui->textEdit->setCurrentCharFormat(fmt);
ui->textEdit->append(line_history);
}
}
file_history.close();
}
QTimer *time1=new QTimer(this);
time1->start(2000);//20s
connect(time1,&QTimer::timeout,[=](){
AnalyseData();
});//绑定定时分析数据函数槽
}
MainWindow::~MainWindow()
{
delete ui;
}
///******************************************************************定时分析数据**************************************************************///
void MainWindow::AnalyseData()
{
///获取数据采集盒状态
QString m_temp="66666";//本机工作频率和温度
QFile file1("/sys/class/thermal/thermal_zone0/temp");//获取cpu工作温度
if (file1.open(QIODevice::ReadOnly | QIODevice::Text)){
m_temp = file1.readLine();
file1.close();
}
m_temp = QString::number((double)m_temp.toInt()/1000,'f',2);
if(ui->checkBox->isChecked()){
int num=ui->spinBox->value();
if(num>0){
ui->spinBox->setValue(num-1);
QFile file(ui->lineEdit->text());
if(file.exists()) {// 文件存在
QTextCharFormat fmt;
fmt.setForeground(Qt::green);
ui->textEdit->setCurrentCharFormat(fmt);
ui->textEdit->append(QString("%1,msata fstab yes,CPU temp %2,has %3").arg(QDateTime::currentDateTime().toString("hh:mm:ss")).arg(m_temp).arg(ui->spinBox->value()));
}else {// 文件不存在
QTextCharFormat fmt;
fmt.setForeground(Qt::red);
ui->textEdit->setCurrentCharFormat(fmt);
ui->textEdit->append(QString("%1,msata fstab err,CPU temp %2,has %3").arg(QDateTime::currentDateTime().toString("hh:mm:ss")).arg(m_temp).arg(ui->spinBox->value()));
}
QFile file_path(qApp->applicationDirPath()+"/test_msata_history.txt");
file_path.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream in(&file_path);
in<<ui->textEdit->toPlainText();
file_path.close();
qDebug()<<"重启";
system("reboot");
}
// else
// ui->textEdit->append("测试完毕!");
}
}
//按键点击事件
void MainWindow::on_checkBox_clicked()
{
// QFile file_config(qApp->applicationDirPath()+"/test_msata_config.txt");
// file_config.open(QIODevice::WriteOnly|QIODevice::Text);
// QTextStream in(&file_config);
// QString res;
// if(ui->checkBox->isChecked()==false)
// res="0";
// in<<res;
// file_config.close();
}
void MainWindow::on_pushButton_clicked()
{
QFile file_path(qApp->applicationDirPath()+"/test_msata_path.txt");
file_path.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream in(&file_path);
in<<ui->lineEdit->text();
file_path.close();
}
void MainWindow::on_pushButton_2_clicked()
{
QFile file_path(qApp->applicationDirPath()+"/test_msata_history.txt");
file_path.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream in(&file_path);
in<<"";
file_path.close();
ui->textEdit->clear();
}
void MainWindow::on_spinBox_valueChanged(int arg1)
{
QFile file_config(qApp->applicationDirPath()+"/test_msata_config.txt");
file_config.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream in(&file_config);
in<<QString::number(arg1);
file_config.close();
}
四、结语
未完待续。。。
可以用AI生成,很多平台都可以,描述清楚就可以对症下药,用起来