Merge branch 'main' into usermod-battery-update2023

This commit is contained in:
Maximilian Mewes 2023-01-20 23:25:13 +01:00
commit 42c8a77755
77 changed files with 5435 additions and 5107 deletions

View File

@ -390,7 +390,8 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME
lib_deps = ${esp32s2.lib_deps}
[env:esp32c3]
platform = espressif32@5.1.1
platform = espressif32@5.1.1 ;; well-tested on -C3, good compatibility with WLED
; platform = espressif32@~5.2.0 ;; might help in case you experience bootloops due to corrupted flash filesystem
framework = arduino
board = esp32-c3-devkitm-1
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv

View File

@ -92,12 +92,14 @@ class Animated_Staircase : public Usermod {
static const char _bottomEchoCm[];
void publishMqtt(bool bottom, const char* state) {
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED){
char subuf[64];
sprintf_P(subuf, PSTR("%s/motion/%d"), mqttDeviceTopic, (int)bottom);
mqtt->publish(subuf, 0, false, state);
}
#endif
}
void updateSegments() {
@ -345,6 +347,7 @@ class Animated_Staircase : public Usermod {
uint16_t getId() { return USERMOD_ID_ANIMATED_STAIRCASE; }
#ifndef WLED_DISABLE_MQTT
/**
* handling of MQTT message
* topic only contains stripped topic (part after /wled/MAC)
@ -382,6 +385,7 @@ class Animated_Staircase : public Usermod {
mqtt->subscribe(subuf, 0);
}
}
#endif
void addToJsonState(JsonObject& root) {
JsonObject staircase = root[FPSTR(_name)];

View File

@ -1,6 +1,10 @@
// force the compiler to show a warning to confirm that this file is included
#warning **** Included USERMOD_BH1750 ****
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"
@ -156,6 +160,7 @@ public:
{
lastLux = lux;
lastSend = millis();
#ifndef WLED_DISABLE_MQTT
if (WLED_MQTT_CONNECTED)
{
if (!mqttInitialized)
@ -170,6 +175,7 @@ public:
{
DEBUG_PRINTLN(F("Missing MQTT connection. Not publishing data"));
}
#endif
}
}

View File

@ -1,6 +1,10 @@
// force the compiler to show a warning to confirm that this file is included
#warning **** Included USERMOD_BME280 version 2.0 ****
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"

View File

@ -194,6 +194,7 @@ class UsermodBattery : public Usermod
if (autoOffEnabled && (autoOffThreshold >= bat->getLevel()))
turnOff();
#ifndef WLED_DISABLE_MQTT
// SmartHome stuff
// still don't know much about MQTT and/or HA
if (WLED_MQTT_CONNECTED) {
@ -201,6 +202,7 @@ class UsermodBattery : public Usermod
snprintf_P(buf, 63, PSTR("%s/voltage"), mqttDeviceTopic);
mqtt->publish(buf, 0, false, String(voltage).c_str());
}
#endif
}

View File

@ -1,6 +1,10 @@
#pragma once
#include "wled.h"
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#include <dht_nonblocking.h>

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#include "wled.h"
#include <Arduino.h>
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#include "wled.h"
#include <Arduino.h>
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/

View File

@ -136,7 +136,7 @@ private:
}
} else {
if (m_offPreset) {
if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(m_offPreset, NotifyUpdateMode);
applyPreset(m_offPreset, NotifyUpdateMode);
return;
} else if (prevPlaylist) {
if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPlaylist, NotifyUpdateMode);
@ -159,6 +159,7 @@ private:
void publishMqtt(const char* state)
{
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED) {
char subuf[64];
@ -166,11 +167,13 @@ private:
strcat_P(subuf, PSTR("/motion"));
mqtt->publish(subuf, 0, false, state);
}
#endif
}
// Create an MQTT Binary Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
void publishHomeAssistantAutodiscovery()
{
#ifndef WLED_DISABLE_MQTT
if (WLED_MQTT_CONNECTED) {
StaticJsonDocument<600> doc;
char uid[24], json_str[1024], buf[128];
@ -200,6 +203,7 @@ private:
mqtt->publish(buf, 0, true, json_str, payload_size); // do we really need to retain?
}
#endif
}
/**

View File

@ -109,6 +109,7 @@ public:
{
lastLDRValue = currentLDRValue;
#ifndef WLED_DISABLE_MQTT
if (WLED_MQTT_CONNECTED)
{
char subuf[45];
@ -121,6 +122,7 @@ public:
DEBUG_PRINTLN("Missing MQTT connection. Not publishing data");
}
}
#endif
}
uint16_t getLastLDRValue()

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
// this is remixed from usermod_v2_SensorsToMqtt.h (sensors_to_mqtt usermod)

View File

@ -29,6 +29,7 @@ class UsermodTemperature : public Usermod {
bool degC = true;
// using parasite power on the sensor
bool parasite = false;
int8_t parasitePin = -1;
// how often do we read from sensor?
unsigned long readingInterval = USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL;
// set last reading as "40 sec before boot", so first reading is taken after 20 sec
@ -53,6 +54,7 @@ class UsermodTemperature : public Usermod {
static const char _enabled[];
static const char _readInterval[];
static const char _parasite[];
static const char _parasitePin[];
//Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013
float readDallas() {
@ -94,12 +96,14 @@ class UsermodTemperature : public Usermod {
DEBUG_PRINTLN(F("Requesting temperature."));
oneWire->reset();
oneWire->skip(); // skip ROM
oneWire->write(0x44,parasite); // request new temperature reading (TODO: parasite would need special handling)
oneWire->write(0x44,parasite); // request new temperature reading
if (parasite && parasitePin >=0 ) digitalWrite(parasitePin, HIGH); // has to happen within 10us (open MOSFET)
lastTemperaturesRequest = millis();
waitingForConversion = true;
}
void readTemperature() {
if (parasite && parasitePin >=0 ) digitalWrite(parasitePin, LOW); // deactivate power (close MOSFET)
temperature = readDallas();
lastMeasurement = millis();
waitingForConversion = false;
@ -134,6 +138,7 @@ class UsermodTemperature : public Usermod {
return false;
}
#ifndef WLED_DISABLE_MQTT
void publishHomeAssistantAutodiscovery() {
if (!WLED_MQTT_CONNECTED) return;
@ -155,6 +160,7 @@ class UsermodTemperature : public Usermod {
mqtt->publish(buf, 0, true, json_str, payload_size);
HApublished = true;
}
#endif
public:
@ -173,6 +179,12 @@ class UsermodTemperature : public Usermod {
delay(25); // try to find sensor
}
}
if (parasite && pinManager.allocatePin(parasitePin, true, PinOwner::UM_Temperature)) {
pinMode(parasitePin, OUTPUT);
digitalWrite(parasitePin, LOW); // deactivate power (close MOSFET)
} else {
parasitePin = -1;
}
} else {
if (temperaturePin >= 0) {
DEBUG_PRINTLN(F("Temperature pin allocation failed."));
@ -212,6 +224,7 @@ class UsermodTemperature : public Usermod {
}
errorCount = 0;
#ifndef WLED_DISABLE_MQTT
if (WLED_MQTT_CONNECTED) {
char subuf[64];
strcpy(subuf, mqttDeviceTopic);
@ -227,6 +240,7 @@ class UsermodTemperature : public Usermod {
// publish something else to indicate status?
}
}
#endif
}
}
@ -236,6 +250,7 @@ class UsermodTemperature : public Usermod {
*/
//void connected() {}
#ifndef WLED_DISABLE_MQTT
/**
* subscribe to MQTT topic if needed
*/
@ -246,6 +261,7 @@ class UsermodTemperature : public Usermod {
publishHomeAssistantAutodiscovery();
}
}
#endif
/*
* API calls te enable data exchange between WLED modules
@ -315,6 +331,7 @@ class UsermodTemperature : public Usermod {
top["degC"] = degC; // usermodparam
top[FPSTR(_readInterval)] = readingInterval / 1000;
top[FPSTR(_parasite)] = parasite;
top[FPSTR(_parasitePin)] = parasitePin;
DEBUG_PRINTLN(F("Temperature config saved."));
}
@ -340,6 +357,7 @@ class UsermodTemperature : public Usermod {
readingInterval = top[FPSTR(_readInterval)] | readingInterval/1000;
readingInterval = min(120,max(10,(int)readingInterval)) * 1000; // convert to ms
parasite = top[FPSTR(_parasite)] | parasite;
parasitePin = top[FPSTR(_parasitePin)] | parasitePin;
if (!initDone) {
// first run: reading from cfg.json
@ -354,12 +372,21 @@ class UsermodTemperature : public Usermod {
delete oneWire;
pinManager.deallocatePin(temperaturePin, PinOwner::UM_Temperature);
temperaturePin = newTemperaturePin;
pinManager.deallocatePin(parasitePin, PinOwner::UM_Temperature);
// initialise
setup();
}
}
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return !top[FPSTR(_parasite)].isNull();
return !top[FPSTR(_parasitePin)].isNull();
}
void appendConfigData()
{
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasite)).c_str());
oappend(SET_F("',1,'<i>(if no Vcc connected)</i>');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
oappend(SET_F("',1,'<i>(for external MOSFET)</i>');")); // 0 is field type, 1 is actual field
}
uint16_t getId()
@ -373,3 +400,4 @@ const char UsermodTemperature::_name[] PROGMEM = "Temperature";
const char UsermodTemperature::_enabled[] PROGMEM = "enabled";
const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s";
const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr";
const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin";

View File

@ -101,6 +101,7 @@ void userLoop() {
if (temptimer - lastMeasure > 60000)
{
lastMeasure = temptimer;
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr)
{
@ -116,6 +117,7 @@ void userLoop() {
t += "/temperature";
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
}
#endif
}
// Check if we time interval for redrawing passes.

View File

@ -103,6 +103,7 @@ void userLoop() {
{
lastMeasure = tempTimer;
#ifndef WLED_DISABLE_MQTT
// Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr)
{
@ -122,6 +123,7 @@ void userLoop() {
h += "/humidity";
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
}
#endif
}
// Check if we time interval for redrawing passes.

View File

@ -219,6 +219,7 @@ class BobLightUsermod : public Usermod {
void enable(bool en) { enabled = en; }
#ifndef WLED_DISABLE_MQTT
/**
* handling of MQTT message
* topic only contains stripped topic (part after /wled/MAC)
@ -249,6 +250,7 @@ class BobLightUsermod : public Usermod {
// mqtt->subscribe(subuf, 0);
//}
}
#endif
void addToJsonInfo(JsonObject& root)
{

View File

@ -66,12 +66,14 @@ class MultiRelay : public Usermod {
static const char _HAautodiscovery[];
void publishMqtt(int relay) {
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED){
char subuf[64];
sprintf_P(subuf, PSTR("%s/relay/%d"), mqttDeviceTopic, relay);
mqtt->publish(subuf, 0, false, _relay[relay].state ? "on" : "off");
}
#endif
}
/**
@ -182,7 +184,7 @@ class MultiRelay : public Usermod {
*/
MultiRelay() {
const int8_t defPins[] = {MULTI_RELAY_PINS};
for (int i=0; i<MULTI_RELAY_MAX_RELAYS; i++) {
for (size_t i=0; i<MULTI_RELAY_MAX_RELAYS; i++) {
_relay[i].pin = i<sizeof(defPins) ? defPins[i] : -1;
_relay[i].delay = 0;
_relay[i].mode = false;
@ -232,6 +234,7 @@ class MultiRelay : public Usermod {
//Functions called by WLED
#ifndef WLED_DISABLE_MQTT
/**
* handling of MQTT message
* topic only contains stripped topic (part after /wled/MAC)
@ -313,6 +316,7 @@ class MultiRelay : public Usermod {
mqtt->publish(buf, 0, true, json_str, payload_size);
}
}
#endif
/**
* setup() is called once at boot. WiFi is not yet connected at this point.

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "SHT85.h"

View File

@ -1,3 +1,7 @@
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"

File diff suppressed because it is too large Load Diff

View File

@ -250,6 +250,7 @@
#define FX_MODE_2DBLOBS 121 //gap fill
#define FX_MODE_2DSCROLLTEXT 122 //gap fill
#define FX_MODE_2DDRIFTROSE 123 //gap fill
#define FX_MODE_2DDISTORTIONWAVES 124
// WLED-SR effects (SR compatible IDs !!!)
#define FX_MODE_PIXELS 128
@ -519,9 +520,9 @@ typedef struct Segment {
bool allocateData(size_t len);
void deallocateData(void);
void resetIfRequired(void);
/**
/**
* Flags that before the next effect is calculated,
* the internal segment state should be reset.
* the internal segment state should be reset.
* Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests.
*/
@ -588,11 +589,13 @@ typedef struct Segment {
void moveX(int8_t delta);
void moveY(int8_t delta);
void move(uint8_t dir, uint8_t delta);
void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color);
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0);
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
void blur1d(fract8 blur_amount); // blur all rows in 1 dimension
void blur2d(fract8 blur_amount) { blur(blur_amount); }
@ -641,7 +644,7 @@ class WS2812FX { // 96 bytes
} mode_data_t;
static WS2812FX* instance;
public:
WS2812FX() :
@ -885,9 +888,9 @@ class WS2812FX { // 96 bytes
uint16_t* customMappingTable;
uint16_t customMappingSize;
uint32_t _lastShow;
uint8_t _segment_index;
uint8_t _mainSegment;

View File

@ -1,6 +1,6 @@
/*
FX_2Dfcn.cpp contains all 2D utility functions
LICENSE
The MIT License (MIT)
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
@ -164,6 +164,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
if (leds) leds[XY(x,y)] = col;
uint8_t _bri_t = currentBri(on ? opacity : 0);
if (!_bri_t && !transitional) return;
if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t);
@ -271,7 +272,7 @@ void Segment::addPixelColorXY(int x, int y, uint32_t color) {
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade);
setPixelColor(x, y, pix);
setPixelColorXY(x, y, pix);
}
// blurRow: perform a blur on a row of a rectangular matrix
@ -428,6 +429,29 @@ void Segment::move(uint8_t dir, uint8_t delta) {
}
}
void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
// Bresenhams Algorithm
int d = 3 - (2*radius);
int y = radius, x = 0;
while (y >= x) {
setPixelColorXY(cx+x, cy+y, col);
setPixelColorXY(cx-x, cy+y, col);
setPixelColorXY(cx+x, cy-y, col);
setPixelColorXY(cx-x, cy-y, col);
setPixelColorXY(cx+y, cy+x, col);
setPixelColorXY(cx-y, cy+x, col);
setPixelColorXY(cx+y, cy-x, col);
setPixelColorXY(cx-y, cy-x, col);
x++;
if (d > 0) {
y--;
d += 4 * (x - y) + 10;
} else {
d += 4 * x + 6;
}
}
}
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
const uint16_t cols = virtualWidth();
@ -437,7 +461,7 @@ void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
if (x * x + y * y <= radius * radius &&
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
addPixelColorXY(cx + x, cy + y, col);
setPixelColorXY(cx + x, cy + y, col);
}
}
}
@ -456,10 +480,10 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
const uint16_t rows = virtualHeight();
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int16_t err = (dx>dy ? dx : -dy)/2, e2;
for (;;) {
addPixelColorXY(x0,y0,c);
setPixelColorXY(x0,y0,c);
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
@ -475,13 +499,16 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
// draws a raster font character on canvas
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color) {
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) {
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
chr -= 32; // align with font table entries
const uint16_t cols = virtualWidth();
const uint16_t rows = virtualHeight();
const int font = w*h;
CRGB col = CRGB(color);
CRGBPalette16 grad = CRGBPalette16(col, col2 ? CRGB(col2) : col);
//if (w<5 || w>6 || h!=8) return;
for (int i = 0; i<h; i++) { // character height
int16_t y0 = y + i;
@ -496,10 +523,11 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); break; // 5x12 font
default: return;
}
col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND);
for (int j = 0; j<w; j++) { // character width
int16_t x0 = x + (w-1) - j;
if ((x0 >= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen
addPixelColorXY(x0, y0, color);
addPixelColorXY(x0, y0, col);
}
}
}

View File

@ -174,18 +174,18 @@ void Segment::deallocateData() {
_dataLen = 0;
}
/**
/**
* If reset of this segment was requested, clears runtime
* settings of this segment.
* Must not be called while an effect mode function is running
* because it could access the data buffer and this method
* because it could access the data buffer and this method
* may free that data buffer.
*/
void Segment::resetIfRequired() {
if (reset) {
if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; }
//if (_t) { delete _t; _t = nullptr; transitional = false; }
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
reset = false; // setOption(SEG_OPTION_RESET, false);
}
}
@ -243,12 +243,12 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
_lastPaletteChange = millis();
timeSinceLastChange = 0;
}
if (timeSinceLastChange <= 500) {
if (timeSinceLastChange <= 250) {
targetPalette = prevRandomPalette;
// there needs to be 255 palette blends (48) for full blend but that is too resource intensive
// so 128 is a compromise (we need to perform full blend of the two palettes as each segment can have random
// palette selected but only 2 static palettes are used)
size_t noOfBlends = ((128U * timeSinceLastChange) / 500U);
size_t noOfBlends = ((128U * timeSinceLastChange) / 250U);
for (size_t i=0; i<noOfBlends; i++) nblendPaletteTowardPalette(targetPalette, randomPalette, 48);
} else {
targetPalette = randomPalette;
@ -459,18 +459,21 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
// load default values from effect string
if (loadDefaults) {
int16_t sOpt;
sOpt = extractModeDefaults(fx, "sx"); if (sOpt >= 0) speed = sOpt;
sOpt = extractModeDefaults(fx, "ix"); if (sOpt >= 0) intensity = sOpt;
sOpt = extractModeDefaults(fx, "c1"); if (sOpt >= 0) custom1 = sOpt;
sOpt = extractModeDefaults(fx, "c2"); if (sOpt >= 0) custom2 = sOpt;
sOpt = extractModeDefaults(fx, "c3"); if (sOpt >= 0) custom3 = sOpt;
sOpt = extractModeDefaults(fx, "sx"); speed = (sOpt >= 0) ? sOpt : DEFAULT_SPEED;
sOpt = extractModeDefaults(fx, "ix"); intensity = (sOpt >= 0) ? sOpt : DEFAULT_INTENSITY;
sOpt = extractModeDefaults(fx, "c1"); custom1 = (sOpt >= 0) ? sOpt : DEFAULT_C1;
sOpt = extractModeDefaults(fx, "c2"); custom2 = (sOpt >= 0) ? sOpt : DEFAULT_C2;
sOpt = extractModeDefaults(fx, "c3"); custom3 = (sOpt >= 0) ? sOpt : DEFAULT_C3;
sOpt = extractModeDefaults(fx, "o1"); check1 = (sOpt >= 0) ? (bool)sOpt : false;
sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false;
sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false;
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) map1D2D = constrain(sOpt, 0, 7);
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) soundSim = constrain(sOpt, 0, 7);
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt;
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt;
sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business
sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt);
sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt); //else setPalette(0);
}
stateChanged = true; // send UDP/WS broadcast
}
@ -574,6 +577,20 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
int y = roundf(cos_t(rad) * i);
setPixelColorXY(x, y, col);
}
// Bresenhams Algorithm (may not fill every pixel)
//int d = 3 - (2*i);
//int y = i, x = 0;
//while (y >= x) {
// setPixelColorXY(x, y, col);
// setPixelColorXY(y, x, col);
// x++;
// if (d > 0) {
// y--;
// d += 4 * (x - y) + 10;
// } else {
// d += 4 * x + 6;
// }
//}
}
break;
case M12_pCorner:
@ -596,6 +613,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t len = length();
uint8_t _bri_t = currentBri(on ? opacity : 0);
if (!_bri_t && !transitional) return;
if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t);
@ -620,7 +638,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t indexSet = i + ((reverse) ? -j : j);
if (indexSet >= start && indexSet < stop) {
if (mirror) { //set the corresponding mirrored pixel
uint16_t indexMir = stop - indexSet + start - 1;
uint16_t indexMir = stop - indexSet + start - 1;
indexMir += offset; // offset/phase
if (indexMir >= stop) indexMir -= len; // wrap
strip.setPixelColor(indexMir, col);
@ -745,7 +763,7 @@ void Segment::refreshLightCapabilities() {
switch (type) {
case TYPE_ANALOG_5CH:
case TYPE_ANALOG_2CH:
capabilities |= 0x04; //segment supports white CCT
capabilities |= 0x04; //segment supports white CCT
}
}
if (correctWB && !(type == TYPE_ANALOG_1CH || type == TYPE_ONOFF)) capabilities |= 0x04; //white balance correction (uses CCT slider)
@ -908,7 +926,7 @@ uint8_t Segment::get_random_wheel_index(uint8_t pos) {
* Gets a single color from the currently selected palette.
* @param i Palette Index (if mapping is true, the full palette will be _virtualSegmentLength long, if false, 255). Will wrap around automatically.
* @param mapping if true, LED position in segment is considered for color
* @param wrap FastLED palettes will usally wrap back to the start smoothly. Set false to get a hard edge
* @param wrap FastLED palettes will usually wrap back to the start smoothly. Set false to get a hard edge
* @param mcol If the default palette 0 is selected, return the standard color 0, 1 or 2 instead. If >2, Party palette is used instead
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
* @returns Single color from palette
@ -1056,7 +1074,7 @@ void WS2812FX::service() {
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
delay = (*_mode[seg.currentMode(seg.mode)])();
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // foce faster updates during transition
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
seg.handleTransition();
}
@ -1097,7 +1115,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
//Stay safe with high amperage and have a reasonable safety margin!
//I am NOT to be held liable for burned down garages!
//fine tune power estimation constants for your setup
//fine tune power estimation constants for your setup
#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
@ -1156,7 +1174,7 @@ void WS2812FX::estimateCurrentAndLimitBri() {
uint32_t powerSum0 = powerSum;
powerSum *= _brightness;
if (powerSum > powerBudget) //scale brightness down to stay in current limit
{
float scale = (float)powerBudget / (float)powerSum;
@ -1180,7 +1198,7 @@ void WS2812FX::show(void) {
if (callback) callback();
estimateCurrentAndLimitBri();
// some buses send asynchronously and this method will return before
// all of the data has been sent.
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
@ -1217,7 +1235,7 @@ void WS2812FX::setTargetFps(uint8_t fps) {
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
if (segid >= _segments.size()) return;
if (m >= getModeCount()) m = getModeCount() - 1;
if (_segments[segid].mode != m) {

View File

@ -2,7 +2,7 @@
/*
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
*
*
* This was put together from these two excellent projects:
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
* https://github.com/probonopd/ESP8266HueEmulator
@ -21,11 +21,11 @@ void alexaInit()
espalexaDevice = new EspalexaDevice(alexaInvocationName, onAlexaChange, EspalexaDeviceType::extendedcolor);
espalexa.addDevice(espalexaDevice);
// up to 9 devices (added second, third, ... i.e. index 1 to 9) serve for switching on up to nine presets (preset IDs 1 to 9 in WLED),
// up to 9 devices (added second, third, ... i.e. index 1 to 9) serve for switching on up to nine presets (preset IDs 1 to 9 in WLED),
// names are identical as the preset names, switching off can be done by switching off any of them
if (alexaNumPresets) {
String name = "";
for (byte presetIndex = 1; presetIndex <= alexaNumPresets; presetIndex++)
for (byte presetIndex = 1; presetIndex <= alexaNumPresets; presetIndex++)
{
if (!getPresetName(presetIndex, name)) break; // no more presets
EspalexaDevice* dev = new EspalexaDevice(name.c_str(), onAlexaChange, EspalexaDeviceType::extendedcolor);
@ -44,7 +44,7 @@ void handleAlexa()
void onAlexaChange(EspalexaDevice* dev)
{
EspalexaDeviceProperty m = dev->getLastChangedProperty();
if (m == EspalexaDeviceProperty::on)
{
if (dev->getId() == 0) // Device 0 is for on/off or macros
@ -56,7 +56,7 @@ void onAlexaChange(EspalexaDevice* dev)
bri = briLast;
stateUpdated(CALL_MODE_ALEXA);
}
} else
} else
{
applyPreset(macroAlexaOn, CALL_MODE_ALEXA);
if (bri == 0) dev->setValue(briLast); //stop Alexa from complaining if macroAlexaOn does not actually turn on
@ -82,7 +82,7 @@ void onAlexaChange(EspalexaDevice* dev)
bri = 0;
stateUpdated(CALL_MODE_ALEXA);
}
} else
} else
{
applyPreset(macroAlexaOff, CALL_MODE_ALEXA);
// below for loop stops Alexa from complaining if macroAlexaOff does not actually turn off

View File

@ -217,7 +217,7 @@ class Bus {
static uint8_t _gAWM; // definition in FX_fcn.cpp
static int16_t _cct; // definition in FX_fcn.cpp
static uint8_t _cctBlend; // definition in FX_fcn.cpp
uint32_t autoWhiteCalc(uint32_t c) {
uint8_t aWM = _autoWhiteMode;
if (_gAWM < 255) aWM = _gAWM;
@ -271,7 +271,7 @@ class BusDigital : public Bus {
//Fix for turning off onboard LED breaking bus
#ifdef LED_BUILTIN
if (_bri == 0 && b > 0) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
}
#endif
Bus::setBrightness(b);
@ -343,7 +343,7 @@ class BusDigital : public Bus {
cleanup();
}
private:
private:
uint8_t _colorOrder = COL_ORDER_GRB;
uint8_t _pins[2] = {255, 255};
uint8_t _iType = I_NONE;
@ -477,7 +477,7 @@ class BusPwm : public Bus {
cleanup();
}
private:
private:
uint8_t _pins[5] = {255, 255, 255, 255, 255};
uint8_t _data[5] = {0};
#ifdef ARDUINO_ARCH_ESP32
@ -553,7 +553,7 @@ class BusOnOff : public Bus {
cleanup();
}
private:
private:
uint8_t _pin = 255;
uint8_t _data = 0;
};
@ -717,7 +717,7 @@ class BusManager {
//do not call this method from system context (network callback)
void removeAll() {
DEBUG_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;

View File

@ -699,7 +699,7 @@ class PolyBus {
}
};
static uint32_t getPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint8_t co) {
RgbwColor col(0,0,0,0);
RgbwColor col(0,0,0,0);
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
@ -771,7 +771,7 @@ class PolyBus {
case I_HS_P98_3: col = (static_cast<B_HS_P98_3*>(busPtr))->GetPixelColor(pix); break;
case I_SS_P98_3: col = (static_cast<B_SS_P98_3*>(busPtr))->GetPixelColor(pix); break;
}
// upper nibble contains W swap information
uint8_t w = col.W;
switch (co >> 4) {
@ -866,7 +866,7 @@ class PolyBus {
}
}
//gives back the internal type index (I_XX_XXX_X above) for the input
//gives back the internal type index (I_XX_XXX_X above) for the input
static uint8_t getI(uint8_t busType, uint8_t* pins, uint8_t num = 0) {
if (!IS_DIGITAL(busType)) return I_NONE;
if (IS_2PIN(busType)) { //SPI LED chips

View File

@ -24,12 +24,14 @@ void shortPressAction(uint8_t b)
applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
}
#ifndef WLED_DISABLE_MQTT
// publish MQTT message
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
char subuf[64];
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
mqtt->publish(subuf, 0, false, "short");
}
#endif
}
void longPressAction(uint8_t b)
@ -43,12 +45,14 @@ void longPressAction(uint8_t b)
applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
}
#ifndef WLED_DISABLE_MQTT
// publish MQTT message
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
char subuf[64];
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
mqtt->publish(subuf, 0, false, "long");
}
#endif
}
void doublePressAction(uint8_t b)
@ -62,12 +66,14 @@ void doublePressAction(uint8_t b)
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON_PRESET);
}
#ifndef WLED_DISABLE_MQTT
// publish MQTT message
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
char subuf[64];
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
mqtt->publish(subuf, 0, false, "double");
}
#endif
}
bool isButtonPressed(uint8_t i)
@ -105,20 +111,21 @@ void handleSwitch(uint8_t b)
}
if (buttonLongPressed[b] == buttonPressedBefore[b]) return;
if (millis() - buttonPressedTime[b] > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
if (!buttonPressedBefore[b]) { // on -> off
if (macroButton[b]) applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
else { //turn on
if (!bri) {toggleOnOff(); stateUpdated(CALL_MODE_BUTTON);}
}
}
} else { // off -> on
if (macroLongPress[b]) applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
else { //turn off
if (bri) {toggleOnOff(); stateUpdated(CALL_MODE_BUTTON);}
}
}
}
#ifndef WLED_DISABLE_MQTT
// publish MQTT message
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
char subuf[64];
@ -126,13 +133,14 @@ void handleSwitch(uint8_t b)
else sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
mqtt->publish(subuf, 0, false, !buttonPressedBefore[b] ? "off" : "on");
}
#endif
buttonLongPressed[b] = buttonPressedBefore[b]; //save the last "long term" switch state
}
}
#define ANALOG_BTN_READ_CYCLE 250 // min time between two analog reading cycles
#define STRIP_WAIT_TIME 6 // max wait time in case of strip.isUpdating()
#define STRIP_WAIT_TIME 6 // max wait time in case of strip.isUpdating()
#define POT_SMOOTHING 0.25f // smoothing factor for raw potentiometer readings
#define POT_SENSITIVITY 4 // changes below this amount are noise (POT scratching, or ADC noise)
@ -165,7 +173,7 @@ void handleAnalog(uint8_t b)
//while(strip.isUpdating() && (millis() - wait_started < STRIP_WAIT_TIME)) {
// delay(1);
//}
//if (strip.isUpdating()) return; // give up
//if (strip.isUpdating()) return; // give up
oldRead[b] = aRead;
@ -326,7 +334,7 @@ void esp32RMTInvertIdle()
void handleIO()
{
handleButton();
//set relay when LEDs turn on
if (strip.getBrightness())
{

View File

@ -64,7 +64,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (apHide > 1) apHide = 1;
CJSON(apBehavior, ap[F("behav")]);
/*
JsonArray ap_ip = ap["ip"];
for (byte i = 0; i < 4; i++) {
@ -136,7 +136,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
#endif
JsonArray ins = hw_led["ins"];
if (fromFS || !ins.isNull()) {
uint8_t s = 0; // bus iterator
if (fromFS) busses.removeAll(); // can't safely manipulate busses directly in network callback
@ -210,14 +210,14 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
btnPin[s] = pin;
#ifdef ARDUINO_ARCH_ESP32
// ESP32 only: check that analog button pin is a valid ADC gpio
if (((buttonType[s] == BTN_TYPE_ANALOG) || (buttonType[s] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[s]) < 0))
if (((buttonType[s] == BTN_TYPE_ANALOG) || (buttonType[s] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[s]) < 0))
{
// not an ADC analog pin
DEBUG_PRINTF("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n", btnPin[s], s);
btnPin[s] = -1;
pinManager.deallocatePin(pin,PinOwner::Button);
}
else
}
else
#endif
{
if (disablePullUp) {
@ -253,7 +253,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
// relies upon only being called once with fromFS == true, which is currently true.
uint8_t s = 0;
if (pinManager.allocatePin(btnPin[0], false, PinOwner::Button)) { // initialized to #define value BTNPIN, or zero if not defined(!)
++s; // do not clear default button if allocated successfully
++s; // do not clear default button if allocated successfully
}
for (; s<WLED_MAX_BUTTONS; s++) {
btnPin[s] = -1;
@ -404,6 +404,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
CJSON(DMXAddress, if_live_dmx[F("addr")]);
if (!DMXAddress || DMXAddress > 510) DMXAddress = 1;
CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]);
if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0;
CJSON(DMXMode, if_live_dmx["mode"]);
tdd = if_live[F("timeout")] | -1;
@ -497,7 +499,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
uint8_t it = 0;
for (JsonObject timer : timers) {
if (it > 9) break;
if (it<8 && timer[F("hour")]==255) it=8; // hour==255 -> sunrise/sunset
if (it<8 && timer[F("hour")]==255) it=8; // hour==255 -> sunrise/sunset
CJSON(timerHours[it], timer[F("hour")]);
CJSON(timerMinutes[it], timer["min"]);
CJSON(timerMacro[it], timer["macro"]);
@ -864,6 +866,7 @@ void serializeConfig() {
if_live_dmx[F("uni")] = e131Universe;
if_live_dmx[F("seqskip")] = e131SkipOutOfSequence;
if_live_dmx[F("addr")] = DMXAddress;
if_live_dmx[F("dss")] = DMXSegmentSpacing;
if_live_dmx["mode"] = DMXMode;
if_live[F("timeout")] = realtimeTimeoutMs / 100;

View File

@ -91,7 +91,7 @@ void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc
r = round(329.698727446 * pow((temp - 60), -0.1332047592));
g = round(288.1221695283 * pow((temp - 60), -0.0755148492));
b = 255;
}
}
//g += 12; //mod by Aircoookie, a bit less accurate but visibly less pinkish
rgb[0] = (uint8_t) constrain(r, 0, 255);
rgb[1] = (uint8_t) constrain(g, 0, 255);
@ -194,7 +194,7 @@ void colorFromDecOrHexString(byte* rgb, char* in)
if (in[0] == 0) return;
char first = in[0];
uint32_t c = 0;
if (first == '#' || first == 'h' || first == 'H') //is HEX encoded
{
c = strtoul(in +1, NULL, 16);

View File

@ -169,10 +169,14 @@
#define DMX_MODE_DISABLED 0 //not used
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (15 channels)
#define DMX_MODE_EFFECT_W 7 //trigger standalone effects of WLED (18 channels)
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
#define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels)
#define DMX_MODE_EFFECT_SEGMENT 8 //trigger standalone effects of WLED (15 channels per segement)
#define DMX_MODE_EFFECT_SEGMENT_W 9 //trigger standalone effects of WLED (18 channels per segement)
#define DMX_MODE_PRESET 10 //apply presets (1 channel)
//Light capability byte (unused) 0bRCCCTTTT
//bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior
@ -309,7 +313,7 @@
#define NTP_PACKET_SIZE 48
//maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses
//maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses
#ifndef MAX_LEDS
#ifdef ESP8266
#define MAX_LEDS 1664 //can't rely on memory limit to limit this to 1600 LEDs
@ -338,7 +342,7 @@
#ifdef ESP8266
#define SETTINGS_STACK_BUF_SIZE 2048
#else
#define SETTINGS_STACK_BUF_SIZE 3096
#define SETTINGS_STACK_BUF_SIZE 3096
#endif
#ifdef WLED_USE_ETHERNET

View File

@ -436,6 +436,9 @@ button {
left: 50%;
margin-left: -92px;
/* Ensure tooltip goes away when mouse leaves control */
pointer-events: none;
/* Fade in tooltip */
opacity: 0;
transition: opacity 0.75s;
@ -865,8 +868,8 @@ select {
transition-duration: 0.5s;
-webkit-backface-visibility: hidden;
-webkit-transform:translate3d(0,0,0);
-webkit-appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
backface-visibility: hidden;
transform:translate3d(0,0,0);
text-overflow: ellipsis;
@ -890,8 +893,8 @@ div.sel-p:after {
position: absolute;
right: 10px;
top: 22px;
width: 0;
height: 0;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-top: 8px solid var(--c-f);
@ -1221,7 +1224,7 @@ TD .checkmark, TD .radiomark {
line-height: 24px;
vertical-align: middle;
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
filter: grayscale(100%);
filter: grayscale(100%);
}
.lbl-l {
@ -1331,7 +1334,7 @@ TD .checkmark, TD .radiomark {
white-space: nowrap;
text-overflow: ellipsis;
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
filter: grayscale(100%);
filter: grayscale(100%);
}
/* list item palette preview */
@ -1362,7 +1365,7 @@ TD .checkmark, TD .radiomark {
background: var(--c-2);
border: 1px solid var(--c-3);
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
filter: grayscale(100%);
filter: grayscale(100%);
}
.fnd input[type="text"]:focus {

View File

@ -807,7 +807,7 @@ function populateSegments(s)
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).style.display = "inline";
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
if (Array.isArray(li.maps) && li.maps.length>1) {
if (!isM && Array.isArray(li.maps) && li.maps.length>1) {
let cont = `Ledmap:&nbsp;<select class="sel-sg" onchange="requestJson({'ledmap':parseInt(this.value)})"><option value="" selected>Unchanged</option>`;
for (const k of (li.maps||[])) cont += `<option value="${k}">${k==0?'Default':'ledmap'+k+'.json'}</option>`;
cont += "</select></div>";
@ -837,7 +837,7 @@ function populateEffects()
});
for (let ef of effects) {
// WLEDSR: add slider and color control to setFX (used by requestjson)
// add slider and color control to setFX (used by requestjson)
let id = ef.id;
let nm = ef.name+" ";
let fd = "";
@ -1362,7 +1362,7 @@ function readState(s,command=false)
return true;
}
// WLEDSR: control HTML elements for Slider and Color Control
// control HTML elements for Slider and Color Control (original ported form WLED-SR)
// Technical notes
// ===============
// If an effect name is followed by an @, slider and color control is effective.
@ -1485,6 +1485,14 @@ function setEffectParameters(idx)
pall.innerHTML = '<i class="icons sel-icon" onclick="tglHex()">&#xe2b3;</i> Color palette not used';
palw.style.display = "none";
}
// not all color selectors shown, hide palettes created from color selectors
// NOTE: this will disallow user to select "* Color ..." palettes which may be undesirable in some cases or for some users
//for (let e of (gId('pallist').querySelectorAll('.lstI')||[])) {
// let fltr = "* C";
// if (cslCnt==1 && csel==0) fltr = "* Colors";
// else if (cslCnt==2) fltr = "* Colors Only";
// if (cslCnt < 3 && e.querySelector('.lstIname').innerText.indexOf(fltr)>=0) e.classList.add('hide'); else e.classList.remove('hide');
//}
}
var jsonTimeout;
@ -1840,7 +1848,7 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
<input type="checkbox" id="p${i}sbchk">
<span class="checkmark"></span>
</label>`;
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>1) {
if (!isM && Array.isArray(lastinfo.maps) && lastinfo.maps.length>1) {
content += `<div class="lbl-l">Ledmap:&nbsp;<div class="sel-p"><select class="sel-p" id="p${i}lmp"><option value="">Unchanged</option>`;
for (const k of (lastinfo.maps||[])) content += `<option value="${k}"${(i>0 && pJson[i].ledmap==k)?" selected":""}>${k==0?'Default':'ledmap'+k+'.json'}</option>`;
content += "</select></div></div>";

View File

@ -68,9 +68,9 @@
<button type=submit id="b" onclick="window.location='/'">Back</button>
<button type="submit" onclick="window.location='./settings/wifi'">WiFi Setup</button>
<button type="submit" onclick="window.location='./settings/leds'">LED Preferences</button>
<button type="submit" onclick="window.location='./settings/2D'">2D Configuration</button>
<button id="2dbtn" style="display:none;" type="submit" onclick="window.location='./settings/2D'">2D Configuration</button>
<button type="submit" onclick="window.location='./settings/ui'">User Interface</button>
<button id="dmxbtn" style="display: none;" type="submit" onclick="window.location='./settings/dmx'">DMX Output</button>
<button id="dmxbtn" style="display:none;" type="submit" onclick="window.location='./settings/dmx'">DMX Output</button>
<button type="submit" onclick="window.location='./settings/sync'">Sync Interfaces</button>
<button type="submit" onclick="window.location='./settings/time'">Time & Macros</button>
<button type="submit" onclick="window.location='./settings/um'">Usermods</button>

View File

@ -9,6 +9,10 @@
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
var customStarts=false,startsDirty=[],maxCOOverrides=5;
var loc = false, locip;
d.um_p = [];
d.rsvd = [];
d.ro_gpio = [];
d.max_gpio = 39;
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
function B(){window.open("/settings","_self");}
function gId(n){return d.getElementById(n);}
@ -23,10 +27,6 @@
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
d.um_p = [];
d.rsvd = [];
d.ro_pins = [];
d.max_gpio = 39;
GetV();checkSi();setABL();
if (d.um_p[0]==-1) d.um_p.shift();
});
@ -66,7 +66,7 @@
for (k=0;k<d.rsvd.length;k++) p.push(d.rsvd[k]); // fill with reservations
for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with usermod pins
if (p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
else if (!(nm == "IR" || nm=="BT") && d.ro_pins.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);LCs[i].value="";LCs[i].focus();return false;}
else if (!(nm == "IR" || nm=="BT") && d.ro_gpio.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);LCs[i].value="";LCs[i].focus();return false;}
for (j=i+1; j<LCs.length; j++)
{
var n2 = LCs[j].name.substring(0,2);

View File

@ -148,15 +148,20 @@ Start universe: <input name="EU" type="number" min="0" max="63999" required><br>
<i>Reboot required.</i> Check out <a href="https://github.com/LedFx/LedFx" target="_blank">LedFx</a>!<br>
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
DMX start address: <input name="DA" type="number" min="1" max="510" required><br>
DMX segment spacing: <input name="XX" type="number" min="0" max="150" required><br>
DMX mode:
<select name=DM>
<option value=0>Disabled</option>
<option value=1>Single RGB</option>
<option value=2>Single DRGB</option>
<option value=3>Effect</option>
<option value=7>Effect + White</option>
<option value=8>Effect Segment</option>
<option value=9>Effect Segment + White</option>
<option value=4>Multi RGB</option>
<option value=5>Dimmer + Multi RGB</option>
<option value=6>Multi RGBW</option>
<option value=10>Preset</option>
</select><br>
<a href="https://kno.wled.ge/interfaces/e1.31-dmx/" target="_blank">E1.31 info</a><br>
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>

View File

@ -7,6 +7,10 @@
<title>Usermod Settings</title>
<script>
var d = document;
d.max_gpio = 39;
d.um_p = [];
d.rsvd = [];
d.ro_gpio = [];
var umCfg = {};
var pins = [], pinO = [], owner;
var loc = false, locip;
@ -25,11 +29,6 @@
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
d.um_p = [];
d.rsvd = [];
d.ro_pins = [];
d.max_gpio = 39;
GetV();
for (let k=0; k<d.rsvd.length; k++) { pins.push(d.rsvd[k]); pinO.push("rsvd"); }
if (d.um_p[0]==-1) d.um_p.shift();
@ -38,6 +37,8 @@
d.Sf.MOSI.max = d.max_gpio;
d.Sf.SCLK.max = d.max_gpio;
d.Sf.MISO.max = d.max_gpio;
let inp = d.getElementsByTagName("input");
for (let i of inp) if (i.type === "number" && i.name.replace("[]","").substr(-3) === "pin") i.max = d.max_gpio;
});
// error event
scE.addEventListener("error", (ev) => {

View File

@ -73,7 +73,7 @@ void initDMX() {
dmx.init(512); // initialize with bus length
#else
dmx.initWrite(512); // initialize with bus length
#endif
#endif
}
#else

View File

@ -12,7 +12,7 @@
//handles RGB data only
void handleDDPPacket(e131_packet_t* p) {
int lastPushSeq = e131LastSequenceNumber[0];
//reject late packets belonging to previous frame (assuming 4 packets max. before push)
if (e131SkipOutOfSequence && lastPushSeq) {
int sn = p->sequenceNum & 0xF;
@ -35,7 +35,7 @@ void handleDDPPacket(e131_packet_t* p) {
if (p->flags & DDP_TIMECODE_FLAG) c = 4; //packet has timecode flag, we do not support it, but data starts 4 bytes later
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_DDP);
if (!realtimeOverride || (realtimeMode && useMainSegmentOnly)) {
for (uint16_t i = start; i < stop; i++) {
setRealtimePixel(i, data[c], data[c+1], data[c+2], ddpChannelsPerLed >3 ? data[c+3] : 0);
@ -132,7 +132,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
return; // nothing to do
break;
case DMX_MODE_SINGLE_RGB: // RGB only
case DMX_MODE_SINGLE_RGB: // 3 channel: [R,G,B]
if (uni != e131Universe) return;
if (availDMXLen < 3) return;
@ -145,7 +145,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
setRealtimePixel(i, e131_data[dataOffset+0], e131_data[dataOffset+1], e131_data[dataOffset+2], wChannel);
break;
case DMX_MODE_SINGLE_DRGB: // Dimmer + RGB
case DMX_MODE_SINGLE_DRGB: // 4 channel: [Dimmer,R,G,B]
if (uni != e131Universe) return;
if (availDMXLen < 4) return;
@ -162,38 +162,77 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
setRealtimePixel(i, e131_data[dataOffset+1], e131_data[dataOffset+2], e131_data[dataOffset+3], wChannel);
break;
case DMX_MODE_EFFECT: // Length 1: Apply Preset ID, length 11-13: apply effect config
if (uni != e131Universe) return;
if (availDMXLen < 11) {
if (availDMXLen > 1) return;
applyPreset(e131_data[dataOffset+0], CALL_MODE_NOTIFICATION);
return;
case DMX_MODE_PRESET: // 2 channel: [Dimmer,Preset]
if (uni != e131Universe || availDMXLen < 2) return;
applyPreset(e131_data[dataOffset+1], CALL_MODE_NOTIFICATION);
if (bri != e131_data[dataOffset]) {
bri = e131_data[dataOffset];
strip.setBrightness(bri, true);
}
if (bri != e131_data[dataOffset+0]) {
bri = e131_data[dataOffset+0];
}
if (e131_data[dataOffset+1] < strip.getModeCount())
effectCurrent = e131_data[dataOffset+ 1];
effectSpeed = e131_data[dataOffset+ 2]; // flickers
effectIntensity = e131_data[dataOffset+ 3];
effectPalette = e131_data[dataOffset+ 4];
col[0] = e131_data[dataOffset+ 5];
col[1] = e131_data[dataOffset+ 6];
col[2] = e131_data[dataOffset+ 7];
colSec[0] = e131_data[dataOffset+ 8];
colSec[1] = e131_data[dataOffset+ 9];
colSec[2] = e131_data[dataOffset+10];
if (availDMXLen > 11)
{
col[3] = e131_data[dataOffset+11]; //white
colSec[3] = e131_data[dataOffset+12];
}
transitionDelayTemp = 0; // act fast
colorUpdated(CALL_MODE_NOTIFICATION); // don't send UDP
return; // don't activate realtime live mode
return;
break;
case DMX_MODE_EFFECT: // 15 channels [bri,effectCurrent,effectSpeed,effectIntensity,effectPalette,effectOption,R,G,B,R2,G2,B2,R3,G3,B3]
case DMX_MODE_EFFECT_W: // 18 channels, same as above but with extra +3 white channels [..,W,W2,W3]
case DMX_MODE_EFFECT_SEGMENT: // 15 channels per segment;
case DMX_MODE_EFFECT_SEGMENT_W: // 18 Channels per segment;
{
if (uni != e131Universe) return;
bool isSegmentMode = DMXMode == DMX_MODE_EFFECT_SEGMENT || DMXMode == DMX_MODE_EFFECT_SEGMENT_W;
uint8_t dmxEffectChannels = (DMXMode == DMX_MODE_EFFECT || DMXMode == DMX_MODE_EFFECT_SEGMENT) ? 15 : 18;
for (uint8_t id = 0; id < strip.getSegmentsNum(); id++) {
Segment& seg = strip.getSegment(id);
if (isSegmentMode)
dataOffset = DMXAddress + id * (dmxEffectChannels + DMXSegmentSpacing);
else
dataOffset = DMXAddress;
// Modify address for Art-Net data
if (protocol == P_ARTNET && dataOffset > 0)
dataOffset--;
// Skip out of universe addresses
if (dataOffset > dmxChannels - dmxEffectChannels + 1)
return;
if (e131_data[dataOffset+1] < strip.getModeCount())
if (e131_data[dataOffset+1] != seg.mode) seg.setMode( e131_data[dataOffset+1]);
if (e131_data[dataOffset+2] != seg.speed) seg.speed = e131_data[dataOffset+2];
if (e131_data[dataOffset+3] != seg.intensity) seg.intensity = e131_data[dataOffset+3];
if (e131_data[dataOffset+4] != seg.palette) seg.setPalette(e131_data[dataOffset+4]);
uint8_t segOption = (uint8_t)floor(e131_data[dataOffset+5]/64.0);
if (segOption == 0 && (seg.mirror || seg.reverse )) {seg.setOption(SEG_OPTION_MIRROR, false); seg.setOption(SEG_OPTION_REVERSED, false);}
if (segOption == 1 && (seg.mirror || !seg.reverse)) {seg.setOption(SEG_OPTION_MIRROR, false); seg.setOption(SEG_OPTION_REVERSED, true);}
if (segOption == 2 && (!seg.mirror || seg.reverse )) {seg.setOption(SEG_OPTION_MIRROR, true); seg.setOption(SEG_OPTION_REVERSED, false);}
if (segOption == 3 && (!seg.mirror || !seg.reverse)) {seg.setOption(SEG_OPTION_MIRROR, true); seg.setOption(SEG_OPTION_REVERSED, true);}
uint32_t colors[3];
byte whites[3] = {0,0,0};
if (dmxEffectChannels == 18) {
whites[0] = e131_data[dataOffset+15];
whites[1] = e131_data[dataOffset+16];
whites[2] = e131_data[dataOffset+17];
}
colors[0] = RGBW32(e131_data[dataOffset+ 6], e131_data[dataOffset+ 7], e131_data[dataOffset+ 8], whites[0]);
colors[1] = RGBW32(e131_data[dataOffset+ 9], e131_data[dataOffset+10], e131_data[dataOffset+11], whites[1]);
colors[2] = RGBW32(e131_data[dataOffset+12], e131_data[dataOffset+13], e131_data[dataOffset+14], whites[2]);
if (colors[0] != seg.colors[0]) seg.setColor(0, colors[0]);
if (colors[1] != seg.colors[1]) seg.setColor(1, colors[1]);
if (colors[2] != seg.colors[2]) seg.setColor(2, colors[2]);
// Set segment opacity or global brightness
if (isSegmentMode) {
if (e131_data[dataOffset] != seg.opacity) seg.setOpacity(e131_data[dataOffset]);
} else if ( id == strip.getSegmentsNum()-1 ) {
if (bri != e131_data[dataOffset]) {
bri = e131_data[dataOffset];
strip.setBrightness(bri, true);
}
}
}
return;
break;
}
case DMX_MODE_MULTIPLE_DRGB:
case DMX_MODE_MULTIPLE_RGB:
case DMX_MODE_MULTIPLE_RGBW:
@ -242,7 +281,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
strip.setBrightness(bri, true);
}
}
if (!is4Chan) {
for (uint16_t i = previousLeds; i < ledsTotal; i++) {
setRealtimePixel(i, e131_data[dmxOffset], e131_data[dmxOffset+1], e131_data[dmxOffset+2], 0);
@ -279,7 +318,11 @@ void handleArtnetPollReply(IPAddress ipAddress) {
case DMX_MODE_SINGLE_RGB:
case DMX_MODE_SINGLE_DRGB:
case DMX_MODE_PRESET:
case DMX_MODE_EFFECT:
case DMX_MODE_EFFECT_W:
case DMX_MODE_EFFECT_SEGMENT:
case DMX_MODE_EFFECT_SEGMENT_W:
break; // 1 universe is enough
case DMX_MODE_MULTIPLE_DRGB:
@ -445,7 +488,7 @@ void sendArtnetPollReply(ArtPollReply *reply, IPAddress ipAddress, uint16_t port
reply->reply_sw_out[0] = (uint8_t)(portAddress & 0x000F);
snprintf_P((char *)reply->reply_node_report, sizeof(reply->reply_node_report)-1, PSTR("#0001 [%04u] OK - WLED v" TOSTRING(WLED_VERSION)), pollReplyCount);
if (pollReplyCount < 9999) {
pollReplyCount++;
} else {

View File

@ -1,18 +1,17 @@
#ifndef WLED_FCN_DECLARE_H
#define WLED_FCN_DECLARE_H
#include <Arduino.h>
#include "src/dependencies/espalexa/EspalexaDevice.h"
#include "src/dependencies/e131/ESPAsyncE131.h"
/*
* All globally accessible functions are declared here
*/
//alexa.cpp
#ifndef WLED_DISABLE_ALEXA
void onAlexaChange(EspalexaDevice* dev);
void alexaInit();
void handleAlexa();
void onAlexaChange(EspalexaDevice* dev);
#endif
//blynk.cpp
#ifndef WLED_DISABLE_BLYNK
@ -172,7 +171,7 @@ void publishMqtt();
void handleTime();
void handleNetworkTime();
void sendNTPPacket();
bool checkNTPResponse();
bool checkNTPResponse();
void updateLocalTime();
void getTimeString(char* out);
bool checkCountdown();
@ -202,7 +201,7 @@ inline bool applyTemporaryPreset() {return applyPreset(255);};
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());
inline void saveTemporaryPreset() {savePreset(255);};
void deletePreset(byte index);
bool getPresetName(byte index, String& name);
bool getPresetName(byte index, String& name);
//set.cpp
bool isAsterisksOnly(const char* str, byte maxLen);

View File

@ -102,7 +102,7 @@ bool bufferedFindSpace(uint16_t targetLen, bool fromStart = true) {
while (f.position() < f.size() -1) {
uint16_t bufsize = f.read(buf, FS_BUFSIZE);
uint16_t count = 0;
while (count < bufsize) {
if(buf[count] == ' ') {
if(++index >= targetLen) { // return true if space long enough
@ -144,7 +144,7 @@ bool bufferedFindObjectEnd() {
while (f.position() < f.size() -1) {
uint16_t bufsize = f.read(buf, FS_BUFSIZE);
uint16_t count = 0;
while (count < bufsize) {
if (buf[count] == '{') objDepth++;
if (buf[count] == '}') objDepth--;
@ -194,7 +194,7 @@ bool appendObjectToFile(const char* key, JsonDocument* content, uint32_t s, uint
doCloseFile = true;
return true; //nothing to append
}
//if there is enough empty space in file, insert there instead of appending
if (!contentLen) contentLen = measureJson(*content);
DEBUGFS_PRINTF("CLen %d\n", contentLen);
@ -211,18 +211,18 @@ bool appendObjectToFile(const char* key, JsonDocument* content, uint32_t s, uint
//permitted space for presets exceeded
updateFSInfo();
if (f.size() + 9000 > (fsBytesTotal - fsBytesUsed)) { //make sure there is enough space to at least copy the file once
errorFlag = ERR_FS_QUOTA;
doCloseFile = true;
return false;
}
//check if last character in file is '}' (typical)
uint32_t eof = f.size() -1;
f.seek(eof, SeekSet);
if (f.read() == '}') pos = eof;
if (pos == 0) //not found
{
DEBUGFS_PRINTLN("not }");
@ -277,12 +277,12 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content)
DEBUGFS_PRINTLN(F("Failed to open!"));
return false;
}
if (!bufferedFind(key)) //key does not exist in file
{
return appendObjectToFile(key, content, s);
}
}
//an object with this key already exists, replace or delete it
pos = f.position();
//measure out end of old object
@ -297,7 +297,7 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content)
//2. The new content is smaller than the old, overwrite and fill diff with spaces
//3. The new content is larger than the old, but smaller than old + trailing spaces, overwrite with new
//4. The new content is larger than old + trailing spaces, delete old and append
uint32_t contentLen = 0;
if (!content->isNull()) contentLen = measureJson(*content);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ void handleHue()
hueNewKey = false;
}
}
if (!WLED_CONNECTED || hueClient == nullptr || millis() - hueLastRequestSent < huePollIntervalMs) return;
hueLastRequestSent = millis();
@ -100,7 +100,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
{
hueError = HUE_ERROR_JSON_PARSING; return;
}
int hueErrorCode = root[0][F("error")]["type"];
if (hueErrorCode)//hue bridge returned error
{
@ -113,7 +113,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
}
return;
}
if (hueAuthRequired)
{
const char* apikey = root[0][F("success")][F("username")];
@ -131,7 +131,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
str = strstr(str,"state");
if (str == nullptr) return;
str = strstr(str,"{");
auto error = deserializeJson(root, str);
if (error)
{
@ -176,7 +176,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
}
hueError = HUE_ERROR_ACTIVE;
//apply vals
if (hueBri != hueBriLast)
{

View File

@ -99,7 +99,7 @@ void handleImprovPacket() {
uint8_t improvState = 0x02; //authorized
if (WLED_WIFI_CONFIGURED) improvState = 0x03; //provisioning
if (Network.isConnected()) improvState = 0x04; //provisioned
sendImprovStateResponse(improvState, false);
sendImprovStateResponse(improvState, false);
if (improvState == 0x04) sendImprovRPCResponse(ImprovRPCType::Request_State);
break;
}
@ -166,7 +166,7 @@ void sendImprovRPCResponse(byte commandId) {
out[11] = len;
out[10] = 1 + len;
out[8] = 3 + len; //RPC command type + data len + url len + url
packetLen = 13 + len;
packetLen = 13 + len;
}
uint8_t checksum = 0;

View File

@ -71,11 +71,11 @@ void decBrightness()
}
// apply preset or fallback to a effect and palette if it doesn't exist
void presetFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID)
void presetFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID)
{
applyPreset(presetID, CALL_MODE_BUTTON_PRESET);
//these two will be overwritten if preset exists in handlePresets()
effectCurrent = effectID;
effectCurrent = effectID;
effectPalette = paletteID;
}
@ -282,7 +282,7 @@ void decodeIR(uint32_t code)
if (code > 0xFFFFFF) return; //invalid code
switch (irEnabled) {
case 1:
case 1:
if (code > 0xF80000) decodeIR24OLD(code); // white 24-key remote (old) - it sends 0xFF0000 values
else decodeIR24(code); // 24-key remote - 0xF70000 to 0xF80000
break;
@ -419,7 +419,7 @@ void decodeIR24CT(uint32_t code)
case IR24_CT_CTPLUS : changeColor(COLOR_COLDWHITE, strip.getSegment(strip.getMainSegmentId()).cct+1); changeEffect(FX_MODE_STATIC); break;
case IR24_CT_CTMINUS : changeColor(COLOR_WARMWHITE, strip.getSegment(strip.getMainSegmentId()).cct-1); changeEffect(FX_MODE_STATIC); break;
case IR24_CT_MEMORY : changeColor(COLOR_NEUTRALWHITE, 127); changeEffect(FX_MODE_STATIC); break;
default: return;
default: return;
}
lastValidCode = code;
}
@ -611,13 +611,13 @@ void decodeIR9(uint32_t code)
/*
This allows users to customize IR actions without the need to edit C code and compile.
From the https://github.com/Aircoookie/WLED/wiki/Infrared-Control page, download the starter
From the https://github.com/Aircoookie/WLED/wiki/Infrared-Control page, download the starter
ir.json file that corresponds to the number of buttons on your remote.
Many of the remotes with the same number of buttons emit the same codes, but will have
different labels or colors. Once you edit the ir.json file, upload it to your controller
using the /edit page.
Each key should be the hex encoded IR code. The "cmd" property should be the HTTP API
Each key should be the hex encoded IR code. The "cmd" property should be the HTTP API
or JSON API command to execute on button press. If the command contains a relative change (SI=~16),
it will register as a repeatable command. If the command doesn't contain a "~" but is repeatable, add "rpt" property
set to true. Other properties are ignored but having labels and positions can assist with editing
@ -632,7 +632,7 @@ Sample:
"label": "Preset 1, fallback to Saw - Party if not found"},
}
*/
void decodeIRJson(uint32_t code)
void decodeIRJson(uint32_t code)
{
char objKey[10];
String cmdStr;
@ -720,10 +720,10 @@ void handleIR()
if (irEnabled > 0)
{
if (irrecv == NULL)
{
{
initIR(); return;
}
if (irrecv->decode(&results))
{
if (results.value != 0) // only print results if anything is received ( != 0 )

View File

@ -45,9 +45,9 @@
#define IR24_PINK 0xF76897
#define IR24_WHITE 0xF7E01F
#define IR24_FLASH 0xF7D02F
#define IR24_STROBE 0xF7F00F
#define IR24_FADE 0xF7C837
#define IR24_SMOOTH 0xF7E817
#define IR24_STROBE 0xF7F00F
#define IR24_FADE 0xF7C837
#define IR24_SMOOTH 0xF7E817
// 24-key defs for white remote control with CW / WW / CT+ and CT- keys (from ALDI LED pillar lamp)
#define IR24_CT_BRIGHTER 0xF700FF // BRI +
@ -75,7 +75,7 @@
#define IR24_CT_CTMINUS 0xF7C837 // CT-
#define IR24_CT_MEMORY 0xF7E817 // MEMORY
// 24-key defs for old remote control
// 24-key defs for old remote control
#define IR24_OLD_BRIGHTER 0xFF906F // Brightness Up
#define IR24_OLD_DARKER 0xFFB847 // Brightness Down
#define IR24_OLD_OFF 0xFFF807 // Power OFF
@ -101,30 +101,30 @@
#define IR24_OLD_FADE 0xFF58A7 // FADE Mode
#define IR24_OLD_SMOOTH 0xFF30CF // SMOOTH Mode
// 40-key defs for blue remote control
#define IR40_BPLUS 0xFF3AC5 //
#define IR40_BMINUS 0xFFBA45 //
#define IR40_OFF 0xFF827D //
#define IR40_ON 0xFF02FD //
#define IR40_RED 0xFF1AE5 //
#define IR40_GREEN 0xFF9A65 //
#define IR40_BLUE 0xFFA25D //
// 40-key defs for blue remote control
#define IR40_BPLUS 0xFF3AC5 //
#define IR40_BMINUS 0xFFBA45 //
#define IR40_OFF 0xFF827D //
#define IR40_ON 0xFF02FD //
#define IR40_RED 0xFF1AE5 //
#define IR40_GREEN 0xFF9A65 //
#define IR40_BLUE 0xFFA25D //
#define IR40_WHITE 0xFF22DD // natural white
#define IR40_REDDISH 0xFF2AD5 //
#define IR40_GREENISH 0xFFAA55 //
#define IR40_DEEPBLUE 0xFF926D //
#define IR40_REDDISH 0xFF2AD5 //
#define IR40_GREENISH 0xFFAA55 //
#define IR40_DEEPBLUE 0xFF926D //
#define IR40_WARMWHITE2 0xFF12ED // warmest white
#define IR40_ORANGE 0xFF0AF5 //
#define IR40_TURQUOISE 0xFF8A75 //
#define IR40_PURPLE 0xFFB24D //
#define IR40_ORANGE 0xFF0AF5 //
#define IR40_TURQUOISE 0xFF8A75 //
#define IR40_PURPLE 0xFFB24D //
#define IR40_WARMWHITE 0xFF32CD // warm white
#define IR40_YELLOWISH 0xFF38C7 //
#define IR40_CYAN 0xFFB847 //
#define IR40_MAGENTA 0xFF7887 //
#define IR40_YELLOWISH 0xFF38C7 //
#define IR40_CYAN 0xFFB847 //
#define IR40_MAGENTA 0xFF7887 //
#define IR40_COLDWHITE 0xFFF807 // cold white
#define IR40_YELLOW 0xFF18E7 //
#define IR40_AQUA 0xFF9867 //
#define IR40_PINK 0xFF58A7 //
#define IR40_YELLOW 0xFF18E7 //
#define IR40_AQUA 0xFF9867 //
#define IR40_PINK 0xFF58A7 //
#define IR40_COLDWHITE2 0xFFD827 // coldest white
#define IR40_WPLUS 0xFF28D7 // white chanel bright plus
#define IR40_WMINUS 0xFFA857 // white chanel bright minus
@ -144,50 +144,50 @@
#define IR40_SLOW 0xFFD02F // SLOW
// 44-key defs
#define IR44_BPLUS 0xFF3AC5 //
#define IR44_BMINUS 0xFFBA45 //
#define IR44_OFF 0xFF827D //
#define IR44_ON 0xFF02FD //
#define IR44_RED 0xFF1AE5 //
#define IR44_GREEN 0xFF9A65 //
#define IR44_BLUE 0xFFA25D //
#define IR44_BPLUS 0xFF3AC5 //
#define IR44_BMINUS 0xFFBA45 //
#define IR44_OFF 0xFF827D //
#define IR44_ON 0xFF02FD //
#define IR44_RED 0xFF1AE5 //
#define IR44_GREEN 0xFF9A65 //
#define IR44_BLUE 0xFFA25D //
#define IR44_WHITE 0xFF22DD // natural white
#define IR44_REDDISH 0xFF2AD5 //
#define IR44_GREENISH 0xFFAA55 //
#define IR44_DEEPBLUE 0xFF926D //
#define IR44_REDDISH 0xFF2AD5 //
#define IR44_GREENISH 0xFFAA55 //
#define IR44_DEEPBLUE 0xFF926D //
#define IR44_WARMWHITE2 0xFF12ED // warmest white
#define IR44_ORANGE 0xFF0AF5 //
#define IR44_TURQUOISE 0xFF8A75 //
#define IR44_PURPLE 0xFFB24D //
#define IR44_ORANGE 0xFF0AF5 //
#define IR44_TURQUOISE 0xFF8A75 //
#define IR44_PURPLE 0xFFB24D //
#define IR44_WARMWHITE 0xFF32CD // warm white
#define IR44_YELLOWISH 0xFF38C7 //
#define IR44_CYAN 0xFFB847 //
#define IR44_MAGENTA 0xFF7887 //
#define IR44_YELLOWISH 0xFF38C7 //
#define IR44_CYAN 0xFFB847 //
#define IR44_MAGENTA 0xFF7887 //
#define IR44_COLDWHITE 0xFFF807 // cold white
#define IR44_YELLOW 0xFF18E7 //
#define IR44_AQUA 0xFF9867 //
#define IR44_PINK 0xFF58A7 //
#define IR44_YELLOW 0xFF18E7 //
#define IR44_AQUA 0xFF9867 //
#define IR44_PINK 0xFF58A7 //
#define IR44_COLDWHITE2 0xFFD827 // coldest white
#define IR44_REDPLUS 0xFF28D7 //
#define IR44_GREENPLUS 0xFFA857 //
#define IR44_BLUEPLUS 0xFF6897 //
#define IR44_QUICK 0xFFE817 //
#define IR44_REDMINUS 0xFF08F7 //
#define IR44_GREENMINUS 0xFF8877 //
#define IR44_BLUEMINUS 0xFF48B7 //
#define IR44_SLOW 0xFFC837 //
#define IR44_DIY1 0xFF30CF //
#define IR44_DIY2 0xFFB04F //
#define IR44_DIY3 0xFF708F //
#define IR44_AUTO 0xFFF00F //
#define IR44_DIY4 0xFF10EF //
#define IR44_DIY5 0xFF906F //
#define IR44_DIY6 0xFF50AF //
#define IR44_FLASH 0xFFD02F //
#define IR44_JUMP3 0xFF20DF //
#define IR44_JUMP7 0xFFA05F //
#define IR44_FADE3 0xFF609F //
#define IR44_FADE7 0xFFE01F //
#define IR44_REDPLUS 0xFF28D7 //
#define IR44_GREENPLUS 0xFFA857 //
#define IR44_BLUEPLUS 0xFF6897 //
#define IR44_QUICK 0xFFE817 //
#define IR44_REDMINUS 0xFF08F7 //
#define IR44_GREENMINUS 0xFF8877 //
#define IR44_BLUEMINUS 0xFF48B7 //
#define IR44_SLOW 0xFFC837 //
#define IR44_DIY1 0xFF30CF //
#define IR44_DIY2 0xFFB04F //
#define IR44_DIY3 0xFF708F //
#define IR44_AUTO 0xFFF00F //
#define IR44_DIY4 0xFF10EF //
#define IR44_DIY5 0xFF906F //
#define IR44_DIY6 0xFF50AF //
#define IR44_FLASH 0xFFD02F //
#define IR44_JUMP3 0xFF20DF //
#define IR44_JUMP7 0xFFA05F //
#define IR44_FADE3 0xFF609F //
#define IR44_FADE7 0xFFE01F //
//Infrared codes for 21-key remote https://images-na.ssl-images-amazon.com/images/I/51NMA0XucnL.jpg
#define IR21_BRIGHTER 0xFFE01F

View File

@ -170,13 +170,20 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
}
#endif
#ifndef WLED_DISABLE_2D
bool reverse = seg.reverse;
bool mirror = seg.mirror;
#endif
seg.selected = elem["sel"] | seg.selected;
seg.reverse = elem["rev"] | seg.reverse;
seg.mirror = elem["mi"] | seg.mirror;
#ifndef WLED_DISABLE_2D
seg.reverse_y = elem["rY"] | seg.reverse_y;
seg.mirror_y = elem["mY"] | seg.mirror_y;
seg.transpose = elem[F("tp")] | seg.transpose;
bool reverse_y = seg.reverse_y;
bool mirror_y = seg.mirror_y;
seg.reverse_y = elem["rY"] | seg.reverse_y;
seg.mirror_y = elem["mY"] | seg.mirror_y;
seg.transpose = elem[F("tp")] | seg.transpose;
if (seg.is2D() && seg.map1D2D == M12_pArc && (reverse != seg.reverse || reverse_y != seg.reverse_y || mirror != seg.mirror || mirror_y != seg.mirror_y)) seg.fill(BLACK); // clear entire segment (in case of Arc 1D to 2D expansion)
#endif
byte fx = seg.mode;
@ -201,7 +208,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
seg.check1 = elem["o1"] | seg.check1;
seg.check2 = elem["o2"] | seg.check2;
seg.check3 = elem["o3"] | seg.check3;
JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) {
// set brightness immediately and disable transition
@ -221,11 +228,11 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
for (size_t i = 0; i < iarr.size(); i++) {
if(iarr[i].is<JsonInteger>()) {
if (!set) {
start = iarr[i];
set = 1;
start = abs(iarr[i].as<int>());
set++;
} else {
stop = iarr[i];
set = 2;
stop = abs(iarr[i].as<int>());
set++;
}
} else { //color
uint8_t rgbw[] = {0,0,0,0};
@ -241,16 +248,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
}
}
if (set < 2) stop = start + 1;
if (set < 2 || stop <= start) stop = start + 1;
uint32_t c = gamma32(RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]));
for (int i = start; i < stop; i++) {
seg.setPixelColor(i, c);
}
if (!set) start++;
while (start < stop) seg.setPixelColor(start++, c);
set = 0;
}
}
strip.trigger();
strip.trigger(); // force segment update
}
// send UDP/WS if segment options changed (except selection; will also deselect current preset)
if (seg.differs(prev) & 0x7F) stateChanged = true;
@ -477,15 +481,17 @@ void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset, b
root["sel"] = seg.isSelected();
root["rev"] = seg.reverse;
root["mi"] = seg.mirror;
#ifndef WLED_DISABLE_2D
if (strip.isMatrix) {
root["rY"] = seg.reverse_y;
root["mY"] = seg.mirror_y;
root[F("tp")] = seg.transpose;
}
root["o1"] = seg.check1;
root["o2"] = seg.check2;
root["o3"] = seg.check3;
root["si"] = seg.soundSim;
#endif
root["o1"] = seg.check1;
root["o2"] = seg.check2;
root["o3"] = seg.check3;
root["si"] = seg.soundSim;
root["m12"] = seg.map1D2D;
}
@ -650,7 +656,7 @@ void serializeInfo(JsonObject root)
fs_info[F("pmt")] = presetsModifiedTime;
root[F("ndc")] = nodeListEnabled ? (int)Nodes.size() : -1;
#ifdef ARDUINO_ARCH_ESP32
#ifdef WLED_DEBUG
wifi_info[F("txPower")] = (int) WiFi.getTxPower();
@ -800,7 +806,7 @@ void serializePalettes(JsonObject root, AsyncWebServerRequest* request)
JsonArray curPalette = palettes.createNestedArray(String(i>=palettesCount ? 255 - i + palettesCount : i));
switch (i) {
case 0: //default palette
setPaletteColors(curPalette, PartyColors_p);
setPaletteColors(curPalette, PartyColors_p);
break;
case 1: //random
curPalette.add("r");

View File

@ -102,19 +102,19 @@ void stateUpdated(byte callMode) {
if (bri != briOld || stateChanged) {
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
//set flag to update blynk, ws and mqtt
interfaceUpdateCallMode = callMode;
stateChanged = false;
} else {
if (nightlightActive && !nightlightActiveOld && callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) {
notify(CALL_MODE_NIGHTLIGHT);
notify(CALL_MODE_NIGHTLIGHT);
interfaceUpdateCallMode = CALL_MODE_NIGHTLIGHT;
}
}
if (callMode != CALL_MODE_NO_NOTIFY && nightlightActive && (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE)) {
briNlT = bri;
nightlightDelayMs -= (millis() - nightlightStartTime);
@ -128,7 +128,7 @@ void stateUpdated(byte callMode) {
//deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
if (fadeTransition) {
//set correct delay if not using notification delay
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration
@ -160,7 +160,7 @@ void updateInterfaces(uint8_t callMode)
sendDataWs();
lastInterfaceUpdate = millis();
if (callMode == CALL_MODE_WS_SEND) return;
#ifndef WLED_DISABLE_ALEXA
if (espalexaDevice != nullptr && callMode != CALL_MODE_ALEXA) {
espalexaDevice->setValue(bri);
@ -168,7 +168,7 @@ void updateInterfaces(uint8_t callMode)
}
#endif
#ifndef WLED_DISABLE_BLYNK
if (callMode != CALL_MODE_BLYNK &&
if (callMode != CALL_MODE_BLYNK &&
callMode != CALL_MODE_NO_NOTIFY) updateBlynk();
#endif
doPublishMqtt = true;
@ -180,8 +180,10 @@ void handleTransitions()
{
//handle still pending interface update
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > INTERFACE_UPDATE_COOLDOWN) updateInterfaces(interfaceUpdateCallMode);
#ifndef WLED_DISABLE_MQTT
if (doPublishMqtt) publishMqtt();
#endif
if (transitionActive && transitionDelayTemp > 0)
{
float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp;
@ -196,7 +198,7 @@ void handleTransitions()
if (tper - tperLast < 0.004) return;
tperLast = tper;
briT = briOld + ((bri - briOld) * tper);
applyBri();
}
}

View File

@ -13,13 +13,13 @@ bool parseLx(int lxValue, byte rgbw[4])
bool ok = false;
float lxRed = 0, lxGreen = 0, lxBlue = 0;
if (lxValue < 200000000) {
if (lxValue < 200000000) {
// Loxone RGB
ok = true;
lxRed = round((lxValue % 1000) * 2.55);
lxGreen = round(((lxValue / 1000) % 1000) * 2.55);
lxBlue = round(((lxValue / 1000000) % 1000) * 2.55);
} else if ((lxValue >= 200000000) && (lxValue <= 201006500)) {
} else if ((lxValue >= 200000000) && (lxValue <= 201006500)) {
// Loxone Lumitech
ok = true;
float tmpBri = floor((lxValue - 200000000) / 10000); ;

View File

@ -177,8 +177,4 @@ bool initMqtt()
mqtt->connect();
return true;
}
#else
bool initMqtt(){return false;}
void publishMqtt(){}
#endif

View File

@ -1,15 +1,15 @@
#pragma once
/*
* Welcome!
* Welcome!
* You can use the file "my_config.h" to make changes to the way WLED is compiled!
* It is possible to enable and disable certain features as well as set defaults for some runtime changeable settings.
*
*
* How to use:
* PlatformIO: Just compile the unmodified code once! The file "my_config.h" will be generated automatically and now you can make your changes.
*
*
* ArduinoIDE: Make a copy of this file and name it "my_config.h". Go to wled.h and uncomment "#define WLED_USE_MY_CONFIG" in the top of the file.
*
*
* DO NOT make changes to the "my_config_sample.h" file directly! Your changes will not be applied.
*/

View File

@ -20,27 +20,27 @@ const ethernet_settings ethernetBoards[] = {
// None
{
},
// WT32-EHT01
// Please note, from my testing only these pins work for LED outputs:
// IO2, IO4, IO12, IO14, IO15
// These pins do not appear to work from my testing:
// IO35, IO36, IO39
{
1, // eth_address,
16, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
1, // eth_address,
16, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
ETH_PHY_LAN8720, // eth_type,
ETH_CLOCK_GPIO0_IN // eth_clk_mode
},
// ESP32-POE
{
0, // eth_address,
12, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
0, // eth_address,
12, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
ETH_PHY_LAN8720, // eth_type,
ETH_CLOCK_GPIO17_OUT // eth_clk_mode
},
@ -77,20 +77,20 @@ const ethernet_settings ethernetBoards[] = {
// ESP3DEUXQuattro
{
1, // eth_address,
-1, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
1, // eth_address,
-1, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
ETH_PHY_LAN8720, // eth_type,
ETH_CLOCK_GPIO17_OUT // eth_clk_mode
},
// ESP32-ETHERNET-KIT-VE
{
0, // eth_address,
5, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
0, // eth_address,
5, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
ETH_PHY_IP101, // eth_type,
ETH_CLOCK_GPIO0_IN // eth_clk_mode
},
@ -135,7 +135,7 @@ void WiFiEvent(WiFiEvent_t event)
#ifdef WLED_USE_ETHERNET
char hostname[25];
#endif
switch (event) {
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
case SYSTEM_EVENT_ETH_START:

View File

@ -162,7 +162,7 @@ void updateTimezone() {
void handleTime() {
handleNetworkTime();
toki.millisecond();
toki.setTick();
@ -363,7 +363,7 @@ void checkTimers()
{
if (timerMacro[i] != 0
&& (timerWeekday[i] & 0x01) //timer is enabled
&& (timerHours[i] == hour(localTime) || timerHours[i] == 24) //if hour is set to 24, activate every hour
&& (timerHours[i] == hour(localTime) || timerHours[i] == 24) //if hour is set to 24, activate every hour
&& timerMinutes[i] == minute(localTime)
&& ((timerWeekday[i] >> weekdayMondayFirst()) & 0x01) //timer should activate at current day of week
&& isTodayInDateRange(((timerMonth[i] >> 4) & 0x0F), timerDay[i], timerMonth[i] & 0x0F, timerDayEnd[i])
@ -416,24 +416,24 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
float N = N1 - (N2 * N3) + day - 30;
//2. convert the longitude to hour value and calculate an approximate time
float lngHour = lon / 15.0f;
float lngHour = lon / 15.0f;
float t = N + (((sunset ? 18 : 6) - lngHour) / 24);
//3. calculate the Sun's mean anomaly
//3. calculate the Sun's mean anomaly
float M = (0.9856f * t) - 3.289f;
//4. calculate the Sun's true longitude
float L = fmod_t(M + (1.916f * sin_t(DEG_TO_RAD*M)) + (0.02f * sin_t(2*DEG_TO_RAD*M)) + 282.634f, 360.0f);
//5a. calculate the Sun's right ascension
//5a. calculate the Sun's right ascension
float RA = fmod_t(RAD_TO_DEG*atan_t(0.91764f * tan_t(DEG_TO_RAD*L)), 360.0f);
//5b. right ascension value needs to be in the same quadrant as L
//5b. right ascension value needs to be in the same quadrant as L
float Lquadrant = floor_t( L/90) * 90;
float RAquadrant = floor_t(RA/90) * 90;
RA = RA + (Lquadrant - RAquadrant);
//5c. right ascension value needs to be converted into hours
//5c. right ascension value needs to be converted into hours
RA /= 15.0f;
//6. calculate the Sun's declination
@ -449,7 +449,7 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
float H = sunset ? RAD_TO_DEG*acos_t(cosH) : 360 - RAD_TO_DEG*acos_t(cosH);
H /= 15.0f;
//8. calculate local mean time of rising/setting
//8. calculate local mean time of rising/setting
float T = H + RA - (0.06571f * t) - 6.622f;
//9. adjust back to UTC

View File

@ -18,7 +18,7 @@ void _overlayAnalogClock()
int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
if (analogClockSecondsTrail)

View File

@ -514,7 +514,7 @@ const byte Tiamat_gp[] PROGMEM = {
220, 39,252,135, //gc from 177,254,255
240, 193,213,253, //gc from 203,239,253
255, 255,249,255};
//Custom palette by Aircoookie
const byte April_Night_gp[] PROGMEM = {
@ -598,16 +598,16 @@ const byte Atlantica_gp[] PROGMEM = {
0, 255, 5, 0, //red
60, 255, 5, 0,
60, 196, 57, 2, //amber (start 61?)
120, 196, 57, 2,
120, 196, 57, 2,
120, 6, 126, 2, //green (start 126?)
180, 6, 126, 2,
180, 4, 30, 114, //blue (start 191?)
255, 4, 30, 114};
// Gradient palette "temperature_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/arendal/tn/temperature.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 144 bytes of program space.
// Size: 144 bytes of program space.
const byte temperature_gp[] PROGMEM = {
0, 1, 27,105,

View File

@ -31,7 +31,7 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
#endif
return false;
}
byte by = gpio >> 3;
byte bi = gpio - 8*by;
bitWrite(pinAlloc[by], bi, false);
@ -119,7 +119,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
continue;
} else if (isPinAllocated(gpio)) {
#ifdef WLED_DEBUG
DEBUG_PRINT(F("PIN ALLOC: FAIL: IO "));
DEBUG_PRINT(F("PIN ALLOC: FAIL: IO "));
DEBUG_PRINT(gpio);
DEBUG_PRINT(F(" already allocated by "));
DebugPrintOwnerTag(ownerTag[gpio]);
@ -143,7 +143,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
// as this can greatly simplify configuration arrays
continue;
}
if (gpio >= WLED_NUM_PINS)
if (gpio >= WLED_NUM_PINS)
continue; // other unexpected GPIO => avoid array bounds violation
byte by = gpio >> 3;
@ -151,7 +151,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
bitWrite(pinAlloc[by], bi, true);
ownerTag[gpio] = tag;
#ifdef WLED_DEBUG
DEBUG_PRINT(F("PIN ALLOC: Pin "));
DEBUG_PRINT(F("PIN ALLOC: Pin "));
DEBUG_PRINT(gpio);
DEBUG_PRINT(F(" allocated by "));
DebugPrintOwnerTag(tag);
@ -183,7 +183,7 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
}
if (isPinAllocated(gpio)) {
#ifdef WLED_DEBUG
DEBUG_PRINT(F("PIN ALLOC: Pin "));
DEBUG_PRINT(F("PIN ALLOC: Pin "));
DEBUG_PRINT(gpio);
DEBUG_PRINT(F(" already allocated by "));
DebugPrintOwnerTag(ownerTag[gpio]);
@ -197,12 +197,12 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
bitWrite(pinAlloc[by], bi, true);
ownerTag[gpio] = tag;
#ifdef WLED_DEBUG
DEBUG_PRINT(F("PIN ALLOC: Pin "));
DEBUG_PRINT(F("PIN ALLOC: Pin "));
DEBUG_PRINT(gpio);
DEBUG_PRINT(F(" successfully allocated by "));
DebugPrintOwnerTag(tag);
DEBUG_PRINTLN(F(""));
#endif
#endif
return true;
}
@ -224,9 +224,9 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
* Strapping pins: GPIO0, GPIO3, GPIO45 and GPIO46 are strapping pins. For more infomation, please refer to ESP32-S3 datasheet.
* Serial TX = GPIO43, RX = GPIO44; LED BUILTIN is usually GPIO39
* USB-JTAG: GPIO 19 and 20 are used by USB-JTAG by default. In order to use them as GPIOs, USB-JTAG will be disabled by the drivers.
* SPI0/1: GPIO26-32 are usually used for SPI flash and PSRAM and not recommended for other uses.
* SPI0/1: GPIO26-32 are usually used for SPI flash and PSRAM and not recommended for other uses.
* When using Octal Flash or Octal PSRAM or both, GPIO33~37 are connected to SPIIO4 ~ SPIIO7 and SPIDQS. Therefore, on boards embedded with ESP32-S3R8 / ESP32-S3R8V chip, GPIO33~37 are also not recommended for other uses.
*
*
* see https://docs.espressif.com/projects/esp-idf/en/v4.4.2/esp32s3/api-reference/peripherals/adc.html
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/adc_oneshot.html
* ADC1: GPIO1 - GPIO10 (channel 0..9)

View File

@ -15,7 +15,7 @@ typedef struct PinManagerPinType {
* Allows PinManager to "lock" an allocation to a specific
* owner, so someone else doesn't accidentally de-allocate
* a pin it hasn't allocated. Also enhances debugging.
*
*
* RAM Cost:
* 17 bytes on ESP8266
* 40 bytes on ESP32
@ -51,7 +51,7 @@ enum struct PinOwner : uint8_t {
UM_MultiRelay = USERMOD_ID_MULTI_RELAY, // 0x0D // Usermod "usermod_multi_relay.h"
UM_AnimatedStaircase = USERMOD_ID_ANIMATED_STAIRCASE, // 0x0E // Usermod "Animated_Staircase.h"
UM_Battery = USERMOD_ID_BATTERY, //
// #define USERMOD_ID_RTC // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" HW_I2C pins
// #define USERMOD_ID_RTC // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" HW_I2C pins
// #define USERMOD_ID_ELEKSTUBE_IPS // 0x10 // Usermod "usermod_elekstube_ips.h" -- Uses quite a few pins ... see Hardware.h and User_Setup.h
// #define USERMOD_ID_SN_PHOTORESISTOR // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager
UM_BH1750 = USERMOD_ID_BH1750, // 0x14 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
@ -92,7 +92,7 @@ class PinManagerClass {
// De-allocation requires the same owner tag (or override)
bool allocatePin(byte gpio, bool output, PinOwner tag);
// Allocates all the pins, or allocates none of the pins, with owner tag.
// Provided to simplify error condition handling in clients
// Provided to simplify error condition handling in clients
// using more than one pin, such as I2C, SPI, rotary encoders,
// ethernet, etc..
bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag );

View File

@ -55,7 +55,7 @@ void unloadPlaylist() {
int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
unloadPlaylist();
JsonArray presets = playlistObj["ps"];
playlistLen = presets.size();
if (playlistLen == 0) return -1;

View File

@ -79,12 +79,12 @@ static void doSaveState() {
playlistSave = false;
}
bool getPresetName(byte index, String& name)
bool getPresetName(byte index, String& name)
{
if (!requestJSONBufferLock(9)) return false;
bool presetExists = false;
if (readObjectFromFileUsingId(getFileName(), index, &doc))
{
{
JsonObject fdo = doc.as<JsonObject>();
if (fdo["n"]) {
name = (const char*)(fdo["n"]);

View File

@ -171,14 +171,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
buttonType[i] = request->arg(be).toInt();
#ifdef ARDUINO_ARCH_ESP32
// ESP32 only: check that analog button pin is a valid ADC gpio
if (((buttonType[i] == BTN_TYPE_ANALOG) || (buttonType[i] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[i]) < 0))
if (((buttonType[i] == BTN_TYPE_ANALOG) || (buttonType[i] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[i]) < 0))
{
// not an ADC analog pin
if (btnPin[i] >= 0) DEBUG_PRINTF("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n", btnPin[i], i);
btnPin[i] = -1;
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button);
}
else
}
else
#endif
{
if (disablePullUp) {
@ -200,7 +200,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
strip.milliampsPerLed = request->arg(F("LA")).toInt();
briS = request->arg(F("CA")).toInt();
turnOnAtBoot = request->hasArg(F("BO"));
@ -284,8 +284,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (t >= 0 && t <= 63999) e131Universe = t;
t = request->arg(F("DA")).toInt();
if (t >= 0 && t <= 510) DMXAddress = t;
t = request->arg(F("XX")).toInt();
if (t >= 0 && t <= 150) DMXSegmentSpacing = t;
t = request->arg(F("DM")).toInt();
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_RGBW) DMXMode = t;
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_PRESET) DMXMode = t;
t = request->arg(F("ET")).toInt();
if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
arlsForceMaxBri = request->hasArg(F("FB"));
@ -362,7 +364,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
longitude = request->arg(F("LN")).toFloat();
latitude = request->arg(F("LT")).toFloat();
// force a sunrise/sunset re-calculation
calculateSunriseAndSunset();
calculateSunriseAndSunset();
overlayCurrent = request->hasArg(F("OL")) ? 1 : 0;
@ -681,7 +683,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
lastEditTime = millis();
if (subPage != 2 && !doReboot) doSerializeConfig = true; //serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
#ifndef WLED_DISABLE_ALEXA
if (subPage == 4) alexaInit();
#endif
}

View File

@ -41,7 +41,7 @@ void notify(byte callMode, bool followUp)
udpOut[8] = mainseg.mode;
udpOut[9] = mainseg.speed;
udpOut[10] = W(col);
//compatibilityVersionByte:
//compatibilityVersionByte:
//0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
@ -62,7 +62,7 @@ void notify(byte callMode, bool followUp)
udpOut[21] = G(col);
udpOut[22] = B(col);
udpOut[23] = W(col);
udpOut[24] = followUp;
uint32_t t = millis() + strip.timebase;
udpOut[25] = (t >> 24) & 0xFF;
@ -219,7 +219,7 @@ void handleNotifications()
if(udpConnected && (notificationCount < udpNumRetries) && ((millis()-notificationSentTime) > 250)){
notify(notificationSentCallMode,true);
}
if (e131NewData && millis() - strip.getLastShow() > 15)
{
e131NewData = false;
@ -231,7 +231,7 @@ void handleNotifications()
//receive UDP notifications
if (!udpConnected) return;
bool isSupp = false;
size_t packetSize = notifierUdp.parsePacket();
if (!packetSize && udp2Connected) {
@ -260,11 +260,11 @@ void handleNotifications()
}
if (!(realtimeMode && useMainSegmentOnly)) strip.show();
return;
}
}
}
if (!(receiveNotifications || receiveDirect)) return;
localIP = Network.localIP();
//notifier and UDP realtime
if (!packetSize || packetSize > UDP_IN_MAXSIZE) return;
@ -313,7 +313,7 @@ void handleNotifications()
if (millis() - notificationSentTime < 1000) return;
if (udpIn[1] > 199) return; //do not receive custom versions
//compatibilityVersionByte:
//compatibilityVersionByte:
byte version = udpIn[11];
// if we are not part of any sync group ignore message
@ -321,7 +321,7 @@ void handleNotifications()
// legacy senders are treated as if sending in sync group 1 only
if (!(receiveGroups & 0x01)) return;
} else if (!(receiveGroups & udpIn[36])) return;
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
//apply colors from notification to main segment, only if not syncing full segments
@ -336,7 +336,7 @@ void handleNotifications()
if (version > 9 && version < 200 && udpIn[37] < 255) { // valid CCT/Kelvin value
uint16_t cct = udpIn[38];
if (udpIn[37] > 0) { //Kelvin
cct |= (udpIn[37] << 8);
cct |= (udpIn[37] << 8);
}
strip.setCCT(cct);
}
@ -404,7 +404,7 @@ void handleNotifications()
}
stateChanged = true;
}
// simple effect sync, applies to all selected segments
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
for (size_t i = 0; i < strip.getSegmentsNum(); i++) {
@ -450,7 +450,7 @@ void handleNotifications()
}
}
}
if (version > 3)
{
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
@ -458,14 +458,14 @@ void handleNotifications()
nightlightActive = udpIn[6];
if (nightlightActive) nightlightDelayMins = udpIn[7];
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
stateUpdated(CALL_MODE_NOTIFICATION);
return;
}
if (!receiveDirect) return;
//TPM2.NET
if (udpIn[0] == 0x9c)
{
@ -543,7 +543,7 @@ void handleNotifications()
for (size_t i = 2; i < packetSize -3; i += 4)
{
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
id++; if (id >= totalLen) break;
}
} else if (udpIn[0] == 4) //dnrgb
@ -652,7 +652,7 @@ void sendSysInfoUDP()
uint8_t data[44] = {0};
data[0] = 255;
data[1] = 1;
for (size_t x = 0; x < 4; x++) {
data[x + 2] = ip[x];
}
@ -717,7 +717,7 @@ void sendSysInfoUDP()
uint8_t sequenceNumber = 0; // this needs to be shared across all outputs
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8_t *buffer, uint8_t bri, bool isRGBW) {
if (!(apActive || interfacesInited) || !client[0] || !length) return 1; // network not initialised or dummy/unset IP address 031522 ajn added check for ap
if (!(apActive || interfacesInited) || !client[0] || !length) return 1; // network not initialised or dummy/unset IP address 031522 ajn added check for ap
WiFiUDP ddpUdp;
@ -730,7 +730,7 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
// there are 3 channels per RGB pixel
uint32_t channel = 0; // TODO: allow specifying the start channel
// the current position in the buffer
// the current position in the buffer
size_t bufferOffset = 0;
for (size_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
@ -768,7 +768,7 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
/*8*/ddpUdp.write(0xFF & (packetSize >> 8));
/*9*/ddpUdp.write(0xFF & (packetSize ));
// write the colors, the write write(const uint8_t *buffer, size_t size)
// write the colors, the write write(const uint8_t *buffer, size_t size)
// function is just a loop internally too
for (size_t i = 0; i < packetSize; i += 3) {
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // R
@ -777,7 +777,7 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
if (isRGBW) ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // W
}
if (!ddpUdp.endPacket()) {
if (!ddpUdp.endPacket()) {
DEBUG_PRINTLN(F("WiFiUDP.endPacket returned an error"));
return 1; // problem
}

View File

@ -9,14 +9,14 @@ void UsermodManager::connected() { for (byte i = 0; i < numMods; i++) um
void UsermodManager::loop() { for (byte i = 0; i < numMods; i++) ums[i]->loop(); }
void UsermodManager::handleOverlayDraw() { for (byte i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); }
void UsermodManager::appendConfigData() { for (byte i = 0; i < numMods; i++) ums[i]->appendConfigData(); }
bool UsermodManager::handleButton(uint8_t b) {
bool UsermodManager::handleButton(uint8_t b) {
bool overrideIO = false;
for (byte i = 0; i < numMods; i++) {
if (ums[i]->handleButton(b)) overrideIO = true;
}
return overrideIO;
}
bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
for (byte i = 0; i < numMods; i++) {
if (mod_id > 0 && ums[i]->getId() != mod_id) continue; // only get data form requested usermod if provided
if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can povide data at one time)
@ -27,7 +27,7 @@ void UsermodManager::addToJsonState(JsonObject& obj) { for (byte i = 0; i < n
void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); }
void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); }
void UsermodManager::addToConfig(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToConfig(obj); }
bool UsermodManager::readFromConfig(JsonObject& obj) {
bool UsermodManager::readFromConfig(JsonObject& obj) {
bool allComplete = true;
for (byte i = 0; i < numMods; i++) {
if (!ums[i]->readFromConfig(obj)) allComplete = false;

View File

@ -4,7 +4,7 @@
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
*
*
* Consider the v2 usermod API if you need a more advanced feature set!
*/
@ -13,7 +13,7 @@
//gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup()
{
}
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
@ -25,5 +25,5 @@ void userConnected()
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
void userLoop()
{
}

View File

@ -6,13 +6,13 @@
class UsermodRenameMe : public Usermod {
private:
public:
void setup() {
}
void loop() {
}
};

View File

@ -55,7 +55,7 @@
#ifdef USERMOD_FOUR_LINE_DISPLAY
#ifdef USE_ALT_DISPlAY
#include "../usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h"
#else
#else
#include "../usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h"
#endif
#endif
@ -169,7 +169,7 @@
// resolved correctly (when included in mod's header only)
#ifdef WLED_USE_SD_MMC
#include "SD_MMC.h"
#elif defined(WLED_USE_SD_SPI)
#elif defined(WLED_USE_SD_SPI)
#include "SD.h"
#include "SPI.h"
#endif
@ -196,119 +196,119 @@ void registerUsermods()
#ifdef USERMOD_BATTERY
usermods.add(new UsermodBattery());
#endif
#ifdef USERMOD_DALLASTEMPERATURE
usermods.add(new UsermodTemperature());
#endif
#ifdef USERMOD_SN_PHOTORESISTOR
usermods.add(new Usermod_SN_Photoresistor());
#endif
#ifdef USERMOD_PWM_FAN
usermods.add(new PWMFanUsermod());
#endif
#ifdef USERMOD_BUZZER
usermods.add(new BuzzerUsermod());
#endif
#ifdef USERMOD_BH1750
usermods.add(new Usermod_BH1750());
#endif
#ifdef USERMOD_BME280
usermods.add(new UsermodBME280());
#endif
#ifdef USERMOD_SENSORSTOMQTT
usermods.add(new UserMod_SensorsToMQTT());
#endif
#ifdef USERMOD_PIRSWITCH
usermods.add(new PIRsensorSwitch());
#endif
#ifdef USERMOD_MODE_SORT
usermods.add(new ModeSortUsermod());
#endif
#ifdef USERMOD_FOUR_LINE_DISPLAY
usermods.add(new FourLineDisplayUsermod());
#endif
#ifdef USERMOD_ROTARY_ENCODER_UI
usermods.add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
#endif
#ifdef USERMOD_AUTO_SAVE
usermods.add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
#endif
#ifdef USERMOD_DHT
usermods.add(new UsermodDHT());
#endif
#ifdef USERMOD_VL53L0X_GESTURES
usermods.add(new UsermodVL53L0XGestures());
#endif
#ifdef USERMOD_ANIMATED_STAIRCASE
usermods.add(new Animated_Staircase());
#endif
#ifdef USERMOD_MULTI_RELAY
usermods.add(new MultiRelay());
#endif
#ifdef USERMOD_RTC
usermods.add(new RTCUsermod());
#endif
#ifdef USERMOD_ELEKSTUBE_IPS
usermods.add(new ElekstubeIPSUsermod());
#endif
#ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR
usermods.add(new RotaryEncoderBrightnessColor());
#endif
#ifdef RGB_ROTARY_ENCODER
usermods.add(new RgbRotaryEncoderUsermod());
#endif
#ifdef USERMOD_ST7789_DISPLAY
usermods.add(new St7789DisplayUsermod());
#endif
#ifdef USERMOD_SEVEN_SEGMENT
usermods.add(new SevenSegmentDisplay());
#endif
#ifdef USERMOD_SSDR
usermods.add(new UsermodSSDR());
#endif
#ifdef USERMOD_CRONIXIE
usermods.add(new UsermodCronixie());
#endif
#ifdef QUINLED_AN_PENTA
usermods.add(new QuinLEDAnPentaUsermod());
#endif
#ifdef USERMOD_WIZLIGHTS
usermods.add(new WizLightsUsermod());
#endif
#ifdef USERMOD_WORDCLOCK
usermods.add(new WordClockUsermod());
#endif
#ifdef USERMOD_MY9291
usermods.add(new MY9291Usermod());
#endif
#ifdef USERMOD_SI7021_MQTT_HA
usermods.add(new Si7021_MQTT_HA());
#endif
@ -316,7 +316,7 @@ void registerUsermods()
#ifdef USERMOD_SMARTNEST
usermods.add(new Smartnest());
#endif
#ifdef USERMOD_AUDIOREACTIVE
usermods.add(new AudioReactive());
#endif
@ -324,15 +324,15 @@ void registerUsermods()
#ifdef USERMOD_ANALOG_CLOCK
usermods.add(new AnalogClockUsermod());
#endif
#ifdef USERMOD_PING_PONG_CLOCK
usermods.add(new PingPongClockUsermod());
#endif
#ifdef USERMOD_ADS1115
usermods.add(new ADS1115Usermod());
#endif
#ifdef USERMOD_BOBLIGHT
usermods.add(new BobLightUsermod());
#endif
@ -340,7 +340,7 @@ void registerUsermods()
#ifdef SD_ADAPTER
usermods.add(new UsermodSdCard());
#endif
#ifdef USERMOD_PWM_OUTPUTS
usermods.add(new PwmOutputsUsermod());
#endif

View File

@ -29,7 +29,7 @@ void parseNumber(const char* str, byte* val, byte minv, byte maxv)
} else {
if (wrap && *val == maxv && out > 0) out = minv;
else if (wrap && *val == minv && out < 0) out = maxv;
else {
else {
out += *val;
if (out > maxv) out = maxv;
if (out < minv) out = minv;
@ -335,7 +335,7 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
}
// we have slider name (including default value) in the dest buffer
for (size_t i=0; i<strlen(dest); i++) if (dest[i]=='=') { dest[i]='\0'; break; } // truncate default value
} else {
// defaults to just speed and intensity since there is no slider data
switch (slider) {
@ -397,7 +397,7 @@ typedef enum UM_SoundSimulations {
UMS_14_3
} um_soundSimulations_t;
um_data_t* simulateSound(uint8_t simulationId)
um_data_t* simulateSound(uint8_t simulationId)
{
static uint8_t samplePeak;
static float FFT_MajorPeak;
@ -426,7 +426,7 @@ um_data_t* simulateSound(uint8_t simulationId)
um_data->u_data = new void*[um_data->u_size];
um_data->u_data[0] = &volumeSmth;
um_data->u_data[1] = &volumeRaw;
um_data->u_data[2] = fftResult;
um_data->u_data[2] = fftResult;
um_data->u_data[3] = &samplePeak;
um_data->u_data[4] = &FFT_MajorPeak;
um_data->u_data[5] = &my_magnitude;

View File

@ -42,7 +42,9 @@ void WLED::loop()
#endif
handleTime();
#ifndef WLED_DISABLE_INFRARED
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
#endif
handleConnection();
handleSerial();
handleNotifications();
@ -64,7 +66,9 @@ void WLED::loop()
yield();
handleIO();
#ifndef WLED_DISABLE_INFRARED
handleIR();
#endif
#ifndef WLED_DISABLE_ALEXA
handleAlexa();
#endif
@ -135,7 +139,9 @@ void WLED::loop()
}
if (millis() - lastMqttReconnectAttempt > 30000 || lastMqttReconnectAttempt == 0) { // lastMqttReconnectAttempt==0 forces immediate broadcast
lastMqttReconnectAttempt = millis();
#ifndef WLED_DISABLE_MQTT
initMqtt();
#endif
yield();
// refresh WLED nodes list
refreshNodeList();
@ -150,7 +156,7 @@ void WLED::loop()
}
//LED settings have been saved, re-init busses
//This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
//This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
if (doInitBusses) {
doInitBusses = false;
DEBUG_PRINTLN(F("Re-init busses."));
@ -364,7 +370,7 @@ void WLED::setup()
if (!fsinit) {
DEBUGFS_PRINTLN(F("FS failed!"));
errorFlag = ERR_FS_BEGIN;
}
}
#ifdef WLED_ADD_EEPROM_SUPPORT
else deEEP();
#else
@ -414,8 +420,10 @@ void WLED::setup()
// fill in unique mdns default
if (strcmp(cmDNS, "x") == 0) sprintf_P(cmDNS, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
#ifndef WLED_DISABLE_MQTT
if (mqttDeviceTopic[0] == 0) sprintf_P(mqttDeviceTopic, PSTR("wled/%*s"), 6, escapedMac.c_str() + 6);
if (mqttClientID[0] == 0) sprintf_P(mqttClientID, PSTR("WLED-%*s"), 6, escapedMac.c_str() + 6);
#endif
#ifdef WLED_ENABLE_ADALIGHT
if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket();
@ -579,10 +587,10 @@ bool WLED::initEthernet()
}
if (!ETH.begin(
(uint8_t) es.eth_address,
(int) es.eth_power,
(int) es.eth_mdc,
(int) es.eth_mdio,
(uint8_t) es.eth_address,
(int) es.eth_power,
(int) es.eth_mdc,
(int) es.eth_mdio,
(eth_phy_type_t) es.eth_type,
(eth_clock_mode_t) es.eth_clk_mode
)) {
@ -674,9 +682,11 @@ void WLED::initInterfaces()
}
#endif
#ifndef WLED_DISABLE_ALEXA
// init Alexa hue emulation
if (alexaEnabled)
alexaInit();
#endif
#ifndef WLED_DISABLE_OTA
if (aOtaEnabled)
@ -715,7 +725,9 @@ void WLED::initInterfaces()
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
ddp.begin(false, DDP_DEFAULT_PORT);
reconnectHue();
#ifndef WLED_DISABLE_MQTT
initMqtt();
#endif
interfacesInited = true;
wasConnected = true;
}

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2301030
#define VERSION 2301170
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -121,6 +121,7 @@
#define ESPALEXA_MAXDEVICES 10
// #define ESPALEXA_DEBUG
#include "src/dependencies/espalexa/Espalexa.h"
#include "src/dependencies/espalexa/EspalexaDevice.h"
#endif
#ifndef WLED_DISABLE_BLYNK
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
@ -135,7 +136,9 @@
#endif
#include "src/dependencies/e131/ESPAsyncE131.h"
#ifdef WLED_ENABLE_MQTT
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
#endif
#define ARDUINOJSON_DECODE_UNICODE 0
#include "src/dependencies/json/AsyncJson-v6.h"
@ -402,12 +405,18 @@ WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings fo
WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454
WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.)
WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
WLED_GLOBAL uint16_t DMXSegmentSpacing _INIT(0); // Number of void/unused channels between each segments DMX channels
WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss
WLED_GLOBAL bool e131Multicast _INIT(false); // multicast or unicast
WLED_GLOBAL bool e131SkipOutOfSequence _INIT(false); // freeze instead of flickering
WLED_GLOBAL uint16_t pollReplyCount _INIT(0); // count number of replies for ArtPoll node report
// mqtt
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0); // used for other periodic tasks too
#ifndef WLED_DISABLE_MQTT
WLED_GLOBAL AsyncMqttClient *mqtt _INIT(NULL);
WLED_GLOBAL bool mqttEnabled _INIT(false);
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
WLED_GLOBAL char mqttDeviceTopic[33] _INIT(""); // main MQTT topic (individual per device, default is wled/mac)
WLED_GLOBAL char mqttGroupTopic[33] _INIT("wled/all"); // second MQTT topic (for example to group devices)
WLED_GLOBAL char mqttServer[33] _INIT(""); // both domains and IPs should work (no SSL)
@ -415,6 +424,10 @@ WLED_GLOBAL char mqttUser[41] _INIT(""); // optional: username
WLED_GLOBAL char mqttPass[65] _INIT(""); // optional: password for MQTT auth
WLED_GLOBAL char mqttClientID[41] _INIT(""); // override the client ID
WLED_GLOBAL uint16_t mqttPort _INIT(1883);
#define WLED_MQTT_CONNECTED (mqtt != nullptr && mqtt->connected())
#else
#define WLED_MQTT_CONNECTED false
#endif
#ifndef WLED_DISABLE_HUESYNC
WLED_GLOBAL bool huePollingEnabled _INIT(false); // poll hue bridge for light state
@ -590,11 +603,8 @@ WLED_GLOBAL uint8_t tpmPacketCount _INIT(0);
WLED_GLOBAL uint16_t tpmPayloadFrameSize _INIT(0);
WLED_GLOBAL bool useMainSegmentOnly _INIT(false);
// mqtt
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0);
WLED_GLOBAL unsigned long lastInterfaceUpdate _INIT(0);
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(CALL_MODE_INIT);
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
// alexa udp
WLED_GLOBAL String escapedMac;
@ -655,8 +665,7 @@ WLED_GLOBAL AsyncWebServer server _INIT_N(((80)));
#ifdef WLED_ENABLE_WEBSOCKETS
WLED_GLOBAL AsyncWebSocket ws _INIT_N((("/ws")));
#endif
WLED_GLOBAL AsyncClient* hueClient _INIT(NULL);
WLED_GLOBAL AsyncMqttClient* mqtt _INIT(NULL);
WLED_GLOBAL AsyncClient *hueClient _INIT(NULL);
WLED_GLOBAL AsyncWebHandler *editHandler _INIT(nullptr);
// udp interface objects
@ -766,7 +775,6 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
#endif
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID, DEFAULT_CLIENT_SSID) != 0)
#define WLED_MQTT_CONNECTED (mqtt != nullptr && mqtt->connected())
#ifndef WLED_AP_SSID_UNIQUE
#define WLED_SET_AP_SSID() do { \

View File

@ -5,7 +5,7 @@
/*
* DEPRECATED, do not use for new settings
* Only used to restore config from pre-0.11 installations using the deEEP() methods
*
*
* Methods to handle saving and loading to non-volatile memory
* EEPROM Map: https://github.com/Aircoookie/WLED/wiki/EEPROM-Map
*/
@ -154,9 +154,9 @@ void loadSettingsFromEEPROM()
turnOnAtBoot = EEPROM.read(369);
//strip.isRgbw = EEPROM.read(372);
//374 - strip.paletteFade
apBehavior = EEPROM.read(376);
//377 = lastEEPROMversion
if (lastEEPROMversion > 3) {
aOtaEnabled = EEPROM.read(390);
@ -164,7 +164,7 @@ void loadSettingsFromEEPROM()
receiveNotificationEffects = EEPROM.read(392);
}
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
if (lastEEPROMversion > 4) {
#ifndef WLED_DISABLE_HUESYNC
huePollingEnabled = EEPROM.read(2048);
@ -232,7 +232,7 @@ void loadSettingsFromEEPROM()
timerMacro[i] = EEPROM.read(2290 + i);
if (timerMacro[i] > 0) timerMacro[i] += 16; //add 16 to work with macro --> preset mapping
if (timerWeekday[i] == 0) timerWeekday[i] = 255;
if (timerMacro[i] == 0) timerWeekday[i] = timerWeekday[i] & 0b11111110;
if (timerMacro[i] == 0) timerWeekday[i] = timerWeekday[i] & 0b11111110;
}
}
@ -319,8 +319,8 @@ void loadSettingsFromEEPROM()
if (lastEEPROMversion > 21) {
udpPort2 = EEPROM.read(378) + ((EEPROM.read(379) << 8) & 0xFF00);
}
}
receiveDirect = !EEPROM.read(2200);
notifyMacro = EEPROM.read(2201);
@ -349,7 +349,7 @@ void loadSettingsFromEEPROM()
DMXChannels = EEPROM.read(2530);
DMXGap = EEPROM.read(2531) + ((EEPROM.read(2532) << 8) & 0xFF00);
DMXStart = EEPROM.read(2533) + ((EEPROM.read(2534) << 8) & 0xFF00);
for (int i=0;i<15;i++) {
DMXFixtureMap[i] = EEPROM.read(2535+i);
} //last used: 2549
@ -372,7 +372,7 @@ void applyMacro(byte index) {
// De-EEPROM routine, upgrade from previous versions to v0.11
void deEEP() {
if (WLED_FS.exists("/presets.json")) return;
DEBUG_PRINTLN(F("Preset file not found, attempting to load from EEPROM"));
DEBUGFS_PRINTLN(F("Allocating saving buffer for dEEP"));
if (!requestJSONBufferLock(8)) return;
@ -413,7 +413,7 @@ void deEEP() {
for (byte j = 0; j < numChannels; j++) colX.add(EEPROM.read(memloc + j));
}
segObj["fx"] = EEPROM.read(i+10);
segObj["sx"] = EEPROM.read(i+11);
segObj["ix"] = EEPROM.read(i+16);

View File

@ -2,7 +2,7 @@
* Contains some trigonometric functions.
* The ANSI C equivalents are likely faster, but using any sin/cos/tan function incurs a memory penalty of 460 bytes on ESP8266, likely for lookup tables.
* This implementation has no extra static memory usage.
*
*
* Source of the cos_t() function: https://web.eecs.utk.edu/~azh/blog/cosine.html (cos_taylor_literal_6terms)
*/

View File

@ -46,7 +46,7 @@ void sendJSON(){
if (i != used-1) Serial.write(',');
}
Serial.println("]");
}
}
}
// RGB LED data returned as bytes in TPM2 format. Faster, and slightly less easy to use on the other end.
@ -64,13 +64,13 @@ void sendBytes(){
Serial.write(qadd8(W(c), B(c))); //B
}
Serial.write(0x36); Serial.write('\n');
}
}
}
void handleSerial()
{
if (pinManager.isPinAllocated(hardwareRX)) return;
#ifdef WLED_ENABLE_ADALIGHT
static auto state = AdaState::Header_A;
static uint16_t count = 0;
@ -94,7 +94,7 @@ void handleSerial()
return;
} else if (next == 'v') {
Serial.print("WLED"); Serial.write(' '); Serial.println(VERSION);
} else if (next == 0xB0) {updateBaudRate( 115200);
} else if (next == 0xB1) {updateBaudRate( 230400);
} else if (next == 0xB2) {updateBaudRate( 460800);
@ -103,11 +103,11 @@ void handleSerial()
} else if (next == 0xB5) {updateBaudRate( 921600);
} else if (next == 0xB6) {updateBaudRate(1000000);
} else if (next == 0xB7) {updateBaudRate(1500000);
} else if (next == 'l') {sendJSON(); // Send LED data as JSON Array
} else if (next == 'L') {sendBytes(); // Send LED data as TPM2 Data Packet
} else if (next == 'o') {continuousSendLED = false; // Disable Continuous Serial Streaming
} else if (next == 'o') {continuousSendLED = false; // Disable Continuous Serial Streaming
} else if (next == 'O') {continuousSendLED = true; // Enable Continuous Serial Streaming
} else if (next == '{') { //JSON API
@ -195,8 +195,8 @@ void handleSerial()
// All other received bytes will disable Continuous Serial Streaming
if (continuousSendLED && next != 'O'){
continuousSendLED = false;
}
}
Serial.read(); //discard the byte
}
#endif

View File

@ -88,7 +88,7 @@ bool captivePortal(AsyncWebServerRequest *request)
String hostH;
if (!request->hasHeader("Host")) return false;
hostH = request->getHeader("Host")->value();
if (!isIp(hostH) && hostH.indexOf("wled.me") < 0 && hostH.indexOf(cmDNS) < 0) {
DEBUG_PRINTLN("Captive portal");
AsyncWebServerResponse *response = request->beginResponse(302);
@ -135,14 +135,14 @@ void initServer()
//request->send_P(200, "text/html", PAGE_liveview);
});
#endif
//settings page
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request);
});
// "/settings/settings.js&p=x" request also handled by serveSettings()
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
if (handleIfNoneMatchCacheHeader(request)) return;
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", PAGE_settingsCss, PAGE_settingsCss_length);
@ -150,27 +150,27 @@ void initServer()
setStaticContentCacheHeaders(response);
request->send(response);
});
server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
if(!handleFileRead(request, "/favicon.ico"))
{
request->send_P(200, "image/x-icon", favicon, 156);
}
});
server.on("/sliders", HTTP_GET, [](AsyncWebServerRequest *request){
serveIndex(request);
});
server.on("/welcome", HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request);
});
server.on("/reset", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129);
doReboot = true;
});
server.on("/settings", HTTP_POST, [](AsyncWebServerRequest *request){
serveSettings(request, true);
});
@ -214,7 +214,7 @@ void initServer()
} else {
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
}
}
}
request->send(200, "application/json", F("{\"success\":true}"));
});
server.addHandler(handler);
@ -222,15 +222,15 @@ void initServer()
server.on("/version", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", (String)VERSION);
});
server.on("/uptime", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", (String)millis());
});
server.on("/freeheap", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", (String)ESP.getFreeHeap());
});
server.on("/u", HTTP_GET, [](AsyncWebServerRequest *request){
if (handleIfNoneMatchCacheHeader(request)) return;
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", PAGE_usermod, PAGE_usermod_length);
@ -239,12 +239,12 @@ void initServer()
request->send(response);
//request->send_P(200, "text/html", PAGE_usermod);
});
//Deprecated, use of /json/state and presets recommended instead
server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){
URL_response(request);
});
server.on("/teapot", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
});
@ -271,14 +271,14 @@ void initServer()
setStaticContentCacheHeaders(response);
request->send(response);
});
server.on("/rangetouch.js", HTTP_GET, [](AsyncWebServerRequest *request){
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", rangetouchJs, rangetouchJs_length);
response->addHeader(FPSTR(s_content_enc),"gzip");
setStaticContentCacheHeaders(response);
request->send(response);
});
createEditHandler(correctPIN);
#ifndef WLED_DISABLE_OTA
@ -289,7 +289,7 @@ void initServer()
} else
serveSettings(request); // checks for "upd" in URL and handles PIN
});
server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
if (!correctPIN) {
serveSettings(request, true); // handle PIN page POST request
@ -298,7 +298,7 @@ void initServer()
if (Update.hasError() || otaLock) {
serveMessage(request, 500, F("Update failed!"), F("Please check your file and retry!"), 254);
} else {
serveMessage(request, 200, F("Update successful!"), F("Rebooting..."), 131);
serveMessage(request, 200, F("Update successful!"), F("Rebooting..."), 131);
doReboot = true;
}
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
@ -348,7 +348,7 @@ void initServer()
#ifdef WLED_ENABLE_WEBSOCKETS
server.addHandler(&ws);
#endif
//called when the url is not defined here, ajax-in; get-settings
server.onNotFound([](AsyncWebServerRequest *request){
DEBUG_PRINTLN("Not-Found HTTP call:");
@ -363,7 +363,7 @@ void initServer()
request->send(response);
return;
}
if(handleSet(request, request->url())) return;
#ifndef WLED_DISABLE_ALEXA
if(espalexa.handleAlexaApiCall(request)) return;
@ -471,7 +471,7 @@ void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& h
messageHead = headl;
messageSub = subl;
optionType = optionT;
request->send_P(code, "text/html", PAGE_msg, msgProcessor);
}
@ -493,7 +493,7 @@ String dmxProcessor(const String& var)
mapJS += "0];";
}
#endif
return mapJS;
}
#endif
@ -526,7 +526,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
byte subPage = 0, originalSubPage = 0;
const String& url = request->url();
if (url.indexOf("sett") >= 0)
if (url.indexOf("sett") >= 0)
{
if (url.indexOf(".js") > 0) subPage = 254;
else if (url.indexOf(".css") > 0) subPage = 253;
@ -589,7 +589,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
return;
}
}
AsyncWebServerResponse *response;
switch (subPage)
{
@ -599,10 +599,14 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
case 4: response = request->beginResponse_P(200, "text/html", PAGE_settings_sync, PAGE_settings_sync_length); break;
case 5: response = request->beginResponse_P(200, "text/html", PAGE_settings_time, PAGE_settings_time_length); break;
case 6: response = request->beginResponse_P(200, "text/html", PAGE_settings_sec, PAGE_settings_sec_length); break;
#ifdef WLED_ENABLE_DMX
case 7: response = request->beginResponse_P(200, "text/html", PAGE_settings_dmx, PAGE_settings_dmx_length); break;
#endif
case 8: response = request->beginResponse_P(200, "text/html", PAGE_settings_um, PAGE_settings_um_length); break;
case 9: response = request->beginResponse_P(200, "text/html", PAGE_update, PAGE_update_length); break;
#ifndef WLED_DISABLE_2D
case 10: response = request->beginResponse_P(200, "text/html", PAGE_settings_2D, PAGE_settings_2D_length); break;
#endif
case 251: {
correctPIN = !strlen(settingsPIN); // lock if a pin is set
createEditHandler(correctPIN);

View File

@ -92,7 +92,7 @@ void URL_response(AsyncWebServerRequest *request)
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", col[i]);
oappend(s);
oappend(s);
}
oappend(SET_F("&C2=h"));
for (int i = 0; i < 3; i++)
@ -115,7 +115,7 @@ void URL_response(AsyncWebServerRequest *request)
oappend(SET_F("<html><body><a href=\""));
oappend(s2buf);
oappend(SET_F("\" target=\"_blank\">"));
oappend(s2buf);
oappend(s2buf);
oappend(SET_F("</a></body></html>"));
if (request != nullptr) request->send(200, "text/html", obuf);
@ -287,6 +287,9 @@ void getSettingsJS(byte subPage, char* dest)
if (subPage == 0)
{
#ifndef WLED_DISABLE_2D // include only if 2D is compiled in
oappend(PSTR("gId('2dbtn').style.display='';"));
#endif
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
oappend(PSTR("gId('dmxbtn').style.display='';"));
#endif
@ -505,6 +508,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',SET_F("EM"),e131Multicast);
sappend('v',SET_F("EU"),e131Universe);
sappend('v',SET_F("DA"),DMXAddress);
sappend('v',SET_F("XX"),DMXSegmentSpacing);
sappend('v',SET_F("DM"),DMXMode);
sappend('v',SET_F("ET"),realtimeTimeoutMs);
sappend('c',SET_F("FB"),arlsForceMaxBri);
@ -566,7 +570,7 @@ void getSettingsJS(byte subPage, char* dest)
case HUE_ERROR_TIMEOUT : strcpy_P(hueErrorString,PSTR("Timeout")); break;
default: sprintf_P(hueErrorString,PSTR("Bridge Error %i"),hueError);
}
sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
#else
oappend(SET_F("toggle('Hue');")); // hide Hue Sync settings
@ -658,17 +662,17 @@ void getSettingsJS(byte subPage, char* dest)
oappend(serverDescription);
oappend(SET_F("\";"));
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
if (subPage == 7)
{
sappend('v',SET_F("PU"),e131ProxyUniverse);
sappend('v',SET_F("CN"),DMXChannels);
sappend('v',SET_F("CG"),DMXGap);
sappend('v',SET_F("CS"),DMXStart);
sappend('v',SET_F("SL"),DMXStartLED);
sappend('i',SET_F("CH1"),DMXFixtureMap[0]);
sappend('i',SET_F("CH2"),DMXFixtureMap[1]);
sappend('i',SET_F("CH3"),DMXFixtureMap[2]);