Added web content download feature.
Need to incorporate into OLED menus etc.
This commit is contained in:
parent
4986a4d741
commit
1d80e34c4b
|
@ -175,7 +175,7 @@ void asyncHTTPrequest::close(){
|
||||||
_client->close();
|
_client->close();
|
||||||
}
|
}
|
||||||
//**************************************************************************************************************
|
//**************************************************************************************************************
|
||||||
int asyncHTTPrequest::readyState(){
|
int asyncHTTPrequest::readyState() const {
|
||||||
return _readyState;
|
return _readyState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ class asyncHTTPrequest {
|
||||||
void abort(); // Abort the current operation
|
void abort(); // Abort the current operation
|
||||||
void close(); // Close the connection
|
void close(); // Close the connection
|
||||||
|
|
||||||
int readyState(); // Return the ready state
|
int readyState() const; // Return the ready state
|
||||||
|
|
||||||
int respHeaderCount(); // Retrieve count of response headers
|
int respHeaderCount(); // Retrieve count of response headers
|
||||||
char* respHeaderName(int index); // Return header name by index
|
char* respHeaderName(int index); // Return header name by index
|
||||||
|
|
|
@ -1567,6 +1567,9 @@ void checkDebugCommands()
|
||||||
else if(rxVal == '-') {
|
else if(rxVal == '-') {
|
||||||
TxManage.queueOffRequest();
|
TxManage.queueOffRequest();
|
||||||
}
|
}
|
||||||
|
else if(rxVal == 'h') {
|
||||||
|
getWebContent();
|
||||||
|
}
|
||||||
else if(rxVal == 'r') {
|
else if(rxVal == 'r') {
|
||||||
ESP.restart(); // reset the esp
|
ESP.restart(); // reset the esp
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include "BrowserUpload.h"
|
#include "BrowserUpload.h"
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
|
#include "WebContentDL.h"
|
||||||
|
|
||||||
extern WiFiManager wm;
|
extern WiFiManager wm;
|
||||||
extern const char* stdHeader;
|
extern const char* stdHeader;
|
||||||
|
@ -54,10 +55,11 @@ extern void checkSplashScreenUpdate();
|
||||||
sBrowserUpload BrowserUpload;
|
sBrowserUpload BrowserUpload;
|
||||||
WebServer server(80);
|
WebServer server(80);
|
||||||
WebSocketsServer webSocket = WebSocketsServer(81);
|
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||||
|
CWebContentDL WebContentDL;
|
||||||
|
|
||||||
bool bRxWebData = false; // flags for OLED animation
|
bool bRxWebData = false; // flags for OLED animation
|
||||||
bool bTxWebData = false;
|
bool bTxWebData = false;
|
||||||
bool bUpdateAccessed = false; // flag used to ensure web update always starts via /update. direct accesses to /updatenow will FAIL
|
bool bUpdateAccessed = false; // flag used to ensure browser update always starts via /update. direct accesses to /updatenow will FAIL
|
||||||
bool bFormatAccessed = false;
|
bool bFormatAccessed = false;
|
||||||
bool bFormatPerformed = false;
|
bool bFormatPerformed = false;
|
||||||
long _SuppliedFileSize = 0;
|
long _SuppliedFileSize = 0;
|
||||||
|
@ -83,6 +85,7 @@ void onUploadProgression();
|
||||||
void onRename();
|
void onRename();
|
||||||
void build404Response(String& content, String file);
|
void build404Response(String& content, String file);
|
||||||
void build500Response(String& content, String file);
|
void build500Response(String& content, String file);
|
||||||
|
void manageWegContentUpdate();
|
||||||
|
|
||||||
void initWebServer(void) {
|
void initWebServer(void) {
|
||||||
|
|
||||||
|
@ -137,6 +140,7 @@ void initWebServer(void) {
|
||||||
|
|
||||||
DebugPort.println("HTTP server started");
|
DebugPort.println("HTTP server started");
|
||||||
|
|
||||||
|
// initWebPageUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,6 +149,7 @@ bool doWebServer(void)
|
||||||
{
|
{
|
||||||
webSocket.loop();
|
webSocket.loop();
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
|
manageWegContentUpdate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1059,3 +1064,41 @@ content += R"=====(" </i></b> exists, but cannot be streamed?
|
||||||
)=====";
|
)=====";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int webContentState = 0;
|
||||||
|
|
||||||
|
void getWebContent() {
|
||||||
|
webContentState = 1;
|
||||||
|
// WebContentDL.get("index.html.gz");
|
||||||
|
// getWebContent("favicon.ico");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void manageWegContentUpdate()
|
||||||
|
{
|
||||||
|
switch(webContentState) {
|
||||||
|
case 1:
|
||||||
|
DebugPort.println("Requesting index.html.gz from Afterburner web site");
|
||||||
|
WebContentDL.get("index.html.gz");
|
||||||
|
webContentState++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
WebContentDL.process();
|
||||||
|
if(!WebContentDL.busy()) {
|
||||||
|
DebugPort.println("Completed index.html.gz from Afterburner web site");
|
||||||
|
webContentState++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
DebugPort.println("Requesting favicon.ico from Afterburner web site");
|
||||||
|
WebContentDL.get("favicon.ico");
|
||||||
|
webContentState++;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
WebContentDL.process();
|
||||||
|
if(!WebContentDL.busy()) {
|
||||||
|
DebugPort.println("Completed favicon.ico from Afterburner web site");
|
||||||
|
webContentState = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -34,5 +34,8 @@ bool sendWebSocketString(const char* Str);
|
||||||
bool isWebSocketClientChange();
|
bool isWebSocketClientChange();
|
||||||
void listSPIFFS(const char * dirname, uint8_t levels, String& HTMLreport, int withHTMLanchors=0);
|
void listSPIFFS(const char * dirname, uint8_t levels, String& HTMLreport, int withHTMLanchors=0);
|
||||||
|
|
||||||
|
void getWebContent();
|
||||||
|
void getWebContent(const char* filename);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
150
src/WiFi/WebContentDL.cpp
Normal file
150
src/WiFi/WebContentDL.cpp
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
// seek a web page update from the afterburner web server
|
||||||
|
|
||||||
|
#include "WebContentDL.h"
|
||||||
|
#include "../Utility/DebugPort.h"
|
||||||
|
|
||||||
|
|
||||||
|
void WebPageDataCB(void* pClass, asyncHTTPrequest* request, size_t available)
|
||||||
|
{
|
||||||
|
CWebContentDL* pParent = (CWebContentDL*)pClass;
|
||||||
|
while(available) {
|
||||||
|
int read = pParent->queueDLdata(available, request);
|
||||||
|
if(read >= 0)
|
||||||
|
available -= read;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WebPageRequestCB(void* pClass, asyncHTTPrequest* request, int readyState)
|
||||||
|
{
|
||||||
|
CWebContentDL* pParent = (CWebContentDL*)pClass;
|
||||||
|
if(readyState == 4){
|
||||||
|
while(request->available()) {
|
||||||
|
pParent->queueDLdata(request->available(), request);
|
||||||
|
}
|
||||||
|
pParent->finalise();
|
||||||
|
|
||||||
|
request->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CWebContentDL::CWebContentDL()
|
||||||
|
{
|
||||||
|
// _request.setDebug(true);
|
||||||
|
_request.onReadyStateChange(WebPageRequestCB, this);
|
||||||
|
_request.onData(WebPageDataCB, this);
|
||||||
|
_queue = xQueueCreate(10, sizeof(sQueueEntry));
|
||||||
|
_fileActive = false;
|
||||||
|
_bytecount = 0;
|
||||||
|
_queuecount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWebContentDL::~CWebContentDL()
|
||||||
|
{
|
||||||
|
vQueueDelete(_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CWebContentDL::busy() const
|
||||||
|
{
|
||||||
|
return _fileActive || (_request.readyState() != 0 && _request.readyState() != 4) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CWebContentDL::get(const char* filename)
|
||||||
|
{
|
||||||
|
if(_request.readyState() == 0 || _request.readyState() == 4){
|
||||||
|
// ensure leading forward slash, required for SPIFFS
|
||||||
|
_filename = "";
|
||||||
|
if(filename[0] != '/') _filename = "/";
|
||||||
|
_filename += filename;
|
||||||
|
// replace with sanitised name
|
||||||
|
filename = _filename.c_str();
|
||||||
|
|
||||||
|
DebugPort.printf("Loading file to SPIFFS: '%s'\r\n", filename);
|
||||||
|
if(SPIFFS.exists(filename)) {
|
||||||
|
DebugPort.println("Removing existing file from SPIFFS");
|
||||||
|
SPIFFS.remove(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
_file = SPIFFS.open(filename, "w"); // Open the file for writing in SPIFFS (create if it doesn't exist)
|
||||||
|
_fileActive = true;
|
||||||
|
_bytecount = 0;
|
||||||
|
_queuecount = 0;
|
||||||
|
|
||||||
|
String URL = "http://afterburner.mrjones.id.au/fota/web";
|
||||||
|
URL += filename;
|
||||||
|
_request.open("GET", URL.c_str());
|
||||||
|
_request.send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWebContentDL::process()
|
||||||
|
{
|
||||||
|
sQueueEntry entry;
|
||||||
|
while(xQueueReceive(_queue, &entry, 0)) {
|
||||||
|
int16_t len = entry.len;
|
||||||
|
if(len == -1) {
|
||||||
|
if(_file) {
|
||||||
|
_file.close();
|
||||||
|
_fileActive = false;
|
||||||
|
}
|
||||||
|
DebugPort.printf("Downloaded %s (%d bytes) - CLOSED OK\r\n", _filename.c_str(), _bytecount);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(len > 0) {
|
||||||
|
if(_file) {
|
||||||
|
if(_file.write(entry.data, len) != len) { // Write the received bytes to the file
|
||||||
|
_file.close();
|
||||||
|
_fileActive = false;
|
||||||
|
DebugPort.printf("Web content downlod - FILE_WRITE error: removing %s\r\n", _filename.c_str());
|
||||||
|
SPIFFS.remove(_filename.c_str()); // remove the bad file from SPIFFS
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_bytecount += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// DebugPort.printf("Len=%d Queuecount=%d/%d total=%d\r\n", entry.len, entry.count, queuecount, webpagecount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t
|
||||||
|
CWebContentDL::queueDLdata(int size, asyncHTTPrequest* request)
|
||||||
|
{
|
||||||
|
sQueueEntry entry;
|
||||||
|
|
||||||
|
if(size > sizeof(entry.data))
|
||||||
|
size = sizeof(entry.data);
|
||||||
|
|
||||||
|
int16_t read = request->responseRead(entry.data, size);
|
||||||
|
|
||||||
|
if(read > 0) {
|
||||||
|
// available -= read;
|
||||||
|
entry.len = read;
|
||||||
|
entry.count = ++_queuecount;
|
||||||
|
|
||||||
|
BaseType_t awoken;
|
||||||
|
xQueueSendFromISR(_queue, &entry, &awoken);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DebugPort.println(" page read error?");
|
||||||
|
}
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CWebContentDL::finalise()
|
||||||
|
{
|
||||||
|
sQueueEntry entry;
|
||||||
|
|
||||||
|
entry.len = -1;
|
||||||
|
entry.count = -1;
|
||||||
|
BaseType_t awoken;
|
||||||
|
xQueueSendFromISR(_queue, &entry, &awoken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
38
src/WiFi/WebContentDL.h
Normal file
38
src/WiFi/WebContentDL.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// seek a web page update from the afterburner web server
|
||||||
|
|
||||||
|
#include "../../asyncHTTPrequest/src/asyncHTTPrequest.h"
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct sQueueEntry {
|
||||||
|
int16_t len;
|
||||||
|
int16_t count;
|
||||||
|
uint8_t data[2044];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
class CWebContentDL {
|
||||||
|
std::string _filename;
|
||||||
|
asyncHTTPrequest _request;
|
||||||
|
bool _fileActive;
|
||||||
|
File _file;
|
||||||
|
int _bytecount;
|
||||||
|
int _queuecount;
|
||||||
|
QueueHandle_t _queue;
|
||||||
|
public:
|
||||||
|
CWebContentDL();
|
||||||
|
~CWebContentDL();
|
||||||
|
void get(const char* filename);
|
||||||
|
void process();
|
||||||
|
// callback handlers
|
||||||
|
int16_t queueDLdata(int size, asyncHTTPrequest* request);
|
||||||
|
void finalise();
|
||||||
|
bool busy() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void WebPageRequestCB(void* optParm, asyncHTTPrequest* request, int readyState);
|
||||||
|
void WebPageDataCB(void* optParm, asyncHTTPrequest*, size_t available);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue