Qt 嵌入式设备应用程序,通过U盘升级的一种思路

最近在做一个通过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_LINUX
    QString 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);
}

 

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
嵌入式设备上使用QT应用程序,可以通过U盘进行升级U盘升级一种常见且简便的更新方法,适用于各种嵌入式应用场景。 首先,准备一个存有新版本软件U盘。将U盘插入嵌入式设备的USB接口上。设备会通过操作系统检测到U盘的连接。 接下来,在QT应用程序中添加相关功能,以便在设备运行时能够进行U盘升级。开发人员可以使用QT提供的API来实现此功能。这样,QT应用程序将能够与U盘进行交互。 在QT应用程序中,可以通过U盘接口检测到U盘的连接状态。一旦检测到U盘插入,可以触发特定的事件进行升级操作。 配置QT应用程序,使其能够读取U盘上的新版本软件。读取过程中可能需要进行一些数据校验和验证,以确保软件的完整性和正确性。 一旦读取完成,QT应用程序可以终止当前运行的软件,然后更新为U盘上的新版本。 在软件升级过程中,可能需要显示一些进度条或提示信息,以便用户了解当前进度。 最后,QT应用程序应该提供一种反馈机制,告知用户升级是否成功,并在成功升级后重新启动新版本的软件。 总的来说,QT嵌入式设备应用程序通过U盘进行升级是一个方便且可靠的方法,无需依赖网络连接,适用于各种场景,如工业控制、智能家居等。开发人员只需在QT应用程序中添加相关功能代码即可实现此升级方式。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值