diff --git a/code/src/config/general.h b/code/src/config/general.h index 0ec313c1..c40a00c4 100644 --- a/code/src/config/general.h +++ b/code/src/config/general.h @@ -27,6 +27,15 @@ // 0 means ANY, 1 zero or one and 2 one and only one #define RELAY_SYNC RELAY_SYNC_ANY +//-------------------------------------------------------------------------------- +// LED +//-------------------------------------------------------------------------------- + +// All defined LEDs in the board can be managed through MQTT +// except the first one when LED_AUTO is set to 1. +// If LED_AUTO is set to 1 the board will use first defined LED to show wifi status. +#define LED_AUTO 1 + // ----------------------------------------------------------------------------- // WIFI & WEB // ----------------------------------------------------------------------------- @@ -59,6 +68,7 @@ #define MQTT_KEEPALIVE 30 #define MQTT_RECONNECT_DELAY 10000 #define MQTT_RELAY_TOPIC "/relay" +#define MQTT_LED_TOPIC "/led" #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 9dc6ac9d..f14e9e77 100644 --- a/code/src/config/hardware.h +++ b/code/src/config/hardware.h @@ -26,8 +26,8 @@ #define DEVICE "LOLIN" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 2 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 2 + #define LED1_PIN_INVERSE 1 // ----------------------------------------------------------------------------- // Itead Studio boards @@ -39,8 +39,8 @@ #define DEVICE "SONOFF" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #elif defined(SONOFF_TH) @@ -48,8 +48,8 @@ #define DEVICE "SONOFF_TH" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #elif defined(SONOFF_TOUCH) @@ -57,8 +57,8 @@ #define DEVICE "SONOFF_TOUCH" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 1 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #elif defined(SONOFF_POW) @@ -66,8 +66,8 @@ #define DEVICE "SONOFF_POW" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 15 - #define LED_PIN_INVERSE 1 + #define LED1_PIN 15 + #define LED1_PIN_INVERSE 0 #define ENABLE_POW 1 #elif defined(SONOFF_DUAL) @@ -75,8 +75,8 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_DUAL" #define BUTTON1_PIN 0 - #define LED_PIN 13 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #undef SERIAL_BAUDRATE #define SERIAL_BAUDRATE 19230 @@ -92,8 +92,8 @@ #define RELAY2_PIN 5 #define RELAY3_PIN 4 #define RELAY4_PIN 15 - #define LED_PIN 13 - #define LED_PIN_INVERSE 1 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #elif defined(SONOFF_SV) @@ -101,8 +101,8 @@ #define DEVICE "SONOFF_SV" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 1 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #elif defined(SLAMPHER) @@ -110,8 +110,8 @@ #define DEVICE "SLAMPHER" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 #elif defined(S20) @@ -119,8 +119,8 @@ #define DEVICE "S20" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 1 // ----------------------------------------------------------------------------- // Electrodragon boards @@ -134,8 +134,8 @@ #define BUTTON2_PIN 2 #define RELAY1_PIN 12 #define RELAY2_PIN 13 - #define LED_PIN 16 - #define LED_PIN_INVERSE 1 + #define LED1_PIN 16 + #define LED1_PIN_INVERSE 0 // ----------------------------------------------------------------------------- // WorkChoice ecoPlug @@ -147,8 +147,8 @@ #define DEVICE "ECOPLUG" #define BUTTON1_PIN 13 #define RELAY_PIN 15 - #define LED_PIN 2 - #define LED_PIN_INVERSE 1 + #define LED1_PIN 2 + #define LED1_PIN_INVERSE 0 // ----------------------------------------------------------------------------- // ESPurna board (still beta) @@ -160,8 +160,8 @@ #define DEVICE "ESPURNA" #define BUTTON1_PIN 0 #define RELAY1_PIN 12 - #define LED_PIN 13 - #define LED_PIN_INVERSE 0 + #define LED1_PIN 13 + #define LED1_PIN_INVERSE 0 // ----------------------------------------------------------------------------- // Unknown hardware diff --git a/code/src/led.ino b/code/src/led.ino index cd8c1346..e2cb3bbe 100644 --- a/code/src/led.ino +++ b/code/src/led.ino @@ -11,36 +11,130 @@ Copyright (C) 2016 by Xose PĂ©rez // LED // ----------------------------------------------------------------------------- -#ifdef LED_PIN +#ifdef LED1_PIN -void blink(unsigned long delayOff, unsigned long delayOn) { +typedef struct { + unsigned char pin; + bool reverse; +} led_t; + +std::vector _leds; +bool ledAuto; + +bool ledStatus(unsigned char id) { + bool status = digitalRead(_leds[id].pin); + return _leds[id].reverse ? !status : status; +} + +bool ledStatus(unsigned char id, bool status) { + bool s = _leds[id].reverse ? !status : status; + digitalWrite(_leds[id].pin, _leds[id].reverse ? !status : status); + return status; +} + +bool ledToggle(unsigned char id) { + return ledStatus(id, !ledStatus(id)); +} + +void ledBlink(unsigned char id, unsigned long delayOff, unsigned long delayOn) { static unsigned long next = millis(); - static bool status = HIGH; if (next < millis()) { - status = !status; - digitalWrite(LED_PIN, LED_PIN_INVERSE ? !status : status); - next += ((status) ? delayOff : delayOn); + next += (ledToggle(id) ? delayOn : delayOff); } } void showStatus() { if (wifiConnected()) { if (WiFi.getMode() == WIFI_AP) { - blink(2000, 2000); + ledBlink(0, 2000, 2000); } else { - blink(5000, 500); + ledBlink(0, 5000, 500); } } else { - blink(500, 500); + ledBlink(0, 500, 500); } } +void ledMQTTCallback(unsigned int type, const char * topic, const char * payload) { + + static bool isFirstMessage = true; + + String mqttSetter = getSetting("mqttSetter", MQTT_USE_SETTER); + + if (type == MQTT_CONNECT_EVENT) { + char buffer[strlen(MQTT_LED_TOPIC) + mqttSetter.length() + 3]; + sprintf(buffer, "%s/+%s", MQTT_LED_TOPIC, mqttSetter.c_str()); + mqttSubscribe(buffer); + } + + if (type == MQTT_MESSAGE_EVENT) { + + // Match topic + String t = String(topic); + if (!t.startsWith(MQTT_LED_TOPIC)) return; + if (!t.endsWith(mqttSetter)) return; + + // Get led ID + unsigned int ledID = topic[strlen(MQTT_LED_TOPIC)+1] - '0'; + if (ledID >= ledCount()) ledID = 0; + + // get value + unsigned int value = (char)payload[0] - '0'; + bool bitAuto = (value & 0x02) > 0; + bool bitState = (value & 0x01) > 0; + + // Check ledAuto + if (ledID == 0) { + ledAuto = bitAuto ? bitState : false; + setSetting("ledAuto", String() + (ledAuto ? "1" : "0")); + if (bitAuto) return; + } + + // Action to perform + ledStatus(ledID, bitState); + + } + +} + +unsigned char ledCount() { + return _leds.size(); +} + +void ledConfigure() { + ledAuto = getSetting("ledAuto", String() + LED_AUTO).toInt() == 1; +} + void ledSetup() { - pinMode(LED_PIN, OUTPUT); + + #ifdef LED1_PIN + _leds.push_back((led_t) { LED1_PIN, LED1_PIN_INVERSE }); + #endif + #ifdef LED2_PIN + _leds.push_back((led_t) { LED2_PIN, LED2_PIN_INVERSE }); + #endif + #ifdef LED3_PIN + _leds.push_back((led_t) { LED3_PIN, LED3_PIN_INVERSE }); + #endif + #ifdef LED4_PIN + _leds.push_back((led_t) { LED4_PIN, LED4_PIN_INVERSE }); + #endif + + for (unsigned int i=0; i < _leds.size(); i++) { + pinMode(_leds[i].pin, OUTPUT); + ledStatus(i, false); + } + + ledConfigure(); + + mqttRegister(ledMQTTCallback); + + DEBUG_MSG("[LED] Number of leds: %d\n", _leds.size()); + } void ledLoop() { - showStatus(); + if (ledAuto) showStatus(); } #else diff --git a/code/src/main.ino b/code/src/main.ino index c376f2bb..8019104d 100644 --- a/code/src/main.ino +++ b/code/src/main.ino @@ -29,6 +29,7 @@ along with this program. If not, see . #include #include #include "FS.h" +void mqttRegister(void (*callback)(unsigned int, const char *, const char *)); template bool setSetting(const String& key, T value); template String getSetting(const String& key, T defaultValue);