diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f56a5eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Precompiled Headers +*.gch +*.pch + +# PlatformIO folders +.pio* + +# Documentation +docs/* + +# Credentials +credentials.h diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6b12260 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: python +python: + - '2.7' +sudo: false +cache: + directories: + - "~/.platformio" +install: + - pip install -U platformio +script: + - pushd examples/advanced && pio run && popd + - pushd examples/ap && pio run && popd + - pushd examples/basic && pio run && popd + - pushd examples/smartconfig && pio run && popd + - pushd examples/wps && pio run && popd diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fbc37f6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,72 @@ +# JustWifi change log + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [2.0.0] 2018-06-11 +### Added +- connected() member in class JustFifi + +## [2.0.0] 2018-06-11 +### Added +- SmartConfig (a.k.a. ESP Touch) support +- WPS Support +- TravisCI build tests +- Codacy code test + +### Changed +- Complete refactor (check examples to adapt your code) +- Changed license to LGPL-3.0 + +## [1.2.0] 2018-05-20 +### Changed +- Moved to GitHub + +## [1.1.9] 2018-05-08 +### Fixed +- Removed unneeded reference to DNSServer.h + +## [1.1.8] 2018-04-23 +### Changed +- Added options for power saving (Thanks to Pablo Pousada Rial) +- Added Travis CI configuration (Thanks to @lobradov) + +## [1.1.7] 2018-04-10 +### Changed +- Increasing hostname size to 32 chars + +## [1.1.6] 2018-01-10 +### Changed +- Allow to register several callbacks +- Changes in the information parameters for scanning and connecting callbacks +- Updated example + +### Deprecated +- onMessage method deprecated in favour of subscribe method + +## [1.1.5] 2017-09-22 +### Fixed +- Fix bug when no hostname defined (#1) +- When multiple routers have the same SSID, choose the one with strongest signal (#2). Thanks to Robert (robi772 @ bitbucket.org)! + +### Changed +- Callbacks output more info about networks + +## [1.1.4] 2017-08-24 +### Fixed +- Fixed code according to Arduino-ESP8266 issue https://github.com/esp8266/Arduino/issues/2186 + +## [1.1.3] 2017-01-17 +### Changed +- Disable autoconnect when using static IP + +## [1.1.2] 2017-01-11 +### Fixed +- Do not disable STA mode after disconnect + +## [1.1.1] 2016-12-29 +### Fixed +- Remove declaration from example, jw is a singleton + +## [1.1.0] 2016-09-29 +- Initial working version as standalone library diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5f97cb --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# JustWifi + +JustWifi is a WIFI Manager library for the [Arduino Core for ESP8266][2]. The goal of the library is to manage ONLY the WIFI connection (no webserver, no mDNS,...) from code and in a reliable and flexible way. + +[![version](https://img.shields.io/badge/version-2.0.0-brightgreen.svg)](CHANGELOG.md) +[![travis](https://travis-ci.org/xoseperez/justwifi.svg?branch=esp32)](https://travis-ci.org/xoseperez/justwifi) +[![codacy](https://img.shields.io/codacy/grade/4ccbea0317c4415eb2d1c562feced407/esp32.svg)](https://www.codacy.com/app/xoseperez/justwifi/dashboard) +[![license](https://img.shields.io/github/license/xoseperez/justwifi.svg)](LICENSE) +
+[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest) +[![twitter](https://img.shields.io/twitter/follow/xoseperez.svg?style=social)](https://twitter.com/intent/follow?screen_name=xoseperez) + +## Features + +The main features of the JustWifi library are: + +* Configure multiple possible networks +* Scan wifi networks so it can try to connect to only those available, in order of signal strength +* Smart Config support (when built with -DJUSTWIFI_ENABLE_SMARTCONFIG, tested with ESP8266 SmartConfig or IoT SmartConfig apps) +* WPS support (when built with -DJUSTWIFI_ENABLE_WPS) +* Fallback to AP mode +* Configurable timeout to try to reconnect after AP fallback +* AP+STA mode +* Static IP (autoconnect is disabled when using static IP) +* Single debug/action callback + +## Usage + +See examples. + +## License + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . diff --git a/examples/advanced/advanced.ino b/examples/advanced/advanced.ino new file mode 100644 index 0000000..530c3e6 --- /dev/null +++ b/examples/advanced/advanced.ino @@ -0,0 +1,144 @@ +/* + +JustWifi - Advanced example + +This example shows how to use callbacks to enable other services like mDNS or +a captive portal (when in AP mode only) + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +// ----------------------------------------------------------------------------- +// mDNS +// ----------------------------------------------------------------------------- + +#if defined(ARDUINO_ARCH_ESP32) + #include +#else + #include +#endif + +void mdnsCallback(justwifi_messages_t code, char * parameter) { + + if (code == MESSAGE_CONNECTED) { + + #if defined(ARDUINO_ARCH_ESP32) + String hostname = String(WiFi.getHostname()); + #else + String hostname = WiFi.hostname(); + #endif + + // Configure mDNS + if (MDNS.begin((char *) hostname.c_str())) { + Serial.printf("[MDNS] OK\n"); + + // Publish as if there is an TELNET service available + MDNS.addService("telnet", "tcp", 22); + + } else { + Serial.printf("[MDNS] FAIL\n"); + } + + } + +} + +// ----------------------------------------------------------------------------- +// Captive portal +// ----------------------------------------------------------------------------- + +#include + +DNSServer dnsServer; + +void captivePortalCallback(justwifi_messages_t code, char * parameter) { + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + if (!WiFi.isConnected()) dnsServer.start(53, "*", WiFi.softAPIP()); + } + + if (code == MESSAGE_CONNECTED) { + dnsServer.stop(); + } + +} + +// ----------------------------------------------------------------------------- + +void setup() { + + Serial.begin(115200); + delay(2000); + Serial.println(); + Serial.println(); + + // ------------------------------------------------------------------------- + + // Init object + jw.init(); + + // Set WIFI hostname (otherwise it would be ESP-XXXXXX) + jw.setHostname("justwifi"); + + // Callbacks + jw.subscribe(infoCallback); + jw.subscribe(mdnsCallback); + jw.subscribe(captivePortalCallback); + + // ------------------------------------------------------------------------- + + // AP mode only as fallback + jw.enableAP(false); + jw.enableAPFallback(true); + + // ------------------------------------------------------------------------- + + // Enable STA mode (connecting to a router) + jw.enableSTA(true); + + // Configure it to scan available networks and connect in order of dBm + jw.enableScan(true); + + // Clean existing network configuration + jw.cleanNetworks(); + + // Add a network with password + jw.addNetwork("home", "password"); + + // Add a network with static IP + jw.addNetwork("moms", "anotherpassword", "192.168.1.201", "192.168.1.1", "255.255.255.0"); + + // Add an open network + jw.addNetwork("work"); + + // ------------------------------------------------------------------------- + + Serial.println("[WIFI] Connecting Wifi..."); + +} + +void loop() { + + // This call takes care of it all + jw.loop(); + + // Small delay to give some breath + delay(10); + +} diff --git a/examples/advanced/platformio.ini b/examples/advanced/platformio.ini new file mode 100644 index 0000000..aa781f6 --- /dev/null +++ b/examples/advanced/platformio.ini @@ -0,0 +1,18 @@ +[platformio] +env_default = d1_mini +src_dir = . +lib_dir = ../.. + +[env:d1_mini] +platform = espressif8266 +board = d1_mini +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 + +[env:nano32] +platform = espressif32 +board = nano32 +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 diff --git a/examples/advanced/utils.ino b/examples/advanced/utils.ino new file mode 100644 index 0000000..f230aed --- /dev/null +++ b/examples/advanced/utils.ino @@ -0,0 +1,165 @@ +/* + +JustWifi - Basic debugging callback utils + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void infoWifi() { + + if (WiFi.isConnected()) { + + uint8_t * bssid = WiFi.BSSID(); + + Serial.printf("[WIFI] MODE STA -------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", WiFi.SSID().c_str()); + Serial.printf("[WIFI] BSSID %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5] + ); + Serial.printf("[WIFI] CH %d\n", WiFi.channel()); + Serial.printf("[WIFI] RSSI %d\n", WiFi.RSSI()); + Serial.printf("[WIFI] IP %s\n", WiFi.localIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.macAddress().c_str()); + Serial.printf("[WIFI] GW %s\n", WiFi.gatewayIP().toString().c_str()); + Serial.printf("[WIFI] MASK %s\n", WiFi.subnetMask().toString().c_str()); + Serial.printf("[WIFI] DNS %s\n", WiFi.dnsIP().toString().c_str()); + #if defined(ARDUINO_ARCH_ESP32) + Serial.printf("[WIFI] HOST %s\n", WiFi.getHostname()); + #else + Serial.printf("[WIFI] HOST %s\n", WiFi.hostname().c_str()); + #endif + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + + if (WiFi.getMode() & WIFI_AP) { + + Serial.printf("[WIFI] MODE AP --------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", jw.getAPSSID().c_str()); + Serial.printf("[WIFI] IP %s\n", WiFi.softAPIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.softAPmacAddress().c_str()); + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + +} + +void infoCallback(justwifi_messages_t code, char * parameter) { + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_TURNING_OFF) { + Serial.printf("[WIFI] Turning OFF\n"); + } + + if (code == MESSAGE_TURNING_ON) { + Serial.printf("[WIFI] Turning ON\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_SCANNING) { + Serial.printf("[WIFI] Scanning\n"); + } + + if (code == MESSAGE_SCAN_FAILED) { + Serial.printf("[WIFI] Scan failed\n"); + } + + if (code == MESSAGE_NO_NETWORKS) { + Serial.printf("[WIFI] No networks found\n"); + } + + if (code == MESSAGE_NO_KNOWN_NETWORKS) { + Serial.printf("[WIFI] No known networks found\n"); + } + + if (code == MESSAGE_FOUND_NETWORK) { + Serial.printf("[WIFI] %s\n", parameter); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_CONNECTING) { + Serial.printf("[WIFI] Connecting to %s\n", parameter); + } + + if (code == MESSAGE_CONNECT_WAITING) { + // too much noise + } + + if (code == MESSAGE_CONNECT_FAILED) { + Serial.printf("[WIFI] Could not connect to %s\n", parameter); + } + + if (code == MESSAGE_CONNECTED) { + infoWifi(); + } + + if (code == MESSAGE_DISCONNECTED) { + Serial.printf("[WIFI] Disconnected\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + infoWifi(); + } + + if (code == MESSAGE_ACCESSPOINT_DESTROYED) { + Serial.printf("[WIFI] Disconnecting access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATING) { + Serial.printf("[WIFI] Creating access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_FAILED) { + Serial.printf("[WIFI] Could not create access point\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_WPS_START) { + Serial.printf("[WIFI] WPS started\n"); + } + + if (code == MESSAGE_WPS_SUCCESS) { + Serial.printf("[WIFI] WPS succeded!\n"); + } + + if (code == MESSAGE_WPS_ERROR) { + Serial.printf("[WIFI] WPS failed\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_SMARTCONFIG_START) { + Serial.printf("[WIFI] Smart Config started\n"); + } + + if (code == MESSAGE_SMARTCONFIG_SUCCESS) { + Serial.printf("[WIFI] Smart Config succeded!\n"); + } + + if (code == MESSAGE_SMARTCONFIG_ERROR) { + Serial.printf("[WIFI] Smart Config failed\n"); + } + +}; diff --git a/examples/ap/ap.ino b/examples/ap/ap.ino new file mode 100644 index 0000000..5af3bce --- /dev/null +++ b/examples/ap/ap.ino @@ -0,0 +1,65 @@ +/* + +JustWifi - Access Point Example + +This example creates an access point. + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void setup() { + + Serial.begin(115200); + delay(2000); + Serial.println(); + Serial.println(); + + // ------------------------------------------------------------------------- + + // Init object + jw.init(); + + // Set WIFI hostname (otherwise it would be ESP-XXXXXX) + jw.setHostname("justwifi"); + + // Callbacks + jw.subscribe(infoCallback); + + // ------------------------------------------------------------------------- + + // Set open access point, do not define to use the hostname + //jw.setSoftAP("justwifi"); + + // Set password protected access point + jw.setSoftAP("justwifi", "password"); + + // Enable AP + jw.enableAP(true); + +} + +void loop() { + + // This call takes care of it all + jw.loop(); + + // Small delay to give some breath + delay(10); + +} diff --git a/examples/ap/platformio.ini b/examples/ap/platformio.ini new file mode 100644 index 0000000..aa781f6 --- /dev/null +++ b/examples/ap/platformio.ini @@ -0,0 +1,18 @@ +[platformio] +env_default = d1_mini +src_dir = . +lib_dir = ../.. + +[env:d1_mini] +platform = espressif8266 +board = d1_mini +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 + +[env:nano32] +platform = espressif32 +board = nano32 +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 diff --git a/examples/ap/utils.ino b/examples/ap/utils.ino new file mode 100644 index 0000000..f230aed --- /dev/null +++ b/examples/ap/utils.ino @@ -0,0 +1,165 @@ +/* + +JustWifi - Basic debugging callback utils + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void infoWifi() { + + if (WiFi.isConnected()) { + + uint8_t * bssid = WiFi.BSSID(); + + Serial.printf("[WIFI] MODE STA -------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", WiFi.SSID().c_str()); + Serial.printf("[WIFI] BSSID %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5] + ); + Serial.printf("[WIFI] CH %d\n", WiFi.channel()); + Serial.printf("[WIFI] RSSI %d\n", WiFi.RSSI()); + Serial.printf("[WIFI] IP %s\n", WiFi.localIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.macAddress().c_str()); + Serial.printf("[WIFI] GW %s\n", WiFi.gatewayIP().toString().c_str()); + Serial.printf("[WIFI] MASK %s\n", WiFi.subnetMask().toString().c_str()); + Serial.printf("[WIFI] DNS %s\n", WiFi.dnsIP().toString().c_str()); + #if defined(ARDUINO_ARCH_ESP32) + Serial.printf("[WIFI] HOST %s\n", WiFi.getHostname()); + #else + Serial.printf("[WIFI] HOST %s\n", WiFi.hostname().c_str()); + #endif + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + + if (WiFi.getMode() & WIFI_AP) { + + Serial.printf("[WIFI] MODE AP --------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", jw.getAPSSID().c_str()); + Serial.printf("[WIFI] IP %s\n", WiFi.softAPIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.softAPmacAddress().c_str()); + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + +} + +void infoCallback(justwifi_messages_t code, char * parameter) { + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_TURNING_OFF) { + Serial.printf("[WIFI] Turning OFF\n"); + } + + if (code == MESSAGE_TURNING_ON) { + Serial.printf("[WIFI] Turning ON\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_SCANNING) { + Serial.printf("[WIFI] Scanning\n"); + } + + if (code == MESSAGE_SCAN_FAILED) { + Serial.printf("[WIFI] Scan failed\n"); + } + + if (code == MESSAGE_NO_NETWORKS) { + Serial.printf("[WIFI] No networks found\n"); + } + + if (code == MESSAGE_NO_KNOWN_NETWORKS) { + Serial.printf("[WIFI] No known networks found\n"); + } + + if (code == MESSAGE_FOUND_NETWORK) { + Serial.printf("[WIFI] %s\n", parameter); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_CONNECTING) { + Serial.printf("[WIFI] Connecting to %s\n", parameter); + } + + if (code == MESSAGE_CONNECT_WAITING) { + // too much noise + } + + if (code == MESSAGE_CONNECT_FAILED) { + Serial.printf("[WIFI] Could not connect to %s\n", parameter); + } + + if (code == MESSAGE_CONNECTED) { + infoWifi(); + } + + if (code == MESSAGE_DISCONNECTED) { + Serial.printf("[WIFI] Disconnected\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + infoWifi(); + } + + if (code == MESSAGE_ACCESSPOINT_DESTROYED) { + Serial.printf("[WIFI] Disconnecting access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATING) { + Serial.printf("[WIFI] Creating access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_FAILED) { + Serial.printf("[WIFI] Could not create access point\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_WPS_START) { + Serial.printf("[WIFI] WPS started\n"); + } + + if (code == MESSAGE_WPS_SUCCESS) { + Serial.printf("[WIFI] WPS succeded!\n"); + } + + if (code == MESSAGE_WPS_ERROR) { + Serial.printf("[WIFI] WPS failed\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_SMARTCONFIG_START) { + Serial.printf("[WIFI] Smart Config started\n"); + } + + if (code == MESSAGE_SMARTCONFIG_SUCCESS) { + Serial.printf("[WIFI] Smart Config succeded!\n"); + } + + if (code == MESSAGE_SMARTCONFIG_ERROR) { + Serial.printf("[WIFI] Smart Config failed\n"); + } + +}; diff --git a/examples/basic/basic.ino b/examples/basic/basic.ino new file mode 100644 index 0000000..8913f81 --- /dev/null +++ b/examples/basic/basic.ino @@ -0,0 +1,84 @@ +/* + +JustWifi - Basic example + +This example shows how to define different networks and enable network scanning + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void setup() { + + Serial.begin(115200); + delay(2000); + Serial.println(); + Serial.println(); + + // ------------------------------------------------------------------------- + + // Init object + jw.init(); + + // Set WIFI hostname (otherwise it would be ESP-XXXXXX) + jw.setHostname("justwifi"); + + // Callbacks + jw.subscribe(infoCallback); + + // ------------------------------------------------------------------------- + + // AP mode only as fallback + jw.enableAP(false); + jw.enableAPFallback(true); + + // ------------------------------------------------------------------------- + + // Enable STA mode (connecting to a router) + jw.enableSTA(true); + + // Configure it to scan available networks and connect in order of dBm + jw.enableScan(true); + + // Clean existing network configuration + jw.cleanNetworks(); + + // Add a network with password + jw.addNetwork("home", "password"); + + // Add a network with static IP + jw.addNetwork("moms", "anotherpassword", "192.168.1.201", "192.168.1.1", "255.255.255.0"); + + // Add an open network + jw.addNetwork("work"); + + // ------------------------------------------------------------------------- + + Serial.println("[WIFI] Connecting Wifi..."); + +} + +void loop() { + + // This call takes care of it all + jw.loop(); + + // Small delay to give some breath + delay(10); + +} diff --git a/examples/basic/platformio.ini b/examples/basic/platformio.ini new file mode 100644 index 0000000..aa781f6 --- /dev/null +++ b/examples/basic/platformio.ini @@ -0,0 +1,18 @@ +[platformio] +env_default = d1_mini +src_dir = . +lib_dir = ../.. + +[env:d1_mini] +platform = espressif8266 +board = d1_mini +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 + +[env:nano32] +platform = espressif32 +board = nano32 +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 diff --git a/examples/basic/utils.ino b/examples/basic/utils.ino new file mode 100644 index 0000000..f230aed --- /dev/null +++ b/examples/basic/utils.ino @@ -0,0 +1,165 @@ +/* + +JustWifi - Basic debugging callback utils + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void infoWifi() { + + if (WiFi.isConnected()) { + + uint8_t * bssid = WiFi.BSSID(); + + Serial.printf("[WIFI] MODE STA -------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", WiFi.SSID().c_str()); + Serial.printf("[WIFI] BSSID %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5] + ); + Serial.printf("[WIFI] CH %d\n", WiFi.channel()); + Serial.printf("[WIFI] RSSI %d\n", WiFi.RSSI()); + Serial.printf("[WIFI] IP %s\n", WiFi.localIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.macAddress().c_str()); + Serial.printf("[WIFI] GW %s\n", WiFi.gatewayIP().toString().c_str()); + Serial.printf("[WIFI] MASK %s\n", WiFi.subnetMask().toString().c_str()); + Serial.printf("[WIFI] DNS %s\n", WiFi.dnsIP().toString().c_str()); + #if defined(ARDUINO_ARCH_ESP32) + Serial.printf("[WIFI] HOST %s\n", WiFi.getHostname()); + #else + Serial.printf("[WIFI] HOST %s\n", WiFi.hostname().c_str()); + #endif + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + + if (WiFi.getMode() & WIFI_AP) { + + Serial.printf("[WIFI] MODE AP --------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", jw.getAPSSID().c_str()); + Serial.printf("[WIFI] IP %s\n", WiFi.softAPIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.softAPmacAddress().c_str()); + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + +} + +void infoCallback(justwifi_messages_t code, char * parameter) { + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_TURNING_OFF) { + Serial.printf("[WIFI] Turning OFF\n"); + } + + if (code == MESSAGE_TURNING_ON) { + Serial.printf("[WIFI] Turning ON\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_SCANNING) { + Serial.printf("[WIFI] Scanning\n"); + } + + if (code == MESSAGE_SCAN_FAILED) { + Serial.printf("[WIFI] Scan failed\n"); + } + + if (code == MESSAGE_NO_NETWORKS) { + Serial.printf("[WIFI] No networks found\n"); + } + + if (code == MESSAGE_NO_KNOWN_NETWORKS) { + Serial.printf("[WIFI] No known networks found\n"); + } + + if (code == MESSAGE_FOUND_NETWORK) { + Serial.printf("[WIFI] %s\n", parameter); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_CONNECTING) { + Serial.printf("[WIFI] Connecting to %s\n", parameter); + } + + if (code == MESSAGE_CONNECT_WAITING) { + // too much noise + } + + if (code == MESSAGE_CONNECT_FAILED) { + Serial.printf("[WIFI] Could not connect to %s\n", parameter); + } + + if (code == MESSAGE_CONNECTED) { + infoWifi(); + } + + if (code == MESSAGE_DISCONNECTED) { + Serial.printf("[WIFI] Disconnected\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + infoWifi(); + } + + if (code == MESSAGE_ACCESSPOINT_DESTROYED) { + Serial.printf("[WIFI] Disconnecting access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATING) { + Serial.printf("[WIFI] Creating access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_FAILED) { + Serial.printf("[WIFI] Could not create access point\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_WPS_START) { + Serial.printf("[WIFI] WPS started\n"); + } + + if (code == MESSAGE_WPS_SUCCESS) { + Serial.printf("[WIFI] WPS succeded!\n"); + } + + if (code == MESSAGE_WPS_ERROR) { + Serial.printf("[WIFI] WPS failed\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_SMARTCONFIG_START) { + Serial.printf("[WIFI] Smart Config started\n"); + } + + if (code == MESSAGE_SMARTCONFIG_SUCCESS) { + Serial.printf("[WIFI] Smart Config succeded!\n"); + } + + if (code == MESSAGE_SMARTCONFIG_ERROR) { + Serial.printf("[WIFI] Smart Config failed\n"); + } + +}; diff --git a/examples/smartconfig/platformio.ini b/examples/smartconfig/platformio.ini new file mode 100644 index 0000000..af77b8d --- /dev/null +++ b/examples/smartconfig/platformio.ini @@ -0,0 +1,20 @@ +[platformio] +env_default = d1_mini +src_dir = . +lib_dir = ../.. + +[env:d1_mini] +platform = espressif8266 +board = d1_mini +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 +build_flags = -DJUSTWIFI_ENABLE_SMARTCONFIG -DDEBUG_ESP_PORT=Serial -DDEBUG_ESP_WIFI -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY + +[env:nano32] +platform = espressif32 +board = nano32 +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 +build_flags = -DJUSTWIFI_ENABLE_WPS -DDEBUG_ESP_PORT=Serial -DDEBUG_ESP_WIFI diff --git a/examples/smartconfig/smartconfig.ino b/examples/smartconfig/smartconfig.ino new file mode 100644 index 0000000..c496c27 --- /dev/null +++ b/examples/smartconfig/smartconfig.ino @@ -0,0 +1,68 @@ +/* + +JustWifi - Smart Config example + +This example shows how to use Smart Config (a.k.a. ESP Touch) to +provide the connection credentials to a device using a mobile app. + +Compatible apps: + +* ESP8266 SmartConfig +* IoT SmartConfig + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void setup() { + + Serial.begin(115200); + delay(2000); + Serial.println(); + Serial.println(); + + // ------------------------------------------------------------------------- + + // Init object + jw.init(); + + // Set WIFI hostname (otherwise it would be ESP-XXXXXX) + jw.setHostname("justwifi"); + + // Callbacks + jw.subscribe(infoCallback); + + // ------------------------------------------------------------------------- + + Serial.println("[WIFI] JustWifi Smart Config (ESP TOUCH) example"); + Serial.println("[WIFI] Start your Smart Config APP..."); + + // Start Smartconfig join + jw.startSmartConfig(); + +} + +void loop() { + + // This call takes care of it all + jw.loop(); + + // Small delay to give some breath + delay(10); + +} diff --git a/examples/smartconfig/utils.ino b/examples/smartconfig/utils.ino new file mode 100644 index 0000000..f230aed --- /dev/null +++ b/examples/smartconfig/utils.ino @@ -0,0 +1,165 @@ +/* + +JustWifi - Basic debugging callback utils + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void infoWifi() { + + if (WiFi.isConnected()) { + + uint8_t * bssid = WiFi.BSSID(); + + Serial.printf("[WIFI] MODE STA -------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", WiFi.SSID().c_str()); + Serial.printf("[WIFI] BSSID %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5] + ); + Serial.printf("[WIFI] CH %d\n", WiFi.channel()); + Serial.printf("[WIFI] RSSI %d\n", WiFi.RSSI()); + Serial.printf("[WIFI] IP %s\n", WiFi.localIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.macAddress().c_str()); + Serial.printf("[WIFI] GW %s\n", WiFi.gatewayIP().toString().c_str()); + Serial.printf("[WIFI] MASK %s\n", WiFi.subnetMask().toString().c_str()); + Serial.printf("[WIFI] DNS %s\n", WiFi.dnsIP().toString().c_str()); + #if defined(ARDUINO_ARCH_ESP32) + Serial.printf("[WIFI] HOST %s\n", WiFi.getHostname()); + #else + Serial.printf("[WIFI] HOST %s\n", WiFi.hostname().c_str()); + #endif + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + + if (WiFi.getMode() & WIFI_AP) { + + Serial.printf("[WIFI] MODE AP --------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", jw.getAPSSID().c_str()); + Serial.printf("[WIFI] IP %s\n", WiFi.softAPIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.softAPmacAddress().c_str()); + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + +} + +void infoCallback(justwifi_messages_t code, char * parameter) { + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_TURNING_OFF) { + Serial.printf("[WIFI] Turning OFF\n"); + } + + if (code == MESSAGE_TURNING_ON) { + Serial.printf("[WIFI] Turning ON\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_SCANNING) { + Serial.printf("[WIFI] Scanning\n"); + } + + if (code == MESSAGE_SCAN_FAILED) { + Serial.printf("[WIFI] Scan failed\n"); + } + + if (code == MESSAGE_NO_NETWORKS) { + Serial.printf("[WIFI] No networks found\n"); + } + + if (code == MESSAGE_NO_KNOWN_NETWORKS) { + Serial.printf("[WIFI] No known networks found\n"); + } + + if (code == MESSAGE_FOUND_NETWORK) { + Serial.printf("[WIFI] %s\n", parameter); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_CONNECTING) { + Serial.printf("[WIFI] Connecting to %s\n", parameter); + } + + if (code == MESSAGE_CONNECT_WAITING) { + // too much noise + } + + if (code == MESSAGE_CONNECT_FAILED) { + Serial.printf("[WIFI] Could not connect to %s\n", parameter); + } + + if (code == MESSAGE_CONNECTED) { + infoWifi(); + } + + if (code == MESSAGE_DISCONNECTED) { + Serial.printf("[WIFI] Disconnected\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + infoWifi(); + } + + if (code == MESSAGE_ACCESSPOINT_DESTROYED) { + Serial.printf("[WIFI] Disconnecting access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATING) { + Serial.printf("[WIFI] Creating access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_FAILED) { + Serial.printf("[WIFI] Could not create access point\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_WPS_START) { + Serial.printf("[WIFI] WPS started\n"); + } + + if (code == MESSAGE_WPS_SUCCESS) { + Serial.printf("[WIFI] WPS succeded!\n"); + } + + if (code == MESSAGE_WPS_ERROR) { + Serial.printf("[WIFI] WPS failed\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_SMARTCONFIG_START) { + Serial.printf("[WIFI] Smart Config started\n"); + } + + if (code == MESSAGE_SMARTCONFIG_SUCCESS) { + Serial.printf("[WIFI] Smart Config succeded!\n"); + } + + if (code == MESSAGE_SMARTCONFIG_ERROR) { + Serial.printf("[WIFI] Smart Config failed\n"); + } + +}; diff --git a/examples/wps/platformio.ini b/examples/wps/platformio.ini new file mode 100644 index 0000000..79c6a02 --- /dev/null +++ b/examples/wps/platformio.ini @@ -0,0 +1,20 @@ +[platformio] +env_default = d1_mini +src_dir = . +lib_dir = ../.. + +[env:d1_mini] +platform = espressif8266 +board = d1_mini +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 +build_flags = -DJUSTWIFI_ENABLE_WPS -DDEBUG_ESP_PORT=Serial -DDEBUG_ESP_WIFI + +[env:nano32] +platform = espressif32 +board = nano32 +framework = arduino +upload_speed = 460800 +monitor_speed = 115200 +build_flags = -DJUSTWIFI_ENABLE_WPS -DDEBUG_ESP_PORT=Serial -DDEBUG_ESP_WIFI diff --git a/examples/wps/utils.ino b/examples/wps/utils.ino new file mode 100644 index 0000000..f230aed --- /dev/null +++ b/examples/wps/utils.ino @@ -0,0 +1,165 @@ +/* + +JustWifi - Basic debugging callback utils + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include + +void infoWifi() { + + if (WiFi.isConnected()) { + + uint8_t * bssid = WiFi.BSSID(); + + Serial.printf("[WIFI] MODE STA -------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", WiFi.SSID().c_str()); + Serial.printf("[WIFI] BSSID %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5] + ); + Serial.printf("[WIFI] CH %d\n", WiFi.channel()); + Serial.printf("[WIFI] RSSI %d\n", WiFi.RSSI()); + Serial.printf("[WIFI] IP %s\n", WiFi.localIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.macAddress().c_str()); + Serial.printf("[WIFI] GW %s\n", WiFi.gatewayIP().toString().c_str()); + Serial.printf("[WIFI] MASK %s\n", WiFi.subnetMask().toString().c_str()); + Serial.printf("[WIFI] DNS %s\n", WiFi.dnsIP().toString().c_str()); + #if defined(ARDUINO_ARCH_ESP32) + Serial.printf("[WIFI] HOST %s\n", WiFi.getHostname()); + #else + Serial.printf("[WIFI] HOST %s\n", WiFi.hostname().c_str()); + #endif + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + + if (WiFi.getMode() & WIFI_AP) { + + Serial.printf("[WIFI] MODE AP --------------------------------------\n"); + Serial.printf("[WIFI] SSID %s\n", jw.getAPSSID().c_str()); + Serial.printf("[WIFI] IP %s\n", WiFi.softAPIP().toString().c_str()); + Serial.printf("[WIFI] MAC %s\n", WiFi.softAPmacAddress().c_str()); + Serial.printf("[WIFI] ----------------------------------------------\n"); + + } + +} + +void infoCallback(justwifi_messages_t code, char * parameter) { + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_TURNING_OFF) { + Serial.printf("[WIFI] Turning OFF\n"); + } + + if (code == MESSAGE_TURNING_ON) { + Serial.printf("[WIFI] Turning ON\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_SCANNING) { + Serial.printf("[WIFI] Scanning\n"); + } + + if (code == MESSAGE_SCAN_FAILED) { + Serial.printf("[WIFI] Scan failed\n"); + } + + if (code == MESSAGE_NO_NETWORKS) { + Serial.printf("[WIFI] No networks found\n"); + } + + if (code == MESSAGE_NO_KNOWN_NETWORKS) { + Serial.printf("[WIFI] No known networks found\n"); + } + + if (code == MESSAGE_FOUND_NETWORK) { + Serial.printf("[WIFI] %s\n", parameter); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_CONNECTING) { + Serial.printf("[WIFI] Connecting to %s\n", parameter); + } + + if (code == MESSAGE_CONNECT_WAITING) { + // too much noise + } + + if (code == MESSAGE_CONNECT_FAILED) { + Serial.printf("[WIFI] Could not connect to %s\n", parameter); + } + + if (code == MESSAGE_CONNECTED) { + infoWifi(); + } + + if (code == MESSAGE_DISCONNECTED) { + Serial.printf("[WIFI] Disconnected\n"); + } + + // ------------------------------------------------------------------------- + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + infoWifi(); + } + + if (code == MESSAGE_ACCESSPOINT_DESTROYED) { + Serial.printf("[WIFI] Disconnecting access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATING) { + Serial.printf("[WIFI] Creating access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_FAILED) { + Serial.printf("[WIFI] Could not create access point\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_WPS_START) { + Serial.printf("[WIFI] WPS started\n"); + } + + if (code == MESSAGE_WPS_SUCCESS) { + Serial.printf("[WIFI] WPS succeded!\n"); + } + + if (code == MESSAGE_WPS_ERROR) { + Serial.printf("[WIFI] WPS failed\n"); + } + + // ------------------------------------------------------------------------ + + if (code == MESSAGE_SMARTCONFIG_START) { + Serial.printf("[WIFI] Smart Config started\n"); + } + + if (code == MESSAGE_SMARTCONFIG_SUCCESS) { + Serial.printf("[WIFI] Smart Config succeded!\n"); + } + + if (code == MESSAGE_SMARTCONFIG_ERROR) { + Serial.printf("[WIFI] Smart Config failed\n"); + } + +}; diff --git a/examples/wps/wps.ino b/examples/wps/wps.ino new file mode 100644 index 0000000..55769b2 --- /dev/null +++ b/examples/wps/wps.ino @@ -0,0 +1,61 @@ +/* + +JustWifi - WPS example + +This example shows how to use connect to a WiFi using WPS. + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ +#include + +void setup() { + + Serial.begin(115200); + delay(2000); + Serial.println(); + Serial.println(); + + // ------------------------------------------------------------------------- + + // Init object + jw.init(); + + // Set WIFI hostname (otherwise it would be ESP-XXXXXX) + jw.setHostname("justwifi"); + + // Callbacks + jw.subscribe(infoCallback); + + // ------------------------------------------------------------------------- + + Serial.println("[WIFI] JustWifi WPS example"); + Serial.println("[WIFI] Click on your router WPS button..."); + + // Start WPS join + jw.startWPS(); + +} + +void loop() { + + // This call takes care of it all + jw.loop(); + + // Small delay to give some breath + delay(10); + +} diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..ba92023 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,61 @@ +####################################### +# Datatypes (KEYWORD1) +####################################### + +network_t KEYWORD1 +justwifi_messages_t KEYWORD1 +justwifi_states_t KEYWORD1 +TMessageFunction KEYWORD1 + +####################################### +# Classes (KEYWORD1) +####################################### + +JustWifi KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +addCurrentNetwork KEYWORD2 +addNetwork KEYWORD2 +setSoftAP KEYWORD2 +setHostname KEYWORD2 +setConnectTimeout KEYWORD2 +setReconnectTimeout KEYWORD2 +resetReconnectTimeout KEYWORD2 +subscribe KEYWORD2 +getAPSSID KEYWORD2 +connectable KEYWORD2 +turnOff KEYWORD2 +turnOn KEYWORD2 +disconnect KEYWORD2 +enableScan KEYWORD2 +enableSTA KEYWORD2 +enableAP KEYWORD2 +enableAPFallback KEYWORD2 +startWPS KEYWORD2 +startSmartConfig KEYWORD2 +init KEYWORD2 +loop KEYWORD2 +_events KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + +RESPONSE_START LITERAL1 +RESPONSE_OK LITERAL1 +RESPONSE_WAIT LITERAL1 +RESPONSE_FAIL LITERAL1 + +JUSTWIFI_ENABLE_WPS LITERAL1 +JUSTWIFI_ENABLE_SMARTCONFIG LITERAL1 + +DEFAULT_CONNECT_TIMEOUT LITERAL1 +DEFAULT_RECONNECT_INTERVAL LITERAL1 +JUSTWIFI_SMARTCONFIG_TIMEOUT LITERAL1 diff --git a/library.json b/library.json new file mode 100644 index 0000000..fa84883 --- /dev/null +++ b/library.json @@ -0,0 +1,25 @@ +{ + "name": "JustWifi", + "keywords": "wifi,manager,scan,wps,smartconfig", + "description": "Wifi Manager for ESP8266, supports multiple wifi networks, scan for strongest signal, WPS and SmartConfig", + "repository": { + "type": "git", + "url": "https://github.com/xoseperez/justwifi.git" + }, + "version": "2.0.0", + "license": "LGPL-3.0", + "exclude": "tests", + "frameworks": "arduino", + "platforms": "espressif8266", + "dependencies": [ + ], + "authors": { + "name": "Xose Perez", + "email": "xose.perez@gmail.com", + "url": "http://tinkerman.cat", + "maintainer": true + }, + "examples": [ + "examples/*/*.ino" + ] +} diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..bc6fdac --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=JustWifi +version=2.0.0 +author=Xose Pérez +maintainer=Xose Pérez +sentence=Wifi Manager for ESP8266 +paragraph=Supports multiple wifi networks, scan for strongest signal, WPS and SmartConfig +category=Communication +url=https://github.com/xoseperez/justwifi.git +architectures=esp8266 +includes=JustWifi.h diff --git a/pre-commit b/pre-commit new file mode 100755 index 0000000..f814c9b --- /dev/null +++ b/pre-commit @@ -0,0 +1,119 @@ +#!/usr/bin/env python +""" + +Referencing current branch in github README.md [1] +This pre-commit hook [2] updates the README.md file's +Travis badge with the current branch. Based on [4]. + +[1] http://stackoverflow.com/questions/18673694/referencing-current-branch-in-github-readme-md +[2] http://www.git-scm.com/book/en/v2/Customizing-Git-Git-Hooks +[3] https://docs.travis-ci.com/user/status-images/ +[4] https://gist.github.com/dandye/dfe0870a6a1151c89ed9 + +Copy this file to .git/hooks/ + +""" + +import os +import sys +import re + +from subprocess import call, check_output +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse + +from fileinput import FileInput +# https://github.com/python/cpython/commit/6cb7b659#diff-78790b53ff259619377058acd4f74672 +if sys.version_info[0] < 3: + class FileInputCtx(FileInput): + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + FileInput = FileInputCtx + + +def run(cmd, cwd=None): + out = check_output(cmd, cwd=cwd) + out = out.decode("latin1").strip() + + return out + + +def git_parse_remote(cwd=None, remote="origin"): + remote_url = run([ + "git", "config", "--local", + "--get", "remote.{}.url".format(remote)], cwd) + + if remote_url.startswith("git"): + _, _, repo = remote_url.partition(":") + elif remote_url.startswith("https"): + parsed = urlparse(remote_url) + repo = parsed.path[1:] + + path = repo.replace(".git", "") + return path.split("/") + + +def git_branch(cwd=None): + return run(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd) + + +def get_version(base, version_h="library.properties"): + version = "unknown" + + path = os.path.join(base, version_h) + with open(path, "r") as version_f: + for line in version_f: + if line.startswith("version="): + version = line.replace("version=", "").strip() + break + + return version + +TEMPLATES = { + "![travis]": "[![travis](https://travis-ci.org/{USER}/{REPO}.svg?branch={BRANCH})]" \ + "(https://travis-ci.org/{USER}/{REPO})\n", + "![version]": "[![version](https://img.shields.io/badge/version-{VERSION}-brightgreen.svg)](CHANGELOG.md)\n", + "![branch]": "[![branch](https://img.shields.io/badge/branch-{BRANCH}-orange.svg)]" \ + "(https://github.org/{USER}/{REPO}/tree/{BRANCH}/)\n", + "![codacy]": "[![codacy](https://img.shields.io/codacy/grade/{CODACY}/{BRANCH}.svg)]" \ + "(https://www.codacy.com/app/{USER}/{REPO}/dashboard)\n" +} + +README = "README.md" + +if __name__ == "__main__": + base = os.getcwd() + + user, repo = git_parse_remote() + fmt = { + "USER": user, + "REPO": repo, + "BRANCH": git_branch(), + "VERSION": get_version(base), + "CODACY": "4ccbea0317c4415eb2d1c562feced407" + } + templates = [ + (k, tmpl.format(**fmt)) + for k, tmpl in TEMPLATES.items() + ] + + def fmt_line(line): + for match, tmpl in templates: + if match in line: + return tmpl + + return line + + path = os.path.join(base, README) + + with FileInput(path, inplace=True) as readme: + for line in readme: + sys.stdout.write(fmt_line(line)) + + sys.exit(call(["git", "add", README])) diff --git a/src/JustWifi.cpp b/src/JustWifi.cpp new file mode 100644 index 0000000..fe1448a --- /dev/null +++ b/src/JustWifi.cpp @@ -0,0 +1,953 @@ +/* + +JustWifi 2.0.0 + +Wifi Manager for ESP8266 + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#include "JustWifi.h" +#include + +#if defined(ARDUINO_ARCH_ESP32) +extern "C" { + #include +} +#endif + +//------------------------------------------------------------------------------ +// CONSTRUCTOR +//------------------------------------------------------------------------------ + +JustWifi::JustWifi() { + _softap.ssid = NULL; + _timeout = 0; + uint32_t chip_id; + #if defined(ARDUINO_ARCH_ESP32) + chip_id = ESP.getEfuseMac() & 0xFFFFFFFF; + #else + chip_id = ESP.getChipId(); + #endif + snprintf_P(_hostname, sizeof(_hostname), PSTR("ESP-%06X"), chip_id); +} + +JustWifi::~JustWifi() { + cleanNetworks(); +} + +// ----------------------------------------------------------------------------- +// WPS +// ----------------------------------------------------------------------------- + +#if defined(JUSTWIFI_ENABLE_WPS) + +#if defined(ARDUINO_ARCH_ESP8266) + +#include "user_interface.h" + +wps_cb_status _jw_wps_status; + +void _jw_wps_status_cb(wps_cb_status status) { + _jw_wps_status = status; +} + + +#else + +#include "esp_wps.h" + +esp_wps_config_t _wifi_wps_config = WPS_CONFIG_INIT_DEFAULT(ESP_WPS_MODE); + +#endif + +void JustWifi::startWPS() { + _state = STATE_WPS_START; +} + +#endif // defined(JUSTWIFI_ENABLE_WPS) + +//------------------------------------------------------------------------------ +// SMART CONFIG +//------------------------------------------------------------------------------ + +#if defined(JUSTWIFI_ENABLE_SMARTCONFIG) + +void JustWifi::startSmartConfig() { + _state = STATE_SMARTCONFIG_START; +} + +#endif // defined(JUSTWIFI_ENABLE_SMARTCONFIG) + +//------------------------------------------------------------------------------ +// SCAN +//------------------------------------------------------------------------------ + +uint8_t JustWifi::_sortByRSSI() { + + bool first = true; + uint8_t bestID = 0xFF; + + for (uint8_t i = 0; i < _network_list.size(); i++) { + + network_t * entry = &_network_list[i]; + + // if no data skip + if (entry->rssi == 0) continue; + + // Empty list + if (first) { + first = false; + bestID = i; + entry->next = 0xFF; + + // The best so far + } else if (entry->rssi > _network_list[bestID].rssi) { + entry->next = bestID; + bestID = i; + + // Walk the list + } else { + + network_t * current = &_network_list[bestID]; + while (current->next != 0xFF) { + if (entry->rssi > _network_list[current->next].rssi) { + entry->next = current->next; + current->next = i; + break; + } + current = &_network_list[current->next]; + } + + // Place it the last + if (current->next == 0xFF) { + current->next = i; + entry->next = 0xFF; + } + + } + + } + + return bestID; + +} + +String JustWifi::_encodingString(uint8_t security) { + #if defined(ARDUINO_ARCH_ESP32) + if (security == WIFI_AUTH_WEP) return String("WEP "); + if (security == WIFI_AUTH_WPA_PSK) return String("WPA "); + if (security == WIFI_AUTH_WPA2_PSK) return String("WPA2 "); + if (security == WIFI_AUTH_WPA_WPA2_PSK) return String("WPA* "); + if (security == WIFI_AUTH_WPA2_ENTERPRISE) return String("WPA2E"); + if (security == WIFI_AUTH_MAX) return String("MAX "); + #else + if (security == ENC_TYPE_WEP) return String("WEP "); + if (security == ENC_TYPE_TKIP) return String("WPA "); + if (security == ENC_TYPE_CCMP) return String("WPA2 "); + if (security == ENC_TYPE_AUTO) return String("AUTO "); + #endif + return String("OPEN "); +} + +uint8_t JustWifi::_populate(uint8_t networkCount) { + + uint8_t count = 0; + + // Reset RSSI to disable networks that have disappeared + for (uint8_t j = 0; j < _network_list.size(); j++) { + _network_list[j].rssi = 0; + _network_list[j].scanned = false; + } + + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* BSSID_scan; + int32_t chan_scan; + + // Populate defined networks with scan data + for (int8_t i = 0; i < networkCount; ++i) { + + #if defined(ARDUINO_ARCH_ESP32) + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan); + #else + bool hidden_scan; + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); + #endif + + bool known = false; + + for (uint8_t j = 0; j < _network_list.size(); j++) { + + network_t * entry = &_network_list[j]; + + if (ssid_scan.equals(entry->ssid)) { + + // Check security + #if defined(ARDUINO_ARCH_ESP32) + if ((sec_scan != WIFI_AUTH_OPEN) && (entry->pass == NULL)) continue; + #else + if ((sec_scan != ENC_TYPE_NONE) && (entry->pass == NULL)) continue; + #endif + + // In case of several networks with the same SSID + // we want to get the one with the best RSSI + // Thanks to Robert (robi772 @ bitbucket.org) + if (entry->rssi < rssi_scan || entry->rssi == 0) { + entry->rssi = rssi_scan; + entry->security = sec_scan; + entry->channel = chan_scan; + entry->scanned = true; + memcpy((void*) &entry->bssid, (void*) BSSID_scan, sizeof(entry->bssid)); + } + + count++; + known = true; + break; + + } + + } + + if (_callbacks.size()) { + + char buffer[128]; + sprintf_P(buffer, + PSTR("%s BSSID: %02X:%02X:%02X:%02X:%02X:%02X CH: %2d RSSI: %3d SEC: %s SSID: %s"), + (known ? "-->" : " "), + BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], + chan_scan, + rssi_scan, + _encodingString(sec_scan).c_str(), + ssid_scan.c_str() + ); + _doCallback(MESSAGE_FOUND_NETWORK, buffer); + + } + + } + + return count; + +} + +void JustWifi::_esp8266_153_reset() { + + #if defined(ARDUINO_ARCH_ESP8266) + + // See https://github.com/esp8266/Arduino/issues/2186 + if (strncmp_P(ESP.getSdkVersion(), PSTR("1.5.3"), 5) == 0) { + if ((WiFi.getMode() & WIFI_AP) > 0) { + WiFi.mode(WIFI_OFF); + delay(10); + WiFi.enableAP(true); + } else { + WiFi.mode(WIFI_OFF); + } + + } + + #endif + +} + +uint8_t JustWifi::_doScan() { + + static bool scanning = false; + + // If not scanning, start scan + if (false == scanning) { + WiFi.disconnect(); + WiFi.enableSTA(true); + WiFi.scanNetworks(true, true); + _doCallback(MESSAGE_SCANNING); + scanning = true; + return RESPONSE_WAIT; + } + + // Check if scanning + int8_t scanResult = WiFi.scanComplete(); + if (WIFI_SCAN_RUNNING == scanResult) { + return RESPONSE_WAIT; + } + + // Scan finished + scanning = false; + + // Sometimes the scan fails, + // this will force the scan to restart + if (WIFI_SCAN_FAILED == scanResult) { + _doCallback(MESSAGE_SCAN_FAILED); + return RESPONSE_WAIT; + } + + // Check networks + if (0 == scanResult) { + WiFi.enableSTA(false); + _doCallback(MESSAGE_NO_NETWORKS); + return RESPONSE_FAIL; + } + + // Populate network list + uint8_t count = _populate(scanResult); + + // Free memory + WiFi.scanDelete(); + + if (0 == count) { + WiFi.enableSTA(false); + _doCallback(MESSAGE_NO_KNOWN_NETWORKS); + return RESPONSE_FAIL; + } + + // Sort networks by RSSI + _currentID = _sortByRSSI(); + return RESPONSE_OK; + +} + +// ----------------------------------------------------------------------------- +// STA +// ----------------------------------------------------------------------------- + +uint8_t JustWifi::_doSTA(uint8_t id) { + + static uint8_t networkID; + static uint8_t state = RESPONSE_START; + static unsigned long timeout; + + // Reset connection process + if (id != 0xFF) { + state = RESPONSE_START; + networkID = id; + } + + // Get network + network_t entry = _network_list[networkID]; + + // No state or previous network failed + if (RESPONSE_START == state) { + + // Init some values + WiFi.persistent(false); + _esp8266_153_reset(); + WiFi.enableSTA(true); + + // Configure static options + if (!entry.dhcp) { + WiFi.config(entry.ip, entry.gw, entry.netmask, entry.dns); + } + + // Info callback + if (_callbacks.size()) { + char buffer[128]; + if (entry.scanned) { + snprintf_P(buffer, sizeof(buffer), + PSTR("BSSID: %02X:%02X:%02X:%02X:%02X:%02X CH: %02d, RSSI: %3d, SEC: %s, SSID: %s"), + entry.bssid[0], entry.bssid[1], entry.bssid[2], entry.bssid[3], entry.bssid[4], entry.bssid[5], + entry.channel, + entry.rssi, + _encodingString(entry.security).c_str(), + entry.ssid + ); + } else { + snprintf_P(buffer, sizeof(buffer), PSTR("SSID: %s"), entry.ssid); + } + _doCallback(MESSAGE_CONNECTING, buffer); + } + + // Connecting + if (entry.channel == 0) { + WiFi.begin(entry.ssid, entry.pass); + } else { + WiFi.begin(entry.ssid, entry.pass, entry.channel, entry.bssid); + } + + timeout = millis(); + return (state = RESPONSE_WAIT); + + } + + // Connected? + if (WiFi.status() == WL_CONNECTED) { + + // Hostname + #if defined(ARDUINO_ARCH_ESP32) + WiFi.setHostname(_hostname); + #else + WiFi.hostname(_hostname); + #endif + + // Autoconnect only if DHCP, since it doesn't store static IP data + WiFi.setAutoConnect(entry.dhcp); + + WiFi.setAutoReconnect(true); + _doCallback(MESSAGE_CONNECTED); + return (state = RESPONSE_OK); + + } + + // Check timeout + if (millis() - timeout > _connect_timeout) { + WiFi.enableSTA(false); + _doCallback(MESSAGE_CONNECT_FAILED, entry.ssid); + return (state = RESPONSE_FAIL); + } + + // Still waiting + _doCallback(MESSAGE_CONNECT_WAITING); + return state; + +} + +// ----------------------------------------------------------------------------- +// AP +// ----------------------------------------------------------------------------- + +bool JustWifi::_doAP() { + + // If already created recreate + if (_ap_connected) enableAP(false); + + // Check if Soft AP configuration defined + if (!_softap.ssid) { + _softap.ssid = strdup(_hostname); + } + + _doCallback(MESSAGE_ACCESSPOINT_CREATING); + + WiFi.enableAP(true); + + // Configure static options + if (_softap.dhcp) { + WiFi.softAPConfig(_softap.ip, _softap.gw, _softap.netmask); + } + + if (_softap.pass) { + WiFi.softAP(_softap.ssid, _softap.pass); + } else { + WiFi.softAP(_softap.ssid); + } + + _doCallback(MESSAGE_ACCESSPOINT_CREATED); + + _ap_connected = true; + return true; + +} + +// ----------------------------------------------------------------------------- +// CALLBACKS +// ----------------------------------------------------------------------------- + +void JustWifi::_doCallback(justwifi_messages_t message, char * parameter) { + for (unsigned char i=0; i < _callbacks.size(); i++) { + (_callbacks[i])(message, parameter); + } +} + +void JustWifi::subscribe(TMessageFunction fn) { + _callbacks.push_back(fn); +} + +// ----------------------------------------------------------------------------- +// STATE MACHINE +// ----------------------------------------------------------------------------- + +void JustWifi::_machine() { + + #if false + static unsigned char previous = 0xFF; + if (_state != previous) { + previous = _state; + Serial.printf("_state: %u, WiFi.getMode(): %u\n", _state, WiFi.getMode()); + } + #endif + + switch(_state) { + + // --------------------------------------------------------------------- + + case STATE_IDLE: + + // Should we connect in STA mode? + if (WiFi.status() != WL_CONNECTED) { + + if (_sta_enabled) { + if (_network_list.size() > 0) { + if ((0 == _timeout) || ((_reconnect_timeout > 0) && (millis() - _timeout > _reconnect_timeout))) { + _currentID = 0; + _state = _scan ? STATE_SCAN_START : STATE_STA_START; + return; + } + } + } + + // Fallback + if (!_ap_connected & _ap_fallback_enabled) { + _state = STATE_FALLBACK; + } + + } + + + break; + + // --------------------------------------------------------------------- + + case STATE_SCAN_START: + _doScan(); + _state = STATE_SCAN_ONGOING; + break; + + case STATE_SCAN_ONGOING: + { + uint8_t response = _doScan(); + if (RESPONSE_OK == response) { + _state = STATE_STA_START; + } else if (RESPONSE_FAIL == response) { + _state = STATE_FALLBACK; + } + } + break; + + // --------------------------------------------------------------------- + + case STATE_STA_START: + _doSTA(_currentID); + _state = STATE_STA_ONGOING; + break; + + case STATE_STA_ONGOING: + { + uint8_t response = _doSTA(); + if (RESPONSE_OK == response) { + _state = STATE_STA_SUCCESS; + } else if (RESPONSE_FAIL == response) { + _state = STATE_STA_START; + if (_scan) { + _currentID = _network_list[_currentID].next; + if (_currentID == 0xFF) { + _state = STATE_STA_FAILED; + } + } else { + _currentID++; + if (_currentID == _network_list.size()) { + _state = STATE_STA_FAILED; + } + } + } + } + break; + + case STATE_STA_FAILED: + _state = STATE_FALLBACK; + break; + + case STATE_STA_SUCCESS: + _state = STATE_IDLE; + break; + + // --------------------------------------------------------------------- + + #if defined(JUSTWIFI_ENABLE_WPS) + + case STATE_WPS_START: + + _doCallback(MESSAGE_WPS_START); + + #if defined(ARDUINO_ARCH_ESP8266) + + _esp8266_153_reset(); + + if (!WiFi.enableSTA(true)) { + _state = STATE_WPS_FAILED; + return; + } + + WiFi.disconnect(); + + if (!wifi_wps_disable()) { + _state = STATE_WPS_FAILED; + return; + } + + // so far only WPS_TYPE_PBC is supported (SDK 1.2.0) + if (!wifi_wps_enable(WPS_TYPE_PBC)) { + _state = STATE_WPS_FAILED; + return; + } + + _jw_wps_status = (wps_cb_status) 5; + if (!wifi_set_wps_cb((wps_st_cb_t) &_jw_wps_status_cb)) { + _state = STATE_WPS_FAILED; + return; + } + + if (!wifi_wps_start()) { + _state = STATE_WPS_FAILED; + return; + } + + #else + + esp_wifi_wps_enable(&_wifi_wps_config); + esp_wifi_wps_start(0); + + #endif + + _state = STATE_WPS_ONGOING; + break; + + case STATE_WPS_ONGOING: + if (5 == _jw_wps_status) { + // Still ongoing + } else if (WPS_CB_ST_SUCCESS == _jw_wps_status) { + _state = STATE_WPS_SUCCESS; + } else { + _state = STATE_WPS_FAILED; + } + break; + + case STATE_WPS_FAILED: + _doCallback(MESSAGE_WPS_ERROR); + wifi_wps_disable(); + _state = STATE_FALLBACK; + break; + + case STATE_WPS_SUCCESS: + _doCallback(MESSAGE_WPS_SUCCESS); + wifi_wps_disable(); + addCurrentNetwork(true); + _state = STATE_IDLE; + break; + + #endif // defined(JUSTWIFI_ENABLE_WPS) + + // --------------------------------------------------------------------- + + #if defined(JUSTWIFI_ENABLE_SMARTCONFIG) + + case STATE_SMARTCONFIG_START: + + _doCallback(MESSAGE_SMARTCONFIG_START); + + enableAP(false); + + if (!WiFi.beginSmartConfig()) { + _state = STATE_SMARTCONFIG_FAILED; + return; + } + + _state = STATE_SMARTCONFIG_ONGOING; + _start = millis(); + + break; + + case STATE_SMARTCONFIG_ONGOING: + if (WiFi.smartConfigDone()) { + _state = STATE_SMARTCONFIG_SUCCESS; + } else if (millis() - _start > JUSTWIFI_SMARTCONFIG_TIMEOUT) { + _state = STATE_SMARTCONFIG_FAILED; + } + break; + + case STATE_SMARTCONFIG_FAILED: + _doCallback(MESSAGE_SMARTCONFIG_ERROR); + WiFi.stopSmartConfig(); + WiFi.enableSTA(false); + _state = STATE_FALLBACK; + break; + + case STATE_SMARTCONFIG_SUCCESS: + _doCallback(MESSAGE_SMARTCONFIG_SUCCESS); + addCurrentNetwork(true); + _state = STATE_IDLE; + break; + + #endif // defined(JUSTWIFI_ENABLE_SMARTCONFIG) + + // --------------------------------------------------------------------- + + case STATE_FALLBACK: + if (!_ap_connected & _ap_fallback_enabled) _doAP(); + _timeout = millis(); + _state = STATE_IDLE; + break; + + default: + _state = STATE_IDLE; + break; + + } + +} + +//------------------------------------------------------------------------------ +// PUBLIC API +//------------------------------------------------------------------------------ + +void JustWifi::cleanNetworks() { + for (uint8_t i = 0; i < _network_list.size(); i++) { + network_t entry = _network_list[i]; + if (entry.ssid) free(entry.ssid); + if (entry.pass) free(entry.pass); + } + _network_list.clear(); +} + +bool JustWifi::addNetwork( + const char * ssid, + const char * pass, + const char * ip, + const char * gw, + const char * netmask, + const char * dns, + bool front +) { + + network_t new_network; + + // Check SSID too long or missing + if (!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + return false; + } + + // Check PASS too long + if (pass && strlen(pass) > 63) { + return false; + } + + // Copy network SSID + new_network.ssid = strdup(ssid); + if (!new_network.ssid) { + return false; + } + + // Copy network PASS + if (pass && *pass != 0x00) { + new_network.pass = strdup(pass); + if (!new_network.pass) { + free(new_network.ssid); + return false; + } + } else { + new_network.pass = NULL; + } + + // Copy static config + new_network.dhcp = true; + if (ip && gw && netmask + && *ip != 0x00 && *gw != 0x00 && *netmask != 0x00) { + new_network.dhcp = false; + new_network.ip.fromString(ip); + new_network.gw.fromString(gw); + new_network.netmask.fromString(netmask); + } + if (dns && *dns != 0x00) { + new_network.dns.fromString(dns); + } + + // Defaults + new_network.rssi = 0; + new_network.security = 0; + new_network.channel = 0; + new_network.next = 0xFF; + new_network.scanned = false; + + // Store data + if (front) { + _network_list.insert(_network_list.begin(), new_network); + } else { + _network_list.push_back(new_network); + } + return true; + +} + +bool JustWifi::addCurrentNetwork(bool front) { + return addNetwork( + WiFi.SSID().c_str(), + WiFi.psk().c_str(), + NULL, NULL, NULL, NULL, + front + ); +} + +bool JustWifi::setSoftAP( + const char * ssid, + const char * pass, + const char * ip, + const char * gw, + const char * netmask +) { + + // Check SSID too long or missing + if (!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + return false; + } + + // Check PASS too long + if (pass && strlen(pass) > 63) { + return false; + } + + // Copy network SSID + _softap.ssid = strdup(ssid); + if (!_softap.ssid) { + return false; + } + + // Copy network PASS + if (pass && *pass != 0x00) { + _softap.pass = strdup(pass); + if (!_softap.pass) { + _softap.ssid = NULL; + return false; + } + } + + // Copy static config + _softap.dhcp = false; + if (ip && gw && netmask + && *ip != 0x00 && *gw != 0x00 && *netmask != 0x00) { + _softap.dhcp = true; + _softap.ip.fromString(ip); + _softap.gw.fromString(gw); + _softap.netmask.fromString(netmask); + } + + if ((WiFi.getMode() & WIFI_AP) > 0) { + + // https://github.com/xoseperez/justwifi/issues/4 + if (_softap.pass) { + WiFi.softAP(_softap.ssid, _softap.pass); + } else { + WiFi.softAP(_softap.ssid); + } + + } + + return true; + +} + +void JustWifi::setConnectTimeout(unsigned long ms) { + _connect_timeout = ms; +} + +void JustWifi::setReconnectTimeout(unsigned long ms) { + _reconnect_timeout = ms; +} + +void JustWifi::resetReconnectTimeout() { + _timeout = millis(); +} + +void JustWifi::setHostname(const char * hostname) { + strncpy(_hostname, hostname, sizeof(_hostname)); +} + +String JustWifi::getAPSSID() { + return String(_softap.ssid); +} + +bool JustWifi::connected() { + return (WiFi.status() == WL_CONNECTED); +} + +bool JustWifi::connectable() { + return _ap_connected; +} + +void JustWifi::disconnect() { + _timeout = 0; + WiFi.disconnect(); + WiFi.enableSTA(false); + _doCallback(MESSAGE_DISCONNECTED); +} + +void JustWifi::turnOff() { + + WiFi.disconnect(); + WiFi.enableAP(false); + WiFi.enableSTA(false); + #if defined(ARDUINO_ARCH_ESP8266) + WiFi.forceSleepBegin(); + #endif + delay(1); + + _sta_enabled = false; + _state = STATE_IDLE; + _doCallback(MESSAGE_TURNING_OFF); + +} + +void JustWifi::turnOn() { + + #if defined(ARDUINO_ARCH_ESP8266) + WiFi.forceSleepWake(); + #endif + delay(1); + + setReconnectTimeout(0); + _sta_enabled = true; + _state = STATE_IDLE; + _doCallback(MESSAGE_TURNING_ON); + +} + +void JustWifi::enableSTA(bool enabled) { + _sta_enabled = enabled; +} + +void JustWifi::enableAP(bool enabled) { + if (enabled) { + _doAP(); + } else if (_ap_connected) { + WiFi.softAPdisconnect(); + WiFi.enableAP(false); + _ap_connected = false; + _doCallback(MESSAGE_ACCESSPOINT_DESTROYED); + } +} + +void JustWifi::enableAPFallback(bool enabled) { + _ap_fallback_enabled = enabled; +} + +void JustWifi::enableScan(bool scan) { + _scan = scan; +} + +void JustWifi::_events(WiFiEvent_t event) { + Serial.printf("[WIFI] Event %u\n", (uint8_t) event); + Serial.println(event); +} + +void JustWifi::init() { + WiFi.enableAP(false); + WiFi.enableSTA(false); + //WiFi.onEvent(reinterpret_cast(&JustWifi::_events), WIFI_EVENT_ANY); +} + +void JustWifi::loop() { + _machine(); +} + +JustWifi jw; diff --git a/src/JustWifi.h b/src/JustWifi.h new file mode 100644 index 0000000..09ca1f4 --- /dev/null +++ b/src/JustWifi.h @@ -0,0 +1,218 @@ +/* + +JustWifi 2.0.0 + +Wifi Manager for ESP8266 + +Copyright (C) 2016-2018 by Xose Pérez + +The JustWifi 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 3 of the License, or +(at your option) any later version. + +The JustWifi 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 the JustWifi library. If not, see . + +*/ + +#ifndef JustWifi_h +#define JustWifi_h + +#include +#include +#if defined(ARDUINO_ARCH_ESP32) +#include +#elif defined(ARDUINO_ARCH_ESP8266) +#include +extern "C" { + #include "user_interface.h" +} +#else +#error "Non supported architecture!" +#endif + + +#define DEFAULT_CONNECT_TIMEOUT 20000 +#define DEFAULT_RECONNECT_INTERVAL 60000 +#define JUSTWIFI_SMARTCONFIG_TIMEOUT 60000 + +#ifdef DEBUG_ESP_WIFI +#ifdef DEBUG_ESP_PORT +#define DEBUG_WIFI_MULTI(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ ) +#endif +#endif + +#ifndef DEBUG_WIFI_MULTI +#define DEBUG_WIFI_MULTI(...) +#endif + +typedef struct { + char * ssid; + char * pass; + bool dhcp; + bool scanned; + IPAddress ip; + IPAddress gw; + IPAddress netmask; + IPAddress dns; + int32_t rssi; + uint8_t security; + uint8_t channel; + uint8_t bssid[6]; + uint8_t next; +} network_t; + +typedef enum { + STATE_IDLE, + STATE_SCAN_START, + STATE_SCAN_ONGOING, + STATE_STA_START, + STATE_STA_ONGOING, + STATE_STA_FAILED, + STATE_STA_SUCCESS, + STATE_WPS_START, + STATE_WPS_ONGOING, + STATE_WPS_FAILED, + STATE_WPS_SUCCESS, + STATE_SMARTCONFIG_START, + STATE_SMARTCONFIG_ONGOING, + STATE_SMARTCONFIG_FAILED, + STATE_SMARTCONFIG_SUCCESS, + STATE_FALLBACK +} justwifi_states_t; + +typedef enum { + MESSAGE_SCANNING, + MESSAGE_SCAN_FAILED, + MESSAGE_NO_NETWORKS, + MESSAGE_FOUND_NETWORK, + MESSAGE_NO_KNOWN_NETWORKS, + MESSAGE_CONNECTING, + MESSAGE_CONNECT_WAITING, + MESSAGE_CONNECT_FAILED, + MESSAGE_CONNECTED, + MESSAGE_ACCESSPOINT_CREATING, + MESSAGE_ACCESSPOINT_CREATED, + MESSAGE_ACCESSPOINT_FAILED, + MESSAGE_ACCESSPOINT_DESTROYED, + MESSAGE_DISCONNECTED, + MESSAGE_HOSTNAME_ERROR, + MESSAGE_TURNING_OFF, + MESSAGE_TURNING_ON, + MESSAGE_WPS_START, + MESSAGE_WPS_SUCCESS, + MESSAGE_WPS_ERROR, + MESSAGE_SMARTCONFIG_START, + MESSAGE_SMARTCONFIG_SUCCESS, + MESSAGE_SMARTCONFIG_ERROR +} justwifi_messages_t; + +enum { + RESPONSE_START, + RESPONSE_OK, + RESPONSE_WAIT, + RESPONSE_FAIL +}; + +class JustWifi { + + public: + + typedef std::function TMessageFunction; + + JustWifi(); + ~JustWifi(); + + void cleanNetworks(); + bool addCurrentNetwork(bool front = false); + bool addNetwork( + const char * ssid, + const char * pass = NULL, + const char * ip = NULL, + const char * gw = NULL, + const char * netmask = NULL, + const char * dns = NULL, + bool front = false + ); + bool setSoftAP( + const char * ssid, + const char * pass = NULL, + const char * ip = NULL, + const char * gw = NULL, + const char * netmask = NULL + ); + + void setHostname(const char * hostname); + void setConnectTimeout(unsigned long ms); + void setReconnectTimeout(unsigned long ms = DEFAULT_RECONNECT_INTERVAL); + void resetReconnectTimeout(); + void subscribe(TMessageFunction fn); + + String getAPSSID(); + bool connectable(); + + bool connected(); + + void turnOff(); + void turnOn(); + void disconnect(); + void enableScan(bool scan); + void enableSTA(bool enabled); + void enableAP(bool enabled); + void enableAPFallback(bool enabled); + + #if defined(JUSTWIFI_ENABLE_WPS) + void startWPS(); + #endif + + #if defined(JUSTWIFI_ENABLE_SMARTCONFIG) + void startSmartConfig(); + #endif + + void init(); + void loop(); + + void _events(WiFiEvent_t event); + + private: + + std::vector _network_list; + std::vector _callbacks; + + unsigned long _connect_timeout = DEFAULT_CONNECT_TIMEOUT; + unsigned long _reconnect_timeout = DEFAULT_RECONNECT_INTERVAL; + unsigned long _timeout = 0; + unsigned long _start = 0; + uint8_t _currentID; + bool _scan = false; + char _hostname[32]; + network_t _softap { NULL, NULL }; + + justwifi_states_t _state = STATE_IDLE; + bool _sta_enabled = true; + bool _ap_connected = false; + bool _ap_fallback_enabled = true; + + bool _doAP(); + uint8_t _doScan(); + uint8_t _doSTA(uint8_t id = 0xFF); + + void _esp8266_153_reset(); + void _machine(); + uint8_t _populate(uint8_t networkCount); + uint8_t _sortByRSSI(); + String _MAC2String(const unsigned char* mac); + String _encodingString(uint8_t security); + void _doCallback(justwifi_messages_t message, char * parameter = NULL); + +}; + +extern JustWifi jw; + +#endif