Merge branch 'MoonModules:mdev' into Strip_Level_Color_Adjust
This commit is contained in:
@@ -3194,7 +3194,13 @@ static uint16_t mode_popcorn_core(bool useaudio) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
//allocate segment data
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
uint16_t dataSize = sizeof(spark) * maxNumPopcorn;
|
||||
size_t dataSize = sizeof(spark) * maxNumPopcorn;
|
||||
uint8_t neededPopcorn = maxNumPopcorn; // WLEDMM
|
||||
if (strips > 8) { // WLEDMM more than 8 virtual strips --> reduce memory requirements to minimum necessary
|
||||
neededPopcorn = (SEGMENT.intensity*maxNumPopcorn)/255;
|
||||
neededPopcorn = min(max(neededPopcorn, uint8_t(2)), uint8_t(maxNumPopcorn));
|
||||
dataSize = sizeof(spark) * neededPopcorn;
|
||||
}
|
||||
if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed
|
||||
|
||||
Spark* popcorn = reinterpret_cast<Spark*>(SEGENV.data);
|
||||
@@ -3212,7 +3218,7 @@ static uint16_t mode_popcorn_core(bool useaudio) {
|
||||
|
||||
struct virtualStrip {
|
||||
static void runStrip(uint16_t stripNr, Spark* popcorn, bool useaudio, um_data_t *um_data) { // WLEDMM added useaudio and um_data
|
||||
float gravity = -0.0001 - (SEGMENT.speed/200000.0); // m/s/s
|
||||
float gravity = -0.0001f - (SEGMENT.speed/200000.0f); // m/s/s
|
||||
gravity *= SEGLEN;
|
||||
|
||||
uint8_t numPopcorn = SEGMENT.intensity*maxNumPopcorn/255;
|
||||
@@ -3267,7 +3273,7 @@ static uint16_t mode_popcorn_core(bool useaudio) {
|
||||
};
|
||||
|
||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||
virtualStrip::runStrip(stripNr, &popcorn[stripNr * maxNumPopcorn], useaudio, um_data); // WLEDMM added useaudio and um_data
|
||||
virtualStrip::runStrip(stripNr, &popcorn[stripNr * neededPopcorn], useaudio, um_data); // WLEDMM added useaudio and um_data
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ void WS2812FX::setUpMatrix() {
|
||||
}
|
||||
|
||||
USER_PRINTF("setUpMatrix %d x %d\n", Segment::maxWidth, Segment::maxHeight);
|
||||
|
||||
|
||||
//WLEDMM recreate customMappingTable if more space needed
|
||||
if (Segment::maxWidth * Segment::maxHeight > customMappingTableSize) {
|
||||
size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight));//TroyHack
|
||||
size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight)); // TroyHacks
|
||||
USER_PRINTF("setupmatrix customMappingTable alloc %d from %d\n", size, customMappingTableSize);
|
||||
//if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||
//customMappingTable = new uint16_t[size];
|
||||
@@ -80,7 +80,10 @@ void WS2812FX::setUpMatrix() {
|
||||
if ((size > 0) && (customMappingTable == nullptr)) { // second try
|
||||
DEBUG_PRINTLN("setUpMatrix: trying to get fresh memory block.");
|
||||
customMappingTable = (uint16_t*) calloc(size, sizeof(uint16_t));
|
||||
if (customMappingTable == nullptr) USER_PRINTLN("setUpMatrix: alloc failed");
|
||||
if (customMappingTable == nullptr) {
|
||||
USER_PRINTLN("setUpMatrix: alloc failed");
|
||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
}
|
||||
}
|
||||
if (customMappingTable != nullptr) customMappingTableSize = size;
|
||||
}
|
||||
@@ -159,6 +162,7 @@ void WS2812FX::setUpMatrix() {
|
||||
} else { // memory allocation error
|
||||
customMappingTableSize = 0;
|
||||
USER_PRINTLN(F("Ledmap alloc error."));
|
||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
isMatrix = false; //WLEDMM does not like this done in teh background while end users are confused whats happened...
|
||||
panels = 0;
|
||||
panel.clear();
|
||||
|
||||
@@ -115,7 +115,7 @@ Segment::Segment(const Segment &orig) {
|
||||
|
||||
//WLEDMM: recreate ledsrgb if more space needed (will not free ledsrgb!)
|
||||
void Segment::allocLeds() {
|
||||
size_t size = sizeof(CRGB)*max((size_t) length(), ledmapMaxSize); //TroyHack
|
||||
size_t size = sizeof(CRGB)*max((size_t) length(), ledmapMaxSize); // TroyHacks
|
||||
if ((size < sizeof(CRGB)) || (size > 164000)) { //softhack too small (<3) or too large (>160Kb)
|
||||
DEBUG_PRINTF("allocLeds warning: size == %u !!\n", size);
|
||||
if (ledsrgb && (ledsrgbSize == 0)) {
|
||||
@@ -128,10 +128,13 @@ void Segment::allocLeds() {
|
||||
if (ledsrgb) free(ledsrgb); // we need a bigger buffer, so free the old one first
|
||||
ledsrgb = (CRGB*)calloc(size, 1);
|
||||
ledsrgbSize = ledsrgb?size:0;
|
||||
if (ledsrgb == nullptr) USER_PRINTLN("allocLeds failed!!");
|
||||
if (ledsrgb == nullptr) {
|
||||
USER_PRINTLN("allocLeds failed!!");
|
||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
}
|
||||
}
|
||||
else {
|
||||
USER_PRINTF("reuse Leds %u from %u\n", size, ledsrgb?ledsrgbSize:0);
|
||||
//USER_PRINTF("reuse Leds %u from %u\n", size, ledsrgb?ledsrgbSize:0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +215,11 @@ bool Segment::allocateData(size_t len) {
|
||||
//DEBUG_PRINTF("allocateData(%u) start %d, stop %d, vlen %d\n", len, start, stop, virtualLength());
|
||||
deallocateData();
|
||||
if (len == 0) return false; // nothing to do
|
||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) {
|
||||
//USER_PRINTF("Segment::allocateData: Segment data quota exceeded! used:%u request:%u max:%d\n", Segment::getUsedSegmentData(), len, MAX_SEGMENT_DATA);
|
||||
if (len > 0) errorFlag = ERR_LOW_SEG_MEM; // WLEDMM raise errorflag
|
||||
return false; //not enough memory
|
||||
}
|
||||
// do not use SPI RAM on ESP32 since it is slow
|
||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
||||
//if (psramFound())
|
||||
@@ -220,10 +227,17 @@ bool Segment::allocateData(size_t len) {
|
||||
//else
|
||||
//#endif
|
||||
data = (byte*) malloc(len);
|
||||
if (!data) { _dataLen = 0; return false;} //allocation failed // WLEDMM reset dataLen
|
||||
if (!data) {
|
||||
_dataLen = 0; // WLEDMM reset dataLen
|
||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
USER_PRINT(F("Segment::allocateData: FAILED to allocate "));
|
||||
USER_PRINT(len); USER_PRINTLN(F(" bytes."));
|
||||
return false;
|
||||
} //allocation failed
|
||||
Segment::addUsedSegmentData(len);
|
||||
_dataLen = len;
|
||||
memset(data, 0, len);
|
||||
if (errorFlag == ERR_LOW_SEG_MEM) errorFlag = ERR_NONE; // WLEDMM reset errorflag on success
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -231,7 +245,7 @@ void Segment::deallocateData() {
|
||||
if (!data) {_dataLen = 0; return;} // WLEDMM reset dataLen
|
||||
free(data);
|
||||
data = nullptr;
|
||||
//DEBUG_PRINTLN("deallocateData() called free().");
|
||||
//USER_PRINTF("Segment::deallocateData: free'd %d bytes.\n", _dataLen);
|
||||
Segment::addUsedSegmentData(-_dataLen);
|
||||
_dataLen = 0;
|
||||
}
|
||||
@@ -482,6 +496,8 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
|
||||
&& (!grp || (grouping == grp && spacing == spc))
|
||||
&& (ofs == UINT16_MAX || ofs == offset)) return;
|
||||
|
||||
stateChanged = true; // send UDP/WS broadcast
|
||||
|
||||
if (stop>start) fill(BLACK); //turn old segment range off // WLEDMM stop > start
|
||||
if (i2 <= i1) { //disable segment
|
||||
stop = 0;
|
||||
@@ -1536,7 +1552,7 @@ void WS2812FX::enumerateLedmaps() {
|
||||
|
||||
USER_PRINTF("enumerateLedmaps %s \"%s\"", fileName, name);
|
||||
if (isMatrix) {
|
||||
//WLEDMM calc ledmapMaxSize (TroyHack)
|
||||
//WLEDMM calc ledmapMaxSize (TroyHacks)
|
||||
char dim[34] = { '\0' };
|
||||
f.find("\"width\":");
|
||||
f.readBytesUntil('\n', dim, sizeof(dim)-1); //hack: use fileName as we have this allocated already
|
||||
@@ -1654,6 +1670,7 @@ void WS2812FX::finalizeInit(void)
|
||||
//#endif
|
||||
if (arrSize > 0) Segment::_globalLeds = (CRGB*) malloc(arrSize); // WLEDMM avoid malloc(0)
|
||||
if ((Segment::_globalLeds != nullptr) && (arrSize > 0)) memset(Segment::_globalLeds, 0, arrSize); // WLEDMM avoid dereferencing nullptr
|
||||
if ((Segment::_globalLeds == nullptr) && (arrSize > 0)) errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
}
|
||||
|
||||
//segments are created in makeAutoSegments();
|
||||
@@ -2273,16 +2290,16 @@ void WS2812FX::loadCustomPalettes() {
|
||||
|
||||
if (readObjectFromFile(fileName, nullptr, &pDoc)) {
|
||||
JsonArray pal = pDoc[F("palette")];
|
||||
if (!pal.isNull() && pal.size()>4) { // not an empty palette (at least 2 entries)
|
||||
if (!pal.isNull() && pal.size()>3) { // not an empty palette (at least 2 entries)
|
||||
if (pal[0].is<int>() && pal[1].is<const char *>()) {
|
||||
// we have an array of index & hex strings
|
||||
size_t palSize = min(pal.size(), (size_t)36); // WLEDMM use native min/max
|
||||
palSize -= palSize % 2; // make sure size is multiple of 2
|
||||
for (size_t i=0, j=0; i<palSize && pal[i].as<int>()<256; i+=2, j+=4) {
|
||||
for (unsigned i=0, j=0; i<palSize && pal[i].as<int>()<256; i+=2, j+=4) {
|
||||
uint8_t rgbw[] = {0,0,0,0};
|
||||
tcp[ j ] = (uint8_t) pal[ i ].as<int>(); // index
|
||||
colorFromHexString(rgbw, pal[i+1].as<const char *>()); // will catch non-string entires
|
||||
for (size_t c=0; c<3; c++) tcp[j+1+c] = rgbw[c]; // only use RGB component
|
||||
for (unsigned c=0; c<3; c++) tcp[j+1+c] = gamma8(rgbw[c]); // only use RGB component
|
||||
DEBUG_PRINTF("%d(%d) : %d %d %d\n", i, int(tcp[j]), int(tcp[j+1]), int(tcp[j+2]), int(tcp[j+3]));
|
||||
}
|
||||
} else {
|
||||
@@ -2290,13 +2307,15 @@ void WS2812FX::loadCustomPalettes() {
|
||||
palSize -= palSize % 4; // make sure size is multiple of 4
|
||||
for (size_t i=0; i<palSize && pal[i].as<int>()<256; i+=4) {
|
||||
tcp[ i ] = (uint8_t) pal[ i ].as<int>(); // index
|
||||
tcp[i+1] = (uint8_t) pal[i+1].as<int>(); // R
|
||||
tcp[i+2] = (uint8_t) pal[i+2].as<int>(); // G
|
||||
tcp[i+3] = (uint8_t) pal[i+3].as<int>(); // B
|
||||
tcp[i+1] = gamma8((uint8_t) pal[i+1].as<int>()); // R
|
||||
tcp[i+2] = gamma8((uint8_t) pal[i+2].as<int>()); // G
|
||||
tcp[i+3] = gamma8((uint8_t) pal[i+3].as<int>()); // B
|
||||
DEBUG_PRINTF("%d(%d) : %d %d %d\n", i, int(tcp[i]), int(tcp[i+1]), int(tcp[i+2]), int(tcp[i+3]));
|
||||
}
|
||||
}
|
||||
customPalettes.push_back(targetPalette.loadDynamicGradientPalette(tcp));
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Wrong palette format."));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -2387,7 +2406,7 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
|
||||
//WLEDMM recreate customMappingTable if more space needed
|
||||
if (Segment::maxWidth * Segment::maxHeight > customMappingTableSize) {
|
||||
size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight));//TroyHack
|
||||
size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight)); // TroyHacks
|
||||
USER_PRINTF("deserializemap customMappingTable alloc %u from %u\n", size, customMappingTableSize);
|
||||
//if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||
//customMappingTable = new uint16_t[size];
|
||||
@@ -2399,7 +2418,10 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
if ((size > 0) && (customMappingTable == nullptr)) { // second try
|
||||
DEBUG_PRINTLN("deserializeMap: trying to get fresh memory block.");
|
||||
customMappingTable = (uint16_t*) calloc(size, sizeof(uint16_t));
|
||||
if (customMappingTable == nullptr) DEBUG_PRINTLN("deserializeMap: alloc failed!");
|
||||
if (customMappingTable == nullptr) {
|
||||
DEBUG_PRINTLN("deserializeMap: alloc failed!");
|
||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
}
|
||||
}
|
||||
if (customMappingTable != nullptr) customMappingTableSize = size;
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
#define USERMOD_ID_WEATHER 91 //Usermod "usermod_v2_weather.h"
|
||||
#define USERMOD_ID_GAMES 92 //Usermod "usermod_v2_games.h"
|
||||
#define USERMOD_ID_ANIMARTRIX 93 //Usermod "usermod_v2_animartrix.h"
|
||||
#define USERMOD_ID_AUTOPLAYLIST 94 // Usermod usermod_v2_auto_playlist.h
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
@@ -347,7 +348,9 @@
|
||||
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
|
||||
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
|
||||
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
|
||||
#define ERR_LOW_MEM 33 // low memory (RAM)
|
||||
#define ERR_LOW_MEM 33 // WLEDMM: low memory (RAM)
|
||||
#define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
|
||||
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
|
||||
|
||||
// Timer mode types
|
||||
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
|
||||
@@ -494,7 +497,10 @@
|
||||
#define DEFAULT_LED_COUNT 30
|
||||
#endif
|
||||
|
||||
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
|
||||
#define INTERFACE_UPDATE_COOLDOWN 1200 // time in ms to wait between websockets, alexa, and MQTT updates
|
||||
|
||||
#define PIN_RETRY_COOLDOWN 3000 // time in ms after an incorrect attempt PIN and OTA pass will be rejected even if correct
|
||||
#define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes
|
||||
|
||||
// HW_PIN_SCL & HW_PIN_SDA are used for information in usermods settings page and usermods themselves
|
||||
// which GPIO pins are actually used in a hardware layout (controller board)
|
||||
|
||||
@@ -1968,8 +1968,14 @@ function readState(s,command=false)
|
||||
errstr = "A filesystem error has occured.";
|
||||
break;
|
||||
case 33:
|
||||
errstr = "Warning: Low Memory (RAM).";
|
||||
break;
|
||||
errstr = "Low Memory (generic RAM).";
|
||||
break;
|
||||
case 34:
|
||||
errstr = "Low Memory (effect data).";
|
||||
break;
|
||||
case 35:
|
||||
errstr = "Low Memory (WS data).";
|
||||
break;
|
||||
}
|
||||
showToast('Error ' + s.error + ": " + errstr, true);
|
||||
}
|
||||
|
||||
@@ -231,11 +231,16 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
|
||||
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);}
|
||||
if ((e131_data[dataOffset+5] & 0b00000010) != seg.reverse_y) { seg.setOption(SEG_OPTION_REVERSED_Y, e131_data[dataOffset+5] & 0b00000010); }
|
||||
if ((e131_data[dataOffset+5] & 0b00000100) != seg.mirror_y) { seg.setOption(SEG_OPTION_MIRROR_Y, e131_data[dataOffset+5] & 0b00000100); }
|
||||
if ((e131_data[dataOffset+5] & 0b00001000) != seg.transpose) { seg.setOption(SEG_OPTION_TRANSPOSED, e131_data[dataOffset+5] & 0b00001000); }
|
||||
if ((e131_data[dataOffset+5] & 0b00110000) / 8 != seg.map1D2D) {
|
||||
seg.map1D2D = (e131_data[dataOffset+5] & 0b00110000) / 8;
|
||||
}
|
||||
// To maintain backwards compatibility with prior e1.31 values, reverse is fixed to mask 0x01000000
|
||||
if ((e131_data[dataOffset+5] & 0b01000000) != seg.reverse) { seg.setOption(SEG_OPTION_REVERSED, e131_data[dataOffset+5] & 0b01000000); }
|
||||
// To maintain backwards compatibility with prior e1.31 values, mirror is fixed to mask 0x10000000
|
||||
if ((e131_data[dataOffset+5] & 0b10000000) != seg.mirror) { seg.setOption(SEG_OPTION_MIRROR, e131_data[dataOffset+5] & 0b10000000); }
|
||||
|
||||
uint32_t colors[3];
|
||||
byte whites[3] = {0,0,0};
|
||||
|
||||
@@ -208,6 +208,7 @@ void _overlayAnalogCountdown();
|
||||
void _overlayAnalogClock();
|
||||
|
||||
//playlist.cpp
|
||||
void suspendPlaylist(); // WLEDMM support function for auto playlist usermod
|
||||
void shufflePlaylist();
|
||||
void unloadPlaylist();
|
||||
int16_t loadPlaylist(JsonObject playlistObject, byte presetId = 0);
|
||||
@@ -370,9 +371,11 @@ void releaseJSONBufferLock();
|
||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen, uint8_t *var = nullptr);
|
||||
int16_t extractModeDefaults(uint8_t mode, const char *segVar);
|
||||
void checkSettingsPIN(const char *pin);
|
||||
uint16_t __attribute__((pure)) crc16(const unsigned char* data_p, size_t length); // WLEDMM: added attribute pure
|
||||
um_data_t* simulateSound(uint8_t simulationId);
|
||||
// WLEDMM enumerateLedmaps(); moved to FX.h
|
||||
uint8_t get_random_wheel_index(uint8_t pos);
|
||||
CRGB getCRGBForBand(int x, uint8_t *fftResult, int pal); //WLEDMM netmindz ar palette
|
||||
char *cleanUpName(char *in); // to clean up a name that was read from file
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
|
||||
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
||||
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
||||
char vString[32];
|
||||
snprintf_P(vString, sizeof(vString)-1, PSTR("0.14.1-b30.36/%i"),VERSION);
|
||||
snprintf_P(vString, sizeof(vString)-1, PSTR("0.14.1-b30.37/%i"),VERSION);
|
||||
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
||||
|
||||
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
||||
|
||||
@@ -105,6 +105,7 @@ void stateUpdated(byte callMode) {
|
||||
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);
|
||||
if (bri != briOld && nodeBroadcastEnabled) sendSysInfoUDP(); // update on state
|
||||
|
||||
//set flag to update ws and mqtt
|
||||
interfaceUpdateCallMode = callMode;
|
||||
@@ -139,6 +140,8 @@ void stateUpdated(byte callMode) {
|
||||
jsonTransitionOnce = false;
|
||||
strip.setTransition(transitionDelayTemp);
|
||||
if (transitionDelayTemp == 0) {
|
||||
jsonTransitionOnce = false;
|
||||
transitionActive = false;
|
||||
applyFinalBri();
|
||||
strip.trigger();
|
||||
return;
|
||||
@@ -161,8 +164,12 @@ void stateUpdated(byte callMode) {
|
||||
|
||||
void updateInterfaces(uint8_t callMode)
|
||||
{
|
||||
if (!interfaceUpdateCallMode || millis() - lastInterfaceUpdate < INTERFACE_UPDATE_COOLDOWN) return;
|
||||
|
||||
sendDataWs();
|
||||
lastInterfaceUpdate = millis();
|
||||
interfaceUpdateCallMode = 0; //disable
|
||||
|
||||
if (callMode == CALL_MODE_WS_SEND) return;
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
@@ -172,14 +179,13 @@ void updateInterfaces(uint8_t callMode)
|
||||
}
|
||||
#endif
|
||||
doPublishMqtt = true;
|
||||
interfaceUpdateCallMode = 0; //disable
|
||||
}
|
||||
|
||||
|
||||
void handleTransitions()
|
||||
{
|
||||
//handle still pending interface update
|
||||
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > INTERFACE_UPDATE_COOLDOWN) updateInterfaces(interfaceUpdateCallMode);
|
||||
updateInterfaces(interfaceUpdateCallMode);
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
if (doPublishMqtt) publishMqtt();
|
||||
#endif
|
||||
@@ -190,12 +196,15 @@ void handleTransitions()
|
||||
if (tper >= 1.0f)
|
||||
{
|
||||
strip.setTransitionMode(false);
|
||||
// restore (global) transition time if not called from UDP notifier or single/temporary transition from JSON (also playlist)
|
||||
if (jsonTransitionOnce) strip.setTransition(transitionDelay);
|
||||
transitionActive = false;
|
||||
jsonTransitionOnce = false;
|
||||
tperLast = 0;
|
||||
applyFinalBri();
|
||||
return;
|
||||
}
|
||||
if (tper - tperLast < 0.004) return;
|
||||
if (tper - tperLast < 0.004f) return;
|
||||
tperLast = tper;
|
||||
briT = briOld + ((bri - briOld) * tper);
|
||||
|
||||
@@ -205,7 +214,7 @@ void handleTransitions()
|
||||
|
||||
|
||||
// legacy method, applies values from col, effectCurrent, ... to selected segments
|
||||
void colorUpdated(byte callMode){
|
||||
void colorUpdated(byte callMode) {
|
||||
applyValuesToSelectedSegs();
|
||||
stateUpdated(callMode);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,12 @@ void shufflePlaylist() {
|
||||
DEBUG_PRINTLN(F("Playlist shuffle."));
|
||||
}
|
||||
|
||||
// WLEDMM supporting function for auto_playlist usermod
|
||||
// prevents the active playlist from progressing (until it gets unloaded)
|
||||
static bool playlistSuspended = false;
|
||||
void suspendPlaylist() {
|
||||
playlistSuspended = true;
|
||||
}
|
||||
|
||||
void unloadPlaylist() {
|
||||
if (playlistEntries != nullptr) {
|
||||
@@ -49,6 +55,7 @@ void unloadPlaylist() {
|
||||
}
|
||||
currentPlaylist = playlistIndex = -1;
|
||||
playlistLen = playlistEntryDur = playlistOptions = 0;
|
||||
playlistSuspended = false; // WLEDMM
|
||||
DEBUG_PRINTLN(F("Playlist unloaded."));
|
||||
}
|
||||
|
||||
@@ -125,6 +132,11 @@ void handlePlaylist() {
|
||||
// if fileDoc is not null JSON buffer is in use so just quit
|
||||
if (currentPlaylist < 0 || playlistEntries == nullptr || fileDoc != nullptr) return;
|
||||
|
||||
if (playlistSuspended) { // WLEDMM
|
||||
if (millis() - presetCycledTime > (100*playlistEntryDur)) presetCycledTime = millis(); // keep updating timer
|
||||
return; // but don't progress to next extry, and don't shuffle
|
||||
}
|
||||
|
||||
if (millis() - presetCycledTime > (100*playlistEntryDur)) {
|
||||
presetCycledTime = millis();
|
||||
if (bri == 0 || nightlightActive) return;
|
||||
|
||||
@@ -712,6 +712,7 @@ void sendSysInfoUDP()
|
||||
#else
|
||||
data[38] = NODE_TYPE_ID_UNDEFINED;
|
||||
#endif
|
||||
if (bri) data[38] |= 0x80U; // add on/off state
|
||||
data[39] = ip[3]; // unit ID == last IP number
|
||||
|
||||
uint32_t build = VERSION;
|
||||
|
||||
@@ -203,6 +203,9 @@
|
||||
#ifdef USERMOD_ANIMARTRIX
|
||||
#include "../usermods/usermod_v2_animartrix/usermod_v2_animartrix.h"
|
||||
#endif
|
||||
#ifdef USERMOD_AUTO_PLAYLIST
|
||||
#include "../usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h"
|
||||
#endif
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
@@ -402,4 +405,9 @@ void registerUsermods()
|
||||
usermods.add(new AnimartrixUsermod("Animartrix", false));
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUTO_PLAYLIST
|
||||
usermods.add(new AutoPlaylistUsermod(false));
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ bool requestJSONBufferLock(uint8_t module)
|
||||
{
|
||||
unsigned long now = millis();
|
||||
|
||||
while (jsonBufferLock && millis()-now < 1200) delay(1); // wait for fraction for buffer lock
|
||||
while (jsonBufferLock && millis()-now < 1100) delay(1); // wait for fraction for buffer lock
|
||||
|
||||
if (jsonBufferLock) {
|
||||
USER_PRINT(F("ERROR: Locking JSON buffer failed! (still locked by "));
|
||||
@@ -239,9 +239,10 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
||||
{
|
||||
if (src == JSON_mode_names || src == nullptr) {
|
||||
if (mode < strip.getModeCount()) {
|
||||
char lineBuffer[256];
|
||||
char lineBuffer[256] = { '\0' };
|
||||
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
||||
strcpy_P(lineBuffer, strip.getModeData(mode));
|
||||
strncpy_P(lineBuffer, strip.getModeData(mode), sizeof(lineBuffer)/sizeof(char)-1);
|
||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
||||
size_t len = strlen(lineBuffer);
|
||||
size_t j = 0;
|
||||
for (; j < maxLen && j < len; j++) {
|
||||
@@ -253,6 +254,12 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
if (src == JSON_palette_names && mode > GRADIENT_PALETTE_COUNT) {
|
||||
snprintf_P(dest, maxLen, PSTR("~ Custom %d~"), 255-mode);
|
||||
dest[maxLen-1] = '\0';
|
||||
return strlen(dest);
|
||||
}
|
||||
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
@@ -363,9 +370,9 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
|
||||
int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
||||
{
|
||||
if (mode < strip.getModeCount()) {
|
||||
char lineBuffer[128] = "";
|
||||
strncpy_P(lineBuffer, strip.getModeData(mode), 127);
|
||||
lineBuffer[127] = '\0'; // terminate string
|
||||
char lineBuffer[256] = { '\0' };
|
||||
strncpy_P(lineBuffer, strip.getModeData(mode), sizeof(lineBuffer)/sizeof(char)-1);
|
||||
lineBuffer[sizeof(lineBuffer)/sizeof(char)-1] = '\0'; // terminate string
|
||||
if (lineBuffer[0] != 0) {
|
||||
char* startPtr = strrchr(lineBuffer, ';'); // last ";" in FX data
|
||||
if (!startPtr) return -1;
|
||||
@@ -381,6 +388,16 @@ int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
||||
}
|
||||
|
||||
|
||||
void checkSettingsPIN(const char* pin) {
|
||||
if (!pin) return;
|
||||
if (!correctPIN && millis() - lastEditTime < PIN_RETRY_COOLDOWN) return; // guard against PIN brute force
|
||||
bool correctBefore = correctPIN;
|
||||
correctPIN = (strlen(settingsPIN) == 0 || strncmp(settingsPIN, pin, 4) == 0);
|
||||
if (correctBefore != correctPIN) createEditHandler(correctPIN);
|
||||
lastEditTime = millis();
|
||||
}
|
||||
|
||||
|
||||
uint16_t crc16(const unsigned char* data_p, size_t length) {
|
||||
uint8_t x;
|
||||
uint16_t crc = 0xFFFF;
|
||||
@@ -401,9 +418,9 @@ uint16_t crc16(const unsigned char* data_p, size_t length) {
|
||||
// (only 2 used as stored in 1 bit in segment options, consider switching to a single global simulation type)
|
||||
typedef enum UM_SoundSimulations {
|
||||
UMS_BeatSin = 0,
|
||||
UMS_WeWillRockYou
|
||||
//UMS_10_13,
|
||||
//UMS_14_3
|
||||
UMS_WeWillRockYou,
|
||||
UMS_10_13,
|
||||
UMS_14_3
|
||||
} um_soundSimulations_t;
|
||||
|
||||
um_data_t* simulateSound(uint8_t simulationId)
|
||||
@@ -491,7 +508,7 @@ um_data_t* simulateSound(uint8_t simulationId)
|
||||
fftResult[i] = 0;
|
||||
}
|
||||
break;
|
||||
/*case UMS_10_3:
|
||||
case UMS_10_13:
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3);
|
||||
volumeSmth = fftResult[8];
|
||||
@@ -500,11 +517,11 @@ um_data_t* simulateSound(uint8_t simulationId)
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3);
|
||||
volumeSmth = fftResult[8];
|
||||
break;*/
|
||||
break;
|
||||
}
|
||||
|
||||
samplePeak = random8() > 250;
|
||||
FFT_MajorPeak = 21 + (volumeSmth*volumeSmth) / 8.0f; // WLEDMM 21hz...8200hz
|
||||
FFT_MajorPeak = 21 + (volumeSmth*volumeSmth) / 8.0f; // walk thru full range of 21hz...8200hz
|
||||
maxVol = 31; // this gets feedback fro UI
|
||||
binNum = 8; // this gets feedback fro UI
|
||||
volumeRaw = volumeSmth;
|
||||
@@ -545,6 +562,20 @@ CRGB getCRGBForBand(int x, uint8_t *fftResult, int pal) {
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new, random color wheel index with a minimum distance of 42 from pos.
|
||||
*/
|
||||
uint8_t get_random_wheel_index(uint8_t pos) {
|
||||
uint8_t r = 0, x = 0, y = 0, d = 0;
|
||||
while (d < 42) {
|
||||
r = random8();
|
||||
x = abs(pos - r);
|
||||
y = 255 - x;
|
||||
d = MIN(x, y);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// WLEDMM extended "trim string" function to support enumerateLedmaps
|
||||
// The function takes char* as input, and removes all leading and trailing "decorations" like spaces, tabs, line endings, quotes, colons
|
||||
// The conversion is "in place" (destructive).
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2402252
|
||||
#define VERSION 2404161
|
||||
|
||||
// WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED.
|
||||
#define _MoonModules_WLED_
|
||||
|
||||
@@ -220,6 +220,8 @@ void initServer()
|
||||
|
||||
if (verboseResponse) {
|
||||
if (!isConfig) {
|
||||
lastInterfaceUpdate = millis(); // prevent WS update until cooldown
|
||||
interfaceUpdateCallMode = CALL_MODE_WS_SEND; // schedule WS update
|
||||
serveJson(request); return; //if JSON contains "v"
|
||||
} else {
|
||||
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
||||
|
||||
@@ -62,14 +62,15 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
||||
}
|
||||
releaseJSONBufferLock(); // will clean fileDoc
|
||||
|
||||
// force broadcast in 500ms after updating client
|
||||
if (verboseResponse) {
|
||||
sendDataWs(client);
|
||||
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
||||
} else {
|
||||
// we have to send something back otherwise WS connection closes
|
||||
client->text(F("{\"success\":true}"));
|
||||
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
||||
if (!interfaceUpdateCallMode) { // individual client response only needed if no WS broadcast soon
|
||||
if (verboseResponse) {
|
||||
sendDataWs(client);
|
||||
} else {
|
||||
// we have to send something back otherwise WS connection closes
|
||||
client->text(F("{\"success\":true}"));
|
||||
}
|
||||
// force broadcast in 500ms after updating client
|
||||
//lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500); // ESP8266 does not like this
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -161,6 +162,7 @@ void sendDataWs(AsyncWebSocketClient * client)
|
||||
ws.closeAll(1013); //code 1013 = temporary overload, try again later
|
||||
ws.cleanupClients(0); //disconnect all clients to release memory
|
||||
ws._cleanBuffers();
|
||||
errorFlag = ERR_LOW_WS_MEM;
|
||||
return; //out of memory
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user