917 lines
27 KiB
C++
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
|