mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-13 05:53:06 +01:00
refactoring: move webserver stuff to own lib
This commit is contained in:
@@ -76,6 +76,7 @@ class Message{
|
||||
class RequestMessage : public Message{
|
||||
protected:
|
||||
String result;
|
||||
String contentType;
|
||||
private:
|
||||
int len=0;
|
||||
int consumed=0;
|
||||
@@ -91,7 +92,8 @@ class RequestMessage : public Message{
|
||||
handled=true;
|
||||
}
|
||||
public:
|
||||
RequestMessage():Message(){
|
||||
RequestMessage(String contentType):Message(){
|
||||
this->contentType=contentType;
|
||||
}
|
||||
virtual ~RequestMessage(){
|
||||
GW_MESSAGE_DEBUG("~RequestMessage %p\n",this)
|
||||
@@ -108,6 +110,9 @@ class RequestMessage : public Message{
|
||||
return cplen;
|
||||
}
|
||||
bool isHandled(){return handled;}
|
||||
String getContentType(){
|
||||
return contentType;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
128
lib/webserver/GwWebServer.cpp
Normal file
128
lib/webserver/GwWebServer.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <ESPmDNS.h>
|
||||
#include "GwWebServer.h"
|
||||
#include <map>
|
||||
|
||||
class EmbeddedFile;
|
||||
static std::map<String,EmbeddedFile*> embeddedFiles;
|
||||
class EmbeddedFile {
|
||||
public:
|
||||
const uint8_t *start;
|
||||
int len;
|
||||
EmbeddedFile(String name,const uint8_t *start,int len){
|
||||
this->start=start;
|
||||
this->len=len;
|
||||
embeddedFiles[name]=this;
|
||||
}
|
||||
} ;
|
||||
#define EMBED_GZ_FILE(fileName, fileExt) \
|
||||
extern const uint8_t fileName##_##fileExt##_File[] asm("_binary_generated_" #fileName "_" #fileExt "_gz_start"); \
|
||||
extern const uint8_t fileName##_##fileExt##_FileLen[] asm("_binary_generated_" #fileName "_" #fileExt "_gz_size"); \
|
||||
const EmbeddedFile fileName##_##fileExt##_Config(#fileName "." #fileExt,(const uint8_t*)fileName##_##fileExt##_File,(int)fileName##_##fileExt##_FileLen);
|
||||
|
||||
EMBED_GZ_FILE(index,html)
|
||||
EMBED_GZ_FILE(config,json)
|
||||
|
||||
void sendEmbeddedFile(String name,String contentType,AsyncWebServerRequest *request){
|
||||
std::map<String,EmbeddedFile*>::iterator it=embeddedFiles.find(name);
|
||||
if (it != embeddedFiles.end()){
|
||||
EmbeddedFile* found=it->second;
|
||||
AsyncWebServerResponse *response=request->beginResponse_P(200,contentType,found->start,found->len);
|
||||
response->addHeader(F("Content-Encoding"), F("gzip"));
|
||||
request->send(response);
|
||||
}
|
||||
else{
|
||||
request->send(404, "text/plain", "Not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GwWebServer::GwWebServer(GwLog* logger,int port){
|
||||
server=new AsyncWebServer(port);
|
||||
queue=xQueueCreate(10,sizeof(Message *));
|
||||
this->logger=logger;
|
||||
}
|
||||
void GwWebServer::begin(){
|
||||
server->onNotFound([](AsyncWebServerRequest *request){
|
||||
request->send(404, "text/plain", "Not found");
|
||||
});
|
||||
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
sendEmbeddedFile("index.html","text/html",request);
|
||||
});
|
||||
server->on("/config.json", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
sendEmbeddedFile("config.json","application/json",request);
|
||||
});
|
||||
server->begin();
|
||||
LOG_DEBUG(GwLog::LOG,"HTTP server started");
|
||||
MDNS.addService("_http","_tcp",80);
|
||||
|
||||
}
|
||||
GwWebServer::~GwWebServer(){
|
||||
server->end();
|
||||
delete server;
|
||||
vQueueDelete(queue);
|
||||
}
|
||||
void GwWebServer::handleAsyncWebRequest(AsyncWebServerRequest *request, RequestMessage *msg)
|
||||
{
|
||||
msg->ref(); //for the queue
|
||||
if (!xQueueSend(queue, &msg, 0))
|
||||
{
|
||||
Serial.println("unable to enqueue");
|
||||
msg->unref(); //queue
|
||||
msg->unref(); //our
|
||||
request->send(500, "text/plain", "queue full");
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "wait queue");
|
||||
if (msg->wait(500))
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "request ok");
|
||||
request->send(200, msg->getContentType(), msg->getResult());
|
||||
msg->unref();
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "switching to async");
|
||||
//msg is handed over to async handling
|
||||
bool finished = false;
|
||||
AsyncWebServerResponse *r = request->beginChunkedResponse(
|
||||
msg->getContentType(), [this,msg, finished](uint8_t *ptr, size_t len, size_t len2) -> size_t
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "try read");
|
||||
if (msg->isHandled() || msg->wait(1))
|
||||
{
|
||||
int rt = msg->consume(ptr, len);
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "async response available, return %d\n", rt);
|
||||
return rt;
|
||||
}
|
||||
else
|
||||
return RESPONSE_TRY_AGAIN;
|
||||
},
|
||||
NULL);
|
||||
request->onDisconnect([this,msg](void)
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "onDisconnect");
|
||||
msg->unref();
|
||||
});
|
||||
request->send(r);
|
||||
}
|
||||
bool GwWebServer::registerMainHandler(const char *url,RequestCreator creator){
|
||||
server->on(url,HTTP_GET, [this,creator,url](AsyncWebServerRequest *request){
|
||||
RequestMessage *msg=(*creator)(request);
|
||||
if (!msg){
|
||||
LOG_DEBUG(GwLog::DEBUG,"creator returns NULL for %s",url);
|
||||
request->send(404, "text/plain", "Not found");
|
||||
return;
|
||||
}
|
||||
handleAsyncWebRequest(request,msg);
|
||||
});
|
||||
}
|
||||
//to be called from the main loop
|
||||
void GwWebServer::fetchMainRequest()
|
||||
{
|
||||
Message *msg = NULL;
|
||||
if (xQueueReceive(queue, &msg, 0))
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "main message");
|
||||
msg->process();
|
||||
msg->unref();
|
||||
}
|
||||
}
|
||||
20
lib/webserver/GwWebServer.h
Normal file
20
lib/webserver/GwWebServer.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _GWWEBSERVER_H
|
||||
#define _GWWEBSERVER_H
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include "GwMessage.h"
|
||||
#include "GwLog.h"
|
||||
class GwWebServer{
|
||||
private:
|
||||
AsyncWebServer *server;
|
||||
QueueHandle_t queue;
|
||||
GwLog *logger;
|
||||
public:
|
||||
typedef RequestMessage *(RequestCreator)(AsyncWebServerRequest *request);
|
||||
GwWebServer(GwLog *logger, int port);
|
||||
~GwWebServer();
|
||||
void begin();
|
||||
bool registerMainHandler(const char *url,RequestCreator creator);
|
||||
void fetchMainRequest(); //to be called from main loop
|
||||
void handleAsyncWebRequest(AsyncWebServerRequest *request, RequestMessage *msg);
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user