From 1b7b22f817e250286d07c07422ab556fd13b9fad Mon Sep 17 00:00:00 2001 From: Clemens Kirchgatterer Date: Sat, 12 May 2018 12:50:18 +0200 Subject: [PATCH 1/2] Fixes WiFi.persistent(false); not working. WiFi config is currently written to NVS regardless of if WiFi.persistent(false); was called before or not. This PR moves some of the static functions in WiFiGeneric.cpp into the WiFiGenericClass to give them access to the _persistent member. Additionally WiFi.getMode() and WiFi.mode() have been made regular methods instead of static. Now esp_wifi_set_storage(WIFI_STORAGE_RAM); is called when persistent storage is switched off. --- libraries/WiFi/src/WiFiGeneric.cpp | 995 ++++++++++----------- libraries/WiFi/src/WiFiGeneric.h | 156 ++-- libraries/WiFi/src/WiFiSTA.cpp | 1284 ++++++++++++++-------------- 3 files changed, 1222 insertions(+), 1213 deletions(-) diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 3ba6aae6814..a11017ba8a0 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1,497 +1,498 @@ -/* - ESP8266WiFiGeneric.cpp - WiFi library for esp8266 - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Reworked on 28 Dec 2015 by Markus Sattler - - */ - -#include "WiFi.h" -#include "WiFiGeneric.h" - -extern "C" { -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "lwip/ip_addr.h" -#include "lwip/opt.h" -#include "lwip/err.h" -#include "lwip/dns.h" -#include "esp_ipc.h" - - -} //extern "C" - -#include "esp32-hal-log.h" - -#undef min -#undef max -#include - -#include "sdkconfig.h" - -#if CONFIG_FREERTOS_UNICORE -#define ARDUINO_RUNNING_CORE 0 -#else -#define ARDUINO_RUNNING_CORE 1 -#endif - -static xQueueHandle _network_event_queue; -static TaskHandle_t _network_event_task_handle = NULL; - -static void _network_event_task(void * arg){ - system_event_t *event = NULL; - for (;;) { - if(xQueueReceive(_network_event_queue, &event, portMAX_DELAY) == pdTRUE){ - WiFiGenericClass::_eventCallback(arg, event); - } - } - vTaskDelete(NULL); - _network_event_task_handle = NULL; -} - -static esp_err_t _network_event_cb(void *arg, system_event_t *event){ - if (xQueueSend(_network_event_queue, &event, portMAX_DELAY) != pdPASS) { - log_w("Network Event Queue Send Failed!"); - return ESP_FAIL; - } - return ESP_OK; -} - -static void _start_network_event_task(){ - if(!_network_event_queue){ - _network_event_queue = xQueueCreate(32, sizeof(system_event_t *)); - if(!_network_event_queue){ - log_e("Network Event Queue Create Failed!"); - return; - } - } - if(!_network_event_task_handle){ - xTaskCreatePinnedToCore(_network_event_task, "network_event", 4096, NULL, 2, &_network_event_task_handle, ARDUINO_RUNNING_CORE); - if(!_network_event_task_handle){ - log_e("Network Event Task Start Failed!"); - return; - } - } - esp_event_loop_init(&_network_event_cb, NULL); -} - -void tcpipInit(){ - static bool initialized = false; - if(!initialized){ - initialized = true; - _start_network_event_task(); - tcpip_adapter_init(); - } -} - -static bool wifiLowLevelInit(){ - static bool lowLevelInitDone = false; - if(!lowLevelInitDone){ - tcpipInit(); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - esp_err_t err = esp_wifi_init(&cfg); - if(err){ - log_e("esp_wifi_init %d", err); - return false; - } - esp_wifi_set_storage(WIFI_STORAGE_FLASH); - esp_wifi_set_mode(WIFI_MODE_NULL); - lowLevelInitDone = true; - } - return true; -} - -static bool wifiLowLevelDeinit(){ - //deinit not working yet! - //esp_wifi_deinit(); - return true; -} - -static bool _esp_wifi_started = false; - -static bool espWiFiStart(){ - if(_esp_wifi_started){ - return true; - } - if(!wifiLowLevelInit()){ - return false; - } - esp_err_t err = esp_wifi_start(); - if (err != ESP_OK) { - log_e("esp_wifi_start %d", err); - wifiLowLevelDeinit(); - return false; - } - _esp_wifi_started = true; - return true; -} - -static bool espWiFiStop(){ - esp_err_t err; - if(!_esp_wifi_started){ - return true; - } - err = esp_wifi_stop(); - if(err){ - log_e("Could not stop WiFi! %u", err); - return false; - } - _esp_wifi_started = false; - return wifiLowLevelDeinit(); -} - -// ----------------------------------------------------------------------------------------------------------------------- -// ------------------------------------------------- Generic WiFi function ----------------------------------------------- -// ----------------------------------------------------------------------------------------------------------------------- - -typedef struct { - WiFiEventCb cb; - WiFiEventFullCb fcb; - WiFiEventSysCb scb; - system_event_id_t event; -} WiFiEventCbList_t; - -// arduino dont like std::vectors move static here -static std::vector cbEventList; - -bool WiFiGenericClass::_persistent = true; -wifi_mode_t WiFiGenericClass::_forceSleepLastMode = WIFI_MODE_NULL; - -WiFiGenericClass::WiFiGenericClass() -{ - -} - -/** - * set callback function - * @param cbEvent WiFiEventCb - * @param event optional filter (WIFI_EVENT_MAX is all events) - */ -void WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); -} - -void WiFiGenericClass::onEvent(WiFiEventFullCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); -} - -void WiFiGenericClass::onEvent(WiFiEventSysCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); -} - -/** - * removes a callback form event handler - * @param cbEvent WiFiEventCb - * @param event optional filter (WIFI_EVENT_MAX is all events) - */ -void WiFiGenericClass::removeEvent(WiFiEventCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.cb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} - -void WiFiGenericClass::removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.fcb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} - -void WiFiGenericClass::removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.scb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} - -/** - * callback for WiFi events - * @param arg - */ -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG -const char * system_event_names[] = { "WIFI_READY", "SCAN_DONE", "STA_START", "STA_STOP", "STA_CONNECTED", "STA_DISCONNECTED", "STA_AUTHMODE_CHANGE", "STA_GOT_IP", "STA_LOST_IP", "STA_WPS_ER_SUCCESS", "STA_WPS_ER_FAILED", "STA_WPS_ER_TIMEOUT", "STA_WPS_ER_PIN", "AP_START", "AP_STOP", "AP_STACONNECTED", "AP_STADISCONNECTED", "AP_PROBEREQRECVED", "GOT_IP6", "ETH_START", "ETH_STOP", "ETH_CONNECTED", "ETH_DISCONNECTED", "ETH_GOT_IP", "MAX"}; -#endif -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN -const char * system_event_reasons[] = { "UNSPECIFIED", "AUTH_EXPIRE", "AUTH_LEAVE", "ASSOC_EXPIRE", "ASSOC_TOOMANY", "NOT_AUTHED", "NOT_ASSOCED", "ASSOC_LEAVE", "ASSOC_NOT_AUTHED", "DISASSOC_PWRCAP_BAD", "DISASSOC_SUPCHAN_BAD", "IE_INVALID", "MIC_FAILURE", "4WAY_HANDSHAKE_TIMEOUT", "GROUP_KEY_UPDATE_TIMEOUT", "IE_IN_4WAY_DIFFERS", "GROUP_CIPHER_INVALID", "PAIRWISE_CIPHER_INVALID", "AKMP_INVALID", "UNSUPP_RSN_IE_VERSION", "INVALID_RSN_IE_CAP", "802_1X_AUTH_FAILED", "CIPHER_SUITE_REJECTED", "BEACON_TIMEOUT", "NO_AP_FOUND", "AUTH_FAIL", "ASSOC_FAIL", "HANDSHAKE_TIMEOUT" }; -#define reason2str(r) ((r>176)?system_event_reasons[r-177]:system_event_reasons[r-1]) -#endif -esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event) -{ - log_d("Event: %d - %s", event->event_id, system_event_names[event->event_id]); - if(event->event_id == SYSTEM_EVENT_SCAN_DONE) { - WiFiScanClass::_scanDone(); - } else if(event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) { - uint8_t reason = event->event_info.disconnected.reason; - log_w("Reason: %u - %s", reason, reason2str(reason)); - if(reason == WIFI_REASON_NO_AP_FOUND) { - WiFiSTAClass::_setStatus(WL_NO_SSID_AVAIL); - } else if(reason == WIFI_REASON_AUTH_FAIL || reason == WIFI_REASON_ASSOC_FAIL) { - WiFiSTAClass::_setStatus(WL_CONNECT_FAILED); - } else if(reason == WIFI_REASON_BEACON_TIMEOUT || reason == WIFI_REASON_HANDSHAKE_TIMEOUT) { - WiFiSTAClass::_setStatus(WL_CONNECTION_LOST); - } else if(reason == WIFI_REASON_AUTH_EXPIRE) { - if(WiFi.getAutoReconnect()){ - WiFi.begin(); - } - } else { - WiFiSTAClass::_setStatus(WL_DISCONNECTED); - } - } else if(event->event_id == SYSTEM_EVENT_STA_START) { - WiFiSTAClass::_setStatus(WL_DISCONNECTED); - } else if(event->event_id == SYSTEM_EVENT_STA_STOP) { - WiFiSTAClass::_setStatus(WL_NO_SHIELD); - } else if(event->event_id == SYSTEM_EVENT_STA_CONNECTED) { - WiFiSTAClass::_setStatus(WL_IDLE_STATUS); - } else if(event->event_id == SYSTEM_EVENT_STA_GOT_IP) { -//#1081 https://github.com/espressif/arduino-esp32/issues/1081 -// if(WiFiSTAClass::status() == WL_IDLE_STATUS) - { - WiFiSTAClass::_setStatus(WL_CONNECTED); - } - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.cb || entry.fcb || entry.scb) { - if(entry.event == (system_event_id_t) event->event_id || entry.event == SYSTEM_EVENT_MAX) { - if(entry.cb){ - entry.cb((system_event_id_t) event->event_id); - } else if(entry.fcb){ - entry.fcb((system_event_id_t) event->event_id, (system_event_info_t) event->event_info); - } else { - entry.scb(event); - } - } - } - } - return ESP_OK; -} - -/** - * Return the current channel associated with the network - * @return channel (1-13) - */ -int32_t WiFiGenericClass::channel(void) -{ - uint8_t primaryChan; - wifi_second_chan_t secondChan; - esp_wifi_get_channel(&primaryChan, &secondChan); - return primaryChan; -} - - -/** - * store WiFi config in SDK flash area - * @param persistent - */ -void WiFiGenericClass::persistent(bool persistent) -{ - _persistent = persistent; -} - - -/** - * set new mode - * @param m WiFiMode_t - */ -bool WiFiGenericClass::mode(wifi_mode_t m) -{ - wifi_mode_t cm = getMode(); - if(cm == WIFI_MODE_MAX){ - return false; - } - if(cm == m) { - return true; - } - esp_err_t err; - err = esp_wifi_set_mode(m); - if(err){ - log_e("Could not set mode! %u", err); - return false; - } - if(m){ - return espWiFiStart(); - } - return espWiFiStop(); -} - -/** - * get WiFi mode - * @return WiFiMode - */ -wifi_mode_t WiFiGenericClass::getMode() -{ - if(!wifiLowLevelInit()){ - return WIFI_MODE_MAX; - } - uint8_t mode; - esp_wifi_get_mode((wifi_mode_t*)&mode); - return (wifi_mode_t)mode; -} - -/** - * control STA mode - * @param enable bool - * @return ok - */ -bool WiFiGenericClass::enableSTA(bool enable) -{ - - wifi_mode_t currentMode = getMode(); - bool isEnabled = ((currentMode & WIFI_MODE_STA) != 0); - - if(isEnabled != enable) { - if(enable) { - return mode((wifi_mode_t)(currentMode | WIFI_MODE_STA)); - } else { - return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_STA))); - } - } else { - return true; - } -} - -/** - * control AP mode - * @param enable bool - * @return ok - */ -bool WiFiGenericClass::enableAP(bool enable) -{ - - wifi_mode_t currentMode = getMode(); - bool isEnabled = ((currentMode & WIFI_MODE_AP) != 0); - - if(isEnabled != enable) { - if(enable) { - return mode((wifi_mode_t)(currentMode | WIFI_MODE_AP)); - } else { - return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_AP))); - } - } else { - return true; - } -} - - -// ----------------------------------------------------------------------------------------------------------------------- -// ------------------------------------------------ Generic Network function --------------------------------------------- -// ----------------------------------------------------------------------------------------------------------------------- - -static bool _dns_busy = false; - -/** - * DNS callback - * @param name - * @param ipaddr - * @param callback_arg - */ -static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) -{ - if(ipaddr) { - (*reinterpret_cast(callback_arg)) = ipaddr->u_addr.ip4.addr; - } - _dns_busy = false; -} - -/** - * Resolve the given hostname to an IP address. - * @param aHostname Name to be resolved - * @param aResult IPAddress structure to store the returned IP address - * @return 1 if aIPAddrString was successfully converted to an IP address, - * else error code - */ -int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) -{ - ip_addr_t addr; - aResult = static_cast(0); - - _dns_busy = true; - err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult); - if(err == ERR_OK && addr.u_addr.ip4.addr) { - aResult = addr.u_addr.ip4.addr; - _dns_busy = false; - } else if(err == ERR_INPROGRESS) { - while(_dns_busy){ - delay(1); - } - } else { - _dns_busy = false; - return 0; - } - return 1; -} - +/* + ESP8266WiFiGeneric.cpp - WiFi library for esp8266 + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Reworked on 28 Dec 2015 by Markus Sattler + + */ + +#include "WiFi.h" +#include "WiFiGeneric.h" + +extern "C" { +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "lwip/ip_addr.h" +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/dns.h" +#include "esp_ipc.h" + + +} //extern "C" + +#include "esp32-hal-log.h" + +#undef min +#undef max +#include + +#include "sdkconfig.h" + +#if CONFIG_FREERTOS_UNICORE +#define ARDUINO_RUNNING_CORE 0 +#else +#define ARDUINO_RUNNING_CORE 1 +#endif + +static xQueueHandle _network_event_queue; +static TaskHandle_t _network_event_task_handle = NULL; + +static void _network_event_task(void * arg){ + system_event_t *event = NULL; + for (;;) { + if(xQueueReceive(_network_event_queue, &event, portMAX_DELAY) == pdTRUE){ + WiFiGenericClass::_eventCallback(arg, event); + } + } + vTaskDelete(NULL); + _network_event_task_handle = NULL; +} + +static esp_err_t _network_event_cb(void *arg, system_event_t *event){ + if (xQueueSend(_network_event_queue, &event, portMAX_DELAY) != pdPASS) { + log_w("Network Event Queue Send Failed!"); + return ESP_FAIL; + } + return ESP_OK; +} + +static void _start_network_event_task(){ + if(!_network_event_queue){ + _network_event_queue = xQueueCreate(32, sizeof(system_event_t *)); + if(!_network_event_queue){ + log_e("Network Event Queue Create Failed!"); + return; + } + } + if(!_network_event_task_handle){ + xTaskCreatePinnedToCore(_network_event_task, "network_event", 4096, NULL, 2, &_network_event_task_handle, ARDUINO_RUNNING_CORE); + if(!_network_event_task_handle){ + log_e("Network Event Task Start Failed!"); + return; + } + } + esp_event_loop_init(&_network_event_cb, NULL); +} + +// ----------------------------------------------------------------------------------------------------------------------- +// ------------------------------------------------- Generic WiFi function ----------------------------------------------- +// ----------------------------------------------------------------------------------------------------------------------- + +typedef struct { + WiFiEventCb cb; + WiFiEventFullCb fcb; + WiFiEventSysCb scb; + system_event_id_t event; +} WiFiEventCbList_t; + +// arduino dont like std::vectors move static here +static std::vector cbEventList; + +bool WiFiGenericClass::_esp_wifi_started = false; +bool WiFiGenericClass::_persistent = true; +wifi_mode_t WiFiGenericClass::_forceSleepLastMode = WIFI_MODE_NULL; + +void WiFiGenericClass::tcpipInit(){ + static bool initialized = false; + if(!initialized){ + initialized = true; + _start_network_event_task(); + tcpip_adapter_init(); + } +} + +bool WiFiGenericClass::wifiLowLevelDeinit(){ + //deinit not working yet! + //esp_wifi_deinit(); + return true; +} + +bool WiFiGenericClass::espWiFiStart(){ + if(_esp_wifi_started){ + return true; + } + if(!wifiLowLevelInit()){ + return false; + } + esp_err_t err = esp_wifi_start(); + if (err != ESP_OK) { + log_e("esp_wifi_start %d", err); + wifiLowLevelDeinit(); + return false; + } + _esp_wifi_started = true; + return true; +} + +bool WiFiGenericClass::espWiFiStop(){ + esp_err_t err; + if(!_esp_wifi_started){ + return true; + } + err = esp_wifi_stop(); + if(err){ + log_e("Could not stop WiFi! %u", err); + return false; + } + _esp_wifi_started = false; + return wifiLowLevelDeinit(); +} + +bool WiFiGenericClass::wifiLowLevelInit(){ + static bool lowLevelInitDone = false; + if(!lowLevelInitDone){ + tcpipInit(); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t err = esp_wifi_init(&cfg); + if(err){ + log_e("esp_wifi_init %d", err); + return false; + } + if (!_persistent) { + esp_wifi_set_storage(WIFI_STORAGE_RAM); + } + esp_wifi_set_mode(WIFI_MODE_NULL); + lowLevelInitDone = true; + } + return true; +} + +WiFiGenericClass::WiFiGenericClass() +{ + +} + +/** + * set callback function + * @param cbEvent WiFiEventCb + * @param event optional filter (WIFI_EVENT_MAX is all events) + */ +void WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + WiFiEventCbList_t newEventHandler; + newEventHandler.cb = cbEvent; + newEventHandler.fcb = NULL; + newEventHandler.scb = NULL; + newEventHandler.event = event; + cbEventList.push_back(newEventHandler); +} + +void WiFiGenericClass::onEvent(WiFiEventFullCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + WiFiEventCbList_t newEventHandler; + newEventHandler.cb = NULL; + newEventHandler.fcb = cbEvent; + newEventHandler.scb = NULL; + newEventHandler.event = event; + cbEventList.push_back(newEventHandler); +} + +void WiFiGenericClass::onEvent(WiFiEventSysCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + WiFiEventCbList_t newEventHandler; + newEventHandler.cb = NULL; + newEventHandler.fcb = NULL; + newEventHandler.scb = cbEvent; + newEventHandler.event = event; + cbEventList.push_back(newEventHandler); +} + +/** + * removes a callback form event handler + * @param cbEvent WiFiEventCb + * @param event optional filter (WIFI_EVENT_MAX is all events) + */ +void WiFiGenericClass::removeEvent(WiFiEventCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.cb == cbEvent && entry.event == event) { + cbEventList.erase(cbEventList.begin() + i); + } + } +} + +void WiFiGenericClass::removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.fcb == cbEvent && entry.event == event) { + cbEventList.erase(cbEventList.begin() + i); + } + } +} + +void WiFiGenericClass::removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.scb == cbEvent && entry.event == event) { + cbEventList.erase(cbEventList.begin() + i); + } + } +} + +/** + * callback for WiFi events + * @param arg + */ +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG +const char * system_event_names[] = { "WIFI_READY", "SCAN_DONE", "STA_START", "STA_STOP", "STA_CONNECTED", "STA_DISCONNECTED", "STA_AUTHMODE_CHANGE", "STA_GOT_IP", "STA_LOST_IP", "STA_WPS_ER_SUCCESS", "STA_WPS_ER_FAILED", "STA_WPS_ER_TIMEOUT", "STA_WPS_ER_PIN", "AP_START", "AP_STOP", "AP_STACONNECTED", "AP_STADISCONNECTED", "AP_PROBEREQRECVED", "GOT_IP6", "ETH_START", "ETH_STOP", "ETH_CONNECTED", "ETH_DISCONNECTED", "ETH_GOT_IP", "MAX"}; +#endif +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN +const char * system_event_reasons[] = { "UNSPECIFIED", "AUTH_EXPIRE", "AUTH_LEAVE", "ASSOC_EXPIRE", "ASSOC_TOOMANY", "NOT_AUTHED", "NOT_ASSOCED", "ASSOC_LEAVE", "ASSOC_NOT_AUTHED", "DISASSOC_PWRCAP_BAD", "DISASSOC_SUPCHAN_BAD", "IE_INVALID", "MIC_FAILURE", "4WAY_HANDSHAKE_TIMEOUT", "GROUP_KEY_UPDATE_TIMEOUT", "IE_IN_4WAY_DIFFERS", "GROUP_CIPHER_INVALID", "PAIRWISE_CIPHER_INVALID", "AKMP_INVALID", "UNSUPP_RSN_IE_VERSION", "INVALID_RSN_IE_CAP", "802_1X_AUTH_FAILED", "CIPHER_SUITE_REJECTED", "BEACON_TIMEOUT", "NO_AP_FOUND", "AUTH_FAIL", "ASSOC_FAIL", "HANDSHAKE_TIMEOUT" }; +#define reason2str(r) ((r>176)?system_event_reasons[r-177]:system_event_reasons[r-1]) +#endif +esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event) +{ + log_d("Event: %d - %s", event->event_id, system_event_names[event->event_id]); + if(event->event_id == SYSTEM_EVENT_SCAN_DONE) { + WiFiScanClass::_scanDone(); + } else if(event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) { + uint8_t reason = event->event_info.disconnected.reason; + log_w("Reason: %u - %s", reason, reason2str(reason)); + if(reason == WIFI_REASON_NO_AP_FOUND) { + WiFiSTAClass::_setStatus(WL_NO_SSID_AVAIL); + } else if(reason == WIFI_REASON_AUTH_FAIL || reason == WIFI_REASON_ASSOC_FAIL) { + WiFiSTAClass::_setStatus(WL_CONNECT_FAILED); + } else if(reason == WIFI_REASON_BEACON_TIMEOUT || reason == WIFI_REASON_HANDSHAKE_TIMEOUT) { + WiFiSTAClass::_setStatus(WL_CONNECTION_LOST); + } else if(reason == WIFI_REASON_AUTH_EXPIRE) { + if(WiFi.getAutoReconnect()){ + WiFi.begin(); + } + } else { + WiFiSTAClass::_setStatus(WL_DISCONNECTED); + } + } else if(event->event_id == SYSTEM_EVENT_STA_START) { + WiFiSTAClass::_setStatus(WL_DISCONNECTED); + } else if(event->event_id == SYSTEM_EVENT_STA_STOP) { + WiFiSTAClass::_setStatus(WL_NO_SHIELD); + } else if(event->event_id == SYSTEM_EVENT_STA_CONNECTED) { + WiFiSTAClass::_setStatus(WL_IDLE_STATUS); + } else if(event->event_id == SYSTEM_EVENT_STA_GOT_IP) { +//#1081 https://github.com/espressif/arduino-esp32/issues/1081 +// if(WiFiSTAClass::status() == WL_IDLE_STATUS) + { + WiFiSTAClass::_setStatus(WL_CONNECTED); + } + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.cb || entry.fcb || entry.scb) { + if(entry.event == (system_event_id_t) event->event_id || entry.event == SYSTEM_EVENT_MAX) { + if(entry.cb){ + entry.cb((system_event_id_t) event->event_id); + } else if(entry.fcb){ + entry.fcb((system_event_id_t) event->event_id, (system_event_info_t) event->event_info); + } else { + entry.scb(event); + } + } + } + } + return ESP_OK; +} + +/** + * Return the current channel associated with the network + * @return channel (1-13) + */ +int32_t WiFiGenericClass::channel(void) +{ + uint8_t primaryChan; + wifi_second_chan_t secondChan; + esp_wifi_get_channel(&primaryChan, &secondChan); + return primaryChan; +} + + +/** + * store WiFi config in SDK flash area + * @param persistent + */ +void WiFiGenericClass::persistent(bool persistent) +{ + _persistent = persistent; +} + + +/** + * set new mode + * @param m WiFiMode_t + */ +bool WiFiGenericClass::mode(wifi_mode_t m) +{ + wifi_mode_t cm = getMode(); + if(cm == WIFI_MODE_MAX){ + return false; + } + if(cm == m) { + return true; + } + esp_err_t err; + err = esp_wifi_set_mode(m); + if(err){ + log_e("Could not set mode! %u", err); + return false; + } + if(m){ + return espWiFiStart(); + } + return espWiFiStop(); +} + +/** + * get WiFi mode + * @return WiFiMode + */ +wifi_mode_t WiFiGenericClass::getMode() +{ + if(!wifiLowLevelInit()){ + return WIFI_MODE_MAX; + } + uint8_t mode; + esp_wifi_get_mode((wifi_mode_t*)&mode); + return (wifi_mode_t)mode; +} + +/** + * control STA mode + * @param enable bool + * @return ok + */ +bool WiFiGenericClass::enableSTA(bool enable) +{ + + wifi_mode_t currentMode = getMode(); + bool isEnabled = ((currentMode & WIFI_MODE_STA) != 0); + + if(isEnabled != enable) { + if(enable) { + return mode((wifi_mode_t)(currentMode | WIFI_MODE_STA)); + } else { + return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_STA))); + } + } else { + return true; + } +} + +/** + * control AP mode + * @param enable bool + * @return ok + */ +bool WiFiGenericClass::enableAP(bool enable) +{ + + wifi_mode_t currentMode = getMode(); + bool isEnabled = ((currentMode & WIFI_MODE_AP) != 0); + + if(isEnabled != enable) { + if(enable) { + return mode((wifi_mode_t)(currentMode | WIFI_MODE_AP)); + } else { + return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_AP))); + } + } else { + return true; + } +} + + +// ----------------------------------------------------------------------------------------------------------------------- +// ------------------------------------------------ Generic Network function --------------------------------------------- +// ----------------------------------------------------------------------------------------------------------------------- + +static bool _dns_busy = false; + +/** + * DNS callback + * @param name + * @param ipaddr + * @param callback_arg + */ +static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{ + if(ipaddr) { + (*reinterpret_cast(callback_arg)) = ipaddr->u_addr.ip4.addr; + } + _dns_busy = false; +} + +/** + * Resolve the given hostname to an IP address. + * @param aHostname Name to be resolved + * @param aResult IPAddress structure to store the returned IP address + * @return 1 if aIPAddrString was successfully converted to an IP address, + * else error code + */ +int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) +{ + ip_addr_t addr; + aResult = static_cast(0); + + _dns_busy = true; + err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult); + if(err == ERR_OK && addr.u_addr.ip4.addr) { + aResult = addr.u_addr.ip4.addr; + _dns_busy = false; + } else if(err == ERR_INPROGRESS) { + while(_dns_busy){ + delay(1); + } + } else { + _dns_busy = false; + return 0; + } + return 1; +} + diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 83eb7f7716a..81b79756336 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -1,74 +1,82 @@ -/* - ESP8266WiFiGeneric.h - esp8266 Wifi support. - Based on WiFi.h from Ardiono WiFi shield library. - Copyright (c) 2011-2014 Arduino. All right reserved. - Modified by Ivan Grokhotkov, December 2014 - Reworked by Markus Sattler, December 2015 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef ESP32WIFIGENERIC_H_ -#define ESP32WIFIGENERIC_H_ - -#include "WiFiType.h" -#include -#include - -typedef void (*WiFiEventCb)(system_event_id_t event); -typedef void (*WiFiEventFullCb)(system_event_id_t event, system_event_info_t info); -typedef void (*WiFiEventSysCb)(system_event_t *event); - -class WiFiGenericClass -{ -public: - - WiFiGenericClass(); - - void onEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void onEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void onEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void removeEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - - int32_t channel(void); - - void persistent(bool persistent); - - static bool mode(wifi_mode_t); - static wifi_mode_t getMode(); - - bool enableSTA(bool enable); - bool enableAP(bool enable); - - static esp_err_t _eventCallback(void *arg, system_event_t *event); - -protected: - static bool _persistent; - static wifi_mode_t _forceSleepLastMode; - -public: - - int hostByName(const char* aHostname, IPAddress& aResult); - -protected: - - friend class WiFiSTAClass; - friend class WiFiScanClass; - friend class WiFiAPClass; -}; - -#endif /* ESP32WIFIGENERIC_H_ */ +/* + ESP8266WiFiGeneric.h - esp8266 Wifi support. + Based on WiFi.h from Ardiono WiFi shield library. + Copyright (c) 2011-2014 Arduino. All right reserved. + Modified by Ivan Grokhotkov, December 2014 + Reworked by Markus Sattler, December 2015 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ESP32WIFIGENERIC_H_ +#define ESP32WIFIGENERIC_H_ + +#include "WiFiType.h" +#include +#include + +typedef void (*WiFiEventCb)(system_event_id_t event); +typedef void (*WiFiEventFullCb)(system_event_id_t event, system_event_info_t info); +typedef void (*WiFiEventSysCb)(system_event_t *event); + +class WiFiGenericClass +{ +public: + + WiFiGenericClass(); + + void onEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void onEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void onEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void removeEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + + int32_t channel(void); + + void persistent(bool persistent); + + bool mode(wifi_mode_t); + wifi_mode_t getMode(); + + bool enableSTA(bool enable); + bool enableAP(bool enable); + + static esp_err_t _eventCallback(void *arg, system_event_t *event); + +protected: + + static bool _esp_wifi_started; + static bool _persistent; + static wifi_mode_t _forceSleepLastMode; + + void tcpipInit(); + bool espWiFiStart(); + bool espWiFiStop(); + bool wifiLowLevelInit(); + bool wifiLowLevelDeinit(); + +public: + + int hostByName(const char* aHostname, IPAddress& aResult); + +protected: + + friend class WiFiSTAClass; + friend class WiFiScanClass; + friend class WiFiAPClass; +}; + +#endif /* ESP32WIFIGENERIC_H_ */ diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index fd7c9714df8..3c465853885 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -1,642 +1,642 @@ -/* - ESP8266WiFiSTA.cpp - WiFi library for esp8266 - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Reworked on 28 Dec 2015 by Markus Sattler - - */ - -#include "WiFi.h" -#include "WiFiGeneric.h" -#include "WiFiSTA.h" - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lwip/err.h" -#include "lwip/dns.h" -#include -#include -} - -// ----------------------------------------------------------------------------------------------------------------------- -// ---------------------------------------------------- Private functions ------------------------------------------------ -// ----------------------------------------------------------------------------------------------------------------------- - -static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs); - - -/** - * compare two STA configurations - * @param lhs station_config - * @param rhs station_config - * @return equal - */ -static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs) -{ - if(strcmp(reinterpret_cast(lhs.sta.ssid), reinterpret_cast(rhs.sta.ssid)) != 0) { - return false; - } - - if(strcmp(reinterpret_cast(lhs.sta.password), reinterpret_cast(rhs.sta.password)) != 0) { - return false; - } - - if(lhs.sta.bssid_set != rhs.sta.bssid_set) { - return false; - } - - if(lhs.sta.bssid_set) { - if(memcmp(lhs.sta.bssid, rhs.sta.bssid, 6) != 0) { - return false; - } - } - - return true; -} - -// ----------------------------------------------------------------------------------------------------------------------- -// ---------------------------------------------------- STA function ----------------------------------------------------- -// ----------------------------------------------------------------------------------------------------------------------- - -bool WiFiSTAClass::_autoReconnect = true; -bool WiFiSTAClass::_useStaticIp = false; -wl_status_t WiFiSTAClass::_status = WL_NO_SHIELD; -/** - * Start Wifi connection - * if passphrase is set the most secure supported mode will be automatically selected - * @param ssid const char* Pointer to the SSID string. - * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). - * @param bssid uint8_t[6] Optional. BSSID / MAC of AP - * @param channel Optional. Channel of AP - * @param connect Optional. call connect - * @return - */ -wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) -{ - - if(!WiFi.enableSTA(true)) { - // enable STA failed - return WL_CONNECT_FAILED; - } - - if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { - // fail SSID too long or missing! - return WL_CONNECT_FAILED; - } - - if(passphrase && strlen(passphrase) > 64) { - // fail passphrase too long! - return WL_CONNECT_FAILED; - } - - wifi_config_t conf; - strcpy(reinterpret_cast(conf.sta.ssid), ssid); - - if(passphrase) { - if (strlen(passphrase) == 64) // it's not a passphrase, is the PSK - memcpy(reinterpret_cast(conf.sta.password), passphrase, 64); - else - strcpy(reinterpret_cast(conf.sta.password), passphrase); - } else { - *conf.sta.password = 0; - } - - if(bssid) { - conf.sta.bssid_set = 1; - memcpy((void *) &conf.sta.bssid[0], (void *) bssid, 6); - } else { - conf.sta.bssid_set = 0; - } - - wifi_config_t current_conf; - esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); - if(!sta_config_equal(current_conf, conf)) { - esp_wifi_set_config(WIFI_IF_STA, &conf); - } - - if(channel > 0 && channel <= 13) { - esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); - } - - esp_wifi_start(); - if(connect) { - esp_wifi_connect(); - } - - if(!_useStaticIp) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else { - tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - } - - return status(); -} - -wl_status_t WiFiSTAClass::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) -{ - return begin((const char*) ssid, (const char*) passphrase, channel, bssid, connect); -} - -/** - * Use to connect to SDK config. - * @return wl_status_t - */ -wl_status_t WiFiSTAClass::begin() -{ - - if(!WiFi.enableSTA(true)) { - // enable STA failed - return WL_CONNECT_FAILED; - } - esp_wifi_start(); - esp_wifi_connect(); - - if(!_useStaticIp) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else { - tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - } - - return status(); -} - -void WiFiSTAClass::_setStatus(wl_status_t status) -{ - _status = status; - //log_i("wifi status: %d", status); -} - -/** - * Change IP configuration settings disabling the dhcp client - * @param local_ip Static ip configuration - * @param gateway Static gateway configuration - * @param subnet Static Subnet mask - * @param dns1 Static DNS server 1 - * @param dns2 Static DNS server 2 - */ -bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) -{ - esp_err_t err = ESP_OK; - - if(!WiFi.enableSTA(true)) { - return false; - } - esp_wifi_start(); - - tcpip_adapter_ip_info_t info; - - if(local_ip != (uint32_t)0x00000000){ - info.ip.addr = static_cast(local_ip); - info.gw.addr = static_cast(gateway); - info.netmask.addr = static_cast(subnet); - } else { - info.ip.addr = 0; - info.gw.addr = 0; - info.netmask.addr = 0; - } - - err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED){ - log_e("DHCP could not be stopped! Error: %d", err); - return false; - } - - err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); - if(err != ERR_OK){ - log_e("STA IP could not be configured! Error: %d", err); - return false; - } - - if(info.ip.addr){ - _useStaticIp = true; - } else { - err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED){ - log_w("DHCP could not be started! Error: %d", err); - return false; - } - _useStaticIp = false; - } - - ip_addr_t d; - d.type = IPADDR_TYPE_V4; - - if(dns1 != (uint32_t)0x00000000) { - // Set DNS1-Server - d.u_addr.ip4.addr = static_cast(dns1); - dns_setserver(0, &d); - } - - if(dns2 != (uint32_t)0x00000000) { - // Set DNS2-Server - d.u_addr.ip4.addr = static_cast(dns2); - dns_setserver(1, &d); - } - - return true; -} - -/** - * will force a disconnect an then start reconnecting to AP - * @return ok - */ -bool WiFiSTAClass::reconnect() -{ - if((WiFi.getMode() & WIFI_MODE_STA) != 0) { - if(esp_wifi_disconnect() == ESP_OK) { - return esp_wifi_connect() == ESP_OK; - } - } - return false; -} - -/** - * Disconnect from the network - * @param wifioff - * @return one value of wl_status_t enum - */ -bool WiFiSTAClass::disconnect(bool wifioff) -{ - bool ret; - wifi_config_t conf; - *conf.sta.ssid = 0; - *conf.sta.password = 0; - - WiFi.getMode(); - esp_wifi_start(); - esp_wifi_set_config(WIFI_IF_STA, &conf); - ret = esp_wifi_disconnect() == ESP_OK; - - if(wifioff) { - WiFi.enableSTA(false); - } - - return ret; -} - -/** - * is STA interface connected? - * @return true if STA is connected to an AD - */ -bool WiFiSTAClass::isConnected() -{ - return (status() == WL_CONNECTED); -} - - -/** - * Setting the ESP32 station to connect to the AP (which is recorded) - * automatically or not when powered on. Enable auto-connect by default. - * @param autoConnect bool - * @return if saved - */ -bool WiFiSTAClass::setAutoConnect(bool autoConnect) -{ - bool ret; - ret = esp_wifi_set_auto_connect(autoConnect); - return ret; -} - -/** - * Checks if ESP32 station mode will connect to AP - * automatically or not when it is powered on. - * @return auto connect - */ -bool WiFiSTAClass::getAutoConnect() -{ - bool autoConnect; - esp_wifi_get_auto_connect(&autoConnect); - return autoConnect; -} - -bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) -{ - _autoReconnect = autoReconnect; - return true; -} - -bool WiFiSTAClass::getAutoReconnect() -{ - return _autoReconnect; -} - -/** - * Wait for WiFi connection to reach a result - * returns the status reached or disconnect if STA is off - * @return wl_status_t - */ -uint8_t WiFiSTAClass::waitForConnectResult() -{ - //1 and 3 have STA enabled - if((WiFiGenericClass::getMode() & WIFI_MODE_STA) == 0) { - return WL_DISCONNECTED; - } - int i = 0; - while((!status() || status() >= WL_DISCONNECTED) && i++ < 100) { - delay(100); - } - return status(); -} - -/** - * Get the station interface IP address. - * @return IPAddress station IP - */ -IPAddress WiFiSTAClass::localIP() -{ - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return IPAddress(ip.ip.addr); -} - - -/** - * Get the station interface MAC address. - * @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH - * @return pointer to uint8_t * - */ -uint8_t* WiFiSTAClass::macAddress(uint8_t* mac) -{ - esp_wifi_get_mac(WIFI_IF_STA, mac); - return mac; -} - -/** - * Get the station interface MAC address. - * @return String mac - */ -String WiFiSTAClass::macAddress(void) -{ - uint8_t mac[6]; - char macStr[18] = { 0 }; - esp_wifi_get_mac(WIFI_IF_STA, mac); - - sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return String(macStr); -} - -/** - * Get the interface subnet mask address. - * @return IPAddress subnetMask - */ -IPAddress WiFiSTAClass::subnetMask() -{ - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return IPAddress(ip.netmask.addr); -} - -/** - * Get the gateway ip address. - * @return IPAddress gatewayIP - */ -IPAddress WiFiSTAClass::gatewayIP() -{ - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return IPAddress(ip.gw.addr); -} - -/** - * Get the DNS ip address. - * @param dns_no - * @return IPAddress DNS Server IP - */ -IPAddress WiFiSTAClass::dnsIP(uint8_t dns_no) -{ - ip_addr_t dns_ip = dns_getserver(dns_no); - return IPAddress(dns_ip.u_addr.ip4.addr); -} - -/** - * Return Connection status. - * @return one of the value defined in wl_status_t - * - */ -wl_status_t WiFiSTAClass::status() -{ - return WiFiSTAClass::_status; -} - -/** - * Return the current SSID associated with the network - * @return SSID - */ -String WiFiSTAClass::SSID() const -{ - wifi_ap_record_t info; - if(!esp_wifi_sta_get_ap_info(&info)) { - return String(reinterpret_cast(info.ssid)); - } - return String(); -} - -/** - * Return the current pre shared key associated with the network - * @return psk string - */ -String WiFiSTAClass::psk() const -{ - wifi_config_t conf; - esp_wifi_get_config(WIFI_IF_STA, &conf); - return String(reinterpret_cast(conf.sta.password)); -} - -/** - * Return the current bssid / mac associated with the network if configured - * @return bssid uint8_t * - */ -uint8_t* WiFiSTAClass::BSSID(void) -{ - static uint8_t bssid[6]; - wifi_ap_record_t info; - if(!esp_wifi_sta_get_ap_info(&info)) { - memcpy(bssid, info.bssid, 6); - return reinterpret_cast(bssid); - } - return NULL; -} - -/** - * Return the current bssid / mac associated with the network if configured - * @return String bssid mac - */ -String WiFiSTAClass::BSSIDstr(void) -{ - uint8_t* bssid = BSSID(); - if(!bssid){ - return String(); - } - char mac[18] = { 0 }; - sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); - return String(mac); -} - -/** - * Return the current network RSSI. - * @return RSSI value - */ -int8_t WiFiSTAClass::RSSI(void) -{ - wifi_ap_record_t info; - if(!esp_wifi_sta_get_ap_info(&info)) { - return info.rssi; - } - return 0; -} - -/** - * Get the station interface Host name. - * @return char array hostname - */ -const char * WiFiSTAClass::getHostname() -{ - const char * hostname; - if(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname)){ - return NULL; - } - return hostname; -} - -/** - * Set the station interface Host name. - * @param hostname pointer to const string - * @return true on success - */ -bool WiFiSTAClass::setHostname(const char * hostname) -{ - return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname) == 0; -} - -/** - * Enable IPv6 on the station interface. - * @return true on success - */ -bool WiFiSTAClass::enableIpV6() -{ - return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA) == 0; -} - -/** - * Get the station interface IPv6 address. - * @return IPv6Address - */ -IPv6Address WiFiSTAClass::localIPv6() -{ - static ip6_addr_t addr; - if(tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &addr)){ - return IPv6Address(); - } - return IPv6Address(addr.addr); -} - - -bool WiFiSTAClass::_smartConfigStarted = false; -bool WiFiSTAClass::_smartConfigDone = false; - - -bool WiFiSTAClass::beginSmartConfig() { - if (_smartConfigStarted) { - return false; - } - - if (!WiFi.mode(WIFI_STA)) { - return false; - } - - esp_wifi_disconnect(); - - esp_err_t err; - err = esp_smartconfig_start(reinterpret_cast(&WiFiSTAClass::_smartConfigCallback), 1); - if (err == ESP_OK) { - _smartConfigStarted = true; - _smartConfigDone = false; - return true; - } - return false; -} - -bool WiFiSTAClass::stopSmartConfig() { - if (!_smartConfigStarted) { - return true; - } - - if (esp_smartconfig_stop() == ESP_OK) { - _smartConfigStarted = false; - return true; - } - - return false; -} - -bool WiFiSTAClass::smartConfigDone() { - if (!_smartConfigStarted) { - return false; - } - - return _smartConfigDone; -} - -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG -const char * sc_status_strings[] = { - "WAIT", - "FIND_CHANNEL", - "GETTING_SSID_PSWD", - "LINK", - "LINK_OVER" -}; - -const char * sc_type_strings[] = { - "ESPTOUCH", - "AIRKISS", - "ESPTOUCH_AIRKISS" -}; -#endif - -void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) { - smartconfig_status_t status = (smartconfig_status_t) st; - log_d("Status: %s", sc_status_strings[st % 5]); - if (status == SC_STATUS_GETTING_SSID_PSWD) { - smartconfig_type_t * type = (smartconfig_type_t *)result; - log_d("Type: %s", sc_type_strings[*type % 3]); - } else if (status == SC_STATUS_LINK) { - wifi_sta_config_t *sta_conf = reinterpret_cast(result); - log_d("SSID: %s", (char *)(sta_conf->ssid)); - sta_conf->bssid_set = 0; - esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)sta_conf); - esp_wifi_connect(); - _smartConfigDone = true; - } else if (status == SC_STATUS_LINK_OVER) { - if(result){ - ip4_addr_t * ip = (ip4_addr_t *)result; - log_d("Sender IP: " IPSTR, IP2STR(ip)); - } - WiFi.stopSmartConfig(); - } -} +/* + ESP8266WiFiSTA.cpp - WiFi library for esp8266 + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Reworked on 28 Dec 2015 by Markus Sattler + + */ + +#include "WiFi.h" +#include "WiFiGeneric.h" +#include "WiFiSTA.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lwip/err.h" +#include "lwip/dns.h" +#include +#include +} + +// ----------------------------------------------------------------------------------------------------------------------- +// ---------------------------------------------------- Private functions ------------------------------------------------ +// ----------------------------------------------------------------------------------------------------------------------- + +static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs); + + +/** + * compare two STA configurations + * @param lhs station_config + * @param rhs station_config + * @return equal + */ +static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs) +{ + if(strcmp(reinterpret_cast(lhs.sta.ssid), reinterpret_cast(rhs.sta.ssid)) != 0) { + return false; + } + + if(strcmp(reinterpret_cast(lhs.sta.password), reinterpret_cast(rhs.sta.password)) != 0) { + return false; + } + + if(lhs.sta.bssid_set != rhs.sta.bssid_set) { + return false; + } + + if(lhs.sta.bssid_set) { + if(memcmp(lhs.sta.bssid, rhs.sta.bssid, 6) != 0) { + return false; + } + } + + return true; +} + +// ----------------------------------------------------------------------------------------------------------------------- +// ---------------------------------------------------- STA function ----------------------------------------------------- +// ----------------------------------------------------------------------------------------------------------------------- + +bool WiFiSTAClass::_autoReconnect = true; +bool WiFiSTAClass::_useStaticIp = false; +wl_status_t WiFiSTAClass::_status = WL_NO_SHIELD; +/** + * Start Wifi connection + * if passphrase is set the most secure supported mode will be automatically selected + * @param ssid const char* Pointer to the SSID string. + * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). + * @param bssid uint8_t[6] Optional. BSSID / MAC of AP + * @param channel Optional. Channel of AP + * @param connect Optional. call connect + * @return + */ +wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) +{ + + if(!WiFi.enableSTA(true)) { + // enable STA failed + return WL_CONNECT_FAILED; + } + + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + // fail SSID too long or missing! + return WL_CONNECT_FAILED; + } + + if(passphrase && strlen(passphrase) > 64) { + // fail passphrase too long! + return WL_CONNECT_FAILED; + } + + wifi_config_t conf; + strcpy(reinterpret_cast(conf.sta.ssid), ssid); + + if(passphrase) { + if (strlen(passphrase) == 64) // it's not a passphrase, is the PSK + memcpy(reinterpret_cast(conf.sta.password), passphrase, 64); + else + strcpy(reinterpret_cast(conf.sta.password), passphrase); + } else { + *conf.sta.password = 0; + } + + if(bssid) { + conf.sta.bssid_set = 1; + memcpy((void *) &conf.sta.bssid[0], (void *) bssid, 6); + } else { + conf.sta.bssid_set = 0; + } + + wifi_config_t current_conf; + esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); + if(!sta_config_equal(current_conf, conf)) { + esp_wifi_set_config(WIFI_IF_STA, &conf); + } + + if(channel > 0 && channel <= 13) { + esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); + } + + esp_wifi_start(); + if(connect) { + esp_wifi_connect(); + } + + if(!_useStaticIp) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } else { + tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); + } + + return status(); +} + +wl_status_t WiFiSTAClass::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) +{ + return begin((const char*) ssid, (const char*) passphrase, channel, bssid, connect); +} + +/** + * Use to connect to SDK config. + * @return wl_status_t + */ +wl_status_t WiFiSTAClass::begin() +{ + + if(!WiFi.enableSTA(true)) { + // enable STA failed + return WL_CONNECT_FAILED; + } + esp_wifi_start(); + esp_wifi_connect(); + + if(!_useStaticIp) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } else { + tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); + } + + return status(); +} + +void WiFiSTAClass::_setStatus(wl_status_t status) +{ + _status = status; + //log_i("wifi status: %d", status); +} + +/** + * Change IP configuration settings disabling the dhcp client + * @param local_ip Static ip configuration + * @param gateway Static gateway configuration + * @param subnet Static Subnet mask + * @param dns1 Static DNS server 1 + * @param dns2 Static DNS server 2 + */ +bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) +{ + esp_err_t err = ESP_OK; + + if(!WiFi.enableSTA(true)) { + return false; + } + esp_wifi_start(); + + tcpip_adapter_ip_info_t info; + + if(local_ip != (uint32_t)0x00000000){ + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + } else { + info.ip.addr = 0; + info.gw.addr = 0; + info.netmask.addr = 0; + } + + err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); + if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED){ + log_e("DHCP could not be stopped! Error: %d", err); + return false; + } + + err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); + if(err != ERR_OK){ + log_e("STA IP could not be configured! Error: %d", err); + return false; + } + + if(info.ip.addr){ + _useStaticIp = true; + } else { + err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED){ + log_w("DHCP could not be started! Error: %d", err); + return false; + } + _useStaticIp = false; + } + + ip_addr_t d; + d.type = IPADDR_TYPE_V4; + + if(dns1 != (uint32_t)0x00000000) { + // Set DNS1-Server + d.u_addr.ip4.addr = static_cast(dns1); + dns_setserver(0, &d); + } + + if(dns2 != (uint32_t)0x00000000) { + // Set DNS2-Server + d.u_addr.ip4.addr = static_cast(dns2); + dns_setserver(1, &d); + } + + return true; +} + +/** + * will force a disconnect an then start reconnecting to AP + * @return ok + */ +bool WiFiSTAClass::reconnect() +{ + if((WiFi.getMode() & WIFI_MODE_STA) != 0) { + if(esp_wifi_disconnect() == ESP_OK) { + return esp_wifi_connect() == ESP_OK; + } + } + return false; +} + +/** + * Disconnect from the network + * @param wifioff + * @return one value of wl_status_t enum + */ +bool WiFiSTAClass::disconnect(bool wifioff) +{ + bool ret; + wifi_config_t conf; + *conf.sta.ssid = 0; + *conf.sta.password = 0; + + WiFi.getMode(); + esp_wifi_start(); + esp_wifi_set_config(WIFI_IF_STA, &conf); + ret = esp_wifi_disconnect() == ESP_OK; + + if(wifioff) { + WiFi.enableSTA(false); + } + + return ret; +} + +/** + * is STA interface connected? + * @return true if STA is connected to an AD + */ +bool WiFiSTAClass::isConnected() +{ + return (status() == WL_CONNECTED); +} + + +/** + * Setting the ESP32 station to connect to the AP (which is recorded) + * automatically or not when powered on. Enable auto-connect by default. + * @param autoConnect bool + * @return if saved + */ +bool WiFiSTAClass::setAutoConnect(bool autoConnect) +{ + bool ret; + ret = esp_wifi_set_auto_connect(autoConnect); + return ret; +} + +/** + * Checks if ESP32 station mode will connect to AP + * automatically or not when it is powered on. + * @return auto connect + */ +bool WiFiSTAClass::getAutoConnect() +{ + bool autoConnect; + esp_wifi_get_auto_connect(&autoConnect); + return autoConnect; +} + +bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) +{ + _autoReconnect = autoReconnect; + return true; +} + +bool WiFiSTAClass::getAutoReconnect() +{ + return _autoReconnect; +} + +/** + * Wait for WiFi connection to reach a result + * returns the status reached or disconnect if STA is off + * @return wl_status_t + */ +uint8_t WiFiSTAClass::waitForConnectResult() +{ + //1 and 3 have STA enabled + if((WiFi.getMode() & WIFI_MODE_STA) == 0) { + return WL_DISCONNECTED; + } + int i = 0; + while((!status() || status() >= WL_DISCONNECTED) && i++ < 100) { + delay(100); + } + return status(); +} + +/** + * Get the station interface IP address. + * @return IPAddress station IP + */ +IPAddress WiFiSTAClass::localIP() +{ + tcpip_adapter_ip_info_t ip; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); + return IPAddress(ip.ip.addr); +} + + +/** + * Get the station interface MAC address. + * @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH + * @return pointer to uint8_t * + */ +uint8_t* WiFiSTAClass::macAddress(uint8_t* mac) +{ + esp_wifi_get_mac(WIFI_IF_STA, mac); + return mac; +} + +/** + * Get the station interface MAC address. + * @return String mac + */ +String WiFiSTAClass::macAddress(void) +{ + uint8_t mac[6]; + char macStr[18] = { 0 }; + esp_wifi_get_mac(WIFI_IF_STA, mac); + + sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(macStr); +} + +/** + * Get the interface subnet mask address. + * @return IPAddress subnetMask + */ +IPAddress WiFiSTAClass::subnetMask() +{ + tcpip_adapter_ip_info_t ip; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); + return IPAddress(ip.netmask.addr); +} + +/** + * Get the gateway ip address. + * @return IPAddress gatewayIP + */ +IPAddress WiFiSTAClass::gatewayIP() +{ + tcpip_adapter_ip_info_t ip; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); + return IPAddress(ip.gw.addr); +} + +/** + * Get the DNS ip address. + * @param dns_no + * @return IPAddress DNS Server IP + */ +IPAddress WiFiSTAClass::dnsIP(uint8_t dns_no) +{ + ip_addr_t dns_ip = dns_getserver(dns_no); + return IPAddress(dns_ip.u_addr.ip4.addr); +} + +/** + * Return Connection status. + * @return one of the value defined in wl_status_t + * + */ +wl_status_t WiFiSTAClass::status() +{ + return WiFiSTAClass::_status; +} + +/** + * Return the current SSID associated with the network + * @return SSID + */ +String WiFiSTAClass::SSID() const +{ + wifi_ap_record_t info; + if(!esp_wifi_sta_get_ap_info(&info)) { + return String(reinterpret_cast(info.ssid)); + } + return String(); +} + +/** + * Return the current pre shared key associated with the network + * @return psk string + */ +String WiFiSTAClass::psk() const +{ + wifi_config_t conf; + esp_wifi_get_config(WIFI_IF_STA, &conf); + return String(reinterpret_cast(conf.sta.password)); +} + +/** + * Return the current bssid / mac associated with the network if configured + * @return bssid uint8_t * + */ +uint8_t* WiFiSTAClass::BSSID(void) +{ + static uint8_t bssid[6]; + wifi_ap_record_t info; + if(!esp_wifi_sta_get_ap_info(&info)) { + memcpy(bssid, info.bssid, 6); + return reinterpret_cast(bssid); + } + return NULL; +} + +/** + * Return the current bssid / mac associated with the network if configured + * @return String bssid mac + */ +String WiFiSTAClass::BSSIDstr(void) +{ + uint8_t* bssid = BSSID(); + if(!bssid){ + return String(); + } + char mac[18] = { 0 }; + sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + return String(mac); +} + +/** + * Return the current network RSSI. + * @return RSSI value + */ +int8_t WiFiSTAClass::RSSI(void) +{ + wifi_ap_record_t info; + if(!esp_wifi_sta_get_ap_info(&info)) { + return info.rssi; + } + return 0; +} + +/** + * Get the station interface Host name. + * @return char array hostname + */ +const char * WiFiSTAClass::getHostname() +{ + const char * hostname; + if(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname)){ + return NULL; + } + return hostname; +} + +/** + * Set the station interface Host name. + * @param hostname pointer to const string + * @return true on success + */ +bool WiFiSTAClass::setHostname(const char * hostname) +{ + return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname) == 0; +} + +/** + * Enable IPv6 on the station interface. + * @return true on success + */ +bool WiFiSTAClass::enableIpV6() +{ + return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA) == 0; +} + +/** + * Get the station interface IPv6 address. + * @return IPv6Address + */ +IPv6Address WiFiSTAClass::localIPv6() +{ + static ip6_addr_t addr; + if(tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &addr)){ + return IPv6Address(); + } + return IPv6Address(addr.addr); +} + + +bool WiFiSTAClass::_smartConfigStarted = false; +bool WiFiSTAClass::_smartConfigDone = false; + + +bool WiFiSTAClass::beginSmartConfig() { + if (_smartConfigStarted) { + return false; + } + + if (!WiFi.mode(WIFI_STA)) { + return false; + } + + esp_wifi_disconnect(); + + esp_err_t err; + err = esp_smartconfig_start(reinterpret_cast(&WiFiSTAClass::_smartConfigCallback), 1); + if (err == ESP_OK) { + _smartConfigStarted = true; + _smartConfigDone = false; + return true; + } + return false; +} + +bool WiFiSTAClass::stopSmartConfig() { + if (!_smartConfigStarted) { + return true; + } + + if (esp_smartconfig_stop() == ESP_OK) { + _smartConfigStarted = false; + return true; + } + + return false; +} + +bool WiFiSTAClass::smartConfigDone() { + if (!_smartConfigStarted) { + return false; + } + + return _smartConfigDone; +} + +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG +const char * sc_status_strings[] = { + "WAIT", + "FIND_CHANNEL", + "GETTING_SSID_PSWD", + "LINK", + "LINK_OVER" +}; + +const char * sc_type_strings[] = { + "ESPTOUCH", + "AIRKISS", + "ESPTOUCH_AIRKISS" +}; +#endif + +void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) { + smartconfig_status_t status = (smartconfig_status_t) st; + log_d("Status: %s", sc_status_strings[st % 5]); + if (status == SC_STATUS_GETTING_SSID_PSWD) { + smartconfig_type_t * type = (smartconfig_type_t *)result; + log_d("Type: %s", sc_type_strings[*type % 3]); + } else if (status == SC_STATUS_LINK) { + wifi_sta_config_t *sta_conf = reinterpret_cast(result); + log_d("SSID: %s", (char *)(sta_conf->ssid)); + sta_conf->bssid_set = 0; + esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)sta_conf); + esp_wifi_connect(); + _smartConfigDone = true; + } else if (status == SC_STATUS_LINK_OVER) { + if(result){ + ip4_addr_t * ip = (ip4_addr_t *)result; + log_d("Sender IP: " IPSTR, IP2STR(ip)); + } + WiFi.stopSmartConfig(); + } +} From 57fbc05f6a7381a217331c692bc62fa6140ed6d3 Mon Sep 17 00:00:00 2001 From: Clemens Kirchgatterer Date: Sat, 12 May 2018 13:09:49 +0200 Subject: [PATCH 2/2] Convert line endings from CRLN to LN. --- libraries/WiFi/src/WiFiGeneric.cpp | 996 ++++++++++----------- libraries/WiFi/src/WiFiGeneric.h | 164 ++-- libraries/WiFi/src/WiFiSTA.cpp | 1284 ++++++++++++++-------------- 3 files changed, 1222 insertions(+), 1222 deletions(-) diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index a11017ba8a0..e8c2885bff1 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1,498 +1,498 @@ -/* - ESP8266WiFiGeneric.cpp - WiFi library for esp8266 - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Reworked on 28 Dec 2015 by Markus Sattler - - */ - -#include "WiFi.h" -#include "WiFiGeneric.h" - -extern "C" { -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "lwip/ip_addr.h" -#include "lwip/opt.h" -#include "lwip/err.h" -#include "lwip/dns.h" -#include "esp_ipc.h" - - -} //extern "C" - -#include "esp32-hal-log.h" - -#undef min -#undef max -#include - -#include "sdkconfig.h" - -#if CONFIG_FREERTOS_UNICORE -#define ARDUINO_RUNNING_CORE 0 -#else -#define ARDUINO_RUNNING_CORE 1 -#endif - -static xQueueHandle _network_event_queue; -static TaskHandle_t _network_event_task_handle = NULL; - -static void _network_event_task(void * arg){ - system_event_t *event = NULL; - for (;;) { - if(xQueueReceive(_network_event_queue, &event, portMAX_DELAY) == pdTRUE){ - WiFiGenericClass::_eventCallback(arg, event); - } - } - vTaskDelete(NULL); - _network_event_task_handle = NULL; -} - -static esp_err_t _network_event_cb(void *arg, system_event_t *event){ - if (xQueueSend(_network_event_queue, &event, portMAX_DELAY) != pdPASS) { - log_w("Network Event Queue Send Failed!"); - return ESP_FAIL; - } - return ESP_OK; -} - -static void _start_network_event_task(){ - if(!_network_event_queue){ - _network_event_queue = xQueueCreate(32, sizeof(system_event_t *)); - if(!_network_event_queue){ - log_e("Network Event Queue Create Failed!"); - return; - } - } - if(!_network_event_task_handle){ - xTaskCreatePinnedToCore(_network_event_task, "network_event", 4096, NULL, 2, &_network_event_task_handle, ARDUINO_RUNNING_CORE); - if(!_network_event_task_handle){ - log_e("Network Event Task Start Failed!"); - return; - } - } - esp_event_loop_init(&_network_event_cb, NULL); -} - -// ----------------------------------------------------------------------------------------------------------------------- -// ------------------------------------------------- Generic WiFi function ----------------------------------------------- -// ----------------------------------------------------------------------------------------------------------------------- - -typedef struct { - WiFiEventCb cb; - WiFiEventFullCb fcb; - WiFiEventSysCb scb; - system_event_id_t event; -} WiFiEventCbList_t; - -// arduino dont like std::vectors move static here -static std::vector cbEventList; - -bool WiFiGenericClass::_esp_wifi_started = false; -bool WiFiGenericClass::_persistent = true; -wifi_mode_t WiFiGenericClass::_forceSleepLastMode = WIFI_MODE_NULL; - -void WiFiGenericClass::tcpipInit(){ - static bool initialized = false; - if(!initialized){ - initialized = true; - _start_network_event_task(); - tcpip_adapter_init(); - } -} - -bool WiFiGenericClass::wifiLowLevelDeinit(){ - //deinit not working yet! - //esp_wifi_deinit(); - return true; -} - -bool WiFiGenericClass::espWiFiStart(){ - if(_esp_wifi_started){ - return true; - } - if(!wifiLowLevelInit()){ - return false; - } - esp_err_t err = esp_wifi_start(); - if (err != ESP_OK) { - log_e("esp_wifi_start %d", err); - wifiLowLevelDeinit(); - return false; - } - _esp_wifi_started = true; - return true; -} - -bool WiFiGenericClass::espWiFiStop(){ - esp_err_t err; - if(!_esp_wifi_started){ - return true; - } - err = esp_wifi_stop(); - if(err){ - log_e("Could not stop WiFi! %u", err); - return false; - } - _esp_wifi_started = false; - return wifiLowLevelDeinit(); -} - -bool WiFiGenericClass::wifiLowLevelInit(){ - static bool lowLevelInitDone = false; - if(!lowLevelInitDone){ - tcpipInit(); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - esp_err_t err = esp_wifi_init(&cfg); - if(err){ - log_e("esp_wifi_init %d", err); - return false; - } - if (!_persistent) { - esp_wifi_set_storage(WIFI_STORAGE_RAM); - } - esp_wifi_set_mode(WIFI_MODE_NULL); - lowLevelInitDone = true; - } - return true; -} - -WiFiGenericClass::WiFiGenericClass() -{ - -} - -/** - * set callback function - * @param cbEvent WiFiEventCb - * @param event optional filter (WIFI_EVENT_MAX is all events) - */ -void WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.fcb = NULL; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); -} - -void WiFiGenericClass::onEvent(WiFiEventFullCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = cbEvent; - newEventHandler.scb = NULL; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); -} - -void WiFiGenericClass::onEvent(WiFiEventSysCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = NULL; - newEventHandler.fcb = NULL; - newEventHandler.scb = cbEvent; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); -} - -/** - * removes a callback form event handler - * @param cbEvent WiFiEventCb - * @param event optional filter (WIFI_EVENT_MAX is all events) - */ -void WiFiGenericClass::removeEvent(WiFiEventCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.cb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} - -void WiFiGenericClass::removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.fcb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} - -void WiFiGenericClass::removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event) -{ - if(!cbEvent) { - return; - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.scb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } -} - -/** - * callback for WiFi events - * @param arg - */ -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG -const char * system_event_names[] = { "WIFI_READY", "SCAN_DONE", "STA_START", "STA_STOP", "STA_CONNECTED", "STA_DISCONNECTED", "STA_AUTHMODE_CHANGE", "STA_GOT_IP", "STA_LOST_IP", "STA_WPS_ER_SUCCESS", "STA_WPS_ER_FAILED", "STA_WPS_ER_TIMEOUT", "STA_WPS_ER_PIN", "AP_START", "AP_STOP", "AP_STACONNECTED", "AP_STADISCONNECTED", "AP_PROBEREQRECVED", "GOT_IP6", "ETH_START", "ETH_STOP", "ETH_CONNECTED", "ETH_DISCONNECTED", "ETH_GOT_IP", "MAX"}; -#endif -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN -const char * system_event_reasons[] = { "UNSPECIFIED", "AUTH_EXPIRE", "AUTH_LEAVE", "ASSOC_EXPIRE", "ASSOC_TOOMANY", "NOT_AUTHED", "NOT_ASSOCED", "ASSOC_LEAVE", "ASSOC_NOT_AUTHED", "DISASSOC_PWRCAP_BAD", "DISASSOC_SUPCHAN_BAD", "IE_INVALID", "MIC_FAILURE", "4WAY_HANDSHAKE_TIMEOUT", "GROUP_KEY_UPDATE_TIMEOUT", "IE_IN_4WAY_DIFFERS", "GROUP_CIPHER_INVALID", "PAIRWISE_CIPHER_INVALID", "AKMP_INVALID", "UNSUPP_RSN_IE_VERSION", "INVALID_RSN_IE_CAP", "802_1X_AUTH_FAILED", "CIPHER_SUITE_REJECTED", "BEACON_TIMEOUT", "NO_AP_FOUND", "AUTH_FAIL", "ASSOC_FAIL", "HANDSHAKE_TIMEOUT" }; -#define reason2str(r) ((r>176)?system_event_reasons[r-177]:system_event_reasons[r-1]) -#endif -esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event) -{ - log_d("Event: %d - %s", event->event_id, system_event_names[event->event_id]); - if(event->event_id == SYSTEM_EVENT_SCAN_DONE) { - WiFiScanClass::_scanDone(); - } else if(event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) { - uint8_t reason = event->event_info.disconnected.reason; - log_w("Reason: %u - %s", reason, reason2str(reason)); - if(reason == WIFI_REASON_NO_AP_FOUND) { - WiFiSTAClass::_setStatus(WL_NO_SSID_AVAIL); - } else if(reason == WIFI_REASON_AUTH_FAIL || reason == WIFI_REASON_ASSOC_FAIL) { - WiFiSTAClass::_setStatus(WL_CONNECT_FAILED); - } else if(reason == WIFI_REASON_BEACON_TIMEOUT || reason == WIFI_REASON_HANDSHAKE_TIMEOUT) { - WiFiSTAClass::_setStatus(WL_CONNECTION_LOST); - } else if(reason == WIFI_REASON_AUTH_EXPIRE) { - if(WiFi.getAutoReconnect()){ - WiFi.begin(); - } - } else { - WiFiSTAClass::_setStatus(WL_DISCONNECTED); - } - } else if(event->event_id == SYSTEM_EVENT_STA_START) { - WiFiSTAClass::_setStatus(WL_DISCONNECTED); - } else if(event->event_id == SYSTEM_EVENT_STA_STOP) { - WiFiSTAClass::_setStatus(WL_NO_SHIELD); - } else if(event->event_id == SYSTEM_EVENT_STA_CONNECTED) { - WiFiSTAClass::_setStatus(WL_IDLE_STATUS); - } else if(event->event_id == SYSTEM_EVENT_STA_GOT_IP) { -//#1081 https://github.com/espressif/arduino-esp32/issues/1081 -// if(WiFiSTAClass::status() == WL_IDLE_STATUS) - { - WiFiSTAClass::_setStatus(WL_CONNECTED); - } - } - - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.cb || entry.fcb || entry.scb) { - if(entry.event == (system_event_id_t) event->event_id || entry.event == SYSTEM_EVENT_MAX) { - if(entry.cb){ - entry.cb((system_event_id_t) event->event_id); - } else if(entry.fcb){ - entry.fcb((system_event_id_t) event->event_id, (system_event_info_t) event->event_info); - } else { - entry.scb(event); - } - } - } - } - return ESP_OK; -} - -/** - * Return the current channel associated with the network - * @return channel (1-13) - */ -int32_t WiFiGenericClass::channel(void) -{ - uint8_t primaryChan; - wifi_second_chan_t secondChan; - esp_wifi_get_channel(&primaryChan, &secondChan); - return primaryChan; -} - - -/** - * store WiFi config in SDK flash area - * @param persistent - */ -void WiFiGenericClass::persistent(bool persistent) -{ - _persistent = persistent; -} - - -/** - * set new mode - * @param m WiFiMode_t - */ -bool WiFiGenericClass::mode(wifi_mode_t m) -{ - wifi_mode_t cm = getMode(); - if(cm == WIFI_MODE_MAX){ - return false; - } - if(cm == m) { - return true; - } - esp_err_t err; - err = esp_wifi_set_mode(m); - if(err){ - log_e("Could not set mode! %u", err); - return false; - } - if(m){ - return espWiFiStart(); - } - return espWiFiStop(); -} - -/** - * get WiFi mode - * @return WiFiMode - */ -wifi_mode_t WiFiGenericClass::getMode() -{ - if(!wifiLowLevelInit()){ - return WIFI_MODE_MAX; - } - uint8_t mode; - esp_wifi_get_mode((wifi_mode_t*)&mode); - return (wifi_mode_t)mode; -} - -/** - * control STA mode - * @param enable bool - * @return ok - */ -bool WiFiGenericClass::enableSTA(bool enable) -{ - - wifi_mode_t currentMode = getMode(); - bool isEnabled = ((currentMode & WIFI_MODE_STA) != 0); - - if(isEnabled != enable) { - if(enable) { - return mode((wifi_mode_t)(currentMode | WIFI_MODE_STA)); - } else { - return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_STA))); - } - } else { - return true; - } -} - -/** - * control AP mode - * @param enable bool - * @return ok - */ -bool WiFiGenericClass::enableAP(bool enable) -{ - - wifi_mode_t currentMode = getMode(); - bool isEnabled = ((currentMode & WIFI_MODE_AP) != 0); - - if(isEnabled != enable) { - if(enable) { - return mode((wifi_mode_t)(currentMode | WIFI_MODE_AP)); - } else { - return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_AP))); - } - } else { - return true; - } -} - - -// ----------------------------------------------------------------------------------------------------------------------- -// ------------------------------------------------ Generic Network function --------------------------------------------- -// ----------------------------------------------------------------------------------------------------------------------- - -static bool _dns_busy = false; - -/** - * DNS callback - * @param name - * @param ipaddr - * @param callback_arg - */ -static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) -{ - if(ipaddr) { - (*reinterpret_cast(callback_arg)) = ipaddr->u_addr.ip4.addr; - } - _dns_busy = false; -} - -/** - * Resolve the given hostname to an IP address. - * @param aHostname Name to be resolved - * @param aResult IPAddress structure to store the returned IP address - * @return 1 if aIPAddrString was successfully converted to an IP address, - * else error code - */ -int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) -{ - ip_addr_t addr; - aResult = static_cast(0); - - _dns_busy = true; - err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult); - if(err == ERR_OK && addr.u_addr.ip4.addr) { - aResult = addr.u_addr.ip4.addr; - _dns_busy = false; - } else if(err == ERR_INPROGRESS) { - while(_dns_busy){ - delay(1); - } - } else { - _dns_busy = false; - return 0; - } - return 1; -} - +/* + ESP8266WiFiGeneric.cpp - WiFi library for esp8266 + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Reworked on 28 Dec 2015 by Markus Sattler + + */ + +#include "WiFi.h" +#include "WiFiGeneric.h" + +extern "C" { +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "lwip/ip_addr.h" +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/dns.h" +#include "esp_ipc.h" + + +} //extern "C" + +#include "esp32-hal-log.h" + +#undef min +#undef max +#include + +#include "sdkconfig.h" + +#if CONFIG_FREERTOS_UNICORE +#define ARDUINO_RUNNING_CORE 0 +#else +#define ARDUINO_RUNNING_CORE 1 +#endif + +static xQueueHandle _network_event_queue; +static TaskHandle_t _network_event_task_handle = NULL; + +static void _network_event_task(void * arg){ + system_event_t *event = NULL; + for (;;) { + if(xQueueReceive(_network_event_queue, &event, portMAX_DELAY) == pdTRUE){ + WiFiGenericClass::_eventCallback(arg, event); + } + } + vTaskDelete(NULL); + _network_event_task_handle = NULL; +} + +static esp_err_t _network_event_cb(void *arg, system_event_t *event){ + if (xQueueSend(_network_event_queue, &event, portMAX_DELAY) != pdPASS) { + log_w("Network Event Queue Send Failed!"); + return ESP_FAIL; + } + return ESP_OK; +} + +static void _start_network_event_task(){ + if(!_network_event_queue){ + _network_event_queue = xQueueCreate(32, sizeof(system_event_t *)); + if(!_network_event_queue){ + log_e("Network Event Queue Create Failed!"); + return; + } + } + if(!_network_event_task_handle){ + xTaskCreatePinnedToCore(_network_event_task, "network_event", 4096, NULL, 2, &_network_event_task_handle, ARDUINO_RUNNING_CORE); + if(!_network_event_task_handle){ + log_e("Network Event Task Start Failed!"); + return; + } + } + esp_event_loop_init(&_network_event_cb, NULL); +} + +// ----------------------------------------------------------------------------------------------------------------------- +// ------------------------------------------------- Generic WiFi function ----------------------------------------------- +// ----------------------------------------------------------------------------------------------------------------------- + +typedef struct { + WiFiEventCb cb; + WiFiEventFullCb fcb; + WiFiEventSysCb scb; + system_event_id_t event; +} WiFiEventCbList_t; + +// arduino dont like std::vectors move static here +static std::vector cbEventList; + +bool WiFiGenericClass::_esp_wifi_started = false; +bool WiFiGenericClass::_persistent = true; +wifi_mode_t WiFiGenericClass::_forceSleepLastMode = WIFI_MODE_NULL; + +void WiFiGenericClass::tcpipInit(){ + static bool initialized = false; + if(!initialized){ + initialized = true; + _start_network_event_task(); + tcpip_adapter_init(); + } +} + +bool WiFiGenericClass::wifiLowLevelDeinit(){ + //deinit not working yet! + //esp_wifi_deinit(); + return true; +} + +bool WiFiGenericClass::espWiFiStart(){ + if(_esp_wifi_started){ + return true; + } + if(!wifiLowLevelInit()){ + return false; + } + esp_err_t err = esp_wifi_start(); + if (err != ESP_OK) { + log_e("esp_wifi_start %d", err); + wifiLowLevelDeinit(); + return false; + } + _esp_wifi_started = true; + return true; +} + +bool WiFiGenericClass::espWiFiStop(){ + esp_err_t err; + if(!_esp_wifi_started){ + return true; + } + err = esp_wifi_stop(); + if(err){ + log_e("Could not stop WiFi! %u", err); + return false; + } + _esp_wifi_started = false; + return wifiLowLevelDeinit(); +} + +bool WiFiGenericClass::wifiLowLevelInit(){ + static bool lowLevelInitDone = false; + if(!lowLevelInitDone){ + tcpipInit(); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t err = esp_wifi_init(&cfg); + if(err){ + log_e("esp_wifi_init %d", err); + return false; + } + if (!_persistent) { + esp_wifi_set_storage(WIFI_STORAGE_RAM); + } + esp_wifi_set_mode(WIFI_MODE_NULL); + lowLevelInitDone = true; + } + return true; +} + +WiFiGenericClass::WiFiGenericClass() +{ + +} + +/** + * set callback function + * @param cbEvent WiFiEventCb + * @param event optional filter (WIFI_EVENT_MAX is all events) + */ +void WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + WiFiEventCbList_t newEventHandler; + newEventHandler.cb = cbEvent; + newEventHandler.fcb = NULL; + newEventHandler.scb = NULL; + newEventHandler.event = event; + cbEventList.push_back(newEventHandler); +} + +void WiFiGenericClass::onEvent(WiFiEventFullCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + WiFiEventCbList_t newEventHandler; + newEventHandler.cb = NULL; + newEventHandler.fcb = cbEvent; + newEventHandler.scb = NULL; + newEventHandler.event = event; + cbEventList.push_back(newEventHandler); +} + +void WiFiGenericClass::onEvent(WiFiEventSysCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + WiFiEventCbList_t newEventHandler; + newEventHandler.cb = NULL; + newEventHandler.fcb = NULL; + newEventHandler.scb = cbEvent; + newEventHandler.event = event; + cbEventList.push_back(newEventHandler); +} + +/** + * removes a callback form event handler + * @param cbEvent WiFiEventCb + * @param event optional filter (WIFI_EVENT_MAX is all events) + */ +void WiFiGenericClass::removeEvent(WiFiEventCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.cb == cbEvent && entry.event == event) { + cbEventList.erase(cbEventList.begin() + i); + } + } +} + +void WiFiGenericClass::removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.fcb == cbEvent && entry.event == event) { + cbEventList.erase(cbEventList.begin() + i); + } + } +} + +void WiFiGenericClass::removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event) +{ + if(!cbEvent) { + return; + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.scb == cbEvent && entry.event == event) { + cbEventList.erase(cbEventList.begin() + i); + } + } +} + +/** + * callback for WiFi events + * @param arg + */ +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG +const char * system_event_names[] = { "WIFI_READY", "SCAN_DONE", "STA_START", "STA_STOP", "STA_CONNECTED", "STA_DISCONNECTED", "STA_AUTHMODE_CHANGE", "STA_GOT_IP", "STA_LOST_IP", "STA_WPS_ER_SUCCESS", "STA_WPS_ER_FAILED", "STA_WPS_ER_TIMEOUT", "STA_WPS_ER_PIN", "AP_START", "AP_STOP", "AP_STACONNECTED", "AP_STADISCONNECTED", "AP_PROBEREQRECVED", "GOT_IP6", "ETH_START", "ETH_STOP", "ETH_CONNECTED", "ETH_DISCONNECTED", "ETH_GOT_IP", "MAX"}; +#endif +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN +const char * system_event_reasons[] = { "UNSPECIFIED", "AUTH_EXPIRE", "AUTH_LEAVE", "ASSOC_EXPIRE", "ASSOC_TOOMANY", "NOT_AUTHED", "NOT_ASSOCED", "ASSOC_LEAVE", "ASSOC_NOT_AUTHED", "DISASSOC_PWRCAP_BAD", "DISASSOC_SUPCHAN_BAD", "IE_INVALID", "MIC_FAILURE", "4WAY_HANDSHAKE_TIMEOUT", "GROUP_KEY_UPDATE_TIMEOUT", "IE_IN_4WAY_DIFFERS", "GROUP_CIPHER_INVALID", "PAIRWISE_CIPHER_INVALID", "AKMP_INVALID", "UNSUPP_RSN_IE_VERSION", "INVALID_RSN_IE_CAP", "802_1X_AUTH_FAILED", "CIPHER_SUITE_REJECTED", "BEACON_TIMEOUT", "NO_AP_FOUND", "AUTH_FAIL", "ASSOC_FAIL", "HANDSHAKE_TIMEOUT" }; +#define reason2str(r) ((r>176)?system_event_reasons[r-177]:system_event_reasons[r-1]) +#endif +esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event) +{ + log_d("Event: %d - %s", event->event_id, system_event_names[event->event_id]); + if(event->event_id == SYSTEM_EVENT_SCAN_DONE) { + WiFiScanClass::_scanDone(); + } else if(event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) { + uint8_t reason = event->event_info.disconnected.reason; + log_w("Reason: %u - %s", reason, reason2str(reason)); + if(reason == WIFI_REASON_NO_AP_FOUND) { + WiFiSTAClass::_setStatus(WL_NO_SSID_AVAIL); + } else if(reason == WIFI_REASON_AUTH_FAIL || reason == WIFI_REASON_ASSOC_FAIL) { + WiFiSTAClass::_setStatus(WL_CONNECT_FAILED); + } else if(reason == WIFI_REASON_BEACON_TIMEOUT || reason == WIFI_REASON_HANDSHAKE_TIMEOUT) { + WiFiSTAClass::_setStatus(WL_CONNECTION_LOST); + } else if(reason == WIFI_REASON_AUTH_EXPIRE) { + if(WiFi.getAutoReconnect()){ + WiFi.begin(); + } + } else { + WiFiSTAClass::_setStatus(WL_DISCONNECTED); + } + } else if(event->event_id == SYSTEM_EVENT_STA_START) { + WiFiSTAClass::_setStatus(WL_DISCONNECTED); + } else if(event->event_id == SYSTEM_EVENT_STA_STOP) { + WiFiSTAClass::_setStatus(WL_NO_SHIELD); + } else if(event->event_id == SYSTEM_EVENT_STA_CONNECTED) { + WiFiSTAClass::_setStatus(WL_IDLE_STATUS); + } else if(event->event_id == SYSTEM_EVENT_STA_GOT_IP) { +//#1081 https://github.com/espressif/arduino-esp32/issues/1081 +// if(WiFiSTAClass::status() == WL_IDLE_STATUS) + { + WiFiSTAClass::_setStatus(WL_CONNECTED); + } + } + + for(uint32_t i = 0; i < cbEventList.size(); i++) { + WiFiEventCbList_t entry = cbEventList[i]; + if(entry.cb || entry.fcb || entry.scb) { + if(entry.event == (system_event_id_t) event->event_id || entry.event == SYSTEM_EVENT_MAX) { + if(entry.cb){ + entry.cb((system_event_id_t) event->event_id); + } else if(entry.fcb){ + entry.fcb((system_event_id_t) event->event_id, (system_event_info_t) event->event_info); + } else { + entry.scb(event); + } + } + } + } + return ESP_OK; +} + +/** + * Return the current channel associated with the network + * @return channel (1-13) + */ +int32_t WiFiGenericClass::channel(void) +{ + uint8_t primaryChan; + wifi_second_chan_t secondChan; + esp_wifi_get_channel(&primaryChan, &secondChan); + return primaryChan; +} + + +/** + * store WiFi config in SDK flash area + * @param persistent + */ +void WiFiGenericClass::persistent(bool persistent) +{ + _persistent = persistent; +} + + +/** + * set new mode + * @param m WiFiMode_t + */ +bool WiFiGenericClass::mode(wifi_mode_t m) +{ + wifi_mode_t cm = getMode(); + if(cm == WIFI_MODE_MAX){ + return false; + } + if(cm == m) { + return true; + } + esp_err_t err; + err = esp_wifi_set_mode(m); + if(err){ + log_e("Could not set mode! %u", err); + return false; + } + if(m){ + return espWiFiStart(); + } + return espWiFiStop(); +} + +/** + * get WiFi mode + * @return WiFiMode + */ +wifi_mode_t WiFiGenericClass::getMode() +{ + if(!wifiLowLevelInit()){ + return WIFI_MODE_MAX; + } + uint8_t mode; + esp_wifi_get_mode((wifi_mode_t*)&mode); + return (wifi_mode_t)mode; +} + +/** + * control STA mode + * @param enable bool + * @return ok + */ +bool WiFiGenericClass::enableSTA(bool enable) +{ + + wifi_mode_t currentMode = getMode(); + bool isEnabled = ((currentMode & WIFI_MODE_STA) != 0); + + if(isEnabled != enable) { + if(enable) { + return mode((wifi_mode_t)(currentMode | WIFI_MODE_STA)); + } else { + return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_STA))); + } + } else { + return true; + } +} + +/** + * control AP mode + * @param enable bool + * @return ok + */ +bool WiFiGenericClass::enableAP(bool enable) +{ + + wifi_mode_t currentMode = getMode(); + bool isEnabled = ((currentMode & WIFI_MODE_AP) != 0); + + if(isEnabled != enable) { + if(enable) { + return mode((wifi_mode_t)(currentMode | WIFI_MODE_AP)); + } else { + return mode((wifi_mode_t)(currentMode & (~WIFI_MODE_AP))); + } + } else { + return true; + } +} + + +// ----------------------------------------------------------------------------------------------------------------------- +// ------------------------------------------------ Generic Network function --------------------------------------------- +// ----------------------------------------------------------------------------------------------------------------------- + +static bool _dns_busy = false; + +/** + * DNS callback + * @param name + * @param ipaddr + * @param callback_arg + */ +static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{ + if(ipaddr) { + (*reinterpret_cast(callback_arg)) = ipaddr->u_addr.ip4.addr; + } + _dns_busy = false; +} + +/** + * Resolve the given hostname to an IP address. + * @param aHostname Name to be resolved + * @param aResult IPAddress structure to store the returned IP address + * @return 1 if aIPAddrString was successfully converted to an IP address, + * else error code + */ +int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) +{ + ip_addr_t addr; + aResult = static_cast(0); + + _dns_busy = true; + err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult); + if(err == ERR_OK && addr.u_addr.ip4.addr) { + aResult = addr.u_addr.ip4.addr; + _dns_busy = false; + } else if(err == ERR_INPROGRESS) { + while(_dns_busy){ + delay(1); + } + } else { + _dns_busy = false; + return 0; + } + return 1; +} + diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 81b79756336..e84cebdaab5 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -1,82 +1,82 @@ -/* - ESP8266WiFiGeneric.h - esp8266 Wifi support. - Based on WiFi.h from Ardiono WiFi shield library. - Copyright (c) 2011-2014 Arduino. All right reserved. - Modified by Ivan Grokhotkov, December 2014 - Reworked by Markus Sattler, December 2015 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef ESP32WIFIGENERIC_H_ -#define ESP32WIFIGENERIC_H_ - -#include "WiFiType.h" -#include -#include - -typedef void (*WiFiEventCb)(system_event_id_t event); -typedef void (*WiFiEventFullCb)(system_event_id_t event, system_event_info_t info); -typedef void (*WiFiEventSysCb)(system_event_t *event); - -class WiFiGenericClass -{ -public: - - WiFiGenericClass(); - - void onEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void onEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void onEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void removeEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - void removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); - - int32_t channel(void); - - void persistent(bool persistent); - - bool mode(wifi_mode_t); - wifi_mode_t getMode(); - - bool enableSTA(bool enable); - bool enableAP(bool enable); - - static esp_err_t _eventCallback(void *arg, system_event_t *event); - -protected: - - static bool _esp_wifi_started; - static bool _persistent; - static wifi_mode_t _forceSleepLastMode; - - void tcpipInit(); - bool espWiFiStart(); - bool espWiFiStop(); - bool wifiLowLevelInit(); - bool wifiLowLevelDeinit(); - -public: - - int hostByName(const char* aHostname, IPAddress& aResult); - -protected: - - friend class WiFiSTAClass; - friend class WiFiScanClass; - friend class WiFiAPClass; -}; - -#endif /* ESP32WIFIGENERIC_H_ */ +/* + ESP8266WiFiGeneric.h - esp8266 Wifi support. + Based on WiFi.h from Ardiono WiFi shield library. + Copyright (c) 2011-2014 Arduino. All right reserved. + Modified by Ivan Grokhotkov, December 2014 + Reworked by Markus Sattler, December 2015 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ESP32WIFIGENERIC_H_ +#define ESP32WIFIGENERIC_H_ + +#include "WiFiType.h" +#include +#include + +typedef void (*WiFiEventCb)(system_event_id_t event); +typedef void (*WiFiEventFullCb)(system_event_id_t event, system_event_info_t info); +typedef void (*WiFiEventSysCb)(system_event_t *event); + +class WiFiGenericClass +{ +public: + + WiFiGenericClass(); + + void onEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void onEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void onEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void removeEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void removeEvent(WiFiEventFullCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + void removeEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX); + + int32_t channel(void); + + void persistent(bool persistent); + + bool mode(wifi_mode_t); + wifi_mode_t getMode(); + + bool enableSTA(bool enable); + bool enableAP(bool enable); + + static esp_err_t _eventCallback(void *arg, system_event_t *event); + +protected: + + static bool _esp_wifi_started; + static bool _persistent; + static wifi_mode_t _forceSleepLastMode; + + void tcpipInit(); + bool espWiFiStart(); + bool espWiFiStop(); + bool wifiLowLevelInit(); + bool wifiLowLevelDeinit(); + +public: + + int hostByName(const char* aHostname, IPAddress& aResult); + +protected: + + friend class WiFiSTAClass; + friend class WiFiScanClass; + friend class WiFiAPClass; +}; + +#endif /* ESP32WIFIGENERIC_H_ */ diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index 3c465853885..ef34471e8c0 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -1,642 +1,642 @@ -/* - ESP8266WiFiSTA.cpp - WiFi library for esp8266 - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Reworked on 28 Dec 2015 by Markus Sattler - - */ - -#include "WiFi.h" -#include "WiFiGeneric.h" -#include "WiFiSTA.h" - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lwip/err.h" -#include "lwip/dns.h" -#include -#include -} - -// ----------------------------------------------------------------------------------------------------------------------- -// ---------------------------------------------------- Private functions ------------------------------------------------ -// ----------------------------------------------------------------------------------------------------------------------- - -static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs); - - -/** - * compare two STA configurations - * @param lhs station_config - * @param rhs station_config - * @return equal - */ -static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs) -{ - if(strcmp(reinterpret_cast(lhs.sta.ssid), reinterpret_cast(rhs.sta.ssid)) != 0) { - return false; - } - - if(strcmp(reinterpret_cast(lhs.sta.password), reinterpret_cast(rhs.sta.password)) != 0) { - return false; - } - - if(lhs.sta.bssid_set != rhs.sta.bssid_set) { - return false; - } - - if(lhs.sta.bssid_set) { - if(memcmp(lhs.sta.bssid, rhs.sta.bssid, 6) != 0) { - return false; - } - } - - return true; -} - -// ----------------------------------------------------------------------------------------------------------------------- -// ---------------------------------------------------- STA function ----------------------------------------------------- -// ----------------------------------------------------------------------------------------------------------------------- - -bool WiFiSTAClass::_autoReconnect = true; -bool WiFiSTAClass::_useStaticIp = false; -wl_status_t WiFiSTAClass::_status = WL_NO_SHIELD; -/** - * Start Wifi connection - * if passphrase is set the most secure supported mode will be automatically selected - * @param ssid const char* Pointer to the SSID string. - * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). - * @param bssid uint8_t[6] Optional. BSSID / MAC of AP - * @param channel Optional. Channel of AP - * @param connect Optional. call connect - * @return - */ -wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) -{ - - if(!WiFi.enableSTA(true)) { - // enable STA failed - return WL_CONNECT_FAILED; - } - - if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { - // fail SSID too long or missing! - return WL_CONNECT_FAILED; - } - - if(passphrase && strlen(passphrase) > 64) { - // fail passphrase too long! - return WL_CONNECT_FAILED; - } - - wifi_config_t conf; - strcpy(reinterpret_cast(conf.sta.ssid), ssid); - - if(passphrase) { - if (strlen(passphrase) == 64) // it's not a passphrase, is the PSK - memcpy(reinterpret_cast(conf.sta.password), passphrase, 64); - else - strcpy(reinterpret_cast(conf.sta.password), passphrase); - } else { - *conf.sta.password = 0; - } - - if(bssid) { - conf.sta.bssid_set = 1; - memcpy((void *) &conf.sta.bssid[0], (void *) bssid, 6); - } else { - conf.sta.bssid_set = 0; - } - - wifi_config_t current_conf; - esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); - if(!sta_config_equal(current_conf, conf)) { - esp_wifi_set_config(WIFI_IF_STA, &conf); - } - - if(channel > 0 && channel <= 13) { - esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); - } - - esp_wifi_start(); - if(connect) { - esp_wifi_connect(); - } - - if(!_useStaticIp) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else { - tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - } - - return status(); -} - -wl_status_t WiFiSTAClass::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) -{ - return begin((const char*) ssid, (const char*) passphrase, channel, bssid, connect); -} - -/** - * Use to connect to SDK config. - * @return wl_status_t - */ -wl_status_t WiFiSTAClass::begin() -{ - - if(!WiFi.enableSTA(true)) { - // enable STA failed - return WL_CONNECT_FAILED; - } - esp_wifi_start(); - esp_wifi_connect(); - - if(!_useStaticIp) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else { - tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - } - - return status(); -} - -void WiFiSTAClass::_setStatus(wl_status_t status) -{ - _status = status; - //log_i("wifi status: %d", status); -} - -/** - * Change IP configuration settings disabling the dhcp client - * @param local_ip Static ip configuration - * @param gateway Static gateway configuration - * @param subnet Static Subnet mask - * @param dns1 Static DNS server 1 - * @param dns2 Static DNS server 2 - */ -bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) -{ - esp_err_t err = ESP_OK; - - if(!WiFi.enableSTA(true)) { - return false; - } - esp_wifi_start(); - - tcpip_adapter_ip_info_t info; - - if(local_ip != (uint32_t)0x00000000){ - info.ip.addr = static_cast(local_ip); - info.gw.addr = static_cast(gateway); - info.netmask.addr = static_cast(subnet); - } else { - info.ip.addr = 0; - info.gw.addr = 0; - info.netmask.addr = 0; - } - - err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); - if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED){ - log_e("DHCP could not be stopped! Error: %d", err); - return false; - } - - err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); - if(err != ERR_OK){ - log_e("STA IP could not be configured! Error: %d", err); - return false; - } - - if(info.ip.addr){ - _useStaticIp = true; - } else { - err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED){ - log_w("DHCP could not be started! Error: %d", err); - return false; - } - _useStaticIp = false; - } - - ip_addr_t d; - d.type = IPADDR_TYPE_V4; - - if(dns1 != (uint32_t)0x00000000) { - // Set DNS1-Server - d.u_addr.ip4.addr = static_cast(dns1); - dns_setserver(0, &d); - } - - if(dns2 != (uint32_t)0x00000000) { - // Set DNS2-Server - d.u_addr.ip4.addr = static_cast(dns2); - dns_setserver(1, &d); - } - - return true; -} - -/** - * will force a disconnect an then start reconnecting to AP - * @return ok - */ -bool WiFiSTAClass::reconnect() -{ - if((WiFi.getMode() & WIFI_MODE_STA) != 0) { - if(esp_wifi_disconnect() == ESP_OK) { - return esp_wifi_connect() == ESP_OK; - } - } - return false; -} - -/** - * Disconnect from the network - * @param wifioff - * @return one value of wl_status_t enum - */ -bool WiFiSTAClass::disconnect(bool wifioff) -{ - bool ret; - wifi_config_t conf; - *conf.sta.ssid = 0; - *conf.sta.password = 0; - - WiFi.getMode(); - esp_wifi_start(); - esp_wifi_set_config(WIFI_IF_STA, &conf); - ret = esp_wifi_disconnect() == ESP_OK; - - if(wifioff) { - WiFi.enableSTA(false); - } - - return ret; -} - -/** - * is STA interface connected? - * @return true if STA is connected to an AD - */ -bool WiFiSTAClass::isConnected() -{ - return (status() == WL_CONNECTED); -} - - -/** - * Setting the ESP32 station to connect to the AP (which is recorded) - * automatically or not when powered on. Enable auto-connect by default. - * @param autoConnect bool - * @return if saved - */ -bool WiFiSTAClass::setAutoConnect(bool autoConnect) -{ - bool ret; - ret = esp_wifi_set_auto_connect(autoConnect); - return ret; -} - -/** - * Checks if ESP32 station mode will connect to AP - * automatically or not when it is powered on. - * @return auto connect - */ -bool WiFiSTAClass::getAutoConnect() -{ - bool autoConnect; - esp_wifi_get_auto_connect(&autoConnect); - return autoConnect; -} - -bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) -{ - _autoReconnect = autoReconnect; - return true; -} - -bool WiFiSTAClass::getAutoReconnect() -{ - return _autoReconnect; -} - -/** - * Wait for WiFi connection to reach a result - * returns the status reached or disconnect if STA is off - * @return wl_status_t - */ -uint8_t WiFiSTAClass::waitForConnectResult() -{ - //1 and 3 have STA enabled - if((WiFi.getMode() & WIFI_MODE_STA) == 0) { - return WL_DISCONNECTED; - } - int i = 0; - while((!status() || status() >= WL_DISCONNECTED) && i++ < 100) { - delay(100); - } - return status(); -} - -/** - * Get the station interface IP address. - * @return IPAddress station IP - */ -IPAddress WiFiSTAClass::localIP() -{ - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return IPAddress(ip.ip.addr); -} - - -/** - * Get the station interface MAC address. - * @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH - * @return pointer to uint8_t * - */ -uint8_t* WiFiSTAClass::macAddress(uint8_t* mac) -{ - esp_wifi_get_mac(WIFI_IF_STA, mac); - return mac; -} - -/** - * Get the station interface MAC address. - * @return String mac - */ -String WiFiSTAClass::macAddress(void) -{ - uint8_t mac[6]; - char macStr[18] = { 0 }; - esp_wifi_get_mac(WIFI_IF_STA, mac); - - sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return String(macStr); -} - -/** - * Get the interface subnet mask address. - * @return IPAddress subnetMask - */ -IPAddress WiFiSTAClass::subnetMask() -{ - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return IPAddress(ip.netmask.addr); -} - -/** - * Get the gateway ip address. - * @return IPAddress gatewayIP - */ -IPAddress WiFiSTAClass::gatewayIP() -{ - tcpip_adapter_ip_info_t ip; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); - return IPAddress(ip.gw.addr); -} - -/** - * Get the DNS ip address. - * @param dns_no - * @return IPAddress DNS Server IP - */ -IPAddress WiFiSTAClass::dnsIP(uint8_t dns_no) -{ - ip_addr_t dns_ip = dns_getserver(dns_no); - return IPAddress(dns_ip.u_addr.ip4.addr); -} - -/** - * Return Connection status. - * @return one of the value defined in wl_status_t - * - */ -wl_status_t WiFiSTAClass::status() -{ - return WiFiSTAClass::_status; -} - -/** - * Return the current SSID associated with the network - * @return SSID - */ -String WiFiSTAClass::SSID() const -{ - wifi_ap_record_t info; - if(!esp_wifi_sta_get_ap_info(&info)) { - return String(reinterpret_cast(info.ssid)); - } - return String(); -} - -/** - * Return the current pre shared key associated with the network - * @return psk string - */ -String WiFiSTAClass::psk() const -{ - wifi_config_t conf; - esp_wifi_get_config(WIFI_IF_STA, &conf); - return String(reinterpret_cast(conf.sta.password)); -} - -/** - * Return the current bssid / mac associated with the network if configured - * @return bssid uint8_t * - */ -uint8_t* WiFiSTAClass::BSSID(void) -{ - static uint8_t bssid[6]; - wifi_ap_record_t info; - if(!esp_wifi_sta_get_ap_info(&info)) { - memcpy(bssid, info.bssid, 6); - return reinterpret_cast(bssid); - } - return NULL; -} - -/** - * Return the current bssid / mac associated with the network if configured - * @return String bssid mac - */ -String WiFiSTAClass::BSSIDstr(void) -{ - uint8_t* bssid = BSSID(); - if(!bssid){ - return String(); - } - char mac[18] = { 0 }; - sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); - return String(mac); -} - -/** - * Return the current network RSSI. - * @return RSSI value - */ -int8_t WiFiSTAClass::RSSI(void) -{ - wifi_ap_record_t info; - if(!esp_wifi_sta_get_ap_info(&info)) { - return info.rssi; - } - return 0; -} - -/** - * Get the station interface Host name. - * @return char array hostname - */ -const char * WiFiSTAClass::getHostname() -{ - const char * hostname; - if(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname)){ - return NULL; - } - return hostname; -} - -/** - * Set the station interface Host name. - * @param hostname pointer to const string - * @return true on success - */ -bool WiFiSTAClass::setHostname(const char * hostname) -{ - return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname) == 0; -} - -/** - * Enable IPv6 on the station interface. - * @return true on success - */ -bool WiFiSTAClass::enableIpV6() -{ - return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA) == 0; -} - -/** - * Get the station interface IPv6 address. - * @return IPv6Address - */ -IPv6Address WiFiSTAClass::localIPv6() -{ - static ip6_addr_t addr; - if(tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &addr)){ - return IPv6Address(); - } - return IPv6Address(addr.addr); -} - - -bool WiFiSTAClass::_smartConfigStarted = false; -bool WiFiSTAClass::_smartConfigDone = false; - - -bool WiFiSTAClass::beginSmartConfig() { - if (_smartConfigStarted) { - return false; - } - - if (!WiFi.mode(WIFI_STA)) { - return false; - } - - esp_wifi_disconnect(); - - esp_err_t err; - err = esp_smartconfig_start(reinterpret_cast(&WiFiSTAClass::_smartConfigCallback), 1); - if (err == ESP_OK) { - _smartConfigStarted = true; - _smartConfigDone = false; - return true; - } - return false; -} - -bool WiFiSTAClass::stopSmartConfig() { - if (!_smartConfigStarted) { - return true; - } - - if (esp_smartconfig_stop() == ESP_OK) { - _smartConfigStarted = false; - return true; - } - - return false; -} - -bool WiFiSTAClass::smartConfigDone() { - if (!_smartConfigStarted) { - return false; - } - - return _smartConfigDone; -} - -#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG -const char * sc_status_strings[] = { - "WAIT", - "FIND_CHANNEL", - "GETTING_SSID_PSWD", - "LINK", - "LINK_OVER" -}; - -const char * sc_type_strings[] = { - "ESPTOUCH", - "AIRKISS", - "ESPTOUCH_AIRKISS" -}; -#endif - -void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) { - smartconfig_status_t status = (smartconfig_status_t) st; - log_d("Status: %s", sc_status_strings[st % 5]); - if (status == SC_STATUS_GETTING_SSID_PSWD) { - smartconfig_type_t * type = (smartconfig_type_t *)result; - log_d("Type: %s", sc_type_strings[*type % 3]); - } else if (status == SC_STATUS_LINK) { - wifi_sta_config_t *sta_conf = reinterpret_cast(result); - log_d("SSID: %s", (char *)(sta_conf->ssid)); - sta_conf->bssid_set = 0; - esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)sta_conf); - esp_wifi_connect(); - _smartConfigDone = true; - } else if (status == SC_STATUS_LINK_OVER) { - if(result){ - ip4_addr_t * ip = (ip4_addr_t *)result; - log_d("Sender IP: " IPSTR, IP2STR(ip)); - } - WiFi.stopSmartConfig(); - } -} +/* + ESP8266WiFiSTA.cpp - WiFi library for esp8266 + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Reworked on 28 Dec 2015 by Markus Sattler + + */ + +#include "WiFi.h" +#include "WiFiGeneric.h" +#include "WiFiSTA.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lwip/err.h" +#include "lwip/dns.h" +#include +#include +} + +// ----------------------------------------------------------------------------------------------------------------------- +// ---------------------------------------------------- Private functions ------------------------------------------------ +// ----------------------------------------------------------------------------------------------------------------------- + +static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs); + + +/** + * compare two STA configurations + * @param lhs station_config + * @param rhs station_config + * @return equal + */ +static bool sta_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs) +{ + if(strcmp(reinterpret_cast(lhs.sta.ssid), reinterpret_cast(rhs.sta.ssid)) != 0) { + return false; + } + + if(strcmp(reinterpret_cast(lhs.sta.password), reinterpret_cast(rhs.sta.password)) != 0) { + return false; + } + + if(lhs.sta.bssid_set != rhs.sta.bssid_set) { + return false; + } + + if(lhs.sta.bssid_set) { + if(memcmp(lhs.sta.bssid, rhs.sta.bssid, 6) != 0) { + return false; + } + } + + return true; +} + +// ----------------------------------------------------------------------------------------------------------------------- +// ---------------------------------------------------- STA function ----------------------------------------------------- +// ----------------------------------------------------------------------------------------------------------------------- + +bool WiFiSTAClass::_autoReconnect = true; +bool WiFiSTAClass::_useStaticIp = false; +wl_status_t WiFiSTAClass::_status = WL_NO_SHIELD; +/** + * Start Wifi connection + * if passphrase is set the most secure supported mode will be automatically selected + * @param ssid const char* Pointer to the SSID string. + * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). + * @param bssid uint8_t[6] Optional. BSSID / MAC of AP + * @param channel Optional. Channel of AP + * @param connect Optional. call connect + * @return + */ +wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) +{ + + if(!WiFi.enableSTA(true)) { + // enable STA failed + return WL_CONNECT_FAILED; + } + + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + // fail SSID too long or missing! + return WL_CONNECT_FAILED; + } + + if(passphrase && strlen(passphrase) > 64) { + // fail passphrase too long! + return WL_CONNECT_FAILED; + } + + wifi_config_t conf; + strcpy(reinterpret_cast(conf.sta.ssid), ssid); + + if(passphrase) { + if (strlen(passphrase) == 64) // it's not a passphrase, is the PSK + memcpy(reinterpret_cast(conf.sta.password), passphrase, 64); + else + strcpy(reinterpret_cast(conf.sta.password), passphrase); + } else { + *conf.sta.password = 0; + } + + if(bssid) { + conf.sta.bssid_set = 1; + memcpy((void *) &conf.sta.bssid[0], (void *) bssid, 6); + } else { + conf.sta.bssid_set = 0; + } + + wifi_config_t current_conf; + esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); + if(!sta_config_equal(current_conf, conf)) { + esp_wifi_set_config(WIFI_IF_STA, &conf); + } + + if(channel > 0 && channel <= 13) { + esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); + } + + esp_wifi_start(); + if(connect) { + esp_wifi_connect(); + } + + if(!_useStaticIp) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } else { + tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); + } + + return status(); +} + +wl_status_t WiFiSTAClass::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) +{ + return begin((const char*) ssid, (const char*) passphrase, channel, bssid, connect); +} + +/** + * Use to connect to SDK config. + * @return wl_status_t + */ +wl_status_t WiFiSTAClass::begin() +{ + + if(!WiFi.enableSTA(true)) { + // enable STA failed + return WL_CONNECT_FAILED; + } + esp_wifi_start(); + esp_wifi_connect(); + + if(!_useStaticIp) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } else { + tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); + } + + return status(); +} + +void WiFiSTAClass::_setStatus(wl_status_t status) +{ + _status = status; + //log_i("wifi status: %d", status); +} + +/** + * Change IP configuration settings disabling the dhcp client + * @param local_ip Static ip configuration + * @param gateway Static gateway configuration + * @param subnet Static Subnet mask + * @param dns1 Static DNS server 1 + * @param dns2 Static DNS server 2 + */ +bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) +{ + esp_err_t err = ESP_OK; + + if(!WiFi.enableSTA(true)) { + return false; + } + esp_wifi_start(); + + tcpip_adapter_ip_info_t info; + + if(local_ip != (uint32_t)0x00000000){ + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + } else { + info.ip.addr = 0; + info.gw.addr = 0; + info.netmask.addr = 0; + } + + err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); + if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED){ + log_e("DHCP could not be stopped! Error: %d", err); + return false; + } + + err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &info); + if(err != ERR_OK){ + log_e("STA IP could not be configured! Error: %d", err); + return false; + } + + if(info.ip.addr){ + _useStaticIp = true; + } else { + err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED){ + log_w("DHCP could not be started! Error: %d", err); + return false; + } + _useStaticIp = false; + } + + ip_addr_t d; + d.type = IPADDR_TYPE_V4; + + if(dns1 != (uint32_t)0x00000000) { + // Set DNS1-Server + d.u_addr.ip4.addr = static_cast(dns1); + dns_setserver(0, &d); + } + + if(dns2 != (uint32_t)0x00000000) { + // Set DNS2-Server + d.u_addr.ip4.addr = static_cast(dns2); + dns_setserver(1, &d); + } + + return true; +} + +/** + * will force a disconnect an then start reconnecting to AP + * @return ok + */ +bool WiFiSTAClass::reconnect() +{ + if((WiFi.getMode() & WIFI_MODE_STA) != 0) { + if(esp_wifi_disconnect() == ESP_OK) { + return esp_wifi_connect() == ESP_OK; + } + } + return false; +} + +/** + * Disconnect from the network + * @param wifioff + * @return one value of wl_status_t enum + */ +bool WiFiSTAClass::disconnect(bool wifioff) +{ + bool ret; + wifi_config_t conf; + *conf.sta.ssid = 0; + *conf.sta.password = 0; + + WiFi.getMode(); + esp_wifi_start(); + esp_wifi_set_config(WIFI_IF_STA, &conf); + ret = esp_wifi_disconnect() == ESP_OK; + + if(wifioff) { + WiFi.enableSTA(false); + } + + return ret; +} + +/** + * is STA interface connected? + * @return true if STA is connected to an AD + */ +bool WiFiSTAClass::isConnected() +{ + return (status() == WL_CONNECTED); +} + + +/** + * Setting the ESP32 station to connect to the AP (which is recorded) + * automatically or not when powered on. Enable auto-connect by default. + * @param autoConnect bool + * @return if saved + */ +bool WiFiSTAClass::setAutoConnect(bool autoConnect) +{ + bool ret; + ret = esp_wifi_set_auto_connect(autoConnect); + return ret; +} + +/** + * Checks if ESP32 station mode will connect to AP + * automatically or not when it is powered on. + * @return auto connect + */ +bool WiFiSTAClass::getAutoConnect() +{ + bool autoConnect; + esp_wifi_get_auto_connect(&autoConnect); + return autoConnect; +} + +bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) +{ + _autoReconnect = autoReconnect; + return true; +} + +bool WiFiSTAClass::getAutoReconnect() +{ + return _autoReconnect; +} + +/** + * Wait for WiFi connection to reach a result + * returns the status reached or disconnect if STA is off + * @return wl_status_t + */ +uint8_t WiFiSTAClass::waitForConnectResult() +{ + //1 and 3 have STA enabled + if((WiFi.getMode() & WIFI_MODE_STA) == 0) { + return WL_DISCONNECTED; + } + int i = 0; + while((!status() || status() >= WL_DISCONNECTED) && i++ < 100) { + delay(100); + } + return status(); +} + +/** + * Get the station interface IP address. + * @return IPAddress station IP + */ +IPAddress WiFiSTAClass::localIP() +{ + tcpip_adapter_ip_info_t ip; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); + return IPAddress(ip.ip.addr); +} + + +/** + * Get the station interface MAC address. + * @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH + * @return pointer to uint8_t * + */ +uint8_t* WiFiSTAClass::macAddress(uint8_t* mac) +{ + esp_wifi_get_mac(WIFI_IF_STA, mac); + return mac; +} + +/** + * Get the station interface MAC address. + * @return String mac + */ +String WiFiSTAClass::macAddress(void) +{ + uint8_t mac[6]; + char macStr[18] = { 0 }; + esp_wifi_get_mac(WIFI_IF_STA, mac); + + sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(macStr); +} + +/** + * Get the interface subnet mask address. + * @return IPAddress subnetMask + */ +IPAddress WiFiSTAClass::subnetMask() +{ + tcpip_adapter_ip_info_t ip; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); + return IPAddress(ip.netmask.addr); +} + +/** + * Get the gateway ip address. + * @return IPAddress gatewayIP + */ +IPAddress WiFiSTAClass::gatewayIP() +{ + tcpip_adapter_ip_info_t ip; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip); + return IPAddress(ip.gw.addr); +} + +/** + * Get the DNS ip address. + * @param dns_no + * @return IPAddress DNS Server IP + */ +IPAddress WiFiSTAClass::dnsIP(uint8_t dns_no) +{ + ip_addr_t dns_ip = dns_getserver(dns_no); + return IPAddress(dns_ip.u_addr.ip4.addr); +} + +/** + * Return Connection status. + * @return one of the value defined in wl_status_t + * + */ +wl_status_t WiFiSTAClass::status() +{ + return WiFiSTAClass::_status; +} + +/** + * Return the current SSID associated with the network + * @return SSID + */ +String WiFiSTAClass::SSID() const +{ + wifi_ap_record_t info; + if(!esp_wifi_sta_get_ap_info(&info)) { + return String(reinterpret_cast(info.ssid)); + } + return String(); +} + +/** + * Return the current pre shared key associated with the network + * @return psk string + */ +String WiFiSTAClass::psk() const +{ + wifi_config_t conf; + esp_wifi_get_config(WIFI_IF_STA, &conf); + return String(reinterpret_cast(conf.sta.password)); +} + +/** + * Return the current bssid / mac associated with the network if configured + * @return bssid uint8_t * + */ +uint8_t* WiFiSTAClass::BSSID(void) +{ + static uint8_t bssid[6]; + wifi_ap_record_t info; + if(!esp_wifi_sta_get_ap_info(&info)) { + memcpy(bssid, info.bssid, 6); + return reinterpret_cast(bssid); + } + return NULL; +} + +/** + * Return the current bssid / mac associated with the network if configured + * @return String bssid mac + */ +String WiFiSTAClass::BSSIDstr(void) +{ + uint8_t* bssid = BSSID(); + if(!bssid){ + return String(); + } + char mac[18] = { 0 }; + sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + return String(mac); +} + +/** + * Return the current network RSSI. + * @return RSSI value + */ +int8_t WiFiSTAClass::RSSI(void) +{ + wifi_ap_record_t info; + if(!esp_wifi_sta_get_ap_info(&info)) { + return info.rssi; + } + return 0; +} + +/** + * Get the station interface Host name. + * @return char array hostname + */ +const char * WiFiSTAClass::getHostname() +{ + const char * hostname; + if(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname)){ + return NULL; + } + return hostname; +} + +/** + * Set the station interface Host name. + * @param hostname pointer to const string + * @return true on success + */ +bool WiFiSTAClass::setHostname(const char * hostname) +{ + return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname) == 0; +} + +/** + * Enable IPv6 on the station interface. + * @return true on success + */ +bool WiFiSTAClass::enableIpV6() +{ + return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA) == 0; +} + +/** + * Get the station interface IPv6 address. + * @return IPv6Address + */ +IPv6Address WiFiSTAClass::localIPv6() +{ + static ip6_addr_t addr; + if(tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &addr)){ + return IPv6Address(); + } + return IPv6Address(addr.addr); +} + + +bool WiFiSTAClass::_smartConfigStarted = false; +bool WiFiSTAClass::_smartConfigDone = false; + + +bool WiFiSTAClass::beginSmartConfig() { + if (_smartConfigStarted) { + return false; + } + + if (!WiFi.mode(WIFI_STA)) { + return false; + } + + esp_wifi_disconnect(); + + esp_err_t err; + err = esp_smartconfig_start(reinterpret_cast(&WiFiSTAClass::_smartConfigCallback), 1); + if (err == ESP_OK) { + _smartConfigStarted = true; + _smartConfigDone = false; + return true; + } + return false; +} + +bool WiFiSTAClass::stopSmartConfig() { + if (!_smartConfigStarted) { + return true; + } + + if (esp_smartconfig_stop() == ESP_OK) { + _smartConfigStarted = false; + return true; + } + + return false; +} + +bool WiFiSTAClass::smartConfigDone() { + if (!_smartConfigStarted) { + return false; + } + + return _smartConfigDone; +} + +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG +const char * sc_status_strings[] = { + "WAIT", + "FIND_CHANNEL", + "GETTING_SSID_PSWD", + "LINK", + "LINK_OVER" +}; + +const char * sc_type_strings[] = { + "ESPTOUCH", + "AIRKISS", + "ESPTOUCH_AIRKISS" +}; +#endif + +void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) { + smartconfig_status_t status = (smartconfig_status_t) st; + log_d("Status: %s", sc_status_strings[st % 5]); + if (status == SC_STATUS_GETTING_SSID_PSWD) { + smartconfig_type_t * type = (smartconfig_type_t *)result; + log_d("Type: %s", sc_type_strings[*type % 3]); + } else if (status == SC_STATUS_LINK) { + wifi_sta_config_t *sta_conf = reinterpret_cast(result); + log_d("SSID: %s", (char *)(sta_conf->ssid)); + sta_conf->bssid_set = 0; + esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)sta_conf); + esp_wifi_connect(); + _smartConfigDone = true; + } else if (status == SC_STATUS_LINK_OVER) { + if(result){ + ip4_addr_t * ip = (ip4_addr_t *)result; + log_d("Sender IP: " IPSTR, IP2STR(ip)); + } + WiFi.stopSmartConfig(); + } +}