Added the OTAUpdater class which wraps the ESP8266httpUpdate to be compatible with my OTA service php file
This commit is contained in:
parent
2eb604d24d
commit
e3e01da80b
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
|
Loading…
Reference in New Issue
Block a user