/* wificonfig.cpp - wifi functions class Copyright (c) 2014 Luc Lebosse. All rights reserved. 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 */ #include "../../include/esp3d_config.h" #if defined (WIFI_FEATURE) #ifdef ARDUINO_ARCH_ESP32 #include #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 #endif //ARDUINO_ARCH_ESP8266 #include "../wifi/wificonfig.h" #include "../network/netconfig.h" #include "../../core/esp3doutput.h" #include "../../core/settings_esp3d.h" const uint8_t DEFAULT_AP_MASK_VALUE[] = {255, 255, 255, 0}; WiFiConfig::WiFiConfig() { } WiFiConfig::~WiFiConfig() { end(); } /** * Check if SSID string is valid */ bool WiFiConfig::isSSIDValid (const char * ssid) { //limited size //char c; if (strlen (ssid) > MAX_SSID_LENGTH || strlen (ssid) < MIN_SSID_LENGTH) { return false; } //only printable for (uint i = 0; i < strlen (ssid); i++) { if (!isPrintable (ssid[i]) ) { return false; } } return true; } const char * WiFiConfig::hostname() { static String tmp; #if defined (ARDUINO_ARCH_ESP8266) if (WiFi.getMode() == WIFI_AP) { //No API for AP tmp = NetConfig::hostname(true); } else { tmp = WiFi.hostname(); } #endif //ARDUINO_ARCH_ESP8266 #if defined (ARDUINO_ARCH_ESP32) if (WiFi.getMode() == WIFI_AP) { //tmp = NetConfig::hostname(true); //Set API is not working so far tmp = WiFi.softAPgetHostname(); } else { tmp = WiFi.getHostname(); } #endif //ARDUINO_ARCH_ESP8266 return tmp.c_str(); } /** * Check if password string is valid */ bool WiFiConfig::isPasswordValid (const char * password) { if (strlen (password) == 0) { return true; //open network } //limited size if ((strlen (password) > MAX_PASSWORD_LENGTH) || (strlen (password) < MIN_PASSWORD_LENGTH)) { return false; } return true; } /* * Get WiFi signal strength */ int32_t WiFiConfig::getSignal (int32_t RSSI) { if (RSSI <= -100) { return 0; } if (RSSI >= -50) { return 100; } return (2 * (RSSI + 100) ); } /* * Connect client to AP */ bool WiFiConfig::ConnectSTA2AP() { String msg, msg_out; uint8_t count = 0; uint8_t dot = 0; wl_status_t status = WiFi.status(); ESP3DOutput output(ESP_ALL_CLIENTS); while (status != WL_CONNECTED && count < 40) { switch (status) { case WL_NO_SSID_AVAIL: msg="No SSID"; break; case WL_CONNECT_FAILED: msg="Connection failed"; break; case WL_CONNECTED: break; default: if ((dot>3) || (dot==0) ) { dot=0; msg_out = "Connecting"; } msg_out+="."; msg= msg_out; dot++; break; } ESP3DGlobalOutput::SetStatus(msg.c_str()); output.printMSG(msg.c_str()); output.flush(); Hal::wait (500); count++; status = WiFi.status(); } return (status == WL_CONNECTED); } /* * Start client mode (Station) */ bool WiFiConfig::StartSTA() { //Sanity check if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) { WiFi.disconnect(); } if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) { WiFi.softAPdisconnect(); } WiFi.enableAP (false); WiFi.mode(WIFI_STA); //Get parameters for STA String SSID = Settings_ESP3D::read_string(ESP_STA_SSID); String password = Settings_ESP3D::read_string(ESP_STA_PASSWORD); if (Settings_ESP3D::read_byte(ESP_STA_IP_MODE) != DHCP_MODE) { int32_t IP = Settings_ESP3D::read_IP(ESP_STA_IP_VALUE); int32_t GW = Settings_ESP3D::read_IP(ESP_STA_GATEWAY_VALUE); int32_t MK = Settings_ESP3D::read_IP(ESP_STA_MASK_VALUE); IPAddress ip(IP), mask(MK), gateway(GW); WiFi.config(ip, gateway,mask); } ESP3DOutput output(ESP_ALL_CLIENTS); String stmp; stmp = "Connecting to '" + SSID + "'";; output.printMSG(stmp.c_str()); if (WiFi.begin(SSID.c_str(), (password.length() > 0)?password.c_str():nullptr)) { #if defined (ARDUINO_ARCH_ESP8266) WiFi.setSleepMode(WIFI_NONE_SLEEP); if (!WiFi.hostname(NetConfig::hostname(true))) { output.printERROR("Set hostname STA failed"); } #endif //ARDUINO_ARCH_ESP8266 #if defined (ARDUINO_ARCH_ESP32) WiFi.setSleep(false); WiFi.setHostname(NetConfig::hostname(true)); #endif //ARDUINO_ARCH_ESP32 return ConnectSTA2AP(); } else { output.printERROR("Starting client failed"); return false; } } /** * Setup and start Access point */ bool WiFiConfig::StartAP() { ESP3DOutput output(ESP_ALL_CLIENTS); //Sanity check if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) { WiFi.disconnect(); } if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) { WiFi.softAPdisconnect(); } WiFi.enableSTA (false); WiFi.mode(WIFI_AP); //Set Sleep Mode to none #if defined (ARDUINO_ARCH_ESP8266) WiFi.setSleepMode(WIFI_NONE_SLEEP); //No API for it //if(!WiFi.hostname(NetConfig::hostname(true))){ // output.printERROR("Set hostname AP failed"); //} #endif //ARDUINO_ARCH_ESP8266 String SSID = Settings_ESP3D::read_string(ESP_AP_SSID); String password = Settings_ESP3D::read_string(ESP_AP_PASSWORD); //channel int8_t channel = Settings_ESP3D::read_byte (ESP_AP_CHANNEL); //IP int32_t IP = Settings_ESP3D::read_IP(ESP_AP_IP_VALUE); IPAddress ip(IP); IPAddress mask(DEFAULT_AP_MASK_VALUE); //Set static IP if (!WiFi.softAPConfig(ip, ip, mask)) { output.printERROR("Set IP to AP failed"); } else { output.printMSG(ip.toString().c_str()); } //Start AP if(WiFi.softAP(SSID.c_str(), (password.length() > 0)?password.c_str():nullptr, channel)) { String stmp = "AP SSID: '" + SSID; if (password.length() > 0) { stmp +="' is started and protected by password"; } else { stmp +=" is started not protected by passord"; } output.printMSG(stmp.c_str()); //must be done after starting AP not before #if defined (ARDUINO_ARCH_ESP32) WiFi.setSleep(false); if (!WiFi.softAPsetHostname(NetConfig::hostname(true))) { output.printERROR("Set hostname AP failed"); } #endif //ARDUINO_ARCH_ESP32 return true; } else { output.printERROR("Starting AP failed"); return false; } } bool WiFiConfig::started() { return (WiFi.getMode() != WIFI_OFF); } /** * begin WiFi setup */ bool WiFiConfig::begin() { bool res = false; end(); ESP3DOutput output(ESP_ALL_CLIENTS); output.printMSG("Starting WiFi"); int8_t wifiMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE); if (wifiMode == ESP_WIFI_AP) { res = StartAP(); } else if (wifiMode == ESP_WIFI_STA) { res = StartSTA(); //AP is backup mode if(!res) { res = StartAP(); } } //prepare the scan //WiFi.scanNetworks (true); return res; } /** * End WiFi */ void WiFiConfig::end() { //Sanity check if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) { WiFi.disconnect(true); } if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) { WiFi.softAPdisconnect(true); } WiFi.mode(WIFI_OFF); ESP3DOutput output(ESP_ALL_CLIENTS); output.printMSG("WiFi Off"); } /** * Handle not critical actions that must be done in sync environement */ void WiFiConfig::handle() { } const char* WiFiConfig::getSleepModeString () { #ifdef ARDUINO_ARCH_ESP32 if (WiFi.getSleep()) { return "Modem"; } else { return "None"; } #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 WiFiSleepType_t ps_type = WiFi.getSleepMode(); if (ps_type == WIFI_NONE_SLEEP) { return "None"; } else if (ps_type == WIFI_LIGHT_SLEEP) { return "Light"; } else if (ps_type == WIFI_MODEM_SLEEP) { return "Modem"; } else { return "???"; } #endif //ARDUINO_ARCH_ESP8266 } const char* WiFiConfig::getPHYModeString (uint8_t wifimode) { #ifdef ARDUINO_ARCH_ESP32 uint8_t PhyMode; esp_wifi_get_protocol ((wifimode == WIFI_STA)?ESP_IF_WIFI_STA:ESP_IF_WIFI_AP, &PhyMode); #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 (void)wifimode; WiFiPhyMode_t PhyMode = WiFi.getPhyMode(); #endif //ARDUINO_ARCH_ESP8266 if (PhyMode == (WIFI_PHY_MODE_11G) ) { return "11g"; } else if (PhyMode == (WIFI_PHY_MODE_11B) ) { return "11b"; } else if (PhyMode == (WIFI_PHY_MODE_11N) ) { return "11n"; } else { return "???"; } } bool WiFiConfig::is_AP_visible() { #ifdef ARDUINO_ARCH_ESP32 wifi_config_t conf; esp_wifi_get_config (ESP_IF_WIFI_AP, &conf); return (conf.ap.ssid_hidden == 0); #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 struct softap_config apconfig; wifi_softap_get_config (&apconfig); return (apconfig.ssid_hidden == 0); #endif //ARDUINO_ARCH_ESP8266 } const char * WiFiConfig::AP_SSID() { static String ssid; #ifdef ARDUINO_ARCH_ESP32 wifi_config_t conf; esp_wifi_get_config (ESP_IF_WIFI_AP, &conf); ssid = (const char*) conf.ap.ssid; #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 struct softap_config apconfig; wifi_softap_get_config (&apconfig); ssid = (const char*) apconfig.ssid; #endif //ARDUINO_ARCH_ESP8266 return ssid.c_str(); } const char * WiFiConfig::AP_Auth_String() { uint8_t mode = 0; #ifdef ARDUINO_ARCH_ESP32 wifi_config_t conf; esp_wifi_get_config (ESP_IF_WIFI_AP, &conf); mode = conf.ap.authmode; #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 struct softap_config apconfig; wifi_softap_get_config (&apconfig); mode = apconfig.authmode; #endif //ARDUINO_ARCH_ESP8266 if (mode == AUTH_OPEN) { return "None"; } else if (mode == AUTH_WEP) { return "WEP"; } else if (mode == AUTH_WPA_PSK) { return "WPA"; } else if (mode == AUTH_WPA2_PSK) { return "WPA2"; } else { return "WPA/WPA2"; } } const char * WiFiConfig::AP_Gateway_String() { static String tmp; #ifdef ARDUINO_ARCH_ESP32 tcpip_adapter_ip_info_t ip_AP; tcpip_adapter_get_ip_info (TCPIP_ADAPTER_IF_AP, &ip_AP); tmp = IPAddress (ip_AP.gw.addr).toString(); #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 struct ip_info ip_AP; if (!wifi_get_ip_info (SOFTAP_IF, &ip_AP)) { log_esp3d("Error getting gateway ip"); } tmp = IPAddress (ip_AP.gw).toString(); #endif //ARDUINO_ARCH_ESP8266 return tmp.c_str(); } const char * WiFiConfig::AP_Mask_String() { static String tmp; #ifdef ARDUINO_ARCH_ESP32 tcpip_adapter_ip_info_t ip_AP; tcpip_adapter_get_ip_info (TCPIP_ADAPTER_IF_AP, &ip_AP); tmp = IPAddress (ip_AP.netmask.addr).toString(); #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 struct ip_info ip_AP; if (!wifi_get_ip_info (SOFTAP_IF, &ip_AP)) { log_esp3d("Error getting mask ip"); } tmp = IPAddress (ip_AP.netmask).toString(); #endif //ARDUINO_ARCH_ESP8266 return tmp.c_str(); } const char * WiFiConfig::getConnectedSTA(uint8_t * totalcount, bool reset) { static uint8_t count = 0; static uint8_t current = 0; static String data; data = ""; #ifdef ARDUINO_ARCH_ESP32 if (current > count) { current =0; } static wifi_sta_list_t station; static tcpip_adapter_sta_list_t tcpip_sta_list; if (reset) { count = 0; } if (count == 0) { current = 0; esp_wifi_ap_get_sta_list (&station); tcpip_adapter_get_sta_list (&station, &tcpip_sta_list); count = station.num; } if (count > 0) { data = IPAddress (tcpip_sta_list.sta[current].ip.addr).toString(); data += "("; data += NetConfig::mac2str(tcpip_sta_list.sta[current].mac); data += ")"; current++; } #endif //ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP8266 static struct station_info * station; if (current > count) { current = 0; count = 0; } if (reset) { count = 0; } if (count == 0) { current = 0; station = wifi_softap_get_station_info(); struct station_info * station_tmp = station; while (station) { //go next record count++; station = STAILQ_NEXT (station, next); } station = station_tmp; } if ((count > 0) && station) { data = IPAddress ((const uint8_t *) &station->ip).toString(); data += "("; data += NetConfig::mac2str(station->bssid); data += ")"; current++; station = STAILQ_NEXT (station, next); if ((current == count) || !station) { wifi_softap_free_station_info(); } } #endif //ARDUINO_ARCH_ESP8266 if(totalcount) { *totalcount = count; } return data.c_str(); } #endif // WIFI_FEATURE