/* 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 "ESP8266WiFi.h" #include "ESP8266WiFiGeneric.h" #include "ESP8266WiFiAP.h" extern "C" { #include "c_types.h" #include "ets_sys.h" #include "os_type.h" #include "osapi.h" #include "mem.h" #include "user_interface.h" } #include "debug.h" // ----------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------- Private functions ------------------------------------------------ // ----------------------------------------------------------------------------------------------------------------------- static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs); /** * compare two AP configurations * @param lhs softap_config * @param rhs softap_config * @return equal */ static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs) { if(strcmp(reinterpret_cast(lhs.ssid), reinterpret_cast(rhs.ssid)) != 0) { return false; } if(strcmp(reinterpret_cast(lhs.password), reinterpret_cast(rhs.password)) != 0) { return false; } if(lhs.channel != rhs.channel) { return false; } if(lhs.ssid_hidden != rhs.ssid_hidden) { return false; } if(lhs.max_connection != rhs.max_connection) { return false; } return true; } // ----------------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------- AP function ----------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- /** * Set up an access point * @param ssid Pointer to the SSID (max 63 char). * @param passphrase (for WPA2 min 8 char, for open use NULL) * @param channel WiFi channel number, 1 - 13. * @param ssid_hidden Network cloaking (0 = broadcast SSID, 1 = hide SSID) * @param max_connection Max simultaneous connected clients, 1 - 4. */ bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection) { if(!WiFi.enableAP(true)) { // enable AP failed DEBUG_WIFI("[AP] enableAP failed!\n"); return false; } if(!ssid || strlen(ssid) == 0 || strlen(ssid) > 31) { // fail SSID too long or missing! DEBUG_WIFI("[AP] SSID too long or missing!\n"); return false; } if(passphrase && strlen(passphrase) > 0 && (strlen(passphrase) > 63 || strlen(passphrase) < 8)) { // fail passphrase to long or short! DEBUG_WIFI("[AP] fail passphrase to long or short!\n"); return false; } bool ret = true; struct softap_config conf; strcpy(reinterpret_cast(conf.ssid), ssid); conf.channel = channel; conf.ssid_len = strlen(ssid); conf.ssid_hidden = ssid_hidden; conf.max_connection = max_connection; conf.beacon_interval = 100; if(!passphrase || strlen(passphrase) == 0) { conf.authmode = AUTH_OPEN; *conf.password = 0; } else { conf.authmode = AUTH_WPA2_PSK; strcpy(reinterpret_cast(conf.password), passphrase); } struct softap_config conf_current; wifi_softap_get_config(&conf_current); if(!softap_config_equal(conf, conf_current)) { ETS_UART_INTR_DISABLE(); if(WiFi._persistent) { ret = wifi_softap_set_config(&conf); } else { ret = wifi_softap_set_config_current(&conf); } ETS_UART_INTR_ENABLE(); if(!ret) { DEBUG_WIFI("[AP] set_config failed!\n"); return false; } } else { DEBUG_WIFI("[AP] softap config unchanged\n"); } if(wifi_softap_dhcps_status() != DHCP_STARTED) { DEBUG_WIFI("[AP] DHCP not started, starting...\n"); if(!wifi_softap_dhcps_start()) { DEBUG_WIFI("[AP] wifi_softap_dhcps_start failed!\n"); ret = false; } } // check IP config struct ip_info ip; if(wifi_get_ip_info(SOFTAP_IF, &ip)) { if(ip.ip.addr == 0x00000000) { // Invalid config DEBUG_WIFI("[AP] IP config Invalid resetting...\n"); //192.168.244.1 , 192.168.244.1 , 255.255.255.0 ret = softAPConfig(0x01F4A8C0, 0x01F4A8C0, 0x00FFFFFF); if(!ret) { DEBUG_WIFI("[AP] softAPConfig failed!\n"); ret = false; } } } else { DEBUG_WIFI("[AP] wifi_get_ip_info failed!\n"); ret = false; } return ret; } /** * Configure access point * @param local_ip access point IP * @param gateway gateway IP * @param subnet subnet mask */ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { DEBUG_WIFI("[APConfig] local_ip: %s gateway: %s subnet: %s\n", local_ip.toString().c_str(), gateway.toString().c_str(), subnet.toString().c_str()); if(!WiFi.enableAP(true)) { // enable AP failed DEBUG_WIFI("[APConfig] enableAP failed!\n"); return false; } bool ret = true; struct ip_info info; info.ip.addr = static_cast(local_ip); info.gw.addr = static_cast(gateway); info.netmask.addr = static_cast(subnet); if(!wifi_softap_dhcps_stop()) { DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n"); } if(!wifi_set_ip_info(SOFTAP_IF, &info)) { DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n"); ret = false; } struct dhcps_lease dhcp_lease; IPAddress ip = local_ip; ip[3] += 99; dhcp_lease.start_ip.addr = static_cast(ip); DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str()); ip[3] += 100; dhcp_lease.end_ip.addr = static_cast(ip); DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str()); if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) { DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n"); ret = false; } // set lease time to 720min --> 12h if(!wifi_softap_set_dhcps_lease_time(720)) { DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_lease_time failed!\n"); ret = false; } uint8 mode = 1; if(!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) { DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_offer_option failed!\n"); ret = false; } if(!wifi_softap_dhcps_start()) { DEBUG_WIFI("[APConfig] wifi_softap_dhcps_start failed!\n"); ret = false; } // check config if(wifi_get_ip_info(SOFTAP_IF, &info)) { if(info.ip.addr == 0x00000000) { DEBUG_WIFI("[APConfig] IP config Invalid?!\n"); ret = false; } else if(local_ip != info.ip.addr) { ip = info.ip.addr; DEBUG_WIFI("[APConfig] IP config not set correct?! new IP: %s\n", ip.toString().c_str()); ret = false; } } else { DEBUG_WIFI("[APConfig] wifi_get_ip_info failed!\n"); ret = false; } return ret; } /** * Disconnect from the network (close AP) * @param wifioff disable mode? * @return one value of wl_status_t enum */ bool ESP8266WiFiAPClass::softAPdisconnect(bool wifioff) { bool ret; struct softap_config conf; *conf.ssid = 0; *conf.password = 0; ETS_UART_INTR_DISABLE(); if(WiFi._persistent) { ret = wifi_softap_set_config(&conf); } else { ret = wifi_softap_set_config_current(&conf); } ETS_UART_INTR_ENABLE(); if(!ret) { DEBUG_WIFI("[APdisconnect] set_config failed!\n"); } if(wifioff) { ret = WiFi.enableAP(false); } return ret; } /** * Get the count of the Station / client that are connected to the softAP interface * @return Stations count */ uint8_t ESP8266WiFiAPClass::softAPgetStationNum() { return wifi_softap_get_station_num(); } /** * Get the softAP interface IP address. * @return IPAddress softAP IP */ IPAddress ESP8266WiFiAPClass::softAPIP() { struct ip_info ip; wifi_get_ip_info(SOFTAP_IF, &ip); return IPAddress(ip.ip.addr); } /** * Get the softAP interface MAC address. * @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH * @return pointer to uint8_t* */ uint8_t* ESP8266WiFiAPClass::softAPmacAddress(uint8_t* mac) { wifi_get_macaddr(SOFTAP_IF, mac); return mac; } /** * Get the softAP interface MAC address. * @return String mac */ String ESP8266WiFiAPClass::softAPmacAddress(void) { uint8_t mac[6]; char macStr[18] = { 0 }; wifi_get_macaddr(SOFTAP_IF, mac); sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return String(macStr); }