ESP8266/ESP32 post上傳更新固件小工具

 

 

ESP8266/ESP32 post上傳更新固件小工具

目錄(結尾提供本項目所有資源下載,開源)

 

ESP8266/ESP32 post上傳更新固件小工具

功能展示

ESP8266無線更新固件配置

QT監視ESP8266固件bin文件變化

QT中http Post方式上傳文件(避坑版本)

QSS

 資源下載


功能展示

最近在用ESP8266做一個羅小黑的智能小檯燈就是下圖這貨~如圖1.1。然後用串口傳輸不方便,我就想直接用WiFi傳輸固件更新。每次編譯好固件之後都要手動打開瀏覽器然後點擊瀏覽文件目錄最後再點擊上傳,本着想偷懶的原則就做了一個監控固件bin文件變化 的小工具軟件,然後bin文件編譯好後就直接上傳到智能檯燈中進行固件更新。最後是這個樣子——如圖1.2

 

圖 1.1  羅小黑智能小檯燈
圖 1.2  程序動態演示圖

 

 

ESP8266無線更新固件配置

在固件中加入固件更新代碼:直接貼代碼了(我用的是Arduino採用C++編寫的,VS2017加插件)主要是用到了ESP8266WebServer這個類

MUpdata.h 

#pragma once
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include "ESP8266WebServer.h"
#include "ESP8266HTTPUpdateServer.h"
#include <ESP8266mDNS.h>

class MUpdata
{
public:
		
	MUpdata();
	bool init();					//初始化
	void setUpdataFlag(bool);		//設置是否可以更新
	void updataLoop();				//更新循環函數
	~MUpdata();

private:
	const char* host = "esp8266-webupdate";
	const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
	ESP8266HTTPUpdateServer httpUpdater;
	ESP8266WebServer *httpServer;
	bool updatFlag;					//更新標誌
};

 MUpdata.cpp

#include "MUpdata.h"

MUpdata::MUpdata()
{
	updatFlag = false;		//初始化更新關閉
}

/************************************************************************
*函數名:初始化函數
*功  能:初始化固件更新類
*輸  出:bool 成功返回true 否則返回false
**************************************************************************/
bool MUpdata::init()
{
	MDNS.begin(host);
	httpServer = new ESP8266WebServer(80);
	httpUpdater.setup(httpServer);
	httpServer->begin();
}

/************************************************************************
*函數名:設置固件更新狀態函數
*功  能:設置固件是否可以更新
*輸  出:無
**************************************************************************/
void MUpdata::setUpdataFlag(bool set)
{
	this->updatFlag = set;
}

/************************************************************************
*函數名:固件更新循環函數
*功  能:檢查固件是否可以更新
*輸  出:無
**************************************************************************/
void MUpdata::updataLoop()
{
	if(updatFlag)
		httpServer->handleClient();
}


MUpdata::~MUpdata()
{
}

 

QT監視ESP8266固件bin文件變化

監視文件變化主要用到了QFileSystemWatcher這個類。如圖2.1,在Qt文檔中我們可以看到通過addPath方法可以添加需要監視的文件路徑,然後當監視文件發生變化的時候會釋放fileChanged(const QString &path)這一信號,所以只需要將固件.bin文件路徑通過addPath添加到QFileSystemWatcher 的監視文件中去,再通過一個connect關聯一下fileChanged信號和你自己寫的槽函數即可。

 

圖 2.1  Qt 文檔介紹的QFileSystemWatcher中addPath方法截圖

 

圖 2.2  Qt 文檔介紹的QFileSystemWatcher中fileChanged信號截圖

 

QT中http Post方式上傳文件(避坑版本)

直接上官方給出的例子

Detailed Description

The QHttpMultiPart class resembles a MIME multipart message to be sent over HTTP.

The QHttpMultiPart resembles a MIME multipart message, as described in RFC 2046, which is to be sent over HTTP. A multipart message consists of an arbitrary number of body parts (see QHttpPart), which are separated by a unique boundary. The boundary of the QHttpMultiPart is constructed with the string "boundary_.oOo._" followed by random characters, and provides enough uniqueness to make sure it does not occur inside the parts itself. If desired, the boundary can still be set via setBoundary().

