Browse Source

LED modes

fastled
Xose Pérez 7 years ago
parent
commit
96202f7967
7 changed files with 3230 additions and 3113 deletions
  1. +6
    -9
      code/espurna/config/general.h
  2. +29
    -11
      code/espurna/config/hardware.h
  3. BIN
      code/espurna/data/index.html.gz
  4. +118
    -49
      code/espurna/led.ino
  5. +5
    -11
      code/espurna/relay.ino
  6. +3047
    -3031
      code/espurna/static/index.html.gz.h
  7. +25
    -2
      code/html/index.html

+ 6
- 9
code/espurna/config/general.h View File

@ -251,15 +251,12 @@ PROGMEM const char* const custom_reset_string[] = {
// 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 a defined LED to show wifi status.
#define LED_AUTO 1
// LED # to use as WIFI status indicator
#ifndef LED_WIFI
#define LED_WIFI 1
#endif
#define LED_MODE_MQTT 0 // LED will be managed from MQTT (OFF by default)
#define LED_MODE_WIFI 1 // LED will blink according to the WIFI status
#define LED_MODE_FOLLOW 2 // LED will follow state of linked relay (check RELAY#_LED)
#define LED_MODE_FOLLOW_INVERSE 3 // LED will follow the opposite state of linked relay (check RELAY#_LED)
#define LED_MODE_FINDME 4 // LED will be ON if all relays are OFF
#define LED_MODE_MIXED 5 // A mixed between WIFI and FINDME
// -----------------------------------------------------------------------------
// WIFI


+ 29
- 11
code/espurna/config/hardware.h View File

@ -13,9 +13,10 @@
// - BUTTON_SET_PULLUP: set pullup by software
// RELAY#_PIN: GPIO for the n-th relay (1-based, up to 4 relays)
// RELAY#_TYPE: Relay can be RELAY_TYPE_NORMAL, RELAY_TYPE_INVERSE or RELAY_TYPE_LATCHED
// RELAY#_LED: LED number that will be bind to the n-th relay (1-based)
// LED#_PIN: GPIO for the n-th LED (1-based, up to 4 LEDs)
// LED#_PIN_INVERSE: LED has inversed logic (lit when pulled down)
// LED#_MODE: Check hardware.h for LED_MODE_%
// LED#_RELAY: Linked relay (1-based)
//
// Besides, other hardware specific information should be stated here
@ -100,11 +101,13 @@
#define RELAY1_TYPE RELAY_TYPE_INVERSE
// LEDs
#define LED1_PIN 5
#define LED1_PIN_INVERSE 0
#define LED1_PIN 2
#define LED1_PIN_INVERSE 1
// HLW8012
#ifndef POWER_PROVIDER
#define POWER_PROVIDER POWER_PROVIDER_HLW8012
#endif
#define HLW8012_SEL_PIN 2
#define HLW8012_CF1_PIN 13
#define HLW8012_CF_PIN 14
@ -145,7 +148,9 @@
#define LED1_PIN_INVERSE 0
// HLW8012
#ifndef POWER_PROVIDER
#define POWER_PROVIDER POWER_PROVIDER_HLW8012
#endif
#define HLW8012_SEL_PIN 5
#define HLW8012_CF1_PIN 13
#define HLW8012_CF_PIN 14
@ -1321,17 +1326,30 @@
#define RELAY4_DELAY_OFF 0
#endif
#ifndef RELAY1_LED
#define RELAY1_LED 0
#ifndef LED1_MODE
#define LED1_MODE LED_MODE_WIFI
#endif
#ifndef LED2_MODE
#define LED2_MODE LED_MODE_MQTT
#endif
#ifndef LED3_MODE
#define LED3_MODE LED_MODE_MQTT
#endif
#ifndef LED4_MODE
#define LED4_MODE LED_MODE_MQTT
#endif
#ifndef LED1_RELAY
#define LED1_RELAY 1
#endif
#ifndef RELAY2_LED
#define RELAY2_LED 0
#ifndef LED2_RELAY
#define LED2_RELAY 2
#endif
#ifndef RELAY3_LED
#define RELAY3_LED 0
#ifndef LED3_RELAY
#define LED3_RELAY 3
#endif
#ifndef RELAY4_LED
#define RELAY4_LED 0
#ifndef LED4_RELAY
#define LED4_RELAY 4
#endif
// Needed for ESP8285 boards under Windows using PlatformIO (?)


BIN
code/espurna/data/index.html.gz View File


+ 118
- 49
code/espurna/led.ino View File

@ -13,53 +13,60 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
typedef struct {
unsigned char pin;
bool reverse;
unsigned char mode;
unsigned char relay;
} led_t;
std::vector<led_t> _leds;
bool ledAuto;
bool ledStatus(unsigned char id) {
if (id >= _leds.size()) return false;
// -----------------------------------------------------------------------------
bool _ledStatus(unsigned char id) {
if (id >= _ledCount()) return false;
bool status = digitalRead(_leds[id].pin);
return _leds[id].reverse ? !status : status;
}
bool ledStatus(unsigned char id, bool status) {
if (id >= _leds.size()) return false;
bool _ledStatus(unsigned char id, bool status) {
if (id >=_ledCount()) return false;
bool s = _leds[id].reverse ? !status : status;
digitalWrite(_leds[id].pin, _leds[id].reverse ? !status : status);
return status;
}
bool ledToggle(unsigned char id) {
if (id >= _leds.size()) return false;
return ledStatus(id, !ledStatus(id));
bool _ledToggle(unsigned char id) {
if (id >= _ledCount()) return false;
return _ledStatus(id, !_ledStatus(id));
}
void ledBlink(unsigned char id, unsigned long delayOff, unsigned long delayOn) {
if (id >= _leds.size()) return;
unsigned char _ledMode(unsigned char id) {
if (id >= _ledCount()) return false;
return _leds[id].mode;
}
void _ledMode(unsigned char id, unsigned char mode) {
if (id >= _ledCount()) return;
_leds[id].mode = mode;
}
void _ledBlink(unsigned char id, unsigned long delayOff, unsigned long delayOn) {
if (id >= _ledCount()) return;
static unsigned long next = millis();
if (next < millis()) {
next += (ledToggle(id) ? delayOn : delayOff);
next += (_ledToggle(id) ? delayOn : delayOff);
}
}
#if LED_WIFI
void showStatus() {
if (wifiConnected()) {
if (WiFi.getMode() == WIFI_AP) {
ledBlink(LED_WIFI - 1, 2500, 2500);
} else {
ledBlink(LED_WIFI - 1, 4900, 100);
}
} else {
ledBlink(LED_WIFI - 1, 500, 500);
}
#if WEB_SUPPORT
void _ledWebSocketOnSend(JsonObject& root) {
if (_ledCount() == 0) return;
root["ledVisible"] = 1;
root["ledMode0"] = _ledMode(0);
}
#endif
#if MQTT_SUPPORT
void ledMQTTCallback(unsigned int type, const char * topic, const char * payload) {
void _ledMQTTCallback(unsigned int type, const char * topic, const char * payload) {
static bool isFirstMessage = true;
@ -77,72 +84,134 @@ void ledMQTTCallback(unsigned int type, const char * topic, const char * payload
// Get led ID
unsigned int ledID = t.substring(strlen(MQTT_TOPIC_LED)+1).toInt();
if (ledID >= ledCount()) {
if (ledID >= _ledCount()) {
DEBUG_MSG_P(PSTR("[LED] Wrong ledID (%d)\n"), ledID);
return;
}
// Check if LED is managed
if (_ledMode(ledID) != LED_MODE_MQTT) return;
// 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;
}
unsigned char value = relayParsePayload(payload);
// Action to perform
ledStatus(ledID, bitState);
if (value == 2) {
_ledToggle(ledID);
} else {
_ledStatus(ledID, value == 1);
}
}
}
#endif
unsigned char ledCount() {
unsigned char _ledCount() {
return _leds.size();
}
void ledConfigure() {
ledAuto = getSetting("ledAuto", String() + LED_AUTO).toInt() == 1;
void _ledConfigure() {
for (unsigned int i=0; i < _leds.size(); i++) {
_ledMode(i, getSetting("ledMode", i, _ledMode(i)).toInt());
}
}
// -----------------------------------------------------------------------------
void ledSetup() {
#ifdef LED1_PIN
_leds.push_back((led_t) { LED1_PIN, LED1_PIN_INVERSE });
_leds.push_back((led_t) { LED1_PIN, LED1_PIN_INVERSE, LED1_MODE, LED1_RELAY });
#endif
#ifdef LED2_PIN
_leds.push_back((led_t) { LED2_PIN, LED2_PIN_INVERSE });
_leds.push_back((led_t) { LED2_PIN, LED2_PIN_INVERSE, LED2_MODE, LED2_RELAY });
#endif
#ifdef LED3_PIN
_leds.push_back((led_t) { LED3_PIN, LED3_PIN_INVERSE });
_leds.push_back((led_t) { LED3_PIN, LED3_PIN_INVERSE, LED3_MODE, LED3_RELAY });
#endif
#ifdef LED4_PIN
_leds.push_back((led_t) { LED4_PIN, LED4_PIN_INVERSE });
_leds.push_back((led_t) { LED4_PIN, LED4_PIN_INVERSE, LED4_MODE, LED4_RELAY });
#endif
for (unsigned int i=0; i < _leds.size(); i++) {
pinMode(_leds[i].pin, OUTPUT);
ledStatus(i, false);
_ledStatus(i, false);
}
ledConfigure();
_ledConfigure();
#if MQTT_SUPPORT
mqttRegister(ledMQTTCallback);
mqttRegister(_ledMQTTCallback);
#endif
#if WEB_SUPPORT
wsOnSendRegister(_ledWebSocketOnSend);
wsOnAfterParseRegister(_ledConfigure);
#endif
DEBUG_MSG_P(PSTR("[LED] Number of leds: %d\n"), _leds.size());
DEBUG_MSG_P(PSTR("[LED] Led auto indicator is %s\n"), ledAuto ? "ON" : "OFF" );
}
void ledLoop() {
#if LED_WIFI
if (ledAuto) showStatus();
#endif
for (unsigned char i=0; i<_leds.size(); i++) {
if (_ledMode(i) == LED_MODE_WIFI) {
if (wifiConnected()) {
if (WiFi.getMode() == WIFI_AP) {
_ledBlink(i, 900, 100);
} else {
_ledBlink(i, 4900, 100);
}
} else {
_ledBlink(i, 500, 500);
}
}
if (_ledMode(i) == LED_MODE_MIXED) {
if (wifiConnected()) {
if (relayStatus(_leds[i].relay-1)) {
if (WiFi.getMode() == WIFI_AP) {
_ledBlink(i, 900, 100);
} else {
_ledBlink(i, 4900, 100);
}
} else {
if (WiFi.getMode() == WIFI_AP) {
_ledBlink(i, 100, 900);
} else {
_ledBlink(i, 100, 4900);
}
}
} else {
_ledBlink(i, 500, 500);
}
}
if (_ledMode(i) == LED_MODE_FOLLOW) {
_ledStatus(i, relayStatus(_leds[i].relay-1));
}
if (_ledMode(i) == LED_MODE_FOLLOW_INVERSE) {
_ledStatus(i, !relayStatus(_leds[i].relay-1));
}
if (_ledMode(i) == LED_MODE_FINDME) {
bool status = true;
for (unsigned char k=0; k<relayCount(); k++) {
if (relayStatus(k)) {
status = false;
break;
}
}
_ledStatus(i, status);
}
}
}

+ 5
- 11
code/espurna/relay.ino View File

@ -19,7 +19,6 @@ typedef struct {
unsigned char pin; // GPIO pin for the relay
unsigned char type;
unsigned char reset_pin;
unsigned char led;
unsigned long delay_on;
unsigned long delay_off;
@ -370,7 +369,7 @@ void _relayWebSocketOnSend(JsonObject& root) {
if (relayCount() == 0) return;
root["relayVisible"] = 1;
// Statuses
JsonArray& relay = root.createNestedArray("relayStatus");
for (unsigned char relayID=0; relayID<relayCount(); relayID++) {
@ -642,16 +641,16 @@ void relaySetup() {
#else
#ifdef RELAY1_PIN
_relays.push_back((relay_t) { RELAY1_PIN, RELAY1_TYPE, RELAY1_RESET_PIN, RELAY1_LED, RELAY1_DELAY_ON, RELAY1_DELAY_OFF });
_relays.push_back((relay_t) { RELAY1_PIN, RELAY1_TYPE, RELAY1_RESET_PIN, RELAY1_DELAY_ON, RELAY1_DELAY_OFF });
#endif
#ifdef RELAY2_PIN
_relays.push_back((relay_t) { RELAY2_PIN, RELAY2_TYPE, RELAY2_RESET_PIN, RELAY2_LED, RELAY2_DELAY_ON, RELAY2_DELAY_OFF });
_relays.push_back((relay_t) { RELAY2_PIN, RELAY2_TYPE, RELAY2_RESET_PIN, RELAY2_DELAY_ON, RELAY2_DELAY_OFF });
#endif
#ifdef RELAY3_PIN
_relays.push_back((relay_t) { RELAY3_PIN, RELAY3_TYPE, RELAY3_RESET_PIN, RELAY3_LED, RELAY3_DELAY_ON, RELAY3_DELAY_OFF });
_relays.push_back((relay_t) { RELAY3_PIN, RELAY3_TYPE, RELAY3_RESET_PIN, RELAY3_DELAY_ON, RELAY3_DELAY_OFF });
#endif
#ifdef RELAY4_PIN
_relays.push_back((relay_t) { RELAY4_PIN, RELAY4_TYPE, RELAY4_RESET_PIN, RELAY4_LED, RELAY4_DELAY_ON, RELAY4_DELAY_OFF });
_relays.push_back((relay_t) { RELAY4_PIN, RELAY4_TYPE, RELAY4_RESET_PIN, RELAY4_DELAY_ON, RELAY4_DELAY_OFF });
#endif
#endif
@ -696,11 +695,6 @@ void relayLoop(void) {
// Call the provider to perform the action
_relayProviderStatus(id, status);
// Change the binded LED if any
if (_relays[id].led > 0) {
ledStatus(_relays[id].led - 1, status);
}
// Send MQTT
#if MQTT_SUPPORT
relayMQTT(id);


+ 3047
- 3031
code/espurna/static/index.html.gz.h
File diff suppressed because it is too large
View File


+ 25
- 2
code/html/index.html View File

@ -306,14 +306,17 @@
<label class="pure-u-1 pure-u-md-1-4">Hostname</label>
<input name="hostname" class="pure-u-1 pure-u-md-3-4" type="text" action="reboot" tabindex="1" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">This name will identify this device in your network (http://&lt;hostname&gt;.local). For this setting to take effect you should restart the wifi interface clicking the "Reconnect" button.</div>
<div class="pure-u-1 pure-u-md-3-4 hint">
This name will identify this device in your network (http://&lt;hostname&gt;.local). For this setting to take effect you should restart the wifi interface clicking the "Reconnect" button.
</div>
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4">Double click delay</label>
<input name="btnDelay" class="pure-u-1 pure-u-md-3-4" type="number" action="reboot" min="0" step="100" max="1000" tabindex="6" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Delay in milliseconds to detect a double click (from 0 to 1000ms).<br />
<div class="pure-u-1 pure-u-md-3-4 hint">
Delay in milliseconds to detect a double click (from 0 to 1000ms).<br />
The lower this number the faster the device will respond to button clicks but the harder it will be to get a double click.
Increase this number if you are having trouble to double click the button.
Set this value to 0 to disable double click. You won't be able to set the device in AP mode manually but your device will respond immediately to button clicks.<br />
@ -321,6 +324,26 @@
</div>
</div>
<div class="pure-g module module-led">
<label class="pure-u-1 pure-u-md-1-4">LED mode</label>
<div class="pure-u-1 pure-u-md-3-4">
<select name="ledMode0" tabindex="7">
<option value="1">WiFi status</option>
<option value="0">MQTT managed</option>
<option value="4">Find me</option>
<option value="5">Mixed</option>
</select>
</div>
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">
This setting defines the behaviour of the main LED in the board.<br />
When in "WiFi status" it will blink at 1Hz when trying to connecting. If successfully connected if will briefly lit every 5 seconds if in STA mode or every second if in AP mode.<br />
When in "MQTT managed" mode you will be able to set the LED state sending a message to "&lt;base_topic&gt;/led/0/set" with a payload of 0, 1 or 2 (to toggle it).<br />
When in "Find me" mode the LED will be ON when all relays are OFF. This is meant to locate switches at night.<br />
When in "Mixed" mode it will follow the WiFi status but will stay mostly on when relays are OFF, and mostly OFF when any of them is ON.
</div>
</div>
<div class="pure-g module module-alexa">
<div class="pure-u-1 pure-u-sm-1-4"><label>Alexa integration</label></div>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" name="alexaEnabled" tabindex="13" /></div>


Loading…
Cancel
Save