搜索引擎友好的网站有哪些特点,网站制作完成之后我们便进入了什么阶段,pc网站转换wap网站,厦门网站建设 孚珀科技Qt u盘自动升级软件 Chapter1 Qt u盘自动升级软件u盘自动升级软件思路#xff1a;step1. 获取U盘 判断U盘名字是否正确#xff0c; 升级文件是否存在。step2. 升级step3. 升级界面 Chapter2 Qt 嵌入式设备应用程序#xff0c;通过U盘升级的一种思路Chapter3 在开发板上运行的… Qt u盘自动升级软件 Chapter1 Qt u盘自动升级软件u盘自动升级软件思路step1. 获取U盘 判断U盘名字是否正确 升级文件是否存在。step2. 升级step3. 升级界面 Chapter2 Qt 嵌入式设备应用程序通过U盘升级的一种思路Chapter3 在开发板上运行的QT应用程序如何拷贝文件到U盘Chapter4 嵌入式QtU盘升级程序前言一、实现过程1.检测U盘中的更新程序2. 数字验证3.升级程序4.主函数 二、总结 Chapter1 Qt u盘自动升级软件
原文链接
u盘自动升级软件思路
1.检测U盘是否存在
2.检测升级文件是否存在升级文件版本是否比当前软件版本新
3.软件升级
step1. 获取U盘 判断U盘名字是否正确 升级文件是否存在。
//获取U盘 判断U盘名字是否正确 升级文件是否存在。
void MainWindow::getUDisk()
{QMapQString,QString namePath;foreach (const QStorageInfo storage, QStorageInfo::mountedVolumes()){if (storage.isValid() storage.isReady()){UDiskPath storage.rootPath();namePath.insert(storage.displayName(),storage.rootPath());}}QString path namePath.value(LADYBUG);QFile file(path/app::updateFile);if(file.exists()){//存在 弹窗是否升级}else{//不存在}
}step2. 升级 OperateThread *thread new OperateThread;thread-setUpgradeFile(strSrcFile);ShowProgressDialog dialog(this);connect(thread, SIGNAL(emitFinish(int)), dialog, SLOT(onThreadFinished(int)));thread-start();dialog.exec();step3. 升级界面
class ShowProgressDialog : public QDialog
{Q_OBJECT
public:explicit ShowProgressDialog(QWidget *parent 0);~ShowProgressDialog();void setTitleText(const QString strText);void setMessageText(const QString strMsg);public slots:void on_btnOk_clicked();void onThreadFinished(int nExitCode);private:QLabel *m_labelTitle;QLabel *m_labelMsg;QPushButton *m_btnOk;QLabel *m_labelWait;QMovie *m_pMovie;
};ShowProgressDialog::ShowProgressDialog(QWidget *parent) : QDialog(parent)
{setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::Dialog);setAttribute(Qt::WA_X11DoNotAcceptFocus);setFocusPolicy(Qt::NoFocus);//更改背景色QPalette palette this-palette();QPixmap pix(:/res/dialog_bg.png);palette.setBrush(QPalette::Background,QBrush(pix));setAutoFillBackground(true);this-setPalette(palette);resize(410, 260);setMinimumSize(QSize(410, 260));setMaximumSize(QSize(410, 260));m_labelTitle new QLabel(this);m_labelMsg new QLabel(this);m_btnOk new QPushButton(this);m_labelWait new QLabel(this);m_pMovie new QMovie(:/res/loading.gif);m_labelTitle-setGeometry(QRect(10, 1, 220, 30));m_labelMsg-setGeometry(QRect(30, 60, 350, 60));m_labelMsg-setWordWrap(true);m_btnOk-setGeometry(QRect(320, 180, 58, 58));m_labelWait-setGeometry(QRect(30, 120, 322, 18));m_labelWait-setMovie(m_pMovie);m_pMovie-start();m_labelTitle-setStyleSheet(font: bold 17px; color: white;);m_labelMsg-setStyleSheet(font: bold 17px ; color: black; );m_btnOk-setStyleSheet(QPushButton{background-image: url(:/res/dialog_ok.png);border: 0px;}QPushButton:pressed{background-image: url(:/res/dialog_ok_p.png);border: 0px;});connect(m_btnOk , SIGNAL(clicked()) , this , SLOT(on_btnOk_clicked()));setTitleText(升级);setMessageText(正在升级请勿插拔U盘!);m_btnOk-hide();
}ShowProgressDialog::~ShowProgressDialog()
{delete m_labelTitle;delete m_labelMsg;delete m_btnOk;
}void ShowProgressDialog::setTitleText(const QString strText)
{m_labelTitle-setText(strText);
}void ShowProgressDialog::setMessageText(const QString strMsg)
{m_labelMsg-setText(strMsg);
}void ShowProgressDialog::on_btnOk_clicked()
{QDialog::accept();
}void ShowProgressDialog::onThreadFinished(int nExitCode)
{qDebug() nExitCode nExitCode;if (nExitCode 0){setMessageText(升级成功请重新上电。);m_btnOk-show();m_pMovie-stop();}else{setMessageText(升级出错!请断电以恢复!);m_btnOk-show();m_pMovie-stop();}
}注意线程继承自QThread完成复制工作。使用QProcess来完成Linux下的解压和删除的工作。关于Qt的多线程可以去查找一下其他的教程这里就不做过多的解释。
class OperateThread : public QThread
{Q_OBJECT
public:explicit OperateThread(QObject *parent 0);public:void setUpgradeFile(QString strUpgradeFile){m_UpgradeFile strUpgradeFile;}protected:void run();signals:void emitFinish(int);public slots:private:void OprUpgradeUp();private:QString m_UpgradeFile;
};OperateThread::OperateThread(QObject *parent) : QThread(parent)
{}void OperateThread::run()
{//很复杂的数据处理OprUpgradeUp();
}void OperateThread::OprUpgradeUp()
{
#define DEST_DIR ../QString destDir QString(%1/update.tar.gz).arg(DEST_DIR);if( QFile::copy(m_UpgradeFile, destDir) ){qDebug()-------成功-----------;}else{qDebug()-------出错-----------;//升级失败emit emitFinish(1);return;}#ifdef Q_OS_LINUXQString exe QString(tar -zxvf %1 -C %2).arg(destDir).arg(DEST_DIR);QProcess::execute(exe);//升级成功自动同步磁盘并删除ARM上的升级包exe QString(sync);QProcess::execute(exe);exe QString(rm -rf %1).arg(destDir);QProcess::execute(exe);
#endif//升级成功emit emitFinish(0);
}Chapter2 Qt 嵌入式设备应用程序通过U盘升级的一种思路
原文链接https://blog.csdn.net/qq1113231395/article/details/81867153
最近在做一个通过U盘升级的功能程序是运行在ARM Linux Qt平台上的。这个应该是很多嵌入式设备必备的一个功能了所以把这部分的实现抽出来做成一个例子供需要的人参考。这只是U盘升级的一种思路如果有更好的方法也可以提供相应的意见。
源码下载softwareupgrade.tar.gz
升级文件的格式是通过tar压缩后的文件以gz结尾的 可以通过tar命令生成相应的升级文件如update.tar.gz
tar -czvf update.tar.gz demo主要思路就是点击相应的功能后从U盘中选中需要升级的文件update.tar.gz之后开启一个线程和一个提示正在升级的对话框以免让用户觉得假死。在线程中完成的事情是将选中的升级文件复制到应用程序的目录中然后将update.tar.gz 解压覆盖原来的程序。最后将update.tar.gz删除。发送一个线程结束的信号。
下面就介绍一下实现过程。
MainWindow很简单只有一个按钮。 点击按钮开启线程显示提示框绑定线程结束后的信号。提示框根据信号的参数值来确定升级是否成功。
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui-setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{QString strSrcFile QFileDialog::getOpenFileName(this, 选择升级文件, ., tar (*.gz));qDebug() strSrcFile strSrcFile;OperateThread *thread new OperateThread;thread-setUpgradeFile(strSrcFile);ShowProgressDialog dialog(this);connect(thread, SIGNAL(emitFinish(int)), dialog, SLOT(onThreadFinished(int)));thread-start();dialog.exec();
}运行的效果图
提示框 void onThreadFinished(int nExitCode) 线程结束后更新提示框。里面还使用到了一些qss来设置背景。
class ShowProgressDialog : public QDialog
{Q_OBJECT
public:explicit ShowProgressDialog(QWidget *parent 0);~ShowProgressDialog();void setTitleText(const QString strText);void setMessageText(const QString strMsg);public slots:void on_btnOk_clicked();void onThreadFinished(int nExitCode);private:QLabel *m_labelTitle;QLabel *m_labelMsg;QPushButton *m_btnOk;QLabel *m_labelWait;QMovie *m_pMovie;
};ShowProgressDialog::ShowProgressDialog(QWidget *parent) : QDialog(parent)
{setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::Dialog);setAttribute(Qt::WA_X11DoNotAcceptFocus);setFocusPolicy(Qt::NoFocus);//更改背景色QPalette palette this-palette();QPixmap pix(:/res/dialog_bg.png);palette.setBrush(QPalette::Background,QBrush(pix));setAutoFillBackground(true);this-setPalette(palette);resize(410, 260);setMinimumSize(QSize(410, 260));setMaximumSize(QSize(410, 260));m_labelTitle new QLabel(this);m_labelMsg new QLabel(this);m_btnOk new QPushButton(this);m_labelWait new QLabel(this);m_pMovie new QMovie(:/res/loading.gif);m_labelTitle-setGeometry(QRect(10, 1, 220, 30));m_labelMsg-setGeometry(QRect(30, 60, 350, 60));m_labelMsg-setWordWrap(true);m_btnOk-setGeometry(QRect(320, 180, 58, 58));m_labelWait-setGeometry(QRect(30, 120, 322, 18));m_labelWait-setMovie(m_pMovie);m_pMovie-start();m_labelTitle-setStyleSheet(font: bold 17px; color: white;);m_labelMsg-setStyleSheet(font: bold 17px ; color: black; );m_btnOk-setStyleSheet(QPushButton{background-image: url(:/res/dialog_ok.png);border: 0px;}QPushButton:pressed{background-image: url(:/res/dialog_ok_p.png);border: 0px;});connect(m_btnOk , SIGNAL(clicked()) , this , SLOT(on_btnOk_clicked()));setTitleText(升级);setMessageText(正在升级请勿插拔U盘!);m_btnOk-hide();
}ShowProgressDialog::~ShowProgressDialog()
{delete m_labelTitle;delete m_labelMsg;delete m_btnOk;
}void ShowProgressDialog::setTitleText(const QString strText)
{m_labelTitle-setText(strText);
}void ShowProgressDialog::setMessageText(const QString strMsg)
{m_labelMsg-setText(strMsg);
}void ShowProgressDialog::on_btnOk_clicked()
{QDialog::accept();
}void ShowProgressDialog::onThreadFinished(int nExitCode)
{qDebug() nExitCode nExitCode;if (nExitCode 0){setMessageText(升级成功请重新上电。);m_btnOk-show();m_pMovie-stop();}else{setMessageText(升级出错!请断电以恢复!);m_btnOk-show();m_pMovie-stop();}
}线程继承自QThread完成复制工作。使用QProcess来完成Linux下的解压和删除的工作。关于Qt的多线程可以去查找一下其他的教程这里就不做过多的解释。
class OperateThread : public QThread
{Q_OBJECT
public:explicit OperateThread(QObject *parent 0);public:void setUpgradeFile(QString strUpgradeFile){m_UpgradeFile strUpgradeFile;}protected:void run();signals:void emitFinish(int);public slots:private:void OprUpgradeUp();private:QString m_UpgradeFile;
};OperateThread::OperateThread(QObject *parent) : QThread(parent)
{}void OperateThread::run()
{//很复杂的数据处理OprUpgradeUp();
}void OperateThread::OprUpgradeUp()
{
#define DEST_DIR ../QString destDir QString(%1/update.tar.gz).arg(DEST_DIR);if( QFile::copy(m_UpgradeFile, destDir) ){qDebug()-------成功-----------;}else{qDebug()-------出错-----------;//升级失败emit emitFinish(1);return;}#ifdef Q_OS_LINUXQString exe QString(tar -zxvf %1 -C %2).arg(destDir).arg(DEST_DIR);QProcess::execute(exe);//升级成功自动同步磁盘并删除ARM上的升级包exe QString(sync);QProcess::execute(exe);exe QString(rm -rf %1).arg(destDir);QProcess::execute(exe);
#endif//升级成功emit emitFinish(0);
}Chapter3 在开发板上运行的QT应用程序如何拷贝文件到U盘
原文链接https://blog.csdn.net/pang_fighting/article/details/139114780
笔者最近一直被这个问题所困惑好在今天已经解决之前找了很多资料试了其他家的使用QProcess类来实现QT应用下的命令行实现但很遗憾还是不行找到新的解决方法如下
system(cp -r /home/root/test_data /run/media/sda1);
system(sync);
system(umount /run/media/sda1);解释一下这需要你的开发板移植的系统能够插入U盘直接挂载否则需要先检测U盘插入再挂载U盘才可以使用笔者用的正点原子157开发板使用的是他们的官方系统这个系统是支持插入U盘直接挂载的挂载目录是“/run/media/sda1”。
U盘挂载完成之后使用C函数system来执行命令行拷贝文件拷贝完成之后执行sync命令最后直接取消挂载拔出U盘即可
Chapter4 嵌入式QtU盘升级程序
原文链接https://blog.csdn.net/sjd753/article/details/135284869
前言
近期在完成一个U盘升级功能对于Arm嵌入式设备来说应该算是必备的了。
参考链接
https://blog.csdn.net/newnewman80/article/details/8766657 https://blog.csdn.net/newnewman80/article/details/8766657
一、实现过程
1.检测U盘中的更新程序
结合netlink捕获USB的热拔插我们需要去检测U盘的挂载点通常情况下都是挂载在/media下。
bool checkConsoleAppExists()
{DIR *dir opendir(/run/media); // 打开 /run/media 目录 具体的挂载点根据设备决定if (dir) {struct dirent *entry;while ((entry readdir(dir)) ! NULL) {if (strcmp(entry-d_name, .) ! 0 strcmp(entry-d_name, ..) ! 0) {devpath /run/media/ std::string(entry-d_name);path /run/media/ std::string(entry-d_name) /updateFileName;std::string signatureFilePath devpath /sigFileName.sig; std::string publicKeyPath devpath /key.pub ;if (access(path.c_str(), F_OK) ! -1) {//检测到更新程序可以做一些校验我这里的话是验证数字签名根据具体情况决定return checkUpdate(signatureFilePath,publicKeyPath,path);}}}closedir(dir);}return false;
}2. 数字验证
/*检测是否需要更新是否为正确的更新程序*/
bool checkUpdate(const std::string signatureFile, const std::string publicKeyFile, const std::string dataFile) {// 打开更新文件// 这里是想要去检测版本号去判断是否需要升级的后面由于使用了数字签名就没有实现这部分。FILE *updateFile fopen(dataFile.c_str(), rb);if (!updateFile) {perror(Error opening update file\n);return false;}// 验证数字签名return verifySignature(signatureFile,publicKeyFile,dataFile);
}// 函数用于验证数字签名是否有效
bool verifySignature(const std::string signatureFile, const std::string publicKeyFile, const std::string dataFile)
{// 打开公钥文件以读取公钥信息FILE* fp fopen(publicKeyFile.c_str(), r);if (!fp) {std::cerr Error opening public key file. std::endl;return false;}// 从公钥文件中读取 RSA 公钥信息RSA* rsa PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);fclose(fp);// 检查是否成功读取公钥信息if (!rsa) {std::cerr Error reading public key. std::endl;return false;}// 创建一个用于存储 RSA 公钥的 EVP_PKEY 对象EVP_PKEY* evpKey EVP_PKEY_new();// 将 RSA 公钥赋值给 EVP_PKEY 对象if (!EVP_PKEY_assign_RSA(evpKey, rsa)) {std::cerr Error assigning RSA key. std::endl;RSA_free(rsa);return false;}// 创建一个用于消息摘要计算的 EVP_MD_CTX 对象EVP_MD_CTX* ctx EVP_MD_CTX_new();if (!ctx) {std::cerr Error creating context. std::endl;RSA_free(rsa);return false;}// 打开数据文件以进行签名验证std::ifstream fileStream(dataFile, std::ios::binary | std::ios::ate);if (!fileStream.is_open()) {std::cerr Error opening data file. std::endl;EVP_MD_CTX_free(ctx);RSA_free(rsa);return false;}// 读取数据文件的大小和内容std::streamsize fileSize fileStream.tellg();fileStream.seekg(0, std::ios::beg);std::vectorunsigned char fileData(fileSize);if (!fileStream.read(reinterpret_castchar*(fileData.data()), fileSize)) {std::cerr Error reading data file. std::endl;fileStream.close();EVP_MD_CTX_free(ctx);RSA_free(rsa);return false;}fileStream.close();// 打开签名文件以进行签名验证std::ifstream signatureFileStream(signatureFile, std::ios::binary);if (!signatureFileStream.is_open()) {std::cerr Error opening signature file. std::endl;EVP_MD_CTX_free(ctx);RSA_free(rsa);return false;}// 读取签名文件的大小和内容signatureFileStream.seekg(0, std::ios::end);size_t signatureFileSize signatureFileStream.tellg();signatureFileStream.seekg(0, std::ios::beg);std::vectorunsigned char signatureData(signatureFileSize);if (!signatureFileStream.read(reinterpret_castchar*(signatureData.data()), signatureFileSize)) {std::cerr Error reading signature file. std::endl;signatureFileStream.close();EVP_MD_CTX_free(ctx);RSA_free(rsa);return false;}signatureFileStream.close();// 更新消息摘要的内容计算数据文件的哈希值if (!EVP_VerifyUpdate(ctx, fileData.data(), fileSize)) {std::cerr Error updating verification. std::endl;EVP_MD_CTX_free(ctx);RSA_free(rsa);return false;}// 验证签名的有效性int result EVP_VerifyFinal(ctx, signatureData.data(), signatureFileSize, evpKey);EVP_MD_CTX_free(ctx);RSA_free(rsa);// 根据验证结果返回相应的布尔值if (result ! 1) {std::cerr Signature verification failed. std::endl;return false;}std::cout Signature verification successful. std::endl;return true;
}3.升级程序
升级程序的话实际上就是一个拷贝的过程。将设备上的备份U盘中的更新程序拷贝出来。
/* 更新程序 */
bool copyFile(const char *sourcePath, const char *destinationPath) {//system(mv updateFileName updateFileName.back); //这里是一个备份,后续可以进行一个升级失败备份还原。FILE *sourceFile fopen(sourcePath, rb);FILE *destinationFile fopen(destinationPath, wb);if (sourceFile NULL) {printf(Error opening sourceFile files.\n);return false;}if(destinationFile NULL){printf(Error opening destinationFile files.\n);return false;}char buffer[1024];size_t bytesRead;while ((bytesRead fread(buffer, 1, sizeof(buffer), sourceFile)) 0) {printf(start copy file........................\n);fwrite(buffer, 1, bytesRead, destinationFile);}/*更简单一点就是用system命令直接拷贝不过有一点需要注意程序在运行的时候有时候会拷贝失败。可以先用system命令删除或者备份然后再进行拷贝,再用system给个权限。*/fclose(sourceFile);fclose(destinationFile);return true;
}
4.主函数
int main(void)
{struct sockaddr_nl client;struct timeval tv;int CppLive, rcvlen, ret;fd_set fds;int buffersize 1024;CppLive socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);memset(client, 0, sizeof(client));client.nl_family AF_NETLINK;client.nl_pid getpid();client.nl_groups 1; /* receive broadcast message*/setsockopt(CppLive, SOL_SOCKET, SO_RCVBUF, buffersize, sizeof(buffersize));bind(CppLive, (struct sockaddr*)client, sizeof(client));while (1) {char buf[UEVENT_BUFFER_SIZE] { 0 };FD_ZERO(fds);FD_SET(CppLive, fds);tv.tv_sec 0;tv.tv_usec 100 * 1000;ret select(CppLive 1, fds, NULL, NULL, tv);if(ret 0)continue;if(!(ret 0 FD_ISSET(CppLive, fds)))continue;/* receive data */rcvlen recv(CppLive, buf, sizeof(buf), 0);if (rcvlen 0) { printf(%s\n, buf);//检测更新程序//升级程序//重启....}}close(CppLive);return 0;
}二、总结
以上就是今天要讲的内容本文仅仅简单介绍了结合netlink的u盘升级后期可以通过Qt实现U盘升级实现一个程序通过界面可以判断更新状态。