diff --git a/platformio.ini b/platformio.ini
index 97a2d49e..c01d4f15 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -446,7 +446,7 @@ lib_deps = ${esp32c3.lib_deps}
; https://github.com/blazoncek/arduinoFFT.git
[env:esp32s3dev_8MB]
-;; ESP32-S3-DevKitC-1 development board, with 8MB FLASH, no PSRAM
+;; ESP32-S3-DevKitC-1 development board, with 8MB FLASH, no PSRAM (flash_mode: qio)
board = esp32-s3-devkitc-1
;platform = espressif32@5.1.1
;platform_packages = platformio/framework-arduinoespressif32@3.20004.220825
@@ -466,6 +466,26 @@ board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
+[env:esp32s3dev_8MB_PSRAM]
+;; ESP32-TinyS3 development board, with 8MB FLASH and 8MB PSRAM (memory_type: qio_opi, qio_qspi, or opi_opi)
+;board = um_tinys3 ; -> needs workaround from https://github.com/Aircoookie/WLED/pull/2905#issuecomment-1328049860
+;board = esp32s3box ; -> error: 'esp32_adc2gpio' was not declared in this scope
+board = esp32-s3-devkitc-1 ; -> compiles, but does not support PSRAM
+platform = espressif32 @ ~5.2.0
+platform_packages =
+upload_speed = 921600
+build_unflags = ${common.build_unflags}
+build_flags = ${common.build_flags} ${esp32s3.build_flags}
+ -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_MSC_ON_BOOT=0
+ ; -D ARDUINO_USB_CDC_ON_BOOT=0
+ ; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM
+ -D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used
+lib_deps = ${esp32s3.lib_deps}
+board_build.partitions = tools/WLED_ESP32_8MB.csv
+board_build.f_flash = 80000000L
+board_build.flash_mode = qio
+monitor_filters = esp32_exception_decoder
+
[env:esp8285_4CH_MagicHome]
board = esp8285
platform = ${common.platform_wled_default}
diff --git a/usermods/BME280_v2/usermod_bme280.h b/usermods/BME280_v2/usermod_bme280.h
index 6b42fc80..c27adfc8 100644
--- a/usermods/BME280_v2/usermod_bme280.h
+++ b/usermods/BME280_v2/usermod_bme280.h
@@ -16,14 +16,15 @@ private:
// NOTE: Do not implement any compile-time variables, anything the user needs to configure
// should be configurable from the Usermod menu using the methods below
// key settings set via usermod menu
- unsigned long TemperatureDecimals = 0; // Number of decimal places in published temperaure values
- unsigned long HumidityDecimals = 0; // Number of decimal places in published humidity values
- unsigned long PressureDecimals = 0; // Number of decimal places in published pressure values
- unsigned long TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
- unsigned long PressureInterval = 300; // Interval to measure pressure in seconds
+ uint8_t TemperatureDecimals = 0; // Number of decimal places in published temperaure values
+ uint8_t HumidityDecimals = 0; // Number of decimal places in published humidity values
+ uint8_t PressureDecimals = 0; // Number of decimal places in published pressure values
+ uint16_t TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
+ uint16_t PressureInterval = 300; // Interval to measure pressure in seconds
bool PublishAlways = false; // Publish values even when they have not changed
bool UseCelsius = true; // Use Celsius for Reporting
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
+ bool enabled = true;
// set the default pins based on the architecture, these get overridden by Usermod menu settings
#ifdef ESP8266
@@ -70,15 +71,10 @@ private:
// MQTT topic strings for publishing Home Assistant discovery topics
bool mqttInitialized = false;
- String mqttTemperatureTopic = "";
- String mqttHumidityTopic = "";
- String mqttPressureTopic = "";
- String mqttHeatIndexTopic = "";
- String mqttDewPointTopic = "";
- // Store packet IDs of MQTT publications
- uint16_t mqttTemperaturePub = 0;
- uint16_t mqttPressurePub = 0;
+ // strings to reduce flash memory usage (used more than twice)
+ static const char _name[];
+ static const char _enabled[];
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu)
void UpdateBME280Data(int SensorType)
@@ -95,7 +91,7 @@ private:
sensorTemperature = _temperature;
sensorHumidity = _humidity;
sensorPressure = _pressure;
- tempScale = "°C";
+ tempScale = F("°C");
if (sensorType == 1)
{
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
@@ -111,7 +107,7 @@ private:
sensorTemperature = _temperature;
sensorHumidity = _humidity;
sensorPressure = _pressure;
- tempScale = "°F";
+ tempScale = F("°F");
if (sensorType == 1)
{
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
@@ -123,18 +119,23 @@ private:
// Procedure to define all MQTT discovery Topics
void _mqttInitialize()
{
- mqttTemperatureTopic = String(mqttDeviceTopic) + F("/temperature");
- mqttPressureTopic = String(mqttDeviceTopic) + F("/pressure");
- mqttHumidityTopic = String(mqttDeviceTopic) + F("/humidity");
- mqttHeatIndexTopic = String(mqttDeviceTopic) + F("/heat_index");
- mqttDewPointTopic = String(mqttDeviceTopic) + F("/dew_point");
+ char mqttTemperatureTopic[128];
+ char mqttHumidityTopic[128];
+ char mqttPressureTopic[128];
+ char mqttHeatIndexTopic[128];
+ char mqttDewPointTopic[128];
+ snprintf_P(mqttTemperatureTopic, 127, PSTR("%s/temperature"), mqttDeviceTopic);
+ snprintf_P(mqttPressureTopic, 127, PSTR("%s/pressure"), mqttDeviceTopic);
+ snprintf_P(mqttHumidityTopic, 127, PSTR("%s/humidity"), mqttDeviceTopic);
+ snprintf_P(mqttHeatIndexTopic, 127, PSTR("%s/heat_index"), mqttDeviceTopic);
+ snprintf_P(mqttDewPointTopic, 127, PSTR("%s/dew_point"), mqttDeviceTopic);
if (HomeAssistantDiscovery) {
- _createMqttSensor(F("Temperature"), mqttTemperatureTopic, F("temperature"), tempScale);
- _createMqttSensor(F("Pressure"), mqttPressureTopic, F("pressure"), F("hPa"));
- _createMqttSensor(F("Humidity"), mqttHumidityTopic, F("humidity"), F("%"));
- _createMqttSensor(F("HeatIndex"), mqttHeatIndexTopic, F("temperature"), tempScale);
- _createMqttSensor(F("DewPoint"), mqttDewPointTopic, F("temperature"), tempScale);
+ _createMqttSensor(F("Temperature"), mqttTemperatureTopic, "temperature", tempScale);
+ _createMqttSensor(F("Pressure"), mqttPressureTopic, "pressure", F("hPa"));
+ _createMqttSensor(F("Humidity"), mqttHumidityTopic, "humidity", F("%"));
+ _createMqttSensor(F("HeatIndex"), mqttHeatIndexTopic, "temperature", tempScale);
+ _createMqttSensor(F("DewPoint"), mqttDewPointTopic, "temperature", tempScale);
}
}
@@ -169,6 +170,15 @@ private:
mqtt->publish(t.c_str(), 0, true, temp.c_str());
}
+ void publishMqtt(const char *topic, const char* state) {
+ //Check if MQTT Connected, otherwise it will crash the 8266
+ if (WLED_MQTT_CONNECTED){
+ char subuf[128];
+ snprintf_P(subuf, 127, PSTR("%s/%s"), mqttDeviceTopic, topic);
+ mqtt->publish(subuf, 0, false, state);
+ }
+ }
+
public:
void setup()
{
@@ -183,7 +193,7 @@ public:
if (!bme.begin())
{
sensorType = 0;
- DEBUG_PRINTLN(F("Could not find BME280I2C sensor!"));
+ DEBUG_PRINTLN(F("Could not find BME280 I2C sensor!"));
}
else
{
@@ -207,14 +217,16 @@ public:
void loop()
{
+ if (!enabled || strip.isUpdating()) return;
+
// BME280 sensor MQTT publishing
- // Check if sensor present and MQTT Connected, otherwise it will crash the MCU
- if (sensorType != 0 && WLED_MQTT_CONNECTED)
+ // Check if sensor present and Connected, otherwise it will crash the MCU
+ if (sensorType != 0)
{
// Timer to fetch new temperature, humidity and pressure data at intervals
timer = millis();
- if (timer - lastTemperatureMeasure >= TemperatureInterval * 1000 || mqttTemperaturePub == 0)
+ if (timer - lastTemperatureMeasure >= TemperatureInterval * 1000)
{
lastTemperatureMeasure = timer;
@@ -223,18 +235,11 @@ public:
float temperature = roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
float humidity, heatIndex, dewPoint;
- if (WLED_MQTT_CONNECTED && !mqttInitialized)
- {
- _mqttInitialize();
- mqttInitialized = true;
- }
-
// If temperature has changed since last measure, create string populated with device topic
// from the UI and values read from sensor, then publish to broker
if (temperature != lastTemperature || PublishAlways)
{
- String topic = String(mqttDeviceTopic) + "/temperature";
- mqttTemperaturePub = mqtt->publish(topic.c_str(), 0, false, String(temperature, TemperatureDecimals).c_str());
+ publishMqtt("temperature", String(temperature, TemperatureDecimals).c_str());
}
lastTemperature = temperature; // Update last sensor temperature for next loop
@@ -247,20 +252,17 @@ public:
if (humidity != lastHumidity || PublishAlways)
{
- String topic = String(mqttDeviceTopic) + F("/humidity");
- mqtt->publish(topic.c_str(), 0, false, String(humidity, HumidityDecimals).c_str());
+ publishMqtt("humidity", String(humidity, HumidityDecimals).c_str());
}
if (heatIndex != lastHeatIndex || PublishAlways)
{
- String topic = String(mqttDeviceTopic) + F("/heat_index");
- mqtt->publish(topic.c_str(), 0, false, String(heatIndex, TemperatureDecimals).c_str());
+ publishMqtt("heat_index", String(heatIndex, TemperatureDecimals).c_str());
}
if (dewPoint != lastDewPoint || PublishAlways)
{
- String topic = String(mqttDeviceTopic) + F("/dew_point");
- mqtt->publish(topic.c_str(), 0, false, String(dewPoint, TemperatureDecimals).c_str());
+ publishMqtt("dew_point", String(dewPoint, TemperatureDecimals).c_str());
}
lastHumidity = humidity;
@@ -269,7 +271,7 @@ public:
}
}
- if (timer - lastPressureMeasure >= PressureInterval * 1000 || mqttPressurePub == 0)
+ if (timer - lastPressureMeasure >= PressureInterval * 1000)
{
lastPressureMeasure = timer;
@@ -277,15 +279,23 @@ public:
if (pressure != lastPressure || PublishAlways)
{
- String topic = String(mqttDeviceTopic) + F("/pressure");
- mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(pressure, PressureDecimals).c_str());
+ publishMqtt("pressure", String(pressure, PressureDecimals).c_str());
}
lastPressure = pressure;
}
}
}
-
+
+ void onMqttConnect(bool sessionPresent)
+ {
+ if (WLED_MQTT_CONNECTED && !mqttInitialized)
+ {
+ _mqttInitialize();
+ mqttInitialized = true;
+ }
+ }
+
/*
* API calls te enable data exchange between WLED modules
*/
@@ -294,9 +304,9 @@ public:
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
} else {
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
- }
-
+ }
}
+
inline float getTemperatureF() {
if (UseCelsius) {
return ((float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
@@ -304,12 +314,15 @@ public:
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
}
}
+
inline float getHumidity() {
return (float)roundf(sensorHumidity * powf(10, HumidityDecimals));
}
+
inline float getPressure() {
return (float)roundf(sensorPressure * powf(10, PressureDecimals));
}
+
inline float getDewPointC() {
if (UseCelsius) {
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
@@ -317,6 +330,7 @@ public:
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
}
}
+
inline float getDewPointF() {
if (UseCelsius) {
return ((float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
@@ -324,13 +338,16 @@ public:
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
}
}
+
inline float getHeatIndexC() {
if (UseCelsius) {
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
} else {
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
}
- }inline float getHeatIndexF() {
+ }
+
+ inline float getHeatIndexF() {
if (UseCelsius) {
return ((float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
} else {
@@ -384,7 +401,8 @@ public:
// Save Usermod Config Settings
void addToConfig(JsonObject& root)
{
- JsonObject top = root.createNestedObject(F("BME280/BMP280"));
+ JsonObject top = root.createNestedObject(FPSTR(_name));
+ top[FPSTR(_enabled)] = enabled;
top[F("TemperatureDecimals")] = TemperatureDecimals;
top[F("HumidityDecimals")] = HumidityDecimals;
top[F("PressureDecimals")] = PressureDecimals;
@@ -405,17 +423,17 @@ public:
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
-
int8_t newPin[2]; for (byte i=0; i<2; i++) newPin[i] = ioPin[i]; // prepare to note changed pins
- JsonObject top = root[F("BME280/BMP280")];
+ JsonObject top = root[FPSTR(_name)];
if (top.isNull()) {
- DEBUG_PRINT(F("BME280/BMP280"));
+ DEBUG_PRINT(F(_name));
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
return false;
}
bool configComplete = !top.isNull();
+ configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
configComplete &= getJsonValue(top[F("TemperatureDecimals")], TemperatureDecimals, 1);
configComplete &= getJsonValue(top[F("HumidityDecimals")], HumidityDecimals, 0);
@@ -427,7 +445,7 @@ public:
configComplete &= getJsonValue(top[F("HomeAssistantDiscovery")], HomeAssistantDiscovery, false);
for (byte i=0; i<2; i++) configComplete &= getJsonValue(top[F("pin")][i], newPin[i], ioPin[i]);
- DEBUG_PRINT(FPSTR(F("BME280/BMP280")));
+ DEBUG_PRINT(FPSTR(_name));
if (!initDone) {
// first run: reading from cfg.json
for (byte i=0; i<2; i++) ioPin[i] = newPin[i];
@@ -454,4 +472,7 @@ public:
uint16_t getId() {
return USERMOD_ID_BME280;
}
-};
\ No newline at end of file
+};
+
+const char UsermodBME280::_name[] PROGMEM = "BME280/BMP280";
+const char UsermodBME280::_enabled[] PROGMEM = "enabled";
diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h
index 78f63602..17a0a35d 100644
--- a/usermods/audioreactive/audio_reactive.h
+++ b/usermods/audioreactive/audio_reactive.h
@@ -1916,10 +1916,10 @@ class AudioReactive : public Usermod {
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'I2S Master CLK','only use -1, 0, 1 or 3');"));
#else
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'I2S Master CLK','');"));
+ oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'', 'I2S Master CLK');"));
#endif
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',4,'I2C SDA',' ');"));
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',5,'I2C SCL',' ');"));
+ oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',4,'', 'I2C SDA');"));
+ oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',5,'', 'I2C SCL');"));
}
diff --git a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
index 79fef942..cd279410 100644
--- a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
+++ b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h
@@ -1036,11 +1036,11 @@ class FourLineDisplayUsermod : public Usermod {
oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'I2C/SPI CLK','-1 use global');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'I2C/SPI DTA','-1 use global');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'SPI CS',' ');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',3,'SPI DC',' ');"));
- oappend(SET_F("addInfo('4LineDisplay:pin[]',4,'SPI RST',' ');"));
+ oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'-1 use global','I2C/SPI CLK');"));
+ oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'-1 use global','I2C/SPI DTA');"));
+ oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'','SPI CS');"));
+ oappend(SET_F("addInfo('4LineDisplay:pin[]',3,'','SPI DC');"));
+ oappend(SET_F("addInfo('4LineDisplay:pin[]',4,'','SPI RST');"));
}
/*
diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
index 13dd0dea..a6dc0762 100644
--- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
+++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h
@@ -191,7 +191,7 @@ private:
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
- palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount());
+ palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount()); // only use internal palettes
// How many palette names start with '*' and should not be sorted?
// (Also skipping the first one, 'Default').
diff --git a/wled00/FX.h b/wled00/FX.h
index 9d2a6e01..93daa7d6 100644
--- a/wled00/FX.h
+++ b/wled00/FX.h
@@ -777,7 +777,7 @@ class WS2812FX { // 96 bytes
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments
inline uint8_t getCurrSegmentId(void) { return _segment_index; }
inline uint8_t getMainSegmentId(void) { return _mainSegment; }
- inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; }
+ inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
inline uint8_t getTargetFps() { return _targetFps; }
inline uint8_t getModeCount() { return _modeCount; }
diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp
index 55493e3e..bca05903 100644
--- a/wled00/FX_2Dfcn.cpp
+++ b/wled00/FX_2Dfcn.cpp
@@ -122,10 +122,11 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM
#ifndef WLED_DISABLE_2D
if (!isMatrix) return; // not a matrix set-up
uint16_t index = y * matrixWidth + x;
+ if (index >= customMappingSize) return; // customMappingSize is always W * H of matrix in 2D setup
#else
uint16_t index = x;
-#endif
if (index >= _length) return;
+#endif
if (index < customMappingSize) index = customMappingTable[index];
busses.setPixelColor(index, col);
}
@@ -134,10 +135,11 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
#ifndef WLED_DISABLE_2D
uint16_t index = (y * matrixWidth + x);
+ if (index >= customMappingSize) return 0; // customMappingSize is always W * H of matrix in 2D setup
#else
uint16_t index = x;
-#endif
if (index >= _length) return 0;
+#endif
if (index < customMappingSize) index = customMappingTable[index];
return busses.getPixelColor(index);
}
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index 4d13224d..b9164885 100644
--- a/wled00/FX_fcn.cpp
+++ b/wled00/FX_fcn.cpp
@@ -425,12 +425,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
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 && (size_t)sOpt < strip.getPaletteCount() + strip.customPalettes.size()) {
- if (sOpt != palette) {
- palette = sOpt;
- }
- }
+ sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt);
}
stateChanged = true; // send UDP/WS broadcast
}
@@ -438,13 +433,13 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
}
void Segment::setPalette(uint8_t pal) {
- if (pal < strip.getPaletteCount()) {
- if (pal != palette) {
- if (strip.paletteFade) startTransition(strip.getTransition());
- palette = pal;
- }
+ if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes
+ if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes
+ if (pal != palette) {
+ if (strip.paletteFade) startTransition(strip.getTransition());
+ palette = pal;
+ stateChanged = true; // send UDP/WS broadcast
}
- stateChanged = true; // send UDP/WS broadcast
}
// 2D matrix
diff --git a/wled00/data/index.js b/wled00/data/index.js
index c4566648..3615b8d8 100644
--- a/wled00/data/index.js
+++ b/wled00/data/index.js
@@ -1560,8 +1560,8 @@ function requestJson(command=null)
if (json.info) {
let i = json.info;
// append custom palettes (when loading for the 1st time)
- if (!command && isEmpty(lastinfo) && i.leds && i.leds.cpal) {
- for (let j = 0; j()) strlcpy(quickLoad, sObj[F("ql")].as(), 3); // only 2 chars for QL
+ if (sObj[F("ql")].is()) strlcpy(quickLoad, sObj[F("ql")].as(), 9); // client limits QL to 2 chars, buffer for 8 bytes to allow unicode
sObj.remove("v");
sObj.remove("time");
sObj.remove(F("error"));
diff --git a/wled00/udp.cpp b/wled00/udp.cpp
index cc0cb22b..2d1388f8 100644
--- a/wled00/udp.cpp
+++ b/wled00/udp.cpp
@@ -411,10 +411,10 @@ void handleNotifications()
for (size_t i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
- if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);
+ seg.setMode(udpIn[8]);
seg.speed = udpIn[9];
if (version > 2) seg.intensity = udpIn[16];
- if (version > 4 && udpIn[19] < strip.getPaletteCount()) seg.palette = udpIn[19];
+ if (version > 4) seg.setPalette(udpIn[19]);
}
stateChanged = true;
}
diff --git a/wled00/wled.h b/wled00/wled.h
index 8ca29ef4..76b108f7 100644
--- a/wled00/wled.h
+++ b/wled00/wled.h
@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
-#define VERSION 2211242
+#define VERSION 2211250
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG