Compare commits
16 Commits
263d47d8d0
...
e3e01da80b
Author | SHA1 | Date | |
---|---|---|---|
|
e3e01da80b | ||
|
2eb604d24d | ||
|
04a5eb9643 | ||
|
9988b03306 | ||
|
beefe8e355 | ||
|
967e5ccdbe | ||
|
09aee48f27 | ||
|
0dcb532007 | ||
|
63b6cf626f | ||
|
d0d5df2b98 | ||
|
86452fb1b8 | ||
|
f547c8fc07 | ||
|
ab493ef6d8 | ||
|
636acb1be1 | ||
|
ff16dbcfce | ||
|
636c3093de |
8
.vscode/tasks.json
vendored
8
.vscode/tasks.json
vendored
@ -6,9 +6,9 @@
|
||||
{
|
||||
"label": "Build",
|
||||
"type": "shell",
|
||||
"command": "arduino-cli compile -v --warnings all -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600 -e \"`pwd`/src/app\"",
|
||||
"command": "arduino-cli compile -v --warnings all -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2n,dbg=Disabled,lvl=None____,wipe=none,baud=921600 -e \"`pwd`/src/app\"",
|
||||
"windows":{
|
||||
"command": "arduino-cli compile -v --warnings all -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600 -e ((pwd).path + '/src/app')"
|
||||
"command": "arduino-cli compile -v --warnings all -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2n,dbg=Disabled,lvl=None____,wipe=none,baud=921600 -e ((pwd).path + '/src/app')"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
@ -23,9 +23,9 @@
|
||||
{
|
||||
"label": "Flash",
|
||||
"type": "shell",
|
||||
"command": "arduino-cli upload -v -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600 \"`pwd`/src/app\" -p ${input:com_port}",
|
||||
"command": "arduino-cli upload -v -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2n,dbg=Disabled,lvl=None____,wipe=none,baud=921600 \"`pwd`/src/app\" -p ${input:com_port}",
|
||||
"windows":{
|
||||
"command": "arduino-cli upload -v -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600 ((pwd).path + '/src/app') -p ${input:com_port}"
|
||||
"command": "arduino-cli upload -v -b esp8266:esp8266:nodemcuv2:xtal=80,vt=flash,exception=disabled,stacksmash=enabled,ssl=basic,mmu=3232,non32xfer=fast,eesz=4M,led=2,ip=lm2n,dbg=Disabled,lvl=None____,wipe=none,baud=921600 ((pwd).path + '/src/app') -p ${input:com_port}"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
|
11
sdCard_content/CONFIG/OTA.CFG
Normal file
11
sdCard_content/CONFIG/OTA.CFG
Normal file
@ -0,0 +1,11 @@
|
||||
#This config file stores the configuration needed for OTA updates
|
||||
#If this file is not present or if there is an error at parsing time
|
||||
#the OTA update feature will be disabled.
|
||||
#If the OTA service does not require any auth key then set this field empty ie ''
|
||||
#The blank new line at then end of the file is mendatory. Without it, the last parameter won't be read.
|
||||
|
||||
ENABLED : 'true'
|
||||
OTA_SERVER_ADDRESS : 'OTA server IP address'
|
||||
OTA_SERVER_PORT : 80
|
||||
OTA_SERVICE_PATH : 'OTA service url path on the server'
|
||||
OTA_SERVICE_AUTH_KEY : 'OTA service auth key'
|
@ -8,9 +8,11 @@
|
||||
WEB_ENABLED : 'true'
|
||||
WEB_PORT : 80
|
||||
WEB_MAX_CLIENT : 0
|
||||
WEB_WWW_DIR : '/WWW'
|
||||
FTP_ENABLED : 'true'
|
||||
FTP_LOGIN : 'ESP8266'
|
||||
FTP_PASSWORD : '12345678'
|
||||
FTP_ROOT_DIR : '/FTP'
|
||||
FTP_PORT : 21
|
||||
FTP_DATA_PORT : 1024
|
||||
FTP_MAX_CLIENT : 0
|
||||
|
@ -6,6 +6,7 @@ const uint16_t screenHeight,
|
||||
const uint16_t I2C_IOExpanderAddress,
|
||||
const uint16_t _I2C_RTCFlashAddress,
|
||||
const Pin SPI_SDCard_cs,
|
||||
const Pin onBoard_LED,
|
||||
const Pin I2C_sda,
|
||||
const Pin I2C_scl,
|
||||
const Pin SPI_mosi,
|
||||
@ -19,6 +20,7 @@ _SPI_mosi(SPI_mosi == DEFAULT_PIN ? GPIO_13_MOSI : SPI_mosi),
|
||||
_SPI_miso(SPI_miso == DEFAULT_PIN ? GPIO_12_MISO : SPI_miso),
|
||||
_SPI_clk(SPI_clk == DEFAULT_PIN ? GPIO_14_CLK : SPI_clk),
|
||||
_SPI_SDCard_cs(SPI_SDCard_cs == DEFAULT_PIN ? GPIO_2 : SPI_SDCard_cs),
|
||||
_onBoard_LED(onBoard_LED == DEFAULT_PIN ? GPIO_2 : onBoard_LED),
|
||||
_I2C_screenAddress(I2C_screenAddress),
|
||||
_I2C_IOExpanderAddress(I2C_IOExpanderAddress),
|
||||
_I2C_RTCFlashAddress(_I2C_RTCFlashAddress),
|
||||
@ -59,6 +61,11 @@ Pin BoardConfig::getSPI_SDCard_cs() const
|
||||
return _SPI_SDCard_cs;
|
||||
}
|
||||
|
||||
Pin BoardConfig::getOnBoard_LED() const
|
||||
{
|
||||
return _onBoard_LED;
|
||||
}
|
||||
|
||||
uint16_t BoardConfig::getI2C_screenAddress() const
|
||||
{
|
||||
return _I2C_screenAddress;
|
||||
@ -69,12 +76,11 @@ uint16_t BoardConfig::getI2C_IOExpanderAddress() const
|
||||
return _I2C_IOExpanderAddress;
|
||||
}
|
||||
|
||||
uint16_t BoardConfig::getRTCFlashAddress() const
|
||||
uint16_t BoardConfig::getI2C_RTCFlashAddress() const
|
||||
{
|
||||
return _I2C_RTCFlashAddress;
|
||||
}
|
||||
|
||||
|
||||
uint32_t BoardConfig::getSPISpeed() const
|
||||
{
|
||||
return _SPISpeed;
|
||||
|
@ -17,6 +17,7 @@ class BoardConfig
|
||||
const uint16_t I2C_IOExpanderAddress = 0x27,
|
||||
const uint16_t _I2C_RTCFlashAddress = 0x0,
|
||||
const Pin SPI_SDCard_cs = GPIO_2,
|
||||
const Pin onBoard_LED = GPIO_2,
|
||||
const Pin I2C_sda = GPIO_4_SDA,
|
||||
const Pin I2C_scl = GPIO_5_SCL,
|
||||
const Pin SPI_mosi = GPIO_13_MOSI,
|
||||
@ -32,10 +33,11 @@ class BoardConfig
|
||||
Pin getSPI_miso() const;
|
||||
Pin getSPI_clk() const;
|
||||
Pin getSPI_SDCard_cs() const;
|
||||
Pin getOnBoard_LED() const;
|
||||
|
||||
uint16_t getI2C_screenAddress() const;
|
||||
uint16_t getI2C_IOExpanderAddress() const;
|
||||
uint16_t getRTCFlashAddress() const;
|
||||
uint16_t getI2C_RTCFlashAddress() const;
|
||||
|
||||
uint32_t getSPISpeed() const;
|
||||
|
||||
@ -51,6 +53,7 @@ class BoardConfig
|
||||
const Pin _SPI_miso;
|
||||
const Pin _SPI_clk;
|
||||
const Pin _SPI_SDCard_cs;
|
||||
const Pin _onBoard_LED;
|
||||
|
||||
//2) I2C Addresses
|
||||
const uint16_t _I2C_screenAddress;
|
||||
|
@ -72,7 +72,7 @@ void *CFGFileParser::parseFile()
|
||||
}
|
||||
}
|
||||
else if(readChar == ' ') _state = PARAM_SECTION;
|
||||
else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || readChar == '_' || readChar == '-' || (readChar >= 48 && readChar <= 57))
|
||||
else if((readChar >= 65 && readChar <= 90) /*A to Z*/ || (readChar >= 97 && readChar <= 122) /*a to z*/ || (readChar >= 48 && readChar <= 57) /*0 to 9*/ || readChar == '_' || readChar == '-')
|
||||
{
|
||||
if(_type == PARAMETER)
|
||||
{
|
||||
@ -100,7 +100,9 @@ void *CFGFileParser::parseFile()
|
||||
else
|
||||
_quotedValue = true;
|
||||
}
|
||||
else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || readChar == ' ' || readChar == '_' || readChar == '-' || (readChar >= 48 && readChar <= 57))
|
||||
else if((readChar >= 65 && readChar <= 90) /*A to Z*/ || (readChar >= 97 && readChar <= 122) /*a to z*/ || (readChar >= 48 && readChar <= 57) /*0 to 9*/ ||
|
||||
readChar == ' ' || readChar == '_' || readChar == '-' || readChar == '.' || readChar == '/'
|
||||
)
|
||||
{
|
||||
//printf("%c",readChar);
|
||||
if(_type == PARAMETER)
|
||||
@ -123,7 +125,7 @@ void *CFGFileParser::parseFile()
|
||||
_type = VALUE;
|
||||
if(readChar == '\'')_state = OPENING_QUOTE;
|
||||
else if(readChar == ' ') _state = PARAM_SECTION;
|
||||
else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || (readChar >= 48 && readChar <= 57) || readChar == '-' || readChar == '_')
|
||||
else if((readChar >= 65 && readChar <= 90) /*A to Z*/ || (readChar >= 97 && readChar <= 122) /*a to z*/ || (readChar >= 48 && readChar <= 57) /*0 to 9*/ || readChar == '_' || readChar == '-')
|
||||
{
|
||||
_state = PARAM_SECTION;
|
||||
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
{
|
||||
if(_value == NULL)
|
||||
return false;
|
||||
return strcmp(_value,"true") == 0 || strcmp(_value,"TRUE") == 0 ? true : false;
|
||||
return strcasecmp(_value,"true") == 0 ? true : false;
|
||||
}
|
||||
const char *getParameter() const{return _parameter == NULL ? "" : _parameter;}
|
||||
bool isQuotedParameter()const{return _quotedParameter;}
|
||||
|
@ -10,7 +10,6 @@
|
||||
HttpClient::HttpClient(const char *address, uint16_t port, uint32_t timeout) : WiFiClient(), _pAddress(address), _port(port)
|
||||
{
|
||||
setTimeout(timeout);
|
||||
connectByHostOrIp();
|
||||
}
|
||||
|
||||
HttpClient::HttpClient(const char *address, const char *resource, uint16_t port, uint32_t timeout) : HttpClient(address, port, timeout)
|
||||
@ -44,7 +43,10 @@ HttpClient::HttpClient(const HttpClient &object) : WiFiClient()
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
if(_resource != NULL)free(_resource);
|
||||
if(connected())
|
||||
stop();
|
||||
if(_resource != NULL)
|
||||
free(_resource);
|
||||
}
|
||||
|
||||
boolean HttpClient::connectByHostOrIp()
|
||||
@ -53,6 +55,17 @@ boolean HttpClient::connectByHostOrIp()
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("About to connect\n");
|
||||
#endif
|
||||
|
||||
//If we constructed the HttpClient with a NULL server address, we don't go further.
|
||||
if(!_pAddress)
|
||||
{
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("IP Address is NULL !\n");
|
||||
#endif
|
||||
_connectionStatus = FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ipAddress.fromString(_pAddress))
|
||||
{
|
||||
_isIp = true;
|
||||
@ -93,12 +106,15 @@ int HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<DictionaryHel
|
||||
//We reset this two flags
|
||||
_httpCode = HTTP_CODE::UNDEFINED_CODE;
|
||||
_httpCodeParsed = false;
|
||||
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
if(_keepAlive)
|
||||
Serial.printf("Link status : %d\n", status());
|
||||
#endif
|
||||
|
||||
//If we did not want to keep the connection alive and it is still open, then we first close it.
|
||||
if(!_keepAlive && connected())stop();
|
||||
|
||||
if(!connected() || _connectionStatus == FAILED)
|
||||
{
|
||||
if(_retries == _maxRetries) return -__LINE__;
|
||||
@ -111,9 +127,9 @@ int HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<DictionaryHel
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
if(_keepAlive)
|
||||
Serial.printf("Link broken, we try to reconnect : addr : %s port %u\nretries : %u\n", _pAddress, _port, _retries);
|
||||
Serial.printf("Link broken, we try to reconnect : addr : %s port %u\nretries : %u\n", _pAddress ? _pAddress : "NULL", _port, _retries);
|
||||
else
|
||||
Serial.printf("We start a new connection : %s port %u\nretries : %u\n", _pAddress, _port, _retries);
|
||||
Serial.printf("We start a new connection : %s port %u\nretries : %u\n", _pAddress ? _pAddress : "NULL", _port, _retries);
|
||||
#endif
|
||||
|
||||
if(!connectByHostOrIp())
|
||||
@ -131,7 +147,7 @@ int HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<DictionaryHel
|
||||
if(connected())
|
||||
{
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Server is listening\n", status());
|
||||
Serial.printf("Server is listening\n");
|
||||
#endif
|
||||
|
||||
switch(method)
|
||||
@ -142,6 +158,7 @@ int HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<DictionaryHel
|
||||
//Here we send the parameters
|
||||
sendUriWithGetParams(getData);
|
||||
sendHeader(HttpMIMEType::UNKNOWN_MIME, 0, headerData);
|
||||
flush(); //We force the send of the request to prevent any timeout on reception !
|
||||
break;
|
||||
case HttpRequestMethod::POST:
|
||||
//It is necessary to compute the content length
|
||||
@ -150,17 +167,18 @@ int HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<DictionaryHel
|
||||
sendUriWithGetParams(getData);
|
||||
sendHeader(HttpMIMEType::APPLICATION_X_WWW_FORM_URLENCODED, computeBodyLength(postData), headerData);
|
||||
sendPostData(postData);
|
||||
flush(); //We force the send of the request to prevent any timeout on reception !
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Http verb unspecified\n", status());
|
||||
Serial.printf("Http verb unspecified\n");
|
||||
#endif
|
||||
if(!_keepAlive)stop();
|
||||
return -__LINE__;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -274,7 +292,7 @@ HttpClient::HTTP_CODE HttpClient::isReplyAvailable(uint16_t timeout)
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
safeSize = available() > 99 ? 99 : available();
|
||||
buffer[peekBytes((uint8_t*)buffer,safeSize)] = '\0';
|
||||
Serial.printf("Body chunk is : %s\n",buffer);
|
||||
Serial.printf("Body chunk is : %s\n", buffer);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -285,7 +303,7 @@ HttpClient::HTTP_CODE HttpClient::isReplyAvailable(uint16_t timeout)
|
||||
}
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.println("\nAfter timeout or all data is received");
|
||||
Serial.printf("\nAfter timeout or all data is received, HTTP_CODE is : %d\n", _httpCode);
|
||||
#endif
|
||||
|
||||
return _httpCode;
|
||||
@ -408,5 +426,20 @@ uint64_t HttpClient::computeBodyLength(Dictionary<DictionaryHelper::StringEntity
|
||||
|
||||
void HttpClient::setMaxRetries(int16_t retries)
|
||||
{
|
||||
_maxRetries = retries;
|
||||
_maxRetries = retries < 0 ? -1 : retries;
|
||||
}
|
||||
|
||||
int16_t HttpClient::getMaxRetries(void) const
|
||||
{
|
||||
return _maxRetries;
|
||||
}
|
||||
|
||||
uint16_t HttpClient::retriesCount(void) const
|
||||
{
|
||||
return _retries;
|
||||
}
|
||||
|
||||
void HttpClient::resetRetriesCount(void)
|
||||
{
|
||||
_retries = 0;
|
||||
}
|
||||
|
@ -37,7 +37,10 @@ class HttpClient : public WiFiClient, public HttpConstants
|
||||
Dictionary<DictionaryHelper::StringEntity> *headerData = NULL);
|
||||
void keepAlive(boolean enabled);
|
||||
void setMaxRetries(int16_t retries);
|
||||
//100 ms is the default timeout
|
||||
int16_t getMaxRetries(void) const;
|
||||
uint16_t retriesCount(void) const;
|
||||
void resetRetriesCount(void);
|
||||
//10s is the default timeout
|
||||
HTTP_CODE isReplyAvailable(uint16_t timeout = 10000);
|
||||
|
||||
uint16_t readHttpBody(uint8_t *buffer, uint32_t size);
|
||||
|
114
src/app/OTAManager.cpp
Normal file
114
src/app/OTAManager.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "OTAManager.h"
|
||||
#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)
|
||||
{ }
|
||||
|
||||
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
|
||||
CFGDictionary<CFGParameterValue> *otaCfg = _sdCardManager->getCFGFile(OTA_CFG_FILE);
|
||||
boolean toReturn(true);
|
||||
//If we did not find the file
|
||||
if(!otaCfg)
|
||||
{
|
||||
DEBUG_OTA_MANAGER("otaCfg is NULL !");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((*otaCfg)("ENABLED") != nullptr)
|
||||
{
|
||||
if((*otaCfg)("ENABLED")->booleanValue())
|
||||
{
|
||||
DEBUG_OTA_MANAGER("ENABLED : %s", (*otaCfg)("ENABLED")->stringValue());
|
||||
if((*otaCfg)("OTA_SERVER_ADDRESS") != nullptr) //This is the only required parameter
|
||||
{
|
||||
_isServiceEnabled = true;
|
||||
_otaUpdater.setLedPin(_boardConfig->getOnBoard_LED(), LOW);
|
||||
_otaUpdater.onStart(std::bind(&OTAManager::updateStartedCb, this));
|
||||
_otaUpdater.onError(std::bind(&OTAManager::updateErrorCb, this, std::placeholders::_1));
|
||||
_otaUpdater.onProgress(std::bind(&OTAManager::updateProgressdCb, this, std::placeholders::_1, std::placeholders::_2));
|
||||
_otaUpdater.onEnd(std::bind(&OTAManager::updateFinishedCb, this));
|
||||
|
||||
|
||||
_otaUpdater.setServerAddress((*otaCfg)("OTA_SERVER_ADDRESS")->stringValue());
|
||||
|
||||
if((*otaCfg)("OTA_SERVER_PORT") != nullptr)
|
||||
{
|
||||
DEBUG_OTA_MANAGER("OTA_SERVER_PORT : %s", (*otaCfg)("OTA_SERVER_PORT")->stringValue());
|
||||
_otaUpdater.setPort((*otaCfg)("OTA_SERVER_PORT")->uintValue());
|
||||
}
|
||||
|
||||
if((*otaCfg)("OTA_SERVICE_PATH") != nullptr)
|
||||
{
|
||||
DEBUG_OTA_MANAGER("OTA_SERVICE_PATH : %s", (*otaCfg)("OTA_SERVICE_PATH")->stringValue());
|
||||
_otaUpdater.setPath((*otaCfg)("OTA_SERVICE_PATH")->stringValue());
|
||||
}
|
||||
|
||||
if((*otaCfg)("OTA_SERVICE_AUTH_KEY") != nullptr)
|
||||
{
|
||||
DEBUG_OTA_MANAGER("OTA_SERVICE_AUTH_KEY : %s", (*otaCfg)("OTA_SERVICE_AUTH_KEY")->stringValue());
|
||||
_otaUpdater.setOtaAuthKey((*otaCfg)("OTA_SERVICE_AUTH_KEY")->stringValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_OTA_MANAGER("OTA_SERVER_ADDRESS is NULL !");
|
||||
toReturn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_OTA_MANAGER("ENABLED is NULL !");
|
||||
toReturn = false;
|
||||
}
|
||||
|
||||
delete otaCfg;
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
boolean OTAManager::isEnabled(void) const
|
||||
{
|
||||
return _isServiceEnabled;
|
||||
}
|
||||
|
||||
OTAUpdater& OTAManager::getOTAUpdater(void)
|
||||
{
|
||||
return _otaUpdater;
|
||||
}
|
||||
|
||||
void OTAManager::updateStartedCb(void)
|
||||
{
|
||||
Serial.println("CALLBACK: HTTP update process started");
|
||||
}
|
||||
|
||||
void OTAManager::updateFinishedCb(void)
|
||||
{
|
||||
Serial.println("CALLBACK: HTTP update process finished");
|
||||
}
|
||||
|
||||
void OTAManager::updateProgressdCb(int cur, int total)
|
||||
{
|
||||
Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total);
|
||||
}
|
||||
|
||||
void OTAManager::updateErrorCb(int err)
|
||||
{
|
||||
Serial.printf("CALLBACK: HTTP update fatal error code %d\n", err);
|
||||
}
|
32
src/app/OTAManager.h
Normal file
32
src/app/OTAManager.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef OTAMANAGER_H
|
||||
#define OTAMANAGER_H
|
||||
|
||||
#include "OTAUpdater.h"
|
||||
#include "SDCardManager.h"
|
||||
#include "BoardConfig.h"
|
||||
|
||||
class OTAManager
|
||||
{
|
||||
friend class SAB;
|
||||
public:
|
||||
~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);
|
||||
void updateProgressdCb(int cur, int total);
|
||||
void updateErrorCb(int err);
|
||||
|
||||
OTAUpdater _otaUpdater;
|
||||
SDCardManager *_sdCardManager = nullptr;
|
||||
const BoardConfig * _boardConfig = nullptr;
|
||||
boolean _isServiceEnabled = false;
|
||||
};
|
||||
|
||||
#endif //OTAMANAGER_H
|
231
src/app/OTAUpdater.cpp
Normal file
231
src/app/OTAUpdater.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
#include "OTAUpdater.h"
|
||||
#include "HttpClient.h"
|
||||
|
||||
//#define DEBUG_OTA_UPDATER
|
||||
|
||||
OTAUpdater::OTAUpdater(const char *serverAddress, const char *path, const char *ota_auth_key, uint16_t port) : _port(port)
|
||||
{
|
||||
if(serverAddress)
|
||||
_serverAddress = strdup(serverAddress);
|
||||
|
||||
if(path)
|
||||
_path = strdup(path);
|
||||
|
||||
if(ota_auth_key)
|
||||
_ota_auth_key = strdup(ota_auth_key);
|
||||
}
|
||||
|
||||
OTAUpdater::OTAUpdater(int httpClientTimeout,const char *serverAddress, const char *path, const char *ota_auth_key, uint16_t port) : ESP8266HTTPUpdate(httpClientTimeout), _port(port)
|
||||
{
|
||||
if(serverAddress)
|
||||
_serverAddress = strdup(serverAddress);
|
||||
|
||||
if(path)
|
||||
_path = strdup(path);
|
||||
|
||||
if(ota_auth_key)
|
||||
_ota_auth_key = strdup(ota_auth_key);
|
||||
}
|
||||
|
||||
OTAUpdater::~OTAUpdater()
|
||||
{
|
||||
if(_publicKey != nullptr)
|
||||
delete _publicKey;
|
||||
|
||||
if(_hash != nullptr)
|
||||
delete _hash;
|
||||
|
||||
if(_signingVerifier != nullptr)
|
||||
delete _signingVerifier;
|
||||
|
||||
free(_serverAddress);
|
||||
free(_path);
|
||||
free(_ota_auth_key);
|
||||
}
|
||||
|
||||
//Enables the binary signing verification
|
||||
void OTAUpdater::enableSHA256UpdateVerification(const char *publicKey)
|
||||
{
|
||||
if(_publicKey != nullptr)
|
||||
delete _publicKey;
|
||||
|
||||
if(_hash != nullptr)
|
||||
delete _hash;
|
||||
|
||||
if(_signingVerifier != nullptr)
|
||||
delete _signingVerifier;
|
||||
|
||||
_publicKey = new BearSSL::PublicKey(publicKey);
|
||||
_hash = new BearSSL::HashSHA256();
|
||||
_signingVerifier = new BearSSL::SigningVerifier(_publicKey);
|
||||
|
||||
Update.installSignature(_hash, _signingVerifier);
|
||||
}
|
||||
|
||||
void OTAUpdater::setServerAddress(const char *serverAddress)
|
||||
{
|
||||
if(!serverAddress)
|
||||
return;
|
||||
|
||||
free(_serverAddress);
|
||||
_serverAddress = strdup(serverAddress);
|
||||
}
|
||||
|
||||
void OTAUpdater::setPath(const char *path)
|
||||
{
|
||||
//The path can be empty
|
||||
if(!path)
|
||||
{
|
||||
free(_path);
|
||||
_path = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(_path);
|
||||
_path = strdup(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OTAUpdater::setOtaAuthKey(const char *ota_auth_key)
|
||||
{
|
||||
//The authKey can be empty
|
||||
if(!ota_auth_key)
|
||||
{
|
||||
free(_ota_auth_key);
|
||||
_ota_auth_key = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(_ota_auth_key);
|
||||
_ota_auth_key = strdup(ota_auth_key);
|
||||
}
|
||||
}
|
||||
|
||||
void OTAUpdater::setPort(uint16_t port)
|
||||
{
|
||||
_port = port;
|
||||
}
|
||||
|
||||
OTAUpdater::UpdateInfo OTAUpdater::fetchUpdateInfo(const char *softwareVersion, uint32_t timeout)
|
||||
{
|
||||
HttpClient httpClient(_serverAddress, _path, _port, timeout);
|
||||
UpdateInfo ui;
|
||||
|
||||
if(!softwareVersion)
|
||||
{
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_NO_UPDATE;
|
||||
return ui;
|
||||
}
|
||||
|
||||
Dictionary<DictionaryHelper::StringEntity> getData;
|
||||
getData.add("authKey", DictionaryHelper::StringEntity(_ota_auth_key));
|
||||
getData.add("checkonly", NULL);
|
||||
|
||||
Dictionary<DictionaryHelper::StringEntity> headerData;
|
||||
headerData.add("x-ESP8266-version",DictionaryHelper::StringEntity(softwareVersion));
|
||||
headerData.add("x-ESP8266-STA-MAC",DictionaryHelper::StringEntity(WiFi.macAddress().c_str()));
|
||||
headerData.add("User-Agent",DictionaryHelper::StringEntity("ESP8266-http-Update"));
|
||||
|
||||
if(httpClient.sendHttpQuery(HttpClient::HttpRequestMethod::GET, &getData, NULL, &headerData) == 0)
|
||||
{
|
||||
HttpConstants::HTTP_CODE result = httpClient.isReplyAvailable(1000);
|
||||
switch(result)
|
||||
{
|
||||
case HttpConstants::HTTP_CODE::HTTP_CODE_OK:
|
||||
{
|
||||
char buffer[100];
|
||||
httpClient.readHttpBody((uint8_t *)buffer, 100);
|
||||
#ifdef DEBUG_OTA_UPDATER
|
||||
Serial.printf("Response from update service : %s\n", buffer);
|
||||
#endif
|
||||
|
||||
char *p = strstr_P(buffer, PSTR("bin_version"));
|
||||
if(p)
|
||||
{
|
||||
p+=14;
|
||||
char *end = strchr(p, '"');
|
||||
if(end)
|
||||
{
|
||||
*end = '\0';
|
||||
|
||||
ui.version = (char *)malloc(strlen(p) * sizeof(char) + 1);
|
||||
if(ui.version)
|
||||
strcpy(ui.version, p);
|
||||
}
|
||||
}
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_UPDATE_AVAILABLE;
|
||||
}
|
||||
break;
|
||||
case HttpConstants::HTTP_CODE::HTTP_CODE_NOT_MODIFIED:
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_NO_UPDATE;
|
||||
break;
|
||||
case HttpConstants::HTTP_CODE::HTTP_CODE_FORBIDDEN:
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_UPDATE_AUTH_ERROR;
|
||||
break;
|
||||
case HttpConstants::HTTP_CODE::HTTP_CODE_NOT_FOUND:
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_UPDATE_REACH_ERROR;
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_OTA_UPDATER
|
||||
Serial.printf("HTTP ERROR CODE IS : %u\n", result);
|
||||
#endif
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_UPDATE_UNDEFINED_ERROR;
|
||||
}
|
||||
|
||||
httpClient.stop();
|
||||
}
|
||||
else
|
||||
ui.info = OTAUpdater::UpdateInfo::HTTP_UPDATE_REACH_ERROR;
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
#define DEBUG_OTA_UPDATER
|
||||
|
||||
HTTPUpdateResult OTAUpdater::update(const char *softwareVersion)
|
||||
{
|
||||
if(!softwareVersion)
|
||||
{
|
||||
#ifdef DEBUG_OTA_UPDATER
|
||||
Serial.printf("Missing softwareVersion !\n");
|
||||
#endif
|
||||
return HTTPUpdateResult::HTTP_UPDATE_NO_UPDATES;
|
||||
}
|
||||
|
||||
if(!_serverAddress)
|
||||
{
|
||||
#ifdef DEBUG_OTA_UPDATER
|
||||
Serial.printf("Missing server address !\n");
|
||||
#endif
|
||||
return HTTPUpdateResult::HTTP_UPDATE_FAILED;
|
||||
}
|
||||
|
||||
//Depending on the presence or not of the path and the authKey, we compute the size we must allocate for the full path
|
||||
uint16_t length = 1 /*for the \0*/;
|
||||
length += _path ? strlen(_path) : 0;
|
||||
length += _ota_auth_key ? strlen(_ota_auth_key) + 9/*for : ?authKey=*/ : 0;
|
||||
|
||||
char *fullpath = (char *)malloc(length * sizeof(char));
|
||||
if(!fullpath)return HTTP_UPDATE_FAILED;
|
||||
|
||||
fullpath[0] = '\0';
|
||||
|
||||
WiFiClient client;
|
||||
|
||||
if(_path)strcpy(fullpath, _path);
|
||||
if(_ota_auth_key)
|
||||
{
|
||||
strcat(fullpath, "?authKey=");
|
||||
strcat(fullpath, _ota_auth_key);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OTA_UPDATER
|
||||
Serial.printf("The fullpath is : %s\n", fullpath);
|
||||
#endif
|
||||
|
||||
HTTPUpdateResult result = ESP8266HTTPUpdate::update(client, _serverAddress, _port, fullpath, softwareVersion);
|
||||
|
||||
free(fullpath);
|
||||
return result;
|
||||
}
|
103
src/app/OTAUpdater.h
Normal file
103
src/app/OTAUpdater.h
Normal file
@ -0,0 +1,103 @@
|
||||
#ifndef OTAUPDATER_H
|
||||
#define OTAUPDATER_H
|
||||
#include <ESP8266httpUpdate.h>
|
||||
|
||||
#define OTAUPDATER_STRING //PSTR
|
||||
|
||||
class OTAUpdater : public ESP8266HTTPUpdate
|
||||
{
|
||||
public:
|
||||
struct UpdateInfo
|
||||
{
|
||||
enum HTTPUpdateInfo {
|
||||
HTTP_NO_UPDATE, //There is no new update available
|
||||
HTTP_UPDATE_AVAILABLE, //There is an update ready to be applied
|
||||
HTTP_UPDATE_AUTH_ERROR, //There was an error during the authentification process by the update service
|
||||
HTTP_UPDATE_REACH_ERROR, //Unable to reach the update service
|
||||
HTTP_UPDATE_UNDEFINED_ERROR
|
||||
};
|
||||
|
||||
UpdateInfo(){}
|
||||
UpdateInfo(const UpdateInfo &object)
|
||||
{
|
||||
info = object.info;
|
||||
if(object.version)
|
||||
{
|
||||
version = (char *) malloc((strlen(object.version) + 1) * sizeof(char));
|
||||
if(version != NULL)
|
||||
strcpy(version, object.version);
|
||||
}
|
||||
}
|
||||
~UpdateInfo(){ dispose(); }
|
||||
UpdateInfo& operator=(const UpdateInfo &object)
|
||||
{
|
||||
info = object.info;
|
||||
if(version)
|
||||
{
|
||||
free(version);version = NULL;
|
||||
}
|
||||
|
||||
if(object.version)
|
||||
{
|
||||
version = (char *) malloc((strlen(object.version) + 1) * sizeof(char));
|
||||
if(version != NULL)
|
||||
strcpy(version, object.version);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void dispose()
|
||||
{
|
||||
if(version)
|
||||
{
|
||||
free(version);version = NULL;
|
||||
}
|
||||
}
|
||||
const char *HTTPUpdateInfoToString(void)
|
||||
{
|
||||
switch(info)
|
||||
{
|
||||
case HTTP_NO_UPDATE:
|
||||
return OTAUPDATER_STRING("HTTP_NO_UPDATE");
|
||||
break;
|
||||
case HTTP_UPDATE_AVAILABLE:
|
||||
return OTAUPDATER_STRING("HTTP_UPDATE_AVAILABLE");
|
||||
break;
|
||||
case HTTP_UPDATE_AUTH_ERROR:
|
||||
return OTAUPDATER_STRING("HTTP_UPDATE_AUTH_ERROR");
|
||||
break;
|
||||
case HTTP_UPDATE_REACH_ERROR:
|
||||
return OTAUPDATER_STRING("HTTP_UPDATE_REACH_ERROR");
|
||||
break;
|
||||
default:
|
||||
return OTAUPDATER_STRING("HTTP_UPDATE_UNDEFINED_ERROR");
|
||||
break;
|
||||
}
|
||||
}
|
||||
HTTPUpdateInfo info = HTTP_NO_UPDATE;
|
||||
char *version = NULL;
|
||||
};
|
||||
OTAUpdater(const char *serverAddress = NULL, const char *path = NULL, const char *ota_auth_key = NULL, uint16_t port = 80);
|
||||
OTAUpdater(int httpClientTimeout, const char *serverAddress, const char *path = NULL, const char *ota_auth_key = NULL, uint16_t port = 80);
|
||||
|
||||
~OTAUpdater();
|
||||
//Enables the binary signing verification
|
||||
void enableSHA256UpdateVerification(const char *publicKey);
|
||||
void setServerAddress(const char *serverAddress);
|
||||
void setPath(const char *path = NULL);
|
||||
void setOtaAuthKey(const char *ota_auth_key = NULL);
|
||||
void setPort(uint16_t port = 80);
|
||||
UpdateInfo fetchUpdateInfo(const char *softwareVersion, uint32_t timeout = 500);
|
||||
HTTPUpdateResult update(const char *softwareVersion);
|
||||
protected:
|
||||
BearSSL::PublicKey *_publicKey = nullptr;
|
||||
BearSSL::HashSHA256 *_hash = nullptr;
|
||||
BearSSL::SigningVerifier *_signingVerifier = nullptr;
|
||||
|
||||
char *_serverAddress = nullptr;
|
||||
char *_path = nullptr;
|
||||
char *_ota_auth_key = nullptr;
|
||||
uint16_t _port;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif //OTAUPDATER_H
|
@ -6,6 +6,7 @@ _screenManager(_display, &_sdCardManager),
|
||||
_connectivityManager(_sdCardManager),
|
||||
_webServer(80, &_sdCardManager, 10),
|
||||
_ftpServer(21, &_sdCardManager, "ESP8266", "12345678", 10),
|
||||
_otaManager(_sdCardManager, _boardConfig),
|
||||
_dbWSServer(81),
|
||||
_pcf(_boardConfig.getI2C_IOExpanderAddress(), Wire),
|
||||
_ioManager(_pcf),
|
||||
@ -21,6 +22,7 @@ _screenManager(_display, &_sdCardManager),
|
||||
_connectivityManager(_sdCardManager),
|
||||
_webServer(webServerPort, &_sdCardManager, 10),
|
||||
_ftpServer(ftpServerPort, &_sdCardManager, "ESP8266", "12345678", 10),
|
||||
_otaManager(_sdCardManager, _boardConfig),
|
||||
_dbWSServer(81),
|
||||
_pcf(_boardConfig.getI2C_IOExpanderAddress(), Wire),
|
||||
_ioManager(_pcf),
|
||||
@ -39,12 +41,18 @@ void SAB::initCommonConfig()
|
||||
|
||||
//We initialize the pins for the I2C communication
|
||||
Wire.begin(_boardConfig.getI2C_sda(), _boardConfig.getI2C_scl());
|
||||
if(!_rtc.begin()) _error |= RTC_BEGIN_ERR;
|
||||
if(!_rtc.begin())
|
||||
_error |= RTC_BEGIN_ERR;
|
||||
else
|
||||
{
|
||||
_rtcManager.setDateTime(_rtc.now());
|
||||
}
|
||||
if(!_display.begin(SSD1306_SWITCHCAPVCC, _boardConfig.getI2C_screenAddress())){ _error |= DISP_BEGIN_ERR;}
|
||||
|
||||
if(!_display.begin(SSD1306_SWITCHCAPVCC, _boardConfig.getI2C_screenAddress()))
|
||||
{
|
||||
_error |= DISP_BEGIN_ERR;
|
||||
}
|
||||
|
||||
if(!_sdCardManager.mountSD())
|
||||
{
|
||||
_error |= SDCARD_INIT_ERR;
|
||||
@ -52,9 +60,11 @@ void SAB::initCommonConfig()
|
||||
_boardConfig.getSPISpeed(),
|
||||
_boardConfig.getSPI_SDCard_cs());
|
||||
}
|
||||
|
||||
_screenManager.init();
|
||||
if(!_connectivityManager.connect()){ _error |= CONNECT_ERR;}
|
||||
if(!_pcf.begin()){_error |= IO_INIT_ERR;}
|
||||
if(!_otaManager.init()){_error |= OTA_INIT_ERR;}
|
||||
|
||||
//We set the different servers :
|
||||
_webServer.setWWWDir(WWW_DIR);
|
||||
@ -104,7 +114,12 @@ FTPServer<FTPClient>& SAB::getFtpServer()
|
||||
return _ftpServer;
|
||||
}
|
||||
|
||||
IOManager& SAB::getIoManager()
|
||||
OTAManager& SAB::getOTAManager()
|
||||
{
|
||||
return _otaManager;
|
||||
}
|
||||
|
||||
IOManager& SAB::getIOManager()
|
||||
{
|
||||
return _ioManager;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "IOManager.h"
|
||||
#include "TaskSchedulerManager.h"
|
||||
#include "PowerManager.h"
|
||||
#include "OTAManager.h"
|
||||
#include "versions.h"
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include <RTClib.h>
|
||||
@ -20,7 +21,7 @@
|
||||
class SAB
|
||||
{
|
||||
public:
|
||||
enum Error {RTC_BEGIN_ERR = 1, DISP_BEGIN_ERR = 2, SDCARD_INIT_ERR = 4, IO_INIT_ERR = 8, CONNECT_ERR = 16};
|
||||
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};
|
||||
|
||||
SAB();
|
||||
SAB(const BoardConfig boardConfig, const unsigned int webServerPort = 80, const unsigned int ftpServerPort = 21);
|
||||
@ -33,10 +34,10 @@ class SAB
|
||||
RTC_DS3231& getRTC_DS3231();
|
||||
SDCardManager& getSdCardManager();
|
||||
ConnectivityManager& getConnectivityManager();
|
||||
//WEBServerManager& getWebServerManager();
|
||||
WEBServer<WEBClient>& getWebServer();
|
||||
FTPServer<FTPClient>& getFtpServer();
|
||||
IOManager& getIoManager();
|
||||
OTAManager& getOTAManager();
|
||||
IOManager& getIOManager();
|
||||
TaskSchedulerManager& getTaskSchedulerManager();
|
||||
PowerManager& getPowerManager();
|
||||
TimeSpan getUpTime() const;
|
||||
@ -56,10 +57,10 @@ class SAB
|
||||
RTC_DS3231 _rtc;
|
||||
RtcManager _rtcManager;
|
||||
ConnectivityManager _connectivityManager;
|
||||
//WEBServerManager _webServerManager;
|
||||
WEBServer<WEBClient> _webServer;
|
||||
FTPServer<FTPClient> _ftpServer;
|
||||
DashboardWSServer _dbWSServer;
|
||||
OTAManager _otaManager;
|
||||
DashboardWSServer _dbWSServer;
|
||||
PCF8574 _pcf;
|
||||
IOManager _ioManager;
|
||||
TaskSchedulerManager _taskSchedulerManager;
|
||||
|
@ -95,9 +95,10 @@ void setup()
|
||||
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", &(otaUpdateApi), NULL, WEBServer<WEBClient>::POST);
|
||||
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.getIoManager().setISROnIOChange(&(ioISR), GPIO_3_RX);
|
||||
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);
|
||||
@ -121,8 +122,8 @@ void loop()
|
||||
vstap.ipAddr = sab.getConnectivityManager().localIP();
|
||||
vstap.sigStrength = sab.getConnectivityManager().RSSI();
|
||||
|
||||
sab.getIoManager().getPcf().digitalReadAll(vio.ioState);
|
||||
sab.getIoManager().getPcf().getPinModeAll(vio.ioMode);
|
||||
sab.getIOManager().getPcf().digitalReadAll(vio.ioState);
|
||||
sab.getIOManager().getPcf().getPinModeAll(vio.ioMode);
|
||||
|
||||
if(ioStateChange)
|
||||
{
|
||||
|
@ -35,10 +35,24 @@ typedef enum { GPIO_0 = 0,
|
||||
#define STA_CFG_FILE "/CONFIG/STA.CFG"
|
||||
#define SCREEN_CFG_FILE "/CONFIG/SCREEN.CFG"
|
||||
#define SERVER_CFG_FILE "/CONFIG/SERVER.CFG"
|
||||
#define OTA_CFG_FILE "/CONFIG/OTA.CFG"
|
||||
#define WWW_DIR "/WWW"
|
||||
#define LOG_DIR "/LOGS"
|
||||
#define FTP_DIR "/FTP"
|
||||
|
||||
//OTA public key for binary verification
|
||||
const char otaVerificationPubKey[] PROGMEM = R"DEL(
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh6eFU0pdfir5CsQqs0v
|
||||
vi7ip7MtRuNgcMtjl7lpXwQuMG5yoso1iR+Fzbz+Cso4lcqarG5uHV8nKYWQ+C39
|
||||
+3OfKx9LSfabCnRAeFFhXuGWEfRcZ9aeW3Jv0Mg2+3sTOfXQGjdgNwOAqZNrL4kr
|
||||
574F+c3o/PAwlr4VLMy7KygorNnaYzC5JF1H5DhqaKNniKVEqGXiVQKW10C04SsM
|
||||
mGV/rKRSPpBVzyBrIf8GNPyVf7W4D0s9gSiCrRWMU2aU3tX35tezwlicsb86MKKM
|
||||
o9ySHAMsIihx3zdwAGOELxE47Ylodq9cwc53fz7pfcdyL+N6FKKWM0bYJAkwNhdJ
|
||||
NQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
)DEL";
|
||||
|
||||
typedef enum { OR_0 = 2, OR_90 = 3, OR_180 = 0, OR_270 = 1 } Orientation;
|
||||
|
||||
typedef enum { BIT = 0, BYTE, KBIT, KBYTE, MBIT, MBYTE, GBIT, GBYTE } SizeUnit;
|
||||
|
@ -3,7 +3,7 @@
|
||||
boolean task_blink(void *pData)
|
||||
{
|
||||
SAB *p = (SAB *) pData;
|
||||
p->getIoManager().getPcf().togglePin(PCF8574::P2);
|
||||
p->getIOManager().getPcf().togglePin(PCF8574::P2);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -19,17 +19,36 @@ boolean task_sys_info(void *pData)
|
||||
|
||||
TimeSpan ts(p->sab->getUpTime());
|
||||
|
||||
Serial.printf_P(PSTR("BATT SENSING...\nUp Time : %d d %d h %d m %d s\nSystem error : %u\nStation IP : %s, %d dBm\nAP IP : %s\nWEB Server clients : %u\nMemory info:\n\tFree RAM : %u\n\tHeap frag : %u\n\tMax block %u\n"),
|
||||
Serial.printf_P(PSTR("BATT SENSING...\nSoftware version : %s\nUp Time : %d d %d h %d m %d s\nSystem error : %u\nStation IP : %s, %d dBm\nAP IP : %s\nDevice MAC : %s\nWEB Server clients : %u\nMemory info:\n\tFree RAM : %u\n\tHeap frag : %u\n\tMax block %u\n"),
|
||||
p->sab->getSoftVersion(),
|
||||
ts.days(), ts.hours(), ts.minutes(), ts.seconds(),
|
||||
p->sab->getError(),
|
||||
p->sab->getConnectivityManager().localIP().toString().c_str(),
|
||||
p->sab->getConnectivityManager().RSSI(),
|
||||
p->sab->getConnectivityManager().softAPIP().toString().c_str(),
|
||||
p->sab->getConnectivityManager().macAddress().c_str(),
|
||||
p->sab->getWebServer().getConnectedClientsCount(),
|
||||
freeRAM,
|
||||
HEAPfrag,
|
||||
biggestContigMemBlock);
|
||||
p->powerInfo = p->sab->getPowerManager().getPowerInfo();
|
||||
|
||||
if(p->sab->getOTAManager().isEnabled())
|
||||
{
|
||||
OTAUpdater::UpdateInfo updateInfo = p->sab->getOTAManager().getOTAUpdater().fetchUpdateInfo(p->sab->getSoftVersion());
|
||||
if(updateInfo.version != NULL)
|
||||
{
|
||||
Serial.printf("OTA : %s -> version(%s)\n", updateInfo.HTTPUpdateInfoToString(), updateInfo.version);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("OTA : %s\n", updateInfo.HTTPUpdateInfoToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("OTA updates disabled");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -63,7 +82,7 @@ boolean task_post_data_logger(void * pData)
|
||||
postData.add("post4", NULL);
|
||||
|
||||
|
||||
if(p->client.sendHttpQuery(HttpClient::HttpRequestMethod::POST, &getData, &postData))
|
||||
if(p->client.sendHttpQuery(HttpClient::HttpRequestMethod::POST, &getData, &postData) == 0)
|
||||
{
|
||||
Serial.println("Send successful");
|
||||
p->rdy = false;
|
||||
|
@ -44,5 +44,7 @@
|
||||
//#define SOFT_VERSION "1.6.12" //WEBServer parsing http query parameters differently, allowing for longer URI and RAM savings.
|
||||
//#define SOFT_VERSION "1.6.13" //ScreenManager now providing and handling display auto power off functionality to save power as well as to fight OLED burn-in.
|
||||
//#define SOFT_VERSION "1.6.14" //Corrected a major stack overflow in the WEBServer and fixed a potential one in the FTPServer.
|
||||
#define SOFT_VERSION "1.6.15" //WEBServer now lists files and folder of a resource when it is a folder.
|
||||
//#define SOFT_VERSION "1.6.15" //WEBServer now lists files and folder of a resource when it is a folder.
|
||||
#define SOFT_VERSION "1.7.0" //OTA update of the device is now possible through a rest API endpoint.
|
||||
|
||||
#endif //VERSIONS_H
|
||||
|
@ -400,38 +400,38 @@ boolean ioSetLevelApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc
|
||||
|
||||
if(HRD.getParams("P0") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P0,atoi(HRD.getParams("P0")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P0,atoi(HRD.getParams("P0")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P1") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P1,atoi(HRD.getParams("P1")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P1,atoi(HRD.getParams("P1")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P2") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P2,atoi(HRD.getParams("P2")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P2,atoi(HRD.getParams("P2")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P3") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P3,atoi(HRD.getParams("P3")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P3,atoi(HRD.getParams("P3")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P4") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P4,atoi(HRD.getParams("P4")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P4,atoi(HRD.getParams("P4")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P5") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P5,atoi(HRD.getParams("P5")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P5,atoi(HRD.getParams("P5")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P6") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P6,atoi(HRD.getParams("P6")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P6,atoi(HRD.getParams("P6")->getString()));
|
||||
}
|
||||
if(HRD.getParams("P7") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().digitalWrite(PCF8574::P7,atoi(HRD.getParams("P7")->getString()));
|
||||
p->getIOManager().getPcf().digitalWrite(PCF8574::P7,atoi(HRD.getParams("P7")->getString()));
|
||||
}
|
||||
|
||||
p->getIoManager().getPcf().digitalReadAll(ioState);//We retrieve the IO state
|
||||
p->getIOManager().getPcf().digitalReadAll(ioState);//We retrieve the IO state
|
||||
sprintf(buffer,"{\"status\":\"ok\",\"P0\":\"%d\",\"P1\":\"%d\",\"P2\":\"%d\",\"P3\":\"%d\",\"P4\":\"%d\",\"P5\":\"%d\",\"P6\":\"%d\",\"P7\":\"%d\"}",ioState[0],ioState[1],ioState[2],ioState[3],ioState[4],ioState[5],ioState[6],ioState[7]);
|
||||
|
||||
WEBServer<WEBClient>::sendHTTPHeader(wc, HttpConstants::httpMIMETypeToString(HttpConstants::APPLICATION_JSON), strlen(buffer));
|
||||
@ -447,7 +447,7 @@ boolean ioGetModeApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc,
|
||||
char helperBuffer[20] = "";
|
||||
const char * const IN = "IN", * const OUT = "OUT";
|
||||
|
||||
p->getIoManager().getPcf().getPinModeAll(ioMode);//We retrieve the IO modes aka INPUT or OUTPUT
|
||||
p->getIOManager().getPcf().getPinModeAll(ioMode);//We retrieve the IO modes aka INPUT or OUTPUT
|
||||
|
||||
if(HRD.getParams.count() == 0)//We send every IO mode
|
||||
{
|
||||
@ -521,38 +521,38 @@ boolean ioSetModeApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc,
|
||||
|
||||
if(HRD.getParams("P0") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P0,strcmp(HRD.getParams("P0")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P0,strcmp(HRD.getParams("P0")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P1") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P1,strcmp(HRD.getParams("P1")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P1,strcmp(HRD.getParams("P1")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P2") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P2,strcmp(HRD.getParams("P2")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P2,strcmp(HRD.getParams("P2")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P3") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P3,strcmp(HRD.getParams("P3")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P3,strcmp(HRD.getParams("P3")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P4") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P4,strcmp(HRD.getParams("P4")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P4,strcmp(HRD.getParams("P4")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P5") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P5,strcmp(HRD.getParams("P5")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P5,strcmp(HRD.getParams("P5")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P6") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P6,strcmp(HRD.getParams("P6")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P6,strcmp(HRD.getParams("P6")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
if(HRD.getParams("P7") != NULL)
|
||||
{
|
||||
p->getIoManager().getPcf().pinMode(PCF8574::P7,strcmp(HRD.getParams("P7")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
p->getIOManager().getPcf().pinMode(PCF8574::P7,strcmp(HRD.getParams("P7")->getString(), IN) == 0 ? INPUT:OUTPUT);
|
||||
}
|
||||
|
||||
p->getIoManager().getPcf().getPinModeAll(ioMode);//We retrieve the IO modes aka INPUT or OUTPUT
|
||||
p->getIOManager().getPcf().getPinModeAll(ioMode);//We retrieve the IO modes aka INPUT or OUTPUT
|
||||
sprintf(buffer,"{\"status\":\"ok\",\"P0\":\"%s\",\"P1\":\"%s\",\"P2\":\"%s\",\"P3\":\"%s\",\"P4\":\"%s\",\"P5\":\"%s\",\"P6\":\"%s\",\"P7\":\"%s\"}",ioMode[0] ? OUT:IN,ioMode[1] ? OUT:IN,ioMode[2] ? OUT:IN,ioMode[3] ? OUT:IN,ioMode[4] ? OUT:IN,ioMode[5] ? OUT:IN,ioMode[6] ? OUT:IN,ioMode[7] ? OUT:IN);
|
||||
|
||||
WEBServer<WEBClient>::sendHTTPHeader(wc, HttpConstants::httpMIMETypeToString(HttpConstants::APPLICATION_JSON), strlen(buffer));
|
||||
@ -563,22 +563,22 @@ boolean ioSetModeApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc,
|
||||
boolean swVersionApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc, void *pData)
|
||||
{
|
||||
(void)HRD;
|
||||
(void)pData;
|
||||
SAB *p = (SAB *)pData;
|
||||
|
||||
char buffer[100] = "";
|
||||
|
||||
sprintf(buffer ,"{\"status\":\"ok\",\"version\":\"%s\"}", SOFT_VERSION);
|
||||
sprintf(buffer ,"{\"status\":\"ok\",\"version\":\"%s\"}", p->getSoftVersion());
|
||||
|
||||
WEBServer<WEBClient>::sendHTTPHeader(wc, HttpConstants::httpMIMETypeToString(HttpConstants::APPLICATION_JSON), strlen(buffer));
|
||||
wc->print(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean otaUpdateApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc, void *pData)
|
||||
boolean otaUpdateUploadApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc, void *pData)
|
||||
{
|
||||
(void)HRD;
|
||||
(void)pData;
|
||||
Serial.printf("OTA Update resquest\n#");
|
||||
Serial.printf("OTA Update Upload resquest\n#");
|
||||
|
||||
char buffer[30] = "";
|
||||
size_t read(0), cnt(0);
|
||||
@ -602,3 +602,58 @@ boolean otaUpdateApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean otaUpdateRemoteApi(WEBServer<WEBClient>::HttpRequestData &HRD, WiFiClient *wc, void *pData)
|
||||
{
|
||||
SAB *p = (SAB *)pData;
|
||||
|
||||
char buffer[100] = "";
|
||||
boolean updateDevice(false);
|
||||
|
||||
if(!p->getOTAManager().isEnabled())
|
||||
{
|
||||
strcpy(buffer ,"{\"status\":\"ok\",\"ota\":\"disabled\"}");
|
||||
}
|
||||
else
|
||||
{
|
||||
OTAUpdater::UpdateInfo updateInfo = p->getOTAManager().getOTAUpdater().fetchUpdateInfo(p->getSoftVersion());
|
||||
|
||||
switch(updateInfo.info)
|
||||
{
|
||||
case OTAUpdater::UpdateInfo::HTTP_NO_UPDATE :
|
||||
strcpy(buffer ,"{\"status\":\"ok\",\"ota\":\"enabled\",\"msg\":\"No update available\"}");
|
||||
break;
|
||||
case OTAUpdater::UpdateInfo::HTTP_UPDATE_AUTH_ERROR :
|
||||
strcpy(buffer ,"{\"status\":\"error\",\"ota\":\"enabled\",\"msg\":\"OTA auth error\"}");
|
||||
break;
|
||||
case OTAUpdater::UpdateInfo::HTTP_UPDATE_AVAILABLE :
|
||||
//Then we update the firmware
|
||||
if(HRD.getParams("update") != NULL)
|
||||
{
|
||||
sprintf(buffer ,"{\"status\":\"ok\",\"ota\":\"enabled\",\"msg\":\"Updating the device, please wait\",\"version\":\"%s\"}", updateInfo.version);
|
||||
updateDevice = true;
|
||||
}
|
||||
else //This means, we only want to get the new version number
|
||||
{
|
||||
sprintf(buffer ,"{\"status\":\"ok\",\"ota\":\"enabled\",\"msg\":\"Update available\",\"version\":\"%s\"}", updateInfo.version);
|
||||
}
|
||||
break;
|
||||
case OTAUpdater::UpdateInfo::HTTP_UPDATE_REACH_ERROR :
|
||||
strcpy(buffer ,"{\"status\":\"error\",\"ota\":\"enabled\",\"msg\":\"OTA reach error\"}");
|
||||
break;
|
||||
default:
|
||||
strcpy(buffer ,"{\"status\":\"error\",\"ota\":\"enabled\",\"msg\":\"Undefined error\"}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WEBServer<WEBClient>::sendHTTPHeader(wc, HttpConstants::httpMIMETypeToString(HttpConstants::APPLICATION_JSON), strlen(buffer));
|
||||
wc->print(buffer);
|
||||
|
||||
if(updateDevice)
|
||||
{
|
||||
p->getOTAManager().getOTAUpdater().update(p->getSoftVersion());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ boolean ioSetLevelApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*
|
||||
boolean ioGetModeApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*);
|
||||
boolean ioSetModeApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*);
|
||||
boolean swVersionApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*);
|
||||
boolean otaUpdateApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*);
|
||||
boolean otaUpdateUploadApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*);
|
||||
boolean otaUpdateRemoteApi(WEBServer<WEBClient>::HttpRequestData&, WiFiClient*, void*);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user