Browse Source

Moved Wifi management code to a library

fastled
Xose Pérez 8 years ago
parent
commit
eea34ed8ce
3 changed files with 404 additions and 111 deletions
  1. +200
    -0
      code/lib/JustWifi/JustWifi.cpp
  2. +99
    -0
      code/lib/JustWifi/JustWifi.h
  3. +105
    -111
      code/src/main.cpp

+ 200
- 0
code/lib/JustWifi/JustWifi.cpp View File

@ -0,0 +1,200 @@
/*
JustWifi
Wifi Manager for ESP8266
Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "JustWifi.h"
#include <functional>
bool JustWifi::connected() {
return (WiFi.status() == WL_CONNECTED);
}
bool JustWifi::autoConnect() {
// Return if already connected
if (connected()) return true;
// Try to connect to last successful network
WiFi.mode(WIFI_STA);
if (WiFi.SSID()) {
_doCallback(MESSAGE_AUTO_CONNECTING, (char *) WiFi.SSID().c_str());
ETS_UART_INTR_DISABLE();
wifi_station_disconnect();
ETS_UART_INTR_ENABLE();
WiFi.begin();
if (WiFi.status() == WL_CONNECTED) {
_mode = MODE_STATION;
_doCallback(MESSAGE_CONNECTED);
return true;
}
_doCallback(MESSAGE_AUTO_FAILED);
} else {
_doCallback(MESSAGE_AUTO_NOSSID);
}
_mode = MODE_NONE;
return false;
}
bool JustWifi::connect() {
unsigned long timeout;
// Return if already connected
if (connected()) return true;
// Loop through configured networks
for (unsigned char i=0; i<_network_count; i++) {
// TODO: Static IP options here
// Connect
_doCallback(MESSAGE_CONNECTING, (char *) _network[i].ssid.c_str());
WiFi.begin(_network[i].ssid.c_str(), _network[i].pass.c_str());
// Check connection with timeout
timeout = millis();
while (millis() - timeout < _connect_timeout) {
_doCallback(MESSAGE_CONNECT_WAITING);
if (WiFi.status() == WL_CONNECTED) break;
delay(100);
}
// Get out of the i loop if connected
if (WiFi.status() == WL_CONNECTED) {
break;
} else {
_mode = MODE_NONE;
_doCallback(MESSAGE_CONNECT_FAILED, (char *) _network[i].ssid.c_str());
}
}
if (WiFi.status() == WL_CONNECTED) {
//WiFi.setAutoConnect(true);
//WiFi.setAutoReconnect(true);
_mode = MODE_STATION;
_doCallback(MESSAGE_CONNECTED);
return true;
}
return false;
}
bool JustWifi::startAP(char * ssid, char * pass) {
// Return if already connected
// if (connected()) return true;
// TODO: Static IP options here
_doCallback(MESSAGE_ACCESSPOINT_CREATING);
WiFi.mode(WIFI_AP);
if (strlen(pass) > 0) {
if (strlen(pass) < 8 || strlen(pass) > 63) {
_mode = MODE_NONE;
_doCallback(MESSAGE_ACCESSPOINT_FAILED);
return false;
}
WiFi.softAP(ssid, pass);
} else {
WiFi.softAP(ssid);
}
// TODO: Setup the DNS server redirecting all the queries to this IP
_ssid = String(ssid);
_mode = MODE_ACCESS_POINT;
_doCallback(MESSAGE_ACCESSPOINT_CREATED);
return true;
}
bool JustWifi::disconnect() {
WiFi.disconnect(true);
_mode = MODE_NONE;
_doCallback(MESSAGE_DISCONNECTED);
}
bool JustWifi::cleanNetworks() {
_network_count = 0;
}
bool JustWifi::addNetwork(char * ssid, char * pass) {
if (_network_count == MAX_NETWORKS) return false;
_network[_network_count].ssid = String(ssid);
_network[_network_count].pass = String(pass);
_network_count++;
return true;
}
justwifi_mode_t JustWifi::getMode() {
return _mode;
}
String JustWifi::getIP() {
if (_mode == MODE_STATION) {
return WiFi.localIP().toString();
} else if (_mode == MODE_ACCESS_POINT) {
return WiFi.softAPIP().toString();
}
return String("");
}
String JustWifi::getNetwork() {
if (_mode == MODE_STATION) {
return WiFi.SSID();
}
return _ssid;
}
void JustWifi::setConnectTimeout(unsigned long ms) {
_connect_timeout = ms;
}
void JustWifi::onMessage(TMessageFunction fn) {
_callback = fn;
}
void JustWifi::loop() {
if ((WiFi.status() != WL_CONNECTED) && (_mode == MODE_STATION)) {
_mode = MODE_NONE;
_doCallback(MESSAGE_DISCONNECTED);
}
if ((WiFi.status() == WL_CONNECTED) && (_mode != MODE_STATION)) {
_mode = MODE_STATION;
_doCallback(MESSAGE_CONNECTED);
}
}
void JustWifi::_doCallback(justwifi_messages_t message, char * parameter) {
if (_callback != NULL) _callback(message, parameter);
}

+ 99
- 0
code/lib/JustWifi/JustWifi.h View File

@ -0,0 +1,99 @@
/*
JustWifi
Wifi Manager for ESP8266
Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JustWifi_h
#define JustWifi_h
#include <functional>
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
#define MAX_NETWORKS 3
#define WIFI_CONNECT_TIMEOUT 10000
struct network_t {
String ssid;
String pass;
};
typedef enum {
MODE_NONE,
MODE_STATION,
MODE_ACCESS_POINT
} justwifi_mode_t;
typedef enum {
MESSAGE_AUTO_NOSSID,
MESSAGE_AUTO_CONNECTING,
MESSAGE_AUTO_FAILED,
MESSAGE_CONNECTING,
MESSAGE_CONNECT_WAITING,
MESSAGE_CONNECT_FAILED,
MESSAGE_CONNECTED,
MESSAGE_ACCESSPOINT_CREATING,
MESSAGE_ACCESSPOINT_FAILED,
MESSAGE_ACCESSPOINT_CREATED,
MESSAGE_DISCONNECTED
} justwifi_messages_t;
class JustWifi {
public:
typedef std::function<void(justwifi_messages_t, char *)> TMessageFunction;
bool autoConnect();
bool connect();
bool startAP(char * ssid, char * pass);
bool disconnect();
bool connected();
bool cleanNetworks();
bool addNetwork(char * ssid, char * pass);
void setConnectTimeout(unsigned long ms);
justwifi_mode_t getMode();
String getIP();
String getNetwork();
void onMessage(TMessageFunction fn);
void loop();
private:
network_t _network[MAX_NETWORKS];
String _ssid;
justwifi_mode_t _mode = MODE_NONE;
unsigned char _network_count = 0;
unsigned long _connect_timeout = WIFI_CONNECT_TIMEOUT;
TMessageFunction _callback = NULL;
void _doCallback(justwifi_messages_t message, char * parameter = NULL);
};
#endif

+ 105
- 111
code/src/main.cpp View File

@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "Config.h" #include "Config.h"
#include "NoFUSSClient.h" #include "NoFUSSClient.h"
#include "JustWifi.h"
#include <DebounceEvent.h> #include <DebounceEvent.h>
#include <EmonLiteESP.h> #include <EmonLiteESP.h>
@ -66,6 +67,10 @@ extern "C" {
#define ENABLE_RF 0 #define ENABLE_RF 0
#define ENABLE_DHT 0 #define ENABLE_DHT 0
#define BUTTON_PIN 0
#define RELAY_PIN 12
#define LED_PIN 13
#ifdef ESPURNA #ifdef ESPURNA
#define MANUFACTURER "TINKERMAN" #define MANUFACTURER "TINKERMAN"
#define DEVICE "ESPURNA" #define DEVICE "ESPURNA"
@ -89,12 +94,10 @@ extern "C" {
#ifdef NODEMCUV2 #ifdef NODEMCUV2
#define MANUFACTURER "NODEMCU" #define MANUFACTURER "NODEMCU"
#define DEVICE "LOLIN" #define DEVICE "LOLIN"
#undef LED_PIN
#define LED_PIN 16
#endif #endif
#define BUTTON_PIN 0
#define RELAY_PIN 12
#define LED_PIN 13
#define ADMIN_PASS "fibonacci" #define ADMIN_PASS "fibonacci"
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
#define STATUS_UPDATE_INTERVAL 10000 #define STATUS_UPDATE_INTERVAL 10000
@ -120,12 +123,6 @@ extern "C" {
#define MQTT_TEMPERATURE_TOPIC "/temperature" #define MQTT_TEMPERATURE_TOPIC "/temperature"
#define MQTT_HUMIDITY_TOPIC "/humidity" #define MQTT_HUMIDITY_TOPIC "/humidity"
#define WIFI_CONNECT_TIMEOUT 10000
#define WIFI_RECONNECT_DELAY 2000
#define WIFI_STATUS_CONNECTING 0
#define WIFI_STATUS_CONNECTED 1
#define WIFI_STATUS_AP 2
#define CURRENT_PIN 0 #define CURRENT_PIN 0
#define ADC_BITS 10 #define ADC_BITS 10
#define REFERENCE_VOLTAGE 1.0 #define REFERENCE_VOLTAGE 1.0
@ -139,8 +136,7 @@ extern "C" {
// Globals // Globals
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
byte status = WIFI_STATUS_CONNECTING;
JustWifi jw;
DebounceEvent button1 = false; DebounceEvent button1 = false;
#if ENABLE_WEBSERVER #if ENABLE_WEBSERVER
@ -227,7 +223,7 @@ void blink(unsigned long delayOff, unsigned long delayOn) {
} }
void showStatus() { void showStatus() {
if (WiFi.status() == WL_CONNECTED) {
if (jw.connected()) {
blink(5000, 500); blink(5000, 500);
} else { } else {
blink(500, 500); blink(500, 500);
@ -424,128 +420,126 @@ void toggleRelay() {
// Wifi // Wifi
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void wifiSetupAP() {
void wifiSetup() {
// Set WIFI module AP mode
WiFi.mode(WIFI_AP);
#ifdef DEBUG
WiFi.printDiag(Serial);
#endif
// Message callbacks
jw.onMessage([](justwifi_messages_t code, char * parameter) {
// SoftAP mode
WiFi.softAP(config.hostname.c_str(), ADMIN_PASS);
status = WIFI_STATUS_AP;
delay(100);
#ifdef DEBUG
Serial.print(F("[WIFI] ACCESS POINT Mode, SSID: "));
Serial.print(config.hostname);
Serial.print(F(", Password: \""));
Serial.print(ADMIN_PASS);
Serial.print(F("\", IP address: "));
Serial.println(WiFi.softAPIP());
#endif
}
void wifiSetupSTA() {
byte network = 0;
// Set WIFI module to STA mode
WiFi.mode(WIFI_STA);
#ifdef DEBUG
//WiFi.printDiag(Serial);
#endif
if (code == MESSAGE_CONNECTED) {
#if ENABLE_NOFUSS
NoFUSSClient.handle();
#endif
} else {
#if ENABLE_MQTT
if (mqtt.connected()) mqtt.disconnect();
#endif
}
#if ENABLE_MQTT
if (mqtt.connected()) mqtt.disconnect();
#endif
#if ENABLE_RF
if (code == MESSAGE_CONNECTING) {
RemoteReceiver::disable();
} else if (code != MESSAGE_CONNECT_WAITING) {
RemoteReceiver::enable();
}
#endif
#if ENABLE_RF
RemoteReceiver::disable();
#endif
if (code == MESSAGE_CONNECT_WAITING) {
showStatus();
}
while (network < 3) {
#ifdef DEBUG
if (config.ssid[network].length() > 0) {
if (code == MESSAGE_AUTO_NOSSID) {
Serial.println("[WIFI] No information about the last successful network");
}
WiFi.begin(
(const char *) config.ssid[network].c_str(),
(const char *) config.pass[network].c_str()
);
if (code == MESSAGE_AUTO_CONNECTING) {
Serial.print("[WIFI] Connecting to last successful network: ");
Serial.println(parameter);
}
#ifdef DEBUG
Serial.print(F("[WIFI] Connecting to "));
Serial.println(config.ssid[network]);
#endif
if (code == MESSAGE_AUTO_FAILED) {
Serial.println("[WIFI] Could not connect to last successful network");
}
// Wait
unsigned long timeout = millis() + WIFI_CONNECT_TIMEOUT;
while (timeout > millis()) {
showStatus();
if (WiFi.status() == WL_CONNECTED) break;
delay(100);
if (code == MESSAGE_CONNECTING) {
Serial.print("[WIFI] Connecting to ");
Serial.println(parameter);
} }
}
if (code == MESSAGE_CONNECT_WAITING) {
//
}
if (WiFi.status() == WL_CONNECTED) break;
network++;
if (code == MESSAGE_CONNECT_FAILED) {
Serial.print("[WIFI] Could not connect to ");
Serial.println(parameter);
}
}
if (code == MESSAGE_CONNECTED) {
Serial.print("[WIFI] Connected to ");
Serial.print(jw.getNetwork());
Serial.print(" with IP ");
Serial.println(jw.getIP());
}
#if ENABLE_RF
RemoteReceiver::enable();
#endif
if (code == MESSAGE_DISCONNECTED) {
Serial.println("[WIFI] Disconnected");
}
if (WiFi.status() == WL_CONNECTED) {
if (code == MESSAGE_ACCESSPOINT_CREATING) {
Serial.println("[WIFI] Creating access point");
}
WiFi.setAutoConnect(true);
status = WIFI_STATUS_CONNECTED;
if (code == MESSAGE_ACCESSPOINT_CREATED) {
Serial.print("[WIFI] Access point created with SSID ");
Serial.print(jw.getNetwork());
Serial.print(" and IP ");
Serial.println(jw.getIP());
}
#ifdef DEBUG
Serial.print(F("[WIFI] STATION Mode, SSID: "));
Serial.print(WiFi.SSID());
Serial.print(F(", IP address: "));
Serial.println(WiFi.localIP());
#endif
if (code == MESSAGE_ACCESSPOINT_FAILED) {
Serial.println("[WIFI] Could not create access point");
}
#if ENABLE_NOFUSS
NoFUSSClient.handle();
#endif #endif
} else {
#ifdef DEBUG
Serial.println(F("[WIFI] Not connected"));
#endif
});
}
} }
void wifiSetup(bool force) {
if (force || (WiFi.status() != WL_CONNECTED)) {
wifiSetupSTA();
if (WiFi.status() != WL_CONNECTED) wifiSetupAP();
}
bool wifiAP() {
//jw.disconnect();
return jw.startAP((char *) config.hostname.c_str(), (char *) ADMIN_PASS);
} }
void wifiLoop() { void wifiLoop() {
static unsigned long last_check = 0;
jw.loop();
// Check disconnection // Check disconnection
if ((status == WIFI_STATUS_CONNECTED) && (WiFi.status() != WL_CONNECTED)) {
status = WIFI_STATUS_CONNECTING;
}
if ((!jw.connected()) && (jw.getMode() != MODE_ACCESS_POINT)) {
// If not connected (either AP or STA) try to reconnect every WIFI_RECONNECT_DELAY
if (status == WIFI_STATUS_CONNECTING) {
if ((millis() - last_check) > WIFI_RECONNECT_DELAY) {
wifiSetup(false);
last_check = millis();
WiFi.printDiag(Serial);
// Set networks
jw.cleanNetworks();
jw.addNetwork((char *) config.ssid[0].c_str(), (char *) config.pass[0].c_str());
jw.addNetwork((char *) config.ssid[1].c_str(), (char *) config.pass[1].c_str());
jw.addNetwork((char *) config.ssid[2].c_str(), (char *) config.pass[2].c_str());
// Connecting
if (!jw.autoConnect()) {
if (!jw.connect()) {
if (!wifiAP()) {
#ifdef DEBUG
Serial.println("[WIFI] Could not start any wifi interface!");
#endif
}
}
} }
} }
} }
@ -801,7 +795,9 @@ void wifiLoop() {
#if ENABLE_POWER #if ENABLE_POWER
power.setCurrentRatio(config.pwCurrentRatio.toFloat()); power.setCurrentRatio(config.pwCurrentRatio.toFloat());
#endif #endif
wifiSetup(true);
// Disconnect from current WIFI network, wifiLoop will take care of the reconnection
jw.disconnect();
} }
@ -1145,7 +1141,7 @@ void hardwareLoop() {
if (button1.loop()) { if (button1.loop()) {
if (button1.getEvent() == EVENT_SINGLE_CLICK) toggleRelay(); if (button1.getEvent() == EVENT_SINGLE_CLICK) toggleRelay();
if (button1.getEvent() == EVENT_LONG_CLICK) wifiSetupAP();
if (button1.getEvent() == EVENT_LONG_CLICK) wifiAP();
if (button1.getEvent() == EVENT_DOUBLE_CLICK) ESP.reset(); if (button1.getEvent() == EVENT_DOUBLE_CLICK) ESP.reset();
} }
@ -1185,12 +1181,12 @@ void welcome() {
Serial.println(getIdentifier()); Serial.println(getIdentifier());
Serial.print(F("Last reset reason: ")); Serial.print(F("Last reset reason: "));
Serial.println(ESP.getResetReason()); Serial.println(ESP.getResetReason());
Serial.print(F("Free heap: "));
Serial.print(ESP.getFreeHeap());
Serial.println(F(" bytes"));
Serial.print(F("Memory size: ")); Serial.print(F("Memory size: "));
Serial.print(ESP.getFlashChipSize()); Serial.print(ESP.getFlashChipSize());
Serial.println(F(" bytes")); Serial.println(F(" bytes"));
Serial.print(F("Free heap: "));
Serial.print(ESP.getFreeHeap());
Serial.println(F(" bytes"));
FSInfo fs_info; FSInfo fs_info;
if (SPIFFS.info(fs_info)) { if (SPIFFS.info(fs_info)) {
Serial.print(F("File system total size: ")); Serial.print(F("File system total size: "));
@ -1216,9 +1212,7 @@ void setup() {
// configuration interface // configuration interface
config.hostname = getIdentifier(); config.hostname = getIdentifier();
wifi_station_set_hostname((char *) config.hostname.c_str()); wifi_station_set_hostname((char *) config.hostname.c_str());
// I am handling first connection in the loop
//wifiSetup(false);
wifiSetup();
#if ENABLE_OTA #if ENABLE_OTA
OTASetup(); OTASetup();


Loading…
Cancel
Save