Added the WEBServerManager class to enable the initialization of the WEBServer using a config file, I might change the behaviour of this initialization when some parameters are missing, renamed the old WEBServerManager class to WEBServerManager_deprecated, now using the new WEBServerManager in the SAB object instead of the WEBServer directly, minor changes to the OTAManager, migrating the dashboard v2 layout so that every tile has the same size
This commit is contained in:
parent
a23fb4cba9
commit
a951cdd6fc
@ -7,7 +7,7 @@
|
||||
|
||||
WEB_ENABLED : 'true'
|
||||
WEB_PORT : 80
|
||||
WEB_MAX_CLIENT : 0
|
||||
WEB_MAX_CLIENT : 10
|
||||
WEB_WWW_DIR : '/WWW'
|
||||
FTP_ENABLED : 'true'
|
||||
FTP_LOGIN : 'ESP8266'
|
||||
@ -15,4 +15,4 @@ FTP_PASSWORD : '12345678'
|
||||
FTP_ROOT_DIR : '/FTP'
|
||||
FTP_PORT : 21
|
||||
FTP_DATA_PORT : 1024
|
||||
FTP_MAX_CLIENT : 0
|
||||
FTP_MAX_CLIENT : 10
|
||||
|
@ -14,6 +14,10 @@
|
||||
{
|
||||
/*flex: 1 0 auto;*/
|
||||
}
|
||||
|
||||
td,tr
|
||||
{
|
||||
}
|
||||
|
||||
.switch label input[type=checkbox]:checked+.lever
|
||||
{
|
||||
@ -116,18 +120,28 @@
|
||||
</div>
|
||||
<!-- End of modal window definition -->
|
||||
<section id="mainpage_id">
|
||||
<div class="row">
|
||||
<div class="row col m6">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Connectivity</h5>
|
||||
</div>
|
||||
<div class="col m6">
|
||||
<div class="card teal darken-1">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title center-align" style="font-weight:bold;">Access Point Mode</span>
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2" style="width: 50%;">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Connectivity</h5>
|
||||
</div>
|
||||
<div class="card-action center-align">
|
||||
<div class="switch">
|
||||
</td>
|
||||
<td colspan="2" style="width: 50%;">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">System Info</h5>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div class="row" style="display:flex;">
|
||||
<div class="teal darken-1 col m3" style="margin: 7px 22px 7px 22px;border-radius: 5px;padding-bottom: 15px;">
|
||||
<div class="white-text">
|
||||
<h5 style="font-weight:bold;" class="center-align">Access Point Mode</h5>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="switch center-align">
|
||||
<label class="white-text">
|
||||
Disabled
|
||||
<input type="checkbox">
|
||||
@ -145,24 +159,20 @@
|
||||
</div>
|
||||
<input placeholder="SSID" id="ssid" type="text" class="validate white-text">
|
||||
<input onmouseleave="showHidePassword('pwd','hide')" onmouseover="showHidePassword('pwd','show');" value="somePassword" placeholder="Password" id="pwd" type="password" class="validate white-text">
|
||||
<hr>
|
||||
<div class="center-align">
|
||||
<button class="btn waves-effect waves-light green darken-3" type="submit" name="apply">
|
||||
Apply ✔
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn waves-effect waves-light green darken-3" type="submit" name="apply">
|
||||
Apply ✔
|
||||
</button>
|
||||
<button class="btn waves-effect waves-light red darken-3" style="" type="submit" name="cancel">
|
||||
Cancel ✘
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col m6">
|
||||
<div class="card teal darken-1">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title center-align" style="font-weight:bold;">Station Mode</span>
|
||||
</div>
|
||||
<div class="card-action center-align">
|
||||
<div class="switch">
|
||||
|
||||
<div class="teal darken-1 col m3" style="margin: 7px 22px 7px 22px;border-radius: 5px;padding-bottom: 15px;">
|
||||
<div class="white-text">
|
||||
<h5 style="font-weight:bold;" class="center-align">Station Mode</h5>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="switch center-align">
|
||||
<label class="white-text">
|
||||
Disabled
|
||||
<input type="checkbox">
|
||||
@ -179,31 +189,30 @@
|
||||
</div>
|
||||
</div>
|
||||
<select id="networksSelect">
|
||||
<option value="" disabled selected>Click on scan</option>
|
||||
<option value="" disabled selected>Click on scan</option>
|
||||
</select>
|
||||
<input placeholder="Password" id="pwd" type="password" class="validate white-text">
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn waves-effect waves-light green darken-3" type="submit" name="apply">
|
||||
Connect
|
||||
</button>
|
||||
<button class="btn waves-effect waves-light lime darken-3" style="" onclick="scanAvailableNetworks();" type="submit" name="Scan">
|
||||
Scan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row col m6">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">System Info</h5>
|
||||
</div>
|
||||
<div class="col m12">
|
||||
<div class="card teal darken-1">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title center-align" style="font-weight:bold;">System State</span>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col m6">
|
||||
<button class="btn waves-effect waves-light green darken-3" type="submit" name="apply">
|
||||
Connect
|
||||
</button>
|
||||
</div>
|
||||
<div class="col m6 right-align">
|
||||
<button class="btn waves-effect waves-light lime darken-3" style="" onclick="scanAvailableNetworks();" type="submit" name="Scan">
|
||||
Scan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action white-text" style="font-size:1.2em;">
|
||||
</div>
|
||||
|
||||
<div class="teal darken-1 col m6" style="margin: 7px 22px 7px 22px;border-radius: 5px;padding-bottom: 15px;">
|
||||
<div class="white-text">
|
||||
<h5 style="font-weight:bold;" class="center-align">System State</h5>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="white-text" style="font-size:1.2em;">
|
||||
<div class="row">
|
||||
<div class="col m6">
|
||||
Cpu frequency :
|
||||
@ -242,79 +251,131 @@
|
||||
<div class="col m6">
|
||||
<span id="upTime"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top:-20px;">
|
||||
<div class="row col m3">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Clock</h5>
|
||||
</div>
|
||||
<div class="col m12">
|
||||
<div class="card teal darken-1">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title center-align" style="font-weight:bold;">DS3231 RTC</span>
|
||||
</td>
|
||||
<td>
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Storage</h5>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="2">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Services</h5>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div class="row" style="display:flex;">
|
||||
<div class="teal darken-1 col m3" style="margin: 7px 22px 7px 22px;border-radius: 5px;padding-bottom: 15px;">
|
||||
<div class="white-text">
|
||||
<h5 style="font-weight:bold;" class="center-align">DS3231 RTC</h5>
|
||||
</div>
|
||||
<hr>
|
||||
<div style="font-size:1.2em;">
|
||||
<input type="text" class="datepicker" id="datepicker_id">
|
||||
<input type="text" class="timepicker" id="timepicker_id">
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col m6">
|
||||
<button class="btn waves-effect waves-light green darken-3" onclick="setRtcTime();" name="apply">
|
||||
Apply ✔
|
||||
</button>
|
||||
</div>
|
||||
<div class="col m6 right-align">
|
||||
<button class="btn waves-effect waves-light green darken-3 tooltipped" onclick="setRtc2BrowserTime();" data-position="bottom" data-tooltip="Use the browser time to set the RTC time" name="browserTime">
|
||||
Set browser time ✔
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-action" style="font-size:1.2em;">
|
||||
<input type="text" class="datepicker" id="datepicker_id">
|
||||
<input type="text" class="timepicker" id="timepicker_id">
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn waves-effect waves-light green darken-3" onclick="setRtcTime();" name="apply">
|
||||
Apply ✔
|
||||
</button>
|
||||
<button class="btn waves-effect waves-light green darken-3 tooltipped" onclick="setRtc2BrowserTime();" data-position="bottom" data-tooltip="Use the browser time to set the RTC time" name="browserTime">
|
||||
Set browser time ✔
|
||||
</button>
|
||||
<div class="teal darken-1 col m3" style="margin: 7px 22px 7px 22px;border-radius: 5px;padding-bottom: 15px;">
|
||||
<div class="white-text">
|
||||
<h5 style="font-weight:bold;" class="center-align">SD Card</h5>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="white-text center-align" style="font-size:1.2em;">
|
||||
<div class="switch">
|
||||
<label class="white-text">
|
||||
Unmounted
|
||||
<input type="checkbox" id="sdcardmounted_id" onchange="mountUnmountCard('sdcardmounted_id');">
|
||||
<span class="lever"></span>
|
||||
Mounted
|
||||
</label>
|
||||
</div>
|
||||
<div class="row left-align">
|
||||
<div class="col m6">
|
||||
Size :
|
||||
</div>
|
||||
<div class="col m6">
|
||||
<span id="cardSize">NaN Gbytes</span>
|
||||
</div>
|
||||
<div class="col m6">
|
||||
Free :
|
||||
</div>
|
||||
<div class="col m6">
|
||||
XX GBytes
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="row" style="margin-top:-20px;">
|
||||
<div class="row col m3">
|
||||
<div class="col m12">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row col m3">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Storage</h5>
|
||||
</div>
|
||||
|
||||
<div class="col m12">
|
||||
<div class="card teal darken-1">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title center-align" style="font-weight:bold;">SD Card</span>
|
||||
</div>
|
||||
<div class="card-action white-text center-align" style="font-size:1.2em;">
|
||||
<div class="switch">
|
||||
<label class="white-text">
|
||||
Unmounted
|
||||
<input type="checkbox" id="sdcardmounted_id" onchange="mountUnmountCard('sdcardmounted_id');">
|
||||
<span class="lever"></span>
|
||||
Mounted
|
||||
</label>
|
||||
</div>
|
||||
<div class="row left-align">
|
||||
<div class="col m6">
|
||||
Size :
|
||||
</div>
|
||||
<div class="col m6">
|
||||
<span id="cardSize">NaN Gbytes</span>
|
||||
</div>
|
||||
<div class="col m6">
|
||||
Free :
|
||||
</div>
|
||||
<div class="col m6">
|
||||
XX GBytes
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col m6">
|
||||
<div style="margin:10px;padding:5px 0 10px 0;" class="grey lighten-2 z-depth-3">
|
||||
<h5 class="center-align">Services</h5>
|
||||
</div>
|
||||
<div class="col m6">
|
||||
<div class="card teal darken-1">
|
||||
<div class="card-content white-text">
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "definition.h"
|
||||
|
||||
#define DEBUG_OTA_MANAGER(...) do {} while(0)
|
||||
|
||||
//#define DEBUG_OTA_MANAGER(...) do { Serial.printf(__VA_ARGS__); Serial.println();} while(0)
|
||||
|
||||
OTAManager::OTAManager(SDCardManager &sdCardManager, const BoardConfig &boardConfig) : _sdCardManager(&sdCardManager), _boardConfig(&boardConfig)
|
||||
@ -12,18 +11,11 @@ OTAManager::~OTAManager()
|
||||
{ }
|
||||
|
||||
boolean OTAManager::init(void)
|
||||
{
|
||||
//If the SDCardManager is not available, then we disable the OTA service
|
||||
if(!_sdCardManager)
|
||||
{
|
||||
DEBUG_OTA_MANAGER("SDCardMng is NULL !");
|
||||
return true;
|
||||
}
|
||||
|
||||
//If the SDCardManager is available, then we try to read the config file
|
||||
{
|
||||
//We try to read the config file
|
||||
CFGDictionary<CFGParameterValue> *otaCfg = _sdCardManager->getCFGFile(OTA_CFG_FILE);
|
||||
boolean toReturn(true);
|
||||
//If we did not find the file
|
||||
//If we did not find the file or we didn't manage to open it !
|
||||
if(!otaCfg)
|
||||
{
|
||||
DEBUG_OTA_MANAGER("otaCfg is NULL !");
|
||||
@ -68,13 +60,17 @@ boolean OTAManager::init(void)
|
||||
else
|
||||
{
|
||||
DEBUG_OTA_MANAGER("OTA_SERVER_ADDRESS is NULL !");
|
||||
_isServiceEnabled = false;
|
||||
toReturn = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
_isServiceEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_OTA_MANAGER("ENABLED is NULL !");
|
||||
_isServiceEnabled = false;
|
||||
toReturn = false;
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,10 @@ class OTAManager
|
||||
boolean init(void);
|
||||
boolean isEnabled(void) const;
|
||||
OTAUpdater& getOTAUpdater(void);
|
||||
|
||||
protected:
|
||||
OTAManager(SDCardManager &sdCardManager, const BoardConfig &boardConfig);
|
||||
OTAManager();
|
||||
|
||||
private:
|
||||
void updateStartedCb(void);
|
||||
void updateFinishedCb(void);
|
||||
@ -27,6 +28,7 @@ class OTAManager
|
||||
SDCardManager *_sdCardManager = nullptr;
|
||||
const BoardConfig * _boardConfig = nullptr;
|
||||
boolean _isServiceEnabled = false;
|
||||
|
||||
};
|
||||
|
||||
#endif //OTAMANAGER_H
|
@ -4,7 +4,7 @@ SAB::SAB() : _sdCardManager(_boardConfig.getSPI_SDCard_cs(), _boardConfig.getSPI
|
||||
_display(_boardConfig.getScreenWidth(),_boardConfig.getScreenHeight(), &Wire),
|
||||
_screenManager(_display, &_sdCardManager),
|
||||
_connectivityManager(_sdCardManager),
|
||||
_webServer(80, &_sdCardManager, 10),
|
||||
_webServerManager(_sdCardManager),
|
||||
_ftpServer(&_sdCardManager, 21, "ESP8266", "12345678", 10),
|
||||
_otaManager(_sdCardManager, _boardConfig),
|
||||
_dbWSServer(81),
|
||||
@ -15,12 +15,12 @@ _taskSchedulerManager(_rtcManager)
|
||||
initCommonConfig();
|
||||
}
|
||||
|
||||
SAB::SAB(const BoardConfig boardConfig, const unsigned int webServerPort, const unsigned int ftpServerPort) : _boardConfig(boardConfig),
|
||||
SAB::SAB(const BoardConfig boardConfig, const unsigned int ftpServerPort) : _boardConfig(boardConfig),
|
||||
_sdCardManager(_boardConfig.getSPI_SDCard_cs(), _boardConfig.getSPISpeed()),
|
||||
_display(_boardConfig.getScreenWidth(), _boardConfig.getScreenHeight(), &Wire),
|
||||
_screenManager(_display, &_sdCardManager),
|
||||
_connectivityManager(_sdCardManager),
|
||||
_webServer(webServerPort, &_sdCardManager, 10),
|
||||
_webServerManager(_sdCardManager),
|
||||
_ftpServer(&_sdCardManager, ftpServerPort, "ESP8266", "12345678", 10),
|
||||
_otaManager(_sdCardManager, _boardConfig),
|
||||
_dbWSServer(81),
|
||||
@ -64,16 +64,14 @@ void SAB::initCommonConfig()
|
||||
_screenManager.init();
|
||||
if(!_connectivityManager.connect()){ _error |= CONNECT_ERR;}
|
||||
if(!_pcf.begin()){_error |= IO_INIT_ERR;}
|
||||
if(!_otaManager.init()){_error |= OTA_INIT_ERR;}
|
||||
if(!_otaManager.init()){_error |= OTAMAN_INIT_ERR;}
|
||||
if(!_webServerManager.init()){_error |= WEBSRVMAN_INIT_ERR;}
|
||||
|
||||
//We set the different servers :
|
||||
_webServer.setWWWDir(WWW_DIR);
|
||||
_ftpServer.setFTPDir(FTP_DIR);
|
||||
//We start the servers
|
||||
_dbWSServer.begin();
|
||||
_webServer.enableTCPKeepAlive(15,5,5);
|
||||
_ftpServer.enableTCPKeepAlive(15,5,5);
|
||||
_webServer.start();
|
||||
_ftpServer.start();
|
||||
}
|
||||
|
||||
@ -106,9 +104,9 @@ ConnectivityManager& SAB::getConnectivityManager()
|
||||
return _connectivityManager;
|
||||
}
|
||||
|
||||
WEBServer<WEBClient>& SAB::getWebServer()
|
||||
WEBServerManager& SAB::getWebServerManager()
|
||||
{
|
||||
return _webServer;
|
||||
return _webServerManager;
|
||||
}
|
||||
|
||||
FTPServer<FTPClient>& SAB::getFtpServer()
|
||||
@ -158,7 +156,7 @@ uint8_t SAB::getError() const
|
||||
|
||||
void SAB::run()
|
||||
{
|
||||
_webServer.run();
|
||||
_webServerManager.getWEBServer().run();
|
||||
_ftpServer.run();
|
||||
_taskSchedulerManager.run();
|
||||
_screenManager.run();
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "ScreenManager.h"
|
||||
#include "SDCardManager.h"
|
||||
#include "ConnectivityManager.h"
|
||||
#include "WEBClient.h" //includes WEBServer internally
|
||||
#include "WEBServerManager.h"
|
||||
#include "FTPClient.h" //includes FTPServer internally
|
||||
#include "DashboardWSServer.h"
|
||||
#include "IOManager.h"
|
||||
@ -21,10 +21,10 @@
|
||||
class SAB
|
||||
{
|
||||
public:
|
||||
enum Error {RTC_BEGIN_ERR = 1, DISP_BEGIN_ERR = 2, SDCARD_INIT_ERR = 4, IO_INIT_ERR = 8, CONNECT_ERR = 16, OTA_INIT_ERR = 32};
|
||||
enum Error {RTC_BEGIN_ERR = 1 << 0, DISP_BEGIN_ERR = 1 << 1, SDCARD_INIT_ERR = 1 << 2, IO_INIT_ERR = 1 << 3, CONNECT_ERR = 1 << 4, OTAMAN_INIT_ERR = 1 << 5, WEBSRVMAN_INIT_ERR = 1 << 6};
|
||||
|
||||
SAB();
|
||||
SAB(const BoardConfig boardConfig, const unsigned int webServerPort = 80, const unsigned int ftpServerPort = 21);
|
||||
SAB(const BoardConfig boardConfig, const unsigned int ftpServerPort = 21);
|
||||
~SAB()
|
||||
{
|
||||
}
|
||||
@ -34,7 +34,7 @@ class SAB
|
||||
RTC_DS3231& getRTC_DS3231();
|
||||
SDCardManager& getSdCardManager();
|
||||
ConnectivityManager& getConnectivityManager();
|
||||
WEBServer<WEBClient>& getWebServer();
|
||||
WEBServerManager& getWebServerManager();
|
||||
FTPServer<FTPClient>& getFtpServer();
|
||||
OTAManager& getOTAManager();
|
||||
IOManager& getIOManager();
|
||||
@ -57,7 +57,7 @@ class SAB
|
||||
RTC_DS3231 _rtc;
|
||||
RtcManager _rtcManager;
|
||||
ConnectivityManager _connectivityManager;
|
||||
WEBServer<WEBClient> _webServer;
|
||||
WEBServerManager _webServerManager;
|
||||
FTPServer<FTPClient> _ftpServer;
|
||||
OTAManager _otaManager;
|
||||
DashboardWSServer _dbWSServer;
|
||||
|
@ -93,6 +93,11 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
||||
}
|
||||
}
|
||||
|
||||
void setSDClass(SDClass *sdClass)
|
||||
{
|
||||
_sdClass = sdClass;
|
||||
}
|
||||
|
||||
const char * getWWWDir(void) const
|
||||
{
|
||||
return _WWWDir;
|
||||
|
@ -1,552 +1,83 @@
|
||||
/**
|
||||
* @file WEBServerManager.cpp
|
||||
* @author Anatole SCHRAMM-HENRY
|
||||
* @brief Single client WEB Server.
|
||||
* This class is now retired and replaced by the much better WEBServer class
|
||||
* which handles multiclients among other things.
|
||||
* @version 0.1
|
||||
* @date 31/03/2019
|
||||
*
|
||||
* @copyright MIT
|
||||
*
|
||||
*/
|
||||
#include "WEBServerManager.h"
|
||||
#include "definition.h"
|
||||
|
||||
//#define DEBUG
|
||||
#define DEBUG_BODY
|
||||
//#define DEBUG_PARAMETER
|
||||
//#define DEBUG_CONTENT_LENGTH
|
||||
//#define DEBUG_RAW
|
||||
//#define DEBUG_FILEPATH
|
||||
//#define DEBUG_WEB_SERVER_MANAGER(...) do {} while(0)
|
||||
#define DEBUG_WEB_SERVER_MANAGER(...) do { Serial.printf(__VA_ARGS__); Serial.println();} while(0)
|
||||
|
||||
WEBServerManager::WEBServerManager(unsigned int port, SDCardManager *sdCardManager) : _wifiServer(port), _sdCardManager(sdCardManager), _httpRequestData({UNDEFINED, UNKNOWN, UNKNOWN_MIME, Dictionary<DictionaryHelper::StringEntity>(), Dictionary<DictionaryHelper::StringEntity>(), NULL,NULL}), _httpParserState(INIT), _clientState(WAITING_FOR_CLIENT), _port(port), _clientTimeout(0)
|
||||
WEBServerManager::WEBServerManager(SDCardManager &sdCardManager) : _sdCardManager(&sdCardManager), _webServer(80, &sdCardManager, 10)
|
||||
{
|
||||
_wifiServer.begin();
|
||||
|
||||
}
|
||||
|
||||
boolean WEBServerManager::addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient* , void*), void *pData, HttpRequestMethod HRM)
|
||||
WEBServerManager::~WEBServerManager()
|
||||
{
|
||||
return _apiDictionary.add(uri,new ApiRoutine({apiRoutine,pData, HRM}));
|
||||
|
||||
}
|
||||
|
||||
void WEBServerManager::clearApiRoutine()
|
||||
boolean WEBServerManager::init(void)
|
||||
{
|
||||
_apiDictionary.clear();
|
||||
}
|
||||
|
||||
boolean WEBServerManager::removeApiRoutine(const char *uri)
|
||||
{
|
||||
return _apiDictionary.remove(uri);
|
||||
}
|
||||
|
||||
boolean WEBServerManager::runServer()
|
||||
{
|
||||
switch(_clientState)
|
||||
{
|
||||
case WAITING_FOR_CLIENT:
|
||||
_wifiClient.stopAll();
|
||||
|
||||
_wifiClient = _wifiServer.available();
|
||||
if(_wifiClient)
|
||||
{
|
||||
_clientState = NEW;
|
||||
#ifdef DEBUG
|
||||
Serial.println("Client connected !!!");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case NEW:
|
||||
_clientState = NOT_HANDLED;
|
||||
break;
|
||||
case NOT_HANDLED:
|
||||
clearHttpRequestData();
|
||||
parseQuery(&_wifiClient);
|
||||
#ifdef DEBUG
|
||||
Serial.println("Nothing more from client !!!");
|
||||
#endif
|
||||
_clientState = QUERY_PARSED;
|
||||
break;
|
||||
case QUERY_PARSED:
|
||||
#ifdef DEBUG
|
||||
Serial.println("Sending response !!!");
|
||||
#endif
|
||||
//We first check if it's an api call
|
||||
if(!sendPageToClientFromApiDictio(&_wifiClient))
|
||||
{
|
||||
sendPageToClientFromSdCard(&_wifiClient);
|
||||
}
|
||||
_clientState = RESPONSE_SENT;
|
||||
break;
|
||||
case RESPONSE_SENT:
|
||||
#ifdef DEBUG
|
||||
Serial.println("Client handled !!!");
|
||||
#endif
|
||||
_clientState = HANDLED;
|
||||
break;
|
||||
case HANDLED:
|
||||
_wifiClient.stopAll();
|
||||
_clientState = WAITING_FOR_CLIENT;
|
||||
#ifdef DEBUG
|
||||
Serial.println("Client discarded !!!");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean WEBServerManager::parseQuery(WiFiClient *wifiClient)
|
||||
{
|
||||
char readChar(0), *parseBuffer(NULL), *parseKey(NULL), *parseValue(NULL), *parseParameter(NULL), *contentLength(NULL);
|
||||
boolean isKey(true), receivingDone(false);
|
||||
unsigned int activeTimeout = 10000;
|
||||
unsigned long dataBytesCounter = 0, dataBytes = 0;
|
||||
|
||||
/* Better way to read data
|
||||
char temp[2048];
|
||||
temp[wifiClient->read((uint8_t*)temp,2040)] = '\0';
|
||||
Serial.print(temp);
|
||||
*/
|
||||
_httpParserState = INIT;
|
||||
_clientTimeout = millis();
|
||||
boolean slashesOrAntiSlashesOnly(true);
|
||||
while((wifiClient->available() || ( millis() - _clientTimeout < activeTimeout)) && wifiClient->connected())
|
||||
{
|
||||
if(wifiClient->available())
|
||||
CFGDictionary<CFGParameterValue> *serverCfg = _sdCardManager->getCFGFile(SERVER_CFG_FILE);
|
||||
boolean toReturn(true);
|
||||
|
||||
//We were not able to read the config file, so we apply default parameters
|
||||
if(!serverCfg)
|
||||
{
|
||||
readChar = (char)wifiClient->read();
|
||||
|
||||
#ifdef DEBUG_RAW
|
||||
Serial.print(readChar);
|
||||
#endif
|
||||
//INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR
|
||||
switch(_httpParserState)
|
||||
{
|
||||
case INIT:
|
||||
if(readChar >= 65 && readChar <= 90)
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_VERB_SECTION;
|
||||
}
|
||||
else
|
||||
_httpParserState = ERROR;
|
||||
break;
|
||||
case LINE_BREAK:
|
||||
if(readChar == '\n')
|
||||
{
|
||||
if(_httpRequestData.HRM == GET)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Serial.println("GET DONE");
|
||||
#endif
|
||||
receivingDone = true;
|
||||
}
|
||||
_httpParserState = BODY_SECTION;
|
||||
}
|
||||
else if(readChar != '\r')
|
||||
{
|
||||
if(parseParameter != NULL)
|
||||
{
|
||||
contentLength = strstr(parseParameter, "ent-Len");//Matches Content-Length short to save some RAM
|
||||
if(contentLength != NULL)
|
||||
{
|
||||
dataBytes = strtol(contentLength+11,NULL,10);
|
||||
#ifdef DEBUG_CONTENT_LENGTH
|
||||
Serial.print("Data length : ");Serial.println(dataBytes);
|
||||
#endif
|
||||
}
|
||||
DEBUG_WEB_SERVER_MANAGER("serverCfg is NULL, applying default parameters !");
|
||||
_webServer.setWWWDir(WWW_DIR);
|
||||
_webServer.enableTCPKeepAlive(15,5,5);
|
||||
_webServer.start();
|
||||
_isServiceEnabled = true;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PARAMETER
|
||||
Serial.println(parseParameter);
|
||||
#endif
|
||||
free(parseParameter);parseParameter = NULL;
|
||||
}
|
||||
parseParameter = addChar(parseParameter, readChar);
|
||||
_httpParserState = PARAMETER_SECTION;
|
||||
}
|
||||
break;
|
||||
case HTTP_VERB_SECTION:
|
||||
if(readChar >= 65 && readChar <= 90)
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_VERB_SECTION;
|
||||
}
|
||||
else if (readChar == ' ')
|
||||
{
|
||||
//This is the end of the section
|
||||
_httpRequestData.HRM = getHttpVerbEnumValue(parseBuffer);
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
_httpParserState = HTTP_RESOURCE_SECTION;
|
||||
}
|
||||
else
|
||||
_httpParserState = ERROR;
|
||||
break;
|
||||
case HTTP_RESOURCE_SECTION:
|
||||
if(readChar == '?' )
|
||||
{
|
||||
free(_httpRequestData.httpResource);_httpRequestData.httpResource = NULL;
|
||||
_httpRequestData.httpResource = parseBuffer;parseBuffer = NULL;
|
||||
//We managed to read the config file, now we can apply it !
|
||||
if((*serverCfg)("WEB_ENABLED"))
|
||||
{
|
||||
if((*serverCfg)("WEB_ENABLED")->booleanValue())
|
||||
{
|
||||
_isServiceEnabled = true;
|
||||
|
||||
_httpParserState = HTTP_RESOURCE_PARAM_SECTION;
|
||||
}
|
||||
else if(readChar == ' ')
|
||||
{
|
||||
free(_httpRequestData.httpResource);_httpRequestData.httpResource = NULL;
|
||||
if(slashesOrAntiSlashesOnly)
|
||||
if((*serverCfg)("WEB_PORT"))
|
||||
{
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
_httpRequestData.httpResource = (char *) malloc(sizeof(char)*2);
|
||||
strcpy(_httpRequestData.httpResource,"/");
|
||||
DEBUG_WEB_SERVER_MANAGER("WEB_PORT is %u", (*serverCfg)("WEB_PORT")->uintValue());
|
||||
_webServer.setPort((*serverCfg)("WEB_PORT")->uintValue());
|
||||
}
|
||||
else
|
||||
_httpRequestData.httpResource = parseBuffer;parseBuffer = NULL;
|
||||
|
||||
_httpParserState = HTTP_VER_SECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(readChar != '/' && readChar != '\\') slashesOrAntiSlashesOnly = false;
|
||||
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_RESOURCE_SECTION;
|
||||
}
|
||||
break;
|
||||
case HTTP_RESOURCE_PARAM_SECTION: //index.web?var1=1&var2=2...
|
||||
if(readChar == ' ')
|
||||
if((*serverCfg)("WEB_MAX_CLIENT"))
|
||||
{
|
||||
_httpRequestData.getParams.add(parseKey,new DictionaryHelper::StringEntity(parseValue));
|
||||
free(parseKey);free(parseValue);
|
||||
parseKey = NULL;parseValue = NULL;
|
||||
_httpParserState = HTTP_VER_SECTION;
|
||||
DEBUG_WEB_SERVER_MANAGER("WEB_MAX_CLIENT is %u", (*serverCfg)("WEB_MAX_CLIENT")->uintValue());
|
||||
_webServer.setMaxClient((*serverCfg)("WEB_MAX_CLIENT")->uintValue());
|
||||
}
|
||||
else if( readChar == '=')
|
||||
isKey = false;
|
||||
else if(readChar == '&')
|
||||
|
||||
if((*serverCfg)("WEB_WWW_DIR"))
|
||||
{
|
||||
isKey = true;
|
||||
_httpRequestData.getParams.add(parseKey, new DictionaryHelper::StringEntity(parseValue));
|
||||
free(parseKey);free(parseValue);
|
||||
parseKey = NULL;parseValue = NULL;
|
||||
DEBUG_WEB_SERVER_MANAGER("WEB_WWW_DIR is %s", (*serverCfg)("WEB_WWW_DIR")->stringValue());
|
||||
_webServer.setWWWDir((*serverCfg)("WEB_WWW_DIR")->stringValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isKey)
|
||||
parseKey = addChar(parseKey, readChar);
|
||||
else
|
||||
parseValue = addChar(parseValue, readChar);
|
||||
}
|
||||
break;
|
||||
case HTTP_VER_SECTION:
|
||||
if((readChar >= 48 && readChar <= 57) || readChar == '.')
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_VER_SECTION;
|
||||
}
|
||||
else if(readChar == '\n')
|
||||
{
|
||||
_httpRequestData.HV = getHttpVersionEnumValue(parseBuffer);
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
_httpParserState = LINE_BREAK;
|
||||
}
|
||||
break;
|
||||
case BODY_SECTION:
|
||||
//parseBuffer = addChar(parseBuffer, readChar);
|
||||
if(_httpRequestData.HRM != GET)
|
||||
{
|
||||
dataBytesCounter++;//Should be always true
|
||||
}
|
||||
#ifdef DEBUG_BODY
|
||||
Serial.print(readChar);
|
||||
#endif
|
||||
break;
|
||||
case PARAMETER_SECTION: //Here are all the http header params
|
||||
if(readChar == '\n')
|
||||
{
|
||||
_httpParserState = LINE_BREAK;
|
||||
}else
|
||||
parseParameter = addChar(parseParameter, readChar);
|
||||
break;
|
||||
case IGNORED:
|
||||
break;
|
||||
case ERROR:
|
||||
return false;
|
||||
break; //Not necessary
|
||||
default :
|
||||
break;
|
||||
}
|
||||
//Exit condition
|
||||
if(receivingDone) break;
|
||||
if(_httpRequestData.HRM == POST && dataBytes != 0 && dataBytes == dataBytesCounter) break;
|
||||
|
||||
_clientTimeout = millis();
|
||||
}
|
||||
//yield(); //Likely causing a crash
|
||||
ESP.wdtFeed();
|
||||
}
|
||||
|
||||
if(parseBuffer != NULL)
|
||||
{
|
||||
if(strlen(parseBuffer) > 0)
|
||||
_webServer.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
_webServer.stop();
|
||||
_isServiceEnabled = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpRequestData.httpBody = parseBuffer;
|
||||
parseBuffer = NULL;
|
||||
DEBUG_WEB_SERVER_MANAGER("WEB_ENABLED is NULL !");
|
||||
toReturn = false;
|
||||
}
|
||||
}
|
||||
|
||||
free(parseParameter);parseParameter = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("HTTP VERB : ");
|
||||
Serial.println(_httpRequestData.HRM);
|
||||
Serial.print("HTTP RESOURCE : ");
|
||||
Serial.println(_httpRequestData.httpResource);
|
||||
Serial.print("HTTP VERSION : ");
|
||||
Serial.println(_httpRequestData.HV);
|
||||
Serial.print("BODY CONTENT : ");
|
||||
Serial.println(_httpRequestData.httpBody);
|
||||
Serial.println("GET PARAMS :");
|
||||
for(int i = 0; i < _httpRequestData.getParams.count(); i++)
|
||||
{
|
||||
Serial.print(_httpRequestData.getParams.getParameter(i));Serial.print(" : ");Serial.println(_httpRequestData.getParams.getAt(i)->getString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
unsigned int WEBServerManager::getPort() const
|
||||
boolean WEBServerManager::isEnabled(void) const
|
||||
{
|
||||
return _port;
|
||||
return _isServiceEnabled;
|
||||
}
|
||||
|
||||
boolean WEBServerManager::sendPageToClientFromSdCard(WiFiClient *wifiClient)
|
||||
WEBServer<WEBClient> &WEBServerManager::getWEBServer(void)
|
||||
{
|
||||
if(_sdCardManager != NULL)
|
||||
{
|
||||
File pageToSend;
|
||||
char readChar(0), *filePath(NULL), *header(NULL), sendBuffer[2048];
|
||||
|
||||
//We check what kind of http verb it is
|
||||
switch(_httpRequestData.HRM)
|
||||
{
|
||||
case GET:
|
||||
filePath = getFilePathByHttpResource(_httpRequestData.httpResource);
|
||||
if(filePath == NULL)
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<p>Failed to malloc filePath</p>\r\n</html>"));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("FILE PATH : ");
|
||||
Serial.println(filePath);
|
||||
#endif
|
||||
|
||||
pageToSend = _sdCardManager->open(filePath);
|
||||
free(filePath);filePath = NULL;
|
||||
|
||||
if(!pageToSend)
|
||||
{
|
||||
char *response(NULL);
|
||||
response = (char *) malloc(sizeof(char) * (strlen("HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Page not found for : </h1>\r\n<h4></h4>\r\n</html>") + strlen(_httpRequestData.httpResource) + 1));
|
||||
if(response == NULL)
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Failed to malloc response</h1>\r\n</html>"));
|
||||
return false;
|
||||
}
|
||||
sprintf(response, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Page not found for : </h1>\r\n<h4>%s</h4>\r\n</html>", _httpRequestData.httpResource);
|
||||
wifiClient->print(response);
|
||||
free(response);response = NULL;
|
||||
pageToSend.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("FILE SIZE : ");
|
||||
Serial.println(pageToSend.size());
|
||||
Serial.print("FILE NAME : ");
|
||||
Serial.println(pageToSend.name());
|
||||
Serial.print("FILE EXTENSION : ");
|
||||
//Serial.println(getFileExtension(pageToSend.name()));
|
||||
#endif
|
||||
|
||||
header = getHTTPHeader(getMIMETypeByExtension(getFileExtension(/*pageToSend.name()*/ "dummy")), pageToSend.size());
|
||||
if(header == NULL)
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Failed to malloc header</h1>\r\n</html>"));
|
||||
pageToSend.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
wifiClient->print(header);
|
||||
free(header);header = NULL;
|
||||
|
||||
while(pageToSend.available())
|
||||
{
|
||||
//if(wifiClient->write(sendBuffer, pageToSend.read(sendBuffer,2048)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
pageToSend.close();
|
||||
break;
|
||||
default: //If not supported
|
||||
wifiClient->print(F("HTTP/1.1 405 Method Not Allowed\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Method Not Allowed</h1>\r\n</html>"));
|
||||
break;
|
||||
}
|
||||
}else
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>SDCardManager is NULL<br \\>Check code</h1>\r\n</html>"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean WEBServerManager::sendPageToClientFromApiDictio(WiFiClient *wifiClient)
|
||||
{
|
||||
if(_apiDictionary.count() == 0 || _httpRequestData.httpResource == NULL)
|
||||
return false;
|
||||
|
||||
ApiRoutine *ref = _apiDictionary(_httpRequestData.httpResource);
|
||||
|
||||
if(ref == NULL)
|
||||
return false;
|
||||
|
||||
if(ref->HRM == UNDEFINED)
|
||||
{
|
||||
return (*(ref->apiRoutine))(_httpRequestData, wifiClient, ref->pData);
|
||||
}else if(ref->HRM == _httpRequestData.HRM)
|
||||
{
|
||||
return (*(ref->apiRoutine))(_httpRequestData, wifiClient, ref->pData);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
WEBServerManager::HttpMIMEType WEBServerManager::getMIMETypeByExtension(const char *extension)
|
||||
{
|
||||
//TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT
|
||||
if(strcmp(extension,"web") == 0) return TEXT_HTML;
|
||||
else if(strcmp(extension,"htm") == 0) return TEXT_HTML;
|
||||
else if(strcmp(extension,"css") == 0) return TEXT_CSS;
|
||||
else if(strcmp(extension,"js") == 0) return TEXT_JAVASCRIPT;
|
||||
else if(strcmp(extension,"png") == 0) return IMAGE_PNG;
|
||||
else if(strcmp(extension,"jpg") == 0) return IMAGE_JPEG;
|
||||
else if(strcmp(extension, "mp3") == 0) return AUDIO_MPEG;
|
||||
else return UNKNOWN_MIME;
|
||||
}
|
||||
|
||||
char *WEBServerManager::getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size)
|
||||
{
|
||||
char *header = (char *) malloc(sizeof(char) + strlen("HTTP/1.1 200 OK\r\nContent-Type: \r\nContent-Length: \r\n\r\n") + 74/*Longest MIME-TYPE*/ + 10 /*Max unsigned long footprint*/ + 1);
|
||||
|
||||
switch(httpMIMEType)
|
||||
{
|
||||
case TEXT_HTML:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/html",size);
|
||||
break;
|
||||
case TEXT_CSS:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/css",size);
|
||||
break;
|
||||
case TEXT_JAVASCRIPT:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/javascript",size);
|
||||
break;
|
||||
case IMAGE_PNG:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","image/png",size);
|
||||
break;
|
||||
case IMAGE_JPEG:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","image/jpeg",size);
|
||||
break;
|
||||
case TEXT_PLAIN:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/plain",size);
|
||||
break;
|
||||
case AUDIO_MPEG:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","audio/mpeg",size);
|
||||
break;
|
||||
case APPLICATION_OCTET_STREAM:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","application/octet-stream",size);
|
||||
break;
|
||||
default:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","application/octet-stream",size);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
char *WEBServerManager::getFileExtension(char *name)
|
||||
{
|
||||
if(name == NULL)return "";
|
||||
|
||||
char *ptr(name);
|
||||
int index(0);
|
||||
while(ptr[index] != '\0')
|
||||
{
|
||||
if(ptr[++index] == '.')
|
||||
{
|
||||
return (name + index +1);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
char *WEBServerManager::getFilePathByHttpResource(char *res)
|
||||
{
|
||||
uint16_t buffSize = strlen(WWW_DIR) + (strcmp(res, "/") == 0 ? 10:strlen(res)) + 1;//10 for /index.htm +1 for \0
|
||||
char *filePath = (char*) malloc( sizeof(char) * buffSize);
|
||||
|
||||
if(filePath == NULL)
|
||||
return NULL;
|
||||
|
||||
strcpy(filePath, WWW_DIR);
|
||||
strcat(filePath, strcmp(res, "/") == 0 ? "/index.htm":res);
|
||||
//sprintf(filePath,"%s%s",WWW_DIR, strcmp(res, "/") == 0 ? "/index.htm":res);
|
||||
|
||||
#ifdef DEBUG_FILEPATH
|
||||
Serial.println(res);
|
||||
Serial.print("Reserved space : ");Serial.println(buffSize);
|
||||
Serial.print("Actual size : ");Serial.println(strlen(filePath));
|
||||
Serial.println(filePath);
|
||||
#endif
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
WEBServerManager::HttpRequestMethod WEBServerManager::getHttpVerbEnumValue(const char *parseBuffer)
|
||||
{
|
||||
//UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
|
||||
if(strcmp(parseBuffer,"GET") == 0){return GET;}
|
||||
else if(strcmp(parseBuffer,"POST") == 0){return POST;}
|
||||
else if(strcmp(parseBuffer,"HEAD") == 0){return HEAD;}
|
||||
else if(strcmp(parseBuffer,"PUT") == 0){return PUT;}
|
||||
else if(strcmp(parseBuffer,"DELETE") == 0){return DELETE;}
|
||||
else if(strcmp(parseBuffer,"CONNECT") == 0){return CONNECT;}
|
||||
else if(strcmp(parseBuffer,"TRACE") == 0){return TRACE;}
|
||||
else if(strcmp(parseBuffer,"PATCH") == 0){return PATCH;}
|
||||
else if(strcmp(parseBuffer,"OPTIONS") == 0){return OPTIONS;}
|
||||
else
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
WEBServerManager::HttpVersion WEBServerManager::getHttpVersionEnumValue(const char *parseBuffer)
|
||||
{
|
||||
//HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0
|
||||
if(strcmp(parseBuffer,"1.1") == 0){return HTTP_1_1;}
|
||||
else if(strcmp(parseBuffer,"2.0") == 0){return HTTP_2_0;}
|
||||
else if(strcmp(parseBuffer,"1.0") == 0){return HTTP_1_0;}
|
||||
else if(strcmp(parseBuffer,"0.9") == 0){return HTTP_0_9;}
|
||||
else
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
void WEBServerManager::clearHttpRequestData()
|
||||
{
|
||||
_httpRequestData.HRM = UNDEFINED;
|
||||
_httpRequestData.HV = UNKNOWN;
|
||||
_httpRequestData.HMT = UNKNOWN_MIME;
|
||||
free(_httpRequestData.httpResource);free(_httpRequestData.httpBody);
|
||||
_httpRequestData.httpResource = NULL;_httpRequestData.httpBody = NULL;
|
||||
_httpRequestData.getParams.dispose();
|
||||
_httpRequestData.postParams.dispose();
|
||||
}
|
||||
return _webServer;
|
||||
}
|
@ -1,81 +1,26 @@
|
||||
/**
|
||||
* @file WEBServerManager.h
|
||||
* @author Anatole SCHRAMM-HENRY
|
||||
* @brief Single client WEB Server.
|
||||
* This class is now retired and replaced by the much better WEBServer class
|
||||
* which handles multiclients among other things.
|
||||
* @version 0.1
|
||||
* @date 31/03/2019
|
||||
*
|
||||
* @copyright MIT
|
||||
*
|
||||
*/
|
||||
#ifndef WEBSERVERMANAGER_H
|
||||
#define WEBSERVERMANAGER_H
|
||||
|
||||
#include <WiFiServer.h>
|
||||
#include <WiFiClient.h>
|
||||
#include "SDCardManager.h"
|
||||
#include "definition.h"
|
||||
#include "Dictionary.h"
|
||||
|
||||
struct HttpRequestData;
|
||||
#include "WEBClient.h" //includes WEBServer internally
|
||||
|
||||
class WEBServerManager
|
||||
{
|
||||
public:
|
||||
enum ClientStatus {NOT_HANDLED, HANDLED, NEW, WAITING_FOR_CLIENT, QUERY_PARSED, RESPONSE_SENT};
|
||||
enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};
|
||||
enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0};
|
||||
enum HttpParserStatus {INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_RESOURCE_PARAM_SECTION, HTTP_VER_SECTION, PARAMETER_SECTION, BODY_SECTION, IGNORED, ERROR};
|
||||
enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED, IMAGE_PNG, IMAGE_JPEG, AUDIO_MPEG, APPLICATION_OCTET_STREAM};
|
||||
struct HttpRequestData{
|
||||
HttpRequestMethod HRM;
|
||||
HttpVersion HV;
|
||||
HttpMIMEType HMT;
|
||||
Dictionary<DictionaryHelper::StringEntity> getParams;
|
||||
Dictionary<DictionaryHelper::StringEntity> postParams;
|
||||
char *httpResource;
|
||||
char *httpBody;
|
||||
};
|
||||
|
||||
WEBServerManager(unsigned int port = 80, SDCardManager *sdCardManager = NULL);
|
||||
friend class SAB;
|
||||
public:
|
||||
~WEBServerManager();
|
||||
boolean init(void);
|
||||
boolean isEnabled(void) const;
|
||||
WEBServer<WEBClient> &getWEBServer(void);
|
||||
|
||||
boolean runServer();
|
||||
unsigned int getPort() const;
|
||||
boolean addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*), void *pData, HttpRequestMethod HRM = UNDEFINED);
|
||||
void clearApiRoutine();
|
||||
boolean removeApiRoutine(const char *uri);
|
||||
protected:
|
||||
private:
|
||||
struct ApiRoutine
|
||||
{
|
||||
boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*);
|
||||
void *pData;
|
||||
HttpRequestMethod HRM;
|
||||
};
|
||||
|
||||
boolean parseQuery(WiFiClient *wifiClient);
|
||||
boolean sendPageToClientFromSdCard(WiFiClient *wifiClient);
|
||||
boolean sendPageToClientFromApiDictio(WiFiClient *wifiClient);
|
||||
HttpRequestMethod getHttpVerbEnumValue(const char *parseBuffer);
|
||||
HttpVersion getHttpVersionEnumValue(const char *parseBuffer);
|
||||
char *getFilePathByHttpResource(char *res);
|
||||
char *getFileExtension(char *name);
|
||||
HttpMIMEType getMIMETypeByExtension(const char *extension);
|
||||
char *getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size);
|
||||
void clearHttpRequestData();
|
||||
|
||||
WiFiServer _wifiServer;
|
||||
WiFiClient _wifiClient;//One client only, may be replaced with a fifo in the future
|
||||
SDCardManager *_sdCardManager;
|
||||
HttpRequestData _httpRequestData;
|
||||
Dictionary<ApiRoutine> _apiDictionary;
|
||||
|
||||
ClientStatus _clientState;
|
||||
HttpParserStatus _httpParserState;
|
||||
unsigned long _clientTimeout;
|
||||
unsigned int _port;
|
||||
protected:
|
||||
WEBServerManager(SDCardManager &sdCardManager);
|
||||
|
||||
private:
|
||||
SDCardManager *_sdCardManager = nullptr;
|
||||
boolean _isServiceEnabled = false;
|
||||
WEBServer<WEBClient> _webServer;
|
||||
|
||||
};
|
||||
|
||||
#endif //WEBSERVERMANAGER_H
|
||||
#endif //WEBSERVERMANAGER_H
|
552
src/app/WEBServerManager_deprecated.cpp
Normal file
552
src/app/WEBServerManager_deprecated.cpp
Normal file
@ -0,0 +1,552 @@
|
||||
/**
|
||||
* @file WEBServerManager.cpp
|
||||
* @author Anatole SCHRAMM-HENRY
|
||||
* @brief Single client WEB Server.
|
||||
* This class is now retired and replaced by the much better WEBServer class
|
||||
* which handles multiclients among other things.
|
||||
* @version 0.1
|
||||
* @date 31/03/2019
|
||||
*
|
||||
* @copyright MIT
|
||||
*
|
||||
*/
|
||||
#include "WEBServerManager_deprecated.h"
|
||||
|
||||
//#define DEBUG
|
||||
#define DEBUG_BODY
|
||||
//#define DEBUG_PARAMETER
|
||||
//#define DEBUG_CONTENT_LENGTH
|
||||
//#define DEBUG_RAW
|
||||
//#define DEBUG_FILEPATH
|
||||
|
||||
WEBServerManager_deprecated::WEBServerManager_deprecated(unsigned int port, SDCardManager *sdCardManager) : _wifiServer(port), _sdCardManager(sdCardManager), _httpRequestData({UNDEFINED, UNKNOWN, UNKNOWN_MIME, Dictionary<DictionaryHelper::StringEntity>(), Dictionary<DictionaryHelper::StringEntity>(), NULL,NULL}), _httpParserState(INIT), _clientState(WAITING_FOR_CLIENT), _port(port), _clientTimeout(0)
|
||||
{
|
||||
_wifiServer.begin();
|
||||
}
|
||||
|
||||
boolean WEBServerManager_deprecated::addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient* , void*), void *pData, HttpRequestMethod HRM)
|
||||
{
|
||||
return _apiDictionary.add(uri,new ApiRoutine({apiRoutine,pData, HRM}));
|
||||
}
|
||||
|
||||
void WEBServerManager_deprecated::clearApiRoutine()
|
||||
{
|
||||
_apiDictionary.clear();
|
||||
}
|
||||
|
||||
boolean WEBServerManager_deprecated::removeApiRoutine(const char *uri)
|
||||
{
|
||||
return _apiDictionary.remove(uri);
|
||||
}
|
||||
|
||||
boolean WEBServerManager_deprecated::runServer()
|
||||
{
|
||||
switch(_clientState)
|
||||
{
|
||||
case WAITING_FOR_CLIENT:
|
||||
_wifiClient.stopAll();
|
||||
|
||||
_wifiClient = _wifiServer.available();
|
||||
if(_wifiClient)
|
||||
{
|
||||
_clientState = NEW;
|
||||
#ifdef DEBUG
|
||||
Serial.println("Client connected !!!");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case NEW:
|
||||
_clientState = NOT_HANDLED;
|
||||
break;
|
||||
case NOT_HANDLED:
|
||||
clearHttpRequestData();
|
||||
parseQuery(&_wifiClient);
|
||||
#ifdef DEBUG
|
||||
Serial.println("Nothing more from client !!!");
|
||||
#endif
|
||||
_clientState = QUERY_PARSED;
|
||||
break;
|
||||
case QUERY_PARSED:
|
||||
#ifdef DEBUG
|
||||
Serial.println("Sending response !!!");
|
||||
#endif
|
||||
//We first check if it's an api call
|
||||
if(!sendPageToClientFromApiDictio(&_wifiClient))
|
||||
{
|
||||
sendPageToClientFromSdCard(&_wifiClient);
|
||||
}
|
||||
_clientState = RESPONSE_SENT;
|
||||
break;
|
||||
case RESPONSE_SENT:
|
||||
#ifdef DEBUG
|
||||
Serial.println("Client handled !!!");
|
||||
#endif
|
||||
_clientState = HANDLED;
|
||||
break;
|
||||
case HANDLED:
|
||||
_wifiClient.stopAll();
|
||||
_clientState = WAITING_FOR_CLIENT;
|
||||
#ifdef DEBUG
|
||||
Serial.println("Client discarded !!!");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean WEBServerManager_deprecated::parseQuery(WiFiClient *wifiClient)
|
||||
{
|
||||
char readChar(0), *parseBuffer(NULL), *parseKey(NULL), *parseValue(NULL), *parseParameter(NULL), *contentLength(NULL);
|
||||
boolean isKey(true), receivingDone(false);
|
||||
unsigned int activeTimeout = 10000;
|
||||
unsigned long dataBytesCounter = 0, dataBytes = 0;
|
||||
|
||||
/* Better way to read data
|
||||
char temp[2048];
|
||||
temp[wifiClient->read((uint8_t*)temp,2040)] = '\0';
|
||||
Serial.print(temp);
|
||||
*/
|
||||
_httpParserState = INIT;
|
||||
_clientTimeout = millis();
|
||||
boolean slashesOrAntiSlashesOnly(true);
|
||||
while((wifiClient->available() || ( millis() - _clientTimeout < activeTimeout)) && wifiClient->connected())
|
||||
{
|
||||
if(wifiClient->available())
|
||||
{
|
||||
readChar = (char)wifiClient->read();
|
||||
|
||||
#ifdef DEBUG_RAW
|
||||
Serial.print(readChar);
|
||||
#endif
|
||||
//INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR
|
||||
switch(_httpParserState)
|
||||
{
|
||||
case INIT:
|
||||
if(readChar >= 65 && readChar <= 90)
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_VERB_SECTION;
|
||||
}
|
||||
else
|
||||
_httpParserState = ERROR;
|
||||
break;
|
||||
case LINE_BREAK:
|
||||
if(readChar == '\n')
|
||||
{
|
||||
if(_httpRequestData.HRM == GET)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Serial.println("GET DONE");
|
||||
#endif
|
||||
receivingDone = true;
|
||||
}
|
||||
_httpParserState = BODY_SECTION;
|
||||
}
|
||||
else if(readChar != '\r')
|
||||
{
|
||||
if(parseParameter != NULL)
|
||||
{
|
||||
contentLength = strstr(parseParameter, "ent-Len");//Matches Content-Length short to save some RAM
|
||||
if(contentLength != NULL)
|
||||
{
|
||||
dataBytes = strtol(contentLength+11,NULL,10);
|
||||
#ifdef DEBUG_CONTENT_LENGTH
|
||||
Serial.print("Data length : ");Serial.println(dataBytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PARAMETER
|
||||
Serial.println(parseParameter);
|
||||
#endif
|
||||
free(parseParameter);parseParameter = NULL;
|
||||
}
|
||||
parseParameter = addChar(parseParameter, readChar);
|
||||
_httpParserState = PARAMETER_SECTION;
|
||||
}
|
||||
break;
|
||||
case HTTP_VERB_SECTION:
|
||||
if(readChar >= 65 && readChar <= 90)
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_VERB_SECTION;
|
||||
}
|
||||
else if (readChar == ' ')
|
||||
{
|
||||
//This is the end of the section
|
||||
_httpRequestData.HRM = getHttpVerbEnumValue(parseBuffer);
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
_httpParserState = HTTP_RESOURCE_SECTION;
|
||||
}
|
||||
else
|
||||
_httpParserState = ERROR;
|
||||
break;
|
||||
case HTTP_RESOURCE_SECTION:
|
||||
if(readChar == '?' )
|
||||
{
|
||||
free(_httpRequestData.httpResource);_httpRequestData.httpResource = NULL;
|
||||
_httpRequestData.httpResource = parseBuffer;parseBuffer = NULL;
|
||||
|
||||
_httpParserState = HTTP_RESOURCE_PARAM_SECTION;
|
||||
}
|
||||
else if(readChar == ' ')
|
||||
{
|
||||
free(_httpRequestData.httpResource);_httpRequestData.httpResource = NULL;
|
||||
if(slashesOrAntiSlashesOnly)
|
||||
{
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
_httpRequestData.httpResource = (char *) malloc(sizeof(char)*2);
|
||||
strcpy(_httpRequestData.httpResource,"/");
|
||||
}
|
||||
else
|
||||
_httpRequestData.httpResource = parseBuffer;parseBuffer = NULL;
|
||||
|
||||
_httpParserState = HTTP_VER_SECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(readChar != '/' && readChar != '\\') slashesOrAntiSlashesOnly = false;
|
||||
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_RESOURCE_SECTION;
|
||||
}
|
||||
break;
|
||||
case HTTP_RESOURCE_PARAM_SECTION: //index.web?var1=1&var2=2...
|
||||
if(readChar == ' ')
|
||||
{
|
||||
_httpRequestData.getParams.add(parseKey,new DictionaryHelper::StringEntity(parseValue));
|
||||
free(parseKey);free(parseValue);
|
||||
parseKey = NULL;parseValue = NULL;
|
||||
_httpParserState = HTTP_VER_SECTION;
|
||||
}
|
||||
else if( readChar == '=')
|
||||
isKey = false;
|
||||
else if(readChar == '&')
|
||||
{
|
||||
isKey = true;
|
||||
_httpRequestData.getParams.add(parseKey, new DictionaryHelper::StringEntity(parseValue));
|
||||
free(parseKey);free(parseValue);
|
||||
parseKey = NULL;parseValue = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isKey)
|
||||
parseKey = addChar(parseKey, readChar);
|
||||
else
|
||||
parseValue = addChar(parseValue, readChar);
|
||||
}
|
||||
break;
|
||||
case HTTP_VER_SECTION:
|
||||
if((readChar >= 48 && readChar <= 57) || readChar == '.')
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, readChar);
|
||||
_httpParserState = HTTP_VER_SECTION;
|
||||
}
|
||||
else if(readChar == '\n')
|
||||
{
|
||||
_httpRequestData.HV = getHttpVersionEnumValue(parseBuffer);
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
_httpParserState = LINE_BREAK;
|
||||
}
|
||||
break;
|
||||
case BODY_SECTION:
|
||||
//parseBuffer = addChar(parseBuffer, readChar);
|
||||
if(_httpRequestData.HRM != GET)
|
||||
{
|
||||
dataBytesCounter++;//Should be always true
|
||||
}
|
||||
#ifdef DEBUG_BODY
|
||||
Serial.print(readChar);
|
||||
#endif
|
||||
break;
|
||||
case PARAMETER_SECTION: //Here are all the http header params
|
||||
if(readChar == '\n')
|
||||
{
|
||||
_httpParserState = LINE_BREAK;
|
||||
}else
|
||||
parseParameter = addChar(parseParameter, readChar);
|
||||
break;
|
||||
case IGNORED:
|
||||
break;
|
||||
case ERROR:
|
||||
return false;
|
||||
break; //Not necessary
|
||||
default :
|
||||
break;
|
||||
}
|
||||
//Exit condition
|
||||
if(receivingDone) break;
|
||||
if(_httpRequestData.HRM == POST && dataBytes != 0 && dataBytes == dataBytesCounter) break;
|
||||
|
||||
_clientTimeout = millis();
|
||||
}
|
||||
//yield(); //Likely causing a crash
|
||||
ESP.wdtFeed();
|
||||
}
|
||||
|
||||
if(parseBuffer != NULL)
|
||||
{
|
||||
if(strlen(parseBuffer) > 0)
|
||||
{
|
||||
_httpRequestData.httpBody = parseBuffer;
|
||||
parseBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(parseParameter);parseParameter = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("HTTP VERB : ");
|
||||
Serial.println(_httpRequestData.HRM);
|
||||
Serial.print("HTTP RESOURCE : ");
|
||||
Serial.println(_httpRequestData.httpResource);
|
||||
Serial.print("HTTP VERSION : ");
|
||||
Serial.println(_httpRequestData.HV);
|
||||
Serial.print("BODY CONTENT : ");
|
||||
Serial.println(_httpRequestData.httpBody);
|
||||
Serial.println("GET PARAMS :");
|
||||
for(int i = 0; i < _httpRequestData.getParams.count(); i++)
|
||||
{
|
||||
Serial.print(_httpRequestData.getParams.getParameter(i));Serial.print(" : ");Serial.println(_httpRequestData.getParams.getAt(i)->getString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int WEBServerManager_deprecated::getPort() const
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
|
||||
boolean WEBServerManager_deprecated::sendPageToClientFromSdCard(WiFiClient *wifiClient)
|
||||
{
|
||||
if(_sdCardManager != NULL)
|
||||
{
|
||||
File pageToSend;
|
||||
char readChar(0), *filePath(NULL), *header(NULL), sendBuffer[2048];
|
||||
|
||||
//We check what kind of http verb it is
|
||||
switch(_httpRequestData.HRM)
|
||||
{
|
||||
case GET:
|
||||
filePath = getFilePathByHttpResource(_httpRequestData.httpResource);
|
||||
if(filePath == NULL)
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<p>Failed to malloc filePath</p>\r\n</html>"));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("FILE PATH : ");
|
||||
Serial.println(filePath);
|
||||
#endif
|
||||
|
||||
pageToSend = _sdCardManager->open(filePath);
|
||||
free(filePath);filePath = NULL;
|
||||
|
||||
if(!pageToSend)
|
||||
{
|
||||
char *response(NULL);
|
||||
response = (char *) malloc(sizeof(char) * (strlen("HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Page not found for : </h1>\r\n<h4></h4>\r\n</html>") + strlen(_httpRequestData.httpResource) + 1));
|
||||
if(response == NULL)
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Failed to malloc response</h1>\r\n</html>"));
|
||||
return false;
|
||||
}
|
||||
sprintf(response, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Page not found for : </h1>\r\n<h4>%s</h4>\r\n</html>", _httpRequestData.httpResource);
|
||||
wifiClient->print(response);
|
||||
free(response);response = NULL;
|
||||
pageToSend.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("FILE SIZE : ");
|
||||
Serial.println(pageToSend.size());
|
||||
Serial.print("FILE NAME : ");
|
||||
Serial.println(pageToSend.name());
|
||||
Serial.print("FILE EXTENSION : ");
|
||||
//Serial.println(getFileExtension(pageToSend.name()));
|
||||
#endif
|
||||
|
||||
header = getHTTPHeader(getMIMETypeByExtension(getFileExtension(/*pageToSend.name()*/ "dummy")), pageToSend.size());
|
||||
if(header == NULL)
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Failed to malloc header</h1>\r\n</html>"));
|
||||
pageToSend.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
wifiClient->print(header);
|
||||
free(header);header = NULL;
|
||||
|
||||
while(pageToSend.available())
|
||||
{
|
||||
//if(wifiClient->write(sendBuffer, pageToSend.read(sendBuffer,2048)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
pageToSend.close();
|
||||
break;
|
||||
default: //If not supported
|
||||
wifiClient->print(F("HTTP/1.1 405 Method Not Allowed\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Method Not Allowed</h1>\r\n</html>"));
|
||||
break;
|
||||
}
|
||||
}else
|
||||
{
|
||||
wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>SDCardManager is NULL<br \\>Check code</h1>\r\n</html>"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean WEBServerManager_deprecated::sendPageToClientFromApiDictio(WiFiClient *wifiClient)
|
||||
{
|
||||
if(_apiDictionary.count() == 0 || _httpRequestData.httpResource == NULL)
|
||||
return false;
|
||||
|
||||
ApiRoutine *ref = _apiDictionary(_httpRequestData.httpResource);
|
||||
|
||||
if(ref == NULL)
|
||||
return false;
|
||||
|
||||
if(ref->HRM == UNDEFINED)
|
||||
{
|
||||
return (*(ref->apiRoutine))(_httpRequestData, wifiClient, ref->pData);
|
||||
}else if(ref->HRM == _httpRequestData.HRM)
|
||||
{
|
||||
return (*(ref->apiRoutine))(_httpRequestData, wifiClient, ref->pData);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
WEBServerManager_deprecated::HttpMIMEType WEBServerManager_deprecated::getMIMETypeByExtension(const char *extension)
|
||||
{
|
||||
//TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT
|
||||
if(strcmp(extension,"web") == 0) return TEXT_HTML;
|
||||
else if(strcmp(extension,"htm") == 0) return TEXT_HTML;
|
||||
else if(strcmp(extension,"css") == 0) return TEXT_CSS;
|
||||
else if(strcmp(extension,"js") == 0) return TEXT_JAVASCRIPT;
|
||||
else if(strcmp(extension,"png") == 0) return IMAGE_PNG;
|
||||
else if(strcmp(extension,"jpg") == 0) return IMAGE_JPEG;
|
||||
else if(strcmp(extension, "mp3") == 0) return AUDIO_MPEG;
|
||||
else return UNKNOWN_MIME;
|
||||
}
|
||||
|
||||
char *WEBServerManager_deprecated::getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size)
|
||||
{
|
||||
char *header = (char *) malloc(sizeof(char) + strlen("HTTP/1.1 200 OK\r\nContent-Type: \r\nContent-Length: \r\n\r\n") + 74/*Longest MIME-TYPE*/ + 10 /*Max unsigned long footprint*/ + 1);
|
||||
|
||||
switch(httpMIMEType)
|
||||
{
|
||||
case TEXT_HTML:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/html",size);
|
||||
break;
|
||||
case TEXT_CSS:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/css",size);
|
||||
break;
|
||||
case TEXT_JAVASCRIPT:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/javascript",size);
|
||||
break;
|
||||
case IMAGE_PNG:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","image/png",size);
|
||||
break;
|
||||
case IMAGE_JPEG:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","image/jpeg",size);
|
||||
break;
|
||||
case TEXT_PLAIN:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/plain",size);
|
||||
break;
|
||||
case AUDIO_MPEG:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","audio/mpeg",size);
|
||||
break;
|
||||
case APPLICATION_OCTET_STREAM:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","application/octet-stream",size);
|
||||
break;
|
||||
default:
|
||||
sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","application/octet-stream",size);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
char *WEBServerManager_deprecated::getFileExtension(char *name)
|
||||
{
|
||||
if(name == NULL)return "";
|
||||
|
||||
char *ptr(name);
|
||||
int index(0);
|
||||
while(ptr[index] != '\0')
|
||||
{
|
||||
if(ptr[++index] == '.')
|
||||
{
|
||||
return (name + index +1);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
char *WEBServerManager_deprecated::getFilePathByHttpResource(char *res)
|
||||
{
|
||||
uint16_t buffSize = strlen(WWW_DIR) + (strcmp(res, "/") == 0 ? 10:strlen(res)) + 1;//10 for /index.htm +1 for \0
|
||||
char *filePath = (char*) malloc( sizeof(char) * buffSize);
|
||||
|
||||
if(filePath == NULL)
|
||||
return NULL;
|
||||
|
||||
strcpy(filePath, WWW_DIR);
|
||||
strcat(filePath, strcmp(res, "/") == 0 ? "/index.htm":res);
|
||||
//sprintf(filePath,"%s%s",WWW_DIR, strcmp(res, "/") == 0 ? "/index.htm":res);
|
||||
|
||||
#ifdef DEBUG_FILEPATH
|
||||
Serial.println(res);
|
||||
Serial.print("Reserved space : ");Serial.println(buffSize);
|
||||
Serial.print("Actual size : ");Serial.println(strlen(filePath));
|
||||
Serial.println(filePath);
|
||||
#endif
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
WEBServerManager_deprecated::HttpRequestMethod WEBServerManager_deprecated::getHttpVerbEnumValue(const char *parseBuffer)
|
||||
{
|
||||
//UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
|
||||
if(strcmp(parseBuffer,"GET") == 0){return GET;}
|
||||
else if(strcmp(parseBuffer,"POST") == 0){return POST;}
|
||||
else if(strcmp(parseBuffer,"HEAD") == 0){return HEAD;}
|
||||
else if(strcmp(parseBuffer,"PUT") == 0){return PUT;}
|
||||
else if(strcmp(parseBuffer,"DELETE") == 0){return DELETE;}
|
||||
else if(strcmp(parseBuffer,"CONNECT") == 0){return CONNECT;}
|
||||
else if(strcmp(parseBuffer,"TRACE") == 0){return TRACE;}
|
||||
else if(strcmp(parseBuffer,"PATCH") == 0){return PATCH;}
|
||||
else if(strcmp(parseBuffer,"OPTIONS") == 0){return OPTIONS;}
|
||||
else
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
WEBServerManager_deprecated::HttpVersion WEBServerManager_deprecated::getHttpVersionEnumValue(const char *parseBuffer)
|
||||
{
|
||||
//HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0
|
||||
if(strcmp(parseBuffer,"1.1") == 0){return HTTP_1_1;}
|
||||
else if(strcmp(parseBuffer,"2.0") == 0){return HTTP_2_0;}
|
||||
else if(strcmp(parseBuffer,"1.0") == 0){return HTTP_1_0;}
|
||||
else if(strcmp(parseBuffer,"0.9") == 0){return HTTP_0_9;}
|
||||
else
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
void WEBServerManager_deprecated::clearHttpRequestData()
|
||||
{
|
||||
_httpRequestData.HRM = UNDEFINED;
|
||||
_httpRequestData.HV = UNKNOWN;
|
||||
_httpRequestData.HMT = UNKNOWN_MIME;
|
||||
free(_httpRequestData.httpResource);free(_httpRequestData.httpBody);
|
||||
_httpRequestData.httpResource = NULL;_httpRequestData.httpBody = NULL;
|
||||
_httpRequestData.getParams.dispose();
|
||||
_httpRequestData.postParams.dispose();
|
||||
}
|
81
src/app/WEBServerManager_deprecated.h
Normal file
81
src/app/WEBServerManager_deprecated.h
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @file WEBServerManager.h
|
||||
* @author Anatole SCHRAMM-HENRY
|
||||
* @brief Single client WEB Server.
|
||||
* This class is now retired and replaced by the much better WEBServer class
|
||||
* which handles multiclients among other things.
|
||||
* @version 0.1
|
||||
* @date 31/03/2019
|
||||
*
|
||||
* @copyright MIT
|
||||
*
|
||||
*/
|
||||
#ifndef WEBSERVERMANAGERDEPRECATED_H
|
||||
#define WEBSERVERMANAGERDEPRECATED_H
|
||||
|
||||
#include <WiFiServer.h>
|
||||
#include <WiFiClient.h>
|
||||
#include "SDCardManager.h"
|
||||
#include "definition.h"
|
||||
#include "Dictionary.h"
|
||||
|
||||
struct HttpRequestData;
|
||||
|
||||
class WEBServerManager_deprecated
|
||||
{
|
||||
public:
|
||||
enum ClientStatus {NOT_HANDLED, HANDLED, NEW, WAITING_FOR_CLIENT, QUERY_PARSED, RESPONSE_SENT};
|
||||
enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};
|
||||
enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0};
|
||||
enum HttpParserStatus {INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_RESOURCE_PARAM_SECTION, HTTP_VER_SECTION, PARAMETER_SECTION, BODY_SECTION, IGNORED, ERROR};
|
||||
enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED, IMAGE_PNG, IMAGE_JPEG, AUDIO_MPEG, APPLICATION_OCTET_STREAM};
|
||||
struct HttpRequestData{
|
||||
HttpRequestMethod HRM;
|
||||
HttpVersion HV;
|
||||
HttpMIMEType HMT;
|
||||
Dictionary<DictionaryHelper::StringEntity> getParams;
|
||||
Dictionary<DictionaryHelper::StringEntity> postParams;
|
||||
char *httpResource;
|
||||
char *httpBody;
|
||||
};
|
||||
|
||||
WEBServerManager_deprecated(unsigned int port = 80, SDCardManager *sdCardManager = NULL);
|
||||
|
||||
boolean runServer();
|
||||
unsigned int getPort() const;
|
||||
boolean addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*), void *pData, HttpRequestMethod HRM = UNDEFINED);
|
||||
void clearApiRoutine();
|
||||
boolean removeApiRoutine(const char *uri);
|
||||
protected:
|
||||
private:
|
||||
struct ApiRoutine
|
||||
{
|
||||
boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*);
|
||||
void *pData;
|
||||
HttpRequestMethod HRM;
|
||||
};
|
||||
|
||||
boolean parseQuery(WiFiClient *wifiClient);
|
||||
boolean sendPageToClientFromSdCard(WiFiClient *wifiClient);
|
||||
boolean sendPageToClientFromApiDictio(WiFiClient *wifiClient);
|
||||
HttpRequestMethod getHttpVerbEnumValue(const char *parseBuffer);
|
||||
HttpVersion getHttpVersionEnumValue(const char *parseBuffer);
|
||||
char *getFilePathByHttpResource(char *res);
|
||||
char *getFileExtension(char *name);
|
||||
HttpMIMEType getMIMETypeByExtension(const char *extension);
|
||||
char *getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size);
|
||||
void clearHttpRequestData();
|
||||
|
||||
WiFiServer _wifiServer;
|
||||
WiFiClient _wifiClient;//One client only, may be replaced with a fifo in the future
|
||||
SDCardManager *_sdCardManager;
|
||||
HttpRequestData _httpRequestData;
|
||||
Dictionary<ApiRoutine> _apiDictionary;
|
||||
|
||||
ClientStatus _clientState;
|
||||
HttpParserStatus _httpParserState;
|
||||
unsigned long _clientTimeout;
|
||||
unsigned int _port;
|
||||
};
|
||||
|
||||
#endif //WEBSERVERMANAGERDEPRECATED_H
|
@ -74,34 +74,35 @@ void setup()
|
||||
sab.getRtcManager().setDateTime(sab.getRTC_DS3231().now());
|
||||
}
|
||||
|
||||
sab.getWebServer().addApiRoutine("/sab/web/apitester", &(apiTesterApi), NULL);
|
||||
sab.getWebServer().addApiRoutine("/sab/view/next", &(nextViewApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/view/reloadcfg", &(reloadViewApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/view", &(viewByUIDApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/rtc/get/datetime", &(rtcGetTimeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/rtc/set/datetime", &(rtcSetTimeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/sdcard/size", &(sdCardSizeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/web/apitester", &(apiTesterApi), NULL);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/view/next", &(nextViewApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/view/reloadcfg", &(reloadViewApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/view", &(viewByUIDApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/rtc/get/datetime", &(rtcGetTimeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/rtc/set/datetime", &(rtcSetTimeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/sdcard/size", &(sdCardSizeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sdCardApiPacket.pSab = &sab;sdCardApiPacket.pView = &v1p;
|
||||
sab.getWebServer().addApiRoutine("/sab/sdcard/action", &(sdCardActionApi), &sdCardApiPacket, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/sdcard/action", &(sdCardActionApi), &sdCardApiPacket, WEBServer<WEBClient>::GET);
|
||||
|
||||
sab.getWebServer().addApiRoutine("/esp/restart", &(espRestartApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/esp/reset", &(espResetApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/wifi/stainfo", &(staWifiInfoApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/wifi/scanner", &(apScannerApi), NULL, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/systeminfo", &(systemInfoApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/power/info", &(powerInfoApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/io/get/level", &(ioGetLevelApi), vio.ioState, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/io/set/level", &(ioSetLevelApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/io/get/mode", &(ioGetModeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/io/set/mode", &(ioSetModeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/sw/version", &(swVersionApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServer().addApiRoutine("/sab/ota/update/upload", &(otaUpdateUploadApi), NULL, WEBServer<WEBClient>::POST);
|
||||
sab.getWebServer().addApiRoutine("/sab/ota/update/device", &(otaUpdateRemoteApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/esp/restart", &(espRestartApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/esp/reset", &(espResetApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/wifi/stainfo", &(staWifiInfoApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/wifi/scanner", &(apScannerApi), NULL, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/systeminfo", &(systemInfoApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/power/info", &(powerInfoApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/io/get/level", &(ioGetLevelApi), vio.ioState, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/io/set/level", &(ioSetLevelApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/io/get/mode", &(ioGetModeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/io/set/mode", &(ioSetModeApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/sw/version", &(swVersionApi), &sab, WEBServer<WEBClient>::GET);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/ota/update/upload", &(otaUpdateUploadApi), NULL, WEBServer<WEBClient>::POST);
|
||||
sab.getWebServerManager().getWEBServer().addApiRoutine("/sab/ota/update/device", &(otaUpdateRemoteApi), &sab, WEBServer<WEBClient>::GET);
|
||||
|
||||
sab.getIOManager().setISROnIOChange(&(ioISR), GPIO_3_RX);
|
||||
|
||||
sab.getTaskSchedulerManager().addTask((uint16_t)0, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setMillis(5000), &(task_blink), &sab);
|
||||
sab.getTaskSchedulerManager().addTask(1, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(10), &(task_sys_info), &v1p);
|
||||
sab.getTaskSchedulerManager().addTask(2, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(5), &(testTask), &sab);
|
||||
//dataLogger.client.keepAlive(true);
|
||||
//sab.getTaskSchedulerManager().addTask(2, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(1)->setTriggerRightAway(false), &(task_post_data_logger), &dataLogger);
|
||||
|
||||
|
@ -27,7 +27,7 @@ boolean task_sys_info(void *pData)
|
||||
p->sab->getConnectivityManager().RSSI(),
|
||||
p->sab->getConnectivityManager().softAPIP().toString().c_str(),
|
||||
p->sab->getConnectivityManager().macAddress().c_str(),
|
||||
p->sab->getWebServer().getConnectedClientsCount(),
|
||||
p->sab->getWebServerManager().getWEBServer().getConnectedClientsCount(),
|
||||
freeRAM,
|
||||
HEAPfrag,
|
||||
biggestContigMemBlock);
|
||||
@ -108,3 +108,10 @@ boolean task_post_data_logger(void * pData)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean testTask(void *pData)
|
||||
{
|
||||
SAB *pSab = (SAB *)pData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
boolean task_blink(void *);
|
||||
boolean task_sys_info(void *);
|
||||
boolean task_esp_reset_restart(void *);
|
||||
boolean testTask(void *);
|
||||
|
||||
typedef struct dataLogger
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user