diff --git a/code/.gitignore b/code/.gitignore index d88ad014..079975bc 100644 --- a/code/.gitignore +++ b/code/.gitignore @@ -11,3 +11,5 @@ custom.h .vscode/.browse.c_cpp.db* .vscode/c_cpp_properties.json .vscode/launch.json +.pioenvs +.piolibdeps diff --git a/code/espurna/button.ino b/code/espurna/button.ino index 1d27c679..642e04fa 100644 --- a/code/espurna/button.ino +++ b/code/espurna/button.ino @@ -164,13 +164,25 @@ void buttonEvent(unsigned int id, unsigned char event) { void buttonSetup() { - #ifdef ITEAD_SONOFF_DUAL + #if defined(ITEAD_SONOFF_DUAL) unsigned int actions = buttonStore(BUTTON_MODE_NONE, BUTTON_MODE_TOGGLE, BUTTON_MODE_NONE, BUTTON_MODE_NONE, BUTTON_MODE_NONE, BUTTON_MODE_NONE); _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, 1}); _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, 2}); _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, BUTTON3_RELAY}); + #elif defined(FOXEL_LIGHTFOX_DUAL) + + unsigned int actions = buttonStore(BUTTON_MODE_NONE, BUTTON_MODE_TOGGLE, BUTTON_MODE_NONE, BUTTON_MODE_NONE, BUTTON_MODE_NONE, BUTTON_MODE_NONE); + unsigned int btn1Relay = getSetting("btnRelay", 0, BUTTON1_RELAY - 1).toInt() + 1; + _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, btn1Relay}); + unsigned int btn2Relay = getSetting("btnRelay", 1, BUTTON2_RELAY - 1).toInt() + 1; + _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, btn2Relay}); + unsigned int btn3Relay = getSetting("btnRelay", 2, BUTTON3_RELAY - 1).toInt() + 1; + _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, btn3Relay}); + unsigned int btn4Relay = getSetting("btnRelay", 3, BUTTON4_RELAY - 1).toInt() + 1; + _buttons.push_back({new DebounceEvent(0, BUTTON_PUSHBUTTON), actions, btn4Relay}); + #else unsigned long btnDelay = getSetting("btnDelay", BUTTON_DBLCLICK_DELAY).toInt(); @@ -240,7 +252,7 @@ void buttonSetup() { void buttonLoop() { - #ifdef ITEAD_SONOFF_DUAL + #if defined(ITEAD_SONOFF_DUAL) if (Serial.available() >= 4) { if (Serial.read() == 0xA0) { @@ -280,6 +292,29 @@ void buttonLoop() { } } + #elif defined(FOXEL_LIGHTFOX_DUAL) + + if (Serial.available() >= 4) { + if (Serial.read() == 0xA0) { + if (Serial.read() == 0x04) { + unsigned char value = Serial.read(); + if (Serial.read() == 0xA1) { + + DEBUG_MSG_P(PSTR("[BUTTON] [LIGHTFOX] Received buttons mask: %d\n"), value); + + for (unsigned int i=0; i<_buttons.size(); i++) { + + bool clicked = (value & (1 << i)) > 0; + + if (clicked) { + buttonEvent(i, BUTTON_EVENT_CLICK); + } + } + } + } + } + } + #else for (unsigned int i=0; i < _buttons.size(); i++) { diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index e6e3f395..961c1bfa 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -117,6 +117,7 @@ //#define ARILUX_AL_LC02_V14 //#define BLITZWOLF_BWSHPX_V23 //#define DIGOO_NX_SP202 +//#define FOXEL_LIGHTFOX_DUAL //-------------------------------------------------------------------------------- // Features (values below are non-default values) diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 4e6e9fb9..b51461af 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -3438,6 +3438,27 @@ #define HLW8012_POWER_RATIO 3368471 #define HLW8012_INTERRUPT_ON FALLING +// ----------------------------------------------------------------------------- +// Foxel's LightFox dual +// https://github.com/foxel/esp-dual-rf-switch +// ----------------------------------------------------------------------------- + +#elif defined(FOXEL_LIGHTFOX_DUAL) + + // Info + #define MANUFACTURER "FOXEL" + #define DEVICE "LIGHTFOX_DUAL" + #define SERIAL_BAUDRATE 19200 + #define RELAY_PROVIDER RELAY_PROVIDER_DUAL + #define DUMMY_RELAY_COUNT 2 + #define DEBUG_SERIAL_SUPPORT 0 + + // Buttons + #define BUTTON1_RELAY 1 + #define BUTTON2_RELAY 2 + #define BUTTON3_RELAY 2 + #define BUTTON4_RELAY 1 + // ----------------------------------------------------------------------------- // TEST boards (do not use!!) // ----------------------------------------------------------------------------- diff --git a/code/espurna/config/webui.h b/code/espurna/config/webui.h index e7ce37ef..f16cd243 100644 --- a/code/espurna/config/webui.h +++ b/code/espurna/config/webui.h @@ -7,6 +7,7 @@ #define WEBUI_IMAGE_SENSOR 2 #define WEBUI_IMAGE_RFBRIDGE 4 #define WEBUI_IMAGE_RFM69 8 +#define WEBUI_IMAGE_LIGHTFOX 16 #define WEBUI_IMAGE_FULL 15 #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE @@ -45,6 +46,13 @@ #endif #endif +#if defined(FOXEL_LIGHTFOX_DUAL) + #ifdef WEBUI_IMAGE + #undef WEBUI_IMAGE + #endif + #define WEBUI_IMAGE WEBUI_IMAGE_LIGHTFOX +#endif + #ifndef WEBUI_IMAGE #define WEBUI_IMAGE WEBUI_IMAGE_SMALL #endif @@ -67,6 +75,9 @@ PROGMEM const char espurna_webui[] = #if WEBUI_IMAGE == WEBUI_IMAGE_RFM69 "RFM69" #endif + #if WEBUI_IMAGE == WEBUI_IMAGE_LIGHTFOX + "LIGHTFOX" + #endif #if WEBUI_IMAGE == WEBUI_IMAGE_FULL "FULL" #endif diff --git a/code/espurna/data/index.all.html.gz b/code/espurna/data/index.all.html.gz index c19e66b6..2f31a058 100644 Binary files a/code/espurna/data/index.all.html.gz and b/code/espurna/data/index.all.html.gz differ diff --git a/code/espurna/data/index.light.html.gz b/code/espurna/data/index.light.html.gz index b6aad189..6aaaaa0b 100644 Binary files a/code/espurna/data/index.light.html.gz and b/code/espurna/data/index.light.html.gz differ diff --git a/code/espurna/data/index.lightfox.html.gz b/code/espurna/data/index.lightfox.html.gz new file mode 100644 index 00000000..28b3d8a5 Binary files /dev/null and b/code/espurna/data/index.lightfox.html.gz differ diff --git a/code/espurna/data/index.rfbridge.html.gz b/code/espurna/data/index.rfbridge.html.gz index eccdd72a..fbaf9eb1 100644 Binary files a/code/espurna/data/index.rfbridge.html.gz and b/code/espurna/data/index.rfbridge.html.gz differ diff --git a/code/espurna/data/index.rfm69.html.gz b/code/espurna/data/index.rfm69.html.gz index 76071c4d..9eac7100 100644 Binary files a/code/espurna/data/index.rfm69.html.gz and b/code/espurna/data/index.rfm69.html.gz differ diff --git a/code/espurna/data/index.sensor.html.gz b/code/espurna/data/index.sensor.html.gz index a4aff4ae..3c733c18 100644 Binary files a/code/espurna/data/index.sensor.html.gz and b/code/espurna/data/index.sensor.html.gz differ diff --git a/code/espurna/data/index.small.html.gz b/code/espurna/data/index.small.html.gz index a43a2989..28b3d8a5 100644 Binary files a/code/espurna/data/index.small.html.gz and b/code/espurna/data/index.small.html.gz differ diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index 0da20639..7e455383 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -189,6 +189,9 @@ void setup() { #if UART_MQTT_SUPPORT uartmqttSetup(); #endif + #ifdef FOXEL_LIGHTFOX_DUAL + lightfoxSetup(); + #endif // 3rd party code hook diff --git a/code/espurna/lightfox.ino b/code/espurna/lightfox.ino new file mode 100644 index 00000000..7814f1e8 --- /dev/null +++ b/code/espurna/lightfox.ino @@ -0,0 +1,107 @@ +/* + +LightFox module + +Copyright (C) 2019 by Andrey F. Kupreychik + +*/ + +#ifdef FOXEL_LIGHTFOX_DUAL + +// ----------------------------------------------------------------------------- +// DEFINITIONS +// ----------------------------------------------------------------------------- + +#define LIGHTFOX_CODE_START 0xA0 +#define LIGHTFOX_CODE_LEARN 0xF1 +#define LIGHTFOX_CODE_CLEAR 0xF2 +#define LIGHTFOX_CODE_STOP 0xA1 + +// ----------------------------------------------------------------------------- +// PUBLIC +// ----------------------------------------------------------------------------- + +void lightfoxLearn() { + Serial.write(LIGHTFOX_CODE_START); + Serial.write(LIGHTFOX_CODE_LEARN); + Serial.write(0x00); + Serial.write(LIGHTFOX_CODE_STOP); + Serial.println(); + Serial.flush(); + DEBUG_MSG_P(PSTR("[LIGHTFOX] Learn comman sent\n")); +} + +void lightfoxClear() { + Serial.write(LIGHTFOX_CODE_START); + Serial.write(LIGHTFOX_CODE_CLEAR); + Serial.write(0x00); + Serial.write(LIGHTFOX_CODE_STOP); + Serial.println(); + Serial.flush(); + DEBUG_MSG_P(PSTR("[LIGHTFOX] Clear comman sent\n")); +} + +// ----------------------------------------------------------------------------- +// WEB +// ----------------------------------------------------------------------------- + +#if WEB_SUPPORT + +void _lightfoxWebSocketOnSend(JsonObject& root) { + root["lightfoxVisible"] = 1; + uint8_t buttonsCount = _buttons.size(); + root["lightfoxRelayCount"] = relayCount(); + JsonArray& rfb = root.createNestedArray("lightfoxButtons"); + for (byte id=0; id #include "static/index.rfbridge.html.gz.h" #elif WEBUI_IMAGE == WEBUI_IMAGE_RFM69 #include "static/index.rfm69.html.gz.h" +#elif WEBUI_IMAGE == WEBUI_IMAGE_LIGHTFOX + #include "static/index.lightfox.html.gz.h" #elif WEBUI_IMAGE == WEBUI_IMAGE_FULL #include "static/index.all.html.gz.h" #endif diff --git a/code/gulpfile.js b/code/gulpfile.js index bf2fada4..42ee6f9c 100644 --- a/code/gulpfile.js +++ b/code/gulpfile.js @@ -115,6 +115,7 @@ var buildWebUI = function(module) { modules['sensor'] = true; modules['rfbridge'] = true; modules['rfm69'] = false; // we will never be adding this except when building RFM69GW + modules['lightfox'] = false; // we will never be adding this except when building lightfox } else if ('small' !== module) { modules[module] = true; } @@ -186,6 +187,10 @@ gulp.task('webui_rfm69', function() { return buildWebUI('rfm69'); }); +gulp.task('webui_lightfox', function() { + return buildWebUI('lightfox'); +}); + gulp.task('webui_all', function() { return buildWebUI('all'); }); @@ -197,6 +202,7 @@ gulp.task('webui', 'webui_light', 'webui_rfbridge', 'webui_rfm69', + 'webui_lightfox', 'webui_all' ) ); diff --git a/code/html/custom.css b/code/html/custom.css index 97d88f5e..49023221 100644 --- a/code/html/custom.css +++ b/code/html/custom.css @@ -158,6 +158,7 @@ div.state { .button-reconnect, .button-ha-del, .button-rfb-forget, +.button-lightfox-clear, .button-del-network, .button-del-mapping, .button-del-schedule, @@ -176,6 +177,7 @@ div.state { .button-add-mapping, .button-upgrade-browse, .button-rfb-learn, +.button-lightfox-learn, .button-ha-add, .button-ha-config, .button-settings-backup, diff --git a/code/html/custom.js b/code/html/custom.js index 890b29a3..0abf1fc6 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -1159,6 +1159,48 @@ function addRfbNode() { } +// ----------------------------------------------------------------------------- +// LightFox +// ----------------------------------------------------------------------------- + + + +function lightfoxLearn() { + sendAction("lightfoxLearn", {}); +} + +function lightfoxClear() { + sendAction("lightfoxClear", {}); +} + +function initLightfox(data, relayCount) { + + var numNodes = data.length; + + var template = $("#lightfoxNodeTemplate").children(); + + var i, j; + for (i=0; i span").text(data[i]["id"]); + $line.find("select").each(function() { + $(this).attr("name", "btnRelay" + data[i]["id"]); + for (j=0; j < relayCount; j++) { + $(this).append($("