Re-worked network.serialConfigure() and initWifi()

To do:  Re-work apConfigure() and update factory reset so that it only deletes HAP and WIFI data, NOT setup code.
This commit is contained in:
Gregg 2020-10-07 08:20:37 -05:00
parent cf0627e8c9
commit a4b86f4618
6 changed files with 136 additions and 173 deletions

View File

@ -1,5 +1,6 @@
#include <ESPmDNS.h>
#include <nvs_flash.h>
#include <sodium.h>
#include "HAP.h"
@ -11,9 +12,14 @@ void HAPClient::init(){
size_t len; // not used but required to read blobs from NVS
nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS
nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS
nvs_flash_init(); // initialize non-volatile-storage partition in flash
nvs_open("WIFI",NVS_READWRITE,&wifiNVS); // open WIFI data namespace in NVS
nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS
nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS
if(!nvs_get_blob(wifiNVS,"WIFIDATA",NULL,&len)) // if found WiFi data in NVS
nvs_get_blob(wifiNVS,"WIFIDATA",&homeSpan.network.wifiData,&len); // retrieve data
struct { // temporary structure to hold SRP verification code and salt stored in NVS
uint8_t salt[16];

View File

@ -99,21 +99,15 @@ void Span::poll() {
Serial.print("\n");
nvs_flash_init(); // initialize non-volatile-storage partition in flash
HAPClient::init(); // read NVS and load HAP settings
initWifi(); // initialize WiFi
if(!foundWifiCredentials){
Serial.print("WIFI CREDENTIALS DATA NOT FOUND -- PLEASE CONFIGURE BY TYPING 'W <RETURN>' OR PRESS CONTROL BUTTON FOR 3 SECONDS TO START ACCESS POINT.\n\n");
statusLED.start(LED_WIFI_NEEDED);
} else
if(!HAPClient::nAdminControllers()){
Serial.print("DEVICE NOT YET PAIRED -- PLEASE PAIR WITH HOMEKIT APP\n\n");
statusLED.start(LED_PAIRING_NEEDED);
if(strlen(network.wifiData.ssid)>0){
initWifi();
} else {
statusLED.on();
Serial.print("*** WIFI CREDENTIALS DATA NOT FOUND -- PLEASE CONFIGURE BY TYPING 'W <RETURN>' OR PRESS CONTROL BUTTON FOR 3 SECONDS TO START ACCESS POINT.\n\n");
statusLED.start(LED_WIFI_NEEDED);
}
controlButton.reset();
Serial.print(displayName);
@ -121,8 +115,7 @@ void Span::poll() {
isInitialized=true;
}
if(foundWifiCredentials && WiFi.status()!=WL_CONNECTED){
Serial.print("*** LOST WIFI CONNECTION! ***\n\n");
if(strlen(network.wifiData.ssid)>0 && WiFi.status()!=WL_CONNECTED){
initWifi();
}
@ -225,12 +218,6 @@ int Span::getFreeSlot(){
void Span::initWifi(){
size_t len; // not used but required to read blobs from NVS
if(nvs_get_blob(HAPClient::wifiNVS,"WIFIDATA",NULL,&len)){ // WiFi data not stored
return;
}
char id[18]; // create string version of Accessory ID for MDNS broadcast
memcpy(id,HAPClient::accessory.ID,17); // copy ID bytes
id[17]='\0'; // add terminating null
@ -241,6 +228,93 @@ void Span::initWifi(){
char hostName[nChars+1];
sprintf(hostName,"%s-%.2s%.2s%.2s%.2s%.2s%.2s",hostNameBase,id,id+3,id+6,id+9,id+12,id+15);
int nTries=0;
statusLED.start(LED_WIFI_CONNECTING);
controlButton.reset();
while(WiFi.status()!=WL_CONNECTED){
Serial.print("Connecting to: ");
Serial.print(network.wifiData.ssid);
Serial.print("... ");
nTries++;
if(WiFi.begin(network.wifiData.ssid,network.wifiData.pwd)!=WL_CONNECTED){
int delayTime=nTries%6?5000:60000;
char buf[8]="";
Serial.print("Can't connect. Re-trying in ");
Serial.print(delayTime/1000);
Serial.print(" seconds. Type 'X <return>' or press Control Button for 3 seconds to terminate search and delete WiFi credentials...");
long sTime=millis();
while(millis()-sTime<delayTime){
if(controlButton.triggered(9999,3000) || (Serial.available() && readSerial(buf,1) && (buf[0]=='X'))){
Serial.print(" TERMINATED!\n");
processSerialCommand("X"); // DELETE WiFi Data
return;
}
}
}
Serial.print("\n");
} // WiFi not yet connected
Serial.print("Success! IP: ");
Serial.print(WiFi.localIP());
Serial.print("\n");
Serial.print("\nStarting MDNS...\n");
Serial.print("Broadcasting as: ");
Serial.print(hostName);
Serial.print(".local (");
Serial.print(displayName);
Serial.print(" / ");
Serial.print(modelName);
Serial.print(")\n");
MDNS.begin(hostName); // set server host name (.local implied)
MDNS.setInstanceName(displayName); // set server display name
MDNS.addService("_hap","_tcp",80); // advertise HAP service on HTTP port (80)
// add MDNS (Bonjour) TXT records for configurable as well as fixed values (HAP Table 6-7)
char cNum[16];
sprintf(cNum,"%d",hapConfig.configNumber);
mdns_service_txt_item_set("_hap","_tcp","c#",cNum); // Accessory Current Configuration Number (updated whenever config of HAP Accessory Attribute Database is updated)
mdns_service_txt_item_set("_hap","_tcp","md",modelName); // Accessory Model Name
mdns_service_txt_item_set("_hap","_tcp","ci",category); // Accessory Category (HAP Section 13.1)
mdns_service_txt_item_set("_hap","_tcp","id",id); // string version of Accessory ID in form XX:XX:XX:XX:XX:XX (HAP Section 5.4)
mdns_service_txt_item_set("_hap","_tcp","ff","0"); // HAP Pairing Feature flags. MUST be "0" to specify Pair Setup method (HAP Table 5-3) without MiFi Authentification
mdns_service_txt_item_set("_hap","_tcp","pv","1.1"); // HAP version - MUST be set to "1.1" (HAP Section 6.6.3)
mdns_service_txt_item_set("_hap","_tcp","s#","1"); // HAP current state - MUST be set to "1"
if(!HAPClient::nAdminControllers()) // Accessory is not yet paired
mdns_service_txt_item_set("_hap","_tcp","sf","1"); // set Status Flag = 1 (Table 6-8)
else
mdns_service_txt_item_set("_hap","_tcp","sf","0"); // set Status Flag = 0
Serial.print("\nStarting Web (HTTP) Server supporting up to ");
Serial.print(maxConnections);
Serial.print(" simultaneous connections...\n\n");
hapServer.begin();
if(!HAPClient::nAdminControllers()){
Serial.print("DEVICE NOT YET PAIRED -- PLEASE PAIR WITH HOMEKIT APP\n\n");
statusLED.start(LED_PAIRING_NEEDED);
} else {
statusLED.on();
}
/*
size_t len; // not used but required to read blobs from NVS
if(nvs_get_blob(HAPClient::wifiNVS,"WIFIDATA",NULL,&len)){ // WiFi data not stored
return;
}
if(!nvs_get_blob(HAPClient::wifiNVS,"WIFIDATA",NULL,&len)){ // if found WiFi data in NVS
nvs_get_blob(HAPClient::wifiNVS,"WIFIDATA",&network.wifiData,&len); // retrieve data
@ -316,77 +390,7 @@ void Span::initWifi(){
ESP.restart(); // re-start device
} // configure network
int nTries=0;
statusLED.start(LED_WIFI_CONNECTING);
controlButton.reset();
while(WiFi.status()!=WL_CONNECTED){
Serial.print("Connecting to: ");
Serial.print(network.wifiData.ssid);
Serial.print("... ");
nTries++;
if(WiFi.begin(network.wifiData.ssid,network.wifiData.pwd)!=WL_CONNECTED){
int delayTime=nTries%6?5000:60000;
char buf[8]="";
Serial.print("Can't connect. Re-trying in ");
Serial.print(delayTime/1000);
Serial.print(" seconds. Type 'W <return>' or press Control Button for 3 seconds to reset WiFi data...\n");
long sTime=millis();
while(millis()-sTime<delayTime){
if(controlButton.triggered(9999,3000) || (Serial.available() && readSerial(buf,1) && (buf[0]=='W'))){
processSerialCommand("W"); // DELETE WiFi Data
return;
}
}
}
} // WiFi not yet connected
Serial.print("Success! IP: ");
Serial.print(WiFi.localIP());
Serial.print("\n");
Serial.print("\nStarting MDNS...\n");
Serial.print("Broadcasting as: ");
Serial.print(hostName);
Serial.print(".local (");
Serial.print(displayName);
Serial.print(" / ");
Serial.print(modelName);
Serial.print(")\n");
MDNS.begin(hostName); // set server host name (.local implied)
MDNS.setInstanceName(displayName); // set server display name
MDNS.addService("_hap","_tcp",80); // advertise HAP service on HTTP port (80)
// add MDNS (Bonjour) TXT records for configurable as well as fixed values (HAP Table 6-7)
char cNum[16];
sprintf(cNum,"%d",hapConfig.configNumber);
mdns_service_txt_item_set("_hap","_tcp","c#",cNum); // Accessory Current Configuration Number (updated whenever config of HAP Accessory Attribute Database is updated)
mdns_service_txt_item_set("_hap","_tcp","md",modelName); // Accessory Model Name
mdns_service_txt_item_set("_hap","_tcp","ci",category); // Accessory Category (HAP Section 13.1)
mdns_service_txt_item_set("_hap","_tcp","id",id); // string version of Accessory ID in form XX:XX:XX:XX:XX:XX (HAP Section 5.4)
mdns_service_txt_item_set("_hap","_tcp","ff","0"); // HAP Pairing Feature flags. MUST be "0" to specify Pair Setup method (HAP Table 5-3) without MiFi Authentification
mdns_service_txt_item_set("_hap","_tcp","pv","1.1"); // HAP version - MUST be set to "1.1" (HAP Section 6.6.3)
mdns_service_txt_item_set("_hap","_tcp","s#","1"); // HAP current state - MUST be set to "1"
if(!HAPClient::nAdminControllers()) // Accessory is not yet paired
mdns_service_txt_item_set("_hap","_tcp","sf","1"); // set Status Flag = 1 (Table 6-8)
else
mdns_service_txt_item_set("_hap","_tcp","sf","0"); // set Status Flag = 0
Serial.print("\nStarting Web (HTTP) Server supporting up to ");
Serial.print(maxConnections);
Serial.print(" simultaneous connections...\n\n");
hapServer.begin();
statusLED.stop();
*/
} // initWiFi
@ -509,10 +513,21 @@ void Span::processSerialCommand(char *c){
case 'W': {
network.serialConfigure();
nvs_set_blob(HAPClient::wifiNVS,"WIFIDATA",&network.wifiData,sizeof(network.wifiData)); // update data
nvs_commit(HAPClient::wifiNVS); // commit to NVS
Serial.print("\n*** Credentials saved!\n\n");
}
break;
case 'X': {
nvs_erase_all(HAPClient::wifiNVS);
nvs_commit(HAPClient::wifiNVS);
sprintf(network.wifiData.ssid,"");
WiFi.disconnect();
Serial.print("\n** WIFI Network Data DELETED **\n\n");
Serial.print("\n*** WIFI CREDENTIALS DATA NOT FOUND -- PLEASE CONFIGURE BY TYPING 'W <RETURN>' OR PRESS CONTROL BUTTON FOR 3 SECONDS TO START ACCESS POINT.\n\n");
statusLED.start(LED_WIFI_NEEDED);
}
break;
@ -584,7 +599,7 @@ void Span::processSerialCommand(char *c){
Serial.print(" d - print attributes database\n");
Serial.print(" i - print detailed info about configuration\n");
Serial.print(" U - unpair device by deleting all Controller data\n");
Serial.print(" W - delete stored WiFi data\n");
Serial.print(" X - disconnect from WiFi and delete WiFi credentials\n");
Serial.print(" H - delete stored HomeKit Pairing data and restart\n");
Serial.print(" F - delete all stored data (Factory Reset) and restart\n");
Serial.print(" ? - print this list of commands\n");

View File

@ -53,7 +53,6 @@ struct Span{
char category[3]=""; // category ID of primary accessory - broadcast as Bonjour field "ci" (HAP Section 13)
unsigned long snapTime; // current time (in millis) snapped before entering Service loops() or updates()
boolean isInitialized=false; // flag indicating HomeSpan has been initialized
boolean foundWifiCredentials=false; // flag indicating whether or not WiFi credentials data is found in NVS
int nFatalErrors=0; // number of fatal errors in user-defined configuration
String configLog="\n*** Config Log ***\n\n"; // log of configuration process, including any errors

View File

@ -34,13 +34,25 @@ void Network::scan(){
///////////////////////////////
boolean Network::serialConfigure(){
void Network::serialConfigure(){
sprintf(wifiData.ssid,"");
sprintf(wifiData.pwd,"");
Serial.print("*** WiFi Setup - Scanning for Networks...\n\n");
scan(); // scan for networks
for(int i=0;i<numSSID;i++){
Serial.print(" ");
Serial.print(i+1);
Serial.print(") ");
Serial.print(ssidList[i]);
Serial.print("\n");
}
while(!strlen(wifiData.ssid)){
Serial.print(">>> WiFi SSID: ");
Serial.print("\n>>> WiFi SSID: ");
readSerial(wifiData.ssid,MAX_SSID);
if(atoi(wifiData.ssid)>0 && atoi(wifiData.ssid)<=numSSID){
strcpy(wifiData.ssid,ssidList[atoi(wifiData.ssid)-1]);
@ -56,76 +68,7 @@ boolean Network::serialConfigure(){
Serial.print("\n");
}
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
while(WiFi.status()!=WL_CONNECTED){
Serial.print("\nConnecting to: ");
Serial.print(wifiData.ssid);
Serial.print("... ");
if(WiFi.begin(wifiData.ssid,wifiData.pwd)!=WL_CONNECTED){
char buf[8]="";
Serial.print("Can't connect. Re-trying in 5 seconds. Type 'X <return>' to cancel...");
long sTime=millis();
while(millis()-sTime<5000){
if(Serial.available()){
readSerial(buf,1);
if(buf[0]=='X'){
Serial.print("Canceled!\n\n");
return(0);
}
}
}
}
} // WiFi not yet connected
Serial.print("Success! IP: ");
Serial.print(WiFi.localIP());
Serial.print("\n\n");
homeSpan.statusLED.start(LED_INPUT_NEEDED);
boolean okay=false;
Serial.print("Specify new 8-digit Setup Code or leave blank to retain existing code...\n\n");
while(!okay){
Serial.print("Setup Code: ");
sprintf(setupCode,"");
readSerial(setupCode,8);
if(strlen(setupCode)==0){
okay=true;
Serial.print("(skipping)\n\n");
} else {
Serial.print(setupCode);
int n=0;
while(setupCode[n]!='\0' && setupCode[n]>='0' && setupCode[n]<='9')
n++;
if(n<8)
Serial.print("\n** Invalid format!\n\n");
else if(!allowedCode(setupCode))
Serial.print("\n** Disallowed code!\n\n");
else {
Serial.print(" Accepted!\n\n");
okay=true;
}
} // if Setup Code not blank
} // while !okay
char k[2]="";
while(k[0]!='y' && k[0]!='n'){
Serial.print("Confirm settings (y/n)? ");
readSerial(k,1);
Serial.print(k);
Serial.print("\n");
}
Serial.print("\n");
return(k[0]=='y');
return;
}
///////////////////////////////

View File

@ -29,14 +29,14 @@ struct Network {
int apStatus; // tracks access point status (0=timed-out, -1=cancel, 1=save)
struct {
char ssid[MAX_SSID+1];
char pwd[MAX_PWD+1];
char ssid[MAX_SSID+1]="";
char pwd[MAX_PWD+1]="";
} wifiData;
char setupCode[8+1];
void scan(); // scan for WiFi networks and save only those with unique SSIDs
boolean serialConfigure(); // configure homeSpan WiFi and Setup Code from Serial Monitor; return 1=save settings, 0=cancel settings
void serialConfigure(); // configure homeSpan WiFi from serial monitor
boolean allowedCode(char *s); // checks if Setup Code is allowed (HAP defines a list of disallowed codes)
void apConfigure(char *hostName); // configure homeSpan WiFi and Setup Code using temporary Captive Access Point 'hostName'; only returns if sucessful, else ESP restarts
void processRequest(char *body, char *formData); // process the HTTP request

View File

@ -33,8 +33,8 @@
/////////////////////////////////////////////////////
// STATUS LED SETTINGS //
#define LED_WIFI_NEEDED 500,0.3,1,3000 // slow single-blink
#define LED_PAIRING_NEEDED 1000,0.9 // drop-out
#define LED_WIFI_NEEDED 3000,0.05 // slow single-blink
#define LED_PAIRING_NEEDED 300,0.5,2,2550 // slow double-blink
#define LED_ALERT 100 // rapid flashing
#define LED_WIFI_CONNECTING 2000 // slow flashing
#define LED_INPUT_NEEDED 500 // medium flashing