Re-established SpanOTA code and tested OTA upload

Only problem was that the definition for esp_image_header_t was moved to a new IDF header file.  Solution was to add: #include <esp_app_format.h>.
This commit is contained in:
Gregg 2024-07-20 09:38:54 -05:00
parent 158274cac6
commit fc4d8d85d1
4 changed files with 161 additions and 159 deletions

View File

@ -40,13 +40,13 @@ void HAPClient::init(){
size_t len; // not used but required to read blobs from NVS
// if(strlen(homeSpan.spanOTA.otaPwd)==0){ // OTA password has not been specified in sketch
// if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS...
// nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // ...retrieve data.
// } else { // otherwise...
// homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password
// }
// }
if(strlen(homeSpan.spanOTA.otaPwd)==0){ // OTA password has not been specified in sketch
if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS...
nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // ...retrieve data.
} else { // otherwise...
homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password
}
}
if(!strlen(homeSpan.qrID)){ // if Setup ID has not been specified in sketch
if(!nvs_get_str(homeSpan.hapNVS,"SETUPID",NULL,&len)){ // check for saved value

View File

@ -38,6 +38,7 @@
#include <esp_sntp.h>
#include <esp_ota_ops.h>
#include <esp_wifi.h>
#include <esp_app_format.h>
#include "HomeSpan.h"
#include "HAP.h"
@ -155,11 +156,11 @@ void Span::begin(Category catID, const char *_displayName, const char *_hostName
nvs_get_u8(otaNVS,"OTA_REQUIRED",&otaRequired);
nvs_set_u8(otaNVS,"OTA_REQUIRED",0);
nvs_commit(otaNVS);
// if(otaRequired && !spanOTA.enabled){
// LOG0("\n\n*** OTA SAFE MODE ALERT: OTA REQUIRED BUT NOT ENABLED. ROLLING BACK TO PREVIOUS APPLICATION ***\n\n");
// delay(100);
// esp_ota_mark_app_invalid_rollback_and_reboot();
// }
if(otaRequired && !spanOTA.enabled){
LOG0("\n\n*** OTA SAFE MODE ALERT: OTA REQUIRED BUT NOT ENABLED. ROLLING BACK TO PREVIOUS APPLICATION ***\n\n");
delay(100);
esp_ota_mark_app_invalid_rollback_and_reboot();
}
} // begin
@ -268,8 +269,8 @@ void Span::pollTask() {
HAPClient::checkNotifications();
HAPClient::checkTimedWrites();
//D if(spanOTA.enabled)
//D ArduinoOTA.handle();
if(spanOTA.enabled)
ArduinoOTA.handle();
if(controlButton && controlButton->primed())
STATUS_UPDATE(start(LED_ALERT),HS_ENTERING_CONFIG_MODE)
@ -476,20 +477,20 @@ void Span::checkConnect(){
mbedtls_base64_encode((uint8_t *)setupHash,9,&len,hashOutput,4); // Step 3: Encode the first 4 bytes of hashOutput in base64, which results in an 8-character, null-terminated, setupHash
mdns_service_txt_item_set("_hap","_tcp","sh",setupHash); // Step 4: broadcast the resulting Setup Hash
// if(spanOTA.enabled){
// ArduinoOTA.setHostname(hostName);
//
// if(spanOTA.auth)
// ArduinoOTA.setPasswordHash(spanOTA.otaPwd);
//
// ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error);
//
// ArduinoOTA.begin();
// LOG0("Starting OTA Server: %s at %s\n",displayName,WiFi.localIP().toString().c_str());
// LOG0("Authorization Password: %s",spanOTA.auth?"Enabled\n\n":"DISABLED!\n\n");
// }
if(spanOTA.enabled){
ArduinoOTA.setHostname(hostName);
//D mdns_service_txt_item_set("_hap","_tcp","ota",spanOTA.enabled?"yes":"no"); // OTA status (info only - NOT used by HAP)
if(spanOTA.auth)
ArduinoOTA.setPasswordHash(spanOTA.otaPwd);
ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error);
ArduinoOTA.begin();
LOG0("Starting OTA Server: %s at %s\n",displayName,WiFi.localIP().toString().c_str());
LOG0("Authorization Password: %s",spanOTA.auth?"Enabled\n\n":"DISABLED!\n\n");
}
mdns_service_txt_item_set("_hap","_tcp","ota",spanOTA.enabled?"yes":"no"); // OTA status (info only - NOT used by HAP)
if(webLog.isEnabled){
mdns_service_txt_item_set("_hap","_tcp","logURL",webLog.statusURL.c_str()+4); // Web Log status (info only - NOT used by HAP)
@ -608,34 +609,34 @@ void Span::processSerialCommand(const char *c){
}
break;
// case 'O': {
//
// char textPwd[34]="\0";
//
// LOG0("\n>>> New OTA Password, or <return> to cancel request: ");
// readSerial(textPwd,33);
//
// if(strlen(textPwd)==0){
// LOG0("(cancelled)\n\n");
// return;
// }
//
// if(strlen(textPwd)==33){
// LOG0("\n*** Sorry, 32 character limit - request cancelled\n\n");
// return;
// }
//
// LOG0("%s\n",mask(textPwd,2).c_str());
// spanOTA.setPassword(textPwd);
// nvs_set_str(otaNVS,"OTADATA",spanOTA.otaPwd); // update data
// nvs_commit(otaNVS);
//
// LOG0("... Accepted! Password change will take effect after next restart.\n");
// if(!spanOTA.enabled)
// LOG0("... Note: OTA has not been enabled in this sketch.\n");
// LOG0("\n");
// }
// break;
case 'O': {
char textPwd[34]="\0";
LOG0("\n>>> New OTA Password, or <return> to cancel request: ");
readSerial(textPwd,33);
if(strlen(textPwd)==0){
LOG0("(cancelled)\n\n");
return;
}
if(strlen(textPwd)==33){
LOG0("\n*** Sorry, 32 character limit - request cancelled\n\n");
return;
}
LOG0("%s\n",mask(textPwd,2).c_str());
spanOTA.setPassword(textPwd);
nvs_set_str(otaNVS,"OTADATA",spanOTA.otaPwd); // update data
nvs_commit(otaNVS);
LOG0("... Accepted! Password change will take effect after next restart.\n");
if(!spanOTA.enabled)
LOG0("... Note: OTA has not been enabled in this sketch.\n");
LOG0("\n");
}
break;
case 'S': {
@ -2457,89 +2458,89 @@ void SpanWebLog::vLog(boolean sysMsg, const char *fmt, va_list ap){
// SpanOTA //
///////////////////////////////
//int SpanOTA::init(boolean _auth, boolean _safeLoad, const char *pwd){
// if(esp_ota_get_running_partition()==esp_ota_get_next_update_partition(NULL)){
// LOG0("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n");
// return(-1);
// }
//
// enabled=true;
// safeLoad=_safeLoad;
// auth=_auth;
// if(pwd==NULL)
// return(0);
// return(setPassword(pwd));
//}
//
/////////////////////////////////
//
//int SpanOTA::setPassword(const char *pwd){
// if(strlen(pwd)<1 || strlen(pwd)>32){
// LOG0("\n*** WARNING: Cannot change OTA password to '%s'. Password length must be between 1 and 32 characters.\n\n",pwd);
// return(-1);
// }
//
// MD5Builder otaPwdHash;
// otaPwdHash.begin();
// otaPwdHash.add(pwd);
// otaPwdHash.calculate();
// otaPwdHash.getChars(homeSpan.spanOTA.otaPwd);
// return(0);
//}
//
/////////////////////////////////
//
//void SpanOTA::start(){
// LOG0("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
// esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
// otaPercent=0;
// STATUS_UPDATE(start(LED_OTA_STARTED),HS_OTA_STARTED)
//}
//
/////////////////////////////////
//
//void SpanOTA::end(){
// nvs_set_u8(homeSpan.otaNVS,"OTA_REQUIRED",safeLoad);
// nvs_commit(homeSpan.otaNVS);
// LOG0(" DONE! Rebooting...\n");
// homeSpan.reboot();
//}
//
/////////////////////////////////
//
//void SpanOTA::progress(uint32_t progress, uint32_t total){
// int percent=progress*100/total;
// if(percent/10 != otaPercent/10){
// otaPercent=percent;
// LOG0("%d%%..",progress*100/total);
// }
//
// if(safeLoad && progress==total){
// SpanPartition newSpanPartition;
// esp_partition_read(esp_ota_get_next_update_partition(NULL), sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t), &newSpanPartition, sizeof(newSpanPartition));
// LOG0("Checking for HomeSpan Magic Cookie: %s..",newSpanPartition.magicCookie);
// if(strcmp(newSpanPartition.magicCookie,spanPartition.magicCookie))
// Update.abort();
// }
//}
//
/////////////////////////////////
//
//void SpanOTA::error(ota_error_t err){
// LOG0("*** OTA Error[%u]: ", err);
// if (err == OTA_AUTH_ERROR) LOG0("Auth Failed\n\n");
// else if (err == OTA_BEGIN_ERROR) LOG0("Begin Failed\n\n");
// else if (err == OTA_CONNECT_ERROR) LOG0("Connect Failed\n\n");
// else if (err == OTA_RECEIVE_ERROR) LOG0("Receive Failed\n\n");
// else if (err == OTA_END_ERROR) LOG0("End Failed\n\n");
//}
//
/////////////////////////////////
//
//int SpanOTA::otaPercent;
//boolean SpanOTA::safeLoad;
//boolean SpanOTA::enabled=false;
//boolean SpanOTA::auth;
int SpanOTA::init(boolean _auth, boolean _safeLoad, const char *pwd){
if(esp_ota_get_running_partition()==esp_ota_get_next_update_partition(NULL)){
LOG0("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n");
return(-1);
}
enabled=true;
safeLoad=_safeLoad;
auth=_auth;
if(pwd==NULL)
return(0);
return(setPassword(pwd));
}
///////////////////////////////
int SpanOTA::setPassword(const char *pwd){
if(strlen(pwd)<1 || strlen(pwd)>32){
LOG0("\n*** WARNING: Cannot change OTA password to '%s'. Password length must be between 1 and 32 characters.\n\n",pwd);
return(-1);
}
MD5Builder otaPwdHash;
otaPwdHash.begin();
otaPwdHash.add(pwd);
otaPwdHash.calculate();
otaPwdHash.getChars(homeSpan.spanOTA.otaPwd);
return(0);
}
///////////////////////////////
void SpanOTA::start(){
LOG0("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
otaPercent=0;
STATUS_UPDATE(start(LED_OTA_STARTED),HS_OTA_STARTED)
}
///////////////////////////////
void SpanOTA::end(){
nvs_set_u8(homeSpan.otaNVS,"OTA_REQUIRED",safeLoad);
nvs_commit(homeSpan.otaNVS);
LOG0(" DONE! Rebooting...\n");
homeSpan.reboot();
}
///////////////////////////////
void SpanOTA::progress(uint32_t progress, uint32_t total){
int percent=progress*100/total;
if(percent/10 != otaPercent/10){
otaPercent=percent;
LOG0("%d%%..",percent);
}
if(safeLoad && progress==total){
SpanPartition newSpanPartition;
esp_partition_read(esp_ota_get_next_update_partition(NULL), sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t), &newSpanPartition, sizeof(newSpanPartition));
LOG0("Checking for HomeSpan Magic Cookie: %s..",newSpanPartition.magicCookie);
if(strcmp(newSpanPartition.magicCookie,spanPartition.magicCookie))
Update.abort();
}
}
///////////////////////////////
void SpanOTA::error(ota_error_t err){
LOG0("*** OTA Error[%u]: ", err);
if (err == OTA_AUTH_ERROR) LOG0("Auth Failed\n\n");
else if (err == OTA_BEGIN_ERROR) LOG0("Begin Failed\n\n");
else if (err == OTA_CONNECT_ERROR) LOG0("Connect Failed\n\n");
else if (err == OTA_RECEIVE_ERROR) LOG0("Receive Failed\n\n");
else if (err == OTA_END_ERROR) LOG0("End Failed\n\n");
}
///////////////////////////////
int SpanOTA::otaPercent;
boolean SpanOTA::safeLoad;
boolean SpanOTA::enabled=false;
boolean SpanOTA::auth;
///////////////////////////////
// SpanPoint //

View File

@ -37,7 +37,7 @@
#include <vector>
#include <list>
#include <nvs.h>
//D#include <ArduinoOTA.h>
#include <ArduinoOTA.h>
#include <esp_now.h>
#include <mbedtls/base64.h>
@ -186,22 +186,22 @@ struct SpanWebLog{ // optional web status/log data
///////////////////////////////
//struct SpanOTA{ // manages OTA process
//
// char otaPwd[33]=""; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
//
// static boolean enabled; // enables OTA - default if not enabled
// static boolean auth; // indicates whether OTA password is required
// static int otaPercent;
// static boolean safeLoad; // indicates whether OTA update should reject any application update that is not another HomeSpan sketch
//
// int init(boolean auth, boolean safeLoad, const char *pwd);
// int setPassword(const char *pwd);
// static void start();
// static void end();
// static void progress(uint32_t progress, uint32_t total);
// static void error(ota_error_t err);
//};
struct SpanOTA{ // manages OTA process
char otaPwd[33]=""; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
static boolean enabled; // enables OTA - default if not enabled
static boolean auth; // indicates whether OTA password is required
static int otaPercent;
static boolean safeLoad; // indicates whether OTA update should reject any application update that is not another HomeSpan sketch
int init(boolean auth, boolean safeLoad, const char *pwd);
int setPassword(const char *pwd);
static void start();
static void end();
static void progress(uint32_t progress, uint32_t total);
static void error(ota_error_t err);
};
//////////////////////////////////////
// USER API CLASSES BEGINS HERE //
@ -273,7 +273,7 @@ class Span{
TaskHandle_t loopTaskHandle; // Arduino Loop Task handle
boolean verboseWifiReconnect = true; // set to false to not print WiFi reconnect attempts messages
//D SpanOTA spanOTA; // manages OTA process
SpanOTA spanOTA; // manages OTA process
SpanConfig hapConfig; // track configuration changes to the HAP Accessory database; used to increment the configuration number (c#) when changes found
list<HAPClient, Mallocator<HAPClient>> hapList; // linked-list of HAPClient structures containing HTTP client connections, parsing routines, and state variables
@ -370,8 +370,8 @@ class Span{
Span& setHostNameSuffix(const char *suffix){asprintf(&hostNameSuffix,"%s",suffix);return(*this);} // sets the hostName suffix to be used instead of the 6-byte AccessoryID
//D int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password
//D int enableOTA(const char *pwd, boolean safeLoad=true){return(spanOTA.init(true, safeLoad, pwd));} // enables Over-the-Air updates, with custom authorization password (overrides any password stored with the 'O' command)
int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password
int enableOTA(const char *pwd, boolean safeLoad=true){return(spanOTA.init(true, safeLoad, pwd));} // enables Over-the-Air updates, with custom authorization password (overrides any password stored with the 'O' command)
Span& enableWebLog(uint16_t maxEntries=0, const char *serv=NULL, const char *tz="UTC", const char *url=DEFAULT_WEBLOG_URL){ // enable Web Logging
webLog.init(maxEntries, serv, tz, url);

View File

@ -32,7 +32,8 @@ void setup() {
Serial.begin(115200);
homeSpan.enableWebLog(50);
homeSpan.begin(Category::Lighting,"HomeSpan LightBulb");
homeSpan.enableOTA();
homeSpan.begin(Category::Lighting,"HomeSpan OTA Test");
new SpanAccessory();
new Service::AccessoryInformation();