WiFiConfig/src/WiFiConfig.cpp

917 lines
27 KiB
C++

#if defined(ESP32)
# include <rom/rtc.h> // duvod resetu (https://github.com/espressif/arduino-esp32/issues/449)
#endif
#include "WiFiConfig.h"
#include <sysvars.hpp>
#include "embHTML.h"
#include <encString.hpp>
#include <FS.h>
#ifndef USEDFS
# if defined(ESP32)
# ifdef USE_LITTLEFS
# include <LITTLEFS.h>
# define USEDFS LITTLEFS
# else
# include <SPIFFS.h>
# define USEDFS SPIFFS
# endif
# else
# include <LittleFS.h>
# define USEDFS LittleFS
# endif
#endif
#ifdef USE_WIFICONFIG_FSEDITOR
# include <SPIFFSEditor.h>
# include <FSWebEditor.h>
#endif
#if defined(ESP8266)
// ESP8266
# define SETHOSTNAME(a) WiFi.hostname(a)
#else
// ESP32
# define SETHOSTNAME(a) WiFi.setHostname(a)
#endif
#ifdef DEBUG_ESP_PORT
# define DEBUG_MSG(_1, ...) DEBUG_ESP_PORT.printf_P(PSTR(_1), ##__VA_ARGS__)
#else
# define DEBUG_MSG(...)
#endif
#if defined(ESP8266)
extern "C" {
# include "user_interface.h"
}
#else
# include <esp_wifi.h>
#endif
#define DNS_PORT 53
extern char WiFiDeviceName[];
static const char CHECKED[] PROGMEM = "checked='checked'";
static bool _doReconfig = false; // TODO: mozna nejak elegantneji? Ale zase setrime RAM...
static uint32_t ESP_getChipId(void)
{
#if defined(ESP8266)
return ESP.getChipId();
#else
uint32_t id = 0;
for (int i = 0; i < 17; i = i + 8) {
id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
return id;
#endif
}
IPAddress getOurIP(void)
{
IPAddress ipa;
WiFiMode_t wm = WiFi.getMode();
switch (wm) {
case WIFI_STA:
ipa = WiFi.localIP();
break;
case WIFI_AP:
ipa = WiFi.softAPIP();
break;
default:
ipa = IPAddress(0, 0, 0, 0); // nelze urcit ip adresu (bud je AP + STA aktivni, nebo je vypnute WiFi)
break;
}
return ipa;
}
uint8_t * getOurMAC(uint8_t *mac)
{
if (WIFIMODE_STA == svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE)))
return WiFi.macAddress(mac);
else
return WiFi.softAPmacAddress(mac);
}
WiFiConfigUsrParameter::WiFiConfigUsrParameter(const char *id, const char *label, const char *defaultValue, unsigned int length, storeparam_cb cb)
{
_next = NULL;
_cb = cb;
_id = id;
_label = label;
_length = length;
_value = new char[length + 1];
for (unsigned int i = 0; i < length; i++) {
_value[i] = 0;
}
if (defaultValue != NULL) {
strncpy(_value, defaultValue, length);
}
}
const char* WiFiConfigUsrParameter::getValue()
{
return _value;
}
const char* WiFiConfigUsrParameter::getID()
{
return _id;
}
const char* WiFiConfigUsrParameter::getLabel()
{
return _label;
}
int WiFiConfigUsrParameter::getValueLength()
{
return _length;
}
void WiFiConfigUsrParameter::setNext(WiFiConfigUsrParameter *n)
{
_next = n;
}
WiFiConfigUsrParameter *WiFiConfigUsrParameter::getNext()
{
return _next;
}
void WiFiConfigUsrParameter::setNewValue(const char *newval)
{
if (0 != strcmp(_value, newval))
_cb(newval);
}
WiFiConfigUsrParameter *WiFiConfig::_searchUsrParameter(const char *name)
{
WiFiConfigUsrParameter *ptr = _params;
while (NULL != ptr) {
if (0 == strcmp(name, ptr->getID()))
break;
ptr = ptr->getNext();
}
return ptr;
}
void WiFiConfig::addParameter(WiFiConfigUsrParameter *p)
{
p->setNext(_params);
_params = p;
}
String WiFiConfig::infoProcessor(const String & var)
{
if (var == F("SDK")) {
#if defined(ESP8266)
return ESP.getFullVersion();
#else
// TODO
return ESP.getSdkVersion();
#endif
} else if (var == F("FS")) {
#if defined(ESP8266)
return String(ESP.getFlashChipRealSize() / 1024);
#else
// TODO
return String(ESP.getFlashChipSize());
#endif
} else if (var == F("SS")) {
return String(ESP.getSketchSize() / 1024);
} else if (var == F("FSS")) {
return String(ESP.getFreeSketchSpace() / 1024);
} else if (var == F("STAMAC")) {
uint8_t mac[6];
uint8_t* macread = WiFi.macAddress(mac);
char macaddress[20];
sprintf_P(macaddress, PSTR("%02x:%02x:%02x:%02x:%02x:%02x"), macread[0], macread[1], macread[2], macread[3], macread[4], macread[5]);
return String(macaddress);
} else if (var == F("APMAC")) {
uint8_t mac[6];
char macaddress[20];
uint8_t *macread = WiFi.softAPmacAddress(mac);
sprintf_P(macaddress, PSTR("%02x:%02x:%02x:%02x:%02x:%02x"), macread[0], macread[1], macread[2], macread[3], macread[4], macread[5]);
return String(macaddress);
} else if (var == F("ESPID")) {
char buff[8];
sprintf_P(buff, PSTR("%06X"), ESP_getChipId());
return String(buff);
} else if (var == F("FID")){
#if defined(ESP8266)
char buff[10];
sprintf_P(buff, PSTR("%08X"), ESP.getFlashChipId());
return String(buff);
#endif
}
return String(F("???"));
}
String WiFiConfig::apProcessor(const String &var)
{
if (var == F("USER")) {
String result;
if (_params) {
WiFiConfigUsrParameter *up = _params;
char buff[128];
result.reserve(1024);
result = FPSTR(PAGE_PARAM_HDR);
while (NULL != up) {
sprintf_P(buff, PAGE_PARAM, up->getLabel(), up->getID(), up->getValueLength(), up->getValue());
result.concat(buff);
up = up->getNext();
}
}
return result;
} else if (var == F("SSID")) {
String result = svGetV<String>(F("ssid"), nullptr, F(WIFICFG_FILE));
strDecode(result);
return result;
} else if (var == F("PASS")) {
String result = svGetV<String>(F("pass"), nullptr, F(WIFICFG_FILE));
strDecode(result);
return result;
} else if (var == F("APMODE")) {
String result;
if (svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE)) == WIFIMODE_AP)
result = FPSTR(CHECKED);
return result;
} else if (var == F("APCHAN")) {
String result;
uint8_t chan = svGetV<int>(F("channel"), nullptr, F(WIFICFG_FILE));
if ((chan < 1) || (chan > 13))
chan = 1; // neplatne cislo kanalu nahradime nejnizsim
result = String(chan);
return result;
} else if (var == F("STATIC")) {
String result;
if (svGetV<int>(F("ipmode"), nullptr, F(WIFICFG_FILE)) == IPCONFIG_STATIC)
result = FPSTR(CHECKED);
return result;
} else if (var == F("IP")) {
String result;
result = _getIP(F("ip")).toString();
return result;
} else if (var == F("MASK")) {
String result;
result = _getIP(F("mask")).toString();
return result;
} else if (var == F("GATE")) {
String result;
result = _getIP(F("gate")).toString();
return result;
} else if(var == F("DNS")) {
String result;
result = _getIP(F("dns")).toString();
return result;
}
return String();
}
String WiFiConfig::rootProcessor(const String &var)
{
String content;
if (var == "STATUS") {
switch (_status) {
#if defined(ESP8266)
case STATION_IDLE:
content = F("Klid");
break;
case STATION_CONNECTING:
content = F("Připojování");
break;
case STATION_WRONG_PASSWORD:
content = F("Špatné heslo");
break;
case STATION_NO_AP_FOUND:
content = F("AP nenalezen");
break;
case STATION_CONNECT_FAIL:
content = F("Připojení selhalo");
break;
case STATION_GOT_IP:
content = F("Získaná ip");
break;
case 0xfe:
content = F("Špatná konfigurace");
break;
case 0xff:
content = F("Vynucená konfigurace");
break;
default:
content = F("Neznámý");
break;
#else
case WL_IDLE_STATUS:
content = F("Klid");
break;
case WL_NO_SSID_AVAIL:
content = F("AP nenalezen");
break;
case WL_CONNECT_FAILED:
content = F("Připojení selhalo");
break;
case 0xfe:
content = F("Špatná konfigurace");
break;
case 0xff:
content = F("Vynucená konfigurace");
break;
default:
content = F("Neznámý");
break;
#endif
}
} else if (var == F("RESTORE")) {
if (USEDFS.exists(F(WIFICFG_OLD_FILE))) {
content = FPSTR(PAGE_RESTORE);
}
}
return content;
}
void WiFiConfig::_handleRestore(AsyncWebServerRequest *request)
{
USEDFS.remove(F(WIFICFG_FILE));
USEDFS.rename(F(WIFICFG_OLD_FILE), F(WIFICFG_FILE));
request->onDisconnect([]() {
_doReconfig = true; // aktivujeme novou konfiguraci a restartujeme ESP
});
request->send_P(200, TEXTHTML, PAGE_SAVED);
}
void WiFiConfig::_handleNotFound(AsyncWebServerRequest *request)
{
DEBUG_MSG("Requested URI: %s\r\n", request->url().c_str());
if (request->url().endsWith(String(F("favicon.ico")))) {
request->send_P(404, TEXTPLAIN, PSTR("Err"));
} else {
String redirect;
redirect.reserve(256);
redirect = F("http://");
redirect.concat(WiFi.softAPIP().toString());
redirect.concat(F("/index.htm"));
DEBUG_MSG("Redirection to: %s\r\n", redirect.c_str());
request->redirect(redirect);
}
}
void WiFiConfig::_handleReset(AsyncWebServerRequest *request)
{
request->onDisconnect([]() {
ESP.restart();
});
request->send_P(200, TEXTHTML, PAGE_RESTART);
}
void WiFiConfig::_handleScan(AsyncWebServerRequest *request)
{
String json;
int n = WiFi.scanComplete();
json.reserve(1024);
json = F("{\"status\":");
json.concat(String(n));
json.concat(F(",\"ssids\":["));
if (n == WIFI_SCAN_FAILED) {
WiFi.scanNetworks(true);
} else if (n) {
for (int i = 0; i < n; ++i) {
if (i)
json.concat(F(","));
json.concat(("{\"rssi\":"));
json.concat(String(WiFi.RSSI(i)));
json.concat(F(",\"ssid\":\""));
json.concat(WiFi.SSID(i));
json.concat(F("\",\"channel\":"));
json.concat(String(WiFi.channel(i)));
json.concat(F(",\"secure\":"));
json.concat(String(WiFi.encryptionType(i)));
json.concat(F("}"));
}
WiFi.scanDelete();
if (WiFi.scanComplete() == WIFI_SCAN_FAILED) {
WiFi.scanNetworks(true);
}
}
json.concat(F("]}"));
request->send(200, FPSTR(TEXTJSON), json);
}
void WiFiConfig::_handleInfo(AsyncWebServerRequest *request)
{
request->send_P(200, TEXTHTML, PAGE_INFO, std::bind(&WiFiConfig::infoProcessor, this, std::placeholders::_1));
}
void WiFiConfig::_handleRoot(AsyncWebServerRequest *request)
{
request->send_P(200, TEXTHTML, PAGE_CAPTIVEPORTALCATCH, std::bind(&WiFiConfig::rootProcessor, this, std::placeholders::_1));
_time = millis() + (_timeout * 1000); // spocitame si novy cas, kdy budeme modul restartovat
}
IPAddress WiFiConfig::_getIP(const String &from)
{
uint32_t ipa;
int result;
ipa = svGetV<uint32_t>(from, &result, F(WIFICFG_FILE));
if (SV_OK != result)
ipa = 0;
return IPAddress(ipa);
}
void WiFiConfig::_handleDisplayAP(AsyncWebServerRequest *request)
{
request->send_P(200, TEXTHTML, PAGE_INDEX1, std::bind(&WiFiConfig::apProcessor, this, std::placeholders::_1));
_time = millis() + (360 * 1000); // spocitame si novy cas, kdy budeme modul restartovat (6 minut)
}
void WiFiConfig::_handleSetAP(AsyncWebServerRequest *request)
{
String str;
str.reserve(128);
str = request->arg(F("_s"));
if (str.length() > 0) {
uint8_t mode;
if (USEDFS.exists(F(WIFICFG_OLD_FILE))) {
USEDFS.remove(F(WIFICFG_OLD_FILE));
}
USEDFS.rename(F(WIFICFG_FILE), F(WIFICFG_OLD_FILE));
strEncode(str);
svSetV(F("ssid"), str, F(WIFICFG_FILE));
str = request->arg(F("_p"));
strEncode(str);
svSetV(F("pass"), str, F(WIFICFG_FILE));
str = request->arg(F("_a"));
if (str.length() > 0) {
mode = WIFIMODE_AP; // rezim AP
str = request->arg(F("_ch")); // kanal AP
svSetV<int>(F("channel"), str.toInt(), F(WIFICFG_FILE));
} else
mode = WIFIMODE_STA; // rezim STA
svSetV(F("mode"), mode, F(WIFICFG_FILE));
str = request->arg(F("_st"));
if (0 == str.length())
svSetV<int>(F("ipmode"), IPCONFIG_DHCP, F(WIFICFG_FILE)); // mame DHCP dynamickou konfiguraci
else {
// staticka ip konfigurace
IPAddress ipa;
svSetV<int>(F("ipmode"), IPCONFIG_STATIC, F(WIFICFG_FILE)); // mame statickou konfiguraci
str = request->arg(F("_i"));
ipa.fromString(str);
svSetV<uint32_t>(F("ip"), (uint32_t)ipa, F(WIFICFG_FILE));
str = request->arg(F("_m"));
ipa.fromString(str);
svSetV<uint32_t>(F("mask"), (uint32_t)ipa, F(WIFICFG_FILE));
str = request->arg(F("_g"));
ipa.fromString(str);
svSetV<uint32_t>(F("gw"), (uint32_t)ipa, F(WIFICFG_FILE));
str = request->arg(F("_d"));
ipa.fromString(str);
svSetV<uint32_t>(F("dns"), (uint32_t)ipa, F(WIFICFG_FILE));
}
// Uzivatelske parametry
for (unsigned i = 0; i < request->args(); i++) {
if (!request->argName(i).startsWith(F("_"))) { // vnitrni parametry WiFiConfig modulu zacinaji _, takze ty muzeme ignorovat
WiFiConfigUsrParameter *up = _searchUsrParameter(request->argName(i).c_str());
if (NULL != up)
up->setNewValue(request->arg(i).c_str());
}
}
}
request->onDisconnect([]() {
_doReconfig = true; // aktivujeme novou konfiguraci a restartujeme ESP
});
request->send_P(200, TEXTHTML, PAGE_SAVED);
}
// Start WiFi v rezimu AP pro nastaveni modulu
wificonfigresult_t WiFiConfig::_setupAP(wificonfig_cb cb)
{
String ssid = SETUP_SSID;
WiFi.persistent(false); // chranime flash pred zbytecnymi prepisy
dnsServer.reset(new DNSServer());
server = new AsyncWebServer(80);
server->reset();
/* Soft AP network parameters */
IPAddress apIP(172, 217, 28, 1);
IPAddress netMsk(255, 255, 255, 0);
WiFi.disconnect(); // pro jistotu se odpojime
// WiFi.mode(WIFI_AP);
#if defined(ARDUINO_ARCH_ESP8266)
WiFi.softAPConfig(apIP, apIP, netMsk);
if (ssid.endsWith(F("?"))) {
char lmac[16];
sprintf_P(lmac, PSTR("%06X"), ESP_getChipId());
ssid.replace(F("?"), String(lmac));
}
WiFi.softAP(ssid.c_str(), NULL, SETUP_CHANNEL);
WiFi.mode(WIFI_AP);
delay(500); // dulezite - jinak se nevraci spravna IP adresa !!! (udajne od verze 2.3.0 uz neni nutne)
#else
// osetreni padu ESP32 - https://github.com/espressif/arduino-esp32/issues/2025
if (ssid.endsWith(F("?"))) {
char lmac[16];
sprintf_P(lmac, PSTR("%06X"), ESP_getChipId());
ssid.replace(F("?"), String(lmac));
}
WiFi.softAP(ssid.c_str(), NULL, SETUP_CHANNEL);
delay(100); // kvuli ESP32 - cekame na start AP
WiFi.softAPConfig(apIP, apIP, netMsk);
#endif
dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); // spustime tzv. Captive portal - vsechny DNS dotazy jsou smerovany na nasi ip adresu
if (cb)
cb(WCS_CONFIGSTART); // signalizujeme start konfiguracniho serveru
// Nastavime handlery weboveho serveru pro konfiguraci
server->onNotFound(std::bind(&WiFiConfig::_handleNotFound, this, std::placeholders::_1));
server->on(PSTR("/config"), std::bind(&WiFiConfig::_handleDisplayAP, this, std::placeholders::_1));
server->on(PSTR("/scan"), std::bind(&WiFiConfig::_handleScan, this, std::placeholders::_1));
server->on(PSTR("/s"), std::bind(&WiFiConfig::_handleSetAP, this, std::placeholders::_1));
server->on(PSTR("/r"), std::bind(&WiFiConfig::_handleReset, this, std::placeholders::_1));
server->on(PSTR("/i"), std::bind(&WiFiConfig::_handleInfo, this, std::placeholders::_1));
server->on(PSTR("/o"), std::bind(&WiFiConfig::_handleRestore, this, std::placeholders::_1));
server->on(PSTR("/index.htm"), std::bind(&WiFiConfig::_handleRoot, this, std::placeholders::_1));
#ifdef USE_WIFICONFIG_OTAUPDATE
server->on(PSTR("/u"), []() {
server->send_P(200, TEXTHTML, PAGE_UPDATE);
});
server->on(PSTR("/update"), HTTP_POST, []() {
server->sendHeader(F("Connection"), F("close"));
server->send(200, FPSTR(TEXTPLAIN), (Update.hasError()) ? F("FAIL") : F("OK"));
ESP.restart();
}, []() {
HTTPUpload& upload = server->upload();
if (upload.status == UPLOAD_FILE_START) {
WiFiUDP::stopAll();
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace)) { //start with max available size
//Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
//Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
//Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
//Update.printError(Serial);
}
}
yield();
});
#endif
#ifdef USE_WIFICONFIG_FSEDITOR
#if 0
#if defined(ESP8266)
server->addHandler(new SPIFFSEditor("admin", "nimda", USEDFS));
#else
server->addHandler(new SPIFFSEditor(USEDFS, "admin", "nimda"));
#endif
#else
#if defined(ESP8266)
server->addHandler(new FSWebEditor("admin", "nimda"));
#else
server->addHandler(new FSWebEditor(USEDFS, "admin", "nimda"));
#endif
#endif
#endif
server->begin(); // startujeme webovy server
// Asynchronne ziskame seznam okolnich AP prakticky okamzite po startu konfiguracniho AP
int n = WiFi.scanComplete();
if (n == WIFI_SCAN_FAILED) {
WiFi.scanNetworks(true);
}
while (1) {
if (_doReconfig) {
// mame aktivovat novou konfiguraci
_prepareWifi();
ESP.restart();
}
if (cb)
cb(WCS_CONFIGWAIT); // volame uzivatelsky callback (napr. signalizace)
dnsServer->processNextRequest();
yield(); // procesy uvnitr systemu ESP potrebuji take svuj cas
if (_timeout) {
if (millis() > _time) {
DEBUG_MSG("AP timeout\r\n");
if (cb)
cb(WCS_CONFIGTIMEOUT); // signalizujeme timeout
break; // ukoncime cekani a vracime se
}
}
}
// tady by asi melo byt zastaveni weboveho a dns serveru...
dnsServer->stop();
server->end();
return WCR_TIMEOUT; // nepripojeno, vyprsel timeout konfiguracniho AP
}
// Testovani, zda se modul pripojil k AP
bool WiFiConfig::_testWifi(wificonfig_cb cb)
{
uint32_t startt = millis();
#if !defined(ESP8266)
_prepareWifi(); // nakonfigurujeme ESP32 dle nastavenych parametru
#endif
DEBUG_MSG("Trying to connect.\r\n");
while ((millis() - startt) < WIFI_STA_CONNECT_TIMEOUT) {
if (WL_CONNECTED == WiFi.status()) {
DEBUG_MSG("Connected...\r\n");
if (cb)
cb(WCS_CONNECTED);
return true; // jsme pripojeni
}
yield();
if (cb)
cb(WCS_CONNECTING); // signalizujeme pokracujici pokus o spojeni
}
DEBUG_MSG("Not connected!\r\n");
#if defined(ESP8266)
_status = wifi_station_get_connect_status();
#else
_status = WiFi.status();
#endif
return false; // pripojeni se nezdarilo
}
wificonfigresult_t WiFiConfig::begin(int forceConfigure, wificonfig_cb cb)
{
wificonfigresult_t result = WCR_OK; // predpokladame, ze se pripojeni podari
DEBUG_MSG("\r\n\r\n"); // oddeleni vypisu
if (0 == forceConfigure) {
DEBUG_MSG("Force config.\r\n");
_status = 0xff;
result = _setupAP(cb);
} else {
#if defined(ESP8266)
if (svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE)) != WiFi.getMode()) {
// neshoduje se rezim - musime spustit konfiguracni AP (poskozena konfigurace)
DEBUG_MSG("Wrong config (%d, %d)\r\n", svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE)), WiFi.getMode());
_status = 0xfe;
result = _setupAP(cb);
} else
#endif
{
switch (svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE))) {
case WIFIMODE_STA: {
DEBUG_MSG("STA mode.\r\n");
SETHOSTNAME(WiFiDeviceName); // nastavime jmeno zarizeni
if (IPCONFIG_STATIC == svGetV<int>(F("ipmode"), nullptr, F(WIFICFG_FILE))) {
DEBUG_MSG("Static configuration SET.\r\n");
WiFi.config(IPAddress(svGetV<uint32_t>(F("ip"), nullptr, F(WIFICFG_FILE))), IPAddress(svGetV<uint32_t>(F("gw"), nullptr, F(WIFICFG_FILE))),
IPAddress(svGetV<uint32_t>(F("mask"), nullptr, F(WIFICFG_FILE))), IPAddress(svGetV<uint32_t>(F("dns"), nullptr, F(WIFICFG_FILE))));
delay(100);
}
if (WC_DONT_RUN_CONFIGAP == _timeout)
result = WCR_CONFIGAP_NOT_STARTED; // nemame spoustet konfiguracni AP - vracime se hned
else {
if (cb)
cb(WCS_CONNECTSTART); // signalizujeme zacatek pokusu o pripojeni
if (!_testWifi(cb)) {
result = _setupAP(cb); // modul se nepripojil - startujeme AP rezim
}
}
}
break;
case WIFIMODE_AP:
DEBUG_MSG("AP mode.\r\n");
if (IPCONFIG_STATIC == svGetV<int>(F("ipmode"), nullptr, F(WIFICFG_FILE))) {
WiFi.softAPConfig(IPAddress(svGetV<uint32_t>(F("ip"), nullptr, F(WIFICFG_FILE))), IPAddress(svGetV<uint32_t>(F("gw"), nullptr, F(WIFICFG_FILE))),
IPAddress(svGetV<uint32_t>(F("mask"), nullptr, F(WIFICFG_FILE))));
}
if (cb)
cb(WCS_CONNECTED); // signalizujeme pripojeni (zde se nic jineho stejne nestane...)
break;
#if !defined(ESP8266)
default:
DEBUG_MSG("Wrong config (%d)\r\n", svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE)));
_status = 0xfe;
result = _setupAP(cb);
break;
#endif
}
}
}
return result; // mame vyreseno
}
wificonfigresult_t WiFiConfig::begin(int forceConfigure, int timeout, wificonfig_cb cb = NULL)
{
if ((timeout > 0) && (40 > timeout))
timeout = 40; // timeout musi byt minimalne 40 sekund
if ((0 == forceConfigure) && (WC_DONT_RUN_CONFIGAP == timeout))
timeout = 40;
_timeout = timeout;
if (_timeout > 0)
_time = millis() + (_timeout * 1000); // spocitame si novy cas, kdy budeme modul restartovat
return begin(forceConfigure, cb); // spustime WiFi
}
#if defined(ESP32)
static const char INITTXT[] = "{}";
#endif
void WiFiConfig::initConfig(const String &ssid, const String &pass, const int mode, const int ipcfg, const IPAddress &ip, const IPAddress &mask, const IPAddress &gw, const IPAddress &dns)
{
String es;
DEBUG_MSG("initConfig %d\r\n", mode);
if (!USEDFS.exists(F(WIFICFG_FILE))) {
DEBUG_MSG("Create file...\r\n");
File f;
f = USEDFS.open(F(WIFICFG_FILE), "w");
#if defined(ESP8266)
f.write("{}");
#else
f.write((const uint8_t *)INITTXT, strlen(INITTXT));
#endif
f.close();
}
es = ssid;
strEncode(es);
svSetV<String>(F("ssid"), es, F(WIFICFG_FILE));
es = pass;
strEncode(es);
svSetV<String>(F("pass"), es, F(WIFICFG_FILE));
svSetV(F("mode"), mode, F(WIFICFG_FILE));
svSetV(F("ipmode"), ipcfg, F(WIFICFG_FILE));
svSetV<int>(F("channel"), 3, F(WIFICFG_FILE));
svSetV<uint32_t>(F("ip"), (uint32_t)ip, F(WIFICFG_FILE));
svSetV<uint32_t>(F("mask"), (uint32_t)mask, F(WIFICFG_FILE));
svSetV<uint32_t>(F("gw"), (uint32_t)gw, F(WIFICFG_FILE));
svSetV<uint32_t>(F("dns"), (uint32_t)dns, F(WIFICFG_FILE));
_prepareWifi(); // nastavime novou WiFi konfiguraci
}
void WiFiConfig::_prepareWifi(void)
{
DEBUG_MSG("Prepare wifi...\r\n");
WiFi.persistent(true); // chceme, aby si modul zapamatoval konfiguraci
WiFi.disconnect(); // vsechno odpojime
delay(100);
String s = svGetV<String>(F("ssid"), nullptr, F(WIFICFG_FILE));
strDecode(s);
String pass = svGetV<String>(F("pass"), nullptr, F(WIFICFG_FILE));
strDecode(pass);
int mode = svGetV<int>(F("mode"), nullptr, F(WIFICFG_FILE));
DEBUG_MSG("SSID %s, Pass %s, Mode %d\r\n", s.c_str(), pass.c_str(), mode);
switch (mode) {
case WIFIMODE_STA: {
DEBUG_MSG("STA mode.\r\n");
#if defined(ESP8266)
if (strlen(WiFiDeviceName)) {
SETHOSTNAME(WiFiDeviceName); // nastavime jmeno zarizeni
}
#endif
if (IPCONFIG_STATIC == svGetV<int>(F("ipmode"), nullptr, F(WIFICFG_FILE))) {
DEBUG_MSG("Static configuration.\r\n");
WiFi.config(IPAddress(svGetV<uint32_t>(F("ip"), nullptr, F(WIFICFG_FILE))), IPAddress(svGetV<uint32_t>(F("gw"), nullptr, F(WIFICFG_FILE))),
IPAddress(svGetV<uint32_t>(F("mask"), nullptr, F(WIFICFG_FILE))), IPAddress(svGetV<uint32_t>(F("dns"), nullptr, F(WIFICFG_FILE))));
delay(100);
}
WiFi.mode(WIFI_STA); // startujeme WiFi v rezimu klienta
WiFi.begin(s.c_str(), pass.c_str());
DEBUG_MSG("STA params: %s, %s\r\n", s.c_str(), pass.c_str());
#if !defined(ESP8266)
if (strlen(WiFiDeviceName)) {
SETHOSTNAME(WiFiDeviceName); // nastavime jmeno zarizeni
}
#endif
#if defined(ESP8266)
WiFi.setAutoConnect(true);
WiFi.setAutoReconnect(true);
// wifi_station_set_auto_connect(true);
#else
//esp_wifi_set_auto_connect(true);
#endif
delay(1000);
}
break;
case WIFIMODE_AP:{
DEBUG_MSG("AP mode.\r\n");
if (s.endsWith(F("?"))) {
char lmac[16];
sprintf_P(lmac, PSTR("%06X"), ESP_getChipId());
s.replace(F("?"), String(lmac));
}
WiFi.mode(WIFI_AP); // startujeme AP
int chan = svGetV<int>(F("channel"), nullptr, F(WIFICFG_FILE));
if (pass.length()) {
// je zadane heslo do AP
WiFi.softAP(s.c_str(), pass.c_str(), chan);
} else {
// otevreny AP
WiFi.softAP(s.c_str(), NULL, chan);
}
if (IPCONFIG_STATIC == svGetV<int>(F("ipmode"), nullptr, F(WIFICFG_FILE))) {
delay(100); // kvuli ESP32 - cekame na start AP
WiFi.softAPConfig(IPAddress(svGetV<uint32_t>(F("ip"), nullptr, F(WIFICFG_FILE))), IPAddress(svGetV<uint32_t>(F("gw"), nullptr, F(WIFICFG_FILE))),
IPAddress(svGetV<uint32_t>(F("mask"), nullptr, F(WIFICFG_FILE))));
}
break;
}
default: // jakykoliv neznamy rezim (mozna zavada na EEPROM???)
DEBUG_MSG("Mode Error (%d)!!\r\n", (int)mode);
break;
}
delay(1000); // cekame XX sekund na ulozeni atd...
}
// EOF