CameraTrigger/arduino/main/wlanmanager.cpp

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();
}