172 lines
4.1 KiB
C++
172 lines
4.1 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2023 Sascha Nitsch (@grumpydevelop@contentnation.net) https://contentnation.net/en/grumpydevelop
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#include <LittleFS.h>
|
|
#include <ESP8266WiFi.h>
|
|
#include "wlanmanager.h"
|
|
|
|
#define _connectTimeout 5000
|
|
|
|
WLANManager::WLANManager() {
|
|
bzero(m_ssid, sizeof(m_ssid));
|
|
bzero(m_password, sizeof(m_password));
|
|
m_dnsServer = NULL;
|
|
m_isAccessPoint = true;
|
|
}
|
|
|
|
void WLANManager::setSSID(const char* ssid, const char* password) {
|
|
strncpy(m_ssid, ssid, sizeof(m_ssid) - 1);
|
|
strncpy(m_password, password, sizeof(m_password) - 1);
|
|
}
|
|
|
|
void WLANManager::loadConfigFromFile(const char* filename) {
|
|
File file = LittleFS.open(filename, "r"); // Open it
|
|
unsigned int size = file.size();
|
|
if (size == 0) {
|
|
return;
|
|
}
|
|
char mode[20]={0};
|
|
char* config = reinterpret_cast<char*>(malloc(size + 1));
|
|
config[size] = 0;
|
|
file.read((unsigned char*)config, size);
|
|
file.close();
|
|
while (config[size - 1] == '\n') {
|
|
config[size - 1] = 0;
|
|
--size;
|
|
}
|
|
// format: "ssid;password;ap/client"
|
|
char* next = nextSemi(config);
|
|
strncpy(m_ssid, config, sizeof(m_ssid)-1);
|
|
if (!next) return;
|
|
char* start = next;
|
|
next = nextSemi(start);
|
|
strncpy(m_password, start, sizeof(m_password)-1);
|
|
start = next;
|
|
next = nextSemi(start);
|
|
strncpy(mode, start, sizeof(mode)-1);
|
|
m_isAccessPoint = strcmp(mode, "ap") == 0;
|
|
free(config);
|
|
}
|
|
|
|
void WLANManager::start() {
|
|
// try to connect to stored AP
|
|
if (m_isAccessPoint || !connectToAp(NULL, NULL, NULL)) {
|
|
// fire up own AP
|
|
openAP();
|
|
m_dnsServer = new DNSServer();
|
|
m_dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
|
|
m_dnsServer->start(53, "*", WiFi.softAPIP());
|
|
}
|
|
}
|
|
|
|
bool WLANManager::connectToAp(const char* ssid, const char* pass, std::function<void()> callback) {
|
|
m_isAccessPoint = false;
|
|
if (ssid == NULL) {
|
|
WiFi.mode(WIFI_STA);
|
|
}
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
return true;
|
|
}
|
|
if (ssid) {
|
|
WiFi.begin(ssid, pass);
|
|
} else {
|
|
if (WiFi.SSID().length()) {
|
|
ETS_UART_INTR_DISABLE();
|
|
wifi_station_disconnect();
|
|
ETS_UART_INTR_ENABLE();
|
|
WiFi.begin();
|
|
} else {
|
|
WiFi.begin(m_ssid, m_password);
|
|
}
|
|
}
|
|
int connRes = waitForConnectResult();
|
|
if (connRes != WL_CONNECTED) {
|
|
WiFi.beginWPSConfig();
|
|
// should be connected at the end of WPS
|
|
connRes = waitForConnectResult();
|
|
}
|
|
if (connRes == WL_CONNECTED) {
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
}
|
|
WiFi.mode(WIFI_STA);
|
|
if (m_dnsServer) {
|
|
delete m_dnsServer;
|
|
m_dnsServer = NULL;
|
|
}
|
|
return connRes == WL_CONNECTED;
|
|
}
|
|
|
|
uint8_t WLANManager::waitForConnectResult() {
|
|
uint32_t start = millis();
|
|
boolean keepConnecting = true;
|
|
uint8_t status;
|
|
while (keepConnecting) {
|
|
status = WiFi.status();
|
|
if (millis() > start + _connectTimeout) {
|
|
keepConnecting = false;
|
|
}
|
|
if (status == WL_CONNECTED || status == WL_CONNECT_FAILED) {
|
|
keepConnecting = false;
|
|
}
|
|
delay(100);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void WLANManager::openAP() {
|
|
m_isAccessPoint = true;
|
|
// do we have stored settings?
|
|
if (!WiFi.isConnected()) {
|
|
WiFi.persistent(false);
|
|
// disconnect sta, start ap
|
|
WiFi.disconnect(); // this alone is not enough to stop the autoconnecter
|
|
WiFi.mode(WIFI_AP);
|
|
WiFi.persistent(true);
|
|
} else {
|
|
// setup AP
|
|
WiFi.mode(WIFI_AP_STA);
|
|
}
|
|
Serial.println(m_ssid);
|
|
Serial.println(m_password);
|
|
WiFi.softAP(m_ssid, m_password);
|
|
}
|
|
|
|
char* WLANManager::nextSemi(char* start) {
|
|
char* semi = strchr(start, ';');
|
|
if (!semi) return NULL;
|
|
*semi = 0;
|
|
return semi + 1;
|
|
}
|
|
|
|
bool WLANManager::isAccessPoint() const {
|
|
return m_isAccessPoint;
|
|
}
|
|
|
|
void WLANManager::save(const char* filename) {
|
|
String line = String(m_ssid) + ";" + m_password + ";" + (m_isAccessPoint ? "ap" : "client");
|
|
File file = LittleFS.open(filename, "w");
|
|
file.write(line.c_str(), line.length());
|
|
file.close();
|
|
}
|
|
|
|
const char* WLANManager::getSSID() const {
|
|
return m_ssid;
|
|
}
|
|
|
|
void WLANManager::loop() {
|
|
if (m_dnsServer) {
|
|
m_dnsServer->processNextRequest();
|
|
}
|
|
}
|
|
|
|
uint32_t WLANManager::getIP() const {
|
|
if (m_isAccessPoint)
|
|
return WiFi.softAPIP();
|
|
return WiFi.localIP();
|
|
}
|