initial commit of C++ back end and react front end
This commit is contained in:
49
src/APSettingsService.cpp
Normal file
49
src/APSettingsService.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <APSettingsService.h>
|
||||
|
||||
APSettingsService::APSettingsService(AsyncWebServer* server, FS* fs) : SettingsService(server, fs, AP_SETTINGS_SERVICE_PATH, AP_SETTINGS_FILE) {
|
||||
}
|
||||
|
||||
APSettingsService::~APSettingsService() {}
|
||||
|
||||
void APSettingsService::loop() {
|
||||
unsigned long now = millis();
|
||||
if (_manageAtMillis <= now){
|
||||
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
||||
if (_provisionMode == AP_MODE_ALWAYS || (_provisionMode == AP_MODE_DISCONNECTED && WiFi.status() != WL_CONNECTED)) {
|
||||
if (currentWiFiMode == WIFI_OFF || currentWiFiMode == WIFI_STA){
|
||||
Serial.println("Starting software access point");
|
||||
WiFi.softAP(_ssid.c_str(), _password.c_str());
|
||||
}
|
||||
} else {
|
||||
if (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA){
|
||||
Serial.println("Stopping software access point");
|
||||
WiFi.softAPdisconnect(true);
|
||||
}
|
||||
}
|
||||
_manageAtMillis = now + MANAGE_NETWORK_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
void APSettingsService::readFromJsonObject(JsonObject& root) {
|
||||
_provisionMode = root["provision_mode"] | AP_MODE_ALWAYS;
|
||||
switch (_provisionMode) {
|
||||
case AP_MODE_ALWAYS:
|
||||
case AP_MODE_DISCONNECTED:
|
||||
case AP_MODE_NEVER:
|
||||
break;
|
||||
default:
|
||||
_provisionMode = AP_MODE_ALWAYS;
|
||||
}
|
||||
_ssid = root["ssid"] | AP_DEFAULT_SSID;
|
||||
_password = root["password"] | AP_DEFAULT_PASSWORD;
|
||||
}
|
||||
|
||||
void APSettingsService::writeToJsonObject(JsonObject& root) {
|
||||
root["provision_mode"] = _provisionMode;
|
||||
root["ssid"] = _ssid;
|
||||
root["password"] = _password;
|
||||
}
|
||||
|
||||
void APSettingsService::onConfigUpdated() {
|
||||
_manageAtMillis = 0;
|
||||
}
|
43
src/APSettingsService.h
Normal file
43
src/APSettingsService.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef APSettingsConfig_h
|
||||
#define APSettingsConfig_h
|
||||
|
||||
#include <IPAddress.h>
|
||||
#include <SettingsService.h>
|
||||
|
||||
#define MANAGE_NETWORK_DELAY 10000
|
||||
|
||||
#define AP_MODE_ALWAYS 0
|
||||
#define AP_MODE_DISCONNECTED 1
|
||||
#define AP_MODE_NEVER 2
|
||||
|
||||
#define AP_DEFAULT_SSID "ssid"
|
||||
#define AP_DEFAULT_PASSWORD "password"
|
||||
|
||||
#define AP_SETTINGS_FILE "/config/apSettings.json"
|
||||
#define AP_SETTINGS_SERVICE_PATH "/apSettings"
|
||||
|
||||
class APSettingsService : public SettingsService {
|
||||
|
||||
public:
|
||||
|
||||
APSettingsService(AsyncWebServer* server, FS* fs);
|
||||
~APSettingsService();
|
||||
|
||||
void loop();
|
||||
|
||||
protected:
|
||||
|
||||
void readFromJsonObject(JsonObject& root);
|
||||
void writeToJsonObject(JsonObject& root);
|
||||
void onConfigUpdated();
|
||||
|
||||
private:
|
||||
|
||||
int _provisionMode;
|
||||
String _ssid;
|
||||
String _password;
|
||||
unsigned long _manageAtMillis;
|
||||
|
||||
};
|
||||
|
||||
#endif // end APSettingsConfig_h
|
19
src/APStatus.cpp
Normal file
19
src/APStatus.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <APStatus.h>
|
||||
|
||||
APStatus::APStatus(AsyncWebServer *server) : _server(server) {
|
||||
_server->on("/apStatus", HTTP_GET, std::bind(&APStatus::apStatus, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void APStatus::apStatus(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||
JsonObject& root = response->getRoot();
|
||||
|
||||
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
||||
root["active"] = (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA);
|
||||
root["ip_address"] = WiFi.softAPIP().toString();
|
||||
root["mac_address"] = WiFi.softAPmacAddress();
|
||||
root["station_num"] = WiFi.softAPgetStationNum();
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
25
src/APStatus.h
Normal file
25
src/APStatus.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef APStatus_h
|
||||
#define APStatus_h
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncJson.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
class APStatus {
|
||||
|
||||
public:
|
||||
|
||||
APStatus(AsyncWebServer *server);
|
||||
|
||||
private:
|
||||
|
||||
AsyncWebServer* _server;
|
||||
|
||||
void apStatus(AsyncWebServerRequest *request);
|
||||
|
||||
};
|
||||
|
||||
#endif // end APStatus_h
|
31
src/AsyncJsonCallbackResponse.h
Normal file
31
src/AsyncJsonCallbackResponse.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _AsyncJsonCallbackResponse_H_
|
||||
#define _AsyncJsonCallbackResponse_H_
|
||||
|
||||
#include <AsyncJson.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
/*
|
||||
* Listens for a response being destroyed and calls a callback during said distruction.
|
||||
* used so we can take action after the response has been rendered to the client.
|
||||
*
|
||||
* Avoids having to fork ESPAsyncWebServer with a callback feature, but not nice!
|
||||
*/
|
||||
|
||||
typedef std::function<void()> AsyncJsonCallback;
|
||||
|
||||
class AsyncJsonCallbackResponse: public AsyncJsonResponse {
|
||||
|
||||
private:
|
||||
|
||||
AsyncJsonCallback _callback;
|
||||
|
||||
public:
|
||||
|
||||
AsyncJsonCallbackResponse(AsyncJsonCallback callback, bool isArray=false) : _callback{callback}, AsyncJsonResponse(isArray) {}
|
||||
~AsyncJsonCallbackResponse() {
|
||||
_callback();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // end _AsyncJsonCallbackResponse_H_
|
115
src/AsyncJsonRequestWebHandler.h
Normal file
115
src/AsyncJsonRequestWebHandler.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#ifndef Async_Json_Request_Web_Handler_H_
|
||||
#define Async_Json_Request_Web_Handler_H_
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#define ASYNC_JSON_REQUEST_DEFAULT_MAX_SIZE 1024
|
||||
#define ASYNC_JSON_REQUEST_MIMETYPE "application/json"
|
||||
|
||||
/*
|
||||
* Handy little utility for dealing with small JSON request body payloads.
|
||||
*
|
||||
* Need to be careful using this as we are somewhat limited by RAM.
|
||||
*
|
||||
* Really only of use where there is a determinate payload size.
|
||||
*/
|
||||
|
||||
typedef std::function<void(AsyncWebServerRequest *request, JsonVariant &json)> JsonRequestCallback;
|
||||
|
||||
class AsyncJsonRequestWebHandler: public AsyncWebHandler {
|
||||
|
||||
private:
|
||||
|
||||
String _uri;
|
||||
WebRequestMethodComposite _method;
|
||||
JsonRequestCallback _onRequest;
|
||||
int _maxContentLength;
|
||||
|
||||
public:
|
||||
|
||||
AsyncJsonRequestWebHandler() :
|
||||
_uri(),
|
||||
_method(HTTP_POST|HTTP_PUT|HTTP_PATCH),
|
||||
_onRequest(NULL),
|
||||
_maxContentLength(ASYNC_JSON_REQUEST_DEFAULT_MAX_SIZE) {}
|
||||
|
||||
~AsyncJsonRequestWebHandler() {}
|
||||
|
||||
void setUri(const String& uri) { _uri = uri; }
|
||||
void setMethod(WebRequestMethodComposite method) { _method = method; }
|
||||
void setMaxContentLength(int maxContentLength) { _maxContentLength = maxContentLength; }
|
||||
void onRequest(JsonRequestCallback fn) { _onRequest = fn; }
|
||||
|
||||
virtual bool canHandle(AsyncWebServerRequest *request) override final {
|
||||
if(!_onRequest)
|
||||
return false;
|
||||
|
||||
if(!(_method & request->method()))
|
||||
return false;
|
||||
|
||||
if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
|
||||
return false;
|
||||
|
||||
if (!request->contentType().equalsIgnoreCase(ASYNC_JSON_REQUEST_MIMETYPE))
|
||||
return false;
|
||||
|
||||
request->addInterestingHeader("ANY");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void handleRequest(AsyncWebServerRequest *request) override final {
|
||||
// no request configured
|
||||
if(!_onRequest) {
|
||||
request->send(404);
|
||||
return;
|
||||
}
|
||||
|
||||
// we have been handed too much data, return a 413 (payload too large)
|
||||
if (request->contentLength() > _maxContentLength) {
|
||||
request->send(413);
|
||||
return;
|
||||
}
|
||||
|
||||
// parse JSON and if possible handle the request
|
||||
if (request->_tempObject) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonVariant json = jsonBuffer.parse((uint8_t *) request->_tempObject);
|
||||
if (json.success()) {
|
||||
_onRequest(request, json);
|
||||
}else{
|
||||
request->send(400);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// fallthrough, we have a null pointer, return 500.
|
||||
// this can be due to running out of memory or never recieving body data.
|
||||
request->send(500);
|
||||
}
|
||||
|
||||
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
|
||||
if (_onRequest) {
|
||||
// don't allocate if data is too large
|
||||
if (total > _maxContentLength){
|
||||
return;
|
||||
}
|
||||
|
||||
// try to allocate memory on first call
|
||||
// NB: the memory allocated here is freed by ~AsyncWebServerRequest
|
||||
if(index == 0 && !request->_tempObject){
|
||||
request->_tempObject = malloc(total);
|
||||
}
|
||||
|
||||
// copy the data into the buffer, if we have a buffer!
|
||||
if (request->_tempObject) {
|
||||
memcpy((uint8_t *) request->_tempObject+index, data, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isRequestHandlerTrivial() override final {
|
||||
return _onRequest ? false : true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // end Async_Json_Request_Web_Handler_H_
|
47
src/AuthSettingsService.cpp
Normal file
47
src/AuthSettingsService.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <AuthSettingsService.h>
|
||||
|
||||
AuthSettingsService::AuthSettingsService(AsyncWebServer* server, FS* fs) : SettingsService(server, fs, AUTH_SETTINGS_SERVICE_PATH, AUTH_SETTINGS_FILE) {
|
||||
_server->on(AUTH_LOGOUT_PATH, HTTP_GET, std::bind(&AuthSettingsService::logout, this, std::placeholders::_1));
|
||||
|
||||
// configure authentication handler
|
||||
_authenticationHandler.setUri(AUTH_AUTHENTICATE_PATH);
|
||||
_authenticationHandler.setMethod(HTTP_POST);
|
||||
_authenticationHandler.onRequest(std::bind(&AuthSettingsService::authenticate, this, std::placeholders::_1, std::placeholders::_2));
|
||||
_server->addHandler(&_authenticationHandler);
|
||||
}
|
||||
|
||||
AuthSettingsService::~AuthSettingsService() {}
|
||||
|
||||
// checks the session is authenticated, refreshes the sessions timeout if so
|
||||
bool AuthSettingsService::authenticated(AsyncWebServerRequest *request){
|
||||
request->send(400);
|
||||
return false;
|
||||
}
|
||||
|
||||
void AuthSettingsService::readFromJsonObject(JsonObject& root){
|
||||
_username = root["username"] | AUTH_DEFAULT_USERNAME;
|
||||
_password = root["password"] | AUTH_DEFAULT_PASSWORD;
|
||||
_sessionTimeout= root["session_timeout"] | AUTH_DEFAULT_SESSION_TIMEOUT;
|
||||
}
|
||||
|
||||
void AuthSettingsService::writeToJsonObject(JsonObject& root){
|
||||
root["username"] = _username;
|
||||
root["password"] = _password;
|
||||
root["session_timeout"] = _sessionTimeout;
|
||||
}
|
||||
|
||||
void AuthSettingsService::logout(AsyncWebServerRequest *request){
|
||||
// revoke the current requests session
|
||||
}
|
||||
|
||||
void AuthSettingsService::authenticate(AsyncWebServerRequest *request, JsonVariant &json){
|
||||
if (json.is<JsonObject>()){
|
||||
JsonObject& credentials = json.as<JsonObject>();
|
||||
if (credentials["username"] == _username && credentials["password"] == _password){
|
||||
// store cookie and write to response
|
||||
}
|
||||
request->send(401);
|
||||
} else{
|
||||
request->send(400);
|
||||
}
|
||||
}
|
56
src/AuthSettingsService.h
Normal file
56
src/AuthSettingsService.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef AuthSettingsService_h
|
||||
#define AuthSettingsService_h
|
||||
|
||||
#include <SettingsService.h>
|
||||
|
||||
#define AUTH_DEFAULT_USERNAME "admin"
|
||||
#define AUTH_DEFAULT_PASSWORD "admin"
|
||||
#define AUTH_DEFAULT_SESSION_TIMEOUT 3600
|
||||
|
||||
#define AUTH_SETTINGS_FILE "/config/authSettings.json"
|
||||
#define AUTH_SETTINGS_SERVICE_PATH "/authSettings"
|
||||
|
||||
#define AUTH_LOGOUT_PATH "/logout"
|
||||
#define AUTH_AUTHENTICATE_PATH "/authenticate"
|
||||
|
||||
// max number of concurrently authenticated clients
|
||||
#define AUTH_MAX_CLIENTS 10
|
||||
|
||||
/*
|
||||
* TODO: Will protect services with a cookie based authentication service.
|
||||
*/
|
||||
|
||||
class AuthSettingsService : public SettingsService {
|
||||
|
||||
public:
|
||||
|
||||
AuthSettingsService(AsyncWebServer* server, FS* fs);
|
||||
~AuthSettingsService();
|
||||
|
||||
// checks the session is authenticated,
|
||||
// refreshes the sessions timeout if found
|
||||
bool authenticated(AsyncWebServerRequest *request);
|
||||
|
||||
protected:
|
||||
|
||||
void readFromJsonObject(JsonObject& root);
|
||||
void writeToJsonObject(JsonObject& root);
|
||||
|
||||
private:
|
||||
|
||||
// callback handler for authentication endpoint
|
||||
AsyncJsonRequestWebHandler _authenticationHandler;
|
||||
|
||||
// only supporting one username at the moment
|
||||
String _username;
|
||||
String _password;
|
||||
|
||||
// session timeout in seconds
|
||||
unsigned int _sessionTimeout;
|
||||
|
||||
void logout(AsyncWebServerRequest *request);
|
||||
void authenticate(AsyncWebServerRequest *request, JsonVariant &json);
|
||||
|
||||
};
|
||||
|
||||
#endif // end AuthSettingsService_h
|
94
src/NTPSettingsService.cpp
Normal file
94
src/NTPSettingsService.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <NTPSettingsService.h>
|
||||
|
||||
NTPSettingsService::NTPSettingsService(AsyncWebServer* server, FS* fs) : SettingsService(server, fs, NTP_SETTINGS_SERVICE_PATH, NTP_SETTINGS_FILE) {
|
||||
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(std::bind(&NTPSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
|
||||
_onStationModeGotIPHandler = WiFi.onStationModeGotIP(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1));
|
||||
|
||||
NTP.onNTPSyncEvent ([this](NTPSyncEvent_t ntpEvent) {
|
||||
_ntpEvent = ntpEvent;
|
||||
_syncEventTriggered = true;
|
||||
});
|
||||
}
|
||||
|
||||
NTPSettingsService::~NTPSettingsService() {}
|
||||
|
||||
void NTPSettingsService::loop() {
|
||||
// detect when we need to re-configure NTP and do it in the main loop
|
||||
if (_reconfigureNTP) {
|
||||
_reconfigureNTP = false;
|
||||
configureNTP();
|
||||
}
|
||||
|
||||
// output sync event to serial
|
||||
if (_syncEventTriggered) {
|
||||
processSyncEvent(_ntpEvent);
|
||||
_syncEventTriggered = false;
|
||||
}
|
||||
|
||||
// keep time synchronized in background
|
||||
now();
|
||||
}
|
||||
|
||||
void NTPSettingsService::readFromJsonObject(JsonObject& root) {
|
||||
_server = root["server"] | NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
|
||||
_interval = root["interval"];
|
||||
|
||||
// validate server is specified, resorting to default
|
||||
_server.trim();
|
||||
if (!_server){
|
||||
_server = NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
|
||||
}
|
||||
|
||||
// make sure interval is in bounds
|
||||
if (_interval < NTP_SETTINGS_MIN_INTERVAL){
|
||||
_interval = NTP_SETTINGS_MIN_INTERVAL;
|
||||
} else if (_interval > NTP_SETTINGS_MAX_INTERVAL) {
|
||||
_interval = NTP_SETTINGS_MAX_INTERVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void NTPSettingsService::writeToJsonObject(JsonObject& root) {
|
||||
root["server"] = _server;
|
||||
root["interval"] = _interval;
|
||||
}
|
||||
|
||||
void NTPSettingsService::onConfigUpdated() {
|
||||
_reconfigureNTP = true;
|
||||
}
|
||||
|
||||
void NTPSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
|
||||
Serial.printf("Got IP address, starting NTP Synchronization\n");
|
||||
_reconfigureNTP = true;
|
||||
}
|
||||
|
||||
void NTPSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
|
||||
Serial.printf("WiFi connection dropped, stopping NTP.\n");
|
||||
|
||||
// stop NTP synchronization, ensuring no re-configuration can take place
|
||||
_reconfigureNTP = false;
|
||||
NTP.stop();
|
||||
}
|
||||
|
||||
void NTPSettingsService::configureNTP() {
|
||||
Serial.println("Configuring NTP...");
|
||||
|
||||
// disable sync
|
||||
NTP.stop();
|
||||
|
||||
// enable sync
|
||||
NTP.begin(_server);
|
||||
NTP.setInterval(_interval);
|
||||
}
|
||||
|
||||
void NTPSettingsService::processSyncEvent(NTPSyncEvent_t ntpEvent) {
|
||||
if (ntpEvent) {
|
||||
Serial.print ("Time Sync error: ");
|
||||
if (ntpEvent == noResponse)
|
||||
Serial.println ("NTP server not reachable");
|
||||
else if (ntpEvent == invalidAddress)
|
||||
Serial.println ("Invalid NTP server address");
|
||||
} else {
|
||||
Serial.print ("Got NTP time: ");
|
||||
Serial.println (NTP.getTimeDateString (NTP.getLastNTPSync ()));
|
||||
}
|
||||
}
|
56
src/NTPSettingsService.h
Normal file
56
src/NTPSettingsService.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef NTPSettingsService_h
|
||||
#define NTPSettingsService_h
|
||||
|
||||
#include <SettingsService.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#include <TimeLib.h>
|
||||
#include <NtpClientLib.h>
|
||||
|
||||
// default time server
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "pool.ntp.org"
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_INTERVAL 3600
|
||||
|
||||
// min poll delay of 60 secs, max 1 day
|
||||
#define NTP_SETTINGS_MIN_INTERVAL 60
|
||||
#define NTP_SETTINGS_MAX_INTERVAL 86400
|
||||
|
||||
#define NTP_SETTINGS_FILE "/config/ntpSettings.json"
|
||||
#define NTP_SETTINGS_SERVICE_PATH "/ntpSettings"
|
||||
|
||||
class NTPSettingsService : public SettingsService {
|
||||
|
||||
public:
|
||||
|
||||
NTPSettingsService(AsyncWebServer* server, FS* fs);
|
||||
~NTPSettingsService();
|
||||
|
||||
void loop();
|
||||
|
||||
protected:
|
||||
|
||||
void readFromJsonObject(JsonObject& root);
|
||||
void writeToJsonObject(JsonObject& root);
|
||||
void onConfigUpdated();
|
||||
|
||||
private:
|
||||
|
||||
WiFiEventHandler _onStationModeDisconnectedHandler;
|
||||
WiFiEventHandler _onStationModeGotIPHandler;
|
||||
|
||||
String _server;
|
||||
int _interval;
|
||||
|
||||
bool _reconfigureNTP = false;
|
||||
bool _syncEventTriggered = false;
|
||||
NTPSyncEvent_t _ntpEvent;
|
||||
|
||||
void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
||||
void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
||||
|
||||
void configureNTP();
|
||||
void processSyncEvent(NTPSyncEvent_t ntpEvent);
|
||||
|
||||
};
|
||||
|
||||
#endif // end NTPSettingsService_h
|
28
src/NTPStatus.cpp
Normal file
28
src/NTPStatus.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <NTPStatus.h>
|
||||
|
||||
NTPStatus::NTPStatus(AsyncWebServer *server) : _server(server) {
|
||||
_server->on("/ntpStatus", HTTP_GET, std::bind(&NTPStatus::ntpStatus, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void NTPStatus::ntpStatus(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||
JsonObject& root = response->getRoot();
|
||||
|
||||
// request time now first, this can sometimes force a sync
|
||||
time_t timeNow = now();
|
||||
timeStatus_t status = timeStatus();
|
||||
time_t lastSync = NTP.getLastNTPSync();
|
||||
root["status"] = (int) status;
|
||||
root["last_sync"] = lastSync;
|
||||
root["server"] = NTP.getNtpServerName();
|
||||
root["interval"] = NTP.getInterval();
|
||||
root["uptime"] = NTP.getUptime();
|
||||
|
||||
// only add now to response if we have successfully synced
|
||||
if (status != timeNotSet){
|
||||
root["now"] = timeNow;
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
26
src/NTPStatus.h
Normal file
26
src/NTPStatus.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef NTPStatus_h
|
||||
#define NTPStatus_h
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncJson.h>
|
||||
#include <TimeLib.h>
|
||||
#include <NtpClientLib.h>
|
||||
|
||||
class NTPStatus {
|
||||
|
||||
public:
|
||||
|
||||
NTPStatus(AsyncWebServer *server);
|
||||
|
||||
private:
|
||||
|
||||
AsyncWebServer* _server;
|
||||
|
||||
void ntpStatus(AsyncWebServerRequest *request);
|
||||
|
||||
};
|
||||
|
||||
#endif // end NTPStatus_h
|
67
src/OTASettingsService.cpp
Normal file
67
src/OTASettingsService.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <OTASettingsService.h>
|
||||
|
||||
OTASettingsService::OTASettingsService(AsyncWebServer* server, FS* fs) : SettingsService(server, fs, OTA_SETTINGS_SERVICE_PATH, OTA_SETTINGS_FILE) {}
|
||||
|
||||
OTASettingsService::~OTASettingsService() {}
|
||||
|
||||
void OTASettingsService::begin() {
|
||||
// load settings
|
||||
SettingsService::begin();
|
||||
|
||||
// configure arduino OTA
|
||||
configureArduinoOTA();
|
||||
}
|
||||
|
||||
void OTASettingsService::loop() {
|
||||
if (_enabled && _arduinoOTA){
|
||||
_arduinoOTA->handle();
|
||||
}
|
||||
}
|
||||
|
||||
void OTASettingsService::onConfigUpdated() {
|
||||
configureArduinoOTA();
|
||||
}
|
||||
|
||||
void OTASettingsService::readFromJsonObject(JsonObject& root) {
|
||||
_enabled = root["enabled"];
|
||||
_port = root["port"];
|
||||
_password = root["password"] | DEFAULT_OTA_PASSWORD;
|
||||
|
||||
// provide defaults
|
||||
if (_port < 0){
|
||||
_port = DEFAULT_OTA_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
void OTASettingsService::writeToJsonObject(JsonObject& root) {
|
||||
root["enabled"] = _enabled;
|
||||
root["port"] = _port;
|
||||
root["password"] = _password;
|
||||
}
|
||||
|
||||
void OTASettingsService::configureArduinoOTA() {
|
||||
delete _arduinoOTA;
|
||||
if (_enabled) {
|
||||
_arduinoOTA = new ArduinoOTAClass;
|
||||
_arduinoOTA->setPort(_port);
|
||||
_arduinoOTA->setPassword(_password.c_str());
|
||||
_arduinoOTA->onStart([]() {
|
||||
Serial.println("Starting");
|
||||
});
|
||||
_arduinoOTA->onEnd([]() {
|
||||
Serial.println("\nEnd");
|
||||
});
|
||||
_arduinoOTA->onProgress([](unsigned int progress, unsigned int total) {
|
||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||
});
|
||||
_arduinoOTA->onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||
});
|
||||
_arduinoOTA->begin();
|
||||
}
|
||||
}
|
44
src/OTASettingsService.h
Normal file
44
src/OTASettingsService.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef OTASettingsService_h
|
||||
#define OTASettingsService_h
|
||||
|
||||
#include <SettingsService.h>
|
||||
#include <ESP8266WiFi.h> // ??
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
// Emergency defaults
|
||||
#define DEFAULT_OTA_PORT 8266
|
||||
#define DEFAULT_OTA_PASSWORD "esp-react"
|
||||
|
||||
#define OTA_SETTINGS_FILE "/config/otaSettings.json"
|
||||
#define OTA_SETTINGS_SERVICE_PATH "/otaSettings"
|
||||
|
||||
class OTASettingsService : public SettingsService {
|
||||
|
||||
public:
|
||||
|
||||
OTASettingsService(AsyncWebServer* server, FS* fs);
|
||||
~OTASettingsService();
|
||||
|
||||
void begin();
|
||||
void loop();
|
||||
|
||||
protected:
|
||||
|
||||
void onConfigUpdated();
|
||||
void readFromJsonObject(JsonObject& root);
|
||||
void writeToJsonObject(JsonObject& root);
|
||||
|
||||
private:
|
||||
|
||||
ArduinoOTAClass *_arduinoOTA;
|
||||
bool _enabled;
|
||||
int _port;
|
||||
String _password;
|
||||
|
||||
void configureArduinoOTA();
|
||||
|
||||
};
|
||||
|
||||
#endif // end NTPSettingsService_h
|
146
src/SettingsService.h
Normal file
146
src/SettingsService.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#ifndef SettingsService_h
|
||||
#define SettingsService_h
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <FS.h>
|
||||
#include <AsyncJson.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncJsonRequestWebHandler.h>
|
||||
#include <AsyncJsonCallbackResponse.h>
|
||||
|
||||
/**
|
||||
* At the moment, not expecting settings service to have to deal with large JSON
|
||||
* files this could be made configurable fairly simply, it's exposed on
|
||||
* AsyncJsonRequestWebHandler with a setter.
|
||||
*/
|
||||
#define MAX_SETTINGS_SIZE 1024
|
||||
|
||||
/*
|
||||
* Abstraction of a service which stores it's settings as JSON in SPIFFS.
|
||||
*/
|
||||
class SettingsService {
|
||||
|
||||
private:
|
||||
|
||||
char const* _filePath;
|
||||
|
||||
AsyncJsonRequestWebHandler _updateHandler;
|
||||
|
||||
bool writeToSPIFFS() {
|
||||
// create and populate a new json object
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
writeToJsonObject(root);
|
||||
|
||||
// serialize it to SPIFFS
|
||||
File configFile = SPIFFS.open(_filePath, "w");
|
||||
|
||||
// failed to open file, return false
|
||||
if (!configFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
root.printTo(configFile);
|
||||
configFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void readFromSPIFFS(){
|
||||
File configFile = SPIFFS.open(_filePath, "r");
|
||||
|
||||
// use defaults if no config found
|
||||
if (configFile) {
|
||||
// Protect against bad data uploaded to SPIFFS
|
||||
// We never expect the config file to get very large, so cap it.
|
||||
size_t size = configFile.size();
|
||||
if (size <= MAX_SETTINGS_SIZE) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.parseObject(configFile);
|
||||
if (root.success()) {
|
||||
readFromJsonObject(root);
|
||||
configFile.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
configFile.close();
|
||||
}
|
||||
|
||||
// If we reach here we have not been successful in loading the config,
|
||||
// hard-coded emergency defaults are now applied.
|
||||
applyDefaultConfig();
|
||||
}
|
||||
|
||||
void fetchConfig(AsyncWebServerRequest *request){
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||
writeToJsonObject(response->getRoot());
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
void updateConfig(AsyncWebServerRequest *request, JsonVariant &json){
|
||||
if (json.is<JsonObject>()){
|
||||
JsonObject& newConfig = json.as<JsonObject>();
|
||||
readFromJsonObject(newConfig);
|
||||
writeToSPIFFS();
|
||||
|
||||
// write settings back with a callback to reconfigure the wifi
|
||||
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();});
|
||||
writeToJsonObject(response->getRoot());
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
} else{
|
||||
request->send(400);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// will serve setting endpoints from here
|
||||
AsyncWebServer* _server;
|
||||
|
||||
// will store and retrieve config from the file system
|
||||
FS* _fs;
|
||||
|
||||
// reads the local config from the
|
||||
virtual void readFromJsonObject(JsonObject& root){}
|
||||
virtual void writeToJsonObject(JsonObject& root){}
|
||||
|
||||
// implement to perform action when config has been updated
|
||||
virtual void onConfigUpdated(){}
|
||||
|
||||
// We assume the readFromJsonObject supplies sensible defaults if an empty object
|
||||
// is supplied, this virtual function allows that to be changed.
|
||||
virtual void applyDefaultConfig(){
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
readFromJsonObject(root);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
SettingsService(AsyncWebServer* server, FS* fs, char const* servicePath, char const* filePath):
|
||||
_server(server), _fs(fs), _filePath(filePath) {
|
||||
|
||||
// configure fetch config handler
|
||||
_server->on(servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
|
||||
|
||||
// configure update settings handler
|
||||
_updateHandler.setUri(servicePath);
|
||||
_updateHandler.setMethod(HTTP_POST);
|
||||
_updateHandler.setMaxContentLength(MAX_SETTINGS_SIZE);
|
||||
_updateHandler.onRequest(std::bind(&SettingsService::updateConfig, this, std::placeholders::_1, std::placeholders::_2));
|
||||
_server->addHandler(&_updateHandler);
|
||||
}
|
||||
|
||||
virtual ~SettingsService() {}
|
||||
|
||||
virtual void begin() {
|
||||
readFromSPIFFS();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // end SettingsService
|
38
src/WiFiScanner.cpp
Normal file
38
src/WiFiScanner.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <WiFiScanner.h>
|
||||
|
||||
WiFiScanner::WiFiScanner(AsyncWebServer *server) : _server(server) {
|
||||
_server->on("/scanNetworks", HTTP_GET, std::bind(&WiFiScanner::scanNetworks, this, std::placeholders::_1));
|
||||
_server->on("/listNetworks", HTTP_GET, std::bind(&WiFiScanner::listNetworks, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void WiFiScanner::scanNetworks(AsyncWebServerRequest *request) {
|
||||
if (WiFi.scanComplete() != -1){
|
||||
WiFi.scanDelete();
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
request->send(202);
|
||||
}
|
||||
|
||||
void WiFiScanner::listNetworks(AsyncWebServerRequest *request) {
|
||||
int numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks > -1){
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||
JsonObject& root = response->getRoot();
|
||||
JsonArray& networks = root.createNestedArray("networks");
|
||||
for (int i=0; i<numNetworks ; i++){
|
||||
JsonObject& network = networks.createNestedObject();
|
||||
network["rssi"] = WiFi.RSSI(i);
|
||||
network["ssid"] = WiFi.SSID(i);
|
||||
network["bssid"] = WiFi.BSSIDstr(i);
|
||||
network["channel"] = WiFi.channel(i);
|
||||
network["encryption_type"] = WiFi.encryptionType(i);
|
||||
network["hidden"] = WiFi.isHidden(i);
|
||||
}
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
} else if (numNetworks == -1){
|
||||
request->send(202);
|
||||
}else{
|
||||
scanNetworks(request);
|
||||
}
|
||||
}
|
26
src/WiFiScanner.h
Normal file
26
src/WiFiScanner.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef WiFiScanner_h
|
||||
#define WiFiScanner_h
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncJson.h>
|
||||
#include <TimeLib.h>
|
||||
|
||||
class WiFiScanner {
|
||||
|
||||
public:
|
||||
|
||||
WiFiScanner(AsyncWebServer *server);
|
||||
|
||||
private:
|
||||
|
||||
AsyncWebServer* _server;
|
||||
|
||||
void scanNetworks(AsyncWebServerRequest *request);
|
||||
void listNetworks(AsyncWebServerRequest *request);
|
||||
|
||||
};
|
||||
|
||||
#endif // end WiFiScanner_h
|
85
src/WiFiSettingsService.cpp
Normal file
85
src/WiFiSettingsService.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <WiFiSettingsService.h>
|
||||
|
||||
WiFiSettingsService::WiFiSettingsService(AsyncWebServer* server, FS* fs) : SettingsService(server, fs, WIFI_SETTINGS_SERVICE_PATH, WIFI_SETTINGS_FILE) {
|
||||
}
|
||||
|
||||
WiFiSettingsService::~WiFiSettingsService() {}
|
||||
|
||||
void WiFiSettingsService::begin() {
|
||||
SettingsService::begin();
|
||||
reconfigureWiFiConnection();
|
||||
}
|
||||
|
||||
void WiFiSettingsService::readFromJsonObject(JsonObject& root){
|
||||
_ssid = root["ssid"] | "";
|
||||
_password = root["password"] | "";
|
||||
_hostname = root["hostname"] | "";
|
||||
_staticIPConfig = root["static_ip_config"] | false;
|
||||
|
||||
// extended settings
|
||||
readIP(root, "local_ip", _localIP);
|
||||
readIP(root, "gateway_ip", _gatewayIP);
|
||||
readIP(root, "subnet_mask", _subnetMask);
|
||||
readIP(root, "dns_ip_1", _dnsIP1);
|
||||
readIP(root, "dns_ip_2", _dnsIP2);
|
||||
|
||||
// Swap around the dns servers if 2 is populated but 1 is not
|
||||
if (_dnsIP1 == 0U && _dnsIP2 != 0U){
|
||||
_dnsIP1 = _dnsIP2;
|
||||
_dnsIP2 = 0U;
|
||||
}
|
||||
|
||||
// Turning off static ip config if we don't meet the minimum requirements
|
||||
// of ipAddress, gateway and subnet. This may change to static ip only
|
||||
// as sensible defaults can be assumed for gateway and subnet
|
||||
if (_staticIPConfig && (_localIP == 0U || _gatewayIP == 0U || _subnetMask == 0U)){
|
||||
_staticIPConfig = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiSettingsService::writeToJsonObject(JsonObject& root){
|
||||
// connection settings
|
||||
root["ssid"] = _ssid;
|
||||
root["password"] = _password;
|
||||
root["hostname"] = _hostname;
|
||||
root["static_ip_config"] = _staticIPConfig;
|
||||
|
||||
// extended settings
|
||||
writeIP(root, "local_ip", _localIP);
|
||||
writeIP(root, "gateway_ip", _gatewayIP);
|
||||
writeIP(root, "subnet_mask", _subnetMask);
|
||||
writeIP(root, "dns_ip_1", _dnsIP1);
|
||||
writeIP(root, "dns_ip_2", _dnsIP2);
|
||||
}
|
||||
|
||||
void WiFiSettingsService::onConfigUpdated() {
|
||||
reconfigureWiFiConnection();
|
||||
}
|
||||
|
||||
void WiFiSettingsService::reconfigureWiFiConnection() {
|
||||
Serial.println("Reconfiguring WiFi...");
|
||||
|
||||
// disconnect and de-configure wifi and software access point
|
||||
WiFi.disconnect(true);
|
||||
|
||||
// configure static ip config for station mode (if set)
|
||||
if (_staticIPConfig) {
|
||||
WiFi.config(_localIP, _gatewayIP, _subnetMask, _dnsIP1, _dnsIP2);
|
||||
}
|
||||
|
||||
// connect to the network
|
||||
WiFi.hostname(_hostname);
|
||||
WiFi.begin(_ssid.c_str(), _password.c_str());
|
||||
}
|
||||
|
||||
void WiFiSettingsService::readIP(JsonObject& root, String key, IPAddress& _ip){
|
||||
if (!root[key] || !_ip.fromString(root[key].as<String>())){
|
||||
_ip = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiSettingsService::writeIP(JsonObject& root, String key, IPAddress& _ip){
|
||||
if (_ip != 0U){
|
||||
root[key] = _ip.toString();
|
||||
}
|
||||
}
|
46
src/WiFiSettingsService.h
Normal file
46
src/WiFiSettingsService.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef WiFiSettingsService_h
|
||||
#define WiFiSettingsService_h
|
||||
|
||||
#include <IPAddress.h>
|
||||
#include <SettingsService.h>
|
||||
|
||||
#define WIFI_SETTINGS_FILE "/config/wifiSettings.json"
|
||||
#define WIFI_SETTINGS_SERVICE_PATH "/wifiSettings"
|
||||
|
||||
class WiFiSettingsService : public SettingsService {
|
||||
|
||||
public:
|
||||
|
||||
WiFiSettingsService(AsyncWebServer* server, FS* fs);
|
||||
~WiFiSettingsService();
|
||||
|
||||
void begin();
|
||||
|
||||
protected:
|
||||
|
||||
void readFromJsonObject(JsonObject& root);
|
||||
void writeToJsonObject(JsonObject& root);
|
||||
void onConfigUpdated();
|
||||
|
||||
void reconfigureWiFiConnection();
|
||||
|
||||
private:
|
||||
// connection settings
|
||||
String _ssid;
|
||||
String _password;
|
||||
String _hostname;
|
||||
bool _staticIPConfig;
|
||||
|
||||
// optional configuration for static IP address
|
||||
IPAddress _localIP;
|
||||
IPAddress _gatewayIP;
|
||||
IPAddress _subnetMask;
|
||||
IPAddress _dnsIP1;
|
||||
IPAddress _dnsIP2;
|
||||
|
||||
void readIP(JsonObject& root, String key, IPAddress& _ip);
|
||||
void writeIP(JsonObject& root, String key, IPAddress& _ip);
|
||||
|
||||
};
|
||||
|
||||
#endif // end WiFiSettingsService_h
|
52
src/WiFiStatus.cpp
Normal file
52
src/WiFiStatus.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <WiFiStatus.h>
|
||||
|
||||
WiFiStatus::WiFiStatus(AsyncWebServer *server) : _server(server) {
|
||||
_server->on("/wifiStatus", HTTP_GET, std::bind(&WiFiStatus::wifiStatus, this, std::placeholders::_1));
|
||||
|
||||
_onStationModeConnectedHandler = WiFi.onStationModeConnected(onStationModeConnected);
|
||||
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(onStationModeDisconnected);
|
||||
_onStationModeGotIPHandler = WiFi.onStationModeGotIP(onStationModeGotIP);
|
||||
}
|
||||
|
||||
void WiFiStatus::onStationModeConnected(const WiFiEventStationModeConnected& event) {
|
||||
Serial.print("WiFi Connected. SSID=");
|
||||
Serial.println(event.ssid);
|
||||
}
|
||||
|
||||
void WiFiStatus::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
|
||||
Serial.print("WiFi Disconnected. Reason code=");
|
||||
Serial.println(event.reason);
|
||||
}
|
||||
|
||||
void WiFiStatus::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
|
||||
Serial.print("WiFi Got IP. localIP=");
|
||||
Serial.print(event.ip);
|
||||
Serial.print(", hostName=");
|
||||
Serial.println(WiFi.hostname());
|
||||
}
|
||||
|
||||
void WiFiStatus::wifiStatus(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||
JsonObject& root = response->getRoot();
|
||||
wl_status_t status = WiFi.status();
|
||||
root["status"] = (uint8_t) status;
|
||||
if (status == WL_CONNECTED){
|
||||
root["local_ip"] = WiFi.localIP().toString();
|
||||
root["rssi"] = WiFi.RSSI();
|
||||
root["ssid"] = WiFi.SSID();
|
||||
root["bssid"] = WiFi.BSSIDstr();
|
||||
root["channel"] = WiFi.channel();
|
||||
root["subnet_mask"] = WiFi.subnetMask().toString();
|
||||
root["gateway_ip"] = WiFi.gatewayIP().toString();
|
||||
IPAddress dnsIP1 = WiFi.dnsIP(0);
|
||||
IPAddress dnsIP2 = WiFi.dnsIP(1);
|
||||
if (dnsIP1 != 0U){
|
||||
root["dns_ip_1"] = dnsIP1.toString();
|
||||
}
|
||||
if (dnsIP2 != 0U){
|
||||
root["dns_ip_2"] = dnsIP2.toString();
|
||||
}
|
||||
}
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
35
src/WiFiStatus.h
Normal file
35
src/WiFiStatus.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef WiFiStatus_h
|
||||
#define WiFiStatus_h
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncJson.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
class WiFiStatus {
|
||||
|
||||
public:
|
||||
|
||||
WiFiStatus(AsyncWebServer *server);
|
||||
|
||||
private:
|
||||
|
||||
AsyncWebServer* _server;
|
||||
|
||||
// handler refrences for logging important WiFi events over serial
|
||||
WiFiEventHandler _onStationModeConnectedHandler;
|
||||
WiFiEventHandler _onStationModeDisconnectedHandler;
|
||||
WiFiEventHandler _onStationModeGotIPHandler;
|
||||
|
||||
// static functions for logging wifi events to the UART
|
||||
static void onStationModeConnected(const WiFiEventStationModeConnected& event);
|
||||
static void onStationModeDisconnected(const WiFiEventStationModeDisconnected& event);
|
||||
static void onStationModeGotIP(const WiFiEventStationModeGotIP& event);
|
||||
|
||||
void wifiStatus(AsyncWebServerRequest *request);
|
||||
|
||||
};
|
||||
|
||||
#endif // end WiFiStatus_h
|
62
src/main.cpp
Normal file
62
src/main.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <Arduino.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <FS.h>
|
||||
#include <WiFiSettingsService.h>
|
||||
#include <WiFiStatus.h>
|
||||
#include <WiFiScanner.h>
|
||||
#include <APSettingsService.h>
|
||||
#include <NTPSettingsService.h>
|
||||
#include <NTPStatus.h>
|
||||
#include <OTASettingsService.h>
|
||||
#include <APStatus.h>
|
||||
|
||||
#define SERIAL_BAUD_RATE 115200
|
||||
|
||||
AsyncWebServer server(80);
|
||||
|
||||
WiFiSettingsService wifiSettingsService = WiFiSettingsService(&server, &SPIFFS);
|
||||
WiFiStatus wifiStatus = WiFiStatus(&server);
|
||||
WiFiScanner wifiScanner = WiFiScanner(&server);
|
||||
APSettingsService apSettingsService = APSettingsService(&server, &SPIFFS);
|
||||
NTPSettingsService ntpSettingsService = NTPSettingsService(&server, &SPIFFS);
|
||||
OTASettingsService otaSettingsService = OTASettingsService(&server, &SPIFFS);
|
||||
NTPStatus ntpStatus = NTPStatus(&server);
|
||||
APStatus apStatus = APStatus(&server);
|
||||
|
||||
void setup() {
|
||||
// Disable wifi config persistance
|
||||
WiFi.persistent(false);
|
||||
|
||||
Serial.begin(SERIAL_BAUD_RATE);
|
||||
SPIFFS.begin();
|
||||
|
||||
// start services
|
||||
ntpSettingsService.begin();
|
||||
otaSettingsService.begin();
|
||||
apSettingsService.begin();
|
||||
wifiSettingsService.begin();
|
||||
|
||||
// Serving static resources from /www/
|
||||
server.serveStatic("/js/", SPIFFS, "/www/js/");
|
||||
server.serveStatic("/css/", SPIFFS, "/www/css/");
|
||||
server.serveStatic("/fonts/", SPIFFS, "/www/fonts/");
|
||||
server.serveStatic("/app/", SPIFFS, "/www/app/");
|
||||
|
||||
// Serving all other get requests with "/www/index.htm"
|
||||
server.onNotFound([](AsyncWebServerRequest *request) {
|
||||
if (request->method() == HTTP_GET) {
|
||||
request->send(SPIFFS, "/www/index.html");
|
||||
} else {
|
||||
request->send(404);
|
||||
}
|
||||
});
|
||||
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
apSettingsService.loop();
|
||||
ntpSettingsService.loop();
|
||||
otaSettingsService.loop();
|
||||
}
|
Reference in New Issue
Block a user