RK3588使用笔记:ubuntu/麒麟系统功能测试程序

news2025/7/14 5:47:02

一、前言

本编文章记录在使用嵌入式系统中的一些功能测试demo程序,大部分都是AI写的,哈哈哈,确实很有帮助,但是得根据自身设备实际情况和知道如何问AI,才能得出你想要的结果,本文就记录一些ubuntu/麒麟系统实际使用过程中测试程序。

目录

1.串口测试程序

2.CAN测试程序

3.背光测试程序(弥补系统pwm匹配异常)

4.电量获取程序(弥补底系统版本不支持电池管理)

5.GPIO测试程序控制状态led灯

6.时间测试程序

7.redis通信测试程序

8.温度、CPU主频测试程序

9.msata挂载稳定性测试程序

二、环境

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生成,很多平台都可以,描述清楚就可以对症下药,用起来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2328364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习deeplearn3

# Jupyter Notebook魔法命令&#xff0c;用于在Notebook中内联显示图表 %matplotlib inline# 导入NumPy库&#xff0c;用于高效的数值计算 import numpy as np# 从matplotlib_inline库导入backend_inline模块&#xff0c;用于设置图表显示格式 from matplotlib_inline import b…

Mac强制解锁APP或文件夹

当Mac安装过火绒企业版、云安全访问服务之类的APP需要卸载的时候&#xff0c;会发现需要管理员密码&#xff0c;正常的卸载流程走不下去&#xff0c;直接删除APP&#xff0c;会提示“不能完成此操作&#xff0c;xxx已锁定”的信息&#xff0c;此处就记录一下如何关闭锁定状态&a…

SQL语句(二)—— DML

目录 一、添加数据 1、给指定字段添加数据 2、给全部字段添加数据 3、批量添加数据 二、修改数据 1、修改数据的具体语法 2、案例分析 3、注意事项 三、删除数据 1、删除数据的具体语法 2、案例 3、注意事项 DML全称是Data Manipulation Language&#xff0c;即数据…

Linux系统程序设计:从入门到高级Day02

这一篇 我带大家复习一下&#xff0c;C语言中的文件 那一部分 大家注意 这里的图并非原创 是当时我老师的图片 本片作用主要是 后续会有文件相关操作&#xff0c;这篇帮大家复习C语言文件中的内容 有助于大家后面的理解。 文章中代码大多是图片格式&#xff0c;是因为这是我…

快速掌握MCP——Spring AI MCP包教包会

最近几个月AI的发展非常快&#xff0c;各种大模型、智能体、AI名词和技术和框架层出不穷&#xff0c;作为一个业余小红书博主的我最近总刷到MCP这个关键字&#xff0c;看着有点高级我也来学习一下。 1.SpringAI与functionCall简单回顾 前几个月我曾写过两篇关于SpringAI的基础…

KUKA机器人查看运行日志的方法

对于KUKA机器人的运行日志都是可以查看和导出的&#xff0c;方便查找问题。KUKA机器人的运行日志查看方法如下&#xff1a; 1、在主菜单下&#xff0c;选择【诊断】-【运行日志】-【显示】下打开&#xff1b; 2、显示出之前的机器人运行日志&#xff1b; 3、也可以通过【过滤器…

MySQL 基础使用指南-MySQL登录与远程登录

MySQL 基础使用指南 1. 登录 MySQL 数据库的命令解析 命令格式&#xff1a; mysql -u用户名 -p密码参数说明&#xff1a; -u&#xff08;user 的缩写&#xff09;&#xff1a;指定登录用户。例如 -uroot 表示以 root 用户登录。-p&#xff08;password 的缩写&#xff09;&a…

web-ui windows安装与配置

web-ui windows安装与配置 安装然后安装依赖 运行配置 安装 git clone https://github.com/browser-use/web-ui.git先把clone下来 需要有python环境 最好是 Python 3.11 这里就不赘述了 然后安装依赖 pip install -r requirements.txt运行 python webui.py --ip 127.0.0.1 …

游戏引擎学习第201天

