update to 2.20

update to 2.20
This commit is contained in:
BPoH_Voodoo
2019-01-28 14:25:40 +01:00
parent 9fb3f96e5f
commit 6d524787bd
31 changed files with 2259 additions and 1039 deletions
+10 -2
View File
@@ -1,4 +1,12 @@
clients/web/node_modules/ clients/web/node_modules/
clients/web/\.vscode/ clients/web/\.vscode/
*.DS_Store
.pioenvs
.piolibdeps
lib/readme.txt
*.h.gch
.clang_complete
.gcc-flags.json
.vscode/*
+6
View File
@@ -0,0 +1,6 @@
[submodule "Arduino/McLighting/data/McLightingUI"]
path = Arduino/McLighting/data/McLightingUI
url = https://github.com/toblum/McLightingUI
[submodule "clients/web/McLightingUI"]
path = clients/web/McLightingUI
url = https://github.com/toblum/McLightingUI
+14
View File
@@ -0,0 +1,14 @@
language: python
python:
- "2.7"
sudo: false
cache:
directories:
- "~/.platformio"
env:
- PLATFORMIO_CI_SRC=Arduino/McLighting
install:
- pip install -U platformio
- platformio update
script:
- platformio ci --project-conf=./platformio.ini -v
+1 -1
View File
@@ -1,4 +1,4 @@
#include <brzo_i2c.h> #include <brzo_i2c.h> //https://github.com/pasko-zh/brzo_i2c
/**************************************************************************/ /**************************************************************************/
/*! /*!
+95 -43
View File
@@ -1,5 +1,4 @@
#include "definitions.h" #include "definitions.h"
#include "version.h" #include "version.h"
// *************************************************************************** // ***************************************************************************
// Load libraries for: WebServer / WiFiManager / WebSockets // Load libraries for: WebServer / WiFiManager / WebSockets
@@ -62,6 +61,18 @@
WiFiEventHandler wifiDisconnectHandler; WiFiEventHandler wifiDisconnectHandler;
#endif #endif
#ifdef ARDUINOJSON_VERSION
#if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR == 7)
#error "Install ArduinoJson v6.7.0-beta"
#endif
#endif
#ifdef ENABLE_E131
#include <ESPAsyncUDP.h> //https://github.com/me-no-dev/ESPAsyncUDP
#include <ESPAsyncE131.h> //https://github.com/forkineye/ESPAsyncE131
ESPAsyncE131 e131(END_UNIVERSE - START_UNIVERSE + 1);
#endif
// *************************************************************************** // ***************************************************************************
// Instanciate HTTP(80) / WebSockets(81) Server // Instanciate HTTP(80) / WebSockets(81) Server
@@ -74,32 +85,6 @@ WebSocketsServer webSocket = WebSocketsServer(81);
ESP8266HTTPUpdateServer httpUpdater; ESP8266HTTPUpdateServer httpUpdater;
#endif #endif
#ifdef USE_NEOANIMATIONFX
// ***************************************************************************
// Load libraries / Instanciate NeoAnimationFX library
// ***************************************************************************
// https://github.com/debsahu/NeoAnimationFX
#include "NeoAnimationFX.h"
#define NEOMETHOD NeoPBBGRB800
NEOMETHOD neoStrip(NUMLEDS);
NeoAnimationFX<NEOMETHOD> strip(neoStrip);
// Uses Pin RX / GPIO3 (Only pin that is supported, due to hardware limitations)
// NEOMETHOD NeoPBBGRB800 uses GRB config 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEOMETHOD NeoPBBGRB400 uses GRB config 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEOMETHOD NeoPBBRGB800 uses RGB config 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEOMETHOD NeoPBBRGB400 uses RGB config 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// Uses Pin D4 / GPIO2 (Only pin that is supported, due to hardware limitations)
// NEOMETHOD NeoPBBGRBU800 uses GRB config 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEOMETHOD NeoPBBGRBU400 uses GRB config 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEOMETHOD NeoPBBRGBU800 uses RGB config 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEOMETHOD NeoPBBRGBU400 uses RGB config 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
#endif
#ifdef USE_WS2812FX
// *************************************************************************** // ***************************************************************************
// Load libraries / Instanciate WS2812FX library // Load libraries / Instanciate WS2812FX library
// *************************************************************************** // ***************************************************************************
@@ -124,6 +109,23 @@ NeoAnimationFX<NEOMETHOD> strip(neoStrip);
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input // pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting // and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first. // on a live circuit...if you must, connect GND first.
#ifdef USE_WS2812FX_DMA
#include <NeoPixelBus.h>
NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 3); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//NeoEsp8266Dma400KbpsMethod dma = NeoEsp8266Dma400KbpsMethod(NUMLEDS, 3); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
#endif
#ifdef USE_WS2812FX_UART
#include <NeoPixelBus.h>
NeoEsp8266Uart800KbpsMethod dma = NeoEsp8266Uart800KbpsMethod(NUMLEDS, 3);
#endif
#if defined(USE_WS2812FX_DMA) or defined(USE_WS2812FX_UART)
void DMA_Show(void) {
if(dma.IsReadyToUpdate()) {
memcpy(dma.getPixels(), strip.getPixels(), dma.getPixelsSize());
dma.Update();
}
}
#endif #endif
// *************************************************************************** // ***************************************************************************
@@ -252,7 +254,7 @@ void setup() {
pinMode(BUILTIN_LED, OUTPUT); pinMode(BUILTIN_LED, OUTPUT);
// button pin setup // button pin setup
#ifdef ENABLE_BUTTON #ifdef ENABLE_BUTTON
pinMode(BUTTON, INPUT_PULLUP); pinMode(BUTTON,INPUT_PULLUP);
#endif #endif
#ifdef ENABLE_BUTTON_GY33 #ifdef ENABLE_BUTTON_GY33
@@ -293,10 +295,14 @@ DBG_OUTPUT_PORT.println("Starting....");
// Setup: Neopixel // Setup: Neopixel
// *************************************************************************** // ***************************************************************************
strip.init(); strip.init();
#if defined(USE_WS2812FX_DMA) or defined(USE_WS2812FX_UART)
dma.Initialize();
strip.setCustomShow(DMA_Show);
#endif
strip.setBrightness(brightness); strip.setBrightness(brightness);
strip.setSpeed(convertSpeed(ws2812fx_speed)); strip.setSpeed(convertSpeed(ws2812fx_speed));
//strip.setMode(FX_MODE_RAINBOW_CYCLE); //strip.setMode(FX_MODE_RAINBOW_CYCLE);
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
strip.start(); strip.start();
// *************************************************************************** // ***************************************************************************
@@ -350,11 +356,15 @@ DBG_OUTPUT_PORT.println("Starting....");
// Uncomment if you want to restart ESP8266 if it cannot connect to WiFi. // Uncomment if you want to restart ESP8266 if it cannot connect to WiFi.
// Value in brackets is in seconds that WiFiManger waits until restart // Value in brackets is in seconds that WiFiManger waits until restart
//wifiManager.setConfigPortalTimeout(180); #ifdef WIFIMGR_PORTAL_TIMEOUT
wifiManager.setConfigPortalTimeout(WIFIMGR_PORTAL_TIMEOUT);
#endif
// Uncomment if you want to set static IP // Uncomment if you want to set static IP
// Order is: IP, Gateway and Subnet // Order is: IP, Gateway and Subnet
//wifiManager.setSTAStaticIPConfig(IPAddress(192,168,0,128), IPAddress(192,168,0,1), IPAddress(255,255,255,0)); #ifdef WIFIMGR_SET_MANUAL_IP
wifiManager.setSTAStaticIPConfig(IPAddress(_ip[0], _ip[1], _ip[2], _ip[3]), IPAddress(_gw[0], _gw[1], _gw[2], _gw[3]), IPAddress(_sn[0], _sn[1], _sn[2], _sn[3]));
#endif
//fetches ssid and pass and tries to connect //fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name //if it does not connect it starts an access point with the specified name
@@ -363,7 +373,7 @@ DBG_OUTPUT_PORT.println("Starting....");
if (!wifiManager.autoConnect(HOSTNAME)) { if (!wifiManager.autoConnect(HOSTNAME)) {
DBG_OUTPUT_PORT.println("failed to connect and hit timeout"); DBG_OUTPUT_PORT.println("failed to connect and hit timeout");
//reset and try again, or maybe put it to deep sleep //reset and try again, or maybe put it to deep sleep
ESP.reset(); //Will be removed when upgrading to standalone offline McLightingUI version ESP.reset(); //Will be removed when upgrading to standalone offline McLightingUI version
delay(1000); //Will be removed when upgrading to standalone offline McLightingUI version delay(1000); //Will be removed when upgrading to standalone offline McLightingUI version
} }
@@ -448,6 +458,10 @@ ESP.reset(); //Will be removed when upgrading to standalone offline McLightingU
// *************************************************************************** // ***************************************************************************
// Configure MQTT // Configure MQTT
// *************************************************************************** // ***************************************************************************
#ifdef ENABLE_MQTT_HOSTNAME_CHIPID
snprintf(mqtt_clientid, 64, "%s-%08X", HOSTNAME, ESP.getChipId());
#endif
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
if (mqtt_host != "" && atoi(mqtt_port) > 0) { if (mqtt_host != "" && atoi(mqtt_port) > 0) {
snprintf(mqtt_intopic, sizeof mqtt_intopic, "%s/in", HOSTNAME); snprintf(mqtt_intopic, sizeof mqtt_intopic, "%s/in", HOSTNAME);
@@ -539,12 +553,15 @@ ESP.reset(); //Will be removed when upgrading to standalone offline McLightingU
json["core_version"] = ESP.getCoreVersion(); json["core_version"] = ESP.getCoreVersion();
json["cpu_freq"] = ESP.getCpuFreqMHz(); json["cpu_freq"] = ESP.getCpuFreqMHz();
json["chip_id"] = ESP.getFlashChipId(); json["chip_id"] = ESP.getFlashChipId();
#ifndef USE_NEOANIMATIONFX #if defined(USE_WS2812FX_DMA)
json["animation_lib"] = "WS2812FX_DMA";
json["pin"] = 3;
#elif defined(USE_WS2812FX_UART)
json["animation_lib"] = "WS2812FX_UART";
json["pin"] = 2;
#else
json["animation_lib"] = "WS2812FX"; json["animation_lib"] = "WS2812FX";
json["pin"] = PIN; json["pin"] = PIN;
#else
json["animation_lib"] = "NeoAnimationFX";
json["pin"] = "Ignored, check NEOMETHOD";
#endif #endif
json["number_leds"] = NUMLEDS; json["number_leds"] = NUMLEDS;
#ifdef ENABLE_BUTTON #ifdef ENABLE_BUTTON
@@ -694,7 +711,7 @@ ESP.reset(); //Will be removed when upgrading to standalone offline McLightingU
server.on("/get_color", []() { server.on("/get_color", []() {
char rgbcolor[9]; char rgbcolor[9];
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.white, main_color.red, main_color.green, main_color.blue); snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.red, main_color.green, main_color.blue, main_color.white);
server.sendHeader("Access-Control-Allow-Origin", "*"); server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", rgbcolor ); server.send(200, "text/plain", rgbcolor );
DBG_OUTPUT_PORT.print("/get_color: "); DBG_OUTPUT_PORT.print("/get_color: ");
@@ -885,6 +902,26 @@ ESP.reset(); //Will be removed when upgrading to standalone offline McLightingU
#endif #endif
}); });
#ifdef ENABLE_E131
server.on("/e131", []() {
exit_func = true;
mode = E131;
getStatusJSON();
#ifdef ENABLE_MQTT
mqtt_client.publish(mqtt_outtopic, String("OK =e131").c_str());
#endif
#ifdef ENABLE_AMQTT
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =131").c_str());
#endif
#ifdef ENABLE_HOMEASSISTANT
stateOn = true;
#endif
#ifdef ENABLE_STATE_SAVE_SPIFFS
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
#endif
});
#endif
server.on("/tv", []() { server.on("/tv", []() {
exit_func = true; exit_func = true;
mode = TV; mode = TV;
@@ -939,6 +976,15 @@ ESP.reset(); //Will be removed when upgrading to standalone offline McLightingU
if (mdns_result) { if (mdns_result) {
MDNS.addService("http", "tcp", 80); MDNS.addService("http", "tcp", 80);
} }
#ifdef ENABLE_E131
// Choose one to begin listening for E1.31 data
// if (e131.begin(E131_UNICAST)) // Listen via Unicast
if (e131.begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) // Listen via Multicast
Serial.println(F("Listening for data..."));
else
Serial.println(F("*** e131.begin failed ***"));
#endif
#ifdef ENABLE_STATE_SAVE_SPIFFS #ifdef ENABLE_STATE_SAVE_SPIFFS
(readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); (readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!");
#endif #endif
@@ -950,7 +996,7 @@ ESP.reset(); //Will be removed when upgrading to standalone offline McLightingU
DBG_OUTPUT_PORT.printf("Found saved state: %s\n", saved_state_string.c_str()); DBG_OUTPUT_PORT.printf("Found saved state: %s\n", saved_state_string.c_str());
setModeByStateString(saved_state_string); setModeByStateString(saved_state_string);
} }
sprintf(last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.white, main_color.red, main_color.green, main_color.blue); sprintf(last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white);
#endif #endif
#ifdef ENABLE_BUTTON_GY33 #ifdef ENABLE_BUTTON_GY33
@@ -1019,7 +1065,7 @@ void loop() {
// mode = HOLD; // mode = HOLD;
} }
if (mode == SETCOLOR) { if (mode == SETCOLOR) {
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
strip.trigger(); strip.trigger();
mode = (prevmode == SET_MODE) ? SETSPEED : HOLD; mode = (prevmode == SET_MODE) ? SETSPEED : HOLD;
} }
@@ -1036,7 +1082,7 @@ void loop() {
} }
#ifdef ENABLE_LEGACY_ANIMATIONS #ifdef ENABLE_LEGACY_ANIMATIONS
if (mode == WIPE) { if (mode == WIPE) {
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
strip.setMode(FX_MODE_COLOR_WIPE); strip.setMode(FX_MODE_COLOR_WIPE);
strip.trigger(); strip.trigger();
mode = HOLD; mode = HOLD;
@@ -1052,13 +1098,13 @@ void loop() {
mode = HOLD; mode = HOLD;
} }
if (mode == THEATERCHASE) { if (mode == THEATERCHASE) {
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
strip.setMode(FX_MODE_THEATER_CHASE); strip.setMode(FX_MODE_THEATER_CHASE);
strip.trigger(); strip.trigger();
mode = HOLD; mode = HOLD;
} }
if (mode == TWINKLERANDOM) { if (mode == TWINKLERANDOM) {
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
strip.setMode(FX_MODE_TWINKLE_RANDOM); strip.setMode(FX_MODE_TWINKLE_RANDOM);
strip.trigger(); strip.trigger();
mode = HOLD; mode = HOLD;
@@ -1068,6 +1114,11 @@ void loop() {
strip.trigger(); strip.trigger();
mode = HOLD; mode = HOLD;
} }
#ifdef ENABLE_E131
if (mode == E131) {
handleE131();
}
#endif
#endif #endif
if (mode == HOLD || mode == CUSTOM) { if (mode == HOLD || mode == CUSTOM) {
if(!strip.isRunning()) strip.start(); if(!strip.isRunning()) strip.start();
@@ -1076,6 +1127,7 @@ void loop() {
exit_func = false; exit_func = false;
} }
#endif #endif
if (prevmode == SET_MODE) prevmode = HOLD;
} }
#ifdef ENABLE_LEGACY_ANIMATIONS #ifdef ENABLE_LEGACY_ANIMATIONS
if (mode == TV) { if (mode == TV) {
@@ -1101,7 +1153,7 @@ void loop() {
#ifdef ENABLE_STATE_SAVE_EEPROM #ifdef ENABLE_STATE_SAVE_EEPROM
// Check for state changes // Check for state changes
sprintf(current_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, strip.getMode(), ws2812fx_speed, brightness, main_color.white, main_color.red, main_color.green, main_color.blue); sprintf(current_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, strip.getMode(), ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white);
if (strcmp(current_state, last_state) != 0) { if (strcmp(current_state, last_state) != 0) {
// DBG_OUTPUT_PORT.printf("STATE CHANGED: %s / %s\n", last_state, current_state); // DBG_OUTPUT_PORT.printf("STATE CHANGED: %s / %s\n", last_state, current_state);
File diff suppressed because it is too large Load Diff
+297 -131
View File
@@ -37,42 +37,85 @@
#ifndef WS2812FX_h #ifndef WS2812FX_h
#define WS2812FX_h #define WS2812FX_h
#define FSH(x) (__FlashStringHelper*)(x)
#include <Adafruit_NeoPixel.h> #include <Adafruit_NeoPixel.h>
#define DEFAULT_BRIGHTNESS 50 #define DEFAULT_BRIGHTNESS (uint8_t)50
#define DEFAULT_MODE 0 #define DEFAULT_MODE (uint8_t)0
#define DEFAULT_SPEED 1000 #define DEFAULT_SPEED (uint16_t)1000
#define DEFAULT_COLOR 0x00FF0000 #define DEFAULT_COLOR (uint32_t)0xFF0000
#define SPEED_MIN 10 #if defined(ESP8266) || defined(ESP32)
#define SPEED_MAX 65535 //#pragma message("Compiling for ESP")
#define SPEED_MIN (uint16_t)2
#else
//#pragma message("Compiling for Arduino")
#define SPEED_MIN (uint16_t)10
#endif
#define SPEED_MAX (uint16_t)65535
#define BRIGHTNESS_MIN 0 #define BRIGHTNESS_MIN (uint8_t)0
#define BRIGHTNESS_MAX 255 #define BRIGHTNESS_MAX (uint8_t)255
/* each segment uses 36 bytes of SRAM memory, so if you're application fails because of /* each segment uses 36 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#define MAX_NUM_SEGMENTS 10 #define MAX_NUM_SEGMENTS 10
#define NUM_COLORS 3 /* number of colors per segment */ #define NUM_COLORS 3 /* number of colors per segment */
#define MAX_CUSTOM_MODES 4
#define SEGMENT _segments[_segment_index] #define SEGMENT _segments[_segment_index]
#define SEGMENT_RUNTIME _segment_runtimes[_segment_index] #define SEGMENT_RUNTIME _segment_runtimes[_segment_index]
#define SEGMENT_LENGTH (SEGMENT.stop - SEGMENT.start + 1) #define SEGMENT_LENGTH (SEGMENT.stop - SEGMENT.start + 1)
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
// some common colors // some common colors
#define RED 0x00FF0000 #define RED (uint32_t)0xFF0000
#define GREEN 0x0000FF00 #define GREEN (uint32_t)0x00FF00
#define BLUE 0x000000FF #define BLUE (uint32_t)0x0000FF
#define WHITE 0x00FFFFFF #define WHITE (uint32_t)0xFFFFFF
#define BLACK 0x00000000 #define BLACK (uint32_t)0x000000
#define YELLOW 0x00FFFF00 #define YELLOW (uint32_t)0xFFFF00
#define CYAN 0x0000FFFF #define CYAN (uint32_t)0x00FFFF
#define MAGENTA 0x00FF00FF #define MAGENTA (uint32_t)0xFF00FF
#define PURPLE 0x00400080 #define PURPLE (uint32_t)0x400080
#define ORANGE 0x00FF3000 #define ORANGE (uint32_t)0xFF3000
#define ULTRAWHITE 0xFFFFFFFF #define PINK (uint32_t)0xFF1493
#define ULTRAWHITE (uint32_t)0xFFFFFFFF
#define DARK(c) (uint32_t)((c >> 4) & 0x0f0f0f0f)
#define MODE_COUNT 57 // segment options
// bit 7: reverse animation
// bits 4-6: fade rate (0-7)
// bit 3: gamma correction
// bits 1-2: size
// bits 0: TBD
#define NO_OPTIONS (uint8_t)B00000000
#define REVERSE (uint8_t)B10000000
#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE)
#define FADE_XFAST (uint8_t)B00010000
#define FADE_FAST (uint8_t)B00100000
#define FADE_MEDIUM (uint8_t)B00110000
#define FADE_SLOW (uint8_t)B01000000
#define FADE_XSLOW (uint8_t)B01010000
#define FADE_XXSLOW (uint8_t)B01100000
#define FADE_GLACIAL (uint8_t)B01110000
#define FADE_RATE ((SEGMENT.options >> 4) & 7)
#define GAMMA (uint8_t)B00001000
#define IS_GAMMA ((SEGMENT.options & GAMMA) == GAMMA)
#define SIZE_SMALL (uint8_t)B00000000
#define SIZE_MEDIUM (uint8_t)B00000010
#define SIZE_LARGE (uint8_t)B00000100
#define SIZE_XLARGE (uint8_t)B00000110
#define SIZE_OPTION ((SEGMENT.options >> 1) & 3)
// segment runtime options (aux_param2)
#define FRAME (uint8_t)B10000000
#define SET_FRAME (SEGMENT_RUNTIME.aux_param2 |= FRAME)
#define CLR_FRAME (SEGMENT_RUNTIME.aux_param2 &= ~FRAME)
#define CYCLE (uint8_t)B01000000
#define SET_CYCLE (SEGMENT_RUNTIME.aux_param2 |= CYCLE)
#define CLR_CYCLE (SEGMENT_RUNTIME.aux_param2 &= ~CYCLE)
#define MODE_COUNT (sizeof(_names)/sizeof(_names[0]))
#define FX_MODE_STATIC 0 #define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1 #define FX_MODE_BLINK 1
@@ -130,7 +173,137 @@
#define FX_MODE_BICOLOR_CHASE 53 #define FX_MODE_BICOLOR_CHASE 53
#define FX_MODE_TRICOLOR_CHASE 54 #define FX_MODE_TRICOLOR_CHASE 54
#define FX_MODE_ICU 55 #define FX_MODE_ICU 55
#define FX_MODE_CUSTOM 56 #define FX_MODE_CUSTOM 56 // keep this for backward compatiblity
#define FX_MODE_CUSTOM_0 56 // custom modes need to go at the end
#define FX_MODE_CUSTOM_1 57
#define FX_MODE_CUSTOM_2 58
#define FX_MODE_CUSTOM_3 59
// create GLOBAL names to allow WS2812FX to compile with sketches and other libs that store strings
// in PROGMEM (get rid of the "section type conflict with __c" errors once and for all. Amen.)
const char name_0[] PROGMEM = "Static";
const char name_1[] PROGMEM = "Blink";
const char name_2[] PROGMEM = "Breath";
const char name_3[] PROGMEM = "Color Wipe";
const char name_4[] PROGMEM = "Color Wipe Inverse";
const char name_5[] PROGMEM = "Color Wipe Reverse";
const char name_6[] PROGMEM = "Color Wipe Reverse Inverse";
const char name_7[] PROGMEM = "Color Wipe Random";
const char name_8[] PROGMEM = "Random Color";
const char name_9[] PROGMEM = "Single Dynamic";
const char name_10[] PROGMEM = "Multi Dynamic";
const char name_11[] PROGMEM = "Rainbow";
const char name_12[] PROGMEM = "Rainbow Cycle";
const char name_13[] PROGMEM = "Scan";
const char name_14[] PROGMEM = "Dual Scan";
const char name_15[] PROGMEM = "Fade";
const char name_16[] PROGMEM = "Theater Chase";
const char name_17[] PROGMEM = "Theater Chase Rainbow";
const char name_18[] PROGMEM = "Running Lights";
const char name_19[] PROGMEM = "Twinkle";
const char name_20[] PROGMEM = "Twinkle Random";
const char name_21[] PROGMEM = "Twinkle Fade";
const char name_22[] PROGMEM = "Twinkle Fade Random";
const char name_23[] PROGMEM = "Sparkle";
const char name_24[] PROGMEM = "Flash Sparkle";
const char name_25[] PROGMEM = "Hyper Sparkle";
const char name_26[] PROGMEM = "Strobe";
const char name_27[] PROGMEM = "Strobe Rainbow";
const char name_28[] PROGMEM = "Multi Strobe";
const char name_29[] PROGMEM = "Blink Rainbow";
const char name_30[] PROGMEM = "Chase White";
const char name_31[] PROGMEM = "Chase Color";
const char name_32[] PROGMEM = "Chase Random";
const char name_33[] PROGMEM = "Chase Rainbow";
const char name_34[] PROGMEM = "Chase Flash";
const char name_35[] PROGMEM = "Chase Flash Random";
const char name_36[] PROGMEM = "Chase Rainbow White";
const char name_37[] PROGMEM = "Chase Blackout";
const char name_38[] PROGMEM = "Chase Blackout Rainbow";
const char name_39[] PROGMEM = "Color Sweep Random";
const char name_40[] PROGMEM = "Running Color";
const char name_41[] PROGMEM = "Running Red Blue";
const char name_42[] PROGMEM = "Running Random";
const char name_43[] PROGMEM = "Larson Scanner";
const char name_44[] PROGMEM = "Comet";
const char name_45[] PROGMEM = "Fireworks";
const char name_46[] PROGMEM = "Fireworks Random";
const char name_47[] PROGMEM = "Merry Christmas";
const char name_48[] PROGMEM = "Fire Flicker";
const char name_49[] PROGMEM = "Fire Flicker (soft)";
const char name_50[] PROGMEM = "Fire Flicker (intense)";
const char name_51[] PROGMEM = "Circus Combustus";
const char name_52[] PROGMEM = "Halloween";
const char name_53[] PROGMEM = "Bicolor Chase";
const char name_54[] PROGMEM = "Tricolor Chase";
const char name_55[] PROGMEM = "ICU";
const char name_56[] PROGMEM = "Custom 0"; // custom modes need to go at the end
const char name_57[] PROGMEM = "Custom 1";
const char name_58[] PROGMEM = "Custom 2";
const char name_59[] PROGMEM = "Custom 3";
static const __FlashStringHelper* _names[] = {
FSH(name_0),
FSH(name_1),
FSH(name_2),
FSH(name_3),
FSH(name_4),
FSH(name_5),
FSH(name_6),
FSH(name_7),
FSH(name_8),
FSH(name_9),
FSH(name_10),
FSH(name_11),
FSH(name_12),
FSH(name_13),
FSH(name_14),
FSH(name_15),
FSH(name_16),
FSH(name_17),
FSH(name_18),
FSH(name_19),
FSH(name_20),
FSH(name_21),
FSH(name_22),
FSH(name_23),
FSH(name_24),
FSH(name_25),
FSH(name_26),
FSH(name_27),
FSH(name_28),
FSH(name_29),
FSH(name_30),
FSH(name_31),
FSH(name_32),
FSH(name_33),
FSH(name_34),
FSH(name_35),
FSH(name_36),
FSH(name_37),
FSH(name_38),
FSH(name_39),
FSH(name_40),
FSH(name_41),
FSH(name_42),
FSH(name_43),
FSH(name_44),
FSH(name_45),
FSH(name_46),
FSH(name_47),
FSH(name_48),
FSH(name_49),
FSH(name_50),
FSH(name_51),
FSH(name_52),
FSH(name_53),
FSH(name_54),
FSH(name_55),
FSH(name_56),
FSH(name_57),
FSH(name_58),
FSH(name_59)
};
class WS2812FX : public Adafruit_NeoPixel { class WS2812FX : public Adafruit_NeoPixel {
@@ -143,21 +316,20 @@ class WS2812FX : public Adafruit_NeoPixel {
uint16_t stop; uint16_t stop;
uint16_t speed; uint16_t speed;
uint8_t mode; uint8_t mode;
bool reverse; uint8_t options;
uint32_t colors[NUM_COLORS]; uint32_t colors[NUM_COLORS];
} segment; } segment;
// segment runtime parameters // segment runtime parameters
public:
typedef struct Segment_runtime { // 16 bytes typedef struct Segment_runtime { // 16 bytes
unsigned long next_time; unsigned long next_time;
uint32_t counter_mode_step; uint32_t counter_mode_step;
uint32_t counter_mode_call; uint32_t counter_mode_call;
uint16_t aux_param; uint8_t aux_param; // auxilary param (usually stores a color_wheel index)
uint16_t aux_param2; uint8_t aux_param2; // auxilary param (usually stores bitwise options)
uint16_t aux_param3; // auxilary param (usually stores a segment index)
} segment_runtime; } segment_runtime;
public:
WS2812FX(uint16_t n, uint8_t p, neoPixelType t) : Adafruit_NeoPixel(n, p, t) { WS2812FX(uint16_t n, uint8_t p, neoPixelType t) : Adafruit_NeoPixel(n, p, t) {
_mode[FX_MODE_STATIC] = &WS2812FX::mode_static; _mode[FX_MODE_STATIC] = &WS2812FX::mode_static;
_mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink;
@@ -205,15 +377,15 @@ class WS2812FX : public Adafruit_NeoPixel {
_mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks; _mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks;
_mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random; _mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random;
_mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas; _mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas;
_mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; _mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker;
_mode[FX_MODE_FIRE_FLICKER_SOFT] = &WS2812FX::mode_fire_flicker_soft; _mode[FX_MODE_FIRE_FLICKER_SOFT] = &WS2812FX::mode_fire_flicker_soft;
_mode[FX_MODE_FIRE_FLICKER_INTENSE] = &WS2812FX::mode_fire_flicker_intense; _mode[FX_MODE_FIRE_FLICKER_INTENSE] = &WS2812FX::mode_fire_flicker_intense;
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; _mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus;
_mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
_mode[FX_MODE_BICOLOR_CHASE] = &WS2812FX::mode_bicolor_chase; _mode[FX_MODE_BICOLOR_CHASE] = &WS2812FX::mode_bicolor_chase;
_mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase; _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase;
// if flash memory is constrained (I'm looking at you Arduino Nano), replace modes // if flash memory is constrained (I'm looking at you Arduino Nano), replace modes
// that use a lot of flash with mode_static (reduces flash footprint by about 3600 bytes) // that use a lot of flash with mode_static (reduces flash footprint by about 2100 bytes)
#ifdef REDUCED_MODES #ifdef REDUCED_MODES
_mode[FX_MODE_BREATH] = &WS2812FX::mode_static; _mode[FX_MODE_BREATH] = &WS2812FX::mode_static;
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_static; _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_static;
@@ -223,67 +395,12 @@ class WS2812FX : public Adafruit_NeoPixel {
_mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights; _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights;
_mode[FX_MODE_ICU] = &WS2812FX::mode_icu; _mode[FX_MODE_ICU] = &WS2812FX::mode_icu;
#endif #endif
_mode[FX_MODE_CUSTOM] = &WS2812FX::mode_custom; _mode[FX_MODE_CUSTOM_0] = &WS2812FX::mode_custom_0;
_mode[FX_MODE_CUSTOM_1] = &WS2812FX::mode_custom_1;
_mode[FX_MODE_CUSTOM_2] = &WS2812FX::mode_custom_2;
_mode[FX_MODE_CUSTOM_3] = &WS2812FX::mode_custom_3;
_name[FX_MODE_STATIC] = F("Static"); brightness = DEFAULT_BRIGHTNESS + 1; // Adafruit_NeoPixel internally offsets brightness by 1
_name[FX_MODE_BLINK] = F("Blink");
_name[FX_MODE_BREATH] = F("Breath");
_name[FX_MODE_COLOR_WIPE] = F("Color Wipe");
_name[FX_MODE_COLOR_WIPE_INV ] = F("Color Wipe Inverse");
_name[FX_MODE_COLOR_WIPE_REV] = F("Color Wipe Reverse");
_name[FX_MODE_COLOR_WIPE_REV_INV] = F("Color Wipe Reverse Inverse");
_name[FX_MODE_COLOR_WIPE_RANDOM] = F("Color Wipe Random");
_name[FX_MODE_RANDOM_COLOR] = F("Random Color");
_name[FX_MODE_SINGLE_DYNAMIC] = F("Single Dynamic");
_name[FX_MODE_MULTI_DYNAMIC] = F("Multi Dynamic");
_name[FX_MODE_RAINBOW] = F("Rainbow");
_name[FX_MODE_RAINBOW_CYCLE] = F("Rainbow Cycle");
_name[FX_MODE_SCAN] = F("Scan");
_name[FX_MODE_DUAL_SCAN] = F("Dual Scan");
_name[FX_MODE_FADE] = F("Fade");
_name[FX_MODE_THEATER_CHASE] = F("Theater Chase");
_name[FX_MODE_THEATER_CHASE_RAINBOW] = F("Theater Chase Rainbow");
_name[FX_MODE_RUNNING_LIGHTS] = F("Running Lights");
_name[FX_MODE_TWINKLE] = F("Twinkle");
_name[FX_MODE_TWINKLE_RANDOM] = F("Twinkle Random");
_name[FX_MODE_TWINKLE_FADE] = F("Twinkle Fade");
_name[FX_MODE_TWINKLE_FADE_RANDOM] = F("Twinkle Fade Random");
_name[FX_MODE_SPARKLE] = F("Sparkle");
_name[FX_MODE_FLASH_SPARKLE] = F("Flash Sparkle");
_name[FX_MODE_HYPER_SPARKLE] = F("Hyper Sparkle");
_name[FX_MODE_STROBE] = F("Strobe");
_name[FX_MODE_STROBE_RAINBOW] = F("Strobe Rainbow");
_name[FX_MODE_MULTI_STROBE] = F("Multi Strobe");
_name[FX_MODE_BLINK_RAINBOW] = F("Blink Rainbow");
_name[FX_MODE_CHASE_WHITE] = F("Chase White");
_name[FX_MODE_CHASE_COLOR] = F("Chase Color");
_name[FX_MODE_CHASE_RANDOM] = F("Chase Random");
_name[FX_MODE_CHASE_RAINBOW] = F("Chase Rainbow");
_name[FX_MODE_CHASE_FLASH] = F("Chase Flash");
_name[FX_MODE_CHASE_FLASH_RANDOM] = F("Chase Flash Random");
_name[FX_MODE_CHASE_RAINBOW_WHITE] = F("Chase Rainbow White");
_name[FX_MODE_CHASE_BLACKOUT] = F("Chase Blackout");
_name[FX_MODE_CHASE_BLACKOUT_RAINBOW] = F("Chase Blackout Rainbow");
_name[FX_MODE_COLOR_SWEEP_RANDOM] = F("Color Sweep Random");
_name[FX_MODE_RUNNING_COLOR] = F("Running Color");
_name[FX_MODE_RUNNING_RED_BLUE] = F("Running Red Blue");
_name[FX_MODE_RUNNING_RANDOM] = F("Running Random");
_name[FX_MODE_LARSON_SCANNER] = F("Larson Scanner");
_name[FX_MODE_COMET] = F("Comet");
_name[FX_MODE_FIREWORKS] = F("Fireworks");
_name[FX_MODE_FIREWORKS_RANDOM] = F("Fireworks Random");
_name[FX_MODE_MERRY_CHRISTMAS] = F("Merry Christmas");
_name[FX_MODE_HALLOWEEN] = F("Halloween");
_name[FX_MODE_FIRE_FLICKER] = F("Fire Flicker");
_name[FX_MODE_FIRE_FLICKER_SOFT] = F("Fire Flicker (soft)");
_name[FX_MODE_FIRE_FLICKER_INTENSE] = F("Fire Flicker (intense)");
_name[FX_MODE_CIRCUS_COMBUSTUS] = F("Circus Combustus");
_name[FX_MODE_BICOLOR_CHASE] = F("Bicolor Chase");
_name[FX_MODE_TRICOLOR_CHASE] = F("Tricolor Chase");
_name[FX_MODE_ICU] = F("ICU");
_name[FX_MODE_CUSTOM] = F("Custom");
_brightness = DEFAULT_BRIGHTNESS;
_running = false; _running = false;
_num_segments = 1; _num_segments = 1;
_segments[0].mode = DEFAULT_MODE; _segments[0].mode = DEFAULT_MODE;
@@ -291,21 +408,33 @@ class WS2812FX : public Adafruit_NeoPixel {
_segments[0].start = 0; _segments[0].start = 0;
_segments[0].stop = n - 1; _segments[0].stop = n - 1;
_segments[0].speed = DEFAULT_SPEED; _segments[0].speed = DEFAULT_SPEED;
RESET_RUNTIME; resetSegmentRuntimes();
} }
void void
// timer(void),
init(void), init(void),
service(void), service(void),
start(void), start(void),
stop(void), stop(void),
pause(void),
resume(void),
strip_off(void),
fade_out(void),
setMode(uint8_t m), setMode(uint8_t m),
setMode(uint8_t seg, uint8_t m),
setOptions(uint8_t seg, uint8_t o),
setCustomMode(uint16_t (*p)()), setCustomMode(uint16_t (*p)()),
setCustomShow(void (*p)()),
setSpeed(uint16_t s), setSpeed(uint16_t s),
setSpeed(uint8_t seg, uint16_t s),
increaseSpeed(uint8_t s), increaseSpeed(uint8_t s),
decreaseSpeed(uint8_t s), decreaseSpeed(uint8_t s),
setColor(uint8_t w, uint8_t r, uint8_t g, uint8_t b), setColor(uint8_t r, uint8_t g, uint8_t b),
setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w),
setColor(uint32_t c), setColor(uint32_t c),
setColor(uint8_t seg, uint32_t c),
setColors(uint8_t seg, uint32_t* c),
setBrightness(uint8_t b), setBrightness(uint8_t b),
increaseBrightness(uint8_t s), increaseBrightness(uint8_t s),
decreaseBrightness(uint8_t s), decreaseBrightness(uint8_t s),
@@ -315,51 +444,91 @@ class WS2812FX : public Adafruit_NeoPixel {
trigger(void), trigger(void),
setNumSegments(uint8_t n), setNumSegments(uint8_t n),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, bool reverse), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, bool reverse),
resetSegments(); setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options),
resetSegments(),
resetSegmentRuntimes(),
resetSegmentRuntime(uint8_t),
setPixelColor(uint16_t n, uint32_t c),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w),
copyPixels(uint16_t d, uint16_t s, uint16_t c),
show(void);
boolean boolean
isRunning(void); isRunning(void),
isTriggered(void),
isFrame(void),
isFrame(uint8_t),
isCycle(void),
isCycle(uint8_t);
uint8_t uint8_t
random8(void),
random8(uint8_t),
getMode(void), getMode(void),
getBrightness(void), getMode(uint8_t),
getModeCount(void), getModeCount(void),
getNumSegments(void); setCustomMode(const __FlashStringHelper* name, uint16_t (*p)()),
setCustomMode(uint8_t i, const __FlashStringHelper* name, uint16_t (*p)()),
getNumSegments(void),
get_random_wheel_index(uint8_t),
getOptions(uint8_t);
uint16_t uint16_t
random16(void),
random16(uint16_t),
getSpeed(void), getSpeed(void),
getLength(void); getSpeed(uint8_t),
getLength(void),
getNumBytes(void);
uint32_t uint32_t
color_wheel(uint8_t), color_wheel(uint8_t),
getColor(void); getColor(void),
getColor(uint8_t),
intensitySum(void);
const __FlashStringHelper* uint32_t* getColors(uint8_t);
getModeName(uint8_t m); uint32_t* intensitySums(void);
WS2812FX::Segment const __FlashStringHelper* getModeName(uint8_t m);
getSegment(void);
WS2812FX::Segment_runtime WS2812FX::Segment* getSegment(void);
getSegmentRuntime(void);
WS2812FX::Segment* WS2812FX::Segment* getSegment(uint8_t);
getSegments(void);
private: WS2812FX::Segment* getSegments(void);
void
strip_off(void),
fade_out(void);
WS2812FX::Segment_runtime* getSegmentRuntime(void);
WS2812FX::Segment_runtime* getSegmentRuntime(uint8_t);
WS2812FX::Segment_runtime* getSegmentRuntimes(void);
// mode helper functions
uint16_t
blink(uint32_t, uint32_t, bool strobe),
color_wipe(uint32_t, uint32_t, bool),
twinkle(uint32_t, uint32_t),
twinkle_fade(uint32_t),
chase(uint32_t, uint32_t, uint32_t),
running(uint32_t, uint32_t),
fireworks(uint32_t),
fire_flicker(int),
tricolor_chase(uint32_t, uint32_t, uint32_t),
scan(uint32_t, uint32_t, bool);
uint32_t
color_blend(uint32_t, uint32_t, uint8_t);
// builtin modes
uint16_t uint16_t
mode_static(void), mode_static(void),
blink(uint32_t, uint32_t, bool strobe),
mode_blink(void), mode_blink(void),
mode_blink_rainbow(void), mode_blink_rainbow(void),
mode_strobe(void), mode_strobe(void),
mode_strobe_rainbow(void), mode_strobe_rainbow(void),
color_wipe(uint32_t, uint32_t, bool),
mode_color_wipe(void), mode_color_wipe(void),
mode_color_wipe_inv(void), mode_color_wipe_inv(void),
mode_color_wipe_rev(void), mode_color_wipe_rev(void),
@@ -373,23 +542,19 @@ class WS2812FX : public Adafruit_NeoPixel {
mode_fade(void), mode_fade(void),
mode_scan(void), mode_scan(void),
mode_dual_scan(void), mode_dual_scan(void),
theater_chase(uint32_t, uint32_t),
mode_theater_chase(void), mode_theater_chase(void),
mode_theater_chase_rainbow(void), mode_theater_chase_rainbow(void),
mode_rainbow(void), mode_rainbow(void),
mode_rainbow_cycle(void), mode_rainbow_cycle(void),
mode_running_lights(void), mode_running_lights(void),
twinkle(uint32_t),
mode_twinkle(void), mode_twinkle(void),
mode_twinkle_random(void), mode_twinkle_random(void),
twinkle_fade(uint32_t),
mode_twinkle_fade(void), mode_twinkle_fade(void),
mode_twinkle_fade_random(void), mode_twinkle_fade_random(void),
mode_sparkle(void), mode_sparkle(void),
mode_flash_sparkle(void), mode_flash_sparkle(void),
mode_hyper_sparkle(void), mode_hyper_sparkle(void),
mode_multi_strobe(void), mode_multi_strobe(void),
chase(uint32_t, uint32_t, uint32_t),
mode_chase_white(void), mode_chase_white(void),
mode_chase_color(void), mode_chase_color(void),
mode_chase_random(void), mode_chase_random(void),
@@ -399,13 +564,11 @@ class WS2812FX : public Adafruit_NeoPixel {
mode_chase_rainbow_white(void), mode_chase_rainbow_white(void),
mode_chase_blackout(void), mode_chase_blackout(void),
mode_chase_blackout_rainbow(void), mode_chase_blackout_rainbow(void),
running(uint32_t, uint32_t),
mode_running_color(void), mode_running_color(void),
mode_running_red_blue(void), mode_running_red_blue(void),
mode_running_random(void), mode_running_random(void),
mode_larson_scanner(void), mode_larson_scanner(void),
mode_comet(void), mode_comet(void),
fireworks(uint32_t),
mode_fireworks(void), mode_fireworks(void),
mode_fireworks_random(void), mode_fireworks_random(void),
mode_merry_christmas(void), mode_merry_christmas(void),
@@ -413,33 +576,36 @@ class WS2812FX : public Adafruit_NeoPixel {
mode_fire_flicker(void), mode_fire_flicker(void),
mode_fire_flicker_soft(void), mode_fire_flicker_soft(void),
mode_fire_flicker_intense(void), mode_fire_flicker_intense(void),
fire_flicker(int),
mode_circus_combustus(void), mode_circus_combustus(void),
tricolor_chase(uint32_t, uint32_t, uint32_t),
mode_bicolor_chase(void), mode_bicolor_chase(void),
mode_tricolor_chase(void), mode_tricolor_chase(void),
mode_icu(void), mode_icu(void),
mode_custom(void); mode_custom_0(void),
mode_custom_1(void),
mode_custom_2(void),
mode_custom_3(void);
private:
uint16_t _rand16seed;
uint16_t (*customModes[MAX_CUSTOM_MODES])(void) {
[]{ return (uint16_t)1000; },
[]{ return (uint16_t)1000; },
[]{ return (uint16_t)1000; },
[]{ return (uint16_t)1000; }
};
void (*customShow)(void) = NULL;
boolean boolean
_running, _running,
_triggered; _triggered;
uint8_t mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
get_random_wheel_index(uint8_t),
_brightness;
const __FlashStringHelper*
_name[MODE_COUNT]; // SRAM footprint: 2 bytes per element
mode_ptr
_mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
uint8_t _segment_index = 0; uint8_t _segment_index = 0;
uint8_t _num_segments = 1; uint8_t _num_segments = 1;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element
// start, stop, speed, mode, reverse, color[] // start, stop, speed, mode, options, color[]
{ 0, 7, DEFAULT_SPEED, FX_MODE_STATIC, false, {DEFAULT_COLOR}} { 0, 7, DEFAULT_SPEED, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}}
}; };
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element
}; };
+68
View File
@@ -0,0 +1,68 @@
/*
Custom effect that changes random pixels to transition between colors
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-08-19 initial version
*/
#ifndef BlockDissolve_h
#define BlockDissolve_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t blockDissolve(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment();
WS2812FX::Segment_runtime* segrt = ws2812fx.getSegmentRuntime();
int seglen = seg->stop - seg->start + 1;
uint32_t color = seg->colors[segrt->aux_param];
ws2812fx.setPixelColor(seg->start, color);
// get the decimated color after setPixelColor() has mangled it
// in accordance to the brightness setting
uint32_t desColor = ws2812fx.getPixelColor(seg->start);
for(uint16_t i=0; i<seglen; i++) {
int index = seg->start + ws2812fx.random16(seglen);
if(ws2812fx.getPixelColor(index) != desColor) {
ws2812fx.setPixelColor(index, color);
return seg->speed;
}
}
for(uint16_t i=seg->start; i<seg->stop; i++) {
ws2812fx.setPixelColor(i, color);
}
segrt->aux_param = (segrt->aux_param + 1) % NUM_COLORS;
return seg->speed;
}
#endif
+67
View File
@@ -0,0 +1,67 @@
/*
Custom effect that creates two Larson scanners moving in opposite directions.
If you set the REVERSE option, an offset will be added to the comet after each
cycle (so if the LEDs are arranged in a circle, the animation will appear to
"walk" around the circle.)
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-02-26 initial version
*/
#ifndef DualLarson_h
#define DualLarson_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t dualLarson(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
WS2812FX::Segment_runtime* segrt = ws2812fx.getSegmentRuntime();
int seglen = seg->stop - seg->start + 1;
static int16_t offset = 0;
int8_t dir = segrt->aux_param ? -1 : 1;
segrt->aux_param3 += dir;
ws2812fx.fade_out();
int16_t segIndex = (segrt->aux_param3 + offset) % seglen;
ws2812fx.setPixelColor(seg->start + segIndex, seg->colors[0]);
ws2812fx.setPixelColor(seg->stop - segIndex, seg->colors[2]);
if(segrt->aux_param3 >= (seg->stop - seg->start) || segrt->aux_param3 <= 0) {
segrt->aux_param = !segrt->aux_param;
if(seg->options & REVERSE) offset = (offset + 1) % seglen;
}
return (seg->speed / (seglen * 2));
}
#endif
+70
View File
@@ -0,0 +1,70 @@
/*
Custom effect that creates random comets
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-02-26 initial version
*/
#ifndef MultiComet_h
#define MultiComet_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t multiComet(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
int seglen = seg->stop - seg->start + 1;
bool isReverse = (seg->options & REVERSE) == REVERSE;
ws2812fx.fade_out();
static int16_t comets[] = {UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX};
static int8_t numComets = sizeof(comets)/sizeof(comets[0]);
for(uint8_t i=0; i < numComets; i++) {
if(comets[i] < seglen) {
if(isReverse) {
ws2812fx.setPixelColor(seg->stop - comets[i], i % 2 ? seg->colors[0] : seg->colors[2]);
} else {
ws2812fx.setPixelColor(seg->start + comets[i], i % 2 ? seg->colors[0] : seg->colors[2]);
}
comets[i]++;
} else {
if(!random(seglen)) {
comets[i] = 0;
}
}
}
return (seg->speed / seglen);
}
#endif
+84
View File
@@ -0,0 +1,84 @@
/*
Custom effect that creates three color spans that oscillate back and forth.
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-07-26 initial version
*/
#ifndef Oscillate_h
#define Oscillate_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
typedef struct Oscillator {
int16_t pos;
int8_t size;
int8_t dir;
int8_t speed;
} oscillator;
uint16_t oscillate(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
int seglen = seg->stop - seg->start + 1;
static oscillator oscillators[NUM_COLORS] = {
{seglen/4, seglen/8, 1, 1},
{seglen/4*2, seglen/8, -1, 1},
{seglen/4*3, seglen/8, 1, 2}
};
for(int8_t i=0; i < sizeof(oscillators)/sizeof(oscillators[0]); i++) {
oscillators[i].pos += oscillators[i].dir * oscillators[i].speed;
if((oscillators[i].dir == -1) && (oscillators[i].pos <= 0)) {
oscillators[i].pos = 0;
oscillators[i].dir = 1;
oscillators[i].speed = random(1, 3);
}
if((oscillators[i].dir == 1) && (oscillators[i].pos >= (seglen - 1))) {
oscillators[i].pos = seglen - 1;
oscillators[i].dir = -1;
oscillators[i].speed = random(1, 3);
}
}
for(int16_t i=0; i < seglen; i++) {
uint32_t color = BLACK;
for(int8_t j=0; j < sizeof(oscillators)/sizeof(oscillators[0]); j++) {
if(i >= oscillators[j].pos - oscillators[j].size && i <= oscillators[j].pos + oscillators[j].size) {
color = (color == BLACK) ? seg->colors[j] : ws2812fx.color_blend(color, seg->colors[j], 128);
}
}
ws2812fx.setPixelColor(seg->start + i, color);
}
return(seg->speed / 8);
}
#endif
+94
View File
@@ -0,0 +1,94 @@
/*
Custom effect that looks like popcorn.
The 'popcorn' is color[0] and the background color is color[1].
If color[0] is the same as color[1], the 'popcorn' will be a random color.
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-11-13 initial version
*/
#ifndef Popcorn_h
#define Popcorn_h
#include <WS2812FX.h>
#define MAX_NUM_POPCORN 10
#define GRAVITY 0.1
extern WS2812FX ws2812fx;
typedef struct Kernel {
float position;
float velocity;
int32_t color;
} kernel;
uint16_t popcorn(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
uint16_t seglen = seg->stop - seg->start + 1;
uint32_t popcornColor = seg->colors[0];
uint32_t bgColor = seg->colors[1];
if(popcornColor == bgColor) popcornColor = ws2812fx.color_wheel(ws2812fx.random8());
bool isReverse = (seg->options & REVERSE) != 0;
static kernel popcorn[MAX_NUM_POPCORN];
static float coeff = 0.0f;
if(coeff == 0.0f) { // calculate the velocity coeff once (the secret sauce)
coeff = pow((float)seglen, 0.5223324f) * 0.3944296f;
}
// reset all LEDs to background color
for(uint16_t i=seg->start; i <= seg->stop; i++) {
ws2812fx.setPixelColor(i, bgColor);
}
uint16_t ledIndex;
for(int8_t i=0; i < MAX_NUM_POPCORN; i++) {
bool isActive = popcorn[i].position >= 0.0f;
if(isActive) { // if kernel is active, update its position
popcorn[i].position += popcorn[i].velocity;
popcorn[i].velocity -= GRAVITY;
ledIndex = isReverse ? seg->stop - popcorn[i].position : seg->start + popcorn[i].position;
if(ledIndex >= seg->start && ledIndex <= seg->stop) ws2812fx.setPixelColor(ledIndex, popcorn[i].color);
} else { // if kernel is inactive, randomly pop it
if(ws2812fx.random8() < 2) { // POP!!!
popcorn[i].position = 0.0f;
popcorn[i].velocity = coeff * (random(66, 100) / 100.0f);
popcorn[i].color = popcornColor;
ledIndex = isReverse ? seg->stop : seg->start;
ws2812fx.setPixelColor(ledIndex, popcorn[i].color);
}
}
}
return(seg->speed / seglen);
}
#endif
+66
View File
@@ -0,0 +1,66 @@
/*
Custom effect that combines the fireworks effect and running effect
to produce a rain-like effect. Depending on the size of your LED strip, you
may want to play with the FADE and SIZE options.
The background color is black, unless you use a FADE_RATE other then DEFAULT,
in which case the background color is color[1].
The color of the rain is either color[0] or color[2] (chosen randomly), unless
color[0]==color[1], in which case the rain is a random color.
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-12-14 initial version
*/
#ifndef Rain_h
#define Rain_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t rain(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
uint16_t seglen = seg->stop - seg->start + 1;
uint32_t rainColor = (ws2812fx.random8() & 1) == 0 ? seg->colors[0] : seg->colors[2];
if(seg->colors[0] == seg->colors[1]) rainColor = ws2812fx.color_wheel(ws2812fx.random8());
ws2812fx.fireworks(rainColor);
// shift everything two pixels
bool isReverse = (seg->options & REVERSE) != 0;
if(isReverse) {
ws2812fx.copyPixels(seg->start + 2, seg->start, seglen - 2);
} else {
ws2812fx.copyPixels(seg->start, seg->start + 2, seglen - 2);
}
return(seg->speed / seglen);
}
#endif
+67
View File
@@ -0,0 +1,67 @@
/*
Custom effect that creates a Larson Scanner with rainbow colors
It has two modes:
1) if the segment options parameter is set to NO_OPTIONS, then
the rainbow of colors span the 'comet'.
2) if the segment options parameter is set to a FADE option
(e.g. FADE_MEDIUM), then the rainbow of colors span the segment
and the 'comet' merely shows the colors at that point in the segment.
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-08-26 initial version
*/
#ifndef RainbowLarson_h
#define RainbowLarson_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t rainbowLarson(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
int seglen = seg->stop - seg->start + 1;
static int16_t index = 0, dir = 1, cnt = 0;
index += dir;
ws2812fx.fade_out();
if(seg->options == NO_OPTIONS) {
ws2812fx.setPixelColor(seg->start + index, ws2812fx.color_wheel((cnt++ % 8) * 32));
} else {
ws2812fx.setPixelColor(seg->start + index, ws2812fx.color_wheel((index * 256) / seglen));
}
if(index >= (seg->stop - seg->start) || index <= 0) dir = -dir;
return (seg->speed / (seglen * 2));
}
#endif
+54
View File
@@ -0,0 +1,54 @@
/*
Custom effect that creates a random chase effect
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-02-26 initial version
*/
#ifndef RandomChase_h
#define RandomChase_h
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t randomChase(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment();
for(uint16_t i=seg->stop; i>seg->start; i--) {
ws2812fx.setPixelColor(i, ws2812fx.getPixelColor(i-1));
}
uint32_t color = ws2812fx.getPixelColor(seg->start + 1);
int r = random(6) != 0 ? (color >> 16 & 0xFF) : random(256);
int g = random(6) != 0 ? (color >> 8 & 0xFF) : random(256);
int b = random(6) != 0 ? (color & 0xFF) : random(256);
ws2812fx.setPixelColor(seg->start, r, g, b);
return seg->speed;
}
#endif
+83
View File
@@ -0,0 +1,83 @@
/*
Custom effect that fades between three colors. You can add the TRIFADE_BLACK option
in the setSegment() call to fade to black between each color.
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-07-26 initial version
*/
#ifndef TriFade_h
#define TriFade_h
#define TRIFADE_BLACK (uint8_t)0x80
#include <WS2812FX.h>
extern WS2812FX ws2812fx;
uint16_t triFade(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
uint8_t options = seg->options;
bool trifade_black = (options & TRIFADE_BLACK) == TRIFADE_BLACK;
static int count = 0;
static uint32_t color1 = 0, color2 = 0;
if(count == 0) {
color1 = seg->colors[0];
color2 = trifade_black ? BLACK : seg->colors[1];
} else if(count == 256) {
color1 = trifade_black ? BLACK : seg->colors[1];
color2 = trifade_black ? seg->colors[1] : seg->colors[2];
} else if(count == 512) {
color1 = trifade_black ? seg->colors[1] : seg->colors[2];
color2 = trifade_black ? BLACK : seg->colors[0];
} else if(count == 768) {
color1 = trifade_black ? BLACK : seg->colors[0];
color2 = trifade_black ? seg->colors[2] : seg->colors[1];
} else if(count == 1024) {
color1 = trifade_black ? seg->colors[2] : seg->colors[1];
color2 = trifade_black ? BLACK : seg->colors[2];
} else if(count == 1280) {
color1 = trifade_black ? BLACK: seg->colors[2];
color2 = seg->colors[0];
}
uint32_t color = ws2812fx.color_blend(color1, color2, count % 256);
for(uint16_t i=seg->start; i <= seg->stop; i++) {
ws2812fx.setPixelColor(i, color);
}
count += 4;
if(count >= 1536) count = 0;
return (seg->speed / 128);
}
#endif
+80
View File
@@ -0,0 +1,80 @@
/*
Custom effect that mimics a multiband VU meter
Keith Lord - 2018
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2018-08-21 initial version
*/
#ifndef VUMeter_h
#define VUMeter_h
#include <WS2812FX.h>
#ifndef NUM_BANDS
#define NUM_BANDS 2
#endif
// set USE_RANDOM_DATA to false in the line below if vuMeterBands[] is populated
// by an external data source. otherwise random data will be used for the effect.
#ifndef USE_RANDOM_DATA
#define USE_RANDOM_DATA true
#endif
extern WS2812FX ws2812fx;
uint8_t vuMeterBands[NUM_BANDS]; // global VU meter band amplitude data (range 0-255)
uint16_t vuMeter(void) {
WS2812FX::Segment* seg = ws2812fx.getSegment();
uint16_t seglen = seg->stop - seg->start + 1;
uint16_t bandSize = seglen / NUM_BANDS;
for(uint8_t i=0; i<NUM_BANDS; i++) {
#if USE_RANDOM_DATA
int randomData = vuMeterBands[i] + ws2812fx.random8(32) - ws2812fx.random8(32);
vuMeterBands[i] = (randomData < 0 || randomData > 255) ? 128 : randomData;
#endif
uint8_t scaledBand = (vuMeterBands[i] * bandSize) / 256;
for(uint16_t j=0; j<bandSize; j++) {
uint16_t index = seg->start + (i * bandSize) + j;
if(j <= scaledBand) {
if(j < bandSize - 4) ws2812fx.setPixelColor(index, seg->colors[0]);
else if(j < bandSize - 2) ws2812fx.setPixelColor(index, seg->colors[1]);
else ws2812fx.setPixelColor(index, seg->colors[2]);
} else {
ws2812fx.setPixelColor(index, BLACK);
}
}
}
return seg->speed;
}
#endif
+48 -27
View File
@@ -1,35 +1,48 @@
//#define USE_NEOANIMATIONFX // Uses NeoAnimationFX, PIN is ignored & set to RX/GPIO3 or UART method: D4/GPIO2, see: https://github.com/debsahu/NeoAnimationFX //#define USE_WS2812FX_DMA // Uses PIN is ignored & set to RX/GPIO3 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
#define USE_WS2812FX // Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX //#define USE_WS2812FX_UART1 // Uses PIN is ignored & set to D4/GPIO2 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
//#define USE_WS2812FX_UART2 // Uses PIN is ignored & set to TX/GPIO1 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
// Neopixel // Neopixel
#define PIN 15 // PIN (15 / D8) where neopixel / WS2811 strip is attached #define PIN 15 // PIN (15 / D8) where neopixel / WS2811 strip is attached
#define NUMLEDS 12 // Number of leds in the strip #define NUMLEDS 194 // Number of leds in the strip
#define BUILTIN_LED 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192 #define BUILTIN_LED 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
#define BUTTON 14 // Input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button. #define BUTTON 14 // Input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button.
#define BUTTON_GY33 12 // Input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button. #define BUTTON_GY33 12 // Input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button.
#define RGBW // If defined, use RGBW Strips #define RGBW // If defined, use RGBW Strips
const char HOSTNAME[] = "FABLightingRGBW"; // Friedly hostname const char HOSTNAME[] = "McLightingRGBW"; // Friedly hostname
#define HTTP_OTA // If defined, enable Added ESP8266HTTPUpdateServer #define HTTP_OTA // If defined, enable ESP8266HTTPUpdateServer OTA code.
//#define ENABLE_OTA // If defined, enable Arduino OTA code. //#define ENABLE_OTA // If defined, enable Arduino OTA code.
#define ENABLE_AMQTT // If defined, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client #define ENABLE_AMQTT // If defined, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
//#define ENABLE_MQTT // If defined, enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API //#define ENABLE_MQTT // If defined, enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active #define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT or ENABLE_AMQTT must be active
#define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control #define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control
//#define ENABLE_BUTTON_GY33 // If defined, enable button handling code for GY-33 color sensor to scan color #define ENABLE_BUTTON_GY33 // If defined, enable button handling code for GY-33 color sensor to scan color
//#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth //#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
#define ENABLE_LEGACY_ANIMATIONS #define ENABLE_LEGACY_ANIMATIONS // Dont disbale this for now
#define ENABLE_STATE_SAVE_SPIFFS // If defined, saves state on SPIFFS #define ENABLE_E131 // E1.31 implementation
//#define ENABLE_STATE_SAVE_EEPROM // If defined, save state on reboot
//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname
#define DBG_OUTPUT_PORT Serial // Set debug output port
#if defined(USE_NEOANIMATIONFX) and defined(USE_WS2812FX) #ifdef ENABLE_E131
#error "Cant have both NeoAnimationFX and WS2812FX enabled. Choose either one." #define START_UNIVERSE 1 // First DMX Universe to listen for
#define END_UNIVERSE 2 // Total number of Universes to listen for, starting at UNIVERSE
#endif #endif
#if !defined(USE_NEOANIMATIONFX) and !defined(USE_WS2812FX)
#error "Need to either use NeoAnimationFX and WS2812FX mode." //#define WIFIMGR_PORTAL_TIMEOUT 180
//#define WIFIMGR_SET_MANUAL_IP
#ifdef WIFIMGR_SET_MANUAL_IP
uint8_t _ip[4] = {192,168,0,128};
uint8_t _gw[4] = {192,168,0,1};
uint8_t _sn[4] = {255,255,255,0};
#endif
#ifdef MQTT_HOME_ASSISTANT_SUPPORT
#define MQTT_HOME_ASSISTANT_0_84_SUPPORT // Comment if using HA version < 0.84
#endif
#if defined(USE_WS2812FX_DMA) and defined(USE_WS2812FX_UART)
#error "Cant have both DMA and UART method."
#endif #endif
#if defined(ENABLE_MQTT) and defined(ENABLE_AMQTT) #if defined(ENABLE_MQTT) and defined(ENABLE_AMQTT)
#error "Cant have both PubSubClient and AsyncMQTT enabled. Choose either one." #error "Cant have both PubSubClient and AsyncMQTT enabled. Choose either one."
@@ -43,15 +56,15 @@ const char HOSTNAME[] = "FABLightingRGBW"; // Friedly hostname
// parameters for automatically cycling favorite patterns // parameters for automatically cycling favorite patterns
uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds) uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
{0x00ff0000, 120, 1, 5.0}, // blink red for 5 seconds {0xff000000, 120, 1, 5.0}, // blink red for 5 seconds
{0x0000ff00, 120, 3, 10.0}, // wipe green for 10 seconds {0x00ff0000, 120, 3, 10.0}, // wipe green for 10 seconds
{0x000000ff, 196, 14, 5.0}, // dual scan blue for 5 seconds {0x0000ff00, 196, 14, 5.0}, // dual scan blue for 5 seconds
{0x000000ff, 196, 46, 15.0} // fireworks for 15 seconds {0x0000ff00, 196, 46, 15.0} // fireworks for 15 seconds
}; };
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) #if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
#define MQTT_MAX_PACKET_SIZE 512 #define MQTT_MAX_PACKET_SIZE 2048
#define MQTT_MAX_RECONNECT_TRIES 4 #define MQTT_MAX_RECONNECT_TRIES 4
int mqtt_reconnect_retries = 0; int mqtt_reconnect_retries = 0;
@@ -80,10 +93,11 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
uint16_t color_temp = 327; // min is 154 and max is 500 uint16_t color_temp = 327; // min is 154 and max is 500
#endif #endif
//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname
#ifdef ENABLE_MQTT_HOSTNAME_CHIPID #ifdef ENABLE_MQTT_HOSTNAME_CHIPID
const char* mqtt_clientid = String(String(HOSTNAME) + "-" + String(ESP.getChipId())).c_str(); // MQTT ClientID char mqtt_clientid[64];
#else #else
const char* mqtt_clientid = HOSTNAME; // MQTT ClientID const char* mqtt_clientid = HOSTNAME;
#endif #endif
char mqtt_host[64] = ""; char mqtt_host[64] = "";
@@ -96,10 +110,15 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
// *************************************************************************** // ***************************************************************************
// Global variables / definitions // Global variables / definitions
// *************************************************************************** // ***************************************************************************
#define DBG_OUTPUT_PORT Serial // Set debug output port
// List of all color modes // List of all color modes
#ifdef ENABLE_LEGACY_ANIMATIONS #ifdef ENABLE_LEGACY_ANIMATIONS
#ifdef ENABLE_E131
enum MODE { SET_MODE, HOLD, AUTO, OFF, TV, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, E131 };
#else
enum MODE { SET_MODE, HOLD, AUTO, OFF, TV, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW}; enum MODE { SET_MODE, HOLD, AUTO, OFF, TV, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW};
#endif
MODE mode = RAINBOW; // Standard mode that is active when software starts MODE mode = RAINBOW; // Standard mode that is active when software starts
bool exit_func = false; // Global helper variable to get out of the color modes when mode changes bool exit_func = false; // Global helper variable to get out of the color modes when mode changes
#else #else
@@ -126,9 +145,11 @@ struct ledstate // Data structure to store a state of a single led
typedef struct ledstate LEDState; // Define the datatype LEDState typedef struct ledstate LEDState; // Define the datatype LEDState
LEDState ledstates[NUMLEDS]; // Get an array of led states to store the state of the whole strip LEDState ledstates[NUMLEDS]; // Get an array of led states to store the state of the whole strip
LEDState main_color = { 0, 255, 0, 0}; // Store the "main color" of the strip used in single color modes LEDState main_color = { 0, 255, 0, 0 }; // Store the "main color" of the strip used in single color modes
#define ENABLE_STATE_SAVE_SPIFFS // If defined, saves state on SPIFFS
//#define ENABLE_STATE_SAVE_EEPROM // If defined, save state on reboot
#ifdef ENABLE_STATE_SAVE_EEPROM #ifdef ENABLE_STATE_SAVE_EEPROM
char current_state[36]; // Keeps the current state representation char current_state[36]; // Keeps the current state representation
char last_state[36]; // Save the last state as string representation char last_state[36]; // Save the last state as string representation
@@ -146,9 +167,9 @@ LEDState main_color = { 0, 255, 0, 0}; // Store the "main color" of the strip u
#endif #endif
#ifdef ENABLE_BUTTON #ifdef ENABLE_BUTTON
#define BTN_MODE_SHORT "STA| 1| 0|245|196|255| 0| 0| 0" // Static white #define BTN_MODE_SHORT "STA| 1| 0|245|196| 0| 0| 0|255" // Static white
#define BTN_MODE_MEDIUM "STA| 1| 48|245|196| 0|255|102| 0" // Fire flicker #define BTN_MODE_MEDIUM "STA| 1| 48|245|196|255|102| 0| 0" // Fire flicker
#define BTN_MODE_LONG "STA| 1| 46|253|196| 0|255|102| 0" // Fireworks random #define BTN_MODE_LONG "STA| 1| 46|253|196|255|102| 0| 0" // Fireworks random
unsigned long keyPrevMillis = 0; unsigned long keyPrevMillis = 0;
const unsigned long keySampleIntervalMs = 25; const unsigned long keySampleIntervalMs = 25;
+141 -54
View File
@@ -1,6 +1,40 @@
// *************************************************************************** // ***************************************************************************
// Request handlers // Request handlers
// *************************************************************************** // ***************************************************************************
#ifdef ENABLE_E131
void checkForRequests(void); //prototype
void handleE131(){
if (!e131.isEmpty())
{
e131_packet_t packet;
e131.pull(&packet); // Pull packet from ring buffer
uint16_t universe = htons(packet.universe);
uint8_t *data = packet.property_values + 1;
if (universe < START_UNIVERSE || universe > END_UNIVERSE) return; //async will take care about filling the buffer
// Serial.printf("Universe %u / %u Channels | Packet#: %u / Errors: %u / CH1: %u\n",
// htons(packet.universe), // The Universe for this packet
// htons(packet.property_value_count) - 1, // Start code is ignored, we're interested in dimmer data
// e131.stats.num_packets, // Packet counter
// e131.stats.packet_errors, // Packet error counter
// packet.property_values[1]); // Dimmer data for Channel 1
uint16_t multipacketOffset = (universe - START_UNIVERSE) * 170; //if more than 170 LEDs (510 channels), client will send in next higher universe
if (NUMLEDS <= multipacketOffset) return;
uint16_t len = (170 + multipacketOffset > NUMLEDS) ? (NUMLEDS - multipacketOffset) : 170;
for (uint16_t i = 0; i < len; i++){
uint16_t j = i * 3;
strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2]);
}
strip.show();
checkForRequests();
}
}
#endif
#ifdef ENABLE_HOMEASSISTANT #ifdef ENABLE_HOMEASSISTANT
void tickerSendState(){ void tickerSendState(){
new_ha_mqtt_msg = true; new_ha_mqtt_msg = true;
@@ -15,15 +49,15 @@ void tickerSpiffsSaveState(){
void getArgs() { void getArgs() {
if (server.arg("rgb") != "") { if (server.arg("rgb") != "") {
uint32_t rgb = (uint32_t) strtoul(server.arg("rgb").c_str(), NULL, 16); uint32_t rgb = (uint32_t) strtoul(server.arg("rgb").c_str(), NULL, 16);
main_color.white = ((rgb >> 24) & 0xFF); main_color.red = ((rgb >> 24) & 0xFF);
main_color.red = ((rgb >> 16) & 0xFF); main_color.green = ((rgb >> 16) & 0xFF);
main_color.green = ((rgb >> 8) & 0xFF); main_color.blue = ((rgb >> 8) & 0xFF);
main_color.blue = ((rgb ) & 0xFF); main_color.white = ((rgb >> 0) & 0xFF);
} else { } else {
main_color.white = server.arg("w").toInt();
main_color.red = server.arg("r").toInt(); main_color.red = server.arg("r").toInt();
main_color.green = server.arg("g").toInt(); main_color.green = server.arg("g").toInt();
main_color.blue = server.arg("b").toInt(); main_color.blue = server.arg("b").toInt();
main_color.white = server.arg("w").toInt();
} }
if (server.arg("s") != "") { if (server.arg("s") != "") {
ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255); ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255);
@@ -39,21 +73,21 @@ void getArgs() {
brightness = constrain(server.arg("p").toInt(), 0, 255); brightness = constrain(server.arg("p").toInt(), 0, 255);
} }
main_color.white = constrain(main_color.white, 0, 255);
main_color.red = constrain(main_color.red, 0, 255); main_color.red = constrain(main_color.red, 0, 255);
main_color.green = constrain(main_color.green, 0, 255); main_color.green = constrain(main_color.green, 0, 255);
main_color.blue = constrain(main_color.blue, 0, 255); main_color.blue = constrain(main_color.blue, 0, 255);
main_color.white = constrain(main_color.white, 0, 255);
DBG_OUTPUT_PORT.print("Mode: "); DBG_OUTPUT_PORT.print("Mode: ");
DBG_OUTPUT_PORT.print(mode); DBG_OUTPUT_PORT.print(mode);
DBG_OUTPUT_PORT.print(", Color: "); DBG_OUTPUT_PORT.print(", Color: ");
DBG_OUTPUT_PORT.print(main_color.white);
DBG_OUTPUT_PORT.print(", ");
DBG_OUTPUT_PORT.print(main_color.red); DBG_OUTPUT_PORT.print(main_color.red);
DBG_OUTPUT_PORT.print(", "); DBG_OUTPUT_PORT.print(", ");
DBG_OUTPUT_PORT.print(main_color.green); DBG_OUTPUT_PORT.print(main_color.green);
DBG_OUTPUT_PORT.print(", "); DBG_OUTPUT_PORT.print(", ");
DBG_OUTPUT_PORT.print(main_color.blue); DBG_OUTPUT_PORT.print(main_color.blue);
DBG_OUTPUT_PORT.print(", ");
DBG_OUTPUT_PORT.print(main_color.white);
DBG_OUTPUT_PORT.print(", Speed:"); DBG_OUTPUT_PORT.print(", Speed:");
DBG_OUTPUT_PORT.print(ws2812fx_speed); DBG_OUTPUT_PORT.print(ws2812fx_speed);
DBG_OUTPUT_PORT.print(", Brightness:"); DBG_OUTPUT_PORT.print(", Brightness:");
@@ -81,10 +115,11 @@ uint16_t convertSpeed(uint8_t mcl_speed) {
void handleSetMainColor(uint8_t * mypayload) { void handleSetMainColor(uint8_t * mypayload) {
// decode rgb data // decode rgb data
uint32_t rgb = (uint32_t) strtoul((const char *) &mypayload[1], NULL, 16); uint32_t rgb = (uint32_t) strtoul((const char *) &mypayload[1], NULL, 16);
main_color.white = ((rgb >> 24) & 0xFF); main_color.red = ((rgb >> 24) & 0xFF);
main_color.red = ((rgb >> 16) & 0xFF); main_color.green = ((rgb >> 16) & 0xFF);
main_color.green = ((rgb >> 8) & 0xFF); main_color.blue = ((rgb >> 8) & 0xFF);
main_color.blue = ((rgb ) & 0xFF); main_color.white = ((rgb >> 0) & 0xFF);
// strip.setColor(main_color.red, main_color.green, main_color.blue);
mode = SETCOLOR; mode = SETCOLOR;
} }
@@ -92,12 +127,12 @@ void handleSetAllMode(uint8_t * mypayload) {
// decode rgb data // decode rgb data
uint32_t rgb = (uint32_t) strtoul((const char *) &mypayload[1], NULL, 16); uint32_t rgb = (uint32_t) strtoul((const char *) &mypayload[1], NULL, 16);
main_color.white = ((rgb >> 24) & 0xFF); main_color.red = ((rgb >> 24) & 0xFF);
main_color.red = ((rgb >> 16) & 0xFF); main_color.green = ((rgb >> 16) & 0xFF);
main_color.green = ((rgb >> 8) & 0xFF); main_color.blue = ((rgb >> 8) & 0xFF);
main_color.blue = ((rgb ) & 0xFF); main_color.white = ((rgb >> 0) & 0xFF);
DBG_OUTPUT_PORT.printf("WS: Set all leds to main color: W: [%u] R: [%u] G: [%u] B: [%u]\n", main_color.white, main_color.red, main_color.green, main_color.blue); DBG_OUTPUT_PORT.printf("WS: Set all leds to main color: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white);
#ifdef ENABLE_LEGACY_ANIMATIONS #ifdef ENABLE_LEGACY_ANIMATIONS
exit_func = true; exit_func = true;
#endif #endif
@@ -113,23 +148,21 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) {
DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\n", led, strip.numPixels(), mypayload ); DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\n", led, strip.numPixels(), mypayload );
if (led <= strip.numPixels()) { if (led <= strip.numPixels()) {
char whitehex[3];
char redhex[3]; char redhex[3];
char greenhex[3]; char greenhex[3];
char bluehex[3]; char bluehex[3];
char whitehex[3];
strncpy (redhex, (const char *) &mypayload[2 + firstChar], 2 );
strncpy (greenhex, (const char *) &mypayload[4 + firstChar], 2 );
strncpy (bluehex, (const char *) &mypayload[6 + firstChar], 2 );
strncpy (whitehex, (const char *) &mypayload[2 + firstChar], 2 ); strncpy (whitehex, (const char *) &mypayload[2 + firstChar], 2 );
strncpy (redhex, (const char *) &mypayload[4 + firstChar], 2 );
strncpy (greenhex, (const char *) &mypayload[6 + firstChar], 2 );
strncpy (bluehex, (const char *) &mypayload[8 + firstChar], 2 );
ledstates[led].white = strtol(whitehex, NULL, 16);
ledstates[led].red = strtol(redhex, NULL, 16); ledstates[led].red = strtol(redhex, NULL, 16);
ledstates[led].green = strtol(greenhex, NULL, 16); ledstates[led].green = strtol(greenhex, NULL, 16);
ledstates[led].blue = strtol(bluehex, NULL, 16); ledstates[led].blue = strtol(bluehex, NULL, 16);
DBG_OUTPUT_PORT.printf(" rgb.white: [%s] rgb.red: [%s] rgb.green: [%s] rgb.blue: [%s]\n", whitehex, redhex, greenhex, bluehex); ledstates[led].white = strtol(whitehex, NULL, 16);
DBG_OUTPUT_PORT.printf(" rgb.white: [%i] rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i]\n", strtol(whitehex, NULL, 16), strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16)); DBG_OUTPUT_PORT.printf("rgb.red: [%s] rgb.green: [%s] rgb.blue: [%s] rgb.white: [%s]\n", redhex, greenhex, bluehex, whitehex);
DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] [%i] (%s)!\n", led, ledstates[led].white, ledstates[led].red, ledstates[led].green, ledstates[led].blue, mypayload); DBG_OUTPUT_PORT.printf("rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i] rgb.white: [%i]\n", strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16), strtol(whitehex, NULL, 16));
DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] [%i] (%s)!\n", led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white, mypayload);
strip.setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white); strip.setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white);
strip.show(); strip.show();
} }
@@ -194,27 +227,27 @@ void setModeByStateString(String saved_state_string) {
ws2812fx_speed = str_ws2812fx_speed.toInt(); ws2812fx_speed = str_ws2812fx_speed.toInt();
String str_brightness = getValue(saved_state_string, '|', 4); String str_brightness = getValue(saved_state_string, '|', 4);
brightness = str_brightness.toInt(); brightness = str_brightness.toInt();
String str_white = getValue(saved_state_string, '|', 5); String str_red = getValue(saved_state_string, '|', 5);
main_color.white = str_white.toInt();
String str_red = getValue(saved_state_string, '|', 6);
main_color.red = str_red.toInt(); main_color.red = str_red.toInt();
String str_green = getValue(saved_state_string, '|', 7); String str_green = getValue(saved_state_string, '|', 6);
main_color.green = str_green.toInt(); main_color.green = str_green.toInt();
String str_blue = getValue(saved_state_string, '|', 8); String str_blue = getValue(saved_state_string, '|', 7);
main_color.blue = str_blue.toInt(); main_color.blue = str_blue.toInt();
String str_white = getValue(saved_state_string, '|', 8);
main_color.white = str_white.toInt();
DBG_OUTPUT_PORT.printf("ws2812fx_mode: %d\n", ws2812fx_mode); DBG_OUTPUT_PORT.printf("ws2812fx_mode: %d\n", ws2812fx_mode);
DBG_OUTPUT_PORT.printf("ws2812fx_speed: %d\n", ws2812fx_speed); DBG_OUTPUT_PORT.printf("ws2812fx_speed: %d\n", ws2812fx_speed);
DBG_OUTPUT_PORT.printf("brightness: %d\n", brightness); DBG_OUTPUT_PORT.printf("brightness: %d\n", brightness);
DBG_OUTPUT_PORT.printf("main_color.white: %d\n", main_color.white);
DBG_OUTPUT_PORT.printf("main_color.red: %d\n", main_color.red); DBG_OUTPUT_PORT.printf("main_color.red: %d\n", main_color.red);
DBG_OUTPUT_PORT.printf("main_color.green: %d\n", main_color.green); DBG_OUTPUT_PORT.printf("main_color.green: %d\n", main_color.green);
DBG_OUTPUT_PORT.printf("main_color.blue: %d\n", main_color.blue); DBG_OUTPUT_PORT.printf("main_color.blue: %d\n", main_color.blue);
DBG_OUTPUT_PORT.printf("main_color.white: %d\n", main_color.white);
strip.setMode(ws2812fx_mode); strip.setMode(ws2812fx_mode);
strip.setSpeed(convertSpeed(ws2812fx_speed)); strip.setSpeed(convertSpeed(ws2812fx_speed));
strip.setBrightness(brightness); strip.setBrightness(brightness);
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
} }
#ifdef ENABLE_LEGACY_ANIMATIONS #ifdef ENABLE_LEGACY_ANIMATIONS
@@ -285,6 +318,19 @@ void setModeByStateString(String saved_state_string) {
} }
#endif #endif
#ifdef ENABLE_E131
void handleE131NamedMode(String str_mode) {
exit_func = true;
if (str_mode.startsWith("=e131") or str_mode.startsWith("/e131")) {
if(strip.isRunning()) strip.stop();
mode = E131;
#ifdef ENABLE_HOMEASSISTANT
stateOn = true;
#endif
}
}
#endif
void handleSetWS2812FXMode(uint8_t * mypayload) { void handleSetWS2812FXMode(uint8_t * mypayload) {
mode = SET_MODE; mode = SET_MODE;
uint8_t ws2812fx_mode_tmp = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10); uint8_t ws2812fx_mode_tmp = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10);
@@ -294,7 +340,7 @@ void handleSetWS2812FXMode(uint8_t * mypayload) {
String listStatusJSON(void) { String listStatusJSON(void) {
uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip.getMode(); uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip.getMode();
const size_t bufferSize = JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(6); const size_t bufferSize = JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(6) + 500;
DynamicJsonDocument jsonBuffer(bufferSize); DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>(); JsonObject root = jsonBuffer.to<JsonObject>();
root["mode"] = (uint8_t) mode; root["mode"] = (uint8_t) mode;
@@ -303,10 +349,10 @@ String listStatusJSON(void) {
root["speed"] = ws2812fx_speed; root["speed"] = ws2812fx_speed;
root["brightness"] = brightness; root["brightness"] = brightness;
JsonArray color = root.createNestedArray("color"); JsonArray color = root.createNestedArray("color");
color.add(main_color.white);
color.add(main_color.red); color.add(main_color.red);
color.add(main_color.green); color.add(main_color.green);
color.add(main_color.blue); color.add(main_color.blue);
color.add(main_color.white);
String json; String json;
serializeJson(root, json); serializeJson(root, json);
@@ -320,9 +366,14 @@ void getStatusJSON() {
} }
String listModesJSON(void) { String listModesJSON(void) {
const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+1) + strip.getModeCount()*JSON_OBJECT_SIZE(2); const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+1) + strip.getModeCount()*JSON_OBJECT_SIZE(2) + 1000;
DynamicJsonDocument jsonBuffer(bufferSize); DynamicJsonDocument jsonBuffer(bufferSize);
JsonArray json = jsonBuffer.to<JsonArray>(); JsonArray json = jsonBuffer.to<JsonArray>();
#ifdef ENABLE_E131
JsonObject objecte131 = json.createNestedObject();
objecte131["mode"] = "e131";
objecte131["name"] = "E131";
#endif
for (uint8_t i = 0; i < strip.getModeCount(); i++) { for (uint8_t i = 0; i < strip.getModeCount(); i++) {
JsonObject object = json.createNestedObject(); JsonObject object = json.createNestedObject();
object["mode"] = i; object["mode"] = i;
@@ -425,7 +476,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
if (payload[0] == '#') { if (payload[0] == '#') {
handleSetMainColor(payload); handleSetMainColor(payload);
Dbg_Prefix(mqtt, num); Dbg_Prefix(mqtt, num);
DBG_OUTPUT_PORT.printf("Set main color to: W: [%u] R: [%u] G: [%u] B: [%u]\n", main_color.white, main_color.red, main_color.green, main_color.blue); DBG_OUTPUT_PORT.printf("Set main color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white);
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
#endif #endif
@@ -449,6 +500,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
Dbg_Prefix(mqtt, num); Dbg_Prefix(mqtt, num);
DBG_OUTPUT_PORT.printf("Set speed to: [%u]\n", ws2812fx_speed); DBG_OUTPUT_PORT.printf("Set speed to: [%u]\n", ws2812fx_speed);
#ifdef ENABLE_HOMEASSISTANT #ifdef ENABLE_HOMEASSISTANT
stateOn = true;
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState); if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
#endif #endif
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
@@ -548,6 +600,9 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
String str_mode = String((char *) &payload[0]); String str_mode = String((char *) &payload[0]);
handleSetNamedMode(str_mode); handleSetNamedMode(str_mode);
#ifdef ENABLE_E131
handleE131NamedMode(str_mode);
#endif
Dbg_Prefix(mqtt, num); Dbg_Prefix(mqtt, num);
DBG_OUTPUT_PORT.printf("Activated mode [%u]!\n", mode); DBG_OUTPUT_PORT.printf("Activated mode [%u]!\n", mode);
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
@@ -615,6 +670,10 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
// / ==> Set WS2812 mode. // / ==> Set WS2812 mode.
if (payload[0] == '/') { if (payload[0] == '/') {
handleSetWS2812FXMode(payload); handleSetWS2812FXMode(payload);
#ifdef ENABLE_E131
String str_mode = String((char *) &payload[0]);
handleE131NamedMode(str_mode);
#endif
Dbg_Prefix(mqtt, num); Dbg_Prefix(mqtt, num);
DBG_OUTPUT_PORT.printf("Set WS2812 mode: [%s]\n", payload); DBG_OUTPUT_PORT.printf("Set WS2812 mode: [%s]\n", payload);
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
@@ -747,7 +806,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
} }
void sendState() { void sendState() {
const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6); const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 500;
DynamicJsonDocument jsonBuffer(bufferSize); DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>(); JsonObject root = jsonBuffer.to<JsonObject>();
@@ -763,9 +822,16 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
root["speed"] = ws2812fx_speed; root["speed"] = ws2812fx_speed;
char modeName[30]; //char modeName[30];
strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem //strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem
root["effect"] = modeName; #if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT)
if (mode == E131)
root["effect"] = "E131";
else
root["effect"] = strip.getModeName(strip.getMode());
#else
root["effect"] = strip.getModeName(strip.getMode());
#endif
char buffer[measureJson(root) + 1]; char buffer[measureJson(root) + 1];
serializeJson(root, buffer, sizeof(buffer)); serializeJson(root, buffer, sizeof(buffer));
@@ -835,9 +901,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
} }
if (root.containsKey("brightness")) { if (root.containsKey("brightness")) {
const char * brightness_json = root["brightness"]; brightness = constrain((uint8_t) root["brightness"], 0, 255); //fix #224
uint8_t b = (uint8_t) strtol((const char *) &brightness_json[0], NULL, 10);
brightness = constrain(b, 0, 255);
mode = BRIGHTNESS; mode = BRIGHTNESS;
} }
@@ -846,6 +910,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
String effectString = root["effect"].as<String>(); String effectString = root["effect"].as<String>();
for (uint8_t i = 0; i < strip.getModeCount(); i++) { for (uint8_t i = 0; i < strip.getModeCount(); i++) {
#if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT)
if(effectString == "E131"){
if(strip.isRunning()) strip.stop();
mode = E131;
break;
}
#endif
if(String(strip.getModeName(i)) == effectString) { if(String(strip.getModeName(i)) == effectString) {
mode = SET_MODE; mode = SET_MODE;
ws2812fx_mode = i; ws2812fx_mode = i;
@@ -920,10 +991,14 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
ha_send_data.detach(); ha_send_data.detach();
mqtt_client.subscribe(mqtt_ha_state_in.c_str(), qossub); mqtt_client.subscribe(mqtt_ha_state_in.c_str(), qossub);
#ifdef MQTT_HOME_ASSISTANT_SUPPORT #ifdef MQTT_HOME_ASSISTANT_SUPPORT
DynamicJsonDocument jsonBuffer(JSON_ARRAY_SIZE(strip.getModeCount()) + JSON_OBJECT_SIZE(11)); DynamicJsonDocument jsonBuffer(JSON_ARRAY_SIZE(strip.getModeCount()) + JSON_OBJECT_SIZE(12) + 1500);
JsonObject json = jsonBuffer.to<JsonObject>(); JsonObject json = jsonBuffer.to<JsonObject>();
json["name"] = HOSTNAME; json["name"] = HOSTNAME;
#ifdef MQTT_HOME_ASSISTANT_0_84_SUPPORT
json["schema"] = "json";
#else
json["platform"] = "mqtt_json"; json["platform"] = "mqtt_json";
#endif
json["state_topic"] = mqtt_ha_state_out; json["state_topic"] = mqtt_ha_state_out;
json["command_topic"] = mqtt_ha_state_in; json["command_topic"] = mqtt_ha_state_in;
json["on_command_type"] = "first"; json["on_command_type"] = "first";
@@ -936,6 +1011,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
for (uint8_t i = 0; i < strip.getModeCount(); i++) { for (uint8_t i = 0; i < strip.getModeCount(); i++) {
effect_list.add(strip.getModeName(i)); effect_list.add(strip.getModeName(i));
} }
#if defined(ENABLE_E131) and defined(MQTT_HOME_ASSISTANT_SUPPORT)
effect_list.add("E131");
#endif
char buffer[measureJson(json) + 1]; char buffer[measureJson(json) + 1];
serializeJson(json, buffer, sizeof(buffer)); serializeJson(json, buffer, sizeof(buffer));
mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true); mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true);
@@ -1016,6 +1094,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
for (uint8_t i = 0; i < strip.getModeCount(); i++) { for (uint8_t i = 0; i < strip.getModeCount(); i++) {
effect_list.add(strip.getModeName(i)); effect_list.add(strip.getModeName(i));
} }
#if defined(ENABLE_E131) and defined(MQTT_HOME_ASSISTANT_SUPPORT)
effect_list.add("E131");
#endif
char buffer[measureJson(json) + 1]; char buffer[measureJson(json) + 1];
serializeJson(json, buffer, sizeof(buffer)); serializeJson(json, buffer, sizeof(buffer));
DBG_OUTPUT_PORT.println(buffer); DBG_OUTPUT_PORT.println(buffer);
@@ -1172,7 +1253,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
uint8_t r, g, b, col, conf; uint8_t r, g, b, col, conf;
tcs.getData(&r, &g, &b, &col, &conf); tcs.getData(&r, &g, &b, &col, &conf);
DBG_OUTPUT_PORT.printf("Colors: R: [%d] G: [%d] B: [%d] Color: [%d] Conf: [%d]\n", (int)r, (int)g, (int)b, (int)col, (int)conf); DBG_OUTPUT_PORT.printf("Colors: R: [%d] G: [%d] B: [%d] Color: [%d] Conf: [%d]\n", (int)r, (int)g, (int)b, (int)col, (int)conf);
main_color.white = 0; main_color.red = (pow((r/255.0), 2.5)*255); main_color.green = (pow((g/255.0), 2.5)*255); main_color.blue = (pow((b/255.0), 2.5)*255); main_color.red = (pow((r/255.0), 2.5)*255); main_color.green = (pow((g/255.0), 2.5)*255); main_color.blue = (pow((b/255.0), 2.5)*255);main_color.white = 0;
ws2812fx_mode = 0; ws2812fx_mode = 0;
mode = SET_MODE; mode = SET_MODE;
buttonState = true; buttonState = true;
@@ -1241,14 +1322,14 @@ bool writeConfigFS(bool saveConfig){
//FS save //FS save
updateFS = true; updateFS = true;
DBG_OUTPUT_PORT.print("Saving config: "); DBG_OUTPUT_PORT.print("Saving config: ");
DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(4)); DynamicJsonDocument jsonBuffer;
JsonObject json = jsonBuffer.to<JsonObject>(); JsonObject json = jsonBuffer.to<JsonObject>();
json["mqtt_host"] = mqtt_host; json["mqtt_host"] = mqtt_host;
json["mqtt_port"] = mqtt_port; json["mqtt_port"] = mqtt_port;
json["mqtt_user"] = mqtt_user; json["mqtt_user"] = mqtt_user;
json["mqtt_pass"] = mqtt_pass; json["mqtt_pass"] = mqtt_pass;
// SPIFFS.remove("/config.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file"); //SPIFFS.remove("/config.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file");
File configFile = SPIFFS.open("/config.json", "w"); File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) DBG_OUTPUT_PORT.println("failed to open config file for writing"); if (!configFile) DBG_OUTPUT_PORT.println("failed to open config file for writing");
@@ -1310,18 +1391,18 @@ bool writeStateFS(){
updateFS = true; updateFS = true;
//save the strip state to FS JSON //save the strip state to FS JSON
DBG_OUTPUT_PORT.print("Saving cfg: "); DBG_OUTPUT_PORT.print("Saving cfg: ");
DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(7)); DynamicJsonDocument jsonBuffer;
JsonObject json = jsonBuffer.to<JsonObject>(); JsonObject json = jsonBuffer.to<JsonObject>();
json["mode"] = static_cast<int>(mode); json["mode"] = static_cast<int>(mode);
json["strip_mode"] = (int) strip.getMode(); json["strip_mode"] = (int) strip.getMode();
json["brightness"] = brightness; json["brightness"] = brightness;
json["speed"] = ws2812fx_speed; json["speed"] = ws2812fx_speed;
json["white"] = main_color.white;
json["red"] = main_color.red; json["red"] = main_color.red;
json["green"] = main_color.green; json["green"] = main_color.green;
json["blue"] = main_color.blue; json["blue"] = main_color.blue;
json["white"] = main_color.white;
// SPIFFS.remove("/state.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file"); //SPIFFS.remove("/stripstate.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file");
File configFile = SPIFFS.open("/stripstate.json", "w"); File configFile = SPIFFS.open("/stripstate.json", "w");
if (!configFile) { if (!configFile) {
DBG_OUTPUT_PORT.println("Failed!"); DBG_OUTPUT_PORT.println("Failed!");
@@ -1362,15 +1443,21 @@ bool readStateFS() {
ws2812fx_mode = json["strip_mode"]; ws2812fx_mode = json["strip_mode"];
brightness = json["brightness"]; brightness = json["brightness"];
ws2812fx_speed = json["speed"]; ws2812fx_speed = json["speed"];
main_color.white = json["white"];
main_color.red = json["red"]; main_color.red = json["red"];
main_color.green = json["green"]; main_color.green = json["green"];
main_color.blue = json["blue"]; main_color.blue = json["blue"];
main_color.white = json["white"];
strip.setMode(ws2812fx_mode); strip.setMode(ws2812fx_mode);
strip.setSpeed(convertSpeed(ws2812fx_speed)); strip.setSpeed(convertSpeed(ws2812fx_speed));
strip.setBrightness(brightness); strip.setBrightness(brightness);
strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white);
#ifdef ENABLE_E131
if (mode == E131) {
strip.stop();
}
#endif
updateFS = false; updateFS = false;
return true; return true;
+1 -1
View File
@@ -1 +1 @@
#define SKETCH_VERSION "2.1.4" #define SKETCH_VERSION "2.2.0"
+42
View File
@@ -17,4 +17,46 @@
* *
* 10 Jul 2018 v 2.1.4 * 10 Jul 2018 v 2.1.4
* - Fixes measureJson() as pointed in #206 * - Fixes measureJson() as pointed in #206
*
* 2 Oct 2018 v 2.1.5
* - Try fixing #224 HA brightness causes reboot
*
* 5 Nov 2018 v 2.1.6
* - Retire NeoAnimationFX
* - Use DMA or UART method along with WS2812FX instead
* - fix #248
*
* 3 Dec 2018 v 2.1.7
* - Contributions by @ MrTheBarbarian from #270
* - rethink ESP.getChipId implementaion
* - check ArduinoJSON version
* - Try restting prevmode as suggested in #276
*
* 11 Dec 2018 v 2.1.8
* - Fix Auto-Discovery for HA version >= 0.84 #286
* - Fix #283
*
* 12 Dec 2018 v 2.2.0
* - Add E1.31 mode initial commit
* - E1.31 mode when activated now stops current animation
*
* 13 Dec 2018 v 2.1.9
* - HA is not getting the correct animation name being run, boils down to changes to ArduinoJson library
* - Bump ArduinoJson library requirment for v6.7.0-beta (better memory management)
* - sendState() needs extra memory for jsonBuffer
* - sensState() effect can be sent directly instead of copying from PROGMEM
*
* 16 Dec 2018 v 2.1.10
* - more ArduinoJson library memory managment fixes
*
* 18 Dec 2018 v 2.1.11
* - More Auto-Discovery fix for HA version >= 0.84 #286
* - Suggestions from https://github.com/home-assistant/home-assistant/issues/19420
*
* 23 Dec 2018 v 2.2.0
* - Add E1.31 mode to getModes(), no need to change McLightingUI
*
* 6 Jan 2018 v 2.2.0
* - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet
* - HA E1.31 mode added
*/ */
+17 -161
View File
@@ -1,165 +1,21 @@
GNU LESSER GENERAL PUBLIC LICENSE MIT License
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (c) 2018 Tobias Blum @toblum, Debashish Sahu @debsahu
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
This version of the GNU Lesser General Public License incorporates The above copyright notice and this permission notice shall be included in all
the terms and conditions of version 3 of the GNU General Public copies or substantial portions of the Software.
License, supplemented by the additional permissions listed below.
0. Additional Definitions. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
As used herein, "this License" refers to version 3 of the GNU Lesser FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
General Public License, and the "GNU GPL" refers to version 3 of the GNU AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
General Public License. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
"The Library" refers to a covered work governed by this License, SOFTWARE.
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+73
View File
@@ -0,0 +1,73 @@
Update 13.05.2018:
I've worked on a new web UI for the last weeks. It's now available as an early preview. There is a [video](https://youtu.be/lryDPMA2qpY) that shows the new features. [Try it out](https://github.com/toblum/McLightingUI) if you want and leave some feedback.
Update 07.04.2018:
And even more changes to McLighting! Most of them were contributed by user @debsahu. Thank you!
- Update arduino-esp8266 to latest, at least version 2.4.1
- AMQTT is now the default MQTT library, it's a bit more lightweight and stable. You can still use PubSubClient if you want to.
- You can use @debsahu great NeoAnimationFX library as a alternative to WS2812FX. It's based on the NeoPixelBus instead of Adafruits NeoPixel library. It can handle longer strips more efficient. If you want, give it a try. WS2812FX is still the default.
- Some more changes regarding Homeassistant integration.
Please see the [Wiki](https://github.com/toblum/McLighting/wiki/Software-installation) for details on the required libraries.
If you have problems with the new version, let us know. You can get the last version [here](https://github.com/toblum/McLighting/tree/Before_AMQTT_NeoAnimationFX).
I'm also working on a alternative web interface for McLighting in the meanwhile, but it may take some more time.
For the german users: McLighting was used in [Kliemannsland](https://youtu.be/3TUjszkS3bY?t=1211) (a funny web show) when they built a really big Neopixel installation.
Update 18.03.2018:
The code for integration with homeassistant was merged into master. It's currently active by default. You can safely disable it in definitions.h when use do not want to use it, or want to use McLighting on a small ESP_01.
There are some informations in the [Wiki](https://github.com/toblum/McLighting/wiki/Homeassistant-integration).
Update 17.02.2018:
User @debsahu contributed code for integration with homeassistant. It's currently in a separate branch (https://github.com/toblum/McLighting/tree/feature/ha_integration). If you're using Homeassistant, please try it out and give feedback.
User @FabLab-Luenn created a version of McLighting (https://github.com/FabLab-Luenen/McLighting) for 6812 and other RGBW strips. Give it a try, if you own such strips.
A thank you goes to all contributors.
Update 12. / 15.02.2018:
Added Home Assistant Support using MQTT Light. A better implementation would be using MQTT Light JSON.
Replaced Home Assistant Support using MQTT Light to MQTT JSON Light.
Update 31.01.2018:
User @codmpm did a very professional McLighting installation and even designed his own PCBs. He has a great writeup for his project at: https://allgeek.de/2018/01/29/esp8266-neopixel-controller/ (in german).
Update 27.01.2018:
Many people asked if it's possible to connect more than one strip (currently not) or at least "sync" multiple McLighting nodes. Although it may be possible to connect more then one WS2812 strip to the same data pin (works in many cases, you just have to try), syncing many McLighting instances would be a benefit. This could easily be achieved done by software like [NodeRed](https://nodered.org/). I added a example flow to demonstrate that [here](https://github.com/toblum/McLighting/blob/master/clients/node_red/websocket_proxy.json). Have a look at the short video [here](https://youtu.be/g3CHtG9c520).
Update 21.01.2018:
User @szepnorbee contributed code for button control. Thank you! It's merged into the master branch now. There is a short manual for configuration [here](https://github.com/toblum/McLighting/wiki/Button-control).
Update 06.01.2018:
After som etesting I merged the "feature/save_state" banch into master, so everybody should now be able to use this new functionality. Basically McLighting now saves the current mode to EEPROM and restores the setting on reboot. So you wont need to select your favorite mode again. If you don't want to use this, you can disable it in definitions.h.
~~Some people noticed that there are currently problems compiling McLighting whe using ESP8266 core in version 2.4.0. This is due to a [problem](https://github.com/kitesurfer1404/WS2812FX/issues/58) with WS2812FX when using this version. For the moment you can stick to the 2.4.0 RC2 (also easily available via the boards manager).~~ (fixed now )
Funny! McLighting was featured in the german radio show ["Netzbasteln"](https://www.deutschlandfunknova.de/beitrag/netzbasteln-wolkenlampe-mit-cloud-anschluss) on Deutschlandfunk Nova with a nice audio tutorial.
Update 16.12.2017:
There was a breaking change in the WS2812FX library: Speeds have a new format (65535-0 instead of 0-255). I released a new version that converts the speeds settings. Please use the latest [WS2812FX library](https://github.com/kitesurfer1404/WS2812FX) (14.12.2017 or later) if use have an existing version installed.
I got many messages from people who use McLighting for own projects. User Brian Lough built a lighting system for his wedding and made a nice instruction video for his build: https://goo.gl/NbfKi8
Update 30.09.2017:
Thanks to [@moose4lord](https://github.com/moose4lord) Mclighting works with the newest version of WS1812FX and has a possibility to define autocycle patterns [Wiki](https://github.com/toblum/McLighting/wiki/Autocycling). Thank for contributing to McLighting everyone!
I was also informed of a new project that is loosely based on McLighting: [Responsive_LED_Control](https://github.com/doctormord/Responsive_LED_Control) That looks very promising.
Update 07.08.2017:
As requested by many of you, McLighting now also features MQTT support. Thanks at @LeonVos for his attempts on this. I implemented the same API as used in WebSockets now for MQTT. Please have a look here for details: https://github.com/toblum/McLighting/wiki/MQTT-API I will try to add a new instruction video soon.
Many of you also took McLighting and adapted the software according your needs. This is great. I found some videos on YouTube that show these projects. I collected them here: https://goo.gl/yG7M4h
If you have done something similar with McLighting, please drop me a note. I'm always interested in what you've done with it.
Update 19.02.2017:
Added OTA support as promised by @markbajaj. Minor other improvements.
Update 05.02.2017:
After a long time I was able to work a bit on McLighting v2 and it's finally out now. The main difference, among minor improvements and library updates, is the usage of the great WS2812FX library for color animations. It brings a lot (almost 50!) of new animations.
The API changed a little bit, because the speed can now be set as a value from 0 to 255, not the delay anymore. So the web inferface had to change accordingly. The new animation mode have to be set also by their number, instead of a dedicated url. The list of all animation modes can also be received by the API. All existing API endpoints are kept for downward compatibility. So you should be able to use the new version without big changes. The original version is kept as branch "mclighting_legacy". Documentation will be updated soon.
Update 04.01.2017:
Now, there are two forks of McLighting (using the famous FastLED library). I did not notice it first, because I currently do not receive notification e-mails by Github (I have no idea why). Maybe you want to give them also a try, I will definitely do so as soon as I find time.
https://github.com/russp81/LEDLAMP_FASTLEDs
And this one was also forked: https://github.com/jake-b/Griswold-LED-Controller
Update 12.08.2016:
There is now a [gitter.im](https://gitter.im/mclighting/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link) chat room for this project.
Update 11.06.2016:
Today I presented the project at [Pi and More 9](https://piandmore.de/) and got some good feedback, even though my presentation was not perfect and time was too short to present everything I prepared. So I uploaded the [slides (german)](documentation/slides/Ein%20SmartLight%20im%20Selbstbau%20für%20unter%2015%20€_Pi%20and%20More%209.pdf) to this repository for your reference.
+45 -116
View File
@@ -1,143 +1,80 @@
# McLighting v2 - The ESP8266 based multi-client lighting gadget # McLighting v2 - The ESP8266 based multi-client lighting gadget
[![Gitter](https://badges.gitter.im/mclighting/Lobby.svg)](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/mclighting/Lobby.svg)](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Build Status](https://travis-ci.com/toblum/McLighting.svg?branch=master)](https://travis-ci.com/toblum/McLighting) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![version](https://img.shields.io/badge/version-v2.2.0-blue.svg)](https://github.com/toblum/McLighting/blob/master/Arduino/McLighting/version.h)
> Mc Lighting (the multi-client lighting gadget) is a very cheap internet-controllable lighting solution based on the famous ESP8266 microcontroller and WS2811/2812 led strips. It features a self-hosted responsive web-interface, a REST-API and a websocket connector. McLighting (the multi-client lighting gadget) is a very cheap internet-controllable lighting solution based on the famous ESP8266 microcontroller and WS2811/2812 led strips. It features among other things a web-interface, a REST-API and a websocket connector.
> Because of it's open architecture and APIs it's easy to build new clients for different platforms (iOS, Android, Windows Universal Apps, Siri/Cortana integration, ...). Because of it's open architecture and APIs it's easy to build new clients for different platforms (iOS, Android, Windows Universal Apps, Siri/Cortana integration, ...).
[![Demo video WebClient](https://j.gifs.com/kRPrzN.gif)](https://youtu.be/rc6QVHKAXBs) [![Demo video WebClient](https://j.gifs.com/kRPrzN.gif)](https://youtu.be/rc6QVHKAXBs)
[![Demo video Apple Homekit integration](https://j.gifs.com/gJP2o6.gif)](https://youtu.be/4JnGXZaPnrw) [![Demo video Apple Homekit integration](https://j.gifs.com/gJP2o6.gif)](https://youtu.be/4JnGXZaPnrw)
___ ---
Update 13.05.2018:
I've worked on a new web UI for the last weeks. It's now available as an early preview. There is a [video](https://youtu.be/lryDPMA2qpY) that shows the new features. [Try it out](https://github.com/toblum/McLightingUI) if you want and leave some feedback.
Update 07.04.2018:
And even more changes to McLighting! Most of them were contributed by user @debsahu. Thank you!
- Update arduino-esp8266 to latest, at least version 2.4.1
- AMQTT is now the default MQTT library, it's a bit more lightweight and stable. You can still use PubSubClient if you want to.
- You can use @debsahu great NeoAnimationFX library as a alternative to WS2812FX. It's based on the NeoPixelBus instead of Adafruits NeoPixel library. It can handle longer strips more efficient. If you want, give it a try. WS2812FX is still the default.
- Some more changes regarding Homeassistant integration.
Please see the [Wiki](https://github.com/toblum/McLighting/wiki/Software-installation) for details on the required libraries.
If you have problems with the new version, let us know. You can get the last version [here](https://github.com/toblum/McLighting/tree/Before_AMQTT_NeoAnimationFX).
I'm also working on a alternative web interface for McLighting in the meanwhile, but it may take some more time.
For the german users: McLighting was used in [Kliemannsland](https://youtu.be/3TUjszkS3bY?t=1211) (a funny web show) when they built a really big Neopixel installation.
Update 18.03.2018:
The code for integration with homeassistant was merged into master. It's currently active by default. You can safely disable it in definitions.h when use do not want to use it, or want to use McLighting on a small ESP_01.
There are some informations in the [Wiki](https://github.com/toblum/McLighting/wiki/Homeassistant-integration).
Update 17.02.2018:
User @debsahu contributed code for integration with homeassistant. It's currently in a separate branch (https://github.com/toblum/McLighting/tree/feature/ha_integration). If you're using Homeassistant, please try it out and give feedback.
User @FabLab-Luenen created a version of McLighting (https://github.com/FabLab-Luenen/McLighting) for 6812 and other RGBW strips. Give it a try, if you own such strips.
A thank you goes to all contributors.
Update 12. / 15.02.2018:
Added Home Assistant Support using MQTT Light. A better implementation would be using MQTT Light JSON.
Replaced Home Assistant Support using MQTT Light to MQTT JSON Light.
Update 31.01.2018:
User @codmpm did a very professional McLighting installation and even designed his own PCBs. He has a great writeup for his project at: https://allgeek.de/2018/01/29/esp8266-neopixel-controller/ (in german).
Update 27.01.2018:
Many people asked if it's possible to connect more than one strip (currently not) or at least "sync" multiple McLighting nodes. Although it may be possible to connect more then one WS2812 strip to the same data pin (works in many cases, you just have to try), syncing many McLighting instances would be a benefit. This could easily be achieved done by software like [NodeRed](https://nodered.org/). I added a example flow to demonstrate that [here](https://github.com/toblum/McLighting/blob/master/clients/node_red/websocket_proxy.json). Have a look at the short video [here](https://youtu.be/g3CHtG9c520).
Update 21.01.2018:
User @szepnorbee contributed code for button control. Thank you! It's merged into the master branch now. There is a short manual for configuration [here](https://github.com/toblum/McLighting/wiki/Button-control).
Update 06.01.2018:
After som etesting I merged the "feature/save_state" banch into master, so everybody should now be able to use this new functionality. Basically McLighting now saves the current mode to EEPROM and restores the setting on reboot. So you wont need to select your favorite mode again. If you don't want to use this, you can disable it in definitions.h.
~~Some people noticed that there are currently problems compiling McLighting whe using ESP8266 core in version 2.4.0. This is due to a [problem](https://github.com/kitesurfer1404/WS2812FX/issues/58) with WS2812FX when using this version. For the moment you can stick to the 2.4.0 RC2 (also easily available via the boards manager).~~ (fixed now )
Funny! McLighting was featured in the german radio show ["Netzbasteln"](https://www.deutschlandfunknova.de/beitrag/netzbasteln-wolkenlampe-mit-cloud-anschluss) on Deutschlandfunk Nova with a nice audio tutorial.
Update 16.12.2017:
There was a breaking change in the WS2812FX library: Speeds have a new format (65535-0 instead of 0-255). I released a new version that converts the speeds settings. Please use the latest [WS2812FX library](https://github.com/kitesurfer1404/WS2812FX) (14.12.2017 or later) if use have an existing version installed.
I got many messages from people who use McLighting for own projects. User Brian Lough built a lighting system for his wedding and made a nice instruction video for his build: https://goo.gl/NbfKi8
Update 30.09.2017:
Thanks to [@moose4lord](https://github.com/moose4lord) Mclighting works with the newest version of WS1812FX and has a possibility to define autocycle patterns [Wiki](https://github.com/toblum/McLighting/wiki/Autocycling). Thank for contributing to McLighting everyone!
I was also informed of a new project that is loosely based on McLighting: [Responsive_LED_Control](https://github.com/doctormord/Responsive_LED_Control) That looks very promising.
Update 07.08.2017:
As requested by many of you, McLighting now also features MQTT support. Thanks at @LeonVos for his attempts on this. I implemented the same API as used in WebSockets now for MQTT. Please have a look here for details: https://github.com/toblum/McLighting/wiki/MQTT-API I will try to add a new instruction video soon.
Many of you also took McLighting and adapted the software according your needs. This is great. I found some videos on YouTube that show these projects. I collected them here: https://goo.gl/yG7M4h
If you have done something similar with McLighting, please drop me a note. I'm always interested in what you've done with it.
Update 19.02.2017:
Added OTA support as promised by @markbajaj. Minor other improvements.
Update 05.02.2017:
After a long time I was able to work a bit on McLighting v2 and it's finally out now. The main difference, among minor improvements and library updates, is the usage of the great WS2812FX library for color animations. It brings a lot (almost 50!) of new animations.
The API changed a little bit, because the speed can now be set as a value from 0 to 255, not the delay anymore. So the web inferface had to change accordingly. The new animation mode have to be set also by their number, instead of a dedicated url. The list of all animation modes can also be received by the API. All existing API endpoints are kept for downward compatibility. So you should be able to use the new version without big changes. The original version is kept as branch "mclighting_legacy". Documentation will be updated soon.
Update 04.01.2017:
Now, there are two forks of McLighting (using the famous FastLED library). I did not notice it first, because I currently do not receive notification e-mails by Github (I have no idea why). Maybe you want to give them also a try, I will definitely do so as soon as I find time.
https://github.com/russp81/LEDLAMP_FASTLEDs
And this one was also forked: https://github.com/jake-b/Griswold-LED-Controller
Update 12.08.2016:
There is now a [gitter.im](https://gitter.im/mclighting/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link) chat room for this project.
Update 11.06.2016:
Today I presented the project at [Pi and More 9](https://piandmore.de/) and got some good feedback, even though my presentation was not perfect and time was too short to present everything I prepared. So I uploaded the [slides (german)](documentation/slides/Ein%20SmartLight%20im%20Selbstbau%20für%20unter%2015%20€_Pi%20and%20More%209.pdf) to this repository for your reference.
___
## The Hardware ## The Hardware
The project ist based on the famous ESP8266 microcontroller and WD2811/WS2812 LED strips. There are many variations of the ESP chip out there, but I chose the NodeMCU dev board, because it's powered by micro USB and has a voltage converter included to power the ESP which uses 3.3V. The project is based on the ESP8266 and WD2811/WS2812 LED strips. There are many variations of the ESP chip out there, but for beginners we suggest a NodeMCU dev board, as these are as "plug 'n' play"as it can get.
A standalone ESP8266 or a Adafruit Huzzah should work too. A standalone ESP8266 or an Adafruit Huzzah should work too.
The RGB LED strips are also available in many different flavours as strip or as standalone LEDs and can easily be chained. The RGB LED strips are also available in many different flavours (as strips or as standalone LEDs) and can easily be chained.
See wiki [Hardware](../../wiki/Hardware) For a detailed explanation see our wiki: [Hardware](../../wiki/Hardware)
## Software installation ## Software installation
See wiki [Software installation](../../wiki/Software-installation)
You can read how to get started on the software side of this project
again in out wiki: [Software installation](../../wiki/Software-installation)
---
### Used Libraries ### Used Libraries
This project uses libraries and code by different authors: This project uses libraries and code by different authors:
- WiFiManager by @tzapu (tested with version 0.12.0)
https://github.com/tzapu/WiFiManager - [WiFiManager](https://github.com/tzapu/WiFiManager) by tzapu (tested with version 0.12.0)
- WS2812FX by @kitesurfer1404 (tested with version downloaded 2017-02-05)
https://github.com/kitesurfer1404/WS2812FX - [WS2812FX](https://github.com/kitesurfer1404/WS2812FX) by kitesurfer1404 (tested with version downloaded 2017-02-05)
- WebSockets by @Links2004 (tested with version 2.0.6)
https://github.com/Links2004/arduinoWebSockets - [WebSockets](https://github.com/Links2004/arduinoWebSockets) by Links2004 (tested with version 2.0.6)
- Adafruit NeoPixel by @adafruit (tested with 1.1.2)
https://github.com/adafruit/Adafruit_NeoPixel - [Adafruit NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel) by adafruit (tested with 1.1.2)
- Optional: PubSubClient by @knolleary (tested with 2.6.0)
Only when you have activated MQTT in definitions.h. - Optional: [PubSubClient](https://github.com/knolleary/pubsubclient/) by knolleary (tested with 2.6.0)
https://github.com/knolleary/pubsubclient/ _Only when you have activated MQTT in definitions.h._
The sketch also uses the following built-in library: The sketch also uses the following built-in library:
- Ticker by @igrr - Ticker by [@igrr](https://github.com/igrr)
Parts of the code were taken or inspired by the following sources: Parts of the code were taken or inspired by the following sources:
- HSB3RGB conversion
https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/ - [HSB3RGB conversion](https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/)
- TV simulator logic inspired by @BulldogLowell
https://github.com/BulldogLowell/PhoneyTV - [TV simulator](https://github.com/BulldogLowell/PhoneyTV) logic inspired by BulldogLowell
- SPIFFS Webserver by Hristo Gochkov
https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/FSBrowser - [SPIFFS Webserver](https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/FSBrowser) by Hristo Gochkov
Thank you to all the authors for distributing their software that way. Thank you to all the authors for distributing their software that way.
I hope I didn't miss any sources and mentioned every author. In case I forgot someone please let me know and I will fix it. I hope I didn't miss any sources and mentioned every author. In case I forgot someone please let me know and I will fix it.
## Todos ## Todos
- [x] MQTT support
- [ ] Support multiple strips and control them separately or together [Issue](https://github.com/toblum/McLighting/issues/118) - [ ] Support multiple strips and control them separately or together [Issue](https://github.com/toblum/McLighting/issues/118)
- [x] Save favourite effects? [Issue](https://github.com/toblum/McLighting/issues/35) - [ ] Make number of pixels, MQTT and PIN configurable via front end [Issue](https://github.com/toblum/McLighting/issues/93) and [Issue](https://github.com/toblum/McLighting/issues/93)
- [ ] Make number of pixels, MQTT and PIN configurable via front end [Issue](https://github.com/toblum/McLighting/issues/93) and [Issue](https://github.com/toblum/McLighting/issues/101)
- [x] OTA update [Issue](https://github.com/toblum/McLighting/issues/93)
- [ ] Bundle webpages instead of SPIFFS [Issue](https://github.com/toblum/McLighting/issues/93) - [ ] Bundle webpages instead of SPIFFS [Issue](https://github.com/toblum/McLighting/issues/93)
- [ ] Remove old / wrong EEPROM settings completely (https://github.com/toblum/McLighting/issues/92) - [ ] Remove old / wrong EEPROM settings completely [Issue]
- [ ] Customer profile to define segments of (in)active areas on the strip [Issue](https://github.com/toblum/McLighting/issues/37)
- [ ] Additional clients
- [ ] If no wifi, at least enable button mode.
- [ ] Also enable McLighting in Wifi AP mode.
- [ ] IR remote support [issue](https://github.com/toblum/McLightingUI/issues/3)
- [ ] Multiple buttons/GPIO Inputs. [Issue](https://github.com/toblum/McLighting/issues/119)
- [ ] Music visualizer / Bring back ArtNet [Issue](https://github.com/toblum/McLighting/issues/111)
- [ ] Display version and parameters (Number of LEDs, definition settings, ..) in the web UI [Issue](https://github.com/toblum/McLighting/issues/150)
- [x] MQTT support
- [x] Save favourite effects? [Issue](https://github.com/toblum/McLighting/issues/35)(https://github.com/toblum/McLighting/issues/101)
- [x] OTA update [Issue](https://github.com/toblum/McLighting/issues/92)
- [x] Fix issue with websockets connection problems - [x] Fix issue with websockets connection problems
- [x] Switch to the [NeoPixelBus library](https://github.com/Makuna/NeoPixelBus/wiki) - [x] Switch to the [NeoPixelBus library](https://github.com/Makuna/NeoPixelBus/wiki)
- [x] Use the led strip for status information in connection phase - [x] Use the led strip for status information in connection phase
@@ -145,21 +82,13 @@ I hope I didn't miss any sources and mentioned every author. In case I forgot so
- [x] Stability improvements - [x] Stability improvements
- [x] RGBW mode [Issue](https://github.com/toblum/McLighting/issues/24) - [x] RGBW mode [Issue](https://github.com/toblum/McLighting/issues/24)
- [x] Add called command to response [Issue](https://github.com/toblum/McLighting/issues/19) - [x] Add called command to response [Issue](https://github.com/toblum/McLighting/issues/19)
- [ ] Customer profile to define segments of (in)active areas on the strip [Issue](https://github.com/toblum/McLighting/issues/37)
- [x] Button control [Issue](https://github.com/toblum/McLighting/issues/36) - [x] Button control [Issue](https://github.com/toblum/McLighting/issues/36)
- [x] Retain last state [Issue](https://github.com/toblum/McLighting/issues/47) - [x] Retain last state [Issue](https://github.com/toblum/McLighting/issues/47)
- [ ] Additional clients
- [ ] If no wifi, at least enable button mode.
- [ ] Also enable McLighting in Wifi AP mode.
- [x] Make a set of NodeRed nodes. - [x] Make a set of NodeRed nodes.
- [ ] IR remote support [issue](https://github.com/toblum/McLightingUI/issues/3)
- [ ] Multiple buttons/GPIO Inputs. [Issue](https://github.com/toblum/McLighting/issues/119)
- [ ] Music visualizer / Bring back ArtNet [Issue](https://github.com/toblum/McLighting/issues/111)
- [ ] Display version and parameters (Number of LEDs, definition settings, ..) in the web UI [Issue](https://github.com/toblum/McLighting/issues/150)
## Licence ## Licence
[GNU LGPLv3](http://www.gnu.org/licenses/lgpl-3.0.txt) [MIT](https://choosealicense.com/licenses/mit/)
## Disclaimer ## Disclaimer
+5 -3
View File
@@ -1,5 +1,6 @@
light: light:
- platform: mqtt_json - platform: mqtt
schema: json
name: "NeoPixel LEDs" name: "NeoPixel LEDs"
state_topic: "home/McLighting01_ha/state/out" state_topic: "home/McLighting01_ha/state/out"
command_topic: "home/McLighting01_ha/state/in" command_topic: "home/McLighting01_ha/state/in"
@@ -63,6 +64,7 @@ light:
- "Bicolor Chase" - "Bicolor Chase"
- "Tricolor Chase" - "Tricolor Chase"
- "ICU" - "ICU"
- "E131"
brightness: true brightness: true
color_temp: true color_temp: true
rgb: true rgb: true
@@ -79,7 +81,7 @@ input_number:
step: 5 step: 5
automation: automation:
- id: 71938579813759813757 - id: "71938579813759813757"
alias: NeoPixel Animation Speed Send alias: NeoPixel Animation Speed Send
initial_state: true initial_state: true
hide_entity: false hide_entity: false
@@ -93,7 +95,7 @@ automation:
topic: home/McLighting01_ha/state/in topic: home/McLighting01_ha/state/in
service: mqtt.publish service: mqtt.publish
- id: 93786598732698756967 - id: "93786598732698756967"
alias: NeoPixel Animation Speed Receive alias: NeoPixel Animation Speed Receive
trigger: trigger:
- platform: mqtt - platform: mqtt
+1
View File
@@ -12,6 +12,7 @@
{ {
"accessory": "HTTP-RGB", "accessory": "HTTP-RGB",
"name": "Wohnzimmerlampe", "name": "Wohnzimmerlampe",
"service": "Light",
"switch": { "switch": {
"status": "http://<ESP_HOST>/get_switch", "status": "http://<ESP_HOST>/get_switch",
+25 -55
View File
@@ -10,14 +10,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="mobile-web-app-capable" content="yes">
<title>McLighting v2</title> <title>McLighting v2</title>
</head> </head>
<body> <body>
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav"> <nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
<div class="nav-wrapper container"> <div class="nav-wrapper container">
<a id="logo-container" href="#" class="brand-logo">McLighting v2</a> <a id="logo-container" href="#" class="brand-logo">Mc Lighting v2</a>
<ul class="right hide-on-med-and-down"> <ul class="right hide-on-med-and-down">
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li> <li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
@@ -120,6 +119,18 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col s12 m6 l6 btn_grid">
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l6 btn_grid">
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV
<i class="material-icons right">send</i>
</a>
</div>
<div id="modes"> <div id="modes">
<div class="input-field col s12"> <div class="input-field col s12">
Loading animations... Loading animations...
@@ -173,9 +184,9 @@ $(function(){
$('#' + pane).removeClass('hide'); $('#' + pane).removeClass('hide');
$('.button-collapse').sideNav('hide'); $('.button-collapse').sideNav('hide');
//if (pane == "pane2") { if (pane == "pane2") {
// setMainColor(); setMainColor();
//} }
} }
@@ -185,54 +196,16 @@ $(function(){
function init() { function init() {
console.log("Connection websockets to:", ws_url); console.log("Connection websockets to:", ws_url);
connection = new WebSocket(ws_url, ['arduino']); connection = new WebSocket(ws_url, ['arduino']);
var mode = 0;
var ws2812fx_mode = 0;
$.getJSON("http://" + host + "/status", function(data) {
console.log("status", data);
mode = data.mode;
ws2812fx_mode = data.ws2812fx_mode;
$("#rng_delay").val(data.speed);
$("#rng_brightness").val(data.brightness);
$("#rng_red").val(data.color[0]);
$("#rng_green").val(data.color[1]);
$("#rng_blue").val(data.color[2]);
var statusColor = "#" + componentToHex(data.color[0]) + componentToHex(data.color[1]) + componentToHex(data.color[2]);
$('#status').css("backgroundColor", statusColor);
$('#status_color').text(statusColor + "- R=" + data.color[0] + ", G=" + data.color[1] + ", B=" + data.color[2]);
});
// Load modes async // Load modes async
// List of all color modes
// enum MODE { SET_MODE, HOLD, AUTO, OFF, TV, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW};
$.getJSON("http://" + host + "/get_modes", function(data) { $.getJSON("http://" + host + "/get_modes", function(data) {
console.log("modes", data); //console.log("modes", data);
var modes_html = ""; var modes_html = "";
modes_html += '<div class="col s12 m6 l6 btn_grid">';
if (mode == "3") {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static red" name="action" data-mode="off">OFF';
} else {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF';
}
modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>';
modes_html += '</div>'
modes_html += '<div class="col s12 m6 l6 btn_grid">';
if (mode == "4") {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static red" name="action" data-mode="tv">TV';
} else {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV';
}
modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>';
modes_html += '</div>';
data.forEach(function(current_mode){ data.forEach(function(current_mode){
if (current_mode.mode !== undefined) { if (current_mode.mode !== undefined) {
modes_html += '<div class="col s12 m6 l6 btn_grid">'; modes_html += '<div class="col s12 m6 l6 btn_grid">';
if (mode == "1" && current_mode.mode == ws2812fx_mode) {
modes_html += '<a class="btn waves-effect waves-light btn_mode red" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
} else {
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name; modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
}
modes_html += '<i class="material-icons right">send</i>'; modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>'; modes_html += '</a>';
modes_html += '</div>'; modes_html += '</div>';
@@ -241,6 +214,7 @@ $(function(){
$('#modes').html(modes_html); $('#modes').html(modes_html);
}); });
// When the connection is open, send some data to the server // When the connection is open, send some data to the server
connection.onopen = function () { connection.onopen = function () {
//connection.send('Ping'); // Send the message 'Ping' to the server //connection.send('Ping'); // Send the message 'Ping' to the server
@@ -319,11 +293,8 @@ $(function(){
var green = $("#rng_green").val(); var green = $("#rng_green").val();
var blue = $("#rng_blue").val(); var blue = $("#rng_blue").val();
var hexColor = componentToHex(red) + componentToHex(green) + componentToHex(blue); var mainColorHex = componentToHex(red) + componentToHex(green) + componentToHex(blue);
var statusColor = "#" + componentToHex(red) + componentToHex(green) + componentToHex(blue); wsSetMainColor(mainColorHex);
wsSetMainColor(hexColor);
$('#status').css("backgroundColor", statusColor);
$('#status_color').text(statusColor + "- R=" + red + ", G=" + green + ", B=" + blue);
} }
@@ -441,10 +412,9 @@ $(function(){
//display the touch/click position and color info //display the touch/click position and color info
function updateStatus(pos, color) { function updateStatus(pos, color) {
//var hexColor = rgbToHex(color); var hexColor = rgbToHex(color);
//wsSetAll(hexColor); wsSetAll(hexColor);
var hexColor = componentToHex(color[0]) + componentToHex(color[1]) + componentToHex(color[2]);
wsSetMainColor(hexColor);
hexColor = "#" + hexColor; hexColor = "#" + hexColor;
$('#status').css("backgroundColor", hexColor); $('#status').css("backgroundColor", hexColor);
+13 -3
View File
@@ -10,14 +10,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="mobile-web-app-capable" content="yes">
<title>McLighting v2</title> <title>McLighting v2</title>
</head> </head>
<body> <body>
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav"> <nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
<div class="nav-wrapper container"> <div class="nav-wrapper container">
<a id="logo-container" href="#" class="brand-logo">McLighting v2</a> <a id="logo-container" href="#" class="brand-logo">Mc Lighting v2</a>
<ul class="right hide-on-med-and-down"> <ul class="right hide-on-med-and-down">
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li> <li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
@@ -120,6 +119,18 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col s12 m6 l6 btn_grid">
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l6 btn_grid">
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV
<i class="material-icons right">send</i>
</a>
</div>
<div id="modes"> <div id="modes">
<div class="input-field col s12"> <div class="input-field col s12">
Loading animations... Loading animations...
@@ -148,5 +159,4 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
<script type="text/javascript">@@include('js/script.js')</script> <script type="text/javascript">@@include('js/script.js')</script>
</body> </body>
\ No newline at end of file
</html> </html>
+12 -53
View File
@@ -25,9 +25,9 @@ $(function(){
$('#' + pane).removeClass('hide'); $('#' + pane).removeClass('hide');
$('.button-collapse').sideNav('hide'); $('.button-collapse').sideNav('hide');
//if (pane == "pane2") { if (pane == "pane2") {
// setMainColor(); setMainColor();
//} }
} }
@@ -37,54 +37,16 @@ $(function(){
function init() { function init() {
console.log("Connection websockets to:", ws_url); console.log("Connection websockets to:", ws_url);
connection = new WebSocket(ws_url, ['arduino']); connection = new WebSocket(ws_url, ['arduino']);
var mode = 0;
var ws2812fx_mode = 0;
$.getJSON("http://" + host + "/status", function(data) {
console.log("status", data);
mode = data.mode;
ws2812fx_mode = data.ws2812fx_mode;
$("#rng_delay").val(data.speed);
$("#rng_brightness").val(data.brightness);
$("#rng_red").val(data.color[0]);
$("#rng_green").val(data.color[1]);
$("#rng_blue").val(data.color[2]);
var statusColor = "#" + componentToHex(data.color[0]) + componentToHex(data.color[1]) + componentToHex(data.color[2]);
$('#status').css("backgroundColor", statusColor);
$('#status_color').text(statusColor + "- R=" + data.color[0] + ", G=" + data.color[1] + ", B=" + data.color[2]);
});
// Load modes async // Load modes async
// List of all color modes
// enum MODE { SET_MODE, HOLD, AUTO, OFF, TV, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW};
$.getJSON("http://" + host + "/get_modes", function(data) { $.getJSON("http://" + host + "/get_modes", function(data) {
console.log("modes", data); //console.log("modes", data);
var modes_html = ""; var modes_html = "";
modes_html += '<div class="col s12 m6 l6 btn_grid">';
if (mode == "3") {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static red" name="action" data-mode="off">OFF';
} else {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF';
}
modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>';
modes_html += '</div>'
modes_html += '<div class="col s12 m6 l6 btn_grid">';
if (mode == "4") {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static red" name="action" data-mode="tv">TV';
} else {
modes_html += '<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV';
}
modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>';
modes_html += '</div>';
data.forEach(function(current_mode){ data.forEach(function(current_mode){
if (current_mode.mode !== undefined) { if (current_mode.mode !== undefined) {
modes_html += '<div class="col s12 m6 l6 btn_grid">'; modes_html += '<div class="col s12 m6 l6 btn_grid">';
if (mode == "1" && current_mode.mode == ws2812fx_mode) {
modes_html += '<a class="btn waves-effect waves-light btn_mode red" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
} else {
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name; modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">(' + current_mode.mode +') '+ current_mode.name;
}
modes_html += '<i class="material-icons right">send</i>'; modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>'; modes_html += '</a>';
modes_html += '</div>'; modes_html += '</div>';
@@ -93,6 +55,7 @@ $(function(){
$('#modes').html(modes_html); $('#modes').html(modes_html);
}); });
// When the connection is open, send some data to the server // When the connection is open, send some data to the server
connection.onopen = function () { connection.onopen = function () {
//connection.send('Ping'); // Send the message 'Ping' to the server //connection.send('Ping'); // Send the message 'Ping' to the server
@@ -171,11 +134,8 @@ $(function(){
var green = $("#rng_green").val(); var green = $("#rng_green").val();
var blue = $("#rng_blue").val(); var blue = $("#rng_blue").val();
var hexColor = componentToHex(red) + componentToHex(green) + componentToHex(blue); var mainColorHex = componentToHex(red) + componentToHex(green) + componentToHex(blue);
var statusColor = "#" + componentToHex(red) + componentToHex(green) + componentToHex(blue); wsSetMainColor(mainColorHex);
wsSetMainColor(hexColor);
$('#status').css("backgroundColor", statusColor);
$('#status_color').text(statusColor + "- R=" + red + ", G=" + green + ", B=" + blue);
} }
@@ -293,10 +253,9 @@ $(function(){
//display the touch/click position and color info //display the touch/click position and color info
function updateStatus(pos, color) { function updateStatus(pos, color) {
//var hexColor = rgbToHex(color); var hexColor = rgbToHex(color);
//wsSetAll(hexColor); wsSetAll(hexColor);
var hexColor = componentToHex(color[0]) + componentToHex(color[1]) + componentToHex(color[2]);
wsSetMainColor(hexColor);
hexColor = "#" + hexColor; hexColor = "#" + hexColor;
$('#status').css("backgroundColor", hexColor); $('#status').css("backgroundColor", hexColor);
+61
View File
@@ -0,0 +1,61 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
src_dir = ./Arduino/McLighting/
data_dir = ./Arduino/McLighting/data/
env_default = nodemcuv2
description = The ESP8266 based multi-client lighting gadget
[common]
framework = arduino
platform = espressif8266@1.8.0
; platform = https://github.com/platformio/platform-espressif8266.git
; platform = https://github.com/platformio/platform-espressif8266.git#feature/stage
; platform = https://github.com/platformio/platform-espressif8266.git#develop
build_flags =
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
-DMQTT_MAX_PACKET_SIZE=2048 ; PubSubClient Specific flags
-w ; supress all warnings
monitor_speed = 115200
board_build.flash_mode = dout
upload_speed = 115200
upload_resetmethod = nodemcu
lib_deps =
WiFiManager@0.14
AsyncMqttClient
https://github.com/bblanchon/ArduinoJson.git#v6.7.0-beta
WS2812FX
NeoPixelBus@2.4.1
WebSockets
ESPAsyncE131
ESPAsyncUDP
Brzo_I2C
[env:esp01_1m]
board = esp01_1m
framework = ${common.framework}
platform = ${common.platform}
build_flags = ${common.build_flags} -D D1=2
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
upload_resetmethod = ${common.upload_resetmethod}
board_build.flash_mode = dout
lib_deps = ${common.lib_deps}
[env:nodemcuv2]
board = nodemcuv2
framework = ${common.framework}
platform = ${common.platform}
build_flags = ${common.build_flags}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
upload_resetmethod = ${common.upload_resetmethod}
lib_deps = ${common.lib_deps}