From 88de7f51d08269207ed160c6b2d51764f519669f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Thu, 6 Oct 2016 11:53:58 +0200 Subject: [PATCH] Complete update --- .gitignore | 8 +- .gitmodules | 3 + code/deploy | 9 +- code/gulpfile.js | 73 +++++++++-- code/html/custom.css | 3 +- code/html/custom.js | 106 +++++++++------- code/html/fsversion | 2 +- code/html/index.html | 71 ++--------- code/lib/JustWifi | 1 + code/lib/JustWifi/JustWifi.cpp | 214 -------------------------------- code/lib/JustWifi/JustWifi.h | 99 --------------- code/main | 1 + code/package.json | 11 +- code/pio_hooks.py | 28 +++++ code/platformio.ini | 115 ++++++----------- code/src/button.ino | 2 +- code/src/debug.h | 5 + code/src/defaults.h | 73 +++++++---- code/src/dht.ino | 78 ++++++------ code/src/emon.ino | 14 ++- code/src/main.ino | 143 ++++++++------------- code/src/mqtt.ino | 117 ++++++++---------- code/src/ntp.ino | 44 +++++++ code/src/ota.ino | 35 ++---- code/src/relay.ino | 10 +- code/src/rf.ino | 46 ++++--- code/src/settings.ino | 8 +- code/src/version.h | 2 +- code/src/webserver.ino | 117 +++--------------- code/src/websockets.ino | 107 ++++++++++++++++ code/src/wifi.ino | 218 ++++++++++++++++----------------- 31 files changed, 746 insertions(+), 1017 deletions(-) create mode 160000 code/lib/JustWifi delete mode 100644 code/lib/JustWifi/JustWifi.cpp delete mode 100644 code/lib/JustWifi/JustWifi.h create mode 120000 code/main create mode 100644 code/pio_hooks.py create mode 100644 code/src/debug.h create mode 100644 code/src/ntp.ino create mode 100644 code/src/websockets.ino diff --git a/.gitignore b/.gitignore index 439d23ef..ea2be86c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,12 @@ *.b#? .modgit firmware* -.pioenvs +*.gch +.pio* +.clang_complete +.gcc-flags.json .sconsign.dblite +credentials.h +.build node_modules +code/data diff --git a/.gitmodules b/.gitmodules index 96388f4d..087a1c97 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "code/vendor/RemoteSwitch-arduino-library"] path = code/vendor/RemoteSwitch-arduino-library url = https://github.com/jccprj/RemoteSwitch-arduino-library +[submodule "code/lib/JustWifi"] + path = code/lib/JustWifi + url = https://bitbucket.org/xoseperez/justwifi diff --git a/code/deploy b/code/deploy index d80f4b65..b98f1dec 100755 --- a/code/deploy +++ b/code/deploy @@ -21,7 +21,7 @@ MQTT_HOST=192.168.1.10 function help() { - echo "Syntax: $0 " + echo "Syntax: $0 " devices } @@ -40,14 +40,15 @@ function valid_ip() { } # Check arguments -if [ "$#" -ne 1 ]; then +if [ "$#" -ne 2 ]; then help exit 1 fi device=$1-device +target=$2 # Get IP -topic=`cat platformio.ini | grep $device -A 10 | grep "topic" | cut -d' ' -f3` +topic=`cat platformio.ini | grep $device -A 2 | grep "topic" | cut -d' ' -f3` if [ "$topic" == "" ]; then echo "Unknown device $device or topic not defined" devices @@ -60,4 +61,4 @@ if valid_ip $ip; then exit 3 fi -platformio run -vv -e $device --target upload --upload-port $ip +platformio run -vv -e $device --target $target --upload-port $ip diff --git a/code/gulpfile.js b/code/gulpfile.js index f127089d..77056eca 100644 --- a/code/gulpfile.js +++ b/code/gulpfile.js @@ -1,16 +1,43 @@ -var gulp = require('gulp'); -var plumber = require('gulp-plumber'); -var htmlmin = require('gulp-htmlmin'); -var cleancss = require('gulp-clean-css'); -var uglify = require('gulp-uglify'); -var gzip = require('gulp-gzip'); -var del = require('del'); -var useref = require('gulp-useref'); -var gulpif = require('gulp-if'); +/* + +ESP8266 file system builder + +Copyright (C) 2016 by Xose Pérez + +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 . + +*/ + +// ----------------------------------------------------------------------------- +// File system builder +// ----------------------------------------------------------------------------- + +const gulp = require('gulp'); +const plumber = require('gulp-plumber'); +const htmlmin = require('gulp-htmlmin'); +const cleancss = require('gulp-clean-css'); +const uglify = require('gulp-uglify'); +const gzip = require('gulp-gzip'); +const del = require('del'); +const useref = require('gulp-useref'); +const gulpif = require('gulp-if'); +const inline = require('gulp-inline'); /* Clean destination folder */ gulp.task('clean', function() { - return del(['data/*']); + del(['data/*']); + return true; }); /* Copy static files */ @@ -22,6 +49,26 @@ gulp.task('files', function() { .pipe(gulp.dest('data/')); }); + +/* Process HTML, CSS, JS --- INLINE --- */ +gulp.task('inline', function() { + return gulp.src('html/*.html') + .pipe(inline({ + base: 'html/', + js: uglify, + css: cleancss, + disabledTypes: ['svg', 'img'] + })) + .pipe(htmlmin({ + collapseWhitespace: true, + removeComments: true, + minifyCSS: true, + minifyJS: true + })) + .pipe(gzip()) + .pipe(gulp.dest('data')); +}) + /* Process HTML, CSS, JS */ gulp.task('html', function() { return gulp.src('html/*.html') @@ -39,5 +86,7 @@ gulp.task('html', function() { .pipe(gulp.dest('data')); }); -/* Default Task */ -gulp.task('default', ['clean', 'files', 'html']); +/* Build file system */ +gulp.task('buildfs', ['clean', 'files', 'html']); +gulp.task('buildfs2', ['clean', 'files', 'inline']); +gulp.task('default', ['buildfs']); diff --git a/code/html/custom.css b/code/html/custom.css index b4536cb6..a83594ce 100644 --- a/code/html/custom.css +++ b/code/html/custom.css @@ -51,9 +51,10 @@ div.hint { margin-top: -5px; } .iPhoneCheckContainer { + margin-top: -10px; letter-spacing: 0em; height: 36px; } .iPhoneCheckHandle { - top: 8px; + top: 9px; } diff --git a/code/html/custom.js b/code/html/custom.js index 7abcd05f..9e69cb8a 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -1,12 +1,11 @@ -var update_timer = null; -var relaySlider; +var websock; function doUpdate() { var self = $(this); self.addClass("loading"); $.ajax({ 'method': 'POST', - 'url': '/post', + 'url': '/save', 'dataType': 'json', 'data': $("#formSave").serializeArray() }).done(function(data) { @@ -28,16 +27,31 @@ function toggleMenu() { $("#menuLink").toggleClass('active'); } -function parseResponse(data) { +function processData(data) { // pre-process - if ("network" in data) data.network = data.network.toUpperCase(); - if ("mqttStatus" in data) data.mqttStatus = data.mqttStatus ? "CONNECTED" : "NOT CONNECTED"; + if ("network" in data) { + data.network = data.network.toUpperCase(); + } + if ("mqttStatus" in data) { + data.mqttStatus = data.mqttStatus ? "CONNECTED" : "NOT CONNECTED"; + } // relay if ("relayStatus" in data) { $("input[name='relayStatus']") .prop("checked", data.relayStatus) + .iphoneStyle({ + checkedLabel: 'ON', + uncheckedLabel: 'OFF', + onChange: function(elem, value) { + $.ajax({ + 'method': 'GET', + 'url': value ? '/relay/on' : '/relay/off', + 'dataType': 'json' + }); + } + }) .iphoneStyle("refresh"); } @@ -49,8 +63,30 @@ function parseResponse(data) { // automatic assign Object.keys(data).forEach(function(key) { - var id = "input[name=" + key + "]"; - if ($(id).length) $(id).val(data[key]); + + // Look for INPUTs + var element = $("input[name=" + key + "]"); + if (element.length > 0) { + if (element.attr('type') == 'checkbox') { + element.prop("checked", data[key] == 1) + .iphoneStyle({ + resizeContainer: false, + resizeHandle: false, + checkedLabel: 'ON', + uncheckedLabel: 'OFF' + }) + .iphoneStyle("refresh"); + } else { + element.val(data[key]); + } + } + + // Look for SELECTs + var element = $("select[name=" + key + "]"); + if (element.length > 0) { + element.val(data[key]); + } + }); // WIFI @@ -63,46 +99,32 @@ function parseResponse(data) { }); }; - if ("updateInterval" in data) { - if (update_timer) clearInterval(update_timer); - if (data.updateInterval > 0) { - update_timer = setInterval(update, data.updateInterval); - } - } - } -function update() { - $.ajax({ - 'method': 'GET', - 'url': '/status', - 'dataType': 'json' - }).done(parseResponse); +function getJson(str) { + try { + return JSON.parse(str); + } catch (e) { + return false; + } } function init() { - $.ajax({ - 'method': 'GET', - 'url': '/get', - 'dataType': 'json' - }).done(parseResponse); -} -$(function() { $("#menuLink").on('click', toggleMenu); $(".button-update").on('click', doUpdate); $(".pure-menu-link").on('click', showPanel); - relaySlider = $('#relayStatus').iphoneStyle({ - checkedLabel: 'ON', - uncheckedLabel: 'OFF', - onChange: function(elem, value) { - $.ajax({ - 'method': 'GET', - 'url': value ? '/relay/on' : '/relay/off', - 'dataType': 'json' - }); - setTimeout(update, 200); - } - }); - init(); -}); + + var host = window.location.hostname; + websock = new WebSocket('ws://' + host + ':81/'); + websock.onopen = function(evt) {}; + websock.onclose = function(evt) {}; + websock.onerror = function(evt) {}; + websock.onmessage = function(evt) { + var data = getJson(evt.data); + if (data) processData(data); + }; + +} + +$(init); diff --git a/code/html/fsversion b/code/html/fsversion index c81aa44a..e3e18070 100644 --- a/code/html/fsversion +++ b/code/html/fsversion @@ -1 +1 @@ -0.9.7 +0.9.8 diff --git a/code/html/index.html b/code/html/index.html index e337c69b..8892db9a 100644 --- a/code/html/index.html +++ b/code/html/index.html @@ -44,10 +44,6 @@ MQTT -
  • - RF -
  • -
  • POWER
  • @@ -87,42 +83,42 @@
    - +
    - +
    - +
    - +
    - - + +
    - - + +
    - - + +
    - - +
    +
    @@ -137,7 +133,7 @@

    WIFI

    -

    You can configure up to 3 different WiFi networks. The device will try to connect to any of them starting with the first one.

    +

    You can configure up to 3 different WiFi networks. The device will try to connect in order of signal strength.

    @@ -233,46 +229,6 @@
    -
    - -
    -

    RADIO

    -

    - Configure your radio channel and device ID. -

    -
    - -
    - -
    - -
    - -
    - -
    This is the 5 bits code (0-31) you define on your remote, usually from a DIP switch.
    - -
    - -
    - -
    This is the button in your remote that will trigger the switch
    - -
    - -
    - -
    -
    - -
    -
    @@ -311,7 +267,6 @@
    - diff --git a/code/lib/JustWifi b/code/lib/JustWifi new file mode 160000 index 00000000..012b9773 --- /dev/null +++ b/code/lib/JustWifi @@ -0,0 +1 @@ +Subproject commit 012b9773add97ba5675b62e70f14164a38024010 diff --git a/code/lib/JustWifi/JustWifi.cpp b/code/lib/JustWifi/JustWifi.cpp deleted file mode 100644 index 19b8a551..00000000 --- a/code/lib/JustWifi/JustWifi.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - -JustWifi - -Wifi Manager for ESP8266 - -Copyright (C) 2016 by Xose Pérez - -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 . - -*/ - -#include "JustWifi.h" -#include - -bool JustWifi::connected() { - return (WiFi.status() == WL_CONNECTED); -} - -bool JustWifi::autoConnect() { - - unsigned long timeout; - - // Return if already connected - if (connected()) return true; - - // Try to connect to last successful network - if (WiFi.SSID().length() > 0) { - - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - - _doCallback(MESSAGE_AUTO_CONNECTING, (char *) WiFi.SSID().c_str()); - WiFi.mode(WIFI_STA); - WiFi.begin(); - - // Check connection with timeout - timeout = millis(); - while (millis() - timeout < _connect_timeout) { - _doCallback(MESSAGE_CONNECT_WAITING); - if (WiFi.status() == WL_CONNECTED) break; - delay(100); - } - - 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++) { - - // Skip if no SSID defined - if (_network[i].ssid.length() == 0) continue; - - // 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); -} diff --git a/code/lib/JustWifi/JustWifi.h b/code/lib/JustWifi/JustWifi.h deleted file mode 100644 index 985254c9..00000000 --- a/code/lib/JustWifi/JustWifi.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - -JustWifi - -Wifi Manager for ESP8266 - -Copyright (C) 2016 by Xose Pérez - -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 . - -*/ - -#ifndef JustWifi_h -#define JustWifi_h - -#include -#include - -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 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 diff --git a/code/main b/code/main new file mode 120000 index 00000000..e8310385 --- /dev/null +++ b/code/main @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/code/package.json b/code/package.json index 0ff1e23e..c31f55be 100644 --- a/code/package.json +++ b/code/package.json @@ -3,13 +3,8 @@ "version": "0.1.0", "description": "Gulp based build system for ESP8266 file system files", "main": "gulpfile.js", - "repository": { - "type": "git", - "url": "" - }, "author": "Xose Pérez ", - "license": "MIT", - "homepage": "", + "license": "GPL-3.0", "devDependencies": { "del": "^2.2.1", "gulp": "^3.9.1", @@ -17,9 +12,11 @@ "gulp-gzip": "^1.4.0", "gulp-htmlmin": "^2.0.0", "gulp-if": "^2.0.1", + "gulp-inline": "^0.1.1", "gulp-plumber": "^1.1.0", "gulp-uglify": "^1.5.3", - "gulp-useref": "^3.1.2" + "gulp-useref": "^3.1.2", + "yargs": "^5.0.0" }, "dependencies": {} } diff --git a/code/pio_hooks.py b/code/pio_hooks.py new file mode 100644 index 00000000..593fb6f7 --- /dev/null +++ b/code/pio_hooks.py @@ -0,0 +1,28 @@ +#!/bin/python + +import subprocess +import socket +from SCons.Script import DefaultEnvironment +env = DefaultEnvironment() + +def is_valid_ip(ip): + try: + socket.inet_aton(ip) + return True + except socket.error: + return False + +def before_build_spiffs(source, target, env): + env.Execute("gulp buildfs2") + +def before_upload(source, target, env): + upload_port = env.get('UPLOAD_PORT', False) + if upload_port and upload_port[0] == '/': + cmd = ["mosquitto_sub", "-t", upload_port, "-h", "192.168.1.10", "-N", "-C", "1"] + ip = subprocess.check_output(cmd) + if is_valid_ip(ip): + env['UPLOAD_PORT'] = '"' + ip + '"' + +#env.AddPreAction("uploadfs", before_upload) +#env.AddPreAction("upload", before_upload) +env.AddPreAction(".pioenvs/%s/spiffs.bin" % env['PIOENV'], before_build_spiffs) diff --git a/code/platformio.ini b/code/platformio.ini index a83933ee..27399c2f 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -1,111 +1,66 @@ -[env:sonoff-debug] -platform = espressif -framework = arduino -board = esp01_1m -lib_install = 89,64,19 -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SONOFF -D DEBUG +[platformio] +env_default = node-debug -[env:sonoff-debug-ota] -platform = espressif +[common] +platform = espressif8266 framework = arduino -board = esp01_1m -lib_install = 89,64,19 -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SONOFF -D DEBUG +lib_install = 19,44,64,89,549,727 +extra_script = pio_hooks.py + +[ota] upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 +[env:sonoff-debug] +include = common +board = esp01_1m +build_flags = -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DSONOFF + +[env:sonoff-debug-ota] +include = env:sonoff-debug,ota + [env:slampher-debug] -platform = espressif -framework = arduino +include = common board = esp01_1m -lib_install = 89,64,19 -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SLAMPHER -D DEBUG +build_flags = -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DSLAMPHER [env:slampher-debug-ota] -platform = espressif -framework = arduino -board = esp01_1m -lib_install = 89,64,19 -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SLAMPHER -D DEBUG -upload_speed = 115200 -upload_port = "192.168.4.1" -upload_flags = --auth=fibonacci --port 8266 +include = env:slampher-debug,ota [env:s20-debug] -platform = espressif -framework = arduino +include = common board = esp01_1m -lib_install = 89,64,19 -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D S20 -D DEBUG +build_flags = -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DS20 [env:s20-debug-ota] -platform = espressif -framework = arduino -board = esp01_1m -lib_install = 89,64,19 -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D S20 -D DEBUG -upload_speed = 115200 -upload_port = "192.168.4.1" -upload_flags = --auth=fibonacci --port 8266 +include = env:s20-debug,ota [env:node-debug] -platform = espressif -framework = arduino +include = common board = nodemcuv2 -lib_install = 89,64,19 -build_flags = -D NODEMCUV2 -D DEBUG +build_flags = -DNODEMCUV2 -DDEBUG_PORT=Serial [env:node-debug-ota] -platform = espressif -framework = arduino -board = nodemcuv2 -lib_install = 89,64,19 -build_flags = -D NODEMCUV2 -D DEBUG -upload_speed = 115200 -upload_port = "192.168.4.1" -upload_flags = --auth=fibonacci --port 8266 +include = env:node-debug,ota + + +[env:ac-device] +topic = /home/cellar/airconditioner/ip +include = env:s20-debug-ota + [env:washer-device] -platform = espressif -framework = arduino -board = esp01_1m -lib_install = 89,64,19 topic = /home/cellar/washer/ip -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SONOFF -D DEBUG -D ENABLE_EMON -D ENABLE_DHT -upload_speed = 115200 -upload_port = "192.168.1.114" -upload_flags = --auth=fibonacci --port 8266 +include = env:sonoff-debug-ota +build_flags = -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DSONOFF -DENABLE_EMON=1 -DENABLE_DHT=1 [env:studio-lamp-device] -platform = espressif -framework = arduino -board = esp01_1m -lib_install = 89,64,19 topic = /home/studio/lamp/ip -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SONOFF -D DEBUG -upload_speed = 115200 -upload_port = "192.168.1.114" -upload_flags = --auth=fibonacci --port 8266 +include = env:sonoff-debug-ota [env:living-lamp-device] -platform = espressif -framework = arduino -board = esp01_1m -lib_install = 89,64,19 topic = /home/living/lamp/ip -build_flags = -Wl,-Tesp8266.flash.1m256.ld -build_flags = -D SONOFF -D DEBUG -D RF -upload_speed = 115200 -upload_port = "192.168.1.114" -upload_flags = --auth=fibonacci --port 8266 +include = env:sonoff-debug-ota diff --git a/code/src/button.ino b/code/src/button.ino index 3aa0d981..6c6ea59f 100644 --- a/code/src/button.ino +++ b/code/src/button.ino @@ -22,7 +22,7 @@ void buttonSetup() { void buttonLoop() { if (button1.loop()) { if (button1.getEvent() == EVENT_SINGLE_CLICK) toggleRelay(); - if (button1.getEvent() == EVENT_LONG_CLICK) wifiAP(); + if (button1.getEvent() == EVENT_LONG_CLICK) createAP(); if (button1.getEvent() == EVENT_DOUBLE_CLICK) ESP.reset(); } } diff --git a/code/src/debug.h b/code/src/debug.h new file mode 100644 index 00000000..65568950 --- /dev/null +++ b/code/src/debug.h @@ -0,0 +1,5 @@ +#ifdef DEBUG_PORT + #define DEBUG_MSG(...) DEBUG_PORT.printf( __VA_ARGS__ ) +#else + #define DEBUG_MSG(...) +#endif diff --git a/code/src/defaults.h b/code/src/defaults.h index a46fa537..a0dff926 100644 --- a/code/src/defaults.h +++ b/code/src/defaults.h @@ -1,5 +1,9 @@ -// Managed from platformio.ini -//#define DEBUG +//------------------------------------------------------------------------------ +// SET BY PLATFORMIO +//------------------------------------------------------------------------------ + +//#define DEBUG_PORT Serial + //#define ESPURNA //#define SONOFF //#define SLAMPHER @@ -8,9 +12,14 @@ //#define ENABLE_NOFUSS 1 //#define ENABLE_EMON 1 -//#define ENABLE_RF 1 //#define ENABLE_DHT 1 +//#define ENABLE_RF 1 + +// ----------------------------------------------------------------------------- +// HARDWARE +// ----------------------------------------------------------------------------- +#define SERIAL_BAUDRATE 115200 #define BUTTON_PIN 0 #define RELAY_PIN 12 @@ -41,28 +50,30 @@ #ifdef NODEMCUV2 #define MANUFACTURER "NODEMCU" #define DEVICE "LOLIN" - #define LED_PIN 4 + #define LED_PIN 2 #endif -#define AP_PASS "fibonacci" - -#define OTA_PASS "fibonacci" -#define OTA_PORT 8266 - +#define HOSTNAME DEVICE #define BUFFER_SIZE 1024 -#define STATUS_UPDATE_INTERVAL 10000 -#define HEARTBEAT_INTERVAL 60000 +#define HEARTBEAT_INTERVAL 300000 #define FS_VERSION_FILE "/fsversion" -#define WIFI_MAX_NETWORKS 3 -#define WIFI_RECONNECT_INTERVAL 300000 -#define RF_PIN 14 +// ----------------------------------------------------------------------------- +// WIFI +// ----------------------------------------------------------------------------- -#define DHT_PIN 14 -#define DHT_UPDATE_INTERVAL 300000 -#define DHT_TYPE DHT22 -#define DHT_TIMING 11 +#define WIFI_RECONNECT_INTERVAL 300000 +#define WIFI_MAX_NETWORKS 3 +#define AP_PASS "fibonacci" +#define OTA_PASS "fibonacci" +#define OTA_PORT 8266 +#define NOFUSS_SERVER "http://192.168.1.100" +#define NOFUSS_INTERVAL 3600000 + +// ----------------------------------------------------------------------------- +// MQTT +// ----------------------------------------------------------------------------- #define MQTT_SERVER "192.168.1.100" #define MQTT_PORT 1883 @@ -74,16 +85,31 @@ #define MQTT_VERSION_TOPIC "/version" #define MQTT_FSVERSION_TOPIC "/fsversion" #define MQTT_HEARTBEAT_TOPIC "/heartbeat" -#define MQTT_POWER_TOPIC "/power" -#define MQTT_TEMPERATURE_TOPIC "/temperature" -#define MQTT_HUMIDITY_TOPIC "/humidity" -#define NOFUSS_SERVER "http://192.168.1.100" -#define NOFUSS_INTERVAL 600000 +// ----------------------------------------------------------------------------- +// NTP +// ----------------------------------------------------------------------------- +#define NTP_SERVER "pool.ntp.org" +#define NTP_TIME_OFFSET 1 +#define NTP_DAY_LIGHT true +#define NTP_UPDATE_INTERVAL 1800 + +//-------------------------------------------------------------------------------- +// DRIVERS +//-------------------------------------------------------------------------------- + +#define RF_PIN 14 #define RF_CHANNEL 31 #define RF_DEVICE 1 +#define DHT_PIN 14 +#define DHT_UPDATE_INTERVAL 300000 +#define DHT_TYPE DHT22 +#define DHT_TIMING 11 +#define DHT_TEMPERATURE_TOPIC "/temperature" +#define DHT_HUMIDITY_TOPIC "/humidity" + #define EMON_CURRENT_PIN 0 #define EMON_SAMPLES 1000 #define EMON_INTERVAL 10000 @@ -94,3 +120,4 @@ #define EMON_CURRENT_OFFSET 0.25 #define EMON_MAINS_VOLTAGE 230 #define EMON_CURRENT_RATIO 180 +#define EMON_POWER_TOPIC "/power" diff --git a/code/src/dht.ino b/code/src/dht.ino index 0de07b73..94e2414d 100644 --- a/code/src/dht.ino +++ b/code/src/dht.ino @@ -9,63 +9,57 @@ Copyright (C) 2016 by Xose Pérez #if ENABLE_DHT - #include "DHT.h" + #include DHT dht(DHT_PIN, DHT_TYPE, DHT_TIMING); - double temperature; - double humidity; // ----------------------------------------------------------------------------- // DHT // ----------------------------------------------------------------------------- - double getTemperature() { - return temperature; - } - - double getHumidity() { - return humidity; - } - void dhtSetup() { dht.begin(); } void dhtLoop() { - static unsigned long last_check = 0; if (!mqttConnected()) return; - if ((last_check > 0) && ((millis() - last_check) < DHT_UPDATE_INTERVAL)) return; - last_check = millis(); - - char buffer[10]; - - temperature = dht.readTemperature(); - if (isnan(temperature)) { - #ifdef DEBUG - Serial.println(F("[DHT] Error reading temperature")); - #endif - } else { - dtostrf(temperature, 4, 1, buffer); - mqttSend((char *) MQTT_TEMPERATURE_TOPIC, buffer); - #ifdef DEBUG - Serial.print(F("[DHT] Temperature: ")); - Serial.println(temperature); - #endif - } - humidity = dht.readHumidity(); - if (isnan(humidity)) { - #ifdef DEBUG - Serial.println(F("[DHT] Error reading humidity")); - #endif - } else { - dtostrf(humidity, 4, 1, buffer); - mqttSend((char *) MQTT_HUMIDITY_TOPIC, buffer); - #ifdef DEBUG - Serial.print(F("[DHT] Humidity: ")); - Serial.println(humidity); - #endif + // Check if we should read new data + static unsigned long last_update = 0; + if ((millis() - last_update > DHT_UPDATE_INTERVAL) || (last_update == 0)) { + last_update = millis(); + + // Read sensor data + double h = dht.readHumidity(); + double t = dht.readTemperature(); + + // Check if readings are valid + if (isnan(h) || isnan(t)) { + + DEBUG_MSG("[DHT] Error reading sensor\n"); + + } else { + + char temperature[6]; + char humidity[6]; + dtostrf(t, 4, 1, temperature); + itoa((int) h, humidity, 10); + + DEBUG_MSG("[DHT] Temperature: %s\n", temperature); + DEBUG_MSG("[DHT] Humidity: %s\n", humidity); + + // Send MQTT messages + mqttSend((char *) getSetting("dhtTemperatureTopic", DHT_TEMPERATURE_TOPIC).c_str(), temperature); + mqttSend((char *) getSetting("dhtHumidityTopic", DHT_HUMIDITY_TOPIC).c_str(), humidity); + + // Update websocket clients + char buffer[20]; + sprintf_P(buffer, PSTR("{\"temperature\": %s, \"humidity\": %s}"), temperature, humidity); + webSocketSend(buffer); + + } + } } diff --git a/code/src/emon.ino b/code/src/emon.ino index 9bae8611..99e8b571 100644 --- a/code/src/emon.ino +++ b/code/src/emon.ino @@ -71,17 +71,19 @@ Copyright (C) 2016 by Xose Pérez float mainsVoltage = getSetting("pwMainsVoltage", String(EMON_MAINS_VOLTAGE)).toFloat(); - #ifdef DEBUG - Serial.print(F("[ENERGY] Power now: ")); - Serial.print(int(current * mainsVoltage)); - Serial.println(F("W")); - #endif + //DEBUG_MSG("[ENERGY] Power now: %dW\n", int(current * mainsVoltage)); + // Update websocket clients + char text[20]; + sprintf_P(text, PSTR("{\"power\": %d}"), int(current * mainsVoltage)); + webSocketSend(text); + + // Send MQTT messages averaged every EMON_MEASUREMENTS if (measurements == EMON_MEASUREMENTS) { char buffer[8]; double power = (sum - max - min) * mainsVoltage / (measurements - 2); sprintf(buffer, "%d", int(power)); - mqttSend((char *) MQTT_POWER_TOPIC, buffer); + mqttSend((char *) getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), buffer); sum = 0; measurements = 0; } diff --git a/code/src/main.ino b/code/src/main.ino index 35e40f1b..fd30e3c5 100644 --- a/code/src/main.ino +++ b/code/src/main.ino @@ -19,48 +19,22 @@ along with this program. If not, see . */ #include -#include "version.h" #include "defaults.h" -#include "FS.h" - -String getSetting(const String& key, String defaultValue = ""); +#include "version.h" +#include "debug.h" // ----------------------------------------------------------------------------- -// Methods +// PROTOTYPES // ----------------------------------------------------------------------------- -void getCompileTime(char * buffer) { - - int day, month, year, hour, minute, second; - - // parse date - String tmp = String(__DATE__); - day = tmp.substring(4,6).toInt(); - year = tmp.substring(7).toInt(); - tmp = tmp.substring(0,3); - if (tmp.equals("Jan")) month = 1; - if (tmp.equals("Feb")) month = 2; - if (tmp.equals("Mar")) month = 3; - if (tmp.equals("Apr")) month = 4; - if (tmp.equals("May")) month = 5; - if (tmp.equals("Jun")) month = 6; - if (tmp.equals("Jul")) month = 7; - if (tmp.equals("Aug")) month = 8; - if (tmp.equals("Sep")) month = 9; - if (tmp.equals("Oct")) month = 10; - if (tmp.equals("Nov")) month = 11; - if (tmp.equals("Dec")) month = 12; - - // parse time - tmp = String(__TIME__); - hour = tmp.substring(0,2).toInt(); - minute = tmp.substring(3,5).toInt(); - second = tmp.substring(6,8).toInt(); - - sprintf(buffer, "%d%02d%02d%02d%02d%02d", year, month, day, hour, minute, second); - buffer[14] = 0; +#include +#include +#include "FS.h" +String getSetting(const String& key, String defaultValue = ""); -} +// ----------------------------------------------------------------------------- +// METHODS +// ----------------------------------------------------------------------------- String getIdentifier() { char identifier[20]; @@ -95,9 +69,7 @@ void hardwareSetup() { void getFSVersion(char * buffer) { File h = SPIFFS.open(FS_VERSION_FILE, "r"); if (!h) { - #ifdef DEBUG - Serial.println(F("[SPIFFS] Could not open file system version file.")); - #endif + DEBUG_MSG("[SPIFFS] Could not open file system version file.\n"); strcpy(buffer, APP_VERSION); return; } @@ -112,83 +84,73 @@ void hardwareLoop() { // Heartbeat static unsigned long last_heartbeat = 0; - if (millis() - last_heartbeat > HEARTBEAT_INTERVAL) { - last_heartbeat = millis(); - mqttSend((char *) MQTT_HEARTBEAT_TOPIC, (char *) "1"); - #ifdef DEBUG - Serial.print(F("[BEAT] Free heap: ")); - Serial.println(ESP.getFreeHeap()); - #endif + if (mqttConnected()) { + if ((millis() - last_heartbeat > HEARTBEAT_INTERVAL) || (last_heartbeat == 0)) { + last_heartbeat = millis(); + mqttSend((char *) MQTT_HEARTBEAT_TOPIC, (char *) "1"); + DEBUG_MSG("[BEAT] Free heap: %d\n", ESP.getFreeHeap()); + DEBUG_MSG("[NTP] Time: %s\n", (char *) NTP.getTimeDateString().c_str()); + } } } // ----------------------------------------------------------------------------- -// Booting +// BOOTING // ----------------------------------------------------------------------------- void welcome() { - char buffer[BUFFER_SIZE]; - getCompileTime(buffer); - Serial.println(); - Serial.println(); - Serial.print(APP_NAME); - Serial.print(F(" ")); - Serial.print(APP_VERSION); - Serial.print(F(" built ")); - Serial.println(buffer); - Serial.println(APP_AUTHOR); - Serial.println(APP_WEBSITE); - Serial.println(); - Serial.print(F("Device: ")); - Serial.println(getIdentifier()); - Serial.print(F("Last reset reason: ")); - Serial.println(ESP.getResetReason()); - Serial.print(F("Memory size: ")); - Serial.print(ESP.getFlashChipSize()); - Serial.println(F(" bytes")); - Serial.print(F("Free heap: ")); - Serial.print(ESP.getFreeHeap()); - Serial.println(F(" bytes")); + + delay(2000); + Serial.printf("%s %s\n", (char *) APP_NAME, (char *) APP_VERSION); + Serial.printf("%s\n%s\n\n", (char *) APP_AUTHOR, (char *) APP_WEBSITE); + //Serial.printf("Device: %s\n", (char *) getIdentifier().c_str()); + Serial.printf("ChipID: %06X\n", ESP.getChipId()); + Serial.printf("Last reset reason: %s\n", (char *) ESP.getResetReason().c_str()); + Serial.printf("Memory size: %d bytes\n", ESP.getFlashChipSize()); + Serial.printf("Free heap: %d bytes\n", ESP.getFreeHeap()); FSInfo fs_info; if (SPIFFS.info(fs_info)) { - Serial.print(F("File system total size: ")); - Serial.print(fs_info.totalBytes); - Serial.println(F(" bytes")); - Serial.print(F("File system used size : ")); - Serial.print(fs_info.usedBytes); - Serial.println(F(" bytes")); + Serial.printf("File system total size: %d bytes\n", fs_info.totalBytes); + Serial.printf(" used size : %d bytes\n", fs_info.usedBytes); + Serial.printf(" block size: %d bytes\n", fs_info.blockSize); + Serial.printf(" page size : %d bytes\n", fs_info.pageSize); + Serial.printf(" max files : %d\n", fs_info.maxOpenFiles); + Serial.printf(" max length: %d\n", fs_info.maxPathLength); } - Serial.println(); + Serial.println(); + } void setup() { hardwareSetup(); + buttonSetup(); + + welcome(); + settingsSetup(); setSetting("hostname", String() + getIdentifier()); saveSettings(); - relaySetup(); - delay(2000); - welcome(); - - buttonSetup(); + relaySetup(); wifiSetup(); otaSetup(); mqttSetup(); webServerSetup(); + webSocketSetup(); + ntpSetup(); #if ENABLE_NOFUSS nofussSetup(); #endif - #if ENABLE_RF - rfSetup(); - #endif #if ENABLE_DHT dhtSetup(); #endif + #if ENABLE_RF + rfSetup(); + #endif #if ENABLE_EMON powerMonitorSetup(); #endif @@ -197,28 +159,29 @@ void setup() { void loop() { - wifiLoop(); hardwareLoop(); buttonLoop(); + settingsLoop(); + wifiLoop(); otaLoop(); mqttLoop(); webServerLoop(); + webSocketLoop(); + ntpLoop(); #if ENABLE_NOFUSS nofussLoop(); #endif - #if ENABLE_RF - rfLoop(); - #endif #if ENABLE_DHT dhtLoop(); #endif + #if ENABLE_RF + rfLoop(); + #endif #if ENABLE_EMON powerMonitorLoop(); #endif - settingsLoop(); - delay(1); } diff --git a/code/src/mqtt.ino b/code/src/mqtt.ino index bc54112a..ff3a5bda 100644 --- a/code/src/mqtt.ino +++ b/code/src/mqtt.ino @@ -7,11 +7,12 @@ Copyright (C) 2016 by Xose Pérez */ -#include #include +#include WiFiClient client; PubSubClient mqtt(client); +boolean mqttStatus = false; String mqttTopic; bool isCallbackMessage = false; @@ -34,34 +35,20 @@ void buildTopics() { } void mqttSend(char * topic, char * message) { - if (!mqtt.connected()) return; if (isCallbackMessage) return; - String path = mqttTopic + String(topic); - - #ifdef DEBUG - Serial.print(F("[MQTT] Sending ")); - Serial.print(path); - Serial.print(F(" ")); - Serial.println(message); - #endif - + DEBUG_MSG("[MQTT] Sending %s %s\n", (char *) path.c_str(), message); mqtt.publish(path.c_str(), message, MQTT_RETAIN); - } void mqttCallback(char* topic, byte* payload, unsigned int length) { - #ifdef DEBUG - Serial.print(F("[MQTT] Received ")); - Serial.print(topic); - Serial.print(F(" ")); - for (int i = 0; i < length; i++) { - Serial.print((char)payload[i]); - } - Serial.println(); - #endif + char buffer[length+1]; + memcpy(buffer, payload, length); + buffer[length] = 0; + + DEBUG_MSG("[MQTT] Received %s %s\n", topic, buffer); // Action to perform if ((char)payload[0] == '0') { @@ -75,52 +62,42 @@ void mqttCallback(char* topic, byte* payload, unsigned int length) { if ((char)payload[0] == '2') { toggleRelay(); } - isCallbackMessage = false; + isCallbackMessage = false; } void mqttConnect() { - String mqttServer = getSetting("mqttServer", MQTT_SERVER); - int mqttPort = getSetting("mqttPort", String(MQTT_PORT)).toInt(); - String mqttUser = getSetting("mqttUser"); - String mqttPassword = getSetting("mqttPassword"); - - if (!mqtt.connected() && (mqttServer.length()>0)) { - - mqtt.setServer((const char *) mqttServer.c_str(), mqttPort); - - #ifdef DEBUG - Serial.print(F("[MQTT] Connecting to broker at ")); - Serial.print(mqttServer); - #endif - - if (mqttUser.length() > 0) { - #ifdef DEBUG - Serial.print(F(" as user ")); - Serial.print(mqttUser); - Serial.print(F(": ")); - #endif - mqtt.connect( - getSetting("hostname").c_str(), - (const char *) mqttUser.c_str(), - (const char *) mqttPassword.c_str() - ); + if (!mqtt.connected()) { + + String host = getSetting("mqttServer", MQTT_SERVER); + String port = getSetting("mqttPort", String(MQTT_PORT)); + String user = getSetting("mqttUser"); + String pass = getSetting("mqttPassword"); + + if (host.length() == 0) return; + + DEBUG_MSG("[MQTT] Connecting to broker at %s", (char *) host.c_str()); + mqtt.setServer(host.c_str(), port.toInt()); + + if ((user != "") & (pass != "")) { + DEBUG_MSG(" as user %s: ", (char *) user.c_str()); + mqtt.connect(getSetting("hostname", HOSTNAME).c_str(), user.c_str(), pass.c_str()); } else { - #ifdef DEBUG - Serial.print(F(" anonymously: ")); - #endif - mqtt.connect(getSetting("hostname").c_str()); + DEBUG_MSG(" anonymously: "); + mqtt.connect(getSetting("hostname", HOSTNAME).c_str()); } if (mqtt.connected()) { - #ifdef DEBUG - Serial.println(F("connected!")); - #endif + DEBUG_MSG("connected!\n"); buildTopics(); + mqttStatus = true; + + // Send status via webSocket + webSocketSend((char *) "{\"mqttStatus\": true}"); // Say hello and report our IP and VERSION mqttSend((char *) MQTT_IP_TOPIC, (char *) getIP().c_str()); @@ -133,19 +110,13 @@ void mqttConnect() { mqttSend((char *) MQTT_STATUS_TOPIC, (char *) (digitalRead(RELAY_PIN) ? "1" : "0")); // Subscribe to topic - #ifdef DEBUG - Serial.print(F("[MQTT] Subscribing to ")); - Serial.println(mqttTopic); - #endif + DEBUG_MSG("[MQTT] Subscribing to %s\n", (char *) mqttTopic.c_str()); mqtt.subscribe(mqttTopic.c_str()); } else { - #ifdef DEBUG - Serial.print(F("failed, rc=")); - Serial.println(mqtt.state()); - #endif + DEBUG_MSG("failed (rc=%d)\n", mqtt.state()); } } @@ -157,14 +128,28 @@ void mqttSetup() { } void mqttLoop() { - static unsigned long timeout = millis(); - if (wifiConnected()) { + + static unsigned long lastPeriod = 0; + + if (WiFi.status() == WL_CONNECTED) { + if (!mqtt.connected()) { - if (timeout < millis()) { + + if (mqttStatus) { + webSocketSend((char *) "{\"mqttStatus\": false}"); + mqttStatus = false; + } + + unsigned long currPeriod = millis() / MQTT_RECONNECT_DELAY; + if (currPeriod != lastPeriod) { + lastPeriod = currPeriod; mqttConnect(); - timeout = millis() + MQTT_RECONNECT_DELAY; } + } + if (mqtt.connected()) mqtt.loop(); + } + } diff --git a/code/src/ntp.ino b/code/src/ntp.ino new file mode 100644 index 00000000..a8203523 --- /dev/null +++ b/code/src/ntp.ino @@ -0,0 +1,44 @@ +/* + +RENTALITO +NTP MODULE + +Copyright (C) 2016 by Xose Pérez + +*/ + +#include +#include +#include + +// ----------------------------------------------------------------------------- +// NTP +// ----------------------------------------------------------------------------- + +void ntpConnect(WiFiEventStationModeGotIP ipInfo) { + NTP.begin(NTP_SERVER, NTP_TIME_OFFSET, NTP_DAY_LIGHT); + NTP.setInterval(NTP_UPDATE_INTERVAL); +} + +void ntpSetup() { + + NTP.onNTPSyncEvent([](NTPSyncEvent_t error) { + if (error) { + if (error == noResponse) { + DEBUG_MSG("[NTP] Error: NTP server not reachable\n"); + } else if (error == invalidAddress) { + DEBUG_MSG("[NTP] Error: Invalid NTP server address\n"); + } + } else { + DEBUG_MSG("[NTP] Time: %s\n", (char *) NTP.getTimeDateString(NTP.getLastNTPSync()).c_str()); + } + }); + + static WiFiEventHandler e; + e = WiFi.onStationModeGotIP(ntpConnect); + +} + +void ntpLoop() { + now(); +} diff --git a/code/src/ota.ino b/code/src/ota.ino index 6a577cd5..5138f295 100644 --- a/code/src/ota.ino +++ b/code/src/ota.ino @@ -7,7 +7,6 @@ Copyright (C) 2016 by Xose Pérez */ -#include #include "ArduinoOTA.h" // ----------------------------------------------------------------------------- @@ -17,41 +16,29 @@ Copyright (C) 2016 by Xose Pérez void otaSetup() { ArduinoOTA.setPort(OTA_PORT); - ArduinoOTA.setHostname(getSetting("hostname").c_str()); + ArduinoOTA.setHostname(getSetting("hostname", HOSTNAME).c_str()); ArduinoOTA.setPassword((const char *) OTA_PASS); ArduinoOTA.onStart([]() { - #if ENABLE_RF - rfEnable(false); - #endif - #if DEBUG - Serial.println(F("[OTA] Start")); - #endif + DEBUG_MSG("[OTA] Start\n"); }); ArduinoOTA.onEnd([]() { - #if DEBUG - Serial.println(F("[OTA] End")); - #endif - #if ENABLE_RF - rfEnable(true); - #endif + DEBUG_MSG("\n[OTA] End\n"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - #if DEBUG - Serial.printf("[OTA] Progress: %u%%\r", (progress / (total / 100))); - #endif + DEBUG_MSG("[OTA] Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { - #if DEBUG - Serial.printf("[OTA] Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) Serial.println(F("[OTA] Auth Failed")); - else if (error == OTA_BEGIN_ERROR) Serial.println(F("[OTA] Begin Failed")); - else if (error == OTA_CONNECT_ERROR) Serial.println(F("[OTA] Connect Failed")); - else if (error == OTA_RECEIVE_ERROR) Serial.println(F("[OTA] Receive Failed")); - else if (error == OTA_END_ERROR) Serial.println(F("[OTA] End Failed")); + #if DEBUG_PORT + DEBUG_MSG("\n[OTA] Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) DEBUG_MSG("Auth Failed\n"); + else if (error == OTA_BEGIN_ERROR) DEBUG_MSG("Begin Failed\n"); + else if (error == OTA_CONNECT_ERROR) DEBUG_MSG("Connect Failed\n"); + else if (error == OTA_RECEIVE_ERROR) DEBUG_MSG("Receive Failed\n"); + else if (error == OTA_END_ERROR) DEBUG_MSG("End Failed\n"); #endif }); diff --git a/code/src/relay.ino b/code/src/relay.ino index 614612d7..662f558f 100644 --- a/code/src/relay.ino +++ b/code/src/relay.ino @@ -17,14 +17,13 @@ void switchRelayOn() { if (!digitalRead(RELAY_PIN)) { - #ifdef DEBUG - Serial.println(F("[RELAY] ON")); - #endif + DEBUG_MSG("[RELAY] ON\n"); digitalWrite(RELAY_PIN, HIGH); EEPROM.write(0, 1); EEPROM.commit(); mqttSend((char *) MQTT_STATUS_TOPIC, (char *) "1"); + webSocketSend((char *) "{\"relayStatus\": true}"); } @@ -34,14 +33,13 @@ void switchRelayOff() { if (digitalRead(RELAY_PIN)) { - #ifdef DEBUG - Serial.println(F("[RELAY] OFF")); - #endif + DEBUG_MSG("[RELAY] OFF\n"); digitalWrite(RELAY_PIN, LOW); EEPROM.write(0, 0); EEPROM.commit(); mqttSend((char *) MQTT_STATUS_TOPIC, (char *) "0"); + webSocketSend((char *) "{\"relayStatus\": false}"); } diff --git a/code/src/rf.ino b/code/src/rf.ino index 44e5629e..569e8bb4 100644 --- a/code/src/rf.ino +++ b/code/src/rf.ino @@ -19,20 +19,10 @@ Copyright (C) 2016 by Xose Pérez // RF // ----------------------------------------------------------------------------- - void rfEnable(bool enable) { - if (enable) { - RemoteReceiver::enable(); - } else { - RemoteReceiver::disable(); - } - } - void rfLoop() { + return; if (rfCode == 0) return; - #ifdef DEBUG - Serial.print(F("[RF] Received code: ")); - Serial.println(rfCode); - #endif + DEBUG_MSG("[RF] Received code: %lu\n", rfCode); if (rfCode == rfCodeON) switchRelayOn(); if (rfCode == rfCodeOFF) switchRelayOff(); rfCode = 0; @@ -62,12 +52,8 @@ Copyright (C) 2016 by Xose Pérez rfCodeOFF = code + 2; rfCodeON = code + 6; - #ifdef DEBUG - Serial.print(F("[RF] Code ON: ")); - Serial.println(rfCodeON); - Serial.print(F("[RF] Code OFF: ")); - Serial.println(rfCodeOFF); - #endif + DEBUG_MSG("[RF] Code ON : %lu\n", rfCodeON); + DEBUG_MSG("[RF] Code OFF: %lu\n", rfCodeOFF); } @@ -76,9 +62,33 @@ Copyright (C) 2016 by Xose Pérez } void rfSetup() { + pinMode(RF_PIN, INPUT_PULLUP); rfBuildCodes(); RemoteReceiver::init(RF_PIN, 3, rfCallback); + RemoteReceiver::disable(); + DEBUG_MSG("[RF] Disabled\n"); + + static WiFiEventHandler e1 = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected& event) { + RemoteReceiver::disable(); + DEBUG_MSG("[RF] Disabled\n"); + }); + + static WiFiEventHandler e2 = WiFi.onSoftAPModeStationDisconnected([](const WiFiEventSoftAPModeStationDisconnected& event) { + RemoteReceiver::disable(); + DEBUG_MSG("[RF] Disabled\n"); + }); + + static WiFiEventHandler e3 = WiFi.onStationModeConnected([](const WiFiEventStationModeConnected& event) { + RemoteReceiver::enable(); + DEBUG_MSG("[RF] Enabled\n"); + }); + + static WiFiEventHandler e4 = WiFi.onSoftAPModeStationConnected([](const WiFiEventSoftAPModeStationConnected& event) { + RemoteReceiver::enable(); + DEBUG_MSG("[RF] Enabled\n"); + }); + } #endif diff --git a/code/src/settings.ino b/code/src/settings.ino index 940df7ce..8d8c16d7 100644 --- a/code/src/settings.ino +++ b/code/src/settings.ino @@ -31,9 +31,7 @@ void settingsSetup() { []() {} #endif ); - #if DEBUG - Serial.println("[SETTINGS] Initialized"); - #endif + DEBUG_MSG("[SETTINGS] Initialized\n"); } void settingsLoop() { @@ -55,9 +53,7 @@ bool delSetting(const String& key) { } void saveSettings() { - #if DEBUG - Serial.println("[SETTINGS] Saving"); - #endif + DEBUG_MSG("[SETTINGS] Saving\n"); #if not AUTO_SAVE EEPROM.commit(); #endif diff --git a/code/src/version.h b/code/src/version.h index bfce3233..63d924f3 100644 --- a/code/src/version.h +++ b/code/src/version.h @@ -1,4 +1,4 @@ #define APP_NAME "Espurna" -#define APP_VERSION "0.9.7" +#define APP_VERSION "0.9.8" #define APP_AUTHOR "xose.perez@gmail.com" #define APP_WEBSITE "http://tinkerman.cat" diff --git a/code/src/webserver.ino b/code/src/webserver.ino index 7632b198..4133617a 100644 --- a/code/src/webserver.ino +++ b/code/src/webserver.ino @@ -35,27 +35,20 @@ String getContentType(String filename) { } void handleRelayOn() { - #ifdef DEBUG - Serial.println(F("[WEBSERVER] Request: /relay/on")); - #endif + DEBUG_MSG("[WEBSERVER] Request: /relay/on\n"); switchRelayOn(); server.send(200, "text/plain", "ON"); } void handleRelayOff() { - #ifdef DEBUG - Serial.println(F("[WEBSERVER] Request: /relay/off")); - #endif + DEBUG_MSG("[WEBSERVER] Request: /relay/off\n"); switchRelayOff(); server.send(200, "text/plain", "OFF"); } bool handleFileRead(String path) { - #ifdef DEBUG - Serial.print(F("[WEBSERVER] Request: ")); - Serial.println(path); - #endif + DEBUG_MSG("[WEBSERVER] Request: %s\n", (char *) path.c_str()); if (path.endsWith("/")) path += "index.html"; String contentType = getContentType(path); @@ -74,86 +67,9 @@ bool handleFileRead(String path) { } -void handleGet() { - - #ifdef DEBUG - Serial.println("[WEBSERVER] Request: /get"); - #endif - - char buffer[64]; - sprintf(buffer, "%s %s", APP_NAME, APP_VERSION); - - StaticJsonBuffer<1024> jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - - root["app"] = buffer; - root["manufacturer"] = String(MANUFACTURER); - root["device"] = String(DEVICE); - root["hostname"] = getSetting("hostname"); - root["network"] = getNetwork(); - root["ip"] = getIP(); - root["updateInterval"] = STATUS_UPDATE_INTERVAL; - root["mqttServer"] = getSetting("mqttServer", MQTT_SERVER); - root["mqttPort"] = getSetting("mqttPort", String(MQTT_PORT)); - root["mqttUser"] = getSetting("mqttUser"); - root["mqttPassword"] = getSetting("mqttPassword"); - root["mqttTopic"] = getSetting("mqttTopic", MQTT_TOPIC); - - JsonArray& wifi = root.createNestedArray("wifi"); - for (byte i=0; i<3; i++) { - JsonObject& network = wifi.createNestedObject(); - network["ssid"] = getSetting("ssid" + String(i)); - network["pass"] = getSetting("pass" + String(i)); - } - - #if ENABLE_RF - root["rfChannel"] = getSetting("rfChannel", String(RF_CHANNEL)); - root["rfDevice"] = getSetting("rfDevice", String(RF_DEVICE)); - #endif - - #if ENABLE_EMON - root["pwMainsVoltage"] = getSetting("pwMainsVoltage", String(EMON_MAINS_VOLTAGE)); - root["pwCurrentRatio"] = getSetting("pwCurrentRatio", String(EMON_CURRENT_RATIO)); - #endif - - String output; - root.printTo(output); - server.send(200, "text/json", output); - -} +void handleSave() { -void handleStatus() { - - // Update reconnection timeout to avoid disconnecting the web client - resetConnectionTimeout(); - - #ifdef DEBUG - //Serial.println("[WEBSERVER] Request: /status"); - #endif - - StaticJsonBuffer<256> jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - root["relayStatus"] = (digitalRead(RELAY_PIN) == HIGH); - root["mqttStatus"] = mqttConnected(); - #if ENABLE_EMON - root["power"] = getCurrent() * getSetting("pwMainsVoltage", String(EMON_MAINS_VOLTAGE)).toFloat(); - #endif - #if ENABLE_DHT - root["temperature"] = getTemperature(); - root["humidity"] = getHumidity(); - #endif - - String output; - root.printTo(output); - server.send(200, "text/json", output); - -} - -void handlePost() { - - #ifdef DEBUG - Serial.println(F("[WEBSERVER] Request: /post")); - #endif + DEBUG_MSG("[WEBSERVER] Request: /save\n"); bool dirty = false; bool dirtyMQTT = false; @@ -182,7 +98,9 @@ void handlePost() { server.send(202, "text/json", "{}"); - if (dirty) saveSettings(); + if (dirty) { + saveSettings(); + } #if ENABLE_RF rfBuildCodes(); @@ -192,13 +110,12 @@ void handlePost() { setCurrentRatio(getSetting("pwCurrentRatio").toFloat()); #endif - // Disconnect from current WIFI network if it's not the first on the list - // wifiLoop will take care of the reconnection - if (getNetwork() != getSetting("ssid0")) { - wifiDisconnect(); + // Reconfigure networks + wifiConfigure(); + wifiDisconnect(); - // else check if we should reconigure MQTT connection - } else if (dirtyMQTT) { + // Check if we should reconigure MQTT connection + if (dirtyMQTT) { mqttDisconnect(); } @@ -206,20 +123,20 @@ void handlePost() { void webServerSetup() { + //SPIFFS.begin(); + // Relay control server.on("/relay/on", HTTP_GET, handleRelayOn); server.on("/relay/off", HTTP_GET, handleRelayOff); // Configuration page - server.on("/get", HTTP_GET, handleGet); - server.on("/post", HTTP_POST, handlePost); - server.on("/status", HTTP_GET, handleStatus); + server.on("/save", HTTP_POST, handleSave); // Anything else server.onNotFound([]() { // Hidden files - #ifndef DEBUG + #ifndef DEBUG_PORT if (server.uri().startsWith("/.")) { server.send(403, "text/plain", "Forbidden"); return; diff --git a/code/src/websockets.ino b/code/src/websockets.ino new file mode 100644 index 00000000..2c88e832 --- /dev/null +++ b/code/src/websockets.ino @@ -0,0 +1,107 @@ +/* + +RENTALITO +WEBSERVER MODULE + +Copyright (C) 2016 by Xose Pérez + +*/ + +#include +#include +#include + +WebSocketsServer webSocket = WebSocketsServer(81); + +// ----------------------------------------------------------------------------- +// WEBSOCKETS +// ----------------------------------------------------------------------------- + +bool webSocketSend(char * payload) { + //DEBUG_MSG("[WEBSOCKET] Broadcasting '%s'\n", payload); + webSocket.broadcastTXT(payload); +} + +bool webSocketSend(uint8_t num, char * payload) { + //DEBUG_MSG("[WEBSOCKET] Sending '%s' to #%d\n", payload, num); + webSocket.sendTXT(num, payload); +} + +void webSocketStart(uint8_t num) { + + char buffer[64]; + sprintf(buffer, "%s %s", APP_NAME, APP_VERSION); + + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + + root["app"] = buffer; + root["manufacturer"] = String(MANUFACTURER); + root["device"] = String(DEVICE); + root["hostname"] = getSetting("hostname", HOSTNAME); + root["network"] = getNetwork(); + root["ip"] = getIP(); + root["mqttStatus"] = mqttConnected() ? "1" : "0"; + root["mqttServer"] = getSetting("mqttServer", MQTT_SERVER); + root["mqttPort"] = getSetting("mqttPort", String(MQTT_PORT)); + root["mqttUser"] = getSetting("mqttUser"); + root["mqttPassword"] = getSetting("mqttPassword"); + root["mqttTopic"] = getSetting("mqttTopic", MQTT_TOPIC); + root["relayStatus"] = digitalRead(RELAY_PIN) == HIGH; + + #if ENABLE_RF + root["rfChannel"] = getSetting("rfChannel", String(RF_CHANNEL)); + root["rfDevice"] = getSetting("rfDevice", String(RF_DEVICE)); + #endif + + #if ENABLE_EMON + root["pwMainsVoltage"] = getSetting("pwMainsVoltage", String(EMON_MAINS_VOLTAGE)); + root["pwCurrentRatio"] = getSetting("pwCurrentRatio", String(EMON_CURRENT_RATIO)); + #endif + + JsonArray& wifi = root.createNestedArray("wifi"); + for (byte i=0; i<3; i++) { + JsonObject& network = wifi.createNestedObject(); + network["ssid"] = getSetting("ssid" + String(i)); + network["pass"] = getSetting("pass" + String(i)); + } + + String output; + root.printTo(output); + webSocket.sendTXT(num, (char *) output.c_str()); + +} + +void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { + + switch(type) { + case WStype_DISCONNECTED: + DEBUG_MSG("[WEBSOCKET] #%u disconnected\n", num); + break; + case WStype_CONNECTED: + #if DEBUG_PORT + { + IPAddress ip = webSocket.remoteIP(num); + DEBUG_MSG("[WEBSOCKET] #%u connected, ip: %d.%d.%d.%d, url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); + } + #endif + webSocketStart(num); + break; + case WStype_TEXT: + DEBUG_MSG("[WEBSOCKET] #%u sent: %s\n", num, payload); + break; + case WStype_BIN: + DEBUG_MSG("[WEBSOCKET] #%u sent binary length: %u\n", num, length); + break; + } + +} + +void webSocketSetup() { + webSocket.begin(); + webSocket.onEvent(webSocketEvent); +} + +void webSocketLoop() { + webSocket.loop(); +} diff --git a/code/src/wifi.ino b/code/src/wifi.ino index 19e6a56b..2f6cd316 100644 --- a/code/src/wifi.ino +++ b/code/src/wifi.ino @@ -9,23 +9,22 @@ Copyright (C) 2016 by Xose Pérez #include "JustWifi.h" -extern "C" { - #include "user_interface.h" -} - -JustWifi jw; -unsigned long wifiLastConnectionTime = 0; - // ----------------------------------------------------------------------------- // WIFI // ----------------------------------------------------------------------------- String getIP() { - return jw.getIP(); + if (WiFi.getMode() == WIFI_AP) { + return WiFi.softAPIP().toString(); + } + return WiFi.localIP().toString(); } String getNetwork() { - return jw.getNetwork(); + if (WiFi.getMode() == WIFI_AP) { + return jw.getAPSSID(); + } + return WiFi.SSID(); } void wifiDisconnect() { @@ -33,136 +32,125 @@ void wifiDisconnect() { } void resetConnectionTimeout() { - wifiLastConnectionTime = millis(); + jw.resetReconnectTimeout(); } bool wifiConnected() { return jw.connected(); } +bool createAP() { + return jw.createAP(); +} + +void wifiConfigure() { + jw.cleanNetworks(); + if (getSetting("ssid0").length() > 0) jw.addNetwork((char *) getSetting("ssid0").c_str(), (char *) getSetting("pass0").c_str()); + if (getSetting("ssid1").length() > 0) jw.addNetwork((char *) getSetting("ssid1").c_str(), (char *) getSetting("pass1").c_str()); + if (getSetting("ssid2").length() > 0) jw.addNetwork((char *) getSetting("ssid2").c_str(), (char *) getSetting("pass2").c_str()); + jw.disconnect(); +} + void wifiSetup() { - wifi_station_set_hostname((char *) getSetting("hostname").c_str()); + jw.setHostname((char *) getSetting("hostname", HOSTNAME).c_str()); + jw.scanNetworks(true); + jw.setAPMode(AP_MODE_ALONE); + jw.setSoftAP((char *) getIdentifier().c_str(), (char *) AP_PASS); + wifiConfigure(); // Message callbacks jw.onMessage([](justwifi_messages_t code, char * parameter) { + #ifdef DEBUG_PORT + + if (code == MESSAGE_SCANNING) { + DEBUG_MSG("[WIFI] Scanning\n"); + } + + if (code == MESSAGE_SCAN_FAILED) { + DEBUG_MSG("[WIFI] Scan failed\n"); + } + + if (code == MESSAGE_NO_NETWORKS) { + DEBUG_MSG("[WIFI] No networks found\n"); + } + + if (code == MESSAGE_NO_KNOWN_NETWORKS) { + DEBUG_MSG("[WIFI] No known networks found\n"); + } + + if (code == MESSAGE_FOUND_NETWORK) { + DEBUG_MSG("[WIFI] %s\n", parameter); + } + + if (code == MESSAGE_CONNECTING) { + DEBUG_MSG("[WIFI] Connecting to %s\n", parameter); + } + + if (code == MESSAGE_CONNECT_WAITING) { + // too much noise + } + + if (code == MESSAGE_CONNECT_FAILED) { + DEBUG_MSG("[WIFI] Could not connect to %s\n", parameter); + } + + if (code == MESSAGE_CONNECTED) { + DEBUG_MSG("[WIFI] MODE STA -------------------------------------\n"); + DEBUG_MSG("[WIFI] SSID %s\n", WiFi.SSID().c_str()); + DEBUG_MSG("[WIFI] IP %s\n", WiFi.localIP().toString().c_str()); + DEBUG_MSG("[WIFI] MAC %s\n", WiFi.macAddress().c_str()); + DEBUG_MSG("[WIFI] GW %s\n", WiFi.gatewayIP().toString().c_str()); + DEBUG_MSG("[WIFI] MASK %s\n", WiFi.subnetMask().toString().c_str()); + DEBUG_MSG("[WIFI] DNS %s\n", WiFi.dnsIP().toString().c_str()); + DEBUG_MSG("[WIFI] HOST %s\n", WiFi.hostname().c_str()); + DEBUG_MSG("[WIFI] ----------------------------------------------\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATED) { + DEBUG_MSG("[WIFI] MODE AP --------------------------------------\n"); + DEBUG_MSG("[WIFI] SSID %s\n", jw.getAPSSID().c_str()); + DEBUG_MSG("[WIFI] IP %s\n", WiFi.softAPIP().toString().c_str()); + DEBUG_MSG("[WIFI] MAC %s\n", WiFi.softAPmacAddress().c_str()); + DEBUG_MSG("[WIFI] ----------------------------------------------\n"); + } + + if (code == MESSAGE_DISCONNECTED) { + DEBUG_MSG("[WIFI] Disconnected\n"); + } + + if (code == MESSAGE_ACCESSPOINT_CREATING) { + DEBUG_MSG("[WIFI] Creating access point\n"); + } + + if (code == MESSAGE_ACCESSPOINT_FAILED) { + DEBUG_MSG("[WIFI] Could not create access point\n"); + } + + #endif + // Disconnect from MQTT server if no WIFI if (code != MESSAGE_CONNECTED) { if (mqttConnected()) mqttDisconnect(); } - #if DEBUG - - if (code == MESSAGE_AUTO_NOSSID) { - Serial.println("[WIFI] No information about the last successful network"); - } - - if (code == MESSAGE_AUTO_CONNECTING) { - Serial.print("[WIFI] Connecting to last successful network: "); - Serial.println(parameter); - } - - if (code == MESSAGE_AUTO_FAILED) { - Serial.println("[WIFI] Could not connect to last successful network"); - } - - if (code == MESSAGE_CONNECTING) { - Serial.print("[WIFI] Connecting to "); - Serial.println(parameter); - } - - if (code == MESSAGE_CONNECT_WAITING) { - // - } - - 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()); - } + // Configure mDNS + if (code == MESSAGE_CONNECTED) { - if (code == MESSAGE_DISCONNECTED) { - Serial.println("[WIFI] Disconnected"); - } + if (MDNS.begin((char *) WiFi.hostname().c_str())) { + MDNS.addService("http", "tcp", 80); + DEBUG_MSG("[MDNS] OK\n"); + } else { + DEBUG_MSG("[MDNS] FAIL\n"); + } - if (code == MESSAGE_ACCESSPOINT_CREATING) { - Serial.println("[WIFI] Creating access point"); - } - - 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()); - } - - if (code == MESSAGE_ACCESSPOINT_FAILED) { - Serial.println("[WIFI] Could not create access point"); - } - - #endif + } }); } -bool wifiAP() { - //jw.disconnect(); - return jw.startAP((char *) getSetting("hostname").c_str(), (char *) AP_PASS); -} - -void wifiConnect() { - - resetConnectionTimeout(); - - //WiFi.printDiag(Serial); - - // Set networks - jw.cleanNetworks(); - jw.addNetwork((char *) getSetting("ssid0").c_str(), (char *) getSetting("pass0").c_str()); - jw.addNetwork((char *) getSetting("ssid1").c_str(), (char *) getSetting("pass1").c_str()); - jw.addNetwork((char *) getSetting("ssid2").c_str(), (char *) getSetting("pass2").c_str()); - - // Connecting - if (!jw.autoConnect()) { - if (!jw.connect()) { - if (!wifiAP()) { - #if DEBUG - Serial.println("[WIFI] Could not start any wifi interface!"); - #endif - } - } - } - -} - void wifiLoop() { - jw.loop(); - - // Check disconnection - if (!jw.connected()) { - - // If we are in AP mode try to reconnect every WIFI_RECONNECT_INTERVAL - // wifiLastConnectionTime gets updated upon every connect try or when - // the webserver is hit by a request to avoid web clients to be - // disconnected while configuring the board - if (jw.getMode() == MODE_ACCESS_POINT) { - if (millis() - wifiLastConnectionTime > WIFI_RECONNECT_INTERVAL) { - wifiConnect(); - } - - // else reconnect right away - } else { - wifiConnect(); - } - } - }