仓库:https://gitee.com/mrxiao_com/2d_game_5 回顾之前的内容&#xff0c;并遇到了一次一阶异常&#xff08;First-Chance Exception&#xff09;。 欢迎来到新一期的开发过程&#xff0c;我们目前正在编写调试接口代码。 当前&#xff0c;我们已经在布局系统上进行了一些工…

Doris:打破 SQL 方言壁垒,构建统一数据查询生态

在大数据领域&#xff0c;不同的数据库系统往往使用不同的 SQL 方言。这就好比不同地区的人说着不同的语言&#xff0c;给数据分析师和开发人员带来极大的困扰。当企业需要整合多个数据源进行分析时&#xff0c;可能要花费大量时间和精力&#xff0c;在不同的 SQL 语法之间切换…

github合并多个commit message以及rebase解决文件冲突

深度学习求解PDE相关代码全部在我的仓库添加链接描述&#xff0c;自取 github仓库合并多个commit message 问题描述如下&#xff1a; 第一步&#xff1a;确保自己在对应分支上 比如说现在我要合并issue/108分支的提交记录&#xff0c;使用git log --oneline查看提交记录一…

【零基础入门unity游戏开发——2D篇】SortingGroup(排序分组)组件

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

系统与网络安全------Windows系统安全(5)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 磁盘分区管理 磁盘的分区管理 WinR运行&#xff0c;执行“diskmgmt.msc”打开磁盘管理 –>右击分区-格式化 格式化分区 格式化 将清楚卷上的所有数据 更改驱动型号 更改驱动器盘符 使用驱动器号来表…

springboot—— Shiro实现认证和授权功能

一、数据库模板设计 在本文中&#xff0c;我们使用RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;模型设计用户&#xff0c;角色和权限间的关系。简单地说&#xff0c;一个用户拥有若干角色&#xff0c;每一个角色拥有若干权限。这样&a…

牛客 除2问题

除2&#xff01; 贪心堆 让偶数入堆 注意点&#xff1a; 1.判断堆是否为空再进行操作 2. 为了防止超时&#xff0c;我们采取先求和的方式&#xff0c;后面调整之后再减掉&#xff0c;可以节省一次遍历的时间。 3.注意数据范围&#xff0c;要用long long #include<iost…

【C++11】异步编程

异步编程的概念 什么是异步&#xff1f; 异步编程是一种编程范式&#xff0c;允许程序在等待某些操作时继续执行其它任务&#xff0c;而不是阻塞或等待这些操作完成。 异步编程vs同步编程&#xff1f; 在传统的同步编程中&#xff0c;代码按顺序同步执行&#xff0c;每个操作需…

论文阅读笔记:Denoising Diffusion Implicit Models (4)

0、快速访问 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08;1&#xff09; 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08;2&#xff09; 论文阅读笔记&#xff1a;Denoising Diffusion Implicit Models &#xff08…

UltraScale+系列FPGA实现 IMX214 MIPI 视频解码转HDMI2.0输出,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 MIPI 编解码方案我已有的4K/8K视频处理解决方案 3、详细设计方案设计框图硬件设计架构FPGA开发板IMX214 摄像头MIPI D-PHYMIPI CSI-2 RX SubsystemBayer…

BUUCTF-web刷题篇(9)

18.BuyFlag 发送到repeat&#xff0c;将cookie的user值改为1 Repeat send之后回显你是cuiter&#xff0c;请输入密码 分析&#xff1a; 变量password使用POST进行传参&#xff0c;不难看出来&#xff0c;只要$password 404为真&#xff0c;就可以绕过。函数is_numeric()判…

MySQL-- 函数(单行函数): 日期和时间函数

目录 1,获取日期、时间 2,日期与时间戳的转换 3,获取月份、星期、星期数、天数等函数 4,日期的操作函数 5,时间和秒钟转换的函数 6,计算日期和时间的函数 7,日期的格式化与解析 1,获取日期、时间 CURDATE() &#xff0c;CURRENT_DATE() 返回…