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:
parent
158274cac6
commit
fc4d8d85d1
14
src/HAP.cpp
14
src/HAP.cpp
|
|
@ -40,13 +40,13 @@ void HAPClient::init(){
|
||||||
|
|
||||||
size_t len; // not used but required to read blobs from NVS
|
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(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...
|
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.
|
nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // ...retrieve data.
|
||||||
// } else { // otherwise...
|
} else { // otherwise...
|
||||||
// homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password
|
homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
if(!strlen(homeSpan.qrID)){ // if Setup ID has not been specified in sketch
|
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
|
if(!nvs_get_str(homeSpan.hapNVS,"SETUPID",NULL,&len)){ // check for saved value
|
||||||
|
|
|
||||||
263
src/HomeSpan.cpp
263
src/HomeSpan.cpp
|
|
@ -38,6 +38,7 @@
|
||||||
#include <esp_sntp.h>
|
#include <esp_sntp.h>
|
||||||
#include <esp_ota_ops.h>
|
#include <esp_ota_ops.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
|
#include <esp_app_format.h>
|
||||||
|
|
||||||
#include "HomeSpan.h"
|
#include "HomeSpan.h"
|
||||||
#include "HAP.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_get_u8(otaNVS,"OTA_REQUIRED",&otaRequired);
|
||||||
nvs_set_u8(otaNVS,"OTA_REQUIRED",0);
|
nvs_set_u8(otaNVS,"OTA_REQUIRED",0);
|
||||||
nvs_commit(otaNVS);
|
nvs_commit(otaNVS);
|
||||||
// if(otaRequired && !spanOTA.enabled){
|
if(otaRequired && !spanOTA.enabled){
|
||||||
// LOG0("\n\n*** OTA SAFE MODE ALERT: OTA REQUIRED BUT NOT ENABLED. ROLLING BACK TO PREVIOUS APPLICATION ***\n\n");
|
LOG0("\n\n*** OTA SAFE MODE ALERT: OTA REQUIRED BUT NOT ENABLED. ROLLING BACK TO PREVIOUS APPLICATION ***\n\n");
|
||||||
// delay(100);
|
delay(100);
|
||||||
// esp_ota_mark_app_invalid_rollback_and_reboot();
|
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||||
// }
|
}
|
||||||
|
|
||||||
} // begin
|
} // begin
|
||||||
|
|
||||||
|
|
@ -268,8 +269,8 @@ void Span::pollTask() {
|
||||||
HAPClient::checkNotifications();
|
HAPClient::checkNotifications();
|
||||||
HAPClient::checkTimedWrites();
|
HAPClient::checkTimedWrites();
|
||||||
|
|
||||||
//D if(spanOTA.enabled)
|
if(spanOTA.enabled)
|
||||||
//D ArduinoOTA.handle();
|
ArduinoOTA.handle();
|
||||||
|
|
||||||
if(controlButton && controlButton->primed())
|
if(controlButton && controlButton->primed())
|
||||||
STATUS_UPDATE(start(LED_ALERT),HS_ENTERING_CONFIG_MODE)
|
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
|
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
|
mdns_service_txt_item_set("_hap","_tcp","sh",setupHash); // Step 4: broadcast the resulting Setup Hash
|
||||||
|
|
||||||
// if(spanOTA.enabled){
|
if(spanOTA.enabled){
|
||||||
// ArduinoOTA.setHostname(hostName);
|
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");
|
|
||||||
// }
|
|
||||||
|
|
||||||
//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){
|
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)
|
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;
|
break;
|
||||||
|
|
||||||
// case 'O': {
|
case 'O': {
|
||||||
//
|
|
||||||
// char textPwd[34]="\0";
|
char textPwd[34]="\0";
|
||||||
//
|
|
||||||
// LOG0("\n>>> New OTA Password, or <return> to cancel request: ");
|
LOG0("\n>>> New OTA Password, or <return> to cancel request: ");
|
||||||
// readSerial(textPwd,33);
|
readSerial(textPwd,33);
|
||||||
//
|
|
||||||
// if(strlen(textPwd)==0){
|
if(strlen(textPwd)==0){
|
||||||
// LOG0("(cancelled)\n\n");
|
LOG0("(cancelled)\n\n");
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if(strlen(textPwd)==33){
|
if(strlen(textPwd)==33){
|
||||||
// LOG0("\n*** Sorry, 32 character limit - request cancelled\n\n");
|
LOG0("\n*** Sorry, 32 character limit - request cancelled\n\n");
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// LOG0("%s\n",mask(textPwd,2).c_str());
|
LOG0("%s\n",mask(textPwd,2).c_str());
|
||||||
// spanOTA.setPassword(textPwd);
|
spanOTA.setPassword(textPwd);
|
||||||
// nvs_set_str(otaNVS,"OTADATA",spanOTA.otaPwd); // update data
|
nvs_set_str(otaNVS,"OTADATA",spanOTA.otaPwd); // update data
|
||||||
// nvs_commit(otaNVS);
|
nvs_commit(otaNVS);
|
||||||
//
|
|
||||||
// LOG0("... Accepted! Password change will take effect after next restart.\n");
|
LOG0("... Accepted! Password change will take effect after next restart.\n");
|
||||||
// if(!spanOTA.enabled)
|
if(!spanOTA.enabled)
|
||||||
// LOG0("... Note: OTA has not been enabled in this sketch.\n");
|
LOG0("... Note: OTA has not been enabled in this sketch.\n");
|
||||||
// LOG0("\n");
|
LOG0("\n");
|
||||||
// }
|
}
|
||||||
// break;
|
break;
|
||||||
|
|
||||||
case 'S': {
|
case 'S': {
|
||||||
|
|
||||||
|
|
@ -2457,89 +2458,89 @@ void SpanWebLog::vLog(boolean sysMsg, const char *fmt, va_list ap){
|
||||||
// SpanOTA //
|
// SpanOTA //
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
//int SpanOTA::init(boolean _auth, boolean _safeLoad, const char *pwd){
|
int SpanOTA::init(boolean _auth, boolean _safeLoad, const char *pwd){
|
||||||
// if(esp_ota_get_running_partition()==esp_ota_get_next_update_partition(NULL)){
|
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");
|
LOG0("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n");
|
||||||
// return(-1);
|
return(-1);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// enabled=true;
|
enabled=true;
|
||||||
// safeLoad=_safeLoad;
|
safeLoad=_safeLoad;
|
||||||
// auth=_auth;
|
auth=_auth;
|
||||||
// if(pwd==NULL)
|
if(pwd==NULL)
|
||||||
// return(0);
|
return(0);
|
||||||
// return(setPassword(pwd));
|
return(setPassword(pwd));
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
/////////////////////////////////
|
///////////////////////////////
|
||||||
//
|
|
||||||
//int SpanOTA::setPassword(const char *pwd){
|
int SpanOTA::setPassword(const char *pwd){
|
||||||
// if(strlen(pwd)<1 || strlen(pwd)>32){
|
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);
|
LOG0("\n*** WARNING: Cannot change OTA password to '%s'. Password length must be between 1 and 32 characters.\n\n",pwd);
|
||||||
// return(-1);
|
return(-1);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// MD5Builder otaPwdHash;
|
MD5Builder otaPwdHash;
|
||||||
// otaPwdHash.begin();
|
otaPwdHash.begin();
|
||||||
// otaPwdHash.add(pwd);
|
otaPwdHash.add(pwd);
|
||||||
// otaPwdHash.calculate();
|
otaPwdHash.calculate();
|
||||||
// otaPwdHash.getChars(homeSpan.spanOTA.otaPwd);
|
otaPwdHash.getChars(homeSpan.spanOTA.otaPwd);
|
||||||
// return(0);
|
return(0);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
/////////////////////////////////
|
///////////////////////////////
|
||||||
//
|
|
||||||
//void SpanOTA::start(){
|
void SpanOTA::start(){
|
||||||
// LOG0("\n*** Current Partition: %s\n*** New Partition: %s\n*** OTA Starting..",
|
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);
|
esp_ota_get_running_partition()->label,esp_ota_get_next_update_partition(NULL)->label);
|
||||||
// otaPercent=0;
|
otaPercent=0;
|
||||||
// STATUS_UPDATE(start(LED_OTA_STARTED),HS_OTA_STARTED)
|
STATUS_UPDATE(start(LED_OTA_STARTED),HS_OTA_STARTED)
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
/////////////////////////////////
|
///////////////////////////////
|
||||||
//
|
|
||||||
//void SpanOTA::end(){
|
void SpanOTA::end(){
|
||||||
// nvs_set_u8(homeSpan.otaNVS,"OTA_REQUIRED",safeLoad);
|
nvs_set_u8(homeSpan.otaNVS,"OTA_REQUIRED",safeLoad);
|
||||||
// nvs_commit(homeSpan.otaNVS);
|
nvs_commit(homeSpan.otaNVS);
|
||||||
// LOG0(" DONE! Rebooting...\n");
|
LOG0(" DONE! Rebooting...\n");
|
||||||
// homeSpan.reboot();
|
homeSpan.reboot();
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
/////////////////////////////////
|
///////////////////////////////
|
||||||
//
|
|
||||||
//void SpanOTA::progress(uint32_t progress, uint32_t total){
|
void SpanOTA::progress(uint32_t progress, uint32_t total){
|
||||||
// int percent=progress*100/total;
|
int percent=progress*100/total;
|
||||||
// if(percent/10 != otaPercent/10){
|
if(percent/10 != otaPercent/10){
|
||||||
// otaPercent=percent;
|
otaPercent=percent;
|
||||||
// LOG0("%d%%..",progress*100/total);
|
LOG0("%d%%..",percent);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if(safeLoad && progress==total){
|
if(safeLoad && progress==total){
|
||||||
// SpanPartition newSpanPartition;
|
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));
|
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);
|
LOG0("Checking for HomeSpan Magic Cookie: %s..",newSpanPartition.magicCookie);
|
||||||
// if(strcmp(newSpanPartition.magicCookie,spanPartition.magicCookie))
|
if(strcmp(newSpanPartition.magicCookie,spanPartition.magicCookie))
|
||||||
// Update.abort();
|
Update.abort();
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
/////////////////////////////////
|
///////////////////////////////
|
||||||
//
|
|
||||||
//void SpanOTA::error(ota_error_t err){
|
void SpanOTA::error(ota_error_t err){
|
||||||
// LOG0("*** OTA Error[%u]: ", err);
|
LOG0("*** OTA Error[%u]: ", err);
|
||||||
// if (err == OTA_AUTH_ERROR) LOG0("Auth Failed\n\n");
|
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_BEGIN_ERROR) LOG0("Begin Failed\n\n");
|
||||||
// else if (err == OTA_CONNECT_ERROR) LOG0("Connect 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_RECEIVE_ERROR) LOG0("Receive Failed\n\n");
|
||||||
// else if (err == OTA_END_ERROR) LOG0("End Failed\n\n");
|
else if (err == OTA_END_ERROR) LOG0("End Failed\n\n");
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
/////////////////////////////////
|
///////////////////////////////
|
||||||
//
|
|
||||||
//int SpanOTA::otaPercent;
|
int SpanOTA::otaPercent;
|
||||||
//boolean SpanOTA::safeLoad;
|
boolean SpanOTA::safeLoad;
|
||||||
//boolean SpanOTA::enabled=false;
|
boolean SpanOTA::enabled=false;
|
||||||
//boolean SpanOTA::auth;
|
boolean SpanOTA::auth;
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// SpanPoint //
|
// SpanPoint //
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <nvs.h>
|
#include <nvs.h>
|
||||||
//D#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
#include <esp_now.h>
|
#include <esp_now.h>
|
||||||
#include <mbedtls/base64.h>
|
#include <mbedtls/base64.h>
|
||||||
|
|
||||||
|
|
@ -186,22 +186,22 @@ struct SpanWebLog{ // optional web status/log data
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
//struct SpanOTA{ // manages OTA process
|
struct SpanOTA{ // manages OTA process
|
||||||
//
|
|
||||||
// char otaPwd[33]=""; // MD5 Hash of OTA password, represented as a string of hexidecimal characters
|
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 enabled; // enables OTA - default if not enabled
|
||||||
// static boolean auth; // indicates whether OTA password is required
|
static boolean auth; // indicates whether OTA password is required
|
||||||
// static int otaPercent;
|
static int otaPercent;
|
||||||
// static boolean safeLoad; // indicates whether OTA update should reject any application update that is not another HomeSpan sketch
|
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 init(boolean auth, boolean safeLoad, const char *pwd);
|
||||||
// int setPassword(const char *pwd);
|
int setPassword(const char *pwd);
|
||||||
// static void start();
|
static void start();
|
||||||
// static void end();
|
static void end();
|
||||||
// static void progress(uint32_t progress, uint32_t total);
|
static void progress(uint32_t progress, uint32_t total);
|
||||||
// static void error(ota_error_t err);
|
static void error(ota_error_t err);
|
||||||
//};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// USER API CLASSES BEGINS HERE //
|
// USER API CLASSES BEGINS HERE //
|
||||||
|
|
@ -273,7 +273,7 @@ class Span{
|
||||||
TaskHandle_t loopTaskHandle; // Arduino Loop Task handle
|
TaskHandle_t loopTaskHandle; // Arduino Loop Task handle
|
||||||
boolean verboseWifiReconnect = true; // set to false to not print WiFi reconnect attempts messages
|
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
|
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
|
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
|
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
|
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(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
|
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);
|
webLog.init(maxEntries, serv, tz, url);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
homeSpan.enableWebLog(50);
|
homeSpan.enableWebLog(50);
|
||||||
homeSpan.begin(Category::Lighting,"HomeSpan LightBulb");
|
homeSpan.enableOTA();
|
||||||
|
homeSpan.begin(Category::Lighting,"HomeSpan OTA Test");
|
||||||
|
|
||||||
new SpanAccessory();
|
new SpanAccessory();
|
||||||
new Service::AccessoryInformation();
|
new Service::AccessoryInformation();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue