You've already forked TEF6686_ESP32
1330 lines
44 KiB
C++
1330 lines
44 KiB
C++
/*!
|
|
@file WiFiConnect.cpp
|
|
|
|
@mainpage WiFi Connection Manager with Captive Portal
|
|
|
|
@section intro_sec Introduction
|
|
|
|
This is the documentation for WiFiConnect for the Arduino platform <a href="https://github.com/smurf0969/WiFiConnect">https://github.com/smurf0969/WiFiConnect</a>.
|
|
Further documentation can be found in the [Wiki](https://github.com/smurf0969/WiFiConnect/wiki) or in the project examples folder on GitHub.
|
|
|
|
It is a WiFi connection manager for use with the popular ESP8266 and ESP32 chips.
|
|
|
|
It contains a captive portal to allow easy connection and changing of WiFi netwoks
|
|
via a web based interface and allows for additional user parameters.
|
|
|
|
It can also display messages via a OLED screen see WiFiConnectOLED class.
|
|
|
|

|
|
|
|
This is a heavily customised version from the origional <a href="https://github.com/tzapu/WiFiManager">WiFiManager</a>
|
|
developed by https://github.com/tzapu .
|
|
|
|
@section dependencies Dependencies
|
|
|
|
This library depends on <a href="https://github.com/esp8266/Arduino">
|
|
ESP8266 Arduino Core</a> or <a href="https://github.com/espressif/arduino-esp32">ESP32 Arduino Core</a> depending on what chip you are using being present on your system.
|
|
Please make sure you have installed the latest version before using this library.
|
|
|
|
@section arduino_libraries Arduino Libraries
|
|
|
|
- ArduinoJson 6.9.1 [https://github.com/bblanchon/ArduinoJson.git](https://github.com/bblanchon/ArduinoJson.git) or [https://blog.benoitblanchon.fr](https://blog.benoitblanchon.fr)
|
|
- ESP8266 OLED SSD1306 ([Custom version](https://github.com/smurf0969/esp8266-oled-ssd1306/tree/Allow-overriding-default-font))
|
|
|
|
@section author Author
|
|
|
|
Written by Stuart Blair.
|
|
|
|
@section license License
|
|
|
|
GNU General Public License v3.0 licence, all text here must be included in any redistribution and you should receive a copy of the license file.
|
|
|
|
*/
|
|
#include "WiFiConnect.h"
|
|
|
|
WiFiConnect::WiFiConnect() {
|
|
//_params = (WiFiConnectParam**)malloc(WiFiConnect_MAX_PARAMS * sizeof(WiFiConnectParam*));
|
|
_apName[0]='\0';
|
|
_apPassword[0]='\0';
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayConnecting(int attempt, int totalAttempts) {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayConnected() {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayAP() {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayParams() {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayManualReset() {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayTurnOFF(int ms) {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayLoop() {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief This function gets overridden by WiFiConnectOLED,
|
|
please view its documentation.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::displayON() {
|
|
/*dummy*/
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the timeout for when the Access Point is idle.
|
|
@param mins
|
|
The number of minutes to before exiting an idle access point.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setAPModeTimeoutMins(int mins) {
|
|
if (mins > 0) {
|
|
_apTimeoutMins = mins;
|
|
}
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the name for the Access Point, setting a default based on
|
|
the ESP chip id if needed.
|
|
@param apName
|
|
The new name for the access point.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setAPName(const char *apName) {
|
|
if(strlen(apName)>32){return;}
|
|
if (strlen(apName)==0||(apName == NULL)) {
|
|
String ssid = "ESP_" + String(ESP_getChipId());
|
|
//_apName = ssid.c_str();
|
|
strcpy(_apName,ssid.c_str());
|
|
|
|
} else if (apName != NULL && strlen(apName)>0) {
|
|
// _apName = apName;
|
|
strcpy(_apName,apName);
|
|
}
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Gets the Access Point name or the default based on the
|
|
ESP chip id if not already set.
|
|
@return The name to be given to the access point.
|
|
*/
|
|
/**************************************************************************/
|
|
const char* WiFiConnect::getAPName() {
|
|
if ((_apName == NULL ) || strlen(_apName)==0) {
|
|
setAPName(NULL);
|
|
}
|
|
return _apName;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Adds a custom parameter to be displayed in the accesspoint and
|
|
parameters portals.
|
|
Custom parameters can be used to save information that you do
|
|
not want to hard code i.e. IP address, Port number that can be
|
|
saved to the file system.
|
|
@param p
|
|
The custom parameter to add.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::addParameter(WiFiConnectParam *p) {
|
|
_params[_paramsCount] = p;
|
|
_paramsCount++;
|
|
DEBUG_WC("Adding parameter");
|
|
DEBUG_WC(p->getID());
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Starts the custom Parameters Portal using default
|
|
access point name and password.
|
|
@return Returns wether WiFi is connected to a network
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::startParamsPortal() {
|
|
return startParamsPortal(AP_NONE, _apName, _apPassword);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Starts the custom Parameters Portal using default
|
|
access point name and password, but allows for specifying how
|
|
to continue.
|
|
@param apcontinue
|
|
What should the access point do if there is still no connection.
|
|
AP_NONE - continue running code,
|
|
AP_LOOP - stay in an infinate loop,
|
|
AP_RESET - Restart the ESP
|
|
AP_WAIT - Keep AP alive waiting for input
|
|
@return Returns wether WiFi is connected to a network if
|
|
AP_NONE is passed as a parameter
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::startParamsPortal(AP_Continue apcontinue) {
|
|
return startParamsPortal(apcontinue, _apName, _apPassword);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Starts the custom Parameters Portal.
|
|
@param apcontinue
|
|
What should the access point do if there is still no connection.
|
|
AP_NONE - continue running code,
|
|
AP_LOOP - stay in an infinate loop,
|
|
AP_RESET - Restart the ESP
|
|
AP_WAIT - Keep AP alive waiting for input
|
|
@param apName
|
|
The Name to use for the access point
|
|
@param apPassword
|
|
The optional Password to protect the access point
|
|
@return Returns wether WiFi is connected to a network if
|
|
AP_NONE is passed as a parameter
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::startParamsPortal(AP_Continue apcontinue, const char *apName, const char *apPassword) {
|
|
|
|
// Wrapper
|
|
return startConfigurationPortal(apcontinue, apName, apPassword, true);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Starts the Access Portal for setting SSID and Password for
|
|
connecting to a network and any custom user parameters.
|
|
Uses the default access point name and password.
|
|
@return Returns wether WiFi is connected to a network if
|
|
AP_NONE is passed as a parameter
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::startConfigurationPortal() {
|
|
return startConfigurationPortal(AP_NONE, _apName, _apPassword);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Starts the Access Portal for setting SSID and Password for
|
|
connecting to a network and any custom user parameters.
|
|
Uses the default access point name and password, but
|
|
allows for specifying how to continue if network not connected.
|
|
@param apcontinue
|
|
What should the access point do if there is still no connection.
|
|
AP_NONE - continue running code,
|
|
AP_LOOP - stay in an infinate loop,
|
|
AP_RESET - Restart the ESP
|
|
AP_WAIT - Keep AP alive waiting for input
|
|
@return Returns wether WiFi is connected to a network if
|
|
AP_NONE is passed as a parameter
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::startConfigurationPortal(AP_Continue apcontinue) {
|
|
return startConfigurationPortal(apcontinue, _apName, _apPassword);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Starts the Access Portal for setting SSID and Password for
|
|
connecting to a network and any custom user parameters.
|
|
@param apcontinue
|
|
What should the access point do if there is still no connection.
|
|
AP_NONE - continue running code,
|
|
AP_LOOP - stay in an infinate loop,
|
|
AP_RESET - Restart the ESP, handy for sensors if you network
|
|
goes down, do they keep trying to connect.
|
|
AP_WAIT - Keep AP alive waiting for input
|
|
@param apName
|
|
The Name to use for the access point
|
|
@param apPassword
|
|
The optional Password to protect the access point
|
|
@return Returns wether WiFi is connected to a network if
|
|
AP_NONE is passed as a parameter
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::startConfigurationPortal(AP_Continue apcontinue, const char *apName, const char *apPassword, bool paramsMode) {
|
|
|
|
if (paramsMode) {
|
|
DEBUG_WC(F("WiFi AP STA - Parameters Portal"));
|
|
} else {
|
|
DEBUG_WC(F("WiFi AP STA - Configuration Portal"));
|
|
}
|
|
_lastAPPage = millis();
|
|
|
|
delay(50);
|
|
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
if (paramsMode) {
|
|
// Can't show the parameters portal if not connected to a WiFi network.
|
|
startConfigurationPortal(AP_WAIT, apName, apPassword, false);
|
|
} else {
|
|
DEBUG_WC("startConfigurationPortal(): WiFi.mode(WIFI_AP)");
|
|
WiFi.mode(WIFI_AP);
|
|
}
|
|
} else {
|
|
WiFi.mode(WIFI_AP_STA); // start an access point on the same channel we're already connected to.
|
|
}
|
|
dnsServer.reset(new DNSServer());
|
|
#ifdef ESP8266
|
|
server.reset(new ESP8266WebServer(80));
|
|
#else
|
|
server.reset(new WebServer(80));
|
|
#endif
|
|
setAPName(apName);
|
|
DEBUG_WC(_apName);
|
|
|
|
if (strlen(apPassword)>0){
|
|
if (strlen(apPassword) < 8 || strlen(apPassword) > 63) {
|
|
// fail passphrase to short or long!
|
|
DEBUG_WC(F("Invalid AccessPoint password. Ignoring"));
|
|
apPassword = NULL;
|
|
}
|
|
//_apPassword = apPassword;
|
|
strcpy(_apPassword,apPassword);
|
|
DEBUG_WC(_apPassword);
|
|
}
|
|
|
|
//optional soft ip config
|
|
if (_ap_static_ip) {
|
|
DEBUG_WC(F("Custom AP IP/GW/Subnet"));
|
|
WiFi.softAPConfig(_ap_static_ip, _ap_static_gw, _ap_static_sn);
|
|
}
|
|
|
|
//if (_apPassword != NULL && _apPassword!="") {
|
|
if(strlen(apPassword)>0){
|
|
WiFi.softAP(_apName, _apPassword);//password option
|
|
} else {
|
|
WiFi.softAP(_apName);
|
|
DEBUG_WC("startConfigurationPortal(): WiFi.softAP(_apName)");
|
|
}
|
|
|
|
delay(500); // Without delay I've seen the IP address blank
|
|
DEBUG_WC(F("AP IP address: "));
|
|
DEBUG_WC(WiFi.softAPIP());
|
|
|
|
// Show on OLED depending on the mode
|
|
if (!paramsMode) { displayAP(); } else { displayParams(); }
|
|
|
|
/* Setup the DNS server redirecting all the domains to the apIP */
|
|
dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
|
|
dnsServer->start(DNS_PORT, "*", WiFi.softAPIP());
|
|
|
|
if (paramsMode)
|
|
{
|
|
|
|
server->on("/", std::bind(&WiFiConnect::handleParamRoot, this));
|
|
server->on("/param", std::bind(&WiFiConnect::handleParams, this));
|
|
server->on("/params", std::bind(&WiFiConnect::handleParams, this));
|
|
server->on("/wifisave", std::bind(&WiFiConnect::handleWifiSave, this));
|
|
server->on("/i", std::bind(&WiFiConnect::handleInfo, this));
|
|
//server->on("/r", std::bind(&WiFiConnect::handleReset, this)); // doesn't work - causes boot loop
|
|
//server->on("/generate_204", std::bind(&WiFiConnect::handle204, this)); //Android/Chrome OS captive portal check.
|
|
server->on("/fwlink", std::bind(&WiFiConnect::handleParamRoot, this)); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
|
|
server->on("/hotspot_detect.html", std::bind(&WiFiConnect::handleParamRoot, this));
|
|
|
|
} else { // Config portal mode
|
|
|
|
/* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
|
|
server->on("/", std::bind(&WiFiConnect::handleRoot, this));
|
|
server->on("/wifi", std::bind(&WiFiConnect::handleWifi, this, true)); // Auto Scan of APs
|
|
server->on("/0wifi", std::bind(&WiFiConnect::handleWifi, this, false)); // Manual entry form only
|
|
server->on("/wifisave", std::bind(&WiFiConnect::handleWifiSave, this));
|
|
server->on("/i", std::bind(&WiFiConnect::handleInfo, this)); // Not of interest - commented out in static HTML
|
|
server->on("/r", std::bind(&WiFiConnect::handleReset, this));
|
|
//server->on("/generate_204", std::bind(&WiFiConnect::handle204, this)); //Android/Chrome OS captive portal check.
|
|
server->on("/fwlink", std::bind(&WiFiConnect::handleRoot, this)); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
|
|
server->on("/hotspot_detect.html", std::bind(&WiFiConnect::handleRoot, this));
|
|
|
|
} // config portal
|
|
|
|
server->onNotFound (std::bind(&WiFiConnect::handleNotFound, this));
|
|
server->begin(); // Web server start
|
|
DEBUG_WC(F("HTTP server started"));
|
|
|
|
//notify we entered AP mode
|
|
if ( _apcallback != NULL) {
|
|
_apcallback(this);
|
|
}
|
|
|
|
if (apcontinue == AP_WAIT)
|
|
DEBUG_WC(F("AP to stay alive indefinitely waiting for configuration."));
|
|
|
|
|
|
_lastAPPage = millis();
|
|
_readyToConnect = false;
|
|
while (true) {
|
|
if (apcontinue != AP_WAIT) {
|
|
if (millis() - (unsigned long int)_lastAPPage >= ( (unsigned int)_apTimeoutMins * 60 * 1000)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
dnsServer->processNextRequest();
|
|
server->handleClient();
|
|
if (_readyToConnect) {
|
|
_readyToConnect = false;
|
|
|
|
DEBUG_WC(F("startConfigurationPortal(): Calling: autoConnect(_ssid.c_str(), _password.c_str(), WIFI_AP_STA)"));
|
|
|
|
if (autoConnect(_ssid.c_str(), _password.c_str(), WIFI_AP_STA)) {
|
|
|
|
DEBUG_WC(F("Connection was a success, so changing to WIFI_STA mode only."));
|
|
WiFi.mode(WIFI_STA);
|
|
delay(500);
|
|
//WiFi.reconnect();
|
|
//delay(500);
|
|
if (_savecallback != NULL) {
|
|
_savecallback();
|
|
}
|
|
break; // we connected!
|
|
}
|
|
else
|
|
{
|
|
DEBUG_WC(F("Connection was a failure. We keep waiting."));
|
|
}
|
|
} // ready to connect
|
|
|
|
yield();
|
|
}
|
|
|
|
//teardown??
|
|
DEBUG_WC(F("Exiting AP (or AP Params) Mode"));
|
|
server->close();
|
|
server.reset();
|
|
|
|
dnsServer.reset();
|
|
boolean con = (WiFi.status() == WL_CONNECTED);
|
|
if (!con) {
|
|
switch (apcontinue) {
|
|
case AP_WAIT:
|
|
break;
|
|
case AP_NONE:
|
|
DEBUG_WC(F("No AP continue action"));
|
|
break;
|
|
case AP_LOOP:
|
|
DEBUG_WC(F("AP to turn off and stay in loop lockup not being accessible."));
|
|
displayManualReset();
|
|
displayTurnOFF(5 * 60 * 100); //5mins
|
|
WiFi.mode(WIFI_OFF);
|
|
while (true) {
|
|
displayLoop();
|
|
delay(1000);
|
|
yield();
|
|
}
|
|
|
|
break;
|
|
case AP_RESTART:
|
|
case AP_RESET:
|
|
displayManualReset();
|
|
DEBUG_WC(F("AP restart chip"));
|
|
delay(1000);
|
|
#if defined(ESP8266)
|
|
ESP.reset();
|
|
#else
|
|
ESP.restart();
|
|
#endif
|
|
delay(2000);
|
|
}
|
|
WiFi.mode(WIFI_STA);
|
|
}
|
|
return con;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Tries to connect to the last connected WiFi network.
|
|
@return Returns wether WiFi is connected
|
|
|
|
@section example_startConfigurationPortal Example
|
|
|
|
The return value can be used to automatically start the access point
|
|
so you may change networks if required.
|
|
|
|
@code
|
|
if(!wificonnect.autoConnect()){
|
|
//Start the access point
|
|
wificonnect.startConfigurationPortal();
|
|
}
|
|
@endcode
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::autoConnect() {
|
|
return autoConnect(NULL, NULL, WIFI_STA);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Tries to connect to the specified WiFi network.
|
|
@param ssidName
|
|
The SSID of the netqork you want to connect to.
|
|
@param ssidPassword
|
|
The password for a secure network.
|
|
@param WiFiMode
|
|
The WiFi mode
|
|
@return Returns wether WiFi is connected
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::autoConnect(char const *ssidName, char const *ssidPassword, WiFiMode_t acWiFiMode) {
|
|
/*
|
|
#ifdef ESP32
|
|
WiFi.persistent(false); // disable persistent for esp32 after esp_wifi_start or else saves wont work (from WiFiManager)
|
|
#endif
|
|
*/
|
|
|
|
DEBUG_WC(F("Auto Connect"));
|
|
WiFi.mode(acWiFiMode);
|
|
DEBUG_WC("autoConnect():WiFi.mode(acWiFiMode)");
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
DEBUG_WC(F("Already Connected"));
|
|
DEBUG_WC(WiFi.localIP());
|
|
return true;
|
|
}
|
|
if (_sta_static_ip) {
|
|
DEBUG_WC(F("Custom STA IP/GW/Subnet"));
|
|
WiFi.config(_sta_static_ip, _sta_static_gw, _sta_static_sn);
|
|
DEBUG_WC(WiFi.localIP());
|
|
}
|
|
|
|
//fix for auto connect racing issue
|
|
/*
|
|
if (WiFi.status() == WL_CONNECTED && (WiFi.SSID() == String(ssidName))) {
|
|
DEBUG_WC(F("Already connected. Bailing out."));
|
|
DEBUG_WC(WiFi.localIP());
|
|
return true;
|
|
//return WL_CONNECTED;
|
|
}
|
|
*/
|
|
|
|
int c = 0;
|
|
while (c < _retryAttempts) {
|
|
displayConnecting(c + 1, _retryAttempts);
|
|
long ms = millis();
|
|
if (ssidName == NULL || strlen(ssidName)==0) {
|
|
|
|
#ifdef ESP8266
|
|
if (WiFi.SSID() == "")
|
|
{
|
|
DEBUG_WC(F("No ESP8266 WiFi SSID configuration stored. Bailing."));
|
|
return false;
|
|
}
|
|
DEBUG_WC(F("Stored SSID:")); DEBUG_WC(WiFi.SSID());
|
|
#endif
|
|
|
|
#ifdef ESP32
|
|
// WiFi.SSID() Always returns null on ESP32.... Arduino framework bug?
|
|
// So use lower-level IDF function to pull persistent configuration.
|
|
wifi_config_t conf;
|
|
esp_wifi_get_config(WIFI_IF_STA, &conf);
|
|
|
|
String stored_ssid = String(reinterpret_cast<const char*>(conf.sta.ssid));
|
|
if (stored_ssid == "")
|
|
{
|
|
DEBUG_WC(F("No ESP32 WiFi SSID configuration stored. Bailing."));
|
|
return false;
|
|
}
|
|
|
|
DEBUG_WC(F("Stored SSID:")); DEBUG_WC(stored_ssid);
|
|
#endif
|
|
|
|
|
|
WiFi.begin(); // persistence is on by default, so if this WiFi connection should happen automatically
|
|
DEBUG_WC("autoConnect(): WiFi.begin()");
|
|
|
|
/*
|
|
#ifdef ESP32
|
|
//https://forum.arduino.cc/index.php?topic=652513.0
|
|
int wifi_retry = 0; // COUNTER SOLVES ESP32-BUG WITH CERTAIN ROUTERS: CONNECTION ONLY ESTABLISHED EVERY SECOND TIME
|
|
|
|
while (WiFi.waitForConnectResult() != WL_CONNECTED && wifi_retry < 3) {
|
|
DEBUG_WC("WLAN Not yet connected on ESP32...retrying");
|
|
WiFi.begin();
|
|
delay(250);
|
|
wifi_retry++;
|
|
}
|
|
|
|
#endif
|
|
*/
|
|
|
|
} else {
|
|
DEBUG_WC(F("Connecting with SSID & Password"));
|
|
DEBUG_WC(ssidName);
|
|
DEBUG_WC(ssidPassword);
|
|
WiFi.begin(ssidName, ssidPassword);
|
|
DEBUG_WC("autoConnect(): WiFi.begin(ssidName, ssidPassword)");
|
|
}
|
|
|
|
|
|
while (millis() - (unsigned long int)ms < ( (unsigned int)_connectionTimeoutSecs * 1000)) {
|
|
int ws = WiFi.status();
|
|
if (ws == WL_CONNECTED) {
|
|
DEBUG_WC(F("WIFI_CONNECTED"));
|
|
delay(500);//wait for ip to refresh
|
|
DEBUG_WC(WiFi.localIP());
|
|
displayConnected();
|
|
return true;
|
|
} else if (ws == WL_CONNECT_FAILED) {
|
|
DEBUG_WC(F("WIFI_CONNECT_FAILED"));
|
|
delay(500);
|
|
//return false;
|
|
} else {
|
|
delay(200);
|
|
yield();
|
|
}
|
|
}
|
|
DEBUG_WC(statusToString(WiFi.status()));
|
|
c++;
|
|
} // attemps
|
|
DEBUG_WC(statusToString(WiFi.status()));
|
|
return false;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets how many times we should try to connect to the WiFi network.
|
|
@param attempts
|
|
How may attampts.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setRetryAttempts(int attempts) {
|
|
if (attempts >= 1) {
|
|
_retryAttempts = attempts;
|
|
}
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets how long to wait for the connection before failing.
|
|
@param timeout
|
|
How may seconds to wait for the connection to be made.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setConnectionTimeoutSecs(int timeout) {
|
|
if (timeout >= 1) {
|
|
_connectionTimeoutSecs = timeout;
|
|
}
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief A helper to clear the settings for the last connected network.
|
|
Remember to comment out or remove and re-upload your code
|
|
otherwise chip will constantly restart.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::resetSettings() {
|
|
DEBUG_WC(F("Clearing Settings for:"));
|
|
DEBUG_WC(WiFi.SSID());
|
|
#if defined(ESP8266)
|
|
WiFi.disconnect(true);
|
|
delay(1000);
|
|
ESP.reset();
|
|
#else
|
|
WiFi.disconnect(true);//doesnt seem to work
|
|
esp_wifi_restore();//doesnt seem to work
|
|
WiFi.begin("0", "0"); //HACK
|
|
delay(1000);
|
|
ESP.restart();
|
|
#endif
|
|
delay(2000);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief A helper function to return the string version of a
|
|
wifi network state.
|
|
@param state
|
|
The state that we want the string representation of.
|
|
@return WiFi state as a string.
|
|
*/
|
|
/**************************************************************************/
|
|
const char* WiFiConnect::statusToString(int state) {
|
|
switch (state) {
|
|
case WL_CONNECTED:
|
|
return "WL_CONNECTED";
|
|
case WL_CONNECT_FAILED:
|
|
return "WL_CONNECT_FAILED";
|
|
case WL_CONNECTION_LOST:
|
|
return "WL_CONNECTION_LOST";
|
|
case WL_DISCONNECTED:
|
|
return "WL_DISCONNECTED";
|
|
case WL_SCAN_COMPLETED:
|
|
return "WL_SCAN_COMPLETED";
|
|
case WL_NO_SSID_AVAIL:
|
|
return "WL_NO_SSID_AVAIL";
|
|
case WL_IDLE_STATUS:
|
|
return "WL_IDLE_STATUS";
|
|
case WL_NO_SHIELD:
|
|
return "WL_NO_SHIELD";
|
|
default:
|
|
return "UNKNOWN CODE";
|
|
}
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Outputs debug messages
|
|
@param text
|
|
The text to be outputted
|
|
*/
|
|
/**************************************************************************/
|
|
template <typename Generic>
|
|
void WiFiConnect::DEBUG_WC(Generic text) {
|
|
if (_debug) {
|
|
Serial.print("*WC: ");
|
|
Serial.println(text);
|
|
}
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the web request for root in the Parameters Portal and
|
|
sends back the html menu
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleParamRoot() {
|
|
if (captivePortal()) { // If captive portal redirect instead of displaying the page.
|
|
return;
|
|
}
|
|
_lastAPPage = millis();
|
|
DEBUG_WC("Sending Root");
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Options");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
page += String(F("<h1>"));
|
|
page += _apName;
|
|
page += String(F("</h1>"));
|
|
// page += String(F("<h3>WiFiConnect</h3>"));
|
|
page += FPSTR(AP_HTTP_PORTAL_PARAM_OPTIONS);
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the web request for displaying custom parameters
|
|
in the Parameters Portal and sends back the html
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleParams() {
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Sending Params"));
|
|
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Config Params");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
page += FPSTR(AP_HTTP_FORM_PARAM_START);
|
|
char parLength[4];
|
|
// add the extra parameters to the form
|
|
for (int i = 0; i < _paramsCount; i++) {
|
|
if (_params[i] == NULL) {
|
|
break;
|
|
}
|
|
|
|
String pitem = FPSTR(AP_HTTP_FORM_PARAM);
|
|
if (_params[i]->getID() != NULL) {
|
|
pitem.replace("{i}", _params[i]->getID());
|
|
pitem.replace("{n}", _params[i]->getID());
|
|
pitem.replace("{p}", _params[i]->getPlaceholder());
|
|
snprintf(parLength, 4, "%d", _params[i]->getValueLength());
|
|
pitem.replace("{l}", parLength);
|
|
pitem.replace("{v}", _params[i]->getValue());
|
|
pitem.replace("{c}", _params[i]->getCustomHTML());
|
|
} else {
|
|
pitem = _params[i]->getCustomHTML();
|
|
}
|
|
|
|
page += pitem;
|
|
}
|
|
if (_params[0] != NULL) {
|
|
page += "<br/>";
|
|
}
|
|
|
|
page += FPSTR(AP_HTTP_FORM_END);
|
|
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the web request for displaying the menu in the
|
|
Access Point portal.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleRoot() {
|
|
if (captivePortal()) { // If captive portal redirect instead of displaying the page.
|
|
return;
|
|
}
|
|
_lastAPPage = millis();
|
|
DEBUG_WC("Sending Root");
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Options");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
page += String(F("<h1>"));
|
|
page += _apName;
|
|
page += String(F("</h1>"));
|
|
//page += String(F("<h3>WiFiConnect</h3>"));
|
|
page += FPSTR(AP_HTTP_PORTAL_OPTIONS);
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
|
|
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the web request for entering the SSID and Password of
|
|
the network you want to connect too.
|
|
Optionally scans and shows available networks.
|
|
@param scan
|
|
Whether to scan for networks or not.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleWifi(boolean scan) {
|
|
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Sending WiFi"));
|
|
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Select WiFi");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
|
|
if (scan) {
|
|
int n = WiFi.scanNetworks();
|
|
DEBUG_WC(F("Scan done"));
|
|
if (n == 0) {
|
|
DEBUG_WC(F("No networks found"));
|
|
page += F("No networks found. Refresh to scan again.");
|
|
} else {
|
|
|
|
//sort networks
|
|
int indices[n];
|
|
for (int i = 0; i < n; i++) {
|
|
indices[i] = i;
|
|
}
|
|
|
|
// RSSI SORT
|
|
|
|
// old sort
|
|
for (int i = 0; i < n; i++) {
|
|
for (int j = i + 1; j < n; j++) {
|
|
if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) {
|
|
std::swap(indices[i], indices[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*std::sort(indices, indices + n, [](const int & a, const int & b) -> bool
|
|
{
|
|
return WiFi.RSSI(a) > WiFi.RSSI(b);
|
|
});*/
|
|
|
|
// remove duplicates ( must be RSSI sorted )
|
|
if (_removeDuplicateAPs) {
|
|
String cssid;
|
|
for (int i = 0; i < n; i++) {
|
|
if (indices[i] == -1) continue;
|
|
cssid = WiFi.SSID(indices[i]);
|
|
for (int j = i + 1; j < n; j++) {
|
|
if (cssid == WiFi.SSID(indices[j])) {
|
|
DEBUG_WC("DUP AP: " + WiFi.SSID(indices[j]));
|
|
indices[j] = -1; // set dup aps to index -1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//display networks in page
|
|
for (int i = 0; i < n; i++) {
|
|
if (indices[i] == -1) continue; // skip dups
|
|
DEBUG_WC(WiFi.SSID(indices[i]));
|
|
DEBUG_WC(WiFi.RSSI(indices[i]));
|
|
int quality = getRSSIasQuality(WiFi.RSSI(indices[i]));
|
|
|
|
if (_minimumQuality == -1 || _minimumQuality < quality) {
|
|
String item = FPSTR(AP_HTTP_ITEM);
|
|
String rssiQ;
|
|
rssiQ += quality;
|
|
item.replace("{v}", WiFi.SSID(indices[i]));
|
|
item.replace("{r}", rssiQ);
|
|
#if defined(ESP8266)
|
|
if (WiFi.encryptionType(indices[i]) != ENC_TYPE_NONE) {
|
|
#else
|
|
if (WiFi.encryptionType(indices[i]) != WIFI_AUTH_OPEN) {
|
|
#endif
|
|
item.replace("{i}", "l");
|
|
} else {
|
|
item.replace("{i}", "");
|
|
}
|
|
//DEBUG_WM(item);
|
|
page += item;
|
|
delay(0);
|
|
} else {
|
|
DEBUG_WC(F("Skipping due to quality"));
|
|
}
|
|
|
|
}
|
|
page += "<br/>";
|
|
}
|
|
}
|
|
|
|
page += FPSTR(AP_HTTP_FORM_START);
|
|
char parLength[4];
|
|
// add the extra parameters to the form
|
|
for (int i = 0; i < _paramsCount; i++) {
|
|
if (_params[i] == NULL) {
|
|
break;
|
|
}
|
|
|
|
String pitem = FPSTR(AP_HTTP_FORM_PARAM);
|
|
if (_params[i]->getID() != NULL) {
|
|
pitem.replace("{i}", _params[i]->getID());
|
|
pitem.replace("{n}", _params[i]->getID());
|
|
pitem.replace("{p}", _params[i]->getPlaceholder());
|
|
snprintf(parLength, 4, "%d", _params[i]->getValueLength());
|
|
pitem.replace("{l}", parLength);
|
|
pitem.replace("{v}", _params[i]->getValue());
|
|
pitem.replace("{c}", _params[i]->getCustomHTML());
|
|
} else {
|
|
pitem = _params[i]->getCustomHTML();
|
|
}
|
|
|
|
page += pitem;
|
|
}
|
|
if (_params[0] != NULL) {
|
|
page += "<br/>";
|
|
}
|
|
|
|
if (_sta_static_ip) {
|
|
|
|
String item = FPSTR(AP_HTTP_FORM_PARAM);
|
|
item.replace("{i}", "ip");
|
|
item.replace("{n}", "ip");
|
|
item.replace("{p}", "Static IP");
|
|
item.replace("{l}", "15");
|
|
item.replace("{v}", _sta_static_ip.toString());
|
|
|
|
page += item;
|
|
|
|
item = FPSTR(AP_HTTP_FORM_PARAM);
|
|
item.replace("{i}", "gw");
|
|
item.replace("{n}", "gw");
|
|
item.replace("{p}", "Static Gateway");
|
|
item.replace("{l}", "15");
|
|
item.replace("{v}", _sta_static_gw.toString());
|
|
|
|
page += item;
|
|
|
|
item = FPSTR(AP_HTTP_FORM_PARAM);
|
|
item.replace("{i}", "sn");
|
|
item.replace("{n}", "sn");
|
|
item.replace("{p}", "Subnet");
|
|
item.replace("{l}", "15");
|
|
item.replace("{v}", _sta_static_sn.toString());
|
|
|
|
page += item;
|
|
|
|
page += "<br/>";
|
|
}
|
|
|
|
page += FPSTR(AP_HTTP_FORM_END);
|
|
page += FPSTR(AP_HTTP_SCAN_LINK);
|
|
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
}
|
|
void WiFiConnect::handleWifiSave() {
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Sending WiFi Save"));
|
|
//SAVE/connect here
|
|
if (_debug) {
|
|
Serial.println(F("*WC Form Args"));
|
|
for (int x = 0; x < server->args(); x++) {
|
|
Serial.print(F("*WC "));
|
|
Serial.print(server->argName(x));
|
|
Serial.print(F("="));
|
|
Serial.println(server->arg(x));
|
|
}
|
|
}
|
|
_ssid = server->arg("s").c_str();
|
|
_ssid.trim();
|
|
DEBUG_WC(_ssid);
|
|
_password = server->arg("p").c_str();
|
|
_password.trim();
|
|
DEBUG_WC(_password);
|
|
//parameters
|
|
for (int i = 0; i < _paramsCount; i++) {
|
|
if (_params[i] == NULL) {
|
|
break;
|
|
}
|
|
//read parameter
|
|
String value = server->arg(_params[i]->getID()).c_str();
|
|
//store it in array
|
|
value.toCharArray(_params[i]->_value, _params[i]->_length);
|
|
DEBUG_WC(F("Parameter"));
|
|
DEBUG_WC(_params[i]->getID());
|
|
DEBUG_WC(value);
|
|
}
|
|
|
|
if (server->arg("ip") != "") {
|
|
DEBUG_WC(F("static ip"));
|
|
DEBUG_WC(server->arg("ip"));
|
|
//_sta_static_ip.fromString(server->arg("ip"));
|
|
String ip = server->arg("ip");
|
|
optionalIPFromString(&_sta_static_ip, ip.c_str());
|
|
}
|
|
if (server->arg("gw") != "") {
|
|
DEBUG_WC(F("static gateway"));
|
|
DEBUG_WC(server->arg("gw"));
|
|
String gw = server->arg("gw");
|
|
optionalIPFromString(&_sta_static_gw, gw.c_str());
|
|
}
|
|
if (server->arg("sn") != "") {
|
|
DEBUG_WC(F("static netmask"));
|
|
DEBUG_WC(server->arg("sn"));
|
|
String sn = server->arg("sn");
|
|
optionalIPFromString(&_sta_static_sn, sn.c_str());
|
|
}
|
|
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Credentials Saved");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
page += FPSTR(AP_HTTP_SAVED);
|
|
page.replace("{ap}", _ssid);
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
_readyToConnect = true;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the web request and shows basic information about the chip.
|
|
TODO: ESP32 information still needs completing.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleInfo() {
|
|
_lastAPPage = millis(); DEBUG_WC(F("Sending Info"));
|
|
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Info");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
page += F("<dl>");
|
|
page += F("<dt>Chip ID</dt><dd>");
|
|
page += ESP_getChipId();
|
|
page += F("</dd>");
|
|
page += F("<dt>Flash Chip ID</dt><dd>");
|
|
#if defined(ESP8266)
|
|
page += ESP.getFlashChipId();
|
|
#else
|
|
// TODO
|
|
page += F("TODO");
|
|
#endif
|
|
page += F("</dd>");
|
|
page += F("<dt>IDE Flash Size</dt><dd>");
|
|
page += ESP.getFlashChipSize();
|
|
page += F(" bytes</dd>");
|
|
page += F("<dt>Real Flash Size</dt><dd>");
|
|
#if defined(ESP8266)
|
|
page += ESP.getFlashChipRealSize();
|
|
#else
|
|
// TODO
|
|
page += F("TODO");
|
|
#endif
|
|
page += F(" bytes</dd>");
|
|
page += F("<dt>Soft AP IP</dt><dd>");
|
|
page += WiFi.softAPIP().toString();
|
|
page += F("</dd>");
|
|
page += F("<dt>Soft AP MAC</dt><dd>");
|
|
page += WiFi.softAPmacAddress();
|
|
page += F("</dd>");
|
|
page += F("<dt>Station MAC</dt><dd>");
|
|
page += WiFi.macAddress();
|
|
page += F("</dd>");
|
|
page += F("</dl>");
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
|
|
DEBUG_WC(F("Sent info page"));
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the reset web request and and restarts the chip.
|
|
Does not clear settings.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleReset() {
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Sending Reset"));
|
|
|
|
String page = FPSTR(AP_HTTP_HEAD);
|
|
page.replace("{v}", "Info");
|
|
page += FPSTR(AP_HTTP_SCRIPT);
|
|
page += FPSTR(AP_HTTP_STYLE);
|
|
page += FPSTR(AP_HTTP_HEAD_END);
|
|
page += F("Module will reset in a few seconds.");
|
|
page += FPSTR(AP_HTTP_END);
|
|
|
|
server->sendHeader("Content-Length", String(page.length()));
|
|
server->send(200, "text/html", page);
|
|
|
|
DEBUG_WC(F("Sent reset page"));
|
|
delay(5000);
|
|
#if defined(ESP8266)
|
|
ESP.reset(); // causes boot loop
|
|
#else
|
|
ESP.restart();
|
|
#endif
|
|
delay(2000);
|
|
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles the 204 web request from Android devices
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handle204() {
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Sending 204"));
|
|
handleRoot();
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Handles any web requests that are not found.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::handleNotFound() {
|
|
if (captivePortal()) { // If captive portal redirect instead of displaying the error page.
|
|
DEBUG_WC(F("Webserver called handleNotFound();"));
|
|
return;
|
|
}
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Sending Not Found"));
|
|
String message = "File Not Found\n\n";
|
|
message += "URI: ";
|
|
message += server->uri();
|
|
message += "\nMethod: ";
|
|
message += ( server->method() == HTTP_GET ) ? "GET" : "POST";
|
|
message += "\nArguments: ";
|
|
message += server->args();
|
|
message += "\n";
|
|
|
|
for ( uint8_t i = 0; i < server->args(); i++ ) {
|
|
message += " " + server->argName ( i ) + ": " + server->arg ( i ) + "\n";
|
|
}
|
|
server->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
server->sendHeader("Pragma", "no-cache");
|
|
server->sendHeader("Expires", "-1");
|
|
server->sendHeader("Content-Length", String(message.length()));
|
|
server->send ( 404, "text/plain", message );
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Redirect to captive portal if we get a request for another domain.
|
|
Return true in that case so the page handler do not try to
|
|
handle the request again.
|
|
@return True if we have redirected to our portal, else false and contimue
|
|
to handle request
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::captivePortal() {
|
|
DEBUG_WC(server->hostHeader());
|
|
|
|
if (!isIp(server->hostHeader()) ) {
|
|
_lastAPPage = millis();
|
|
DEBUG_WC(F("Request redirected to captive portal"));
|
|
String msg = "redirect\n";
|
|
server->sendHeader("Location", String("http://") + toStringIp(server->client().localIP()), true);
|
|
server->sendHeader("Content-Length", String(msg.length()));
|
|
server->send ( 302, "text/plain", msg); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
|
//server->client().stop(); // Stop is needed because we sent no content length
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the function to be called when we enter Access Point
|
|
for configuration.
|
|
Gets passed a the WiFiConnect for additional usage within function.
|
|
@param func
|
|
The function to be called.
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setAPCallback( void (*func)(WiFiConnect* myWiFiConnect) ) {
|
|
_apcallback = func;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the function to be called when we need to save the
|
|
custom parameters/configuration.
|
|
@param func
|
|
The function to be called.
|
|
This function should be short running and ideally just set.
|
|
a flag for processing else where.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setSaveConfigCallback( void (*func)() ) {
|
|
_savecallback = func;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Function to convert RSSI into a usable range 0-100 so we can
|
|
use it to exclude poor networks.
|
|
@param RSSI
|
|
The quality/signal strength of the WiFi network.
|
|
@return Value in the range of 0-100 to network indicate quality.
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
int WiFiConnect::getRSSIasQuality(int RSSI) {
|
|
int quality = 0;
|
|
|
|
if (RSSI <= -100) {
|
|
quality = 0;
|
|
} else if (RSSI >= -50) {
|
|
quality = 100;
|
|
} else {
|
|
quality = 2 * (RSSI + 100);
|
|
}
|
|
return quality;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Function to check if a given string is an IP Address.
|
|
@param str
|
|
The string to process.
|
|
@return True if inputted string is an IP Address.
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
boolean WiFiConnect::isIp(String str) {
|
|
for (unsigned int i = 0; i < str.length(); i++) {
|
|
int c = str.charAt(i);
|
|
if (c != '.' && (c < '0' || c > '9')) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Function to return a IPAddress as a string representation.
|
|
@param ip
|
|
The IPAddress to process.
|
|
@return String version of the IPAddress
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
String WiFiConnect::toStringIp(IPAddress ip) {
|
|
String res = "";
|
|
for (int i = 0; i < 3; i++) {
|
|
res += String((ip >> (8 * i)) & 0xFF) + ".";
|
|
}
|
|
res += String(((ip >> 8 * 3)) & 0xFF);
|
|
return res;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Used to turn on or off messages to the serial port/monitor.
|
|
@param isDebug
|
|
Set to true to enable messages.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setDebug(boolean isDebug) {
|
|
_debug = isDebug;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Used to set a static ip/gateway and subnet mask for the access point.
|
|
IP and DNS Gateway are normally the same for a captive portal.
|
|
@param ip
|
|
The IP address that you want to access the portal through.
|
|
@param gw
|
|
The gateway address for the DNS server, usually the same as IP for
|
|
captive portal.
|
|
@param sn
|
|
The subnet mask for the access point, usually 255.255.255.0
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setAPStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn) {
|
|
_ap_static_ip = ip;
|
|
_ap_static_gw = gw;
|
|
_ap_static_sn = sn;
|
|
}
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Used to set a static ip/gateway and subnet mask for the local
|
|
network.
|
|
@param ip
|
|
The IP address that you want to use on the network.
|
|
@param gw
|
|
The gateway address for the DNS server or network router.
|
|
@param sn
|
|
The subnet mask for the access point, usually 255.255.255.0
|
|
for local networks.
|
|
*/
|
|
/**************************************************************************/
|
|
void WiFiConnect::setSTAStaticIPConfig(IPAddress ip, IPAddress gw, IPAddress sn) {
|
|
_sta_static_ip = ip;
|
|
_sta_static_gw = gw;
|
|
_sta_static_sn = sn;
|
|
}
|