Skip to content

Commit

Permalink
Merge branch 'master' of github.com:nrwiersma/ConfigManager
Browse files Browse the repository at this point in the history
  • Loading branch information
nrwiersma committed Aug 24, 2017
2 parents 98e288f + 404e036 commit 8226157
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 18 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ on the most common IDEs:

## Methods

### getMode
```
Mode getMode()
```
> Gets the current mode, **ap** or **api**.
### setAPName
```
void setAPName(const char *name)
Expand All @@ -74,6 +80,14 @@ void setAPFilename(const char *filename)
```
> Sets the path in SPIFFS to the webpage to be served by the access point.
### setAPTimeout
```
void setAPTimeout(const int timeout)
```
> Sets the access point timeout, in seconds (default 0, no timeout).
>
> **Note:** *The timeout starts when the access point is started, but is evaluated in the loop function.*
### setAPICallback
```
void setAPICallback(std::function<void(ESP8266WebServer*)> callback)
Expand Down
69 changes: 52 additions & 17 deletions src/ConfigManager.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
#include "ConfigManager.h"

const byte DNS_PORT = 53;
const char magicBytes[2] = {'C', 'M'};

const char mimeHTML[] PROGMEM = "text/html";
const char mimeJSON[] PROGMEM = "application/json";
const char mimePlain[] PROGMEM = "text/plain";

Mode ConfigManager::getMode() {
return this->mode;
}

void ConfigManager::setAPName(const char *name) {
this->apName = (char *)name;
}

void ConfigManager::setAPFilename(const char *filename) {
this->apFilename = (char *)filename;
}

void ConfigManager::setAPTimeout(const int timeout) {
this->apTimeout = timeout;
}

void ConfigManager::setWifiConnectRetries(const int retries) {
this->wifiConnectRetries = retries;
}
Expand All @@ -17,15 +31,23 @@ void ConfigManager::setWifiConnectInterval(const int interval) {
this->wifiConnectInterval = interval;
}

void ConfigManager::setAPFilename(const char *filename) {
this->apFilename = (char *)filename;
void ConfigManager::setAPCallback(std::function<void(ESP8266WebServer*)> callback) {
this->apCallback = callback;
}

void ConfigManager::setAPICallback(std::function<void(ESP8266WebServer*)> callback) {
this->apiCallback = callback;
}

void ConfigManager::loop() {
if (mode == ap && apTimeout > 0 && ((millis() - apStart) / 1000) > apTimeout) {
ESP.restart();
}

if (dnsServer) {
dnsServer->processNextRequest();
}

if (server) {
server->handleClient();
}
Expand Down Expand Up @@ -92,8 +114,10 @@ void ConfigManager::handleAPPost() {
strncpy(ssidChar, ssid.c_str(), sizeof(ssidChar));
strncpy(passwordChar, password.c_str(), sizeof(passwordChar));

EEPROM.put(0, ssidChar);
EEPROM.put(32, passwordChar);

EEPROM.put(0, magicBytes);
EEPROM.put(WIFI_OFFSET, ssidChar);
EEPROM.put(WIFI_OFFSET + 32, passwordChar);
EEPROM.commit();

server->send(204, FPSTR(mimePlain), F("Saved. Will attempt to reboot."));
Expand Down Expand Up @@ -176,16 +200,18 @@ bool ConfigManager::wifiConnected() {
}

void ConfigManager::setup() {
char magic[2];
char ssid[32];
char password[64];

Serial.println(F("Reading saved configuration"));

EEPROM.get(0, ssid);
EEPROM.get(32, password);
EEPROM.get(0, magic);
EEPROM.get(WIFI_OFFSET, ssid);
EEPROM.get(WIFI_OFFSET + 32, password);
readConfig();

if (ssid != NULL) {
if (memcmp(magic, magicBytes, 2) == 0) {
WiFi.begin(ssid, password[0] == '\0' ? NULL : password);
if (wifiConnected()) {
Serial.print(F("Connected to "));
Expand All @@ -197,6 +223,9 @@ void ConfigManager::setup() {
startApi();
return;
}
} else {
// We are at a cold start, don't bother timeing out.
apTimeout = 0;
}

startAP();
Expand All @@ -206,6 +235,8 @@ void ConfigManager::startAP() {
const char* headerKeys[] = {"Content-Type"};
size_t headerKeysSize = sizeof(headerKeys)/sizeof(char*);

mode = ap;

Serial.println(F("Starting Access Point"));

IPAddress ip(192, 168, 1, 1);
Expand All @@ -215,55 +246,59 @@ void ConfigManager::startAP() {

delay(500); // Need to wait to get IP

DNSServer dnsServer;
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(DNS_PORT, "*", ip);
dnsServer.reset(new DNSServer);
dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
dnsServer->start(DNS_PORT, "*", ip);

server.reset(new ESP8266WebServer(80));
server->collectHeaders(headerKeys, headerKeysSize);
server->on("/", HTTPMethod::HTTP_GET, std::bind(&ConfigManager::handleAPGet, this));
server->on("/", HTTPMethod::HTTP_POST, std::bind(&ConfigManager::handleAPPost, this));
server->onNotFound(std::bind(&ConfigManager::handleNotFound, this));
server->begin();

while (1) {
dnsServer.processNextRequest();
server->handleClient();
if (apCallback) {
apCallback(server.get());
}

server->begin();

apStart = millis();
}

void ConfigManager::startApi() {
const char* headerKeys[] = {"Content-Type"};
size_t headerKeysSize = sizeof(headerKeys)/sizeof(char*);

mode = api;

server.reset(new ESP8266WebServer(80));
server->collectHeaders(headerKeys, headerKeysSize);
server->on("/", HTTPMethod::HTTP_GET, std::bind(&ConfigManager::handleAPGet, this));
server->on("/", HTTPMethod::HTTP_POST, std::bind(&ConfigManager::handleAPPost, this));
server->on("/settings", HTTPMethod::HTTP_GET, std::bind(&ConfigManager::handleRESTGet, this));
server->on("/settings", HTTPMethod::HTTP_PUT, std::bind(&ConfigManager::handleRESTPut, this));
server->onNotFound(std::bind(&ConfigManager::handleNotFound, this));

if (apiCallback) {
apiCallback(server.get());
}

server->onNotFound(std::bind(&ConfigManager::handleNotFound, this));
server->begin();
}

void ConfigManager::readConfig() {
byte *ptr = (byte *)config;

for (int i = 0; i < configSize; i++) {
*(ptr++) = EEPROM.read(96 + i);
*(ptr++) = EEPROM.read(CONFIG_OFFSET + i);
}
}

void ConfigManager::writeConfig() {
byte *ptr = (byte *)config;

for (int i = 0; i < configSize; i++) {
EEPROM.write(96 + i, *(ptr++));
EEPROM.write(CONFIG_OFFSET + i, *(ptr++));
}
EEPROM.commit();
}
Expand Down
19 changes: 18 additions & 1 deletion src/ConfigManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#include <list>
#include "ArduinoJson.h"

#define WIFI_OFFSET 2
#define CONFIG_OFFSET 98

enum Mode {ap, api};

enum ParameterMode { get, set, both};

/**
Expand Down Expand Up @@ -103,10 +108,13 @@ class ConfigManager {
public:
ConfigManager() {}

Mode getMode();
void setAPName(const char *name);
void setAPFilename(const char *filename);
void setAPTimeout(const int timeout);
void setWifiConnectRetries(const int retries);
void setWifiConnectInterval(const int interval);
void setAPCallback(std::function<void(ESP8266WebServer*)> callback);
void setAPICallback(std::function<void(ESP8266WebServer*)> callback);
void loop();

Expand All @@ -115,7 +123,7 @@ class ConfigManager {
this->config = &config;
this->configSize = sizeof(T);

EEPROM.begin(96 + this->configSize);
EEPROM.begin(CONFIG_OFFSET + this->configSize);

setup();
}
Expand All @@ -137,14 +145,23 @@ class ConfigManager {
void save();

private:
Mode mode;
void *config;
size_t configSize;

char *apName = (char *)"Thing";
char *apFilename = (char *)"/index.html";
int apTimeout = 0;
unsigned long apStart = 0;

int wifiConnectRetries = 20;
int wifiConnectInterval = 500;

std::unique_ptr<DNSServer> dnsServer;
std::unique_ptr<ESP8266WebServer> server;
std::list<BaseParameter*> parameters;

std::function<void(ESP8266WebServer*)> apCallback;
std::function<void(ESP8266WebServer*)> apiCallback;

JsonObject &decodeJson(String jsonString);
Expand Down

0 comments on commit 8226157

Please sign in to comment.