22#include <ESP8266WiFi.h>
23#include <ESP8266mDNS.h>
40#include <config.min.html.gz.h>
113 : mpCredentials(&credentials),
114 mApSubnet(255, 255, 255, 0),
115 mConfigServer(IPAddress(1, 1, 1, 1),
116 [this](AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
117 _handleWebSocketEvent(server, client, type, arg, data, len);
120 mApName.toUpperCase();
123 mLastSaveResult = -1;
126 WiFi.persistent(
false);
127 WiFi.setAutoConnect(
false);
128 WiFi.setAutoReconnect(
false);
129 WiFi.setHostname(mApName.c_str());
145 scheduler.
push(
"server_start", mTaskStart);
146 scheduler.
push(
"server_serve", mTaskServe);
147 scheduler.
push(
"server_stop", mTaskStop);
148 scheduler.
push(
"ap_config", mTaskConfigAp);
149 scheduler.
push(
"ap_stop", mTaskStopAp);
150 scheduler.
push(
"sta_connect", mTaskConnectSta);
151 scheduler.
push(
"sta_connecting", mTaskConnecting);
152 scheduler.
push(
"wifi_monitor", mTaskMonitoring);
153 scheduler.
push(
"wifi_scan", mTaskScan);
154 scheduler.
push(
"wifi_check", mTaskAvailabilityCheck);
156 scheduler.
push(
"wifi_scan_complete", mWifiScan.getTask());
168 mWifiStorage.restore();
169 if (mWifiStorage.isCredentialsValid()) {
170 mTaskConnectSta->once(500);
172 mTaskConfigAp->once(500);
184 if (_tryToRecoverAp()) {
188 mTaskConfigAp->once(100);
198 UNIOT_LOG_DEBUG(
"Forget credentials: %s", mWifiStorage.getSsid().c_str());
199 mWifiStorage.clean();
201 mTaskConfigAp->once(500);
212 if (mWifiStorage.isCredentialsValid()) {
214 mTaskConnectSta->once(500);
216 if (_tryToRecoverAp()) {
235 if (!ssid.isEmpty()) {
236 mWifiStorage.setCredentials(ssid, password);
237 mWifiStorage.store();
269 if (mConfigServer.
start()) {
270 _initServerCallbacks();
272 mTaskServe->attach(10);
282 static bool wsClosed =
false;
288 mConfigServer.wsCloseAll();
293 mTaskServe->detach();
294 mConfigServer.stop();
296 mLastNetworks =
static_cast<const char *
>(
nullptr);
301 WiFi.disconnect(
true,
true);
302 mTaskStopAp->detach();
303 if (WiFi.softAPConfig(mConfigServer.ip(), mConfigServer.ip(), mApSubnet) && WiFi.softAP(mApName.c_str())) {
304#if defined(ESP32) && defined(ENABLE_LOWER_WIFI_TX_POWER)
305 WiFi.setTxPower(WIFI_TX_POWER_LEVEL);
307 mTaskStart->once(500);
308 mTaskScan->once(500);
309 mTaskAvailabilityCheck->attach(10000);
315 mTaskConfigAp->attach(500, 1);
321 WiFi.softAPdisconnect(
true);
326 WiFi.disconnect(
false,
true);
327 bool connect = WiFi.begin(mWifiStorage.getSsid().c_str(), mWifiStorage.getPassword().c_str()) != WL_CONNECT_FAILED;
329#if defined(ESP32) && defined(ENABLE_LOWER_WIFI_TX_POWER)
330 WiFi.setTxPower(WIFI_TX_POWER_LEVEL);
332 mTaskConnecting->attach(100, 50);
336 mLastSaveResult = -1;
338 mTaskConnecting->detach();
346 auto __processFailure = [
this](
int triesBeforeGivingUp = 3) {
347 static int tries = 0;
348 if (++tries < triesBeforeGivingUp) {
349 UNIOT_LOG_INFO(
"Tries to connect until give up is %d", triesBeforeGivingUp - tries);
350 mTaskConnectSta->attach(500, 1);
353 mWifiStorage.restore();
360 switch (WiFi.status()) {
363 mTaskMonitoring->attach(200);
364 mWifiStorage.store();
365 if (mpCredentials->isOwnerChanged()) {
366 mpCredentials->store();
371 mTaskStop->once(30000);
372 mTaskStopAp->once(35000);
373 mTaskAvailabilityCheck->detach();
377 case WL_NO_SSID_AVAIL:
378 case WL_CONNECT_FAILED:
383 case WL_WRONG_PASSWORD:
389 case WL_DISCONNECTED:
390 case WL_CONNECTION_LOST:
403 if (WiFi.status() != WL_CONNECTED) {
404 mTaskMonitoring->detach();
411 static auto __broadcastNets = [
this](
const String &netJsonArray) {
414 .put(
"nets", netJsonArray,
false)
416 mConfigServer.wsTextAll(nets);
420 mWifiScan.scanNetworksAsync([
this](
int n) {
421 mLastNetworks =
static_cast<const char *
>(
nullptr);
422 JSON::Array jsonNets(mLastNetworks);
423 for (
auto i = 0; i < n; ++i) {
424 jsonNets.appendArray()
425 .append(WiFi.BSSIDstr(i))
426 .append(WiFi.SSID(i))
427 .append(WiFi.RSSI(i))
428 .append(mWifiScan.isSecured(WiFi.encryptionType(i)))
433 __broadcastNets(mLastNetworks);
436 __broadcastNets(mLastNetworks);
441 static int scanInProgressFuse = 0;
442 if (scanInProgressFuse-- > 0) {
448 !mConfigServer.wsClientsActive() &&
449 mWifiStorage.isCredentialsValid()) {
450 UNIOT_LOG_INFO(
"Checking availability of the network [%s]", mWifiStorage.getSsid().c_str());
451 scanInProgressFuse = 3;
453 mWifiScan.scanNetworksAsync([&](
int n) {
454 scanInProgressFuse = 0;
455 if (self.isAttached() &&
457 !mConfigServer.wsClientsActive() &&
458 mWifiStorage.isCredentialsValid()) {
459 for (
auto i = 0; i < n; ++i) {
460 if (WiFi.SSID(i) == mWifiStorage.getSsid()) {
461 UNIOT_LOG_INFO(
"Network [%s] is available", WiFi.SSID(i).c_str());
482 void _initServerCallbacks() {
483 auto server = mConfigServer.get();
485 server->onNotFound([](AsyncWebServerRequest *request) {
489 request->redirect(
"http://uniot.local/");
492 server->on(
"/", [
this](AsyncWebServerRequest *request) {
493 auto response = request->beginResponse(200,
"text/html", CONFIG_MIN_HTML_GZ, CONFIG_MIN_HTML_GZ_LENGTH,
nullptr);
494 response->addHeader(
"Content-Encoding",
"gzip");
495 request->send(response);
512 void _handleWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
void *arg, uint8_t *data,
size_t len) {
516 UNIOT_LOG_INFO(
"WebSocket client #%u connected from %s", client->id(), client->remoteIP().toString().c_str());
518 case WS_EVT_DISCONNECT:
520 UNIOT_LOG_INFO(
"WebSocket client #%u disconnected", client->id());
523 _handleWebSocketMessage(client->id(), arg, data, len);
541 void _handleWebSocketMessage(uint32_t clientId,
void *arg, uint8_t *data,
size_t len) {
542 auto *info = (AwsFrameInfo *)arg;
543 if (info->opcode == WS_BINARY) {
544 CBORObject msg(Bytes(data, len));
545 if (!msg.hasError()) {
546 auto action = msg.getInt(
"action");
547 if (action != ACTIONS::INVALID) {
549 case ACTIONS::STATUS: {
552 .put(
"id", mpCredentials->getDeviceId())
553 .put(
"acc", mpCredentials->getOwnerId())
554 .put(
"nets", mLastNetworks.length() ? mLastNetworks :
"[]",
false)
555 .put(
"homeNet", WiFi.isConnected() ? WiFi.SSID() :
"")
557 mConfigServer.wsTextAll(status);
560 case ACTIONS::SAVE: {
561 mWifiStorage.setCredentials(msg.getString(
"ssid"), msg.getString(
"pass"));
562 if (mWifiStorage.isCredentialsValid()) {
563 mTaskConnectSta->once(500);
564 mpCredentials->setOwnerId(msg.getString(
"acc"));
565 UNIOT_LOG_DEBUG(
"Is owner changed: %d", mpCredentials->isOwnerChanged());
569 case ACTIONS::SCAN: {
570 mTaskScan->once(1000);
574 if (mLastSaveResult > -1) {
576 JSON::Object(success)
577 .put(
"success", mLastSaveResult)
579 mConfigServer.wsText(clientId, success);
603 bool _tryToRecoverAp() {
606 mTaskStart->once(100);
607 mTaskStopAp->detach();
608 mConfigServer.wsEnable(
true);
609 mTaskAvailabilityCheck->attach(10000);
615 Credentials *mpCredentials;
616 WifiStorage mWifiStorage;
620 ConfigCaptivePortal mConfigServer;
622 String mLastNetworks;
623 int8_t mLastSaveResult;
640 ESP32WifiScan mWifiScan;
641#elif defined(ESP8266)
642 ESP8266WifiScan mWifiScan;
Captive portal implementation for device configuration.
Network event definitions for the Uniot event system.
Platform-specific WiFi network scanning utilities.
void wsEnable(bool enable)
Enable or disable WebSocket functionality.
Definition ConfigCaptivePortal.h:279
bool start()
Start the captive portal services.
Definition ConfigCaptivePortal.h:159
Manages device identity and cryptographic credentials for Uniot devices.
Definition Credentials.h:61
uint32_t getShortDeviceId() const
Gets a shorter unique identifier for the device.
Definition Credentials.h:176
void emitEvent(unsigned int topic, int msg)
bool sendDataToChannel(T_topic channel, T_data data)
Sends data to a specific channel on all connected EventBus instances.
Definition EventEntity.h:98
Interface for connecting components to the TaskScheduler.
Definition ISchedulerConnectionKit.h:35
NetworkScheduler(Credentials &credentials)
Construct a new NetworkScheduler.
Definition NetworkScheduler.h:112
bool reconnect()
Attempt to reconnect using stored credentials.
Definition NetworkScheduler.h:211
void config()
Start or recover configuration mode.
Definition NetworkScheduler.h:183
virtual void attach() override
Attach the network scheduler and start initial connection.
Definition NetworkScheduler.h:167
void forget()
Forget stored WiFi credentials and enter configuration mode.
Definition NetworkScheduler.h:197
virtual void pushTo(TaskScheduler &scheduler) override
Push all network tasks to the scheduler.
Definition NetworkScheduler.h:144
bool setCredentials(const String &ssid, const String &password)
Set and store new WiFi credentials.
Definition NetworkScheduler.h:234
Definition TaskScheduler.h:164
EventEmitter< unsigned int, int, Bytes > CoreEventEmitter
A specialized EventEmitter for core system events.
Definition EventEmitter.h:78
#define UNIOT_LOG_INFO(...)
Log an INFO level message Used for general information about system operation. Only compiled if UNIOT...
Definition Logger.h:268
#define UNIOT_LOG_WARN(...)
Log an WARN level message Used for warnings about potentially problematic situations....
Definition Logger.h:247
#define UNIOT_LOG_DEBUG(...)
Log an DEBUG level message Used for general information about system operation. Only compiled if UNIO...
Definition Logger.h:293
SharedPointer< SchedulerTask > TaskPtr
Shared pointer type for scheduler tasks.
Definition TaskScheduler.h:171
static TaskPtr make(SchedulerTask::SchedulerTaskCallback callback)
Static factory method to create a task with a callback.
Definition TaskScheduler.h:193
TaskScheduler & push(const char *name, TaskPtr task)
Add a named task to the scheduler.
Definition TaskScheduler.h:214
@ DISCONNECTING
Currently disconnecting from network.
Definition NetworkEvents.h:88
@ SUCCESS
Network operation completed successfully.
Definition NetworkEvents.h:86
@ ACCESS_POINT
Device is operating in access point mode.
Definition NetworkEvents.h:90
@ AVAILABLE
Configured network is available for connection.
Definition NetworkEvents.h:91
@ DISCONNECTED
Network connection has been lost or terminated.
Definition NetworkEvents.h:89
@ FAILED
Network operation failed (connection, scan, etc.)
Definition NetworkEvents.h:85
@ CONNECTING
Currently attempting to connect to network.
Definition NetworkEvents.h:87
@ CONNECTION
WiFi connection state changes and operations.
Definition NetworkEvents.h:74
@ OUT_SSID
Channel for broadcasting current SSID information.
Definition NetworkEvents.h:63
Contains all classes and functions related to the Uniot Core.