From 11434301e05551d50a419703da5f068d8b61c225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Tue, 6 Dec 2016 22:02:34 +0100 Subject: [PATCH] * Support for ITead's Sonoff Dual * Support for Electrodragon's ESP Relay Board * Support for multi-relay boards * Changed relay MQTT topics * Changed relay API entry points * Removed non-secure api entry points --- code/data/fsversion | 2 +- code/data/index.html.gz | Bin 45355 -> 45647 bytes code/html/custom.css | 3 + code/html/custom.js | 62 +++++++++--- code/html/fsversion | 2 +- code/html/index.html | 25 ++++- code/platformio.custom.ini | 16 ++++ code/platformio.ini | 46 ++++++++- code/src/button.ino | 54 ++++++++++- code/src/config/general.h | 5 +- code/src/config/hardware.h | 36 +++++-- code/src/config/version.h | 4 +- code/src/fauxmo.ino | 19 +++- code/src/main.ino | 35 +++---- code/src/mqtt.ino | 25 +++-- code/src/relay.ino | 189 ++++++++++++++++++++++++++++++++----- code/src/web.ino | 89 +++++++++++------ 17 files changed, 490 insertions(+), 122 deletions(-) diff --git a/code/data/fsversion b/code/data/fsversion index 21e8796a..9084fa2f 100644 --- a/code/data/fsversion +++ b/code/data/fsversion @@ -1 +1 @@ -1.0.3 +1.1.0 diff --git a/code/data/index.html.gz b/code/data/index.html.gz index 59a3d111d388511ca5d4103cc1ca5f55a215e6fe..6a84e34f7adf0f10aad93f413af58b6533d0d99b 100644 GIT binary patch delta 44384 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� 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 f<{1^uHP*S`c_|33v=me)|6cbB<KE>Bk delta 44147 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 AVE_OC diff --git a/code/html/custom.css b/code/html/custom.css index 0d544a6a..c129c81b 100644 --- a/code/html/custom.css +++ b/code/html/custom.css @@ -61,3 +61,6 @@ div.hint { .module { display: none; } +#relayTemplate { + display: none; +} diff --git a/code/html/custom.js b/code/html/custom.js index 486ce000..5d6ef086 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -22,7 +22,8 @@ function doReconnect() { } function doToggle(element, value) { - websock.send(JSON.stringify({'action': value ? 'on' : 'off'})); + var relayID = parseInt(element.attr("data")); + websock.send(JSON.stringify({'action': value ? 'on' : 'off', 'relayID': relayID})); return false; } @@ -57,6 +58,31 @@ function toggleMenu() { $("#menuLink").toggleClass('active'); } +function createRelays(count) { + + var current = $("#relays > div").length; + if (current > 0) return; + + var template = $("#relayTemplate .pure-g")[0]; + for (var relayID=0; relayID 1) $(".relay_id", line).html(" " + relayID); + line.appendTo("#relays"); + $(":checkbox", line).iphoneStyle({ + onChange: doToggle, + resizeContainer: true, + resizeHandle: true, + checkedLabel: 'ON', + uncheckedLabel: 'OFF' + }); + + } + +} + function processData(data) { // title @@ -84,6 +110,26 @@ function processData(data) { return; } + // Relay status + if (key == "relayStatus") { + + var relays = data.relayStatus; + createRelays(relays.length); + + for (var relayID in relays) { + var element = $(".relayStatus[data=" + relayID + "]"); + if (element.length > 0) { + element + .prop("checked", relays[relayID]) + .iphoneStyle("refresh"); + } + } + + return; + + } + + // Messages if (key == "message") { window.alert(data.message); @@ -166,20 +212,6 @@ function init() { $(".button-apikey").on('click', doGenerateAPIKey); $(".pure-menu-link").on('click', showPanel); - $("input[name='relayStatus']") - .iphoneStyle({ - onChange: doToggle - }); - $("input[type='checkbox']") - .iphoneStyle({ - resizeContainer: true, - resizeHandle: true, - checkedLabel: 'ON', - uncheckedLabel: 'OFF' - }) - .iphoneStyle("refresh"); - - $.ajax({ 'method': 'GET', 'url': '/auth' diff --git a/code/html/fsversion b/code/html/fsversion index 21e8796a..9084fa2f 100644 --- a/code/html/fsversion +++ b/code/html/fsversion @@ -1 +1 @@ -1.0.3 +1.1.0 diff --git a/code/html/index.html b/code/html/index.html index 0bec6d50..00b8bfc7 100644 --- a/code/html/index.html +++ b/code/html/index.html @@ -132,11 +132,17 @@ -

+
+ +
+ +
+
 
+
Define how the different relays should be synchronized.
+
+
diff --git a/code/platformio.custom.ini b/code/platformio.custom.ini index 3b434ed2..1dda5f93 100644 --- a/code/platformio.custom.ini +++ b/code/platformio.custom.ini @@ -65,6 +65,14 @@ build_flags = -g -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DSONOFF_POW [env:sonoff-pow-debug-ota] include = env:sonoff-pow-debug,ota +[env:sonoff-dual-debug] +include = common +board = esp12e +build_flags = -g -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DSONOFF_DUAL + +[env:sonoff-dual-debug-ota] +include = env:sonoff-dual-debug,ota + [env:slampher-debug] include = common board = esp01_1m @@ -81,6 +89,14 @@ build_flags = -g -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DS20 [env:s20-debug-ota] include = env:s20-debug,ota +[env:electrodragon-debug] +include = common +board = esp12e +build_flags = -g -Wl,-Tesp8266.flash.1m256.ld -DDEBUG_PORT=Serial -DESP_RELAY_BOARD + +[env:electrodragon-debug-ota] +include = env:electrodragon-debug,ota + # ------------------------------------------------------------------------------ [env:ac-device] diff --git a/code/platformio.ini b/code/platformio.ini index bbe389f0..95c215b4 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -32,7 +32,7 @@ board = nodemcuv2 lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} extra_script = pio_hooks.py -build_flags = -g -DNODEMCUV2 -DDEBUG_PORT=Serial +build_flags = -g -DNODEMCUV2 -DDEBUG_PORT=Serial -DNOWSAUTH [env:node-debug-ota] platform = espressif8266 @@ -41,7 +41,7 @@ board = nodemcuv2 lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} extra_script = pio_hooks.py -build_flags = -g -DNODEMCUV2 -DDEBUG_PORT=Serial +build_flags = -g -DNODEMCUV2 -DDEBUG_PORT=Serial -DNOWSAUTH upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 @@ -88,6 +88,27 @@ upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 +[env:sonoff-dual-debug] +platform = espressif8266 +framework = arduino +board = esp01_1m +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -Wl,-Tesp8266.flash.1m256.ld -DSONOFF_DUAL + +[env:sonoff-dual-debug-ota] +platform = espressif8266 +framework = arduino +board = esp01_1m +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -Wl,-Tesp8266.flash.1m256.ld -DSONOFF_DUAL +upload_speed = 115200 +upload_port = "192.168.4.1" +upload_flags = --auth=fibonacci --port 8266 + [env:slampher-debug] platform = espressif8266 framework = arduino @@ -130,6 +151,27 @@ upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 +[env:electrodragon-debug] +platform = espressif8266 +framework = arduino +board = esp12e +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -DDEBUG_PORT=Serial -DDEBUG_PORT=Serial -DESP_RELAY_BOARD + +[env:electrodragon-debug-ota] +platform = espressif8266 +framework = arduino +board = esp12e +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -DDEBUG_PORT=Serial -DDEBUG_PORT=Serial -DESP_RELAY_BOARD +upload_speed = 115200 +upload_port = "192.168.4.1" +upload_flags = --auth=fibonacci --port 8266 + # ------------------------------------------------------------------------------ [env:ac-device] diff --git a/code/src/button.ino b/code/src/button.ino index bc79e8a0..53cafda5 100644 --- a/code/src/button.ino +++ b/code/src/button.ino @@ -7,14 +7,58 @@ Copyright (C) 2016 by Xose Pérez */ -#include - -DebounceEvent button1 = false; - // ----------------------------------------------------------------------------- // BUTTON // ----------------------------------------------------------------------------- +#ifdef SONOFF_DUAL + +void buttonSetup() {} + +void buttonLoop() { + + if (Serial.available() >= 4) { + + unsigned char value; + if (Serial.read() == 0xA0) { + if (Serial.read() == 0x04) { + value = Serial.read(); + if (Serial.read() == 0xA1) { + + // RELAYs and BUTTONs are synchonized in the SIL F330 + // The on-board BUTTON2 should toggle RELAY0 value + // Since we are not passing back RELAY2 value + // (in the relayStatus method) it will only be present + // here if it has actually been pressed + if ((value & 4) == 4) value = value ^ 1; + + // Otherwise check if any of the other two BUTTONs + // (in the header) has been pressent, but we should + // ensure that we only toggle one of them to avoid + // the synchronization going mad + // This loop is generic for any PSB-04 module + for (unsigned int i=0; i 0; + + // relayStatus returns true if the status has changed + if (relayStatus(i, status)) break; + + } + + } + } + } + + } + +} + +#else + +#include +DebounceEvent button1 = false; + void buttonSetup() { button1 = DebounceEvent(BUTTON_PIN); } @@ -26,3 +70,5 @@ void buttonLoop() { if (button1.getEvent() == EVENT_LONG_CLICK) ESP.reset(); } } + +#endif diff --git a/code/src/config/general.h b/code/src/config/general.h index bf859923..a1edee7f 100644 --- a/code/src/config/general.h +++ b/code/src/config/general.h @@ -15,6 +15,9 @@ // 0 means OFF, 1 ON and 2 whatever was before #define RELAY_MODE 1 +// 0 means ANY, 1 zero or one and 2 one and only one +#define RELAY_SYNC 0 + // ----------------------------------------------------------------------------- // WIFI & WEB // ----------------------------------------------------------------------------- @@ -45,7 +48,7 @@ #define MQTT_QOS 0 #define MQTT_KEEPALIVE 30 #define MQTT_RECONNECT_DELAY 10000 -#define MQTT_STATUS_TOPIC "" +#define MQTT_RELAY_TOPIC "/relay/%d" #define MQTT_IP_TOPIC "/ip" #define MQTT_VERSION_TOPIC "/version" #define MQTT_FSVERSION_TOPIC "/fsversion" diff --git a/code/src/config/hardware.h b/code/src/config/hardware.h index 34ef53a5..c1c13b6d 100644 --- a/code/src/config/hardware.h +++ b/code/src/config/hardware.h @@ -7,7 +7,7 @@ #define MANUFACTURER "NODEMCU" #define DEVICE "LOLIN" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 2 #define LED_PIN_INVERSE 0 @@ -20,7 +20,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 13 #define LED_PIN_INVERSE 0 @@ -29,7 +29,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_TH" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 13 #define LED_PIN_INVERSE 0 @@ -38,17 +38,29 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_POW" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 15 #define LED_PIN_INVERSE 1 #define ENABLE_POW 1 +#elif defined(SONOFF_DUAL) + + #define MANUFACTURER "ITEAD" + #define DEVICE "SONOFF_DUAL" + #define BUTTON_PIN 0 + #define RELAY1_PIN 12 + #define RELAY2_PIN 13 + #define LED_PIN 15 + #define LED_PIN_INVERSE 1 + #undef SERIAL_BAUDRATE + #define SERIAL_BAUDRATE 19230 + #elif defined(SLAMPHER) #define MANUFACTURER "ITEAD" #define DEVICE "SLAMPHER" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 13 #define LED_PIN_INVERSE 0 @@ -57,10 +69,20 @@ #define MANUFACTURER "ITEAD" #define DEVICE "S20" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 13 #define LED_PIN_INVERSE 0 +#elif defined(ESP_RELAY_BOARD) + + #define MANUFACTURER "ELECTRODRAGON" + #define DEVICE "ESP_RELAY_BOARD" + #define BUTTON_PIN 2 + #define RELAY1_PIN 12 + #define RELAY2_PIN 13 + #define LED_PIN 16 + #define LED_PIN_INVERSE 0 + // ----------------------------------------------------------------------------- // ESPurna board (still beta) // ----------------------------------------------------------------------------- @@ -70,7 +92,7 @@ #define MANUFACTURER "TINKERMAN" #define DEVICE "ESPURNA" #define BUTTON_PIN 0 - #define RELAY_PIN 12 + #define RELAY1_PIN 12 #define LED_PIN 13 #define LED_PIN_INVERSE 0 diff --git a/code/src/config/version.h b/code/src/config/version.h index b434af89..b11726cc 100644 --- a/code/src/config/version.h +++ b/code/src/config/version.h @@ -1,4 +1,4 @@ -#define APP_NAME "Espurna" -#define APP_VERSION "1.0.3" +#define APP_NAME "ESPurna" +#define APP_VERSION "1.1.0" #define APP_AUTHOR "xose.perez@gmail.com" #define APP_WEBSITE "http://tinkerman.cat" diff --git a/code/src/fauxmo.ino b/code/src/fauxmo.ino index 245432c0..3d89669a 100644 --- a/code/src/fauxmo.ino +++ b/code/src/fauxmo.ino @@ -23,10 +23,23 @@ void fauxmoConfigure() { void fauxmoSetup() { fauxmoConfigure(); - fauxmo.addDevice(getSetting("hostname", HOSTNAME).c_str()); - fauxmo.onMessage([](const char * name, bool state) { + unsigned int relays = relayCount(); + String hostname = getSetting("hostname", HOSTNAME); + if (relays == 1) { + fauxmo.addDevice(hostname.c_str()); + } else { + for (unsigned int i=0; i 1) { + id = name[strlen(name)-1] - '0'; + if (id >= relays) id = 0; + } + relayStatus(id, state); }); } diff --git a/code/src/main.ino b/code/src/main.ino index 4a9e1864..8b5593c6 100644 --- a/code/src/main.ino +++ b/code/src/main.ino @@ -64,7 +64,7 @@ void showStatus() { } void hardwareSetup() { - Serial.begin(115200); + Serial.begin(SERIAL_BAUDRATE); pinMode(LED_PIN, OUTPUT); SPIFFS.begin(); } @@ -105,24 +105,23 @@ void hardwareLoop() { void welcome() { 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()); + DEBUG_MSG("%s %s\n", (char *) APP_NAME, (char *) APP_VERSION); + DEBUG_MSG("%s\n%s\n\n", (char *) APP_AUTHOR, (char *) APP_WEBSITE); + //DEBUG_MSG("Device: %s\n", (char *) getIdentifier().c_str()); + DEBUG_MSG("ChipID: %06X\n", ESP.getChipId()); + DEBUG_MSG("Last reset reason: %s\n", (char *) ESP.getResetReason().c_str()); + DEBUG_MSG("Memory size: %d bytes\n", ESP.getFlashChipSize()); + DEBUG_MSG("Free heap: %d bytes\n", ESP.getFreeHeap()); FSInfo fs_info; if (SPIFFS.info(fs_info)) { - 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); + DEBUG_MSG("File system total size: %d bytes\n", fs_info.totalBytes); + DEBUG_MSG(" used size : %d bytes\n", fs_info.usedBytes); + DEBUG_MSG(" block size: %d bytes\n", fs_info.blockSize); + DEBUG_MSG(" page size : %d bytes\n", fs_info.pageSize); + DEBUG_MSG(" max files : %d\n", fs_info.maxOpenFiles); + DEBUG_MSG(" max length: %d\n", fs_info.maxPathLength); } - Serial.println(); - Serial.println(); + DEBUG_MSG("\n\n"); } @@ -174,12 +173,14 @@ void loop() { hardwareLoop(); buttonLoop(); - settingsLoop(); wifiLoop(); otaLoop(); mqttLoop(); ntpLoop(); + #ifndef SONOFF_DUAL + settingsLoop(); + #endif #if ENABLE_NOFUSS nofussLoop(); #endif diff --git a/code/src/mqtt.ino b/code/src/mqtt.ino index 73c53268..5c0cbf17 100644 --- a/code/src/mqtt.ino +++ b/code/src/mqtt.ino @@ -43,6 +43,8 @@ void mqttSend(char * topic, char * message) { void _mqttOnConnect(bool sessionPresent) { + char buffer[50]; + DEBUG_MSG("[MQTT] Connected!\n"); // Send status via webSocket @@ -54,16 +56,16 @@ void _mqttOnConnect(bool sessionPresent) { // Say hello and report our IP and VERSION mqttSend((char *) MQTT_IP_TOPIC, (char *) getIP().c_str()); mqttSend((char *) MQTT_VERSION_TOPIC, (char *) APP_VERSION); - char buffer[10]; getFSVersion(buffer); mqttSend((char *) MQTT_FSVERSION_TOPIC, buffer); // Publish current relay status - mqttSend((char *) MQTT_STATUS_TOPIC, (char *) (relayStatus(0) ? "1" : "0")); + relayMQTT(); - // Subscribe to topic - DEBUG_MSG("[MQTT] Subscribing to %s\n", (char *) mqttTopic.c_str()); - mqtt.subscribe(mqttTopic.c_str(), MQTT_QOS); + // Subscribe to relay topics + sprintf(buffer, "%s/relay/#", mqttTopic.c_str()); + DEBUG_MSG("[MQTT] Subscribing to %s\n", buffer); + mqtt.subscribe(buffer, MQTT_QOS); } @@ -78,8 +80,7 @@ void _mqttOnMessage(char* topic, char* payload, AsyncMqttClientMessageProperties static bool isFirstMessage = true; - payload[len] = '\0'; - DEBUG_MSG("[MQTT] Received %s %s\n", topic, payload); + DEBUG_MSG("[MQTT] Received %s %c\n", topic, payload[0]); // If relayMode is not SAME avoid responding to a retained message if (isFirstMessage) { @@ -88,17 +89,21 @@ void _mqttOnMessage(char* topic, char* payload, AsyncMqttClientMessageProperties if (relayMode != 2) return; } + // Get relay ID + unsigned int relayID = topic[strlen(topic)-1] - '0'; + if (relayID >= relayCount()) relayID = 0; + // Action to perform if ((char)payload[0] == '0') { isCallbackMessage = true; - relayStatus(0, false); + relayStatus(relayID, false); } if ((char)payload[0] == '1') { isCallbackMessage = true; - relayStatus(0, true); + relayStatus(relayID, true); } if ((char)payload[0] == '2') { - relayToggle(0); + relayToggle(relayID); } isCallbackMessage = false; diff --git a/code/src/relay.ino b/code/src/relay.ino index e72efdaf..62a8a6e4 100644 --- a/code/src/relay.ino +++ b/code/src/relay.ino @@ -8,56 +8,195 @@ Copyright (C) 2016 by Xose Pérez */ #include +#include +#include + +std::vector _relays; +bool recursive = false; +#ifdef SONOFF_DUAL + unsigned char dualRelayStatus = 0; +#endif + +#define RELAY_MODE_OFF 0 +#define RELAY_MODE_ON 1 +#define RELAY_MODE_SAME 2 + +#define RELAY_SYNC_ANY 0 +#define RELAY_SYNC_NONE_OR_ONE 1 +#define RELAY_SYNC_ONE 2 + // ----------------------------------------------------------------------------- // RELAY // ----------------------------------------------------------------------------- -void _relayOn(unsigned char id) { +void relayMQTT(unsigned char id) { + char buffer[10]; + sprintf(buffer, MQTT_RELAY_TOPIC, id); + mqttSend(buffer, (char *) (relayStatus(id) ? "1" : "0")); +} - if (!digitalRead(RELAY_PIN)) { - DEBUG_MSG("[RELAY] ON\n"); - digitalWrite(RELAY_PIN, HIGH); - EEPROM.write(0, 1); - EEPROM.commit(); - mqttSend((char *) MQTT_STATUS_TOPIC, (char *) "1"); +void relayMQTT() { + for (unsigned int i=0; i < _relays.size(); i++) { + relayMQTT(i); } +} - wsSend((char *) "{\"relayStatus\": true}"); - +String relayString() { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + JsonArray& relay = root.createNestedArray("relayStatus"); + for (unsigned char i=0; i 0); + #else + return (digitalRead(_relays[id]) == HIGH); + #endif } -void relayStatus(unsigned char id, bool status) { - status ? _relayOn(id) : _relayOff(id); +void relaySync(unsigned char id) { + + if (_relays.size() > 1) { + + recursive = true; + + byte relaySync = getSetting("relaySync", String(RELAY_SYNC)).toInt(); + bool status = relayStatus(id); + + // If NONE_OR_ONE or ONE and setting ON we should set OFF all the others + if (status) { + if (relaySync != RELAY_SYNC_ANY) { + for (unsigned short i=0; i<_relays.size(); i++) { + if (i != id) relayStatus(i, false); + } + } + + // If ONLY_ONE and setting OFF we should set ON the other one + } else { + if (relaySync == RELAY_SYNC_ONE) { + unsigned char i = (id + 1) % _relays.size(); + relayStatus(i, true); + } + } + + recursive = false; + + } + } -bool relayStatus(unsigned char id) { - return (digitalRead(RELAY_PIN) == HIGH); +bool relayStatus(unsigned char id, bool status) { + + bool changed = false; + + if (relayStatus(id) != status) { + + DEBUG_MSG("[RELAY] %d => %s\n", id, status ? "ON" : "OFF"); + changed = true; + + #ifdef SONOFF_DUAL + + dualRelayStatus ^= (1 << id); + Serial.flush(); + Serial.write(0xA0); + Serial.write(0x04); + Serial.write(dualRelayStatus); + Serial.write(0xA1); + Serial.flush(); + + #else + digitalWrite(_relays[id], status); + #endif + + if (!recursive) { + relaySync(id); + relaySave(); + } + + } + + relayMQTT(id); + if (!recursive) relayWS(); + return changed; } void relayToggle(unsigned char id) { relayStatus(id, !relayStatus(id)); } +unsigned char relayCount() { + return _relays.size(); +} + void relaySetup() { - pinMode(RELAY_PIN, OUTPUT); + + #ifdef SONOFF_DUAL + + // Two dummy relays for the dual + _relays.push_back(0); + _relays.push_back(0); + + #else + + #ifdef RELAY1_PIN + _relays.push_back(RELAY1_PIN); + #endif + #ifdef RELAY2_PIN + _relays.push_back(RELAY2_PIN); + #endif + #ifdef RELAY3_PIN + _relays.push_back(RELAY3_PIN); + #endif + #ifdef RELAY4_PIN + _relays.push_back(RELAY4_PIN); + #endif + + #endif + EEPROM.begin(4096); byte relayMode = getSetting("relayMode", String(RELAY_MODE)).toInt(); - if (relayMode == 0) relayStatus(0, false); - if (relayMode == 1) relayStatus(0, true); - if (relayMode == 2) relayStatus(0, EEPROM.read(0) == 1); + + for (unsigned int i=0; i < _relays.size(); i++) { + pinMode(_relays[i], OUTPUT); + if (relayMode == RELAY_MODE_OFF) relayStatus(i, false); + if (relayMode == RELAY_MODE_ON) relayStatus(i, true); + } + + if (relayMode == RELAY_MODE_SAME) relayRetrieve(); + } diff --git a/code/src/web.ino b/code/src/web.ino index 7cd8ac1e..d49546be 100644 --- a/code/src/web.ino +++ b/code/src/web.ino @@ -54,12 +54,18 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) { if (root.containsKey("action")) { String action = root["action"]; + unsigned int relayID = 0; + if (root.containsKey("relayID")) { + String value = root["relayID"]; + relayID = value.toInt(); + } + DEBUG_MSG("[WEBSOCKET] Requested action: %s\n", action.c_str()); if (action.equals("reset")) ESP.reset(); if (action.equals("reconnect")) wifiDisconnect(); - if (action.equals("on")) relayStatus(0, true); - if (action.equals("off")) relayStatus(0, false); + if (action.equals("on")) relayStatus(relayID, true); + if (action.equals("off")) relayStatus(relayID, false); }; @@ -191,14 +197,24 @@ void _wsStart(uint32_t client_id) { root["hostname"] = getSetting("hostname", HOSTNAME); root["network"] = getNetwork(); root["ip"] = getIP(); + root["mqttStatus"] = mqttConnected(); 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"] = relayStatus(0); + + JsonArray& relay = root.createNestedArray("relayStatus"); + for (unsigned char relayID=0; relayID 1) { + root["multirelayVisible"] = 1; + root["relaySync"] = getSetting("relaySync", String(RELAY_SYNC)); + } + root["apiEnabled"] = getSetting("apiEnabled").toInt() == 1; root["apiKey"] = getSetting("apiKey"); @@ -340,24 +356,6 @@ void _onHome(AsyncWebServerRequest *request) { request->send(SPIFFS, "/index.html"); } -void _onRelayOn(AsyncWebServerRequest *request) { - - _logRequest(request); - - relayStatus(0, true); - request->send(200, "text/plain", "ON"); - -}; - -void _onRelayOff(AsyncWebServerRequest *request) { - - _logRequest(request); - - relayStatus(0, false); - request->send(200, "text/plain", "OFF"); - -}; - bool _apiAuth(AsyncWebServerRequest *request) { if (getSetting("apiEnabled").toInt() == 0) { @@ -383,9 +381,34 @@ bool _apiAuth(AsyncWebServerRequest *request) { } +void _onRelay(AsyncWebServerRequest *request) { + + _logRequest(request); + + if (!_apiAuth(request)) return; + + bool asJson = false; + if (request->hasHeader("Accept")) { + AsyncWebHeader* h = request->getHeader("Accept"); + asJson = h->value().equals("application/json"); + } + + String output; + if (asJson) { + output = relayString(); + request->send(200, "application/json", output); + } else { + for (unsigned int i=0; isend(200, "text/plain", output); + } + +}; + ArRequestHandlerFunction _onRelayStatusWrapper(unsigned int relayID) { - return [&](AsyncWebServerRequest *request) { + return [relayID](AsyncWebServerRequest *request) { _logRequest(request); @@ -394,6 +417,8 @@ ArRequestHandlerFunction _onRelayStatusWrapper(unsigned int relayID) { if (request->method() == HTTP_PUT) { if (request->hasParam("status", true)) { AsyncWebParameter* p = request->getParam("status", true); + wsSend((char *) String(relayID).c_str()); + wsSend((char *) p->value().c_str()); unsigned int value = p->value().toInt(); if (value == 2) { relayToggle(relayID); @@ -409,10 +434,10 @@ ArRequestHandlerFunction _onRelayStatusWrapper(unsigned int relayID) { asJson = h->value().equals("application/json"); } + String output; if (asJson) { - char buffer[20]; - sprintf(buffer, "{\"status\": %d}", relayStatus(relayID) ? 1 : 0); - request->send(200, "application/json", buffer); + output = String("{\"relayStatus\": ") + String(relayStatus(relayID) ? "1" : "0") + "}"; + request->send(200, "application/json", output); } else { request->send(200, "text/plain", relayStatus(relayID) ? "1" : "0"); } @@ -427,16 +452,18 @@ void webSetup() { ws.onEvent(_wsEvent); server.addHandler(&ws); - // Serve home (password protected) + // Serve home (basic authentication protection) server.on("/", HTTP_GET, _onHome); server.on("/index.html", HTTP_GET, _onHome); server.on("/auth", HTTP_GET, _onAuth); - // API entry points (non protected) - server.on("/relay/on", HTTP_GET, _onRelayOn); - server.on("/relay/off", HTTP_GET, _onRelayOff); - server.on("/relay/0/status", HTTP_GET + HTTP_PUT, _onRelayStatusWrapper(0)); - //server.on("/relay/1/status", HTTP_GET + HTTP_PUT, _onRelayStatusWrapper(1)); + // API entry points (protected with apikey) + for (unsigned int relayID=0; relayID