As an example, consider the following code snippet, which constructs a multipart message containing a text part followed by an image part:

官方示例:

  QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

  QHttpPart textPart;
  textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
  textPart.setBody("my text");

  QHttpPart imagePart;
  imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
  imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
  QFile *file = new QFile("image.jpg");
  file->open(QIODevice::ReadOnly);
  imagePart.setBodyDevice(file);
  file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart

  multiPart->append(textPart);
  multiPart->append(imagePart);

  QUrl url("http://my.server.tld");
  QNetworkRequest request(url);

  QNetworkAccessManager manager;
  QNetworkReply *reply = manager.post(request, multiPart);
  multiPart->setParent(reply); // delete the multiPart with the reply
  // here connect signals etc.

官方的例子中說可以不設置界限,實際上不設置的話是post不出去的還有一個巨大的坑就是,需要在你的這個方法裏面加上一個evenLoop事件循環,不然也是post不出去的。最終修改代碼如下(這個是我自己寫的):

我寫的post方法 


/**********************************************************
*函數名:post上傳函數
*功  能:以post上傳文件
*輸  入:無
*輸  出:無
***********************************************************/
void FileWatchUpdata::onPost()
{
	postRunningFlag = true;
	ui.logLab->setText(QString::fromLocal8Bit("正在上傳"));
	qDebug() << QString::fromLocal8Bit("正在上傳文件");
	QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
	QHttpPart FilePart;

	FilePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"XPY.ino.bin\""));
	QFile *file = new QFile(fileName);
	file->open(QIODevice::ReadOnly);
	FilePart.setBodyDevice(file);
	file->setParent(multiPart); 
	multiPart->append(FilePart);
	uploadServiceUrl = QUrl(ui.uploadServiceIpEdt->text());
	QNetworkRequest request(uploadServiceUrl);

	QNetworkAccessManager manager;
	QString bd = "fasdlkfjaslkdgj;lkadjglk;";
	multiPart->setBoundary(bd.toLatin1());
	request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data;boundary=" + bd);

	QNetworkReply *reply = manager.post(request, multiPart);
	multiPart->setParent(reply);

	QEventLoop eventloop;
	connect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
	connect(reply, SIGNAL(finished()), this, SLOT(onFinished()));
	connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(onUploadProgress(qint64, qint64)));
	eventloop.exec(QEventLoop::ExcludeUserInputEvents);
}

注意:這裏有兩點需要注意:

  1. 要添加界限boundary。
  2. 要用QeventLoop進行事件循環,並在結尾要將finished信號和quit槽函數進行綁定。

QSS

通過QSS可以改變程序的樣式,我這裏想用Linux黑框綠色字體主體樣式。具體配置如下:

//主背景樣式
background-color: rgba(0, 0, 0, 100);

//按鈕的樣式
QPushButton{
 	color: rgb(85, 255, 0);
	border:1px solid rgb(85, 255, 0);
}
QPushButton::pressed {
	color: rgb(85, 255, 0);
	border:1px solid rgb(85, 255, 0);
	background-color:rgba(85,255,0,100);
}
QPushButton::hover{
	color: rgb(85, 255, 0);
	border:1px solid rgb(85, 255, 0);
	background-color:rgba(85,255,0,50);
}

//QLab樣式
color: rgb(85, 255, 0);
background-color: rgba(255, 255, 255, 0);

//QLineEdit樣式
QLineEdit
{
	color:rgb(85, 255, 0);
	border:1px solid rgb(85, 255, 0);
	background: rgba(0, 0, 0, 0);
	border-radius: 0px;	
}
QLineEdit::hover
{
	color:rgb(85, 255, 0);
	border:1px solid rgb(85, 255, 0);
	background: rgba(0, 0, 0, 100);
	border-radius: 0px;	
}
//QCheckBox樣式,主要想要改變其框內點擊效果的話只能用圖片對樣式進行修改
QCheckBox{
	color: rgb(85, 255, 0);
	background-color: rgba(255, 255, 255, 0);
}

QCheckBox::indicator:unchecked{
    image:url(:/FileWatchUpdata/Resources/act1.png);
}

QCheckBox::indicator:checked{
    image:url(:/FileWatchUpdata/Resources/act2.png);
}

 資源下載

發佈了10 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章