🛜 Simplify wifi services
This commit is contained in:
@@ -21,9 +21,6 @@ ESP32SvelteKit::ESP32SvelteKit(PsychicHttpServer *server, unsigned int numberEnd
|
||||
_taskManager(),
|
||||
_featureService(server),
|
||||
_securitySettingsService(server, &ESPFS),
|
||||
_wifiSettingsService(server, &ESPFS, &_securitySettingsService, &_socket),
|
||||
_wifiScanner(server, &_securitySettingsService),
|
||||
_wifiStatus(server, &_securitySettingsService),
|
||||
_apSettingsService(server, &ESPFS, &_securitySettingsService),
|
||||
_apStatus(server, &_securitySettingsService, &_apSettingsService),
|
||||
_socket(server, &_securitySettingsService, AuthenticationPredicates::IS_AUTHENTICATED),
|
||||
@@ -72,14 +69,12 @@ void ESP32SvelteKit::begin() {
|
||||
ESP_LOGI("Running Firmware Version: %s", APP_VERSION);
|
||||
ESPFS.begin(true);
|
||||
|
||||
_wifiSettingsService.initWiFi();
|
||||
startServices();
|
||||
|
||||
setupServer();
|
||||
|
||||
setupMDNS();
|
||||
|
||||
startServices();
|
||||
|
||||
ESP_LOGV("ESP32SvelteKit", "Starting loop task");
|
||||
_taskManager.createTask(this->_loopImpl, "Spot main", 4096, this, 2, NULL, ESP32SVELTEKIT_RUNNING_CORE);
|
||||
}
|
||||
@@ -88,6 +83,17 @@ void ESP32SvelteKit::setupServer() {
|
||||
_server->config.max_uri_handlers = _numberEndpoints;
|
||||
_server->listen(80);
|
||||
|
||||
_server->on("/api/wifi/scan", HTTP_GET, _wifiService.handleScan);
|
||||
_server->on("/api/wifi/networks", HTTP_GET,
|
||||
[this](PsychicRequest *request) { return _wifiService.getNetworks(request); });
|
||||
_server->on("/api/wifi/sta/status", HTTP_GET,
|
||||
[this](PsychicRequest *request) { return _wifiService.getNetworkStatus(request); });
|
||||
_server->on("/api/wifi/sta/settings", HTTP_GET,
|
||||
[this](PsychicRequest *request) { return _wifiService.endpoint.getState(request); });
|
||||
_server->on("/api/wifi/sta/settings", HTTP_POST, [this](PsychicRequest *request, JsonVariant &json) {
|
||||
return _wifiService.endpoint.handleStateUpdate(request, json);
|
||||
});
|
||||
|
||||
#ifdef EMBED_WWW
|
||||
ESP_LOGV("ESP32SvelteKit", "Registering routes from PROGMEM static resources");
|
||||
WWWData::registerRoutes([&](const String &uri, const String &contentType, const uint8_t *content, size_t len) {
|
||||
@@ -140,7 +146,7 @@ void ESP32SvelteKit::setupServer() {
|
||||
|
||||
void ESP32SvelteKit::setupMDNS() {
|
||||
ESP_LOGV("ESP32SvelteKit", "Starting MDNS");
|
||||
MDNS.begin(_wifiSettingsService.getHostname().c_str());
|
||||
MDNS.begin(_wifiService.getHostname());
|
||||
MDNS.setInstanceName(_appName);
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("ws", "tcp", 80);
|
||||
@@ -148,6 +154,7 @@ void ESP32SvelteKit::setupMDNS() {
|
||||
}
|
||||
|
||||
void ESP32SvelteKit::startServices() {
|
||||
_wifiService.begin();
|
||||
_apStatus.begin();
|
||||
_socket.begin();
|
||||
_apSettingsService.begin();
|
||||
@@ -155,9 +162,6 @@ void ESP32SvelteKit::startServices() {
|
||||
_featureService.begin();
|
||||
_restartService.begin();
|
||||
_systemStatus.begin();
|
||||
_wifiSettingsService.begin();
|
||||
_wifiScanner.begin();
|
||||
_wifiStatus.begin();
|
||||
|
||||
#if FT_ENABLED(USE_UPLOAD_FIRMWARE)
|
||||
_uploadFirmwareService.begin();
|
||||
@@ -203,7 +207,7 @@ void IRAM_ATTR ESP32SvelteKit::loop() {
|
||||
#if FT_ENABLED(USE_WS2812)
|
||||
_ledService.loop();
|
||||
#endif
|
||||
_wifiSettingsService.loop();
|
||||
_wifiService.loop();
|
||||
_apSettingsService.loop();
|
||||
#if FT_ENABLED(USE_ANALYTICS)
|
||||
_analyticsService.loop();
|
||||
|
||||
@@ -46,9 +46,7 @@
|
||||
#include <TaskManager.h>
|
||||
#include <UploadFirmwareService.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiScanner.h>
|
||||
#include <WiFiSettingsService.h>
|
||||
#include <WiFiStatus.h>
|
||||
#include <wifi_service.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#ifdef EMBED_WWW
|
||||
@@ -85,8 +83,6 @@ class ESP32SvelteKit {
|
||||
|
||||
EventSocket *getSocket() { return &_socket; }
|
||||
|
||||
StatefulService<WiFiSettings> *getWiFiSettingsService() { return &_wifiSettingsService; }
|
||||
|
||||
StatefulService<APSettings> *getAPSettingsService() { return &_apSettingsService; }
|
||||
|
||||
#if FT_ENABLED(USE_NTP)
|
||||
@@ -135,9 +131,10 @@ class ESP32SvelteKit {
|
||||
unsigned int _numberEndpoints;
|
||||
FeaturesService _featureService;
|
||||
SecuritySettingsService _securitySettingsService;
|
||||
WiFiSettingsService _wifiSettingsService;
|
||||
WiFiScanner _wifiScanner;
|
||||
WiFiStatus _wifiStatus;
|
||||
WiFiService _wifiService;
|
||||
// WiFiSettingsService _wifiSettingsService;
|
||||
// WiFiScanner _wifiScanner;
|
||||
// WiFiStatus _wifiStatus;
|
||||
APSettingsService _apSettingsService;
|
||||
APStatus _apStatus;
|
||||
EventSocket _socket;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
* Copyright (C) 2024 runeharlyk
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
@@ -17,6 +18,7 @@
|
||||
|
||||
#include <FS.h>
|
||||
#include <StatefulService.h>
|
||||
#include <ESPFS.h>
|
||||
|
||||
template <class T>
|
||||
class FSPersistence {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <StatefulService.h>
|
||||
|
||||
update_handler_id_t StateUpdateHandlerInfo::currentUpdatedHandlerId = 0;
|
||||
hook_handler_id_t StateHookHandlerInfo::currentHookHandlerId = 0;
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
* Copyright (C) 2024 runeharlyk
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
@@ -23,11 +24,7 @@
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
enum class StateUpdateResult {
|
||||
CHANGED = 0, // The update changed the state and propagation should take place if required
|
||||
UNCHANGED, // The state was unchanged, propagation should not take place
|
||||
ERROR // There was a problem updating the state, propagation should not take place
|
||||
};
|
||||
#include <state_result.h>
|
||||
|
||||
template <typename T>
|
||||
using JsonStateUpdater = std::function<StateUpdateResult(JsonObject &root, T &settings)>;
|
||||
@@ -41,7 +38,7 @@ typedef std::function<void(const String &originId)> StateUpdateCallback;
|
||||
typedef std::function<void(const String &originId, StateUpdateResult &result)> StateHookCallback;
|
||||
|
||||
typedef struct StateUpdateHandlerInfo {
|
||||
static update_handler_id_t currentUpdatedHandlerId;
|
||||
static inline update_handler_id_t currentUpdatedHandlerId = 0;
|
||||
update_handler_id_t _id;
|
||||
StateUpdateCallback _cb;
|
||||
bool _allowRemove;
|
||||
@@ -50,7 +47,7 @@ typedef struct StateUpdateHandlerInfo {
|
||||
} StateUpdateHandlerInfo_t;
|
||||
|
||||
typedef struct StateHookHandlerInfo {
|
||||
static hook_handler_id_t currentHookHandlerId;
|
||||
static inline hook_handler_id_t currentHookHandlerId = 0;
|
||||
hook_handler_id_t _id;
|
||||
StateHookCallback _cb;
|
||||
bool _allowRemove;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <WiFiScanner.h>
|
||||
|
||||
WiFiScanner::WiFiScanner(PsychicHttpServer *server, SecurityManager *securityManager)
|
||||
: _server(server), _securityManager(securityManager) {}
|
||||
|
||||
void WiFiScanner::begin() {
|
||||
_server->on(SCAN_NETWORKS_SERVICE_PATH, HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WiFiScanner::scanNetworks, this, std::placeholders::_1),
|
||||
AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
ESP_LOGV("WiFiScanner", "Registered GET endpoint: %s", SCAN_NETWORKS_SERVICE_PATH);
|
||||
|
||||
_server->on(LIST_NETWORKS_SERVICE_PATH, HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WiFiScanner::listNetworks, this, std::placeholders::_1),
|
||||
AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
ESP_LOGV("WiFiScanner", "Registered GET endpoint: %s", LIST_NETWORKS_SERVICE_PATH);
|
||||
}
|
||||
|
||||
esp_err_t WiFiScanner::scanNetworks(PsychicRequest *request) {
|
||||
if (WiFi.scanComplete() != -1) {
|
||||
WiFi.scanDelete();
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
return request->reply(202);
|
||||
}
|
||||
|
||||
esp_err_t WiFiScanner::listNetworks(PsychicRequest *request) {
|
||||
int numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks > -1) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false);
|
||||
JsonObject root = response.getRoot();
|
||||
JsonArray networks = root["networks"].to<JsonArray>();
|
||||
for (int i = 0; i < numNetworks; i++) {
|
||||
JsonObject network = networks.add<JsonObject>();
|
||||
network["rssi"] = WiFi.RSSI(i);
|
||||
network["ssid"] = WiFi.SSID(i);
|
||||
network["bssid"] = WiFi.BSSIDstr(i);
|
||||
network["channel"] = WiFi.channel(i);
|
||||
network["encryption_type"] = (uint8_t)WiFi.encryptionType(i);
|
||||
}
|
||||
|
||||
return response.send();
|
||||
} else if (numNetworks == -1) {
|
||||
return request->reply(202);
|
||||
} else {
|
||||
return scanNetworks(request);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#ifndef WiFiScanner_h
|
||||
#define WiFiScanner_h
|
||||
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <PsychicHttp.h>
|
||||
#include <SecurityManager.h>
|
||||
|
||||
#define SCAN_NETWORKS_SERVICE_PATH "/api/scanNetworks"
|
||||
#define LIST_NETWORKS_SERVICE_PATH "/api/listNetworks"
|
||||
|
||||
class WiFiScanner {
|
||||
public:
|
||||
WiFiScanner(PsychicHttpServer *server, SecurityManager *securityManager);
|
||||
|
||||
void begin();
|
||||
|
||||
private:
|
||||
PsychicHttpServer *_server;
|
||||
SecurityManager *_securityManager;
|
||||
|
||||
esp_err_t scanNetworks(PsychicRequest *request);
|
||||
esp_err_t listNetworks(PsychicRequest *request);
|
||||
};
|
||||
|
||||
#endif // end WiFiScanner_h
|
||||
@@ -1,177 +0,0 @@
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <WiFiSettingsService.h>
|
||||
|
||||
WiFiSettingsService::WiFiSettingsService(PsychicHttpServer *server, FS *fs, SecurityManager *securityManager,
|
||||
EventSocket *socket)
|
||||
: _server(server),
|
||||
_securityManager(securityManager),
|
||||
_httpEndpoint(WiFiSettings::read, WiFiSettings::update, this, server, WIFI_SETTINGS_SERVICE_PATH, securityManager,
|
||||
AuthenticationPredicates::IS_ADMIN),
|
||||
_eventEndpoint(WiFiSettings::read, WiFiSettings::update, this, socket, EVENT_WIFI_SETTINGS),
|
||||
_fsPersistence(WiFiSettings::read, WiFiSettings::update, this, fs, WIFI_SETTINGS_FILE),
|
||||
_lastConnectionAttempt(0),
|
||||
_socket(socket) {
|
||||
addUpdateHandler([&](const String &originId) { reconfigureWiFiConnection(); }, false);
|
||||
}
|
||||
|
||||
void WiFiSettingsService::initWiFi() {
|
||||
WiFi.mode(WIFI_MODE_STA); // this is the default.
|
||||
|
||||
// Disable WiFi config persistance and auto reconnect
|
||||
WiFi.persistent(false);
|
||||
WiFi.setAutoReconnect(false);
|
||||
|
||||
WiFi.onEvent(
|
||||
std::bind(&WiFiSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2),
|
||||
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||
WiFi.onEvent(std::bind(&WiFiSettingsService::onStationModeStop, this, std::placeholders::_1, std::placeholders::_2),
|
||||
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_STOP);
|
||||
|
||||
_fsPersistence.readFromFS();
|
||||
reconfigureWiFiConnection();
|
||||
}
|
||||
|
||||
void WiFiSettingsService::begin() {
|
||||
_httpEndpoint.begin();
|
||||
_eventEndpoint.begin();
|
||||
}
|
||||
|
||||
void WiFiSettingsService::reconfigureWiFiConnection() {
|
||||
// reset last connection attempt to force loop to reconnect immediately
|
||||
_lastConnectionAttempt = 0;
|
||||
|
||||
// disconnect and de-configure wifi
|
||||
if (WiFi.disconnect(true)) {
|
||||
_stopping = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiSettingsService::loop() {
|
||||
EXECUTE_EVERY_N_MS(WIFI_RECONNECTION_DELAY, manageSTA());
|
||||
EXECUTE_EVERY_N_MS(RSSI_EVENT_DELAY, updateRSSI());
|
||||
}
|
||||
|
||||
String WiFiSettingsService::getHostname() { return _state.hostname; }
|
||||
|
||||
void WiFiSettingsService::manageSTA() {
|
||||
// Abort if already connected, or if we have no SSID
|
||||
if (WiFi.isConnected() || _state.wifiSettings.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Connect or reconnect as required
|
||||
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
||||
connectToWiFi();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiSettingsService::connectToWiFi() {
|
||||
// reset availability flag for all stored networks
|
||||
for (auto &network : _state.wifiSettings) {
|
||||
network.available = false;
|
||||
}
|
||||
|
||||
// scanning for available networks
|
||||
int scanResult = WiFi.scanNetworks();
|
||||
if (scanResult == WIFI_SCAN_FAILED) {
|
||||
ESP_LOGE("WiFiSettingsService", "WiFi scan failed.");
|
||||
} else if (scanResult == 0) {
|
||||
ESP_LOGI("WiFiSettingsService", "No networks found.");
|
||||
} else {
|
||||
ESP_LOGI("WiFiSettingsService", "%d networks found.", scanResult);
|
||||
|
||||
// find the best network to connect
|
||||
wifi_settings_t *bestNetwork = NULL;
|
||||
int bestNetworkDb = FACTORY_WIFI_RSSI_THRESHOLD;
|
||||
|
||||
for (int i = 0; i < scanResult; ++i) {
|
||||
String ssid_scan;
|
||||
int32_t rssi_scan;
|
||||
uint8_t sec_scan;
|
||||
uint8_t *BSSID_scan;
|
||||
int32_t chan_scan;
|
||||
|
||||
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan);
|
||||
ESP_LOGV("WiFiSettingsService", "SSID: %s, RSSI: %d dbm", ssid_scan.c_str(), rssi_scan);
|
||||
|
||||
for (auto &network : _state.wifiSettings) {
|
||||
if (ssid_scan == network.ssid) { // SSID match
|
||||
if (rssi_scan > bestNetworkDb) { // best network
|
||||
bestNetworkDb = rssi_scan;
|
||||
bestNetwork = &network;
|
||||
network.available = true;
|
||||
} else if (rssi_scan >= FACTORY_WIFI_RSSI_THRESHOLD) { // available network
|
||||
network.available = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if configured to prioritize signal strength, use the best network else use the first available network
|
||||
if (_state.priorityBySignalStrength == false) {
|
||||
for (auto &network : _state.wifiSettings) {
|
||||
if (network.available == true) {
|
||||
ESP_LOGI("WiFiSettingsService", "Connecting to first available network: %s", network.ssid.c_str());
|
||||
configureNetwork(network);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_state.priorityBySignalStrength == true && bestNetwork) {
|
||||
ESP_LOGI("WiFiSettingsService", "Connecting to strongest network: %s", bestNetwork->ssid.c_str());
|
||||
configureNetwork(*bestNetwork);
|
||||
WiFi.begin(bestNetwork->ssid.c_str(), bestNetwork->password.c_str());
|
||||
} else // no suitable network to connect
|
||||
{
|
||||
ESP_LOGI("WiFiSettingsService", "No known networks found.");
|
||||
}
|
||||
|
||||
// delete scan results
|
||||
WiFi.scanDelete();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiSettingsService::configureNetwork(wifi_settings_t &network) {
|
||||
if (network.staticIPConfig) {
|
||||
// configure for static IP
|
||||
WiFi.config(network.localIP, network.gatewayIP, network.subnetMask, network.dnsIP1, network.dnsIP2);
|
||||
} else {
|
||||
// configure for DHCP
|
||||
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
}
|
||||
WiFi.setHostname(_state.hostname.c_str());
|
||||
|
||||
// attempt to connect to the network
|
||||
WiFi.begin(network.ssid.c_str(), network.password.c_str());
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
WiFi.setTxPower(WIFI_POWER_8_5dBm); // https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
|
||||
#endif
|
||||
}
|
||||
|
||||
void WiFiSettingsService::updateRSSI() {
|
||||
char buffer[8];
|
||||
snprintf(buffer, sizeof(buffer), "%d", WiFi.RSSI());
|
||||
_socket->emit(EVENT_RSSI, buffer);
|
||||
}
|
||||
|
||||
void WiFiSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) { WiFi.disconnect(true); }
|
||||
void WiFiSettingsService::onStationModeStop(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
if (_stopping) {
|
||||
_lastConnectionAttempt = 0;
|
||||
_stopping = false;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <WiFiStatus.h>
|
||||
|
||||
WiFiStatus::WiFiStatus(PsychicHttpServer *server, SecurityManager *securityManager)
|
||||
: _server(server), _securityManager(securityManager) {}
|
||||
|
||||
void WiFiStatus::begin() {
|
||||
_server->on(WIFI_STATUS_SERVICE_PATH, HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WiFiStatus::wifiStatus, this, std::placeholders::_1),
|
||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
ESP_LOGV("WiFiStatus", "Registered GET endpoint: %s", WIFI_STATUS_SERVICE_PATH);
|
||||
|
||||
WiFi.onEvent(onStationModeConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED);
|
||||
WiFi.onEvent(onStationModeDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||
WiFi.onEvent(onStationModeGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
||||
}
|
||||
|
||||
void WiFiStatus::onStationModeConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
ESP_LOGI("WiFiStatus", "WiFi Connected.");
|
||||
}
|
||||
|
||||
void WiFiStatus::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
ESP_LOGI("WiFiStatus", "WiFi Disconnected. Reason code=%d", info.wifi_sta_disconnected.reason);
|
||||
}
|
||||
|
||||
void WiFiStatus::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
ESP_LOGI("WiFiStatus", "WiFi Got IP. localIP=%s, hostName=%s", WiFi.localIP().toString().c_str(),
|
||||
WiFi.getHostname());
|
||||
}
|
||||
|
||||
esp_err_t WiFiStatus::wifiStatus(PsychicRequest *request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false);
|
||||
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["mac_address"] = WiFi.macAddress();
|
||||
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 (IPUtils::isSet(dnsIP1)) {
|
||||
root["dns_ip_1"] = dnsIP1.toString();
|
||||
}
|
||||
if (IPUtils::isSet(dnsIP2)) {
|
||||
root["dns_ip_2"] = dnsIP2.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return response.send();
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef WiFiStatus_h
|
||||
#define WiFiStatus_h
|
||||
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <PsychicHttp.h>
|
||||
#include <IPUtils.h>
|
||||
#include <SecurityManager.h>
|
||||
|
||||
#define WIFI_STATUS_SERVICE_PATH "/api/wifiStatus"
|
||||
|
||||
class WiFiStatus {
|
||||
public:
|
||||
WiFiStatus(PsychicHttpServer *server, SecurityManager *securityManager);
|
||||
|
||||
void begin();
|
||||
|
||||
private:
|
||||
PsychicHttpServer *_server;
|
||||
SecurityManager *_securityManager;
|
||||
|
||||
// static functions for logging WiFi events to the UART
|
||||
static void onStationModeConnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
static void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
static void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
esp_err_t wifiStatus(PsychicRequest *request);
|
||||
};
|
||||
|
||||
#endif // end WiFiStatus_h
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum class StateUpdateResult {
|
||||
CHANGED = 0, // The update changed the state and propagation should take place if required
|
||||
UNCHANGED, // The state was unchanged, propagation should not take place
|
||||
ERROR // There was a problem updating the state, propagation should not take place
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <PsychicHttp.h>
|
||||
#include <stateful_service_endpoint.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#define HTTP_ENDPOINT_ORIGIN_ID "http"
|
||||
#define HTTPS_ENDPOINT_ORIGIN_ID "https"
|
||||
|
||||
template <class T>
|
||||
class StatefulHttpEndpoint {
|
||||
protected:
|
||||
JsonStateReader<T> _stateReader;
|
||||
JsonStateUpdater<T> _stateUpdater;
|
||||
StatefulService<T> *_statefulService;
|
||||
|
||||
public:
|
||||
StatefulHttpEndpoint(JsonStateReader<T> stateReader, JsonStateUpdater<T> stateUpdater,
|
||||
StatefulService<T> *statefulService)
|
||||
: _stateReader(stateReader), _stateUpdater(stateUpdater), _statefulService(statefulService) {}
|
||||
|
||||
esp_err_t handleStateUpdate(PsychicRequest *request, JsonVariant &json) {
|
||||
if (!json.is<JsonObject>()) {
|
||||
return request->reply(400);
|
||||
}
|
||||
|
||||
JsonObject jsonObject = json.as<JsonObject>();
|
||||
StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
||||
|
||||
if (outcome == StateUpdateResult::ERROR) {
|
||||
return request->reply(400);
|
||||
} else if ((outcome == StateUpdateResult::CHANGED)) {
|
||||
// persist the changes to the FS
|
||||
_statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID);
|
||||
}
|
||||
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false);
|
||||
jsonObject = response.getRoot();
|
||||
|
||||
_statefulService->read(jsonObject, _stateReader);
|
||||
|
||||
return response.send();
|
||||
}
|
||||
|
||||
esp_err_t getState(PsychicRequest *request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false);
|
||||
JsonObject jsonObject = response.getRoot();
|
||||
_statefulService->read(jsonObject, _stateReader);
|
||||
return response.send();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,208 @@
|
||||
#include <wifi_service.h>
|
||||
|
||||
WiFiService::WiFiService()
|
||||
: endpoint(WiFiSettings::read, WiFiSettings::update, this),
|
||||
_fsPersistence(WiFiSettings::read, WiFiSettings::update, this, &ESPFS, WIFI_SETTINGS_FILE) {
|
||||
addUpdateHandler([&](const String &originId) { reconfigureWiFiConnection(); }, false);
|
||||
}
|
||||
|
||||
WiFiService::~WiFiService() {}
|
||||
|
||||
void WiFiService::begin() {
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
|
||||
WiFi.persistent(false);
|
||||
WiFi.setAutoReconnect(false);
|
||||
|
||||
WiFi.onEvent(std::bind(&WiFiService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2),
|
||||
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||
WiFi.onEvent(std::bind(&WiFiService::onStationModeStop, this, std::placeholders::_1, std::placeholders::_2),
|
||||
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_STOP);
|
||||
|
||||
WiFi.onEvent(onStationModeGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
||||
|
||||
_fsPersistence.readFromFS();
|
||||
reconfigureWiFiConnection();
|
||||
}
|
||||
|
||||
void WiFiService::reconfigureWiFiConnection() {
|
||||
_lastConnectionAttempt = 0;
|
||||
|
||||
if (WiFi.disconnect(true)) _stopping = true;
|
||||
}
|
||||
|
||||
void WiFiService::loop() { EXECUTE_EVERY_N_MS(reconnectDelay, manageSTA()); }
|
||||
|
||||
esp_err_t WiFiService::handleScan(PsychicRequest *request) {
|
||||
if (WiFi.scanComplete() != -1) {
|
||||
WiFi.scanDelete();
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
return request->reply(202);
|
||||
}
|
||||
|
||||
esp_err_t WiFiService::getNetworks(PsychicRequest *request) {
|
||||
int numNetworks = WiFi.scanComplete();
|
||||
if (numNetworks == -1)
|
||||
return request->reply(202);
|
||||
else if (numNetworks < -1)
|
||||
return handleScan(request);
|
||||
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false);
|
||||
JsonObject root = response.getRoot();
|
||||
getNetworks(root);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
void WiFiService::setupMDNS(const char *hostname) {
|
||||
MDNS.begin(_state.hostname.c_str());
|
||||
MDNS.setInstanceName(hostname);
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("ws", "tcp", 80);
|
||||
MDNS.addServiceTxt("http", "tcp", "Firmware Version", APP_VERSION);
|
||||
}
|
||||
|
||||
void WiFiService::getNetworks(JsonObject &root) {
|
||||
JsonArray networks = root["networks"].to<JsonArray>();
|
||||
int numNetworks = WiFi.scanComplete();
|
||||
for (int i = 0; i < numNetworks; i++) {
|
||||
JsonObject network = networks.add<JsonObject>();
|
||||
network["rssi"] = WiFi.RSSI(i);
|
||||
network["ssid"] = WiFi.SSID(i);
|
||||
network["bssid"] = WiFi.BSSIDstr(i);
|
||||
network["channel"] = WiFi.channel(i);
|
||||
network["encryption_type"] = (uint8_t)WiFi.encryptionType(i);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t WiFiService::getNetworkStatus(PsychicRequest *request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false);
|
||||
JsonObject root = response.getRoot();
|
||||
getNetworkStatus(root);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
void WiFiService::getNetworkStatus(JsonObject &root) {
|
||||
wl_status_t status = WiFi.status();
|
||||
root["status"] = (uint8_t)status;
|
||||
if (status == WL_CONNECTED) {
|
||||
root["local_ip"] = WiFi.localIP().toString();
|
||||
root["mac_address"] = WiFi.macAddress();
|
||||
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 != INADDR_NONE) {
|
||||
root["dns_ip_1"] = dnsIP1.toString();
|
||||
}
|
||||
if (dnsIP2 != INADDR_NONE) {
|
||||
root["dns_ip_2"] = dnsIP2.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiService::manageSTA() {
|
||||
if (WiFi.isConnected() || _state.wifiSettings.empty()) return;
|
||||
if ((WiFi.getMode() & WIFI_STA) == 0) connectToWiFi();
|
||||
}
|
||||
|
||||
void WiFiService::connectToWiFi() {
|
||||
// reset availability flag for all stored networks
|
||||
for (auto &network : _state.wifiSettings) {
|
||||
network.available = false;
|
||||
}
|
||||
|
||||
// scanning for available networks
|
||||
int scanResult = WiFi.scanNetworks();
|
||||
if (scanResult == WIFI_SCAN_FAILED) {
|
||||
ESP_LOGE("WiFiSettingsService", "WiFi scan failed.");
|
||||
} else if (scanResult == 0) {
|
||||
ESP_LOGI("WiFiSettingsService", "No networks found.");
|
||||
} else {
|
||||
ESP_LOGI("WiFiSettingsService", "%d networks found.", scanResult);
|
||||
|
||||
// find the best network to connect
|
||||
wifi_settings_t *bestNetwork = nullptr;
|
||||
int32_t bestNetworkDb = FACTORY_WIFI_RSSI_THRESHOLD;
|
||||
|
||||
for (int i = 0; i < scanResult; ++i) {
|
||||
String ssid_scan;
|
||||
int32_t rssi_scan;
|
||||
uint8_t sec_scan;
|
||||
uint8_t *BSSID_scan;
|
||||
int32_t chan_scan;
|
||||
|
||||
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan);
|
||||
|
||||
for (auto &network : _state.wifiSettings) {
|
||||
if (ssid_scan == network.ssid) {
|
||||
if (rssi_scan >= FACTORY_WIFI_RSSI_THRESHOLD) {
|
||||
network.available = true;
|
||||
}
|
||||
if (rssi_scan > bestNetworkDb) {
|
||||
bestNetworkDb = rssi_scan;
|
||||
bestNetwork = &network;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_state.priorityBySignalStrength) {
|
||||
for (auto &network : _state.wifiSettings) {
|
||||
if (network.available == true) {
|
||||
ESP_LOGI("WiFiSettingsService", "Connecting to first available network: %s", network.ssid.c_str());
|
||||
configureNetwork(network);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_state.priorityBySignalStrength && bestNetwork) {
|
||||
ESP_LOGI("WiFiSettingsService", "Connecting to strongest network: %s", bestNetwork->ssid.c_str());
|
||||
configureNetwork(*bestNetwork);
|
||||
WiFi.begin(bestNetwork->ssid.c_str(), bestNetwork->password.c_str());
|
||||
} else {
|
||||
ESP_LOGI("WiFiSettingsService", "No known networks found.");
|
||||
}
|
||||
|
||||
WiFi.scanDelete();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiService::configureNetwork(wifi_settings_t &network) {
|
||||
if (network.staticIPConfig) {
|
||||
// configure for static IP
|
||||
WiFi.config(network.localIP, network.gatewayIP, network.subnetMask, network.dnsIP1, network.dnsIP2);
|
||||
} else {
|
||||
// configure for DHCP
|
||||
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
}
|
||||
WiFi.setHostname(_state.hostname.c_str());
|
||||
|
||||
// attempt to connect to the network
|
||||
WiFi.begin(network.ssid.c_str(), network.password.c_str());
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
WiFi.setTxPower(WIFI_POWER_8_5dBm); // https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
|
||||
#endif
|
||||
}
|
||||
|
||||
void WiFiService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
WiFi.disconnect(true);
|
||||
ESP_LOGI("WiFiStatus", "WiFi Disconnected. Reason code=%d", info.wifi_sta_disconnected.reason);
|
||||
}
|
||||
|
||||
void WiFiService::onStationModeStop(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
if (_stopping) {
|
||||
_lastConnectionAttempt = 0;
|
||||
_stopping = false;
|
||||
}
|
||||
ESP_LOGI("WiFiStatus", "WiFi Connected.");
|
||||
}
|
||||
|
||||
void WiFiService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
ESP_LOGI("WiFiStatus", "WiFi Got IP. localIP=%s, hostName=%s", WiFi.localIP().toString().c_str(),
|
||||
WiFi.getHostname());
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <PsychicHttp.h>
|
||||
#include <IPAddress.h>
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
|
||||
#include <ESPFS.h>
|
||||
#include <Timing.h>
|
||||
#include <StatefulService.h>
|
||||
#include <FSPersistence.h>
|
||||
#include <stateful_service_endpoint.h>
|
||||
#include <wifi_settings.h>
|
||||
|
||||
class WiFiService : public StatefulService<WiFiSettings> {
|
||||
private:
|
||||
static void getNetworks(JsonObject &root);
|
||||
static void getNetworkStatus(JsonObject &root);
|
||||
void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
void onStationModeStop(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
static void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
|
||||
FSPersistence<WiFiSettings> _fsPersistence;
|
||||
|
||||
void reconfigureWiFiConnection();
|
||||
void manageSTA();
|
||||
void connectToWiFi();
|
||||
void configureNetwork(wifi_settings_t &network);
|
||||
|
||||
unsigned long _lastConnectionAttempt;
|
||||
bool _stopping;
|
||||
|
||||
constexpr static uint16_t reconnectDelay {10000};
|
||||
|
||||
public:
|
||||
WiFiService();
|
||||
~WiFiService();
|
||||
|
||||
void begin();
|
||||
void loop();
|
||||
|
||||
void setupMDNS(const char *hostname);
|
||||
|
||||
const char *getHostname() { return _state.hostname.c_str(); }
|
||||
|
||||
static esp_err_t handleScan(PsychicRequest *request);
|
||||
static esp_err_t getNetworks(PsychicRequest *request);
|
||||
static esp_err_t getNetworkStatus(PsychicRequest *request);
|
||||
|
||||
StatefulHttpEndpoint<WiFiSettings> endpoint;
|
||||
};
|
||||
+8
-83
@@ -1,60 +1,17 @@
|
||||
#ifndef WiFiSettingsService_h
|
||||
#define WiFiSettingsService_h
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* ESP32 SvelteKit
|
||||
*
|
||||
* A simple, secure and extensible framework for IoT projects for ESP32 platforms
|
||||
* with responsive Sveltekit front-end built with TailwindCSS and DaisyUI.
|
||||
* https://github.com/theelims/ESP32-sveltekit
|
||||
*
|
||||
* Copyright (C) 2018 - 2023 rjwats
|
||||
* Copyright (C) 2023 theelims
|
||||
*
|
||||
* All Rights Reserved. This software may be modified and distributed under
|
||||
* the terms of the LGPL v3 license. See the LICENSE file for details.
|
||||
**/
|
||||
|
||||
#include <EventEndpoint.h>
|
||||
#include <EventSocket.h>
|
||||
#include <FSPersistence.h>
|
||||
#include <HttpEndpoint.h>
|
||||
#include <JsonUtils.h>
|
||||
#include <PsychicHttp.h>
|
||||
#include <SecurityManager.h>
|
||||
#include <SettingValue.h>
|
||||
#include <StatefulService.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiMulti.h>
|
||||
#include <vector>
|
||||
#include <Timing.h>
|
||||
#include <ESPFS.h>
|
||||
|
||||
#ifndef FACTORY_WIFI_SSID
|
||||
#define FACTORY_WIFI_SSID ""
|
||||
#endif
|
||||
|
||||
#ifndef FACTORY_WIFI_PASSWORD
|
||||
#define FACTORY_WIFI_PASSWORD ""
|
||||
#endif
|
||||
|
||||
#ifndef FACTORY_WIFI_HOSTNAME
|
||||
#define FACTORY_WIFI_HOSTNAME "#{platform}-#{unique_id}"
|
||||
#endif
|
||||
#include <IPAddress.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <JsonUtils.h>
|
||||
#include <IPUtils.h>
|
||||
#include <SettingValue.h>
|
||||
#include <state_result.h>
|
||||
|
||||
#ifndef FACTORY_WIFI_RSSI_THRESHOLD
|
||||
#define FACTORY_WIFI_RSSI_THRESHOLD -80
|
||||
#endif
|
||||
|
||||
#define WIFI_SETTINGS_SERVICE_PATH "/api/wifiSettings"
|
||||
|
||||
#define WIFI_RECONNECTION_DELAY 1000 * 30
|
||||
#define RSSI_EVENT_DELAY 500
|
||||
|
||||
#define EVENT_RSSI "rssi"
|
||||
#define EVENT_WIFI_SETTINGS "WiFiSettings"
|
||||
|
||||
// Struct defining the wifi settings
|
||||
typedef struct {
|
||||
String ssid;
|
||||
String password;
|
||||
@@ -69,7 +26,6 @@ typedef struct {
|
||||
|
||||
class WiFiSettings {
|
||||
public:
|
||||
// core wifi configuration
|
||||
String hostname;
|
||||
bool priorityBySignalStrength;
|
||||
std::vector<wifi_settings_t> wifiSettings;
|
||||
@@ -185,35 +141,4 @@ class WiFiSettings {
|
||||
|
||||
return StateUpdateResult::CHANGED;
|
||||
};
|
||||
};
|
||||
|
||||
class WiFiSettingsService : public StatefulService<WiFiSettings> {
|
||||
public:
|
||||
WiFiSettingsService(PsychicHttpServer *server, FS *fs, SecurityManager *securityManager, EventSocket *socket);
|
||||
|
||||
void initWiFi();
|
||||
void begin();
|
||||
void loop();
|
||||
String getHostname();
|
||||
|
||||
private:
|
||||
PsychicHttpServer *_server;
|
||||
SecurityManager *_securityManager;
|
||||
HttpEndpoint<WiFiSettings> _httpEndpoint;
|
||||
EventEndpoint<WiFiSettings> _eventEndpoint;
|
||||
FSPersistence<WiFiSettings> _fsPersistence;
|
||||
EventSocket *_socket;
|
||||
unsigned long _lastConnectionAttempt;
|
||||
|
||||
bool _stopping;
|
||||
void onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
void onStationModeStop(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
|
||||
void reconfigureWiFiConnection();
|
||||
void manageSTA();
|
||||
void connectToWiFi();
|
||||
void configureNetwork(wifi_settings_t &network);
|
||||
void updateRSSI();
|
||||
};
|
||||
|
||||
#endif // end WiFiSettingsService_h
|
||||
};
|
||||
Reference in New Issue
Block a user