NVS support for credential storage #119

pull/123/head
Hieromon Ikasamo 6 years ago
parent 0ad6253ec6
commit fc9b1e221d
  1. 50
      src/AutoConnectCredential.cpp
  2. 43
      src/AutoConnectCredential.h

@ -9,7 +9,7 @@
#include "AutoConnectCredential.h" #include "AutoConnectCredential.h"
#if defined(ARDUINO_ARCH_ESP8266) #if AC_CREDENTIAL_PREFERENCES == 0
#define AC_HEADERSIZE ((int)(_offset + sizeof(AC_IDENTIFIER) - 1 + sizeof(uint8_t) + sizeof(uint16_t))) #define AC_HEADERSIZE ((int)(_offset + sizeof(AC_IDENTIFIER) - 1 + sizeof(uint8_t) + sizeof(uint16_t)))
/** /**
@ -291,7 +291,7 @@ void AutoConnectCredential::_retrieveEntry(char* ssid, char* password, uint8_t*
bssid[i] = _eeprom->read(_dp++); bssid[i] = _eeprom->read(_dp++);
} }
#elif defined(ARDUINO_ARCH_ESP32) #else
/** /**
* AutoConnectCredential constructor takes the available count of saved * AutoConnectCredential constructor takes the available count of saved
@ -361,19 +361,16 @@ bool AutoConnectCredential::del(const char* ssid) {
* the specified SSID was not found. * the specified SSID was not found.
*/ */
int8_t AutoConnectCredential::load(const char* ssid, struct station_config* config) { int8_t AutoConnectCredential::load(const char* ssid, struct station_config* config) {
decltype(_credit)::iterator it = _credit.find(String(ssid));
if (it != _credit.end()) {
_obtain(it, config);
// Determine the number in entries // Determine the number in entries
int8_t en = 0; int8_t en = 0;
for (decltype(_credit)::iterator se = _credit.begin(), e = _credit.end(); se != e; ++se) { for (decltype(_credit)::iterator it = _credit.begin(), e = _credit.end(); it != e; ++it) {
if (it == se) String key = it->first;
break; if (!strcmp(ssid, key.c_str())) {
en++; _obtain(it, config);
}
return en; return en;
} }
en++;
}
return -1; return -1;
} }
@ -435,6 +432,10 @@ bool AutoConnectCredential::_add(const station_config_t* config) {
memcpy(credtBody.bssid, config->bssid, sizeof(AC_CREDTBODY_t::bssid)); memcpy(credtBody.bssid, config->bssid, sizeof(AC_CREDTBODY_t::bssid));
std::pair<AC_CREDT_t::iterator, bool> rc = _credit.insert(std::make_pair(ssid, credtBody)); std::pair<AC_CREDT_t::iterator, bool> rc = _credit.insert(std::make_pair(ssid, credtBody));
_entries = _credit.size(); _entries = _credit.size();
#ifdef AC_DBG
if (!rc.second)
AC_DBG("Failed to save a credential %s\n", config->ssid);
#endif
return rc.second; return rc.second;
} }
return false; return false;
@ -446,30 +447,27 @@ bool AutoConnectCredential::_add(const station_config_t* config) {
size_t AutoConnectCredential::_commit(void) { size_t AutoConnectCredential::_commit(void) {
AC_CREDTBODY_t credtBody; AC_CREDTBODY_t credtBody;
String ssid; String ssid;
size_t sz = 0;
size_t psz = 0;
// Calculate the container size for saving to NVS.
// Calculate the serialization size for each entry and add the size of 'e' with the size of 'ss' to it. // Calculate the serialization size for each entry and add the size of 'e' with the size of 'ss' to it.
size_t sz = 0;
for (const auto& credt : _credit) { for (const auto& credt : _credit) {
ssid = credt.first; ssid = credt.first;
credtBody = credt.second; credtBody = credt.second;
sz += ssid.length() + sizeof('\0') + credtBody.password.length() + sizeof('\0') + sizeof(AC_CREDTBODY_t::bssid); sz += ssid.length() + sizeof('\0') + credtBody.password.length() + sizeof('\0') + sizeof(AC_CREDTBODY_t::bssid);
} }
_entries = _credit.size();
// When the entry is not empty, the size of container terminator as '\0' must be added. // When the entry is not empty, the size of container terminator as '\0' must be added.
_containSize = sz + (_entries ? sizeof('\0') : 0); _containSize = sz + (_entries ? sizeof('\0') : 0);
// Add size of 'e' and 'ss' field. // Calculate the nvs pool size for saving to NVS. Add size of 'e' and 'ss' field.
psz = _containSize + sizeof(uint8_t) + sizeof(uint16_t); size_t psz = _containSize + sizeof(uint8_t) + sizeof(uint16_t);
// Dump container to serialization pool and write it back to NVS. // Dump container to serialization pool and write it back to NVS.
uint8_t* credtPool = (uint8_t*)malloc(psz); uint8_t* credtPool = (uint8_t*)malloc(psz);
if (credtPool) { if (credtPool) {
credtPool[0] = _entries; // 'e' uint16_t dp = 0;
credtPool[1] = (uint8_t)((uint16_t)psz & 0x00ff); // 'ss' low byte credtPool[dp++] = _entries; // 'e'
credtPool[2] = (uint8_t)((uint16_t)psz >> 8); // 'ss' high byte credtPool[dp++] = (uint8_t)(psz & 0x00ff); // 'ss' low byte
credtPool[dp++] = (uint8_t)(psz >> 8); // 'ss' high byte
// Starts dump of credential entries // Starts dump of credential entries
uint16_t dp = 3;
for (const auto& credt : _credit) { for (const auto& credt : _credit) {
ssid = credt.first; // Retrieve SSID ssid = credt.first; // Retrieve SSID
credtBody = credt.second; // Retrieve an entry credtBody = credt.second; // Retrieve an entry
@ -517,9 +515,9 @@ uint8_t AutoConnectCredential::_import(void) {
if (credtPool) { if (credtPool) {
_pref->getBytes(AC_CREDENTIAL_NVSKEY, static_cast<void*>(credtPool), psz); _pref->getBytes(AC_CREDENTIAL_NVSKEY, static_cast<void*>(credtPool), psz);
_credit.clear(); _credit.clear();
cn = credtPool[0]; // Retrieve 'e' uint16_t dp = 0;
_containSize = credtPool[1] + (uint16_t)(credtPool[2] << 8); // Retrieve 'ss' cn = credtPool[dp++]; // Retrieve 'e'
uint16_t dp = sizeof(uint8_t) + sizeof(uint16_t); _containSize = (uint16_t)credtPool[dp++] + (uint16_t)credtPool[dp++] << 8; // Retrieve size of 'ss'
// Starts import // Starts import
while (dp < psz - sizeof('\0')) { while (dp < psz - sizeof('\0')) {
AC_CREDTBODY_t credtBody; AC_CREDTBODY_t credtBody;
@ -530,10 +528,10 @@ uint8_t AutoConnectCredential::_import(void) {
credtBody.password = String(reinterpret_cast<const char*>(&credtPool[dp])); credtBody.password = String(reinterpret_cast<const char*>(&credtPool[dp]));
// BSSID // BSSID
dp += credtBody.password.length() + sizeof('\0'); dp += credtBody.password.length() + sizeof('\0');
for (uint8_t ep = 0; ep < sizeof(AC_CREDTBODY_t::bssid); ep++) memcpy(credtBody.bssid, &credtPool[dp], sizeof(AC_CREDTBODY_t::bssid));
credtBody.bssid[ep] = credtPool[dp++];
// Make an entry // Make an entry
_credit.insert(std::make_pair(ssid, credtBody)); _credit.insert(std::make_pair(ssid, credtBody));
dp += sizeof(AC_CREDTBODY_t::bssid);
} }
free(credtPool); free(credtPool);
} }

@ -10,18 +10,41 @@
#ifndef _AUTOCONNECTCREDENTIAL_H_ #ifndef _AUTOCONNECTCREDENTIAL_H_
#define _AUTOCONNECTCREDENTIAL_H_ #define _AUTOCONNECTCREDENTIAL_H_
// The AUTOCONNECT_USE_PREFERENCES macro indicates which classes apply
// to the credentials storage structure either EEPROM or Preferences.
// It is a valid indicator only for ESP32.
// Undefine this macro, it maintains backward compatibility by applying
// EEPROM to the credentials storage class in the arduino-esp32 core
// v1.0.2 and earlier.
#define AUTOCONNECT_USE_PREFERENCES
#include <Arduino.h> #include <Arduino.h>
#include <memory> #include <memory>
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
extern "C" { extern "C" {
#include <user_interface.h> #include <user_interface.h>
} }
#define NO_GLOBAL_EEPROM #define AC_CREDENTIAL_PREFERENCES 0
#include <EEPROM.h>
#elif defined(ARDUINO_ARCH_ESP32) #elif defined(ARDUINO_ARCH_ESP32)
#include <map>
#include <esp_wifi.h> #include <esp_wifi.h>
struct station_config {
uint8_t ssid[32];
uint8_t password[64];
uint8_t bssid_set;
uint8_t bssid[6];
wifi_fast_scan_threshold_t threshold;
};
#ifdef AUTOCONNECT_USE_PREFERENCES
#define AC_CREDENTIAL_PREFERENCES 1
#include <map>
#include <Preferences.h> #include <Preferences.h>
#else
#define AC_CREDENTIAL_PREFERENCES 0
#endif
#if AC_CREDENTIAL_PREFERENCES == 0
#define NO_GLOBAL_EEPROM
#include <EEPROM.h>
#endif
#endif #endif
/** /**
@ -58,7 +81,8 @@ class AutoConnectCredentialBase {
uint16_t _containSize; /**< Container size */ uint16_t _containSize; /**< Container size */
}; };
#if defined(ARDUINO_ARCH_ESP8266) #if AC_CREDENTIAL_PREFERENCES == 0
// #pragma message "AutoConnectCredential applies the EEPROM"
/** AutoConnectCredential class using EEPROM for ESP8266 */ /** AutoConnectCredential class using EEPROM for ESP8266 */
class AutoConnectCredential : public AutoConnectCredentialBase { class AutoConnectCredential : public AutoConnectCredentialBase {
@ -83,19 +107,12 @@ class AutoConnectCredential : public AutoConnectCredentialBase {
std::unique_ptr<EEPROMClass> _eeprom; /**< shared EEPROM class */ std::unique_ptr<EEPROMClass> _eeprom; /**< shared EEPROM class */
}; };
#elif defined(ARDUINO_ARCH_ESP32) #else
// #pragma message "AutoConnectCredential applies the Preferences"
#define AC_CREDENTIAL_NVSNAME AC_IDENTIFIER #define AC_CREDENTIAL_NVSNAME AC_IDENTIFIER
#define AC_CREDENTIAL_NVSKEY AC_CREDENTIAL_NVSNAME #define AC_CREDENTIAL_NVSKEY AC_CREDENTIAL_NVSNAME
struct station_config {
uint8_t ssid[32];
uint8_t password[64];
uint8_t bssid_set;
uint8_t bssid[6];
wifi_fast_scan_threshold_t threshold;
};
/** AutoConnectCredential class using Preferences for ESP32 */ /** AutoConnectCredential class using Preferences for ESP32 */
class AutoConnectCredential : public AutoConnectCredentialBase { class AutoConnectCredential : public AutoConnectCredentialBase {
public: public:

Loading…
Cancel
Save