2018-11-19 17:07:25 +00:00
|
|
|
/*
|
2019-10-27 10:13:24 +00:00
|
|
|
support_wifi.ino - wifi support for Tasmota
|
2018-11-19 17:07:25 +00:00
|
|
|
|
2019-01-01 12:55:01 +00:00
|
|
|
Copyright (C) 2019 Theo Arends
|
2018-11-19 17:07:25 +00:00
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Wifi
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2018-11-20 13:10:32 +00:00
|
|
|
#ifndef WIFI_RSSI_THRESHOLD
|
2019-03-31 10:59:04 +01:00
|
|
|
#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network
|
2018-11-20 13:10:32 +00:00
|
|
|
#endif
|
|
|
|
#ifndef WIFI_RESCAN_MINUTES
|
2019-03-31 10:59:04 +01:00
|
|
|
#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan
|
2018-11-20 13:10:32 +00:00
|
|
|
#endif
|
|
|
|
|
2019-03-31 10:59:04 +01:00
|
|
|
const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart
|
|
|
|
const uint8_t WIFI_CHECK_SEC = 20; // seconds
|
|
|
|
const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds
|
2018-11-19 17:07:25 +00:00
|
|
|
|
2019-08-18 12:23:43 +01:00
|
|
|
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
|
2019-10-11 06:40:55 +01:00
|
|
|
#if LWIP_IPV6
|
|
|
|
#include <AddrList.h> // IPv6 DualStack
|
2019-10-14 11:34:01 +01:00
|
|
|
#endif // LWIP_IPV6=1
|
2018-11-19 17:07:25 +00:00
|
|
|
|
2019-08-17 16:13:09 +01:00
|
|
|
struct WIFI {
|
2019-08-18 12:23:43 +01:00
|
|
|
uint32_t last_event = 0; // Last wifi connection event
|
|
|
|
uint32_t downtime = 0; // Wifi down duration
|
|
|
|
uint16_t link_count = 0; // Number of wifi re-connect
|
2019-08-17 16:13:09 +01:00
|
|
|
uint8_t counter;
|
|
|
|
uint8_t retry_init;
|
|
|
|
uint8_t retry;
|
|
|
|
uint8_t status;
|
|
|
|
uint8_t config_type = 0;
|
|
|
|
uint8_t config_counter = 0;
|
2019-08-18 12:23:43 +01:00
|
|
|
uint8_t mdns_begun = 0; // mDNS active
|
2019-08-17 16:13:09 +01:00
|
|
|
uint8_t scan_state;
|
|
|
|
uint8_t bssid[6];
|
|
|
|
} Wifi;
|
2018-11-19 17:07:25 +00:00
|
|
|
|
|
|
|
int WifiGetRssiAsQuality(int rssi)
|
|
|
|
{
|
|
|
|
int quality = 0;
|
|
|
|
|
|
|
|
if (rssi <= -100) {
|
|
|
|
quality = 0;
|
|
|
|
} else if (rssi >= -50) {
|
|
|
|
quality = 100;
|
|
|
|
} else {
|
|
|
|
quality = 2 * (rssi + 100);
|
|
|
|
}
|
|
|
|
return quality;
|
|
|
|
}
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
bool WifiConfigCounter(void)
|
2018-11-19 17:07:25 +00:00
|
|
|
{
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.config_counter) {
|
|
|
|
Wifi.config_counter = WIFI_CONFIG_SEC;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
return (Wifi.config_counter);
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void WifiConfig(uint8_t type)
|
|
|
|
{
|
2019-08-17 16:13:09 +01:00
|
|
|
if (!Wifi.config_type) {
|
2018-11-19 17:07:25 +00:00
|
|
|
if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; }
|
2019-05-20 14:09:42 +01:00
|
|
|
#ifdef USE_EMULATION
|
2018-11-19 17:07:25 +00:00
|
|
|
UdpDisconnect();
|
|
|
|
#endif // USE_EMULATION
|
|
|
|
WiFi.disconnect(); // Solve possible Wifi hangs
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.config_type = type;
|
2018-11-19 17:07:25 +00:00
|
|
|
|
|
|
|
#ifndef USE_WEBSERVER
|
2019-10-22 15:34:25 +01:00
|
|
|
if (WIFI_MANAGER == Wifi.config_type) {
|
|
|
|
Wifi.config_type = WIFI_SERIAL;
|
|
|
|
}
|
2018-11-19 17:07:25 +00:00
|
|
|
#endif // USE_WEBSERVER
|
|
|
|
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.config_counter = WIFI_CONFIG_SEC; // Allow up to WIFI_CONFIG_SECS seconds for phone to provide ssid/pswd
|
|
|
|
Wifi.counter = Wifi.config_counter +5;
|
2018-11-19 17:07:25 +00:00
|
|
|
blinks = 1999;
|
2019-08-17 16:13:09 +01:00
|
|
|
if (WIFI_RESTART == Wifi.config_type) {
|
2018-11-19 17:07:25 +00:00
|
|
|
restart_flag = 2;
|
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
else if (WIFI_SERIAL == Wifi.config_type) {
|
2018-11-19 17:07:25 +00:00
|
|
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES));
|
|
|
|
}
|
|
|
|
#ifdef USE_WEBSERVER
|
2019-08-17 16:13:09 +01:00
|
|
|
else if (WIFI_MANAGER == Wifi.config_type || WIFI_MANAGER_RESET_ONLY == Wifi.config_type) {
|
2018-11-19 17:07:25 +00:00
|
|
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES));
|
2019-08-17 16:13:09 +01:00
|
|
|
WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == Wifi.config_type);
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
#endif // USE_WEBSERVER
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WiFiSetSleepMode(void)
|
|
|
|
{
|
|
|
|
/* Excerpt from the esp8266 non os sdk api reference (v2.2.1):
|
|
|
|
* Sets sleep type for power saving. Set WIFI_NONE_SLEEP to disable power saving.
|
|
|
|
* - Default mode: WIFI_MODEM_SLEEP.
|
|
|
|
* - In order to lower the power comsumption, ESP8266 changes the TCP timer
|
|
|
|
* tick from 250ms to 3s in WIFI_LIGHT_SLEEP mode, which leads to increased timeout for
|
|
|
|
* TCP timer. Therefore, the WIFI_MODEM_SLEEP or deep-sleep mode should be used
|
|
|
|
* where there is a requirement for the accurancy of the TCP timer.
|
|
|
|
*
|
|
|
|
* Sleep is disabled in core 2.4.1 and 2.4.2 as there are bugs in their SDKs
|
2019-10-27 10:13:24 +00:00
|
|
|
* See https://github.com/arendst/Tasmota/issues/2559
|
2018-11-19 17:07:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
// Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255
|
|
|
|
#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
|
|
|
|
#else // Enabled in 2.3.0, 2.4.0 and stage
|
2019-11-03 12:51:22 +00:00
|
|
|
if (sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
|
|
|
|
WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
2019-11-03 12:51:22 +00:00
|
|
|
WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default)
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-11-19 22:06:42 +00:00
|
|
|
void WifiBegin(uint8_t flag, uint8_t channel)
|
2018-11-19 17:07:25 +00:00
|
|
|
{
|
|
|
|
const char kWifiPhyMode[] = " BGN";
|
|
|
|
|
2019-05-20 14:09:42 +01:00
|
|
|
#ifdef USE_EMULATION
|
2018-11-19 17:07:25 +00:00
|
|
|
UdpDisconnect();
|
|
|
|
#endif // USE_EMULATION
|
|
|
|
|
|
|
|
#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // (!strncmp_P(ESP.getSdkVersion(),PSTR("1.5.3"),5))
|
|
|
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186));
|
|
|
|
WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186
|
|
|
|
#endif
|
|
|
|
|
|
|
|
WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083)
|
|
|
|
WiFi.disconnect(true); // Delete SDK wifi config
|
|
|
|
delay(200);
|
|
|
|
WiFi.mode(WIFI_STA); // Disable AP mode
|
|
|
|
WiFiSetSleepMode();
|
2019-02-18 14:41:41 +00:00
|
|
|
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N
|
|
|
|
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G
|
2018-11-19 17:07:25 +00:00
|
|
|
if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); }
|
2018-11-20 13:10:32 +00:00
|
|
|
// WiFi.setAutoReconnect(true);
|
2018-11-19 17:07:25 +00:00
|
|
|
switch (flag) {
|
|
|
|
case 0: // AP1
|
|
|
|
case 1: // AP2
|
|
|
|
Settings.sta_active = flag;
|
|
|
|
break;
|
|
|
|
case 2: // Toggle
|
|
|
|
Settings.sta_active ^= 1;
|
|
|
|
} // 3: Current AP
|
|
|
|
if ('\0' == Settings.sta_ssid[Settings.sta_active][0]) { Settings.sta_active ^= 1; } // Skip empty SSID
|
|
|
|
if (Settings.ip_address[0]) {
|
|
|
|
WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP
|
|
|
|
}
|
|
|
|
WiFi.hostname(my_hostname);
|
2018-11-19 22:06:42 +00:00
|
|
|
if (channel) {
|
2019-08-17 16:13:09 +01:00
|
|
|
WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], channel, Wifi.bssid);
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
|
|
|
WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active]);
|
|
|
|
}
|
2019-03-08 14:15:42 +00:00
|
|
|
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."),
|
2018-11-19 17:07:25 +00:00
|
|
|
Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname);
|
2019-10-11 06:40:55 +01:00
|
|
|
|
|
|
|
#if LWIP_IPV6
|
|
|
|
for (bool configured = false; !configured;) {
|
2019-10-11 13:39:58 +01:00
|
|
|
uint16_t cfgcnt = 0;
|
|
|
|
for (auto addr : addrList) {
|
|
|
|
if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) {
|
2019-10-13 13:15:32 +01:00
|
|
|
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str());
|
2019-10-11 13:39:58 +01:00
|
|
|
break; // IPv6 is mandatory but stop after 15 seconds
|
|
|
|
}
|
2019-10-11 06:40:55 +01:00
|
|
|
delay(500); // Loop until real IPv6 address is aquired or too many tries failed
|
|
|
|
cfgcnt++;
|
|
|
|
}
|
|
|
|
}
|
2019-10-14 11:34:01 +01:00
|
|
|
#endif // LWIP_IPV6=1
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
|
2018-11-19 22:06:42 +00:00
|
|
|
void WifiBeginAfterScan()
|
|
|
|
{
|
2018-11-20 11:03:42 +00:00
|
|
|
static int8_t best_network_db;
|
2018-11-19 22:06:42 +00:00
|
|
|
|
|
|
|
// Not active
|
2019-08-17 16:13:09 +01:00
|
|
|
if (0 == Wifi.scan_state) { return; }
|
2018-11-19 22:06:42 +00:00
|
|
|
// Init scan when not connected
|
2019-08-17 16:13:09 +01:00
|
|
|
if (1 == Wifi.scan_state) {
|
|
|
|
memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid));
|
2018-11-20 11:03:42 +00:00
|
|
|
best_network_db = -127;
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.scan_state = 3;
|
2018-11-19 22:06:42 +00:00
|
|
|
}
|
|
|
|
// Init scan when connected
|
2019-08-17 16:13:09 +01:00
|
|
|
if (2 == Wifi.scan_state) {
|
2018-11-20 11:03:42 +00:00
|
|
|
uint8_t* bssid = WiFi.BSSID(); // Get current bssid
|
2019-08-17 16:13:09 +01:00
|
|
|
memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid));
|
2018-11-20 11:03:42 +00:00
|
|
|
best_network_db = WiFi.RSSI(); // Get current rssi and add threshold
|
2018-12-21 12:53:38 +00:00
|
|
|
if (best_network_db < -WIFI_RSSI_THRESHOLD) { best_network_db += WIFI_RSSI_THRESHOLD; }
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.scan_state = 3;
|
2018-11-19 22:06:42 +00:00
|
|
|
}
|
|
|
|
// Init scan
|
2019-08-17 16:13:09 +01:00
|
|
|
if (3 == Wifi.scan_state) {
|
2018-11-19 22:06:42 +00:00
|
|
|
if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) {
|
|
|
|
WiFi.scanNetworks(true); // Start wifi scan async
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.scan_state++;
|
2018-11-19 22:06:42 +00:00
|
|
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR("Network (re)scan started..."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int8_t wifi_scan_result = WiFi.scanComplete();
|
|
|
|
// Check scan done
|
2019-08-17 16:13:09 +01:00
|
|
|
if (4 == Wifi.scan_state) {
|
2018-11-19 22:06:42 +00:00
|
|
|
if (wifi_scan_result != WIFI_SCAN_RUNNING) {
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.scan_state++;
|
2018-11-19 22:06:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Scan done
|
2019-08-17 16:13:09 +01:00
|
|
|
if (5 == Wifi.scan_state) {
|
2018-11-19 22:06:42 +00:00
|
|
|
int32_t channel = 0; // No scan result
|
|
|
|
int8_t ap = 3; // AP default if not found
|
2018-11-20 11:03:42 +00:00
|
|
|
uint8_t last_bssid[6]; // Save last bssid
|
2019-08-17 16:13:09 +01:00
|
|
|
memcpy((void*) &last_bssid, (void*) &Wifi.bssid, sizeof(last_bssid));
|
2018-11-19 22:06:42 +00:00
|
|
|
|
|
|
|
if (wifi_scan_result > 0) {
|
|
|
|
// Networks found
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < wifi_scan_result; ++i) {
|
2018-11-19 22:06:42 +00:00
|
|
|
|
|
|
|
String ssid_scan;
|
|
|
|
int32_t rssi_scan;
|
|
|
|
uint8_t sec_scan;
|
|
|
|
uint8_t* bssid_scan;
|
|
|
|
int32_t chan_scan;
|
|
|
|
bool hidden_scan;
|
|
|
|
|
|
|
|
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan);
|
|
|
|
|
|
|
|
bool known = false;
|
2019-06-30 15:44:36 +01:00
|
|
|
uint32_t j;
|
2018-11-19 22:06:42 +00:00
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
if (ssid_scan == Settings.sta_ssid[j]) { // SSID match
|
|
|
|
known = true;
|
2018-11-20 11:03:42 +00:00
|
|
|
if (rssi_scan > best_network_db) { // Best network
|
2018-11-19 22:06:42 +00:00
|
|
|
if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan
|
2018-11-20 11:03:42 +00:00
|
|
|
best_network_db = (int8_t)rssi_scan;
|
2018-11-19 22:06:42 +00:00
|
|
|
channel = chan_scan;
|
|
|
|
ap = j; // AP1 or AP2
|
2019-08-17 16:13:09 +01:00
|
|
|
memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid));
|
2018-11-19 22:06:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-08-10 16:34:59 +01:00
|
|
|
char hex_char[18];
|
|
|
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %s, RSSI %d, Encryption %d"),
|
|
|
|
i,
|
|
|
|
(known) ? (j) ? '2' : '1' : '-',
|
|
|
|
ssid_scan.c_str(),
|
|
|
|
chan_scan,
|
2019-08-13 18:53:12 +01:00
|
|
|
ToHex_P((unsigned char*)bssid_scan, 6, hex_char, sizeof(hex_char), ':'),
|
2019-08-10 16:34:59 +01:00
|
|
|
rssi_scan,
|
|
|
|
(sec_scan == ENC_TYPE_NONE) ? 0 : 1);
|
2018-11-19 22:06:42 +00:00
|
|
|
delay(0);
|
|
|
|
}
|
|
|
|
WiFi.scanDelete(); // Clean up Ram
|
|
|
|
delay(0);
|
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.scan_state = 0;
|
2018-11-20 11:03:42 +00:00
|
|
|
// If bssid changed then (re)connect wifi
|
2019-08-17 16:13:09 +01:00
|
|
|
for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) {
|
|
|
|
if (last_bssid[i] != Wifi.bssid[i]) {
|
2018-11-19 22:06:42 +00:00
|
|
|
WifiBegin(ap, channel); // 0 (AP1), 1 (AP2) or 3 (default AP)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-18 16:05:25 +00:00
|
|
|
uint16_t WifiLinkCount()
|
2019-02-18 14:41:41 +00:00
|
|
|
{
|
2019-08-17 16:13:09 +01:00
|
|
|
return Wifi.link_count;
|
2019-02-18 14:41:41 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 17:02:22 +00:00
|
|
|
String WifiDowntime()
|
|
|
|
{
|
2019-08-17 16:13:09 +01:00
|
|
|
return GetDuration(Wifi.downtime);
|
2019-02-18 17:02:22 +00:00
|
|
|
}
|
|
|
|
|
2018-11-19 17:07:25 +00:00
|
|
|
void WifiSetState(uint8_t state)
|
|
|
|
{
|
|
|
|
if (state == global_state.wifi_down) {
|
|
|
|
if (state) {
|
|
|
|
rules_flag.wifi_connected = 1;
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.link_count++;
|
|
|
|
Wifi.downtime += UpTime() - Wifi.last_event;
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
|
|
|
rules_flag.wifi_disconnected = 1;
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.last_event = UpTime();
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
global_state.wifi_down = state ^1;
|
|
|
|
}
|
|
|
|
|
2019-10-14 11:34:01 +01:00
|
|
|
#if LWIP_IPV6
|
2019-10-13 13:15:32 +01:00
|
|
|
bool WifiCheckIPv6(void)
|
|
|
|
{
|
|
|
|
bool ipv6_global=false;
|
|
|
|
|
|
|
|
for (auto a : addrList) {
|
|
|
|
if(!a.isLocal() && a.isV6()) ipv6_global=true;
|
|
|
|
}
|
|
|
|
return ipv6_global;
|
|
|
|
}
|
2019-10-24 12:13:16 +01:00
|
|
|
|
|
|
|
bool WifiCheckIPAddrStatus(void) // Return false for 169.254.x.x or fe80::/64
|
|
|
|
{
|
|
|
|
bool ip_global=false;
|
|
|
|
|
|
|
|
for (auto a : addrList) {
|
|
|
|
if(!a.isLocal()) ip_global=true;
|
|
|
|
}
|
|
|
|
return ip_global;
|
|
|
|
}
|
2019-10-14 11:34:01 +01:00
|
|
|
#endif // LWIP_IPV6=1
|
2019-10-13 13:15:32 +01:00
|
|
|
|
2018-11-19 17:07:25 +00:00
|
|
|
void WifiCheckIp(void)
|
|
|
|
{
|
2019-10-14 11:34:01 +01:00
|
|
|
#if LWIP_IPV6
|
2019-10-24 12:13:16 +01:00
|
|
|
if(WifiCheckIPAddrStatus()) {
|
2019-10-13 13:15:32 +01:00
|
|
|
Wifi.status = WL_CONNECTED;
|
|
|
|
#else
|
2018-11-19 17:07:25 +00:00
|
|
|
if ((WL_CONNECTED == WiFi.status()) && (static_cast<uint32_t>(WiFi.localIP()) != 0)) {
|
2019-10-14 11:34:01 +01:00
|
|
|
#endif // LWIP_IPV6=1
|
2018-11-19 17:07:25 +00:00
|
|
|
WifiSetState(1);
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.counter = WIFI_CHECK_SEC;
|
|
|
|
Wifi.retry = Wifi.retry_init;
|
|
|
|
AddLog_P((Wifi.status != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED));
|
|
|
|
if (Wifi.status != WL_CONNECTED) {
|
2018-11-19 17:07:25 +00:00
|
|
|
// AddLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses"));
|
|
|
|
Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP();
|
|
|
|
Settings.ip_address[2] = (uint32_t)WiFi.subnetMask();
|
|
|
|
Settings.ip_address[3] = (uint32_t)WiFi.dnsIP();
|
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.status = WL_CONNECTED;
|
2019-01-17 11:34:06 +00:00
|
|
|
#ifdef USE_DISCOVERY
|
|
|
|
#ifdef WEBSERVER_ADVERTISE
|
2019-08-17 16:13:09 +01:00
|
|
|
if (2 == Wifi.mdns_begun) {
|
2019-01-16 16:53:23 +00:00
|
|
|
MDNS.update();
|
|
|
|
AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update");
|
|
|
|
}
|
2019-01-17 11:34:06 +00:00
|
|
|
#endif // USE_DISCOVERY
|
|
|
|
#endif // WEBSERVER_ADVERTISE
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
|
|
|
WifiSetState(0);
|
|
|
|
uint8_t wifi_config_tool = Settings.sta_config;
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.status = WiFi.status();
|
|
|
|
switch (Wifi.status) {
|
2018-11-19 17:07:25 +00:00
|
|
|
case WL_CONNECTED:
|
|
|
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS));
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.status = 0;
|
|
|
|
Wifi.retry = Wifi.retry_init;
|
2018-11-19 17:07:25 +00:00
|
|
|
break;
|
|
|
|
case WL_NO_SSID_AVAIL:
|
|
|
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED));
|
|
|
|
if (WIFI_WAIT == Settings.sta_config) {
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.retry = Wifi.retry_init;
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.retry > (Wifi.retry_init / 2)) {
|
|
|
|
Wifi.retry = Wifi.retry_init / 2;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
else if (Wifi.retry) {
|
|
|
|
Wifi.retry = 0;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WL_CONNECT_FAILED:
|
|
|
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD));
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.retry > (Wifi.retry_init / 2)) {
|
|
|
|
Wifi.retry = Wifi.retry_init / 2;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
else if (Wifi.retry) {
|
|
|
|
Wifi.retry = 0;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: // WL_IDLE_STATUS and WL_DISCONNECTED
|
2019-08-17 16:13:09 +01:00
|
|
|
if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) {
|
2018-11-19 17:07:25 +00:00
|
|
|
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT));
|
|
|
|
} else {
|
|
|
|
if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) {
|
2019-10-22 15:34:25 +01:00
|
|
|
wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.retry = 0;
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
|
|
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.retry) {
|
2019-11-03 12:51:22 +00:00
|
|
|
if (Settings.flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.retry_init == Wifi.retry) {
|
|
|
|
Wifi.scan_state = 1; // Select scanned SSID
|
2018-11-20 13:10:32 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.retry_init == Wifi.retry) {
|
2018-11-19 22:06:42 +00:00
|
|
|
WifiBegin(3, 0); // Select default SSID
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
if ((Settings.sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) {
|
2018-11-19 22:06:42 +00:00
|
|
|
WifiBegin(2, 0); // Select alternate SSID
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.counter = 1;
|
|
|
|
Wifi.retry--;
|
2018-11-19 17:07:25 +00:00
|
|
|
} else {
|
|
|
|
WifiConfig(wifi_config_tool);
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.counter = 1;
|
|
|
|
Wifi.retry = Wifi.retry_init;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WifiCheck(uint8_t param)
|
|
|
|
{
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.counter--;
|
2018-11-19 17:07:25 +00:00
|
|
|
switch (param) {
|
|
|
|
case WIFI_SERIAL:
|
|
|
|
case WIFI_MANAGER:
|
|
|
|
WifiConfig(param);
|
|
|
|
break;
|
|
|
|
default:
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.config_counter) {
|
|
|
|
Wifi.config_counter--;
|
|
|
|
Wifi.counter = Wifi.config_counter +5;
|
|
|
|
if (Wifi.config_counter) {
|
|
|
|
if (!Wifi.config_counter) {
|
2018-11-19 17:07:25 +00:00
|
|
|
if (strlen(WiFi.SSID().c_str())) {
|
|
|
|
strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0]));
|
|
|
|
}
|
|
|
|
if (strlen(WiFi.psk().c_str())) {
|
|
|
|
strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0]));
|
|
|
|
}
|
|
|
|
Settings.sta_active = 0;
|
2019-10-22 15:34:25 +01:00
|
|
|
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), Settings.sta_ssid[0]);
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-17 16:13:09 +01:00
|
|
|
if (!Wifi.config_counter) {
|
2018-11-19 17:07:25 +00:00
|
|
|
// SettingsSdkErase(); // Disabled v6.1.0b due to possible bad wifi connects
|
|
|
|
restart_flag = 2;
|
|
|
|
}
|
|
|
|
} else {
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.scan_state) { WifiBeginAfterScan(); }
|
2018-11-19 22:06:42 +00:00
|
|
|
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.counter <= 0) {
|
2018-11-19 17:07:25 +00:00
|
|
|
AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION));
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.counter = WIFI_CHECK_SEC;
|
2018-11-19 17:07:25 +00:00
|
|
|
WifiCheckIp();
|
|
|
|
}
|
2019-10-14 11:34:01 +01:00
|
|
|
#if LWIP_IPV6
|
2019-10-24 12:13:16 +01:00
|
|
|
if (WifiCheckIPAddrStatus()) {
|
2019-10-13 13:15:32 +01:00
|
|
|
#else
|
2019-08-17 16:13:09 +01:00
|
|
|
if ((WL_CONNECTED == WiFi.status()) && (static_cast<uint32_t>(WiFi.localIP()) != 0) && !Wifi.config_type) {
|
2019-10-14 11:34:01 +01:00
|
|
|
#endif // LWIP_IPV6=1
|
2018-11-19 17:07:25 +00:00
|
|
|
WifiSetState(1);
|
2018-11-19 22:06:42 +00:00
|
|
|
|
2019-11-03 12:51:22 +00:00
|
|
|
if (Settings.flag3.use_wifi_rescan) { // SetOption57 - Scan wifi network every 44 minutes for configured AP's
|
2018-11-20 13:10:32 +00:00
|
|
|
if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) {
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.scan_state = 2;
|
2018-11-19 22:06:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 13:55:45 +00:00
|
|
|
#ifdef FIRMWARE_MINIMAL
|
2018-11-19 17:07:25 +00:00
|
|
|
if (1 == RtcSettings.ota_loader) {
|
|
|
|
RtcSettings.ota_loader = 0;
|
|
|
|
ota_state_flag = 3;
|
|
|
|
}
|
2019-02-08 13:55:45 +00:00
|
|
|
#endif // FIRMWARE_MINIMAL
|
2018-11-19 17:07:25 +00:00
|
|
|
|
|
|
|
#ifdef USE_DISCOVERY
|
2019-11-03 12:51:22 +00:00
|
|
|
if (Settings.flag3.mdns_enabled) { // SetOption55 - Control mDNS service
|
2019-08-17 16:13:09 +01:00
|
|
|
if (!Wifi.mdns_begun) {
|
2019-01-03 16:30:54 +00:00
|
|
|
// if (mdns_delayed_start) {
|
|
|
|
// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION));
|
|
|
|
// mdns_delayed_start--;
|
|
|
|
// } else {
|
|
|
|
// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START];
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.mdns_begun = (uint8_t)MDNS.begin(my_hostname);
|
|
|
|
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Wifi.mdns_begun) ? D_INITIALIZED : D_FAILED);
|
2019-01-03 16:30:54 +00:00
|
|
|
// }
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // USE_DISCOVERY
|
|
|
|
|
|
|
|
#ifdef USE_WEBSERVER
|
|
|
|
if (Settings.webserver) {
|
|
|
|
StartWebserver(Settings.webserver, WiFi.localIP());
|
|
|
|
#ifdef USE_DISCOVERY
|
|
|
|
#ifdef WEBSERVER_ADVERTISE
|
2019-08-17 16:13:09 +01:00
|
|
|
if (1 == Wifi.mdns_begun) {
|
|
|
|
Wifi.mdns_begun = 2;
|
2018-11-19 17:07:25 +00:00
|
|
|
MDNS.addService("http", "tcp", WEB_PORT);
|
|
|
|
}
|
|
|
|
#endif // WEBSERVER_ADVERTISE
|
|
|
|
#endif // USE_DISCOVERY
|
|
|
|
} else {
|
|
|
|
StopWebserver();
|
|
|
|
}
|
|
|
|
#ifdef USE_EMULATION
|
|
|
|
if (Settings.flag2.emulation) { UdpConnect(); }
|
|
|
|
#endif // USE_EMULATION
|
|
|
|
#endif // USE_WEBSERVER
|
|
|
|
|
|
|
|
#ifdef USE_KNX
|
2019-11-03 11:33:36 +00:00
|
|
|
if (!knx_started && Settings.flag.knx_enabled) { // CMND_KNX_ENABLED
|
2018-11-19 17:07:25 +00:00
|
|
|
KNXStart();
|
|
|
|
knx_started = true;
|
|
|
|
}
|
|
|
|
#endif // USE_KNX
|
|
|
|
|
|
|
|
} else {
|
|
|
|
WifiSetState(0);
|
2019-05-20 14:09:42 +01:00
|
|
|
#ifdef USE_EMULATION
|
2018-11-19 17:07:25 +00:00
|
|
|
UdpDisconnect();
|
|
|
|
#endif // USE_EMULATION
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.mdns_begun = 0;
|
2018-11-19 17:07:25 +00:00
|
|
|
#ifdef USE_KNX
|
|
|
|
knx_started = false;
|
|
|
|
#endif // USE_KNX
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int WifiState(void)
|
|
|
|
{
|
|
|
|
int state = -1;
|
|
|
|
|
|
|
|
if (!global_state.wifi_down) { state = WIFI_RESTART; }
|
2019-08-17 16:13:09 +01:00
|
|
|
if (Wifi.config_type) { state = Wifi.config_type; }
|
2018-11-19 17:07:25 +00:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WifiConnect(void)
|
|
|
|
{
|
|
|
|
WifiSetState(0);
|
|
|
|
WiFi.persistent(false); // Solve possible wifi init errors
|
2019-08-17 16:13:09 +01:00
|
|
|
Wifi.status = 0;
|
|
|
|
Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2);
|
|
|
|
Wifi.retry = Wifi.retry_init;
|
|
|
|
Wifi.counter = 1;
|
2018-11-19 17:07:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0
|
|
|
|
// Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset
|
|
|
|
void WifiDisconnect(void)
|
|
|
|
{
|
|
|
|
// Courtesy of EspEasy
|
|
|
|
WiFi.persistent(true); // use SDK storage of SSID/WPA parameters
|
|
|
|
ETS_UART_INTR_DISABLE();
|
|
|
|
wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage
|
|
|
|
ETS_UART_INTR_ENABLE();
|
|
|
|
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
|
|
|
}
|
|
|
|
|
|
|
|
void EspRestart(void)
|
|
|
|
{
|
|
|
|
delay(100); // Allow time for message xfer - disabled v6.1.0b
|
2019-11-03 11:33:36 +00:00
|
|
|
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
|
|
|
|
MqttDisconnect();
|
|
|
|
}
|
2018-11-19 17:07:25 +00:00
|
|
|
WifiDisconnect();
|
|
|
|
// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0
|
|
|
|
ESP.reset();
|
|
|
|
}
|