mirror of
https://github.com/wled/WLED.git
synced 2025-04-24 06:47:18 +00:00
Merge branch '0_15' into blending-styles
This commit is contained in:
commit
fafb2eba69
@ -116,7 +116,8 @@ async function minify(str, type = "plain") {
|
||||
} else if (type == "css-minify") {
|
||||
return new CleanCSS({}).minify(str).styles;
|
||||
} else if (type == "js-minify") {
|
||||
return await minifyHtml('<script>' + str + '</script>', options).replace(/<[\/]*script>/g, '');
|
||||
let js = await minifyHtml('<script>' + str + '</script>', options);
|
||||
return js.replace(/<[\/]*script>/g, '');
|
||||
} else if (type == "html-minify") {
|
||||
return await minifyHtml(str, options);
|
||||
}
|
||||
@ -252,6 +253,12 @@ writeChunks(
|
||||
str
|
||||
.replace("%%", "%")
|
||||
},
|
||||
{
|
||||
file: "common.js",
|
||||
name: "JS_common",
|
||||
method: "gzip",
|
||||
filter: "js-minify",
|
||||
},
|
||||
{
|
||||
file: "settings.htm",
|
||||
name: "PAGE_settings",
|
||||
|
@ -332,7 +332,7 @@ class Animated_Staircase : public Usermod {
|
||||
};
|
||||
// NOTE: this *WILL* return TRUE if all the pins are set to -1.
|
||||
// this is *BY DESIGN*.
|
||||
if (!pinManager.allocateMultiplePins(pins, 4, PinOwner::UM_AnimatedStaircase)) {
|
||||
if (!PinManager::allocateMultiplePins(pins, 4, PinOwner::UM_AnimatedStaircase)) {
|
||||
topPIRorTriggerPin = -1;
|
||||
topEchoPin = -1;
|
||||
bottomPIRorTriggerPin = -1;
|
||||
@ -513,10 +513,10 @@ class Animated_Staircase : public Usermod {
|
||||
(oldBottomAPin != bottomPIRorTriggerPin) ||
|
||||
(oldBottomBPin != bottomEchoPin)) {
|
||||
changed = true;
|
||||
pinManager.deallocatePin(oldTopAPin, PinOwner::UM_AnimatedStaircase);
|
||||
pinManager.deallocatePin(oldTopBPin, PinOwner::UM_AnimatedStaircase);
|
||||
pinManager.deallocatePin(oldBottomAPin, PinOwner::UM_AnimatedStaircase);
|
||||
pinManager.deallocatePin(oldBottomBPin, PinOwner::UM_AnimatedStaircase);
|
||||
PinManager::deallocatePin(oldTopAPin, PinOwner::UM_AnimatedStaircase);
|
||||
PinManager::deallocatePin(oldTopBPin, PinOwner::UM_AnimatedStaircase);
|
||||
PinManager::deallocatePin(oldBottomAPin, PinOwner::UM_AnimatedStaircase);
|
||||
PinManager::deallocatePin(oldBottomBPin, PinOwner::UM_AnimatedStaircase);
|
||||
}
|
||||
if (changed) setup();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ Before compiling, you have to make the following modifications:
|
||||
Edit `usermods_list.cpp`:
|
||||
1. Open `wled00/usermods_list.cpp`
|
||||
2. add `#include "../usermods/Animated_Staircase/Animated_Staircase.h"` to the top of the file
|
||||
3. add `usermods.add(new Animated_Staircase());` to the end of the `void registerUsermods()` function.
|
||||
3. add `UsermodManager::add(new Animated_Staircase());` to the end of the `void registerUsermods()` function.
|
||||
|
||||
You can configure usermod using the Usermods settings page.
|
||||
Please enter GPIO pins for PIR or ultrasonic sensors (trigger and echo).
|
||||
|
@ -200,7 +200,7 @@ class UsermodBattery : public Usermod
|
||||
bool success = false;
|
||||
DEBUG_PRINTLN(F("Allocating battery pin..."));
|
||||
if (batteryPin >= 0 && digitalPinToAnalogChannel(batteryPin) >= 0)
|
||||
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
|
||||
if (PinManager::allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
|
||||
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
|
||||
success = true;
|
||||
}
|
||||
@ -561,7 +561,7 @@ class UsermodBattery : public Usermod
|
||||
if (newBatteryPin != batteryPin)
|
||||
{
|
||||
// deallocate pin
|
||||
pinManager.deallocatePin(batteryPin, PinOwner::UM_Battery);
|
||||
PinManager::deallocatePin(batteryPin, PinOwner::UM_Battery);
|
||||
batteryPin = newBatteryPin;
|
||||
// initialise
|
||||
setup();
|
||||
|
@ -71,7 +71,7 @@ class MyExampleUsermod : public Usermod {
|
||||
// #endif
|
||||
// in setup()
|
||||
// #ifdef USERMOD_EXAMPLE
|
||||
// UM = (MyExampleUsermod*) usermods.lookup(USERMOD_ID_EXAMPLE);
|
||||
// UM = (MyExampleUsermod*) UsermodManager::lookup(USERMOD_ID_EXAMPLE);
|
||||
// #endif
|
||||
// somewhere in loop() or other member method
|
||||
// #ifdef USERMOD_EXAMPLE
|
||||
|
@ -59,10 +59,10 @@ void registerUsermods()
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//usermods.add(new UsermodTemperature());
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
usermods.add(new FixUnreachableNetServices());
|
||||
//UsermodManager::add(new MyExampleUsermod());
|
||||
//UsermodManager::add(new UsermodTemperature());
|
||||
//UsermodManager::add(new UsermodRenameMe());
|
||||
UsermodManager::add(new FixUnreachableNetServices());
|
||||
|
||||
}
|
||||
```
|
||||
|
@ -30,7 +30,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod {
|
||||
void setup() {
|
||||
// register ldrPin
|
||||
if ((ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0)) {
|
||||
if(!pinManager.allocatePin(ldrPin, false, PinOwner::UM_LDR_DUSK_DAWN)) ldrEnabled = false; // pin already in use -> disable usermod
|
||||
if(!PinManager::allocatePin(ldrPin, false, PinOwner::UM_LDR_DUSK_DAWN)) ldrEnabled = false; // pin already in use -> disable usermod
|
||||
else pinMode(ldrPin, INPUT); // alloc success -> configure pin for input
|
||||
} else ldrEnabled = false; // invalid pin -> disable usermod
|
||||
initDone = true;
|
||||
@ -110,7 +110,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod {
|
||||
|
||||
if (initDone && (ldrPin != oldLdrPin)) {
|
||||
// pin changed - un-register previous pin, register new pin
|
||||
if (oldLdrPin >= 0) pinManager.deallocatePin(oldLdrPin, PinOwner::UM_LDR_DUSK_DAWN);
|
||||
if (oldLdrPin >= 0) PinManager::deallocatePin(oldLdrPin, PinOwner::UM_LDR_DUSK_DAWN);
|
||||
setup(); // setup new pin
|
||||
}
|
||||
return configComplete;
|
||||
@ -139,7 +139,7 @@ class LDR_Dusk_Dawn_v2 : public Usermod {
|
||||
//LDR_Off_Count.add(ldrOffCount);
|
||||
|
||||
//bool pinValid = ((ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0));
|
||||
//if (pinManager.getPinOwner(ldrPin) != PinOwner::UM_LDR_DUSK_DAWN) pinValid = false;
|
||||
//if (PinManager::getPinOwner(ldrPin) != PinOwner::UM_LDR_DUSK_DAWN) pinValid = false;
|
||||
//JsonArray LDR_valid = user.createNestedArray(F("LDR pin"));
|
||||
//LDR_valid.add(ldrPin);
|
||||
//LDR_valid.add(pinValid ? F(" OK"): F(" invalid"));
|
||||
|
@ -52,7 +52,7 @@ class MyUsermod : public Usermod {
|
||||
|
||||
void togglePIRSensor() {
|
||||
#ifdef USERMOD_PIR_SENSOR_SWITCH
|
||||
PIRsensorSwitch *PIRsensor = (PIRsensorSwitch::*) usermods.lookup(USERMOD_ID_PIRSWITCH);
|
||||
PIRsensorSwitch *PIRsensor = (PIRsensorSwitch::*) UsermodManager::lookup(USERMOD_ID_PIRSWITCH);
|
||||
if (PIRsensor != nullptr) {
|
||||
PIRsensor->EnablePIRsensor(!PIRsensor->PIRsensorEnabled());
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ void PIRsensorSwitch::setup()
|
||||
sensorPinState[i] = LOW;
|
||||
if (PIRsensorPin[i] < 0) continue;
|
||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||
if (pinManager.allocatePin(PIRsensorPin[i], false, PinOwner::UM_PIR)) {
|
||||
if (PinManager::allocatePin(PIRsensorPin[i], false, PinOwner::UM_PIR)) {
|
||||
// PIR Sensor mode INPUT_PULLDOWN
|
||||
#ifdef ESP8266
|
||||
pinMode(PIRsensorPin[i], PIRsensorPin[i]==16 ? INPUT_PULLDOWN_16 : INPUT_PULLUP); // ESP8266 has INPUT_PULLDOWN on GPIO16 only
|
||||
@ -564,7 +564,7 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root)
|
||||
DEBUG_PRINTLN(F(" config loaded."));
|
||||
} else {
|
||||
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++)
|
||||
if (oldPin[i] >= 0) pinManager.deallocatePin(oldPin[i], PinOwner::UM_PIR);
|
||||
if (oldPin[i] >= 0) PinManager::deallocatePin(oldPin[i], PinOwner::UM_PIR);
|
||||
setup();
|
||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ class PWMFanUsermod : public Usermod {
|
||||
static const char _lock[];
|
||||
|
||||
void initTacho(void) {
|
||||
if (tachoPin < 0 || !pinManager.allocatePin(tachoPin, false, PinOwner::UM_Unspecified)){
|
||||
if (tachoPin < 0 || !PinManager::allocatePin(tachoPin, false, PinOwner::UM_Unspecified)){
|
||||
tachoPin = -1;
|
||||
return;
|
||||
}
|
||||
@ -88,7 +88,7 @@ class PWMFanUsermod : public Usermod {
|
||||
void deinitTacho(void) {
|
||||
if (tachoPin < 0) return;
|
||||
detachInterrupt(digitalPinToInterrupt(tachoPin));
|
||||
pinManager.deallocatePin(tachoPin, PinOwner::UM_Unspecified);
|
||||
PinManager::deallocatePin(tachoPin, PinOwner::UM_Unspecified);
|
||||
tachoPin = -1;
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ class PWMFanUsermod : public Usermod {
|
||||
|
||||
// https://randomnerdtutorials.com/esp32-pwm-arduino-ide/
|
||||
void initPWMfan(void) {
|
||||
if (pwmPin < 0 || !pinManager.allocatePin(pwmPin, true, PinOwner::UM_Unspecified)) {
|
||||
if (pwmPin < 0 || !PinManager::allocatePin(pwmPin, true, PinOwner::UM_Unspecified)) {
|
||||
enabled = false;
|
||||
pwmPin = -1;
|
||||
return;
|
||||
@ -121,7 +121,7 @@ class PWMFanUsermod : public Usermod {
|
||||
analogWriteRange(255);
|
||||
analogWriteFreq(WLED_PWM_FREQ);
|
||||
#else
|
||||
pwmChannel = pinManager.allocateLedc(1);
|
||||
pwmChannel = PinManager::allocateLedc(1);
|
||||
if (pwmChannel == 255) { //no more free LEDC channels
|
||||
deinitPWMfan(); return;
|
||||
}
|
||||
@ -136,9 +136,9 @@ class PWMFanUsermod : public Usermod {
|
||||
void deinitPWMfan(void) {
|
||||
if (pwmPin < 0) return;
|
||||
|
||||
pinManager.deallocatePin(pwmPin, PinOwner::UM_Unspecified);
|
||||
PinManager::deallocatePin(pwmPin, PinOwner::UM_Unspecified);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
pinManager.deallocateLedc(pwmChannel, 1);
|
||||
PinManager::deallocateLedc(pwmChannel, 1);
|
||||
#endif
|
||||
pwmPin = -1;
|
||||
}
|
||||
@ -191,9 +191,9 @@ class PWMFanUsermod : public Usermod {
|
||||
void setup() override {
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
// This Usermod requires Temperature usermod
|
||||
tempUM = (UsermodTemperature*) usermods.lookup(USERMOD_ID_TEMPERATURE);
|
||||
tempUM = (UsermodTemperature*) UsermodManager::lookup(USERMOD_ID_TEMPERATURE);
|
||||
#elif defined(USERMOD_SHT)
|
||||
tempUM = (ShtUsermod*) usermods.lookup(USERMOD_ID_SHT);
|
||||
tempUM = (ShtUsermod*) UsermodManager::lookup(USERMOD_ID_SHT);
|
||||
#endif
|
||||
initTacho();
|
||||
initPWMfan();
|
||||
|
@ -9,6 +9,6 @@
|
||||
void registerUsermods()
|
||||
{
|
||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||
usermods.add(new Usermod_SN_Photoresistor());
|
||||
UsermodManager::add(new Usermod_SN_Photoresistor());
|
||||
#endif
|
||||
}
|
@ -138,10 +138,10 @@ class St7789DisplayUsermod : public Usermod {
|
||||
void setup() override
|
||||
{
|
||||
PinManagerPinType spiPins[] = { { spi_mosi, true }, { spi_miso, false}, { spi_sclk, true } };
|
||||
if (!pinManager.allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { enabled = false; return; }
|
||||
if (!PinManager::allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { enabled = false; return; }
|
||||
PinManagerPinType displayPins[] = { { TFT_CS, true}, { TFT_DC, true}, { TFT_RST, true }, { TFT_BL, true } };
|
||||
if (!pinManager.allocateMultiplePins(displayPins, sizeof(displayPins)/sizeof(PinManagerPinType), PinOwner::UM_FourLineDisplay)) {
|
||||
pinManager.deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI);
|
||||
if (!PinManager::allocateMultiplePins(displayPins, sizeof(displayPins)/sizeof(PinManagerPinType), PinOwner::UM_FourLineDisplay)) {
|
||||
PinManager::deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI);
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ class UsermodTemperature : public Usermod {
|
||||
void publishHomeAssistantAutodiscovery();
|
||||
#endif
|
||||
|
||||
static UsermodTemperature* _instance; // to overcome nonstatic getTemperatureC() method and avoid usermods.lookup(USERMOD_ID_TEMPERATURE);
|
||||
static UsermodTemperature* _instance; // to overcome nonstatic getTemperatureC() method and avoid UsermodManager::lookup(USERMOD_ID_TEMPERATURE);
|
||||
|
||||
public:
|
||||
|
||||
@ -223,14 +223,14 @@ void UsermodTemperature::setup() {
|
||||
// config says we are enabled
|
||||
DEBUG_PRINTLN(F("Allocating temperature pin..."));
|
||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||
if (temperaturePin >= 0 && pinManager.allocatePin(temperaturePin, true, PinOwner::UM_Temperature)) {
|
||||
if (temperaturePin >= 0 && PinManager::allocatePin(temperaturePin, true, PinOwner::UM_Temperature)) {
|
||||
oneWire = new OneWire(temperaturePin);
|
||||
if (oneWire->reset()) {
|
||||
while (!findSensor() && retries--) {
|
||||
delay(25); // try to find sensor
|
||||
}
|
||||
}
|
||||
if (parasite && pinManager.allocatePin(parasitePin, true, PinOwner::UM_Temperature)) {
|
||||
if (parasite && PinManager::allocatePin(parasitePin, true, PinOwner::UM_Temperature)) {
|
||||
pinMode(parasitePin, OUTPUT);
|
||||
digitalWrite(parasitePin, LOW); // deactivate power (close MOSFET)
|
||||
} else {
|
||||
@ -423,9 +423,9 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
|
||||
DEBUG_PRINTLN(F("Re-init temperature."));
|
||||
// deallocate pin and release memory
|
||||
delete oneWire;
|
||||
pinManager.deallocatePin(temperaturePin, PinOwner::UM_Temperature);
|
||||
PinManager::deallocatePin(temperaturePin, PinOwner::UM_Temperature);
|
||||
temperaturePin = newTemperaturePin;
|
||||
pinManager.deallocatePin(parasitePin, PinOwner::UM_Temperature);
|
||||
PinManager::deallocatePin(parasitePin, PinOwner::UM_Temperature);
|
||||
// initialise
|
||||
setup();
|
||||
}
|
||||
@ -461,13 +461,13 @@ const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx";
|
||||
const char UsermodTemperature::_sensor[] PROGMEM = "sensor";
|
||||
const char UsermodTemperature::_temperature[] PROGMEM = "temperature";
|
||||
const char UsermodTemperature::_Temperature[] PROGMEM = "/temperature";
|
||||
const char UsermodTemperature::_data_fx[] PROGMEM = "Temperature@Min,Max;;!;01;pal=54";
|
||||
const char UsermodTemperature::_data_fx[] PROGMEM = "Temperature@Min,Max;;!;01;pal=54,sx=255,ix=0";
|
||||
|
||||
static uint16_t mode_temperature() {
|
||||
float low = mapf((float)SEGMENT.speed, 0.f, 255.f, -150.f, 149.9f); // default: 0°C, range: -15°C to 15°C
|
||||
float high = mapf((float)SEGMENT.intensity, 0.f, 255.f, 150.f, 450.f); // default: 30°C, range 15°C to 45°C
|
||||
float temp = constrain(UsermodTemperature::getInstance()->getTemperatureC()*10.f, low, high); // get a little better resolution
|
||||
unsigned i = map(temp, (unsigned)low, (unsigned)high, 0, 255);
|
||||
float low = roundf(mapf((float)SEGMENT.speed, 0.f, 255.f, -150.f, 150.f)); // default: 15°C, range: -15°C to 15°C
|
||||
float high = roundf(mapf((float)SEGMENT.intensity, 0.f, 255.f, 300.f, 600.f)); // default: 30°C, range 30°C to 60°C
|
||||
float temp = constrain(UsermodTemperature::getInstance()->getTemperatureC()*10.f, low, high); // get a little better resolution (*10)
|
||||
unsigned i = map(roundf(temp), (unsigned)low, (unsigned)high, 0, 248);
|
||||
SEGMENT.fill(SEGMENT.color_from_palette(i, false, false, 255));
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
@ -194,8 +194,8 @@ class I2SSource : public AudioSource {
|
||||
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE) {
|
||||
DEBUGSR_PRINTLN(F("I2SSource:: initialize()."));
|
||||
if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) {
|
||||
if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
|
||||
!pinManager.allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206
|
||||
if (!PinManager::allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
|
||||
!PinManager::allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206
|
||||
DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pins: ws=%d, sd=%d\n", i2swsPin, i2ssdPin);
|
||||
return;
|
||||
}
|
||||
@ -203,7 +203,7 @@ class I2SSource : public AudioSource {
|
||||
|
||||
// i2ssckPin needs special treatment, since it might be unused on PDM mics
|
||||
if (i2sckPin != I2S_PIN_NO_CHANGE) {
|
||||
if (!pinManager.allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) {
|
||||
if (!PinManager::allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) {
|
||||
DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pins: sck=%d\n", i2sckPin);
|
||||
return;
|
||||
}
|
||||
@ -249,7 +249,7 @@ class I2SSource : public AudioSource {
|
||||
// Reserve the master clock pin if provided
|
||||
_mclkPin = mclkPin;
|
||||
if (mclkPin != I2S_PIN_NO_CHANGE) {
|
||||
if(!pinManager.allocatePin(mclkPin, true, PinOwner::UM_Audioreactive)) {
|
||||
if(!PinManager::allocatePin(mclkPin, true, PinOwner::UM_Audioreactive)) {
|
||||
DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pin: MCLK=%d\n", mclkPin);
|
||||
return;
|
||||
} else
|
||||
@ -307,11 +307,11 @@ class I2SSource : public AudioSource {
|
||||
DEBUGSR_PRINTF("Failed to uninstall i2s driver: %d\n", err);
|
||||
return;
|
||||
}
|
||||
if (_pinConfig.ws_io_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.ws_io_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.data_in_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.data_in_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.bck_io_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.bck_io_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.ws_io_num != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_pinConfig.ws_io_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.data_in_num != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_pinConfig.data_in_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.bck_io_num != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_pinConfig.bck_io_num, PinOwner::UM_Audioreactive);
|
||||
// Release the master clock pin
|
||||
if (_mclkPin != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_mclkPin, PinOwner::UM_Audioreactive);
|
||||
if (_mclkPin != I2S_PIN_NO_CHANGE) PinManager::deallocatePin(_mclkPin, PinOwner::UM_Audioreactive);
|
||||
}
|
||||
|
||||
virtual void getSamples(float *buffer, uint16_t num_samples) {
|
||||
@ -589,7 +589,7 @@ class I2SAdcSource : public I2SSource {
|
||||
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
DEBUGSR_PRINTLN(F("I2SAdcSource:: initialize()."));
|
||||
_myADCchannel = 0x0F;
|
||||
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
||||
if(!PinManager::allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
||||
DEBUGSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin);
|
||||
return;
|
||||
}
|
||||
@ -717,7 +717,7 @@ class I2SAdcSource : public I2SSource {
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
pinManager.deallocatePin(_audioPin, PinOwner::UM_Audioreactive);
|
||||
PinManager::deallocatePin(_audioPin, PinOwner::UM_Audioreactive);
|
||||
_initialized = false;
|
||||
_myADCchannel = 0x0F;
|
||||
|
||||
|
@ -86,6 +86,6 @@ Example **usermods_list.cpp**:
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
usermods.add(new MPU6050Driver());
|
||||
UsermodManager::add(new MPU6050Driver());
|
||||
}
|
||||
```
|
||||
|
@ -163,7 +163,7 @@ class GyroSurge : public Usermod {
|
||||
void loop() {
|
||||
// get IMU data
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_IMU)) {
|
||||
if (!UsermodManager::getUMData(&um_data, USERMOD_ID_IMU)) {
|
||||
// Apply max
|
||||
strip.getSegment(0).fadeToBlackBy(max);
|
||||
return;
|
||||
|
@ -164,7 +164,7 @@ class MPU6050Driver : public Usermod {
|
||||
if (i2c_scl<0 || i2c_sda<0) { DEBUG_PRINTLN(F("MPU6050: I2C is no good.")); return; }
|
||||
// Check the interrupt pin
|
||||
if (config.interruptPin >= 0) {
|
||||
irqBound = pinManager.allocatePin(config.interruptPin, false, PinOwner::UM_IMU);
|
||||
irqBound = PinManager::allocatePin(config.interruptPin, false, PinOwner::UM_IMU);
|
||||
if (!irqBound) { DEBUG_PRINTLN(F("MPU6050: IRQ pin already in use.")); return; }
|
||||
pinMode(config.interruptPin, INPUT);
|
||||
};
|
||||
@ -408,7 +408,7 @@ class MPU6050Driver : public Usermod {
|
||||
// Previously loaded and config changed
|
||||
if (irqBound && ((old_cfg.interruptPin != config.interruptPin) || !config.enabled)) {
|
||||
detachInterrupt(old_cfg.interruptPin);
|
||||
pinManager.deallocatePin(old_cfg.interruptPin, PinOwner::UM_IMU);
|
||||
PinManager::deallocatePin(old_cfg.interruptPin, PinOwner::UM_IMU);
|
||||
irqBound = false;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ Example `usermods_list.cpp`:
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
usermods.add(new UsermodMqttSwitch());
|
||||
UsermodManager::add(new UsermodMqttSwitch());
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -41,7 +41,7 @@ When a relay is switched, a message is published:
|
||||
|
||||
## Usermod installation
|
||||
|
||||
1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `usermods.add(new MultiRelay());` at the bottom of `usermods_list.cpp`.
|
||||
1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `UsermodManager::add(new MultiRelay());` at the bottom of `usermods_list.cpp`.
|
||||
or
|
||||
2. Use `#define USERMOD_MULTI_RELAY` in wled.h or `-D USERMOD_MULTI_RELAY` in your platformio.ini
|
||||
|
||||
@ -90,9 +90,9 @@ void registerUsermods()
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//usermods.add(new UsermodTemperature());
|
||||
usermods.add(new MultiRelay());
|
||||
//UsermodManager::add(new MyExampleUsermod());
|
||||
//UsermodManager::add(new UsermodTemperature());
|
||||
UsermodManager::add(new MultiRelay());
|
||||
|
||||
}
|
||||
```
|
||||
|
@ -516,7 +516,7 @@ void MultiRelay::setup() {
|
||||
if (!_relay[i].external) _relay[i].state = !offMode;
|
||||
state |= (uint8_t)(_relay[i].invert ? !_relay[i].state : _relay[i].state) << pin;
|
||||
} else if (_relay[i].pin<100 && _relay[i].pin>=0) {
|
||||
if (pinManager.allocatePin(_relay[i].pin,true, PinOwner::UM_MultiRelay)) {
|
||||
if (PinManager::allocatePin(_relay[i].pin,true, PinOwner::UM_MultiRelay)) {
|
||||
if (!_relay[i].external) _relay[i].state = !offMode;
|
||||
switchRelay(i, _relay[i].state);
|
||||
_relay[i].active = false;
|
||||
@ -817,7 +817,7 @@ bool MultiRelay::readFromConfig(JsonObject &root) {
|
||||
// deallocate all pins 1st
|
||||
for (int i=0; i<MULTI_RELAY_MAX_RELAYS; i++)
|
||||
if (oldPin[i]>=0 && oldPin[i]<100) {
|
||||
pinManager.deallocatePin(oldPin[i], PinOwner::UM_MultiRelay);
|
||||
PinManager::deallocatePin(oldPin[i], PinOwner::UM_MultiRelay);
|
||||
}
|
||||
// allocate new pins
|
||||
setup();
|
||||
|
@ -112,15 +112,15 @@ class PixelsDiceTrayUsermod : public Usermod {
|
||||
SetSPIPinsFromMacros();
|
||||
PinManagerPinType spiPins[] = {
|
||||
{spi_mosi, true}, {spi_miso, false}, {spi_sclk, true}};
|
||||
if (!pinManager.allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) {
|
||||
if (!PinManager::allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) {
|
||||
enabled = false;
|
||||
} else {
|
||||
PinManagerPinType displayPins[] = {
|
||||
{TFT_CS, true}, {TFT_DC, true}, {TFT_RST, true}, {TFT_BL, true}};
|
||||
if (!pinManager.allocateMultiplePins(
|
||||
if (!PinManager::allocateMultiplePins(
|
||||
displayPins, sizeof(displayPins) / sizeof(PinManagerPinType),
|
||||
PinOwner::UM_FourLineDisplay)) {
|
||||
pinManager.deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI);
|
||||
PinManager::deallocateMultiplePins(spiPins, 3, PinOwner::HW_SPI);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +29,13 @@ class PwmOutput {
|
||||
return;
|
||||
|
||||
DEBUG_PRINTF("pwm_output[%d]: setup to freq %d\n", pin_, freq_);
|
||||
if (!pinManager.allocatePin(pin_, true, PinOwner::UM_PWM_OUTPUTS))
|
||||
if (!PinManager::allocatePin(pin_, true, PinOwner::UM_PWM_OUTPUTS))
|
||||
return;
|
||||
|
||||
channel_ = pinManager.allocateLedc(1);
|
||||
channel_ = PinManager::allocateLedc(1);
|
||||
if (channel_ == 255) {
|
||||
DEBUG_PRINTF("pwm_output[%d]: failed to quire ledc\n", pin_);
|
||||
pinManager.deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS);
|
||||
PinManager::deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -49,9 +49,9 @@ class PwmOutput {
|
||||
DEBUG_PRINTF("pwm_output[%d]: close\n", pin_);
|
||||
if (!enabled_)
|
||||
return;
|
||||
pinManager.deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS);
|
||||
PinManager::deallocatePin(pin_, PinOwner::UM_PWM_OUTPUTS);
|
||||
if (channel_ != 255)
|
||||
pinManager.deallocateLedc(channel_, 1);
|
||||
PinManager::deallocateLedc(channel_, 1);
|
||||
channel_ = 255;
|
||||
duty_ = 0.0f;
|
||||
enabled_ = false;
|
||||
|
@ -129,7 +129,7 @@ class QuinLEDAnPentaUsermod : public Usermod
|
||||
void initOledDisplay()
|
||||
{
|
||||
PinManagerPinType pins[5] = { { oledSpiClk, true }, { oledSpiData, true }, { oledSpiCs, true }, { oledSpiDc, true }, { oledSpiRst, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 5, PinOwner::UM_QuinLEDAnPenta)) {
|
||||
if (!PinManager::allocateMultiplePins(pins, 5, PinOwner::UM_QuinLEDAnPenta)) {
|
||||
DEBUG_PRINTF("[%s] OLED pin allocation failed!\n", _name);
|
||||
oledEnabled = oledInitDone = false;
|
||||
return;
|
||||
@ -164,11 +164,11 @@ class QuinLEDAnPentaUsermod : public Usermod
|
||||
oledDisplay->clear();
|
||||
}
|
||||
|
||||
pinManager.deallocatePin(oledSpiClk, PinOwner::UM_QuinLEDAnPenta);
|
||||
pinManager.deallocatePin(oledSpiData, PinOwner::UM_QuinLEDAnPenta);
|
||||
pinManager.deallocatePin(oledSpiCs, PinOwner::UM_QuinLEDAnPenta);
|
||||
pinManager.deallocatePin(oledSpiDc, PinOwner::UM_QuinLEDAnPenta);
|
||||
pinManager.deallocatePin(oledSpiRst, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(oledSpiClk, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(oledSpiData, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(oledSpiCs, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(oledSpiDc, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(oledSpiRst, PinOwner::UM_QuinLEDAnPenta);
|
||||
|
||||
delete oledDisplay;
|
||||
|
||||
@ -184,7 +184,7 @@ class QuinLEDAnPentaUsermod : public Usermod
|
||||
void initSht30TempHumiditySensor()
|
||||
{
|
||||
PinManagerPinType pins[2] = { { shtSda, true }, { shtScl, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_QuinLEDAnPenta)) {
|
||||
if (!PinManager::allocateMultiplePins(pins, 2, PinOwner::UM_QuinLEDAnPenta)) {
|
||||
DEBUG_PRINTF("[%s] SHT30 pin allocation failed!\n", _name);
|
||||
shtEnabled = shtInitDone = false;
|
||||
return;
|
||||
@ -212,8 +212,8 @@ class QuinLEDAnPentaUsermod : public Usermod
|
||||
sht30TempHumidSensor->reset();
|
||||
}
|
||||
|
||||
pinManager.deallocatePin(shtSda, PinOwner::UM_QuinLEDAnPenta);
|
||||
pinManager.deallocatePin(shtScl, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(shtSda, PinOwner::UM_QuinLEDAnPenta);
|
||||
PinManager::deallocatePin(shtScl, PinOwner::UM_QuinLEDAnPenta);
|
||||
|
||||
delete sht30TempHumidSensor;
|
||||
|
||||
|
@ -40,7 +40,7 @@ class RgbRotaryEncoderUsermod : public Usermod
|
||||
void initRotaryEncoder()
|
||||
{
|
||||
PinManagerPinType pins[2] = { { eaIo, false }, { ebIo, false } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_RGBRotaryEncoder)) {
|
||||
if (!PinManager::allocateMultiplePins(pins, 2, PinOwner::UM_RGBRotaryEncoder)) {
|
||||
eaIo = -1;
|
||||
ebIo = -1;
|
||||
cleanup();
|
||||
@ -108,11 +108,11 @@ class RgbRotaryEncoderUsermod : public Usermod
|
||||
{
|
||||
// Only deallocate pins if we allocated them ;)
|
||||
if (eaIo != -1) {
|
||||
pinManager.deallocatePin(eaIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
PinManager::deallocatePin(eaIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
eaIo = -1;
|
||||
}
|
||||
if (ebIo != -1) {
|
||||
pinManager.deallocatePin(ebIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
PinManager::deallocatePin(ebIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
ebIo = -1;
|
||||
}
|
||||
|
||||
@ -303,8 +303,8 @@ class RgbRotaryEncoderUsermod : public Usermod
|
||||
}
|
||||
|
||||
if (eaIo != oldEaIo || ebIo != oldEbIo || stepsPerClick != oldStepsPerClick || incrementPerClick != oldIncrementPerClick) {
|
||||
pinManager.deallocatePin(oldEaIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
pinManager.deallocatePin(oldEbIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
PinManager::deallocatePin(oldEaIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
PinManager::deallocatePin(oldEbIo, PinOwner::UM_RGBRotaryEncoder);
|
||||
|
||||
delete rotaryEncoder;
|
||||
initRotaryEncoder();
|
||||
|
@ -45,7 +45,7 @@ class UsermodSdCard : public Usermod {
|
||||
{ configPinPico, true }
|
||||
};
|
||||
|
||||
if (!pinManager.allocateMultiplePins(pins, 4, PinOwner::UM_SdCard)) {
|
||||
if (!PinManager::allocateMultiplePins(pins, 4, PinOwner::UM_SdCard)) {
|
||||
DEBUG_PRINTF("[%s] SD (SPI) pin allocation failed!\n", _name);
|
||||
sdInitDone = false;
|
||||
return;
|
||||
@ -75,10 +75,10 @@ class UsermodSdCard : public Usermod {
|
||||
SD_ADAPTER.end();
|
||||
|
||||
DEBUG_PRINTF("[%s] deallocate pins!\n", _name);
|
||||
pinManager.deallocatePin(configPinSourceSelect, PinOwner::UM_SdCard);
|
||||
pinManager.deallocatePin(configPinSourceClock, PinOwner::UM_SdCard);
|
||||
pinManager.deallocatePin(configPinPoci, PinOwner::UM_SdCard);
|
||||
pinManager.deallocatePin(configPinPico, PinOwner::UM_SdCard);
|
||||
PinManager::deallocatePin(configPinSourceSelect, PinOwner::UM_SdCard);
|
||||
PinManager::deallocatePin(configPinSourceClock, PinOwner::UM_SdCard);
|
||||
PinManager::deallocatePin(configPinPoci, PinOwner::UM_SdCard);
|
||||
PinManager::deallocatePin(configPinPico, PinOwner::UM_SdCard);
|
||||
|
||||
sdInitDone = false;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ public:
|
||||
_setAllFalse();
|
||||
|
||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||
ptr = (Usermod_SN_Photoresistor*) usermods.lookup(USERMOD_ID_SN_PHOTORESISTOR);
|
||||
ptr = (Usermod_SN_Photoresistor*) UsermodManager::lookup(USERMOD_ID_SN_PHOTORESISTOR);
|
||||
#endif
|
||||
DEBUG_PRINTLN(F("Setup done"));
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class AutoSaveUsermod : public Usermod {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
// This Usermod has enhanced functionality if
|
||||
// FourLineDisplayUsermod is available.
|
||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
display = (FourLineDisplayUsermod*) UsermodManager::lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
#endif
|
||||
initDone = true;
|
||||
if (enabled && applyAutoSaveOnBoot) applyPreset(autoSavePreset);
|
||||
|
@ -543,7 +543,7 @@ void FourLineDisplayUsermod::setup() {
|
||||
type = NONE;
|
||||
} else {
|
||||
PinManagerPinType cspins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
|
||||
if (!pinManager.allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { type = NONE; }
|
||||
if (!PinManager::allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { type = NONE; }
|
||||
}
|
||||
} else {
|
||||
if (i2c_scl<0 || i2c_sda<0) { type=NONE; }
|
||||
@ -569,7 +569,7 @@ void FourLineDisplayUsermod::setup() {
|
||||
if (nullptr == u8x8) {
|
||||
DEBUG_PRINTLN(F("Display init failed."));
|
||||
if (isSPI) {
|
||||
pinManager.deallocateMultiplePins((const uint8_t*)ioPin, 3, PinOwner::UM_FourLineDisplay);
|
||||
PinManager::deallocateMultiplePins((const uint8_t*)ioPin, 3, PinOwner::UM_FourLineDisplay);
|
||||
}
|
||||
type = NONE;
|
||||
return;
|
||||
@ -1307,7 +1307,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
|
||||
bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64 || type == SSD1309_SPI64);
|
||||
bool newSPI = (newType == SSD1306_SPI || newType == SSD1306_SPI64 || newType == SSD1309_SPI64);
|
||||
if (isSPI) {
|
||||
if (pinsChanged || !newSPI) pinManager.deallocateMultiplePins((const uint8_t*)oldPin, 3, PinOwner::UM_FourLineDisplay);
|
||||
if (pinsChanged || !newSPI) PinManager::deallocateMultiplePins((const uint8_t*)oldPin, 3, PinOwner::UM_FourLineDisplay);
|
||||
if (!newSPI) {
|
||||
// was SPI but is no longer SPI
|
||||
if (i2c_scl<0 || i2c_sda<0) { newType=NONE; }
|
||||
@ -1315,7 +1315,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
|
||||
// still SPI but pins changed
|
||||
PinManagerPinType cspins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
|
||||
if (ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) { newType=NONE; }
|
||||
else if (!pinManager.allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; }
|
||||
else if (!PinManager::allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; }
|
||||
}
|
||||
} else if (newSPI) {
|
||||
// was I2C but is now SPI
|
||||
@ -1324,7 +1324,7 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
|
||||
} else {
|
||||
PinManagerPinType pins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
|
||||
if (ioPin[0]<0 || ioPin[1]<0 || ioPin[1]<0) { newType=NONE; }
|
||||
else if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; }
|
||||
else if (!PinManager::allocateMultiplePins(pins, 3, PinOwner::UM_FourLineDisplay)) { newType=NONE; }
|
||||
}
|
||||
} else {
|
||||
// just I2C type changed
|
||||
|
@ -489,7 +489,7 @@ void RotaryEncoderUIUsermod::setup()
|
||||
enabled = false;
|
||||
return;
|
||||
} else {
|
||||
if (pinIRQ >= 0 && pinManager.allocatePin(pinIRQ, false, PinOwner::UM_RotaryEncoderUI)) {
|
||||
if (pinIRQ >= 0 && PinManager::allocatePin(pinIRQ, false, PinOwner::UM_RotaryEncoderUI)) {
|
||||
pinMode(pinIRQ, INPUT_PULLUP);
|
||||
attachInterrupt(pinIRQ, i2cReadingISR, FALLING); // RISING, FALLING, CHANGE, ONLOW, ONHIGH
|
||||
DEBUG_PRINTLN(F("Interrupt attached."));
|
||||
@ -502,7 +502,7 @@ void RotaryEncoderUIUsermod::setup()
|
||||
}
|
||||
} else {
|
||||
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
||||
if (pinA<0 || pinB<0 || !pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
||||
if (pinA<0 || pinB<0 || !PinManager::allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
||||
pinA = pinB = pinC = -1;
|
||||
enabled = false;
|
||||
return;
|
||||
@ -525,7 +525,7 @@ void RotaryEncoderUIUsermod::setup()
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
// This Usermod uses FourLineDisplayUsermod for the best experience.
|
||||
// But it's optional. But you want it.
|
||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
display = (FourLineDisplayUsermod*) UsermodManager::lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
if (display != nullptr) {
|
||||
display->setMarkLine(1, 0);
|
||||
}
|
||||
@ -1138,14 +1138,14 @@ bool RotaryEncoderUIUsermod::readFromConfig(JsonObject &root) {
|
||||
if (oldPcf8574) {
|
||||
if (pinIRQ >= 0) {
|
||||
detachInterrupt(pinIRQ);
|
||||
pinManager.deallocatePin(pinIRQ, PinOwner::UM_RotaryEncoderUI);
|
||||
PinManager::deallocatePin(pinIRQ, PinOwner::UM_RotaryEncoderUI);
|
||||
DEBUG_PRINTLN(F("Deallocated old IRQ pin."));
|
||||
}
|
||||
pinIRQ = newIRQpin<100 ? newIRQpin : -1; // ignore PCF8574 pins
|
||||
} else {
|
||||
pinManager.deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI);
|
||||
pinManager.deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI);
|
||||
pinManager.deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI);
|
||||
PinManager::deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI);
|
||||
PinManager::deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI);
|
||||
PinManager::deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI);
|
||||
DEBUG_PRINTLN(F("Deallocated old pins."));
|
||||
}
|
||||
pinA = newDTpin;
|
||||
|
@ -75,7 +75,7 @@ int8_t tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec) {
|
||||
|
||||
static um_data_t* getAudioData() {
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
if (!UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
// add support for no audio
|
||||
um_data = simulateSound(SEGMENT.soundSim);
|
||||
}
|
||||
@ -6298,7 +6298,7 @@ static const char _data_FX_MODE_2DPLASMAROTOZOOM[] PROGMEM = "Rotozoomer@!,Scale
|
||||
uint8_t *fftResult = nullptr;
|
||||
float *fftBin = nullptr;
|
||||
um_data_t *um_data;
|
||||
if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
if (UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
volumeSmth = *(float*) um_data->u_data[0];
|
||||
volumeRaw = *(float*) um_data->u_data[1];
|
||||
fftResult = (uint8_t*) um_data->u_data[2];
|
||||
@ -6911,7 +6911,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline.
|
||||
uint8_t *myVals = reinterpret_cast<uint8_t*>(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low.
|
||||
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
if (!UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
um_data = simulateSound(SEGMENT.soundSim);
|
||||
}
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
@ -7494,7 +7494,7 @@ uint16_t mode_2DAkemi(void) {
|
||||
const float normalFactor = 0.4f;
|
||||
|
||||
um_data_t *um_data;
|
||||
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
if (!UsermodManager::getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
|
||||
um_data = simulateSound(SEGMENT.soundSim);
|
||||
}
|
||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||
|
@ -187,11 +187,7 @@ void IRAM_ATTR_YN Segment::deallocateData() {
|
||||
if ((Segment::getUsedSegmentData() > 0) && (_dataLen > 0)) { // check that we don't have a dangling / inconsistent data pointer
|
||||
free(data);
|
||||
} else {
|
||||
DEBUG_PRINT(F("---- Released data "));
|
||||
DEBUG_PRINTF_P(PSTR("(%p): "), this);
|
||||
DEBUG_PRINT(F("inconsistent UsedSegmentData "));
|
||||
DEBUG_PRINTF_P(PSTR("(%d/%d)"), _dataLen, Segment::getUsedSegmentData());
|
||||
DEBUG_PRINTLN(F(", cowardly refusing to free nothing."));
|
||||
DEBUG_PRINTF_P(PSTR("---- Released data (%p): inconsistent UsedSegmentData (%d/%d), cowardly refusing to free nothing.\n"), this, _dataLen, Segment::getUsedSegmentData());
|
||||
}
|
||||
data = nullptr;
|
||||
Segment::addUsedSegmentData(_dataLen <= Segment::getUsedSegmentData() ? -_dataLen : -Segment::getUsedSegmentData());
|
||||
@ -1136,7 +1132,6 @@ void Segment::refreshLightCapabilities() {
|
||||
if (bus->getStart() >= segStopIdx) continue;
|
||||
if (bus->getStart() + bus->getLength() <= segStartIdx) continue;
|
||||
|
||||
//uint8_t type = bus->getType();
|
||||
if (bus->hasRGB() || (strip.cctFromRgb && bus->hasCCT())) capabilities |= SEG_CAPABILITY_RGB;
|
||||
if (!strip.cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT;
|
||||
if (strip.correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider)
|
||||
@ -1353,7 +1348,7 @@ void WS2812FX::finalizeInit() {
|
||||
// When booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware
|
||||
// i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), read/only pins, etc.
|
||||
// Pin should not be already allocated, read/only or defined for current bus
|
||||
while (pinManager.isPinAllocated(defPin[j]) || !pinManager.isPinOk(defPin[j],true)) {
|
||||
while (PinManager::isPinAllocated(defPin[j]) || !PinManager::isPinOk(defPin[j],true)) {
|
||||
if (validPin) {
|
||||
DEBUG_PRINTLN(F("Some of the provided pins cannot be used to configure this LED output."));
|
||||
defPin[j] = 1; // start with GPIO1 and work upwards
|
||||
@ -1364,16 +1359,30 @@ void WS2812FX::finalizeInit() {
|
||||
DEBUG_PRINTLN(F("No available pins left! Can't configure output."));
|
||||
return;
|
||||
}
|
||||
// is the newly assigned pin already defined? try next in line until there are no clashes
|
||||
// is the newly assigned pin already defined or used previously?
|
||||
// try next in line until there are no clashes or we run out of pins
|
||||
bool clash;
|
||||
do {
|
||||
clash = false;
|
||||
for (const auto &pin : defDataPins) {
|
||||
if (pin == defPin[j]) {
|
||||
defPin[j]++;
|
||||
if (defPin[j] < WLED_NUM_PINS) clash = true;
|
||||
// check for conflicts on current bus
|
||||
for (const auto &pin : defPin) {
|
||||
if (&pin != &defPin[j] && pin == defPin[j]) {
|
||||
clash = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We already have a clash on current bus, no point checking next buses
|
||||
if (!clash) {
|
||||
// check for conflicts in defined pins
|
||||
for (const auto &pin : defDataPins) {
|
||||
if (pin == defPin[j]) {
|
||||
clash = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clash) defPin[j]++;
|
||||
if (defPin[j] >= WLED_NUM_PINS) break;
|
||||
} while (clash);
|
||||
}
|
||||
}
|
||||
@ -1722,7 +1731,7 @@ uint16_t WS2812FX::getLengthPhysical() const {
|
||||
unsigned len = 0;
|
||||
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
||||
Bus *bus = BusManager::getBus(b);
|
||||
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
||||
if (bus->isVirtual()) continue; //exclude non-physical network busses
|
||||
len += bus->getLength();
|
||||
}
|
||||
return len;
|
||||
|
@ -130,11 +130,11 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
|
||||
, _colorOrderMap(com)
|
||||
{
|
||||
if (!isDigital(bc.type) || !bc.count) return;
|
||||
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
|
||||
if (!PinManager::allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
|
||||
_frequencykHz = 0U;
|
||||
_pins[0] = bc.pins[0];
|
||||
if (is2Pin(bc.type)) {
|
||||
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
|
||||
if (!PinManager::allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
@ -422,8 +422,8 @@ void BusDigital::cleanup() {
|
||||
_valid = false;
|
||||
_busPtr = nullptr;
|
||||
if (_data != nullptr) freeData();
|
||||
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
PinManager::deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
PinManager::deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
}
|
||||
|
||||
|
||||
@ -464,16 +464,16 @@ BusPwm::BusPwm(BusConfig &bc)
|
||||
|
||||
managed_pin_type pins[numPins];
|
||||
for (unsigned i = 0; i < numPins; i++) pins[i] = {(int8_t)bc.pins[i], true};
|
||||
if (!pinManager.allocateMultiplePins(pins, numPins, PinOwner::BusPwm)) return;
|
||||
if (!PinManager::allocateMultiplePins(pins, numPins, PinOwner::BusPwm)) return;
|
||||
|
||||
#ifdef ESP8266
|
||||
analogWriteRange((1<<_depth)-1);
|
||||
analogWriteFreq(_frequency);
|
||||
#else
|
||||
// for 2 pin PWM CCT strip pinManager will make sure both LEDC channels are in the same speed group and sharing the same timer
|
||||
_ledcStart = pinManager.allocateLedc(numPins);
|
||||
_ledcStart = PinManager::allocateLedc(numPins);
|
||||
if (_ledcStart == 255) { //no more free LEDC channels
|
||||
pinManager.deallocateMultiplePins(pins, numPins, PinOwner::BusPwm);
|
||||
PinManager::deallocateMultiplePins(pins, numPins, PinOwner::BusPwm);
|
||||
return;
|
||||
}
|
||||
// if _needsRefresh is true (UI hack) we are using dithering (credit @dedehai & @zalatnaicsongor)
|
||||
@ -640,8 +640,8 @@ std::vector<LEDType> BusPwm::getLEDTypes() {
|
||||
void BusPwm::deallocatePins() {
|
||||
unsigned numPins = getPins();
|
||||
for (unsigned i = 0; i < numPins; i++) {
|
||||
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
|
||||
if (!pinManager.isPinOk(_pins[i])) continue;
|
||||
PinManager::deallocatePin(_pins[i], PinOwner::BusPwm);
|
||||
if (!PinManager::isPinOk(_pins[i])) continue;
|
||||
#ifdef ESP8266
|
||||
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
|
||||
#else
|
||||
@ -649,7 +649,7 @@ void BusPwm::deallocatePins() {
|
||||
#endif
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
pinManager.deallocateLedc(_ledcStart, numPins);
|
||||
PinManager::deallocateLedc(_ledcStart, numPins);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -661,7 +661,7 @@ BusOnOff::BusOnOff(BusConfig &bc)
|
||||
if (!Bus::isOnOff(bc.type)) return;
|
||||
|
||||
uint8_t currentPin = bc.pins[0];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
|
||||
if (!PinManager::allocatePin(currentPin, true, PinOwner::BusOnOff)) {
|
||||
return;
|
||||
}
|
||||
_pin = currentPin; //store only after allocatePin() succeeds
|
||||
@ -830,7 +830,7 @@ static String LEDTypesToJson(const std::vector<LEDType>& types) {
|
||||
String json;
|
||||
for (const auto &type : types) {
|
||||
// capabilities follows similar pattern as JSON API
|
||||
int capabilities = Bus::hasRGB(type.id) | Bus::hasWhite(type.id)<<1 | Bus::hasCCT(type.id)<<2 | Bus::is16bit(type.id)<<4;
|
||||
int capabilities = Bus::hasRGB(type.id) | Bus::hasWhite(type.id)<<1 | Bus::hasCCT(type.id)<<2 | Bus::is16bit(type.id)<<4 | Bus::mustRefresh(type.id)<<5;
|
||||
char str[256];
|
||||
sprintf_P(str, PSTR("{i:%d,c:%d,t:\"%s\",n:\"%s\"},"), type.id, capabilities, type.type, type.name);
|
||||
json += str;
|
||||
@ -904,7 +904,7 @@ void BusManager::esp32RMTInvertIdle() {
|
||||
void BusManager::on() {
|
||||
#ifdef ESP8266
|
||||
//Fix for turning off onboard LED breaking bus
|
||||
if (pinManager.getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
|
||||
if (PinManager::getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
|
||||
for (unsigned i = 0; i < numBusses; i++) {
|
||||
uint8_t pins[2] = {255,255};
|
||||
if (busses[i]->isDigital() && busses[i]->getPins(pins)) {
|
||||
@ -926,7 +926,7 @@ void BusManager::off() {
|
||||
#ifdef ESP8266
|
||||
// turn off built-in LED if strip is turned off
|
||||
// this will break digital bus so will need to be re-initialised on On
|
||||
if (pinManager.getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
|
||||
if (PinManager::getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
|
||||
for (unsigned i = 0; i < numBusses; i++) if (busses[i]->isOffRefreshRequired()) return;
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
|
@ -104,6 +104,7 @@ class Bus {
|
||||
inline bool isPWM() const { return isPWM(_type); }
|
||||
inline bool isVirtual() const { return isVirtual(_type); }
|
||||
inline bool is16bit() const { return is16bit(_type); }
|
||||
inline bool mustRefresh() const { return mustRefresh(_type); }
|
||||
inline void setReversed(bool reversed) { _reversed = reversed; }
|
||||
inline void setStart(uint16_t start) { _start = start; }
|
||||
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
||||
@ -142,6 +143,7 @@ class Bus {
|
||||
static constexpr bool isPWM(uint8_t type) { return (type >= TYPE_ANALOG_MIN && type <= TYPE_ANALOG_MAX); }
|
||||
static constexpr bool isVirtual(uint8_t type) { return (type >= TYPE_VIRTUAL_MIN && type <= TYPE_VIRTUAL_MAX); }
|
||||
static constexpr bool is16bit(uint8_t type) { return type == TYPE_UCS8903 || type == TYPE_UCS8904 || type == TYPE_SM16825; }
|
||||
static constexpr bool mustRefresh(uint8_t type) { return type == TYPE_TM1814; }
|
||||
static constexpr int numPWMPins(uint8_t type) { return (type - 40); }
|
||||
|
||||
static inline int16_t getCCT() { return _cct; }
|
||||
@ -280,7 +282,7 @@ class BusOnOff : public Bus {
|
||||
uint32_t getPixelColor(uint16_t pix) const override;
|
||||
uint8_t getPins(uint8_t* pinArray) const override;
|
||||
void show() override;
|
||||
void cleanup() { pinManager.deallocatePin(_pin, PinOwner::BusOnOff); }
|
||||
void cleanup() { PinManager::deallocatePin(_pin, PinOwner::BusOnOff); }
|
||||
|
||||
static std::vector<LEDType> getLEDTypes();
|
||||
|
||||
|
@ -267,7 +267,7 @@ void handleButton()
|
||||
if (btnPin[b]<0 || buttonType[b] == BTN_TYPE_NONE) continue;
|
||||
#endif
|
||||
|
||||
if (usermods.handleButton(b)) continue; // did usermod handle buttons
|
||||
if (UsermodManager::handleButton(b)) continue; // did usermod handle buttons
|
||||
|
||||
if (buttonType[b] == BTN_TYPE_ANALOG || buttonType[b] == BTN_TYPE_ANALOG_INVERTED) { // button is not a button but a potentiometer
|
||||
if (now - lastAnalogRead > ANALOG_BTN_READ_CYCLE) {
|
||||
|
@ -261,12 +261,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonArray hw_btn_ins = btn_obj["ins"];
|
||||
if (!hw_btn_ins.isNull()) {
|
||||
// deallocate existing button pins
|
||||
for (unsigned b = 0; b < WLED_MAX_BUTTONS; b++) pinManager.deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button
|
||||
for (unsigned b = 0; b < WLED_MAX_BUTTONS; b++) PinManager::deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button
|
||||
unsigned s = 0;
|
||||
for (JsonObject btn : hw_btn_ins) {
|
||||
CJSON(buttonType[s], btn["type"]);
|
||||
int8_t pin = btn["pin"][0] | -1;
|
||||
if (pin > -1 && pinManager.allocatePin(pin, false, PinOwner::Button)) {
|
||||
if (pin > -1 && PinManager::allocatePin(pin, false, PinOwner::Button)) {
|
||||
btnPin[s] = pin;
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
// ESP32 only: check that analog button pin is a valid ADC gpio
|
||||
@ -275,7 +275,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
// not an ADC analog pin
|
||||
DEBUG_PRINTF_P(PSTR("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);
|
||||
PinManager::deallocatePin(pin,PinOwner::Button);
|
||||
} else {
|
||||
analogReadResolution(12); // see #4040
|
||||
}
|
||||
@ -286,7 +286,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
// not a touch pin
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not a touch pin!\n"), btnPin[s], s);
|
||||
btnPin[s] = -1;
|
||||
pinManager.deallocatePin(pin,PinOwner::Button);
|
||||
PinManager::deallocatePin(pin,PinOwner::Button);
|
||||
}
|
||||
//if touch pin, enable the touch interrupt on ESP32 S2 & S3
|
||||
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state but need to attach an interrupt to do so
|
||||
@ -331,7 +331,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (fromFS) {
|
||||
// relies upon only being called once with fromFS == true, which is currently true.
|
||||
for (size_t s = 0; s < WLED_MAX_BUTTONS; s++) {
|
||||
if (buttonType[s] == BTN_TYPE_NONE || btnPin[s] < 0 || !pinManager.allocatePin(btnPin[s], false, PinOwner::Button)) {
|
||||
if (buttonType[s] == BTN_TYPE_NONE || btnPin[s] < 0 || !PinManager::allocatePin(btnPin[s], false, PinOwner::Button)) {
|
||||
btnPin[s] = -1;
|
||||
buttonType[s] = BTN_TYPE_NONE;
|
||||
}
|
||||
@ -358,8 +358,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||
if (hw_ir_pin > -2) {
|
||||
pinManager.deallocatePin(irPin, PinOwner::IR);
|
||||
if (pinManager.allocatePin(hw_ir_pin, false, PinOwner::IR)) {
|
||||
PinManager::deallocatePin(irPin, PinOwner::IR);
|
||||
if (PinManager::allocatePin(hw_ir_pin, false, PinOwner::IR)) {
|
||||
irPin = hw_ir_pin;
|
||||
} else {
|
||||
irPin = -1;
|
||||
@ -374,8 +374,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
rlyOpenDrain = relay[F("odrain")] | rlyOpenDrain;
|
||||
int hw_relay_pin = relay["pin"] | -2;
|
||||
if (hw_relay_pin > -2) {
|
||||
pinManager.deallocatePin(rlyPin, PinOwner::Relay);
|
||||
if (pinManager.allocatePin(hw_relay_pin,true, PinOwner::Relay)) {
|
||||
PinManager::deallocatePin(rlyPin, PinOwner::Relay);
|
||||
if (PinManager::allocatePin(hw_relay_pin,true, PinOwner::Relay)) {
|
||||
rlyPin = hw_relay_pin;
|
||||
pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT);
|
||||
} else {
|
||||
@ -394,7 +394,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(i2c_sda, hw_if_i2c[0]);
|
||||
CJSON(i2c_scl, hw_if_i2c[1]);
|
||||
PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } };
|
||||
if (i2c_scl >= 0 && i2c_sda >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
if (i2c_scl >= 0 && i2c_sda >= 0 && PinManager::allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
#ifdef ESP32
|
||||
if (!Wire.setPins(i2c_sda, i2c_scl)) { i2c_scl = i2c_sda = -1; } // this will fail if Wire is initialised (Wire.begin() called prior)
|
||||
else Wire.begin();
|
||||
@ -410,7 +410,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(spi_sclk, hw_if_spi[1]);
|
||||
CJSON(spi_miso, hw_if_spi[2]);
|
||||
PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_miso, true }, { spi_sclk, true } };
|
||||
if (spi_mosi >= 0 && spi_sclk >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
|
||||
if (spi_mosi >= 0 && spi_sclk >= 0 && PinManager::allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
|
||||
#ifdef ESP32
|
||||
SPI.begin(spi_sclk, spi_miso, spi_mosi); // SPI global uses VSPI on ESP32 and FSPI on C3, S3
|
||||
#else
|
||||
@ -479,6 +479,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(receiveNotificationBrightness, if_sync_recv["bri"]);
|
||||
CJSON(receiveNotificationColor, if_sync_recv["col"]);
|
||||
CJSON(receiveNotificationEffects, if_sync_recv["fx"]);
|
||||
CJSON(receiveNotificationPalette, if_sync_recv["pal"]);
|
||||
CJSON(receiveGroups, if_sync_recv["grp"]);
|
||||
CJSON(receiveSegmentOptions, if_sync_recv["seg"]);
|
||||
CJSON(receiveSegmentBounds, if_sync_recv["sb"]);
|
||||
@ -660,7 +661,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
DEBUG_PRINTLN(F("Starting usermod config."));
|
||||
JsonObject usermods_settings = doc["um"];
|
||||
if (!usermods_settings.isNull()) {
|
||||
needsSave = !usermods.readFromConfig(usermods_settings);
|
||||
needsSave = !UsermodManager::readFromConfig(usermods_settings);
|
||||
}
|
||||
|
||||
if (fromFS) return needsSave;
|
||||
@ -696,7 +697,7 @@ void deserializeConfigFromFS() {
|
||||
// save default values to /cfg.json
|
||||
// call readFromConfig() with an empty object so that usermods can initialize to defaults prior to saving
|
||||
JsonObject empty = JsonObject();
|
||||
usermods.readFromConfig(empty);
|
||||
UsermodManager::readFromConfig(empty);
|
||||
serializeConfig();
|
||||
// init Ethernet (in case default type is set at compile time)
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
@ -963,6 +964,7 @@ void serializeConfig() {
|
||||
if_sync_recv["bri"] = receiveNotificationBrightness;
|
||||
if_sync_recv["col"] = receiveNotificationColor;
|
||||
if_sync_recv["fx"] = receiveNotificationEffects;
|
||||
if_sync_recv["pal"] = receiveNotificationPalette;
|
||||
if_sync_recv["grp"] = receiveGroups;
|
||||
if_sync_recv["seg"] = receiveSegmentOptions;
|
||||
if_sync_recv["sb"] = receiveSegmentBounds;
|
||||
@ -1113,7 +1115,7 @@ void serializeConfig() {
|
||||
#endif
|
||||
|
||||
JsonObject usermods_settings = root.createNestedObject("um");
|
||||
usermods.addToConfig(usermods_settings);
|
||||
UsermodManager::addToConfig(usermods_settings);
|
||||
|
||||
File f = WLED_FS.open(FPSTR(s_cfg_json), "w");
|
||||
if (f) serializeJson(root, f);
|
||||
|
118
wled00/data/common.js
Normal file
118
wled00/data/common.js
Normal file
@ -0,0 +1,118 @@
|
||||
var d=document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
|
||||
function H(pg="") { window.open("https://kno.wled.ge/"+pg); }
|
||||
function GH() { window.open("https://github.com/Aircoookie/WLED"); }
|
||||
function gId(c) { return d.getElementById(c); } // getElementById
|
||||
function cE(e) { return d.createElement(e); } // createElement
|
||||
function gEBCN(c) { return d.getElementsByClassName(c); } // getElementsByClassName
|
||||
function gN(s) { return d.getElementsByName(s)[0]; } // getElementsByName
|
||||
function isE(o) { return Object.keys(o).length === 0; } // isEmpty
|
||||
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); } // isObject
|
||||
function isN(n) { return !isNaN(parseFloat(n)) && isFinite(n); } // isNumber
|
||||
// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
|
||||
function isF(n) { return n === +n && n !== (n|0); } // isFloat
|
||||
function isI(n) { return n === +n && n === (n|0); } // isInteger
|
||||
function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); }
|
||||
function tooltip(cont=null) {
|
||||
d.querySelectorAll((cont?cont+" ":"")+"[title]").forEach((element)=>{
|
||||
element.addEventListener("mouseover", ()=>{
|
||||
// save title
|
||||
element.setAttribute("data-title", element.getAttribute("title"));
|
||||
const tooltip = d.createElement("span");
|
||||
tooltip.className = "tooltip";
|
||||
tooltip.textContent = element.getAttribute("title");
|
||||
|
||||
// prevent default title popup
|
||||
element.removeAttribute("title");
|
||||
|
||||
let { top, left, width } = element.getBoundingClientRect();
|
||||
|
||||
d.body.appendChild(tooltip);
|
||||
|
||||
const { offsetHeight, offsetWidth } = tooltip;
|
||||
|
||||
const offset = element.classList.contains("sliderwrap") ? 4 : 10;
|
||||
top -= offsetHeight + offset;
|
||||
left += (width - offsetWidth) / 2;
|
||||
|
||||
tooltip.style.top = top + "px";
|
||||
tooltip.style.left = left + "px";
|
||||
tooltip.classList.add("visible");
|
||||
});
|
||||
|
||||
element.addEventListener("mouseout", ()=>{
|
||||
d.querySelectorAll('.tooltip').forEach((tooltip)=>{
|
||||
tooltip.classList.remove("visible");
|
||||
d.body.removeChild(tooltip);
|
||||
});
|
||||
// restore title
|
||||
element.setAttribute("title", element.getAttribute("data-title"));
|
||||
});
|
||||
});
|
||||
};
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true, preGetV = undefined, postGetV = undefined) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
if (preGetV) preGetV();
|
||||
GetV();
|
||||
if (postGetV) postGetV();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function getLoc() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 1) paths.pop(); // remove subpage (or "settings")
|
||||
if (paths.length > 0 && paths[paths.length-1]=="settings") paths.pop(); // remove "settings"
|
||||
if (paths.length > 1) {
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
function getURL(path) { return (loc ? locproto + "//" + locip : "") + path; }
|
||||
function B() { window.open(getURL("/settings"),"_self"); }
|
||||
var timeout;
|
||||
function showToast(text, error = false) {
|
||||
var x = gId("toast");
|
||||
if (!x) return;
|
||||
x.innerHTML = text;
|
||||
x.className = error ? "error":"show";
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
|
||||
}
|
||||
function uploadFile(fileObj, name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", fileObj.files[0], name);
|
||||
req.send(formData);
|
||||
fileObj.value = '';
|
||||
return false;
|
||||
}
|
@ -608,8 +608,8 @@
|
||||
}
|
||||
|
||||
function generatePaletteDivs() {
|
||||
const palettesDiv = d.getElementById("palettes");
|
||||
const staticPalettesDiv = d.getElementById("staticPalettes");
|
||||
const palettesDiv = gId("palettes");
|
||||
const staticPalettesDiv = gId("staticPalettes");
|
||||
const paletteDivs = Array.from(palettesDiv.children).filter((child) => {
|
||||
return child.id.match(/^palette\d$/); // match only elements with id starting with "palette" followed by a single digit
|
||||
});
|
||||
@ -620,25 +620,25 @@
|
||||
|
||||
for (let i = 0; i < paletteArray.length; i++) {
|
||||
const palette = paletteArray[i];
|
||||
const paletteDiv = d.createElement("div");
|
||||
const paletteDiv = cE("div");
|
||||
paletteDiv.id = `palette${i}`;
|
||||
paletteDiv.classList.add("palette");
|
||||
const thisKey = Object.keys(palette)[0];
|
||||
paletteDiv.dataset.colarray = JSON.stringify(palette[thisKey]);
|
||||
|
||||
const gradientDiv = d.createElement("div");
|
||||
const gradientDiv = cE("div");
|
||||
gradientDiv.id = `paletteGradient${i}`
|
||||
const buttonsDiv = d.createElement("div");
|
||||
const buttonsDiv = cE("div");
|
||||
buttonsDiv.id = `buttonsDiv${i}`;
|
||||
buttonsDiv.classList.add("buttonsDiv")
|
||||
|
||||
const sendSpan = d.createElement("span");
|
||||
const sendSpan = cE("span");
|
||||
sendSpan.id = `sendSpan${i}`;
|
||||
sendSpan.onclick = function() {initiateUpload(i)};
|
||||
sendSpan.setAttribute('title', `Send current editor to slot ${i}`); // perhaps Save instead of Send?
|
||||
sendSpan.innerHTML = svgSave;
|
||||
sendSpan.classList.add("sendSpan")
|
||||
const editSpan = d.createElement("span");
|
||||
const editSpan = cE("span");
|
||||
editSpan.id = `editSpan${i}`;
|
||||
editSpan.onclick = function() {loadForEdit(i)};
|
||||
editSpan.setAttribute('title', `Copy slot ${i} palette to editor`);
|
||||
|
@ -3207,7 +3207,7 @@ function simplifyUI() {
|
||||
createDropdown("palw", "Change palette");
|
||||
createDropdown("fx", "Change effect", [gId("fxFind"), gId("fxlist")]);
|
||||
|
||||
// Hide pallete label
|
||||
// Hide palette label
|
||||
gId("pall").style.display = "none";
|
||||
gId("Colors").insertBefore(document.createElement("br"), gId("pall"));
|
||||
// Hide effect label
|
||||
|
@ -882,10 +882,8 @@
|
||||
hostnameLabel();
|
||||
})();
|
||||
|
||||
function gId(id) {
|
||||
return d.getElementById(id);
|
||||
}
|
||||
|
||||
function gId(e) {return d.getElementById(e);}
|
||||
function cE(e) {return d.createElement(e);}
|
||||
function hostnameLabel() {
|
||||
const link = gId("wledEdit");
|
||||
link.href = WLED_URL + "/edit";
|
||||
@ -1675,7 +1673,7 @@
|
||||
}
|
||||
|
||||
function createCanvas(width, height) {
|
||||
const canvas = d.createElement("canvas");
|
||||
const canvas = cE("canvas");
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
@ -1719,7 +1717,7 @@
|
||||
const blob = new Blob([text], { type: mimeType });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const anchorElement = d.createElement("a");
|
||||
const anchorElement = cE("a");
|
||||
anchorElement.href = url;
|
||||
anchorElement.download = `${filename}.${fileExtension}`;
|
||||
|
||||
@ -1790,7 +1788,7 @@
|
||||
hideElement = "preview"
|
||||
) {
|
||||
const hide = gId(hideElement);
|
||||
const toast = d.createElement("div");
|
||||
const toast = cE("div");
|
||||
const wait = 100;
|
||||
|
||||
toast.style.animation = "fadeIn";
|
||||
@ -1799,14 +1797,14 @@
|
||||
|
||||
toast.classList.add("toast", type);
|
||||
|
||||
const body = d.createElement("span");
|
||||
const body = cE("span");
|
||||
body.classList.add("toast-body");
|
||||
|
||||
body.textContent = message;
|
||||
|
||||
toast.appendChild(body);
|
||||
|
||||
const progress = d.createElement("div");
|
||||
const progress = cE("div");
|
||||
progress.classList.add("toast-progress");
|
||||
|
||||
progress.style.animation = "progress";
|
||||
@ -1831,7 +1829,7 @@
|
||||
|
||||
function carousel(id, images, delay = 3000) {
|
||||
let index = 0;
|
||||
const carousel = d.createElement("div");
|
||||
const carousel = cE("div");
|
||||
carousel.classList.add("carousel");
|
||||
|
||||
images.forEach((canvas, i) => {
|
||||
@ -1959,7 +1957,7 @@
|
||||
let errorElement = parent.querySelector(".error-message");
|
||||
|
||||
if (!errorElement) {
|
||||
errorElement = d.createElement("div");
|
||||
errorElement = cE("div");
|
||||
errorElement.classList.add("error-message");
|
||||
parent.appendChild(errorElement);
|
||||
}
|
||||
|
@ -4,53 +4,12 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>WLED Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
function gId(n){return d.getElementById(n);}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 1) {
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=0'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
|
@ -4,62 +4,19 @@
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>2D Set-up</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
var maxPanels=64;
|
||||
var ctx = null; // WLEDMM
|
||||
function H(){window.open("https://kno.wled.ge/features/2D");}
|
||||
function B(){window.open(getURL("/settings"),"_self");}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
var ctx = null;
|
||||
function fS(){d.Sf.submit();} // <button type=submit> sometimes didn't work
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
function S() {
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=10'), false, undefined, ()=>{
|
||||
UI();
|
||||
Sf.MPC.setAttribute("max",maxPanels);
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "2d"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=10'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/2D');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
|
||||
function UI() {
|
||||
if (gId("somp").value === "0") {
|
||||
@ -71,29 +28,6 @@
|
||||
draw();
|
||||
}
|
||||
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.className = error ? "error":"show";
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
|
||||
}
|
||||
|
||||
function uploadFile(name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", d.Sf.data.files[0], name);
|
||||
req.send(formData);
|
||||
d.Sf.data.value = '';
|
||||
return false;
|
||||
}
|
||||
|
||||
function addPanels() {
|
||||
let c = parseInt(d.Sf.MPC.value);
|
||||
let i = gId("panels").children.length;
|
||||
@ -308,7 +242,7 @@ Y:<input name="P${i}Y" type="number" min="0" max="255" value="0" oninput="UI()">
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('features/2D')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="button" onclick="fS()">Save</button><hr>
|
||||
</div>
|
||||
<h2>2D setup</h2>
|
||||
@ -351,7 +285,7 @@ Y:<input name="P${i}Y" type="number" min="0" max="255" value="0" oninput="UI()">
|
||||
<hr class="sml">
|
||||
<div id="MD"></div>
|
||||
<canvas id="canvas"></canvas>
|
||||
<div id="json" >Gap file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/2d-gaps.json')">Upload</button></div>
|
||||
<div id="json" >Gap file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile(d.Sf.data,'/2d-gaps.json')">Upload</button></div>
|
||||
<i>Note: Gap file is a <b>.json</b> file containing an array with number of elements equal to the matrix size.<br>
|
||||
A value of -1 means that pixel at that position is missing, a value of 0 means never paint that pixel, and 1 means regular pixel.</i>
|
||||
</div>
|
||||
|
@ -4,88 +4,46 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<meta charset="utf-8">
|
||||
<title>DMX Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
|
||||
function B(){window.open(getURL("/settings"),"_self");}
|
||||
function HW(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
|
||||
function GCH(num) {
|
||||
d.getElementById('dmxchannels').innerHTML += "";
|
||||
gId('dmxchannels').innerHTML += "";
|
||||
for (i=0;i<num;i++) {
|
||||
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||
gId('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||
}
|
||||
}
|
||||
function mMap(){
|
||||
numCh=document.Sf.CN.value;
|
||||
numGap=document.Sf.CG.value;
|
||||
if (parseInt(numCh)>parseInt(numGap)) {
|
||||
d.getElementById("gapwarning").style.display="block";
|
||||
gId("gapwarning").style.display="block";
|
||||
} else {
|
||||
d.getElementById("gapwarning").style.display="none";
|
||||
gId("gapwarning").style.display="none";
|
||||
}
|
||||
for (i=0;i<15;i++) {
|
||||
if (i>=numCh) {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||
d.getElementById("CH"+(i+1)).disabled = true;
|
||||
gId("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||
gId("CH"+(i+1)).disabled = true;
|
||||
|
||||
} else {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
||||
d.getElementById("CH"+(i+1)).disabled = false;
|
||||
gId("CH"+(i+1) + "s").style.opacity = "1";
|
||||
gId("CH"+(i+1)).disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GCH(15);GetV();mMap();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S(){
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "dmx"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=7'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=7'), false, ()=>{GCH(15);}, ()=>{mMap();}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/dmx');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="HW()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>Imma firin ma lazer (if it has DMX support)</h2><!-- TODO: Change to something less-meme-related //-->
|
||||
|
@ -4,20 +4,12 @@
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>LED Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d=document,laprev=55,maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=2048,maxL=1664,maxCO=5,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||
var laprev=55,maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=2048,maxL=1664,maxCO=5,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||
var oMaxB=1;
|
||||
d.ledTypes = [/*{i:22,c:1,t:"D",n:"WS2812"},{i:42,c:6,t:"AA",n:"PWM CCT"}*/]; // filled from GetV()
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_gpio = [];
|
||||
d.max_gpio = 50;
|
||||
var customStarts=false,startsDirty=[];
|
||||
var loc = false, locip, locproto = "http:";
|
||||
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
|
||||
function B(){window.open(getURL("/settings"),"_self");}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
function off(n){d.getElementsByName(n)[0].value = -1;}
|
||||
function off(n) { gN(n).value = -1;}
|
||||
// these functions correspond to C macros found in const.h
|
||||
function gT(t) { for (let type of d.ledTypes) if (t == type.i) return type; } // getType from available ledTypes
|
||||
function isPWM(t) { return gT(t).t.charAt(0) === "A"; } // is PWM type
|
||||
@ -30,38 +22,24 @@
|
||||
function hasW(t) { return !!(gT(t).c & 0x02); } // has white channel
|
||||
function hasCCT(t) { return !!(gT(t).c & 0x04); } // is white CCT enabled
|
||||
function is16b(t) { return !!(gT(t).c & 0x10); } // is digital 16 bit type
|
||||
function mustR(t) { return !!(gT(t).c & 0x20); } // Off refresh is mandatory
|
||||
function numPins(t){ return Math.max(gT(t).t.length, 1); } // type length determines number of GPIO pins
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
GetV();
|
||||
function S() {
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=2'), false, ()=>{
|
||||
d.ledTypes = [/*{i:22,c:1,t:"D",n:"WS2812"},{i:42,c:6,t:"AA",n:"PWM CCT"}*/]; // filled from GetV()
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_gpio = [];
|
||||
d.max_gpio = 50;
|
||||
}, ()=>{
|
||||
checkSi();
|
||||
setABL();
|
||||
d.Sf.addEventListener("submit", trySubmit);
|
||||
if (d.um_p[0]==-1) d.um_p.shift();
|
||||
pinDropdowns();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.className = error ? "error":"show";
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(()=>{ x.className = x.className.replace("show", ""); }, 2900);
|
||||
}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/leds');
|
||||
}
|
||||
function bLimits(b,v,p,m,l,o=5,d=2,a=6) {
|
||||
// maxB - max buses (can be changed if using ESP32 parallel I2S)
|
||||
@ -278,7 +256,7 @@
|
||||
d.Sf["LA"+n].min = (isVir(t) || isAna(t)) ? 0 : 1;
|
||||
d.Sf["MA"+n].min = (isVir(t) || isAna(t)) ? 0 : 250;
|
||||
}
|
||||
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
||||
gId("rf"+n).onclick = mustR(t) ? (()=>{return false}) : (()=>{}); // prevent change change of "Refresh" checkmark when mandatory
|
||||
gRGBW |= hasW(t); // RGBW checkbox
|
||||
gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM
|
||||
gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown
|
||||
@ -403,7 +381,7 @@
|
||||
}
|
||||
function addLEDs(n,init=true)
|
||||
{
|
||||
var o = d.getElementsByClassName("iST");
|
||||
var o = gEBCN("iST");
|
||||
var i = o.length;
|
||||
let disable = (sel,opt) => { sel.querySelectorAll(opt).forEach((o)=>{o.disabled=true;}); }
|
||||
|
||||
@ -465,10 +443,10 @@ mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
|
||||
</div>`;
|
||||
f.insertAdjacentHTML("beforeend", cn);
|
||||
// fill led types (credit @netmindz)
|
||||
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((sel,n)=>{
|
||||
f.querySelectorAll("select[name^=LT]").forEach((sel,n)=>{
|
||||
if (sel.length == 0) { // ignore already updated
|
||||
for (let type of d.ledTypes) {
|
||||
let opt = d.createElement("option");
|
||||
let opt = cE("option");
|
||||
opt.value = type.i;
|
||||
opt.text = type.n;
|
||||
if (type.t != undefined && type.t != "") {
|
||||
@ -480,9 +458,9 @@ mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
|
||||
});
|
||||
// disable inappropriate LED types
|
||||
let sel = d.getElementsByName("LT"+s)[0]
|
||||
if (i >= maxB || digitalB >= maxD) disable(sel,'option[data-type="D"]');
|
||||
if (i >= maxB || twopinB >= 1) disable(sel,'option[data-type="2P"]');
|
||||
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`);
|
||||
if (i >= maxB || digitalB >= maxD) disable(sel,'option[data-type="D"]'); // NOTE: see isDig()
|
||||
if (i >= maxB || twopinB >= 1) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P()
|
||||
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM()
|
||||
sel.selectedIndex = sel.querySelector('option:not(:disabled)').index;
|
||||
}
|
||||
if (n==-1) {
|
||||
@ -499,7 +477,7 @@ mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
|
||||
}
|
||||
|
||||
function addCOM(start=0,len=1,co=0) {
|
||||
var i = d.getElementsByClassName("com_entry").length;
|
||||
var i = gEBCN("com_entry").length;
|
||||
if (i >= maxCO) return;
|
||||
var s = String.fromCharCode((i<10?48:55)+i);
|
||||
var b = `<div class="com_entry">
|
||||
@ -530,7 +508,7 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
}
|
||||
|
||||
function remCOM() {
|
||||
var entries = d.getElementsByClassName("com_entry");
|
||||
var entries = gEBCN("com_entry");
|
||||
var i = entries.length;
|
||||
if (i === 0) return;
|
||||
entries[i-1].remove();
|
||||
@ -542,7 +520,7 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
if (_newMaxCOOverrides) {
|
||||
maxCO = _newMaxCOOverrides;
|
||||
}
|
||||
for (let e of d.getElementsByClassName("com_entry")) {
|
||||
for (let e of gEBCN("com_entry")) {
|
||||
e.remove();
|
||||
}
|
||||
btnCOM(0);
|
||||
@ -578,25 +556,14 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
}
|
||||
function checkSi() { //on load, checks whether there are custom start fields
|
||||
var cs = false;
|
||||
for (var i=1; i < d.getElementsByClassName("iST").length; i++) {
|
||||
var v = parseInt(gId("ls"+(i-1)).value) + parseInt(d.getElementsByName("LC"+(i-1))[0].value);
|
||||
for (var i=1; i < gEBCN("iST").length; i++) {
|
||||
var v = parseInt(gId("ls"+(i-1)).value) + parseInt(gN("LC"+(i-1)).value);
|
||||
if (v != parseInt(gId("ls"+i).value)) {cs = true; startsDirty[i] = true;}
|
||||
}
|
||||
if (gId("ls0") && parseInt(gId("ls0").value) != 0) {cs = true; startsDirty[0] = true;}
|
||||
gId("si").checked = cs;
|
||||
tglSi(cs);
|
||||
}
|
||||
function uploadFile(name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", d.Sf.data.files[0], name);
|
||||
req.send(formData);
|
||||
d.Sf.data.value = '';
|
||||
return false;
|
||||
}
|
||||
// https://stackoverflow.com/questions/7346563/loading-local-json-file
|
||||
function loadCfg(o) {
|
||||
var f, fr;
|
||||
@ -725,7 +692,7 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
}
|
||||
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
||||
function addDropdown(field) {
|
||||
let sel = d.createElement('select');
|
||||
let sel = cE('select');
|
||||
sel.classList.add("pin");
|
||||
let inp = d.getElementsByName(field)[0];
|
||||
if (inp && inp.tagName === "INPUT" && (inp.type === "text" || inp.type === "number")) { // may also use nodeName
|
||||
@ -750,7 +717,7 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
}
|
||||
function addOption(sel,txt,val) {
|
||||
if (sel===null) return; // select object missing
|
||||
let opt = d.createElement("option");
|
||||
let opt = cE("option");
|
||||
opt.value = val;
|
||||
opt.text = txt;
|
||||
sel.appendChild(opt);
|
||||
@ -760,40 +727,13 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "leds"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=2'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/leds');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('features/settings/#led-settings')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>LED & Hardware setup</h2>
|
||||
@ -861,7 +801,7 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
<option value=8>JSON remote</option>
|
||||
</select><span style="cursor: pointer;" onclick="off('IR')"> ✕</span><br>
|
||||
Apply IR change to main segment only: <input type="checkbox" name="MSO"><br>
|
||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/ir.json')">Upload</button><br></div>
|
||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile(d.Sf.data,'/ir.json')">Upload</button><br></div>
|
||||
<a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br>
|
||||
<hr class="sml">
|
||||
Relay GPIO: <input type="number" min="-1" max="48" name="RL" onchange="UI()" class="xs"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span><br>
|
||||
|
@ -4,55 +4,9 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<meta charset="utf-8">
|
||||
<title>Misc Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d = document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); }
|
||||
function B() { window.open(getURL("/settings"),"_self"); }
|
||||
function U() { window.open(getURL("/update"),"_self"); }
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function isObj(o) { return (o && typeof o === 'object' && !Array.isArray(o)); }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
setBckFilename(gId("bckcfg"));
|
||||
setBckFilename(gId("bckpresets"));
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.classList.add(error ? "error":"show");
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.classList.remove("show"); }, 2900);
|
||||
}
|
||||
function uploadFile(fO,name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", getURL("/upload"));
|
||||
var formData = new FormData();
|
||||
formData.append("data", fO.files[0], name);
|
||||
req.send(formData);
|
||||
fO.value = '';
|
||||
return false;
|
||||
}
|
||||
function checkNum(o) {
|
||||
const specialkeys = ["Backspace", "Tab", "Enter", "Shift", "Control", "Alt", "Pause", "CapsLock", "Escape", "Space", "PageUp", "PageDown", "End", "Home", "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown", "Insert", "Delete"];
|
||||
// true if key is a number or a special key
|
||||
@ -64,36 +18,17 @@
|
||||
x.setAttribute("download","wled_" + x.getAttribute("download") + (sd=="WLED"?"":("_" +sd)));
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "sec"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
getLoc();
|
||||
if (loc) {
|
||||
gId("bckcfg").setAttribute('href',getURL(gId("bckcfg").pathname));
|
||||
gId("bckpresets").setAttribute('href',getURL(gId("bckpresets").pathname));
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=6'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
loadJS(getURL('/settings/s.js?p=6'), false, undefined, ()=>{
|
||||
setBckFilename(gId("bckcfg"));
|
||||
setBckFilename(gId("bckpresets"));
|
||||
}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/sec');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import url("style.css");
|
||||
@ -102,7 +37,7 @@
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('features/settings/#security-settings')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>Security & Update setup</h2>
|
||||
|
59
wled00/data/settings_sync.htm
Executable file → Normal file
59
wled00/data/settings_sync.htm
Executable file → Normal file
@ -4,32 +4,10 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<meta charset="utf-8">
|
||||
<title>Sync Settings</title>
|
||||
<script>var d=document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
function gId(s){return d.getElementById(s);}
|
||||
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
||||
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
||||
function B(){window.open(getURL("/settings"),"_self");}
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
||||
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();SetVal();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function FC()
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
@ -55,26 +33,8 @@
|
||||
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
|
||||
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
||||
function S(){
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let paths = l.pathname.slice(1,l.pathname.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "sync"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=4'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=4'), false, undefined, ()=>{SetVal();}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/sync');
|
||||
}
|
||||
function getURL(path) {
|
||||
@ -86,7 +46,7 @@
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post" onsubmit="GC()">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('interfaces/udp-notifier/')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>Sync setup</h2>
|
||||
@ -138,7 +98,7 @@ Use ESP-NOW sync: <input type="checkbox" name="EN"><br><i>(in AP mode or no WiFi
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Receive</h3>
|
||||
<nowrap><input type="checkbox" name="RB">Brightness,</nowrap> <nowrap><input type="checkbox" name="RC">Color,</nowrap> <nowrap>and <input type="checkbox" name="RX">Effects</nowrap><br>
|
||||
<nowrap><input type="checkbox" name="RB">Brightness,</nowrap> <nowrap><input type="checkbox" name="RC">Color,</nowrap> <nowrap><input type="checkbox" name="RX">Effects,</nowrap> <nowrap>and <input type="checkbox" name="RP">Palette</nowrap><br>
|
||||
<input type="checkbox" name="SO"> Segment options, <input type="checkbox" name="SG"> bounds
|
||||
<h3>Send</h3>
|
||||
Enable Sync on start: <input type="checkbox" name="SS"><br>
|
||||
@ -199,7 +159,7 @@ Realtime LED offset: <input name="WO" type="number" min="-255" max="255" require
|
||||
<div id="Alexa">
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
Alexa invocation name: <input type="text" name="AI" maxlength="32"><br>
|
||||
Also emulate devices to call the first <input name="AP" type="number" class="s" min="0" max="9" required> presets<br><br>
|
||||
Also emulate devices to call the first <input name="AP" type="number" class="s" min="0" max="9"> presets<br><br>
|
||||
</div>
|
||||
<hr class="sml">
|
||||
<div class="warn">⚠ <b>MQTT and Hue sync all connect to external hosts!<br>
|
||||
@ -245,6 +205,10 @@ Hue Bridge IP:<br>
|
||||
Hue status: <span class="sip"> Disabled in this build </span>
|
||||
</div>
|
||||
<h3>Serial</h3>
|
||||
<div id="NoSerial" class="hide">
|
||||
<em class="warn">This firmware build does not support Serial interface.<br></em>
|
||||
</div>
|
||||
<div id="Serial">
|
||||
Baud rate:
|
||||
<select name=BD>
|
||||
<option value=1152>115200</option>
|
||||
@ -257,6 +221,7 @@ Baud rate:
|
||||
<option value=15000>1500000</option>
|
||||
</select><br>
|
||||
<i>Keep at 115200 to use Improv. Some boards may not support high rates.</i>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
|
@ -4,60 +4,19 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<meta charset="utf-8">
|
||||
<title>Time Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
var el=false;
|
||||
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#time-settings"); }
|
||||
function B() { window.open(getURL("/settings"),"_self"); }
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function gN(s) { return d.getElementsByName(s)[0]; }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
BTa();GetV();updLoc();Cs();FC();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "time"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=5'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=5'), false, ()=>{BTa();}, ()=>{
|
||||
updLatLon();
|
||||
Cs();
|
||||
FC();
|
||||
}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/time');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
function expand(o,i)
|
||||
{
|
||||
var t = gId("WD"+i);
|
||||
@ -141,21 +100,21 @@
|
||||
td = tr.insertCell(3);
|
||||
td.innerHTML = `<input name="MD${b}" type="number" class="s" min="0" max="250" value="${d}" required>`;
|
||||
}
|
||||
function getLoc() {
|
||||
function getLatLon() {
|
||||
if (!el) {
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.origin !== "https://locate.wled.me") return;
|
||||
if (event.data instanceof Object) {
|
||||
d.Sf.LT.value = event.data.lat;
|
||||
d.Sf.LN.value = event.data.lon;
|
||||
updLoc();
|
||||
updLatLon();
|
||||
}
|
||||
}, false);
|
||||
el = true;
|
||||
}
|
||||
window.open("https://locate.wled.me","_blank");
|
||||
}
|
||||
function updLoc(i) {
|
||||
function updLatLon(i) {
|
||||
if (parseFloat(d.Sf.LT.value)<0) { d.Sf.LTR.value = "S"; d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } else d.Sf.LTR.value = "N";
|
||||
if (parseFloat(d.Sf.LN.value)<0) { d.Sf.LNR.value = "W"; d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } else d.Sf.LNR.value = "E";
|
||||
}
|
||||
@ -165,7 +124,7 @@
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post" onsubmit="Wd()">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('features/settings/#time-settings')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>Time setup</h2>
|
||||
@ -202,7 +161,7 @@
|
||||
Current local time is <span class="times">unknown</span>.<br>
|
||||
Latitude: <select name="LTR"><option value="N">N</option><option value="S">S</option></select><input name="LT" type="number" class="xl" min="0" max="66.6" step="0.01"><br>
|
||||
Longitude: <select name="LNR"><option value="E">E</option><option value="W">W</option></select><input name="LN" type="number" class="xl" min="0" max="180" step="0.01"><br>
|
||||
<button type="button" id="locbtn" onclick="getLoc()">Get location</button>
|
||||
<button type="button" id="locbtn" onclick="getLatLon()">Get location</button>
|
||||
<div><i>(opens new tab, only works in browser)</i></div>
|
||||
<div id="sun" class="times"></div>
|
||||
<h3>Clock</h3>
|
||||
|
@ -4,9 +4,8 @@
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>UI Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d = document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
var initial_ds, initial_st, initial_su, oldUrl;
|
||||
var sett = null;
|
||||
var l = {
|
||||
@ -47,11 +46,6 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); }
|
||||
function isObject(item) {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||
}
|
||||
function set(path, obj, val) {
|
||||
var tar = obj;
|
||||
var pList = path.split('_');
|
||||
@ -63,23 +57,13 @@
|
||||
}
|
||||
tar[pList[len-1]] = val;
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.classList.add(error ? "error":"show");
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.classList.remove("show"); }, 2900);
|
||||
}
|
||||
function addRec(s, path = "", label = null)
|
||||
{
|
||||
var str = "";
|
||||
for (let i in s)
|
||||
{
|
||||
var fk = path + (path?'_':'') + i;
|
||||
if (isObject(s[i])) {
|
||||
if (isO(s[i])) {
|
||||
if (label && label[i] && label[i]["LABEL"]) str += `<h3>${label[i]["LABEL"]}</h3>`;
|
||||
str += addRec(s[i], fk, label? label[i] : null);
|
||||
} else {
|
||||
@ -174,57 +158,16 @@
|
||||
if (d.Sf.DS.value != initial_ds || /*d.Sf.ST.checked != initial_st ||*/ d.Sf.SU.checked != initial_su) d.Sf.submit();
|
||||
}
|
||||
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
function S() {
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=3'), false, undefined, ()=>{
|
||||
initial_ds = d.Sf.DS.value;
|
||||
//initial_st = d.Sf.ST.checked;
|
||||
initial_su = d.Sf.SU.checked;
|
||||
GetLS();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "ui"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
loadJS(getURL('/settings/s.js?p=3'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/ui');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
|
||||
function B() { window.open(getURL("/settings"),"_self"); }
|
||||
function UI()
|
||||
{
|
||||
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
||||
@ -264,25 +207,13 @@
|
||||
if (gId("theme_bg_rnd").checked) toggle("Image");
|
||||
gId("theme_bg_rnd").checked = false;
|
||||
}
|
||||
|
||||
function uploadFile(fO,name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", fO.files[0], name);
|
||||
req.send(formData);
|
||||
fO.value = '';
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('features/settings/#user-interface-settings')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="button" onclick="Save()">Save</button><br>
|
||||
<span id="lssuc" style="color:green; display:none">✔ Local UI settings saved!</span>
|
||||
<span id="lserr" style="color:red; display:none">⚠ Could not access local storage. Make sure it is enabled in your browser.</span><hr>
|
||||
|
@ -4,75 +4,55 @@
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>Usermod Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d = document;
|
||||
d.max_gpio = 50;
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_gpio = [];
|
||||
d.extra = [];
|
||||
var umCfg = {};
|
||||
var pins = [], pinO = [], owner;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
var urows;
|
||||
var numM = 0;
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
|
||||
function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
|
||||
function B() { window.open(getURL("/settings"),"_self"); }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
GetV();
|
||||
for (let r of d.rsvd) { pins.push(r); pinO.push("rsvd"); } // reserved pins
|
||||
if (d.um_p[0]==-1) d.um_p.shift(); // remove filler
|
||||
d.Sf.SDA.max = d.Sf.SCL.max = d.Sf.MOSI.max = d.Sf.SCLK.max = d.Sf.MISO.max = d.max_gpio-1;
|
||||
//for (let i of d.getElementsByTagName("input")) if (i.type === "number" && i.name.replace("[]","").substr(-3) === "pin") i.max = d.max_gpio-1;
|
||||
pinDD(); // convert INPUT to SELECT for pins
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
getLoc();
|
||||
// load settings and insert values into DOM
|
||||
fetch(getURL('/cfg.json'), {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) gId('lserr').style.display = "inline";
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
umCfg = json.um;
|
||||
getPins(json);
|
||||
urows="";
|
||||
if (isO(umCfg)) {
|
||||
for (const [k,o] of Object.entries(umCfg)) {
|
||||
urows += `<hr><h3>${k}</h3>`;
|
||||
addField(k,'unknown',o);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "um"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
ldS();
|
||||
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
||||
gId("um").innerHTML = urows;
|
||||
loadJS(getURL('/settings/s.js?p=8'), false, ()=>{
|
||||
d.max_gpio = 50;
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_gpio = [];
|
||||
d.extra = [];
|
||||
}, ()=>{
|
||||
for (let r of d.rsvd) { pins.push(r); pinO.push("rsvd"); } // reserved pins
|
||||
if (d.um_p[0]==-1) d.um_p.shift(); // remove filler
|
||||
d.Sf.SDA.max = d.Sf.SCL.max = d.Sf.MOSI.max = d.Sf.SCLK.max = d.Sf.MISO.max = d.max_gpio;
|
||||
//for (let i of d.getElementsByTagName("input")) if (i.type === "number" && i.name.replace("[]","").substr(-3) === "pin") i.max = d.max_gpio;
|
||||
pinDD(); // convert INPUT to SELECT for pins
|
||||
}); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
})
|
||||
.catch((error)=>{
|
||||
gId('lserr').style.display = "inline";
|
||||
console.log(error);
|
||||
});
|
||||
if (!numM) gId("um").innerHTML = "No Usermods installed.";
|
||||
if (loc) d.Sf.action = getURL('/settings/um');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
|
||||
function isF(n) { return n === +n && n !== (n|0); }
|
||||
function isI(n) { return n === +n && n === (n|0); }
|
||||
function check(o,k) { // input object, pin owner key
|
||||
/* no longer necessary with pin dropdown fields
|
||||
var n = o.name.replace("[]","").substr(-3);
|
||||
@ -220,7 +200,7 @@
|
||||
}
|
||||
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
||||
function addDD(um,fld) {
|
||||
let sel = d.createElement('select');
|
||||
let sel = cE('select');
|
||||
if (typeof(fld) === "string") { // parameter from usermod (field name)
|
||||
if (fld.includes("pin")) sel.classList.add("pin");
|
||||
um += ":"+fld;
|
||||
@ -258,7 +238,7 @@
|
||||
var addDropdown = addDD; // backwards compatibility
|
||||
function addO(sel,txt,val) {
|
||||
if (sel===null) return; // select object missing
|
||||
let opt = d.createElement("option");
|
||||
let opt = cE("option");
|
||||
opt.value = val;
|
||||
opt.text = txt;
|
||||
sel.appendChild(opt);
|
||||
@ -284,34 +264,6 @@
|
||||
function addHB(um) {
|
||||
addI(um + ':help',0,`<button onclick="location.href='https://kno.wled.ge/usermods/${um}'" type="button">?</button>`);
|
||||
}
|
||||
// load settings and insert values into DOM
|
||||
function ldS() {
|
||||
fetch(getURL('/cfg.json'), {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) gId('lserr').style.display = "inline";
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
umCfg = json.um;
|
||||
getPins(json);
|
||||
urows="";
|
||||
if (isO(umCfg)) {
|
||||
for (const [k,o] of Object.entries(umCfg)) {
|
||||
urows += `<hr><h3>${k}</h3>`;
|
||||
addField(k,'unknown',o);
|
||||
}
|
||||
}
|
||||
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
||||
gId("um").innerHTML = urows;
|
||||
loadJS(getURL('/settings/s.js?p=8'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
})
|
||||
.catch((error)=>{
|
||||
gId('lserr').style.display = "inline";
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
function svS(e) {
|
||||
e.preventDefault();
|
||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||
|
@ -4,16 +4,10 @@
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>WiFi Settings</title>
|
||||
<script src="common.js" async type="text/javascript"></script>
|
||||
<script>
|
||||
var d = document;
|
||||
var loc = false, locip, locproto = "http:";
|
||||
var scanLoops = 0, preScanSSID = "";
|
||||
var maxNetworks = 3;
|
||||
function gId(e) { return d.getElementById(e); }
|
||||
function cE(e) { return d.createElement(e); }
|
||||
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
||||
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
|
||||
function B(){window.open(getURL("/settings"),"_self");}
|
||||
function N() {
|
||||
const button = gId("scan");
|
||||
button.disabled = true;
|
||||
@ -137,58 +131,18 @@ Static subnet mask:<br>
|
||||
entries[i-1].remove();
|
||||
btnWiFi(i-1);
|
||||
}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = cE("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
let l = window.location;
|
||||
if (l.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
} else {
|
||||
// detect reverse proxy
|
||||
let path = l.pathname;
|
||||
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
|
||||
if (paths.length > 2) {
|
||||
paths.pop(); // remove "wifi"
|
||||
paths.pop(); // remove "settings"
|
||||
locproto = l.protocol;
|
||||
loc = true;
|
||||
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
|
||||
}
|
||||
}
|
||||
getLoc();
|
||||
loadJS(getURL('/settings/s.js?p=1'), false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
if (loc) d.Sf.action = getURL('/settings/wifi');
|
||||
}
|
||||
function getURL(path) {
|
||||
return (loc ? locproto + "//" + locip : "") + path;
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<div class="helpB"><button type="button" onclick="H('features/settings/#wifi-settings')">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button><hr>
|
||||
</div>
|
||||
<h2>WiFi setup</h2>
|
||||
|
@ -317,34 +317,34 @@ class Usermod {
|
||||
|
||||
class UsermodManager {
|
||||
private:
|
||||
Usermod* ums[WLED_MAX_USERMODS];
|
||||
byte numMods = 0;
|
||||
static Usermod* ums[WLED_MAX_USERMODS];
|
||||
static byte numMods;
|
||||
|
||||
public:
|
||||
void loop();
|
||||
void handleOverlayDraw();
|
||||
bool handleButton(uint8_t b);
|
||||
bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
|
||||
void setup();
|
||||
void connected();
|
||||
void appendConfigData();
|
||||
void addToJsonState(JsonObject& obj);
|
||||
void addToJsonInfo(JsonObject& obj);
|
||||
void readFromJsonState(JsonObject& obj);
|
||||
void addToConfig(JsonObject& obj);
|
||||
bool readFromConfig(JsonObject& obj);
|
||||
static void loop();
|
||||
static void handleOverlayDraw();
|
||||
static bool handleButton(uint8_t b);
|
||||
static bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
|
||||
static void setup();
|
||||
static void connected();
|
||||
static void appendConfigData();
|
||||
static void addToJsonState(JsonObject& obj);
|
||||
static void addToJsonInfo(JsonObject& obj);
|
||||
static void readFromJsonState(JsonObject& obj);
|
||||
static void addToConfig(JsonObject& obj);
|
||||
static bool readFromConfig(JsonObject& obj);
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
void onMqttConnect(bool sessionPresent);
|
||||
bool onMqttMessage(char* topic, char* payload);
|
||||
static void onMqttConnect(bool sessionPresent);
|
||||
static bool onMqttMessage(char* topic, char* payload);
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_ESPNOW
|
||||
bool onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len);
|
||||
static bool onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len);
|
||||
#endif
|
||||
void onUpdateBegin(bool);
|
||||
void onStateChange(uint8_t);
|
||||
bool add(Usermod* um);
|
||||
Usermod* lookup(uint16_t mod_id);
|
||||
byte getModCount() {return numMods;};
|
||||
static void onUpdateBegin(bool);
|
||||
static void onStateChange(uint8_t);
|
||||
static bool add(Usermod* um);
|
||||
static Usermod* lookup(uint16_t mod_id);
|
||||
static inline byte getModCount() {return numMods;};
|
||||
};
|
||||
|
||||
//usermods_list.cpp
|
||||
|
@ -714,9 +714,8 @@ void handleIR()
|
||||
if (strip.isUpdating() && timeDiff < 240) return; // be nice, but not too nice
|
||||
irCheckedTime = currentTime;
|
||||
if (irrecv->decode(&results)) {
|
||||
if (results.value != 0) { // only print results if anything is received ( != 0 )
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) // Serial TX pin (GPIO 1 on ESP32 and ESP8266)
|
||||
Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value);
|
||||
if (results.value != 0 && serialCanTX) { // only print results if anything is received ( != 0 )
|
||||
Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value);
|
||||
}
|
||||
decodeIR(results.value);
|
||||
irrecv->resume();
|
||||
|
@ -441,7 +441,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
}
|
||||
strip.resume();
|
||||
|
||||
usermods.readFromJsonState(root);
|
||||
UsermodManager::readFromJsonState(root);
|
||||
|
||||
loadLedmap = root[F("ledmap")] | loadLedmap;
|
||||
|
||||
@ -600,7 +600,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
|
||||
root[F("pl")] = currentPlaylist;
|
||||
root[F("ledmap")] = currentLedmap;
|
||||
|
||||
usermods.addToJsonState(root);
|
||||
UsermodManager::addToJsonState(root);
|
||||
|
||||
JsonObject nl = root.createNestedObject("nl");
|
||||
nl["on"] = nightlightActive;
|
||||
@ -792,7 +792,7 @@ void serializeInfo(JsonObject root)
|
||||
getTimeString(time);
|
||||
root[F("time")] = time;
|
||||
|
||||
usermods.addToJsonInfo(root);
|
||||
UsermodManager::addToJsonInfo(root);
|
||||
|
||||
uint16_t os = 0;
|
||||
#ifdef WLED_DEBUG
|
||||
|
@ -126,7 +126,7 @@ void stateUpdated(byte callMode) {
|
||||
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
|
||||
|
||||
// notify usermods of state change
|
||||
usermods.onStateChange(callMode);
|
||||
UsermodManager::onStateChange(callMode);
|
||||
|
||||
if (strip.getTransition() == 0) {
|
||||
jsonTransitionOnce = false;
|
||||
|
@ -45,7 +45,7 @@ static void onMqttConnect(bool sessionPresent)
|
||||
mqtt->subscribe(subuf, 0);
|
||||
}
|
||||
|
||||
usermods.onMqttConnect(sessionPresent);
|
||||
UsermodManager::onMqttConnect(sessionPresent);
|
||||
|
||||
DEBUG_PRINTLN(F("MQTT ready"));
|
||||
publishMqtt();
|
||||
@ -89,7 +89,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
|
||||
topic += topicPrefixLen;
|
||||
} else {
|
||||
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
||||
usermods.onMqttMessage(topic, payloadStr);
|
||||
UsermodManager::onMqttMessage(topic, payloadStr);
|
||||
delete[] payloadStr;
|
||||
payloadStr = nullptr;
|
||||
return;
|
||||
@ -115,7 +115,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
|
||||
}
|
||||
} else if (strlen(topic) != 0) {
|
||||
// non standard topic, check with usermods
|
||||
usermods.onMqttMessage(topic, payloadStr);
|
||||
UsermodManager::onMqttMessage(topic, payloadStr);
|
||||
} else {
|
||||
// topmost topic (just wled/MAC)
|
||||
parseMQTTBriPayload(payloadStr);
|
||||
|
@ -88,7 +88,7 @@ void _overlayAnalogCountdown()
|
||||
}
|
||||
|
||||
void handleOverlayDraw() {
|
||||
usermods.handleOverlayDraw();
|
||||
UsermodManager::handleOverlayDraw();
|
||||
if (analogClockSolidBlack) {
|
||||
const Segment* segments = strip.getSegments();
|
||||
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
|
@ -1,34 +1,28 @@
|
||||
#include "pin_manager.h"
|
||||
#include "wled.h"
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
static void DebugPrintOwnerTag(PinOwner tag)
|
||||
{
|
||||
uint32_t q = static_cast<uint8_t>(tag);
|
||||
if (q) {
|
||||
DEBUG_PRINTF_P(PSTR("0x%02x (%d)"), q, q);
|
||||
} else {
|
||||
DEBUG_PRINT(F("(no owner)"));
|
||||
}
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef bitRead
|
||||
// Arduino variants assume 32 bit values
|
||||
#undef bitRead
|
||||
#undef bitSet
|
||||
#undef bitClear
|
||||
#define bitRead(var,bit) (((unsigned long long)(var)>>(bit))&0x1ULL)
|
||||
#define bitSet(var,bit) ((var)|=(1ULL<<(bit)))
|
||||
#define bitClear(var,bit) ((var)&=(~(1ULL<<(bit))))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/// Actual allocation/deallocation routines
|
||||
bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
|
||||
bool PinManager::deallocatePin(byte gpio, PinOwner tag)
|
||||
{
|
||||
if (gpio == 0xFF) return true; // explicitly allow clients to free -1 as a no-op
|
||||
if (!isPinOk(gpio, false)) return false; // but return false for any other invalid pin
|
||||
|
||||
// if a non-zero ownerTag, only allow de-allocation if the owner's tag is provided
|
||||
if ((ownerTag[gpio] != PinOwner::None) && (ownerTag[gpio] != tag)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN DEALLOC: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINT(F(", but attempted de-allocation by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN DEALLOC: FAIL GPIO %d allocated by 0x%02X, but attempted de-allocation by 0x%02X.\n"), gpio, static_cast<int>(ownerTag[gpio]), static_cast<int>(tag));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -38,7 +32,7 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
|
||||
}
|
||||
|
||||
// support function for deallocating multiple pins
|
||||
bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag)
|
||||
bool PinManager::deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
DEBUG_PRINTLN(F("MULTIPIN DEALLOC"));
|
||||
@ -54,14 +48,7 @@ bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte array
|
||||
// if the current pin is allocated by selected owner it is possible to release it
|
||||
continue;
|
||||
}
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN DEALLOC: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINT(F(", but attempted de-allocation by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN DEALLOC: FAIL GPIO %d allocated by 0x%02X, but attempted de-allocation by 0x%02X.\n"), gpio, static_cast<int>(ownerTag[gpio]), static_cast<int>(tag));
|
||||
shouldFail = true;
|
||||
}
|
||||
if (shouldFail) {
|
||||
@ -85,14 +72,14 @@ bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte array
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinManagerClass::deallocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
bool PinManager::deallocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
uint8_t pins[arrayElementCount];
|
||||
for (int i=0; i<arrayElementCount; i++) pins[i] = mptArray[i].pin;
|
||||
return deallocateMultiplePins(pins, arrayElementCount, tag);
|
||||
}
|
||||
|
||||
bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
bool PinManager::allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
// first verify the pins are OK and not already allocated
|
||||
@ -104,25 +91,14 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
continue;
|
||||
}
|
||||
if (!isPinOk(gpio, mptArray[i].isOutput)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: GPIO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" as ")); DEBUG_PRINT(mptArray[i].isOutput ? F("output"): F("input"));
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL Invalid pin attempted to be allocated: GPIO %d as %s\n."), gpio, mptArray[i].isOutput ? PSTR("output"): PSTR("input"));
|
||||
shouldFail = true;
|
||||
}
|
||||
if ((tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) && isPinAllocated(gpio, tag)) {
|
||||
// allow multiple "allocations" of HW I2C & SPI bus pins
|
||||
continue;
|
||||
} else if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" already allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL GPIO %d already allocated by 0x%02X.\n"), gpio, static_cast<int>(ownerTag[gpio]));
|
||||
shouldFail = true;
|
||||
}
|
||||
}
|
||||
@ -146,64 +122,45 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
|
||||
bitWrite(pinAlloc, gpio, true);
|
||||
ownerTag[gpio] = tag;
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: Pin %d allocated by 0x%02X.\n"), gpio, static_cast<int>(tag));
|
||||
}
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: 0x%014llX.\n"), (unsigned long long)pinAlloc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
bool PinManager::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
{
|
||||
// HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
|
||||
if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) {
|
||||
#ifdef WLED_DEBUG
|
||||
if (gpio < 255) { // 255 (-1) is the "not defined GPIO"
|
||||
if (!isPinOk(gpio, output)) {
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL for owner "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
DEBUG_PRINT(F(": GPIO ")); DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL for owner 0x%02X: GPIO %d "), static_cast<int>(tag), gpio);
|
||||
if (output) DEBUG_PRINTLN(F(" cannot be used for i/o on this MCU."));
|
||||
else DEBUG_PRINTLN(F(" cannot be used as input on this MCU."));
|
||||
} else {
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL: GPIO ")); DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINTLN(F(" - HW I2C & SPI pins have to be allocated using allocateMultiplePins()"));
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL GPIO %d - HW I2C & SPI pins have to be allocated using allocateMultiplePins.\n"), gpio);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" already allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: FAIL Pin %d already allocated by 0x%02X.\n"), gpio, static_cast<int>(ownerTag[gpio]));
|
||||
return false;
|
||||
}
|
||||
|
||||
bitWrite(pinAlloc, gpio, true);
|
||||
ownerTag[gpio] = tag;
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" successfully allocated by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: Pin %d successfully allocated by 0x%02X.\n"), gpio, static_cast<int>(ownerTag[gpio]));
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC: 0x%014llX.\n"), (unsigned long long)pinAlloc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// if tag is set to PinOwner::None, checks for ANY owner of the pin.
|
||||
// if tag is set to any other value, checks if that tag is the current owner of the pin.
|
||||
bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) const
|
||||
bool PinManager::isPinAllocated(byte gpio, PinOwner tag)
|
||||
{
|
||||
if (!isPinOk(gpio, false)) return true;
|
||||
if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false;
|
||||
@ -227,7 +184,7 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag) const
|
||||
*/
|
||||
|
||||
// Check if supplied GPIO is ok to use
|
||||
bool PinManagerClass::isPinOk(byte gpio, bool output) const
|
||||
bool PinManager::isPinOk(byte gpio, bool output)
|
||||
{
|
||||
if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
@ -267,7 +224,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PinManagerClass::isReadOnlyPin(byte gpio)
|
||||
bool PinManager::isReadOnlyPin(byte gpio)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (gpio < WLED_NUM_PINS) return (digitalPinIsValid(gpio) && !digitalPinCanOutput(gpio));
|
||||
@ -275,14 +232,14 @@ bool PinManagerClass::isReadOnlyPin(byte gpio)
|
||||
return false;
|
||||
}
|
||||
|
||||
PinOwner PinManagerClass::getPinOwner(byte gpio) const
|
||||
PinOwner PinManager::getPinOwner(byte gpio)
|
||||
{
|
||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||
return ownerTag[gpio];
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
byte PinManagerClass::allocateLedc(byte channels)
|
||||
byte PinManager::allocateLedc(byte channels)
|
||||
{
|
||||
if (channels > WLED_MAX_ANALOG_CHANNELS || channels == 0) return 255;
|
||||
unsigned ca = 0;
|
||||
@ -309,7 +266,7 @@ byte PinManagerClass::allocateLedc(byte channels)
|
||||
return 255; //not enough consecutive free LEDC channels
|
||||
}
|
||||
|
||||
void PinManagerClass::deallocateLedc(byte pos, byte channels)
|
||||
void PinManager::deallocateLedc(byte pos, byte channels)
|
||||
{
|
||||
for (unsigned j = pos; j < pos + channels && j < WLED_MAX_ANALOG_CHANNELS; j++) {
|
||||
bitWrite(ledcAlloc, j, false);
|
||||
@ -317,4 +274,12 @@ void PinManagerClass::deallocateLedc(byte pos, byte channels)
|
||||
}
|
||||
#endif
|
||||
|
||||
PinManagerClass pinManager = PinManagerClass();
|
||||
#ifdef ESP8266
|
||||
uint32_t PinManager::pinAlloc = 0UL;
|
||||
#else
|
||||
uint64_t PinManager::pinAlloc = 0ULL;
|
||||
uint16_t PinManager::ledcAlloc = 0;
|
||||
#endif
|
||||
uint8_t PinManager::i2cAllocCount = 0;
|
||||
uint8_t PinManager::spiAllocCount = 0;
|
||||
PinOwner PinManager::ownerTag[WLED_NUM_PINS] = { PinOwner::None };
|
||||
|
@ -70,57 +70,54 @@ enum struct PinOwner : uint8_t {
|
||||
};
|
||||
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
||||
|
||||
class PinManagerClass {
|
||||
class PinManager {
|
||||
private:
|
||||
struct {
|
||||
#ifdef ESP8266
|
||||
#define WLED_NUM_PINS (GPIO_PIN_COUNT+1) // somehow they forgot GPIO 16 (0-16==17)
|
||||
uint32_t pinAlloc : 24; // 24bit, 1 bit per pin, we use first 17bits
|
||||
#define WLED_NUM_PINS (GPIO_PIN_COUNT+1) // somehow they forgot GPIO 16 (0-16==17)
|
||||
static uint32_t pinAlloc; // 1 bit per pin, we use first 17bits
|
||||
#else
|
||||
#define WLED_NUM_PINS (GPIO_PIN_COUNT)
|
||||
uint64_t pinAlloc : 56; // 56 bits, 1 bit per pin, we use 50 bits on ESP32-S3
|
||||
uint16_t ledcAlloc : 16; // up to 16 LEDC channels (WLED_MAX_ANALOG_CHANNELS)
|
||||
#define WLED_NUM_PINS (GPIO_PIN_COUNT)
|
||||
static uint64_t pinAlloc; // 1 bit per pin, we use 50 bits on ESP32-S3
|
||||
static uint16_t ledcAlloc; // up to 16 LEDC channels (WLED_MAX_ANALOG_CHANNELS)
|
||||
#endif
|
||||
uint8_t i2cAllocCount : 4; // allow multiple allocation of I2C bus pins but keep track of allocations
|
||||
uint8_t spiAllocCount : 4; // allow multiple allocation of SPI bus pins but keep track of allocations
|
||||
} __attribute__ ((packed));
|
||||
PinOwner ownerTag[WLED_NUM_PINS] = { PinOwner::None };
|
||||
static uint8_t i2cAllocCount; // allow multiple allocation of I2C bus pins but keep track of allocations
|
||||
static uint8_t spiAllocCount; // allow multiple allocation of SPI bus pins but keep track of allocations
|
||||
static PinOwner ownerTag[WLED_NUM_PINS];
|
||||
|
||||
public:
|
||||
PinManagerClass() : pinAlloc(0), i2cAllocCount(0), spiAllocCount(0) {}
|
||||
// De-allocates a single pin
|
||||
bool deallocatePin(byte gpio, PinOwner tag);
|
||||
// De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified)
|
||||
bool deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
bool deallocateMultiplePins(const managed_pin_type *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
// Allocates a single pin, with an owner tag.
|
||||
// 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
|
||||
// using more than one pin, such as I2C, SPI, rotary encoders,
|
||||
// ethernet, etc..
|
||||
bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag );
|
||||
// De-allocates a single pin
|
||||
static bool deallocatePin(byte gpio, PinOwner tag);
|
||||
// De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified)
|
||||
static bool deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
static bool deallocateMultiplePins(const managed_pin_type *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
// Allocates a single pin, with an owner tag.
|
||||
// De-allocation requires the same owner tag (or override)
|
||||
static 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
|
||||
// using more than one pin, such as I2C, SPI, rotary encoders,
|
||||
// ethernet, etc..
|
||||
static bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag );
|
||||
|
||||
[[deprecated("Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging")]]
|
||||
inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); }
|
||||
[[deprecated("Replaced by two-parameter deallocatePin(gpio, ownerTag), for improved debugging")]]
|
||||
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
|
||||
[[deprecated("Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging")]]
|
||||
static inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); }
|
||||
[[deprecated("Replaced by two-parameter deallocatePin(gpio, ownerTag), for improved debugging")]]
|
||||
static inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
|
||||
|
||||
// will return true for reserved pins
|
||||
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None) const;
|
||||
// will return false for reserved pins
|
||||
bool isPinOk(byte gpio, bool output = true) const;
|
||||
|
||||
static bool isReadOnlyPin(byte gpio);
|
||||
// will return true for reserved pins
|
||||
static bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
||||
// will return false for reserved pins
|
||||
static bool isPinOk(byte gpio, bool output = true);
|
||||
|
||||
static bool isReadOnlyPin(byte gpio);
|
||||
|
||||
PinOwner getPinOwner(byte gpio) const;
|
||||
static PinOwner getPinOwner(byte gpio);
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
byte allocateLedc(byte channels);
|
||||
void deallocateLedc(byte pos, byte channels);
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
static byte allocateLedc(byte channels);
|
||||
static void deallocateLedc(byte pos, byte channels);
|
||||
#endif
|
||||
};
|
||||
|
||||
extern PinManagerClass pinManager;
|
||||
//extern PinManager pinManager;
|
||||
#endif
|
||||
|
@ -104,18 +104,18 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin, PinOwner::Relay)) {
|
||||
pinManager.deallocatePin(rlyPin, PinOwner::Relay);
|
||||
if (rlyPin>=0 && PinManager::isPinAllocated(rlyPin, PinOwner::Relay)) {
|
||||
PinManager::deallocatePin(rlyPin, PinOwner::Relay);
|
||||
}
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
if (irPin>=0 && pinManager.isPinAllocated(irPin, PinOwner::IR)) {
|
||||
if (irPin>=0 && PinManager::isPinAllocated(irPin, PinOwner::IR)) {
|
||||
deInitIR();
|
||||
pinManager.deallocatePin(irPin, PinOwner::IR);
|
||||
PinManager::deallocatePin(irPin, PinOwner::IR);
|
||||
}
|
||||
#endif
|
||||
for (unsigned s=0; s<WLED_MAX_BUTTONS; s++) {
|
||||
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s], PinOwner::Button)) {
|
||||
pinManager.deallocatePin(btnPin[s], PinOwner::Button);
|
||||
if (btnPin[s]>=0 && PinManager::isPinAllocated(btnPin[s], PinOwner::Button)) {
|
||||
PinManager::deallocatePin(btnPin[s], PinOwner::Button);
|
||||
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state, detach interrupt
|
||||
if (digitalPinToTouchChannel(btnPin[s]) >= 0) // if touch capable pin
|
||||
touchDetachInterrupt(btnPin[s]); // if not assigned previously, this will do nothing
|
||||
@ -233,7 +233,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
// update other pins
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||
if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) {
|
||||
if (PinManager::allocatePin(hw_ir_pin,false, PinOwner::IR)) {
|
||||
irPin = hw_ir_pin;
|
||||
} else {
|
||||
irPin = -1;
|
||||
@ -244,7 +244,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
irApplyToAllSelected = !request->hasArg(F("MSO"));
|
||||
|
||||
int hw_rly_pin = request->arg(F("RL")).toInt();
|
||||
if (pinManager.allocatePin(hw_rly_pin,true, PinOwner::Relay)) {
|
||||
if (PinManager::allocatePin(hw_rly_pin,true, PinOwner::Relay)) {
|
||||
rlyPin = hw_rly_pin;
|
||||
} else {
|
||||
rlyPin = -1;
|
||||
@ -259,7 +259,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
|
||||
char be[4] = "BE"; be[2] = offset+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10)
|
||||
int hw_btn_pin = request->arg(bt).toInt();
|
||||
if (hw_btn_pin >= 0 && pinManager.allocatePin(hw_btn_pin,false,PinOwner::Button)) {
|
||||
if (hw_btn_pin >= 0 && PinManager::allocatePin(hw_btn_pin,false,PinOwner::Button)) {
|
||||
btnPin[i] = hw_btn_pin;
|
||||
buttonType[i] = request->arg(be).toInt();
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
@ -270,7 +270,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
// not an ADC analog pin
|
||||
DEBUG_PRINTF_P(PSTR("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);
|
||||
PinManager::deallocatePin(hw_btn_pin,PinOwner::Button);
|
||||
} else {
|
||||
analogReadResolution(12); // see #4040
|
||||
}
|
||||
@ -282,7 +282,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
// not a touch pin
|
||||
DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not an touch pin!\n"), btnPin[i], i);
|
||||
btnPin[i] = -1;
|
||||
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button);
|
||||
PinManager::deallocatePin(hw_btn_pin,PinOwner::Button);
|
||||
}
|
||||
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a fucntion to check touch state but need to attach an interrupt to do so
|
||||
else
|
||||
@ -376,6 +376,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
receiveNotificationBrightness = request->hasArg(F("RB"));
|
||||
receiveNotificationColor = request->hasArg(F("RC"));
|
||||
receiveNotificationEffects = request->hasArg(F("RX"));
|
||||
receiveNotificationPalette = request->hasArg(F("RP"));
|
||||
receiveSegmentOptions = request->hasArg(F("SO"));
|
||||
receiveSegmentBounds = request->hasArg(F("SG"));
|
||||
sendNotifications = request->hasArg(F("SS"));
|
||||
@ -627,10 +628,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (i2c_sda != hw_sda_pin || i2c_scl != hw_scl_pin) {
|
||||
// only if pins changed
|
||||
uint8_t old_i2c[2] = { static_cast<uint8_t>(i2c_scl), static_cast<uint8_t>(i2c_sda) };
|
||||
pinManager.deallocateMultiplePins(old_i2c, 2, PinOwner::HW_I2C); // just in case deallocation of old pins
|
||||
PinManager::deallocateMultiplePins(old_i2c, 2, PinOwner::HW_I2C); // just in case deallocation of old pins
|
||||
|
||||
PinManagerPinType i2c[2] = { { hw_sda_pin, true }, { hw_scl_pin, true } };
|
||||
if (hw_sda_pin >= 0 && hw_scl_pin >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
if (hw_sda_pin >= 0 && hw_scl_pin >= 0 && PinManager::allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
i2c_sda = hw_sda_pin;
|
||||
i2c_scl = hw_scl_pin;
|
||||
// no bus re-initialisation as usermods do not get any notification
|
||||
@ -654,9 +655,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (spi_mosi != hw_mosi_pin || spi_miso != hw_miso_pin || spi_sclk != hw_sclk_pin) {
|
||||
// only if pins changed
|
||||
uint8_t old_spi[3] = { static_cast<uint8_t>(spi_mosi), static_cast<uint8_t>(spi_miso), static_cast<uint8_t>(spi_sclk) };
|
||||
pinManager.deallocateMultiplePins(old_spi, 3, PinOwner::HW_SPI); // just in case deallocation of old pins
|
||||
PinManager::deallocateMultiplePins(old_spi, 3, PinOwner::HW_SPI); // just in case deallocation of old pins
|
||||
PinManagerPinType spi[3] = { { hw_mosi_pin, true }, { hw_miso_pin, true }, { hw_sclk_pin, true } };
|
||||
if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
|
||||
if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && PinManager::allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
|
||||
spi_mosi = hw_mosi_pin;
|
||||
spi_miso = hw_miso_pin;
|
||||
spi_sclk = hw_sclk_pin;
|
||||
@ -746,8 +747,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
DEBUG_PRINTF_P(PSTR(" = %s\n"), value.c_str());
|
||||
}
|
||||
}
|
||||
usermods.readFromConfig(um); // force change of usermod parameters
|
||||
DEBUG_PRINTLN(F("Done re-init usermods."));
|
||||
UsermodManager::readFromConfig(um); // force change of usermod parameters
|
||||
DEBUG_PRINTLN(F("Done re-init UsermodManager::"));
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ void parseNotifyPacket(uint8_t *udpIn) {
|
||||
if (!(receiveGroups & 0x01)) return;
|
||||
} else if (!(receiveGroups & udpIn[36])) return;
|
||||
|
||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects || receiveNotificationPalette);
|
||||
|
||||
// set transition time before making any segment changes
|
||||
if (version > 3) {
|
||||
@ -309,6 +309,9 @@ void parseNotifyPacket(uint8_t *udpIn) {
|
||||
selseg.setMode(udpIn[11+ofs]);
|
||||
selseg.speed = udpIn[12+ofs];
|
||||
selseg.intensity = udpIn[13+ofs];
|
||||
}
|
||||
if (receiveNotificationPalette || !someSel) {
|
||||
DEBUG_PRINTF_P(PSTR("Apply palette: %u\n"), id);
|
||||
selseg.palette = udpIn[14+ofs];
|
||||
}
|
||||
if (receiveNotificationColor || !someSel) {
|
||||
@ -350,14 +353,16 @@ void parseNotifyPacket(uint8_t *udpIn) {
|
||||
}
|
||||
|
||||
// simple effect sync, applies to all selected segments
|
||||
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
|
||||
if ((applyEffects || receiveNotificationPalette) && (version < 11 || !receiveSegmentOptions)) {
|
||||
for (size_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
seg.setMode(udpIn[8]);
|
||||
seg.speed = udpIn[9];
|
||||
if (version > 2) seg.intensity = udpIn[16];
|
||||
if (version > 4) seg.setPalette(udpIn[19]);
|
||||
if (applyEffects) {
|
||||
seg.setMode(udpIn[8]);
|
||||
seg.speed = udpIn[9];
|
||||
if (version > 2) seg.intensity = udpIn[16];
|
||||
}
|
||||
if (version > 4 && receiveNotificationPalette) seg.setPalette(udpIn[19]);
|
||||
}
|
||||
stateChanged = true;
|
||||
}
|
||||
@ -969,7 +974,7 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs
|
||||
|
||||
#ifndef WLED_DISABLE_ESPNOW
|
||||
// usermods hook can override processing
|
||||
if (usermods.onEspNowMessage(address, data, len)) return;
|
||||
if (UsermodManager::onEspNowMessage(address, data, len)) return;
|
||||
#endif
|
||||
|
||||
// handle WiZ Mote data
|
||||
|
@ -68,3 +68,6 @@ bool UsermodManager::add(Usermod* um)
|
||||
ums[numMods++] = um;
|
||||
return true;
|
||||
}
|
||||
|
||||
Usermod* UsermodManager::ums[WLED_MAX_USERMODS] = {nullptr};
|
||||
byte UsermodManager::numMods = 0;
|
||||
|
@ -249,225 +249,225 @@ void registerUsermods()
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//UsermodManager::add(new MyExampleUsermod());
|
||||
|
||||
#ifdef USERMOD_BATTERY
|
||||
usermods.add(new UsermodBattery());
|
||||
UsermodManager::add(new UsermodBattery());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
usermods.add(new UsermodTemperature());
|
||||
UsermodManager::add(new UsermodTemperature());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||
usermods.add(new Usermod_SN_Photoresistor());
|
||||
UsermodManager::add(new Usermod_SN_Photoresistor());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PWM_FAN
|
||||
usermods.add(new PWMFanUsermod());
|
||||
UsermodManager::add(new PWMFanUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BUZZER
|
||||
usermods.add(new BuzzerUsermod());
|
||||
UsermodManager::add(new BuzzerUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BH1750
|
||||
usermods.add(new Usermod_BH1750());
|
||||
UsermodManager::add(new Usermod_BH1750());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BME280
|
||||
usermods.add(new UsermodBME280());
|
||||
UsermodManager::add(new UsermodBME280());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BME68X
|
||||
usermods.add(new UsermodBME68X());
|
||||
UsermodManager::add(new UsermodBME68X());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SENSORSTOMQTT
|
||||
usermods.add(new UserMod_SensorsToMQTT());
|
||||
UsermodManager::add(new UserMod_SensorsToMQTT());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PIRSWITCH
|
||||
usermods.add(new PIRsensorSwitch());
|
||||
UsermodManager::add(new PIRsensorSwitch());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
usermods.add(new FourLineDisplayUsermod());
|
||||
UsermodManager::add(new FourLineDisplayUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ROTARY_ENCODER_UI
|
||||
usermods.add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
|
||||
UsermodManager::add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUTO_SAVE
|
||||
usermods.add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
|
||||
UsermodManager::add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_DHT
|
||||
usermods.add(new UsermodDHT());
|
||||
UsermodManager::add(new UsermodDHT());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_VL53L0X_GESTURES
|
||||
usermods.add(new UsermodVL53L0XGestures());
|
||||
UsermodManager::add(new UsermodVL53L0XGestures());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ANIMATED_STAIRCASE
|
||||
usermods.add(new Animated_Staircase());
|
||||
UsermodManager::add(new Animated_Staircase());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_MULTI_RELAY
|
||||
usermods.add(new MultiRelay());
|
||||
UsermodManager::add(new MultiRelay());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_RTC
|
||||
usermods.add(new RTCUsermod());
|
||||
UsermodManager::add(new RTCUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ELEKSTUBE_IPS
|
||||
usermods.add(new ElekstubeIPSUsermod());
|
||||
UsermodManager::add(new ElekstubeIPSUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR
|
||||
usermods.add(new RotaryEncoderBrightnessColor());
|
||||
UsermodManager::add(new RotaryEncoderBrightnessColor());
|
||||
#endif
|
||||
|
||||
#ifdef RGB_ROTARY_ENCODER
|
||||
usermods.add(new RgbRotaryEncoderUsermod());
|
||||
UsermodManager::add(new RgbRotaryEncoderUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ST7789_DISPLAY
|
||||
usermods.add(new St7789DisplayUsermod());
|
||||
UsermodManager::add(new St7789DisplayUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PIXELS_DICE_TRAY
|
||||
usermods.add(new PixelsDiceTrayUsermod());
|
||||
UsermodManager::add(new PixelsDiceTrayUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SEVEN_SEGMENT
|
||||
usermods.add(new SevenSegmentDisplay());
|
||||
UsermodManager::add(new SevenSegmentDisplay());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SSDR
|
||||
usermods.add(new UsermodSSDR());
|
||||
UsermodManager::add(new UsermodSSDR());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_CRONIXIE
|
||||
usermods.add(new UsermodCronixie());
|
||||
UsermodManager::add(new UsermodCronixie());
|
||||
#endif
|
||||
|
||||
#ifdef QUINLED_AN_PENTA
|
||||
usermods.add(new QuinLEDAnPentaUsermod());
|
||||
UsermodManager::add(new QuinLEDAnPentaUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_WIZLIGHTS
|
||||
usermods.add(new WizLightsUsermod());
|
||||
UsermodManager::add(new WizLightsUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_WIREGUARD
|
||||
usermods.add(new WireguardUsermod());
|
||||
UsermodManager::add(new WireguardUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_WORDCLOCK
|
||||
usermods.add(new WordClockUsermod());
|
||||
UsermodManager::add(new WordClockUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_MY9291
|
||||
usermods.add(new MY9291Usermod());
|
||||
UsermodManager::add(new MY9291Usermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SI7021_MQTT_HA
|
||||
usermods.add(new Si7021_MQTT_HA());
|
||||
UsermodManager::add(new Si7021_MQTT_HA());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SMARTNEST
|
||||
usermods.add(new Smartnest());
|
||||
UsermodManager::add(new Smartnest());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
usermods.add(new AudioReactive());
|
||||
UsermodManager::add(new AudioReactive());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ANALOG_CLOCK
|
||||
usermods.add(new AnalogClockUsermod());
|
||||
UsermodManager::add(new AnalogClockUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PING_PONG_CLOCK
|
||||
usermods.add(new PingPongClockUsermod());
|
||||
UsermodManager::add(new PingPongClockUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ADS1115
|
||||
usermods.add(new ADS1115Usermod());
|
||||
UsermodManager::add(new ADS1115Usermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_KLIPPER_PERCENTAGE
|
||||
usermods.add(new klipper_percentage());
|
||||
UsermodManager::add(new klipper_percentage());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BOBLIGHT
|
||||
usermods.add(new BobLightUsermod());
|
||||
UsermodManager::add(new BobLightUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef SD_ADAPTER
|
||||
usermods.add(new UsermodSdCard());
|
||||
UsermodManager::add(new UsermodSdCard());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PWM_OUTPUTS
|
||||
usermods.add(new PwmOutputsUsermod());
|
||||
UsermodManager::add(new PwmOutputsUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SHT
|
||||
usermods.add(new ShtUsermod());
|
||||
UsermodManager::add(new ShtUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ANIMARTRIX
|
||||
usermods.add(new AnimartrixUsermod("Animartrix", false));
|
||||
UsermodManager::add(new AnimartrixUsermod("Animartrix", false));
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_INTERNAL_TEMPERATURE
|
||||
usermods.add(new InternalTemperatureUsermod());
|
||||
UsermodManager::add(new InternalTemperatureUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_HTTP_PULL_LIGHT_CONTROL
|
||||
usermods.add(new HttpPullLightControl());
|
||||
UsermodManager::add(new HttpPullLightControl());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_MPU6050_IMU
|
||||
static MPU6050Driver mpu6050; usermods.add(&mpu6050);
|
||||
static MPU6050Driver mpu6050; UsermodManager::add(&mpu6050);
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_GYRO_SURGE
|
||||
static GyroSurge gyro_surge; usermods.add(&gyro_surge);
|
||||
static GyroSurge gyro_surge; UsermodManager::add(&gyro_surge);
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_LDR_DUSK_DAWN
|
||||
usermods.add(new LDR_Dusk_Dawn_v2());
|
||||
UsermodManager::add(new LDR_Dusk_Dawn_v2());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_STAIRCASE_WIPE
|
||||
usermods.add(new StairwayWipeUsermod());
|
||||
UsermodManager::add(new StairwayWipeUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_MAX17048
|
||||
usermods.add(new Usermod_MAX17048());
|
||||
UsermodManager::add(new Usermod_MAX17048());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_TETRISAI
|
||||
usermods.add(new TetrisAIUsermod());
|
||||
UsermodManager::add(new TetrisAIUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AHT10
|
||||
usermods.add(new UsermodAHT10());
|
||||
UsermodManager::add(new UsermodAHT10());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_INA226
|
||||
usermods.add(new UsermodINA226());
|
||||
UsermodManager::add(new UsermodINA226());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_LD2410
|
||||
usermods.add(new LD2410Usermod());
|
||||
UsermodManager::add(new LD2410Usermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_POV_DISPLAY
|
||||
usermods.add(new PovDisplayUsermod());
|
||||
UsermodManager::add(new PovDisplayUsermod());
|
||||
#endif
|
||||
}
|
||||
|
@ -54,23 +54,25 @@ void WLED::loop()
|
||||
#endif
|
||||
|
||||
handleTime();
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
#endif
|
||||
#endif
|
||||
handleConnection();
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
handleSerial();
|
||||
#endif
|
||||
handleImprovWifiScan();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
handleDMX();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
unsigned long usermodMillis = millis();
|
||||
#endif
|
||||
userLoop();
|
||||
usermods.loop();
|
||||
UsermodManager::loop();
|
||||
#ifdef WLED_DEBUG
|
||||
usermodMillis = millis() - usermodMillis;
|
||||
avgUsermodMillis += usermodMillis;
|
||||
@ -408,10 +410,10 @@ void WLED::setup()
|
||||
#endif
|
||||
|
||||
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
|
||||
pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
|
||||
PinManager::allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin
|
||||
pinManager.allocatePin(2, true, PinOwner::DMX);
|
||||
PinManager::allocatePin(2, true, PinOwner::DMX);
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN(F("Registering usermods ..."));
|
||||
@ -450,7 +452,7 @@ void WLED::setup()
|
||||
DEBUG_PRINTF_P(PSTR("heap %u\n"), ESP.getFreeHeap());
|
||||
|
||||
#if defined(STATUSLED) && STATUSLED>=0
|
||||
if (!pinManager.isPinAllocated(STATUSLED)) {
|
||||
if (!PinManager::isPinAllocated(STATUSLED)) {
|
||||
// NOTE: Special case: The status LED should *NOT* be allocated.
|
||||
// See comments in handleStatusLed().
|
||||
pinMode(STATUSLED, OUTPUT);
|
||||
@ -463,7 +465,7 @@ void WLED::setup()
|
||||
|
||||
DEBUG_PRINTLN(F("Usermods setup"));
|
||||
userSetup();
|
||||
usermods.setup();
|
||||
UsermodManager::setup();
|
||||
DEBUG_PRINTF_P(PSTR("heap %u\n"), ESP.getFreeHeap());
|
||||
|
||||
if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
@ -476,10 +478,14 @@ void WLED::setup()
|
||||
WiFi.mode(WIFI_STA); // enable scanning
|
||||
findWiFi(true); // start scanning for available WiFi-s
|
||||
|
||||
// all GPIOs are allocated at this point
|
||||
serialCanRX = !PinManager::isPinAllocated(hardwareRX); // Serial RX pin (GPIO 3 on ESP32 and ESP8266)
|
||||
serialCanTX = !PinManager::isPinAllocated(hardwareTX) || PinManager::getPinOwner(hardwareTX) == PinOwner::DebugOut; // Serial TX pin (GPIO 1 on ESP32 and ESP8266)
|
||||
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
//Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused
|
||||
//Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused
|
||||
if (!pinManager.isPinAllocated(hardwareRX) && !pinManager.isPinAllocated(hardwareTX)) {
|
||||
if (serialCanRX && serialCanTX) {
|
||||
Serial.println(F("Ada"));
|
||||
}
|
||||
#endif
|
||||
@ -491,10 +497,6 @@ void WLED::setup()
|
||||
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();
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled) {
|
||||
ArduinoOTA.onStart([]() {
|
||||
@ -521,7 +523,7 @@ void WLED::setup()
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket();
|
||||
if (serialCanRX && Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket();
|
||||
#endif
|
||||
|
||||
// HTTP server page init
|
||||
@ -683,7 +685,7 @@ bool WLED::initEthernet()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pinManager.allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) {
|
||||
if (!PinManager::allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) {
|
||||
DEBUG_PRINTLN(F("initE: Failed to allocate ethernet pins"));
|
||||
return false;
|
||||
}
|
||||
@ -717,7 +719,7 @@ bool WLED::initEthernet()
|
||||
DEBUG_PRINTLN(F("initC: ETH.begin() failed"));
|
||||
// de-allocate the allocated pins
|
||||
for (managed_pin_type mpt : pinsToAllocate) {
|
||||
pinManager.deallocatePin(mpt.pin, PinOwner::Ethernet);
|
||||
PinManager::deallocatePin(mpt.pin, PinOwner::Ethernet);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1008,7 +1010,7 @@ void WLED::handleConnection()
|
||||
}
|
||||
initInterfaces();
|
||||
userConnected();
|
||||
usermods.connected();
|
||||
UsermodManager::connected();
|
||||
lastMqttReconnectAttempt = 0; // force immediate update
|
||||
|
||||
// shut down AP
|
||||
@ -1031,7 +1033,7 @@ void WLED::handleStatusLED()
|
||||
uint32_t c = 0;
|
||||
|
||||
#if STATUSLED>=0
|
||||
if (pinManager.isPinAllocated(STATUSLED)) {
|
||||
if (PinManager::isPinAllocated(STATUSLED)) {
|
||||
return; //lower priority if something else uses the same pin
|
||||
}
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2409140
|
||||
#define VERSION 2409170
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -510,6 +510,8 @@ WLED_GLOBAL bool hueApplyColor _INIT(true);
|
||||
#endif
|
||||
|
||||
WLED_GLOBAL uint16_t serialBaud _INIT(1152); // serial baud rate, multiply by 100
|
||||
WLED_GLOBAL bool serialCanRX _INIT(false);
|
||||
WLED_GLOBAL bool serialCanTX _INIT(false);
|
||||
|
||||
#ifndef WLED_DISABLE_ESPNOW
|
||||
WLED_GLOBAL bool enableESPNow _INIT(false); // global on/off for ESP-NOW
|
||||
@ -638,17 +640,19 @@ typedef class Receive {
|
||||
bool SegmentOptions : 1;
|
||||
bool SegmentBounds : 1;
|
||||
bool Direct : 1;
|
||||
uint8_t reserved : 2;
|
||||
bool Palette : 1;
|
||||
uint8_t reserved : 1;
|
||||
};
|
||||
};
|
||||
Receive(int i) { Options = i; }
|
||||
Receive(bool b, bool c, bool e, bool sO, bool sB) {
|
||||
Brightness = b;
|
||||
Color = c;
|
||||
Effects = e;
|
||||
SegmentOptions = sO;
|
||||
SegmentBounds = sB;
|
||||
};
|
||||
Receive(bool b, bool c, bool e, bool sO, bool sB, bool p)
|
||||
: Brightness(b)
|
||||
, Color(c)
|
||||
, Effects(e)
|
||||
, SegmentOptions(sO)
|
||||
, SegmentBounds(sB)
|
||||
, Palette(p)
|
||||
{};
|
||||
} __attribute__ ((aligned(1), packed)) receive_notification_t;
|
||||
typedef class Send {
|
||||
public:
|
||||
@ -670,11 +674,12 @@ typedef class Send {
|
||||
Hue = h;
|
||||
}
|
||||
} __attribute__ ((aligned(1), packed)) send_notification_t;
|
||||
WLED_GLOBAL receive_notification_t receiveN _INIT(0b00100111);
|
||||
WLED_GLOBAL receive_notification_t receiveN _INIT(0b01100111);
|
||||
WLED_GLOBAL send_notification_t notifyG _INIT(0b00001111);
|
||||
#define receiveNotificationBrightness receiveN.Brightness
|
||||
#define receiveNotificationColor receiveN.Color
|
||||
#define receiveNotificationEffects receiveN.Effects
|
||||
#define receiveNotificationPalette receiveN.Palette
|
||||
#define receiveSegmentOptions receiveN.SegmentOptions
|
||||
#define receiveSegmentBounds receiveN.SegmentBounds
|
||||
#define receiveDirect receiveN.Direct
|
||||
@ -686,6 +691,7 @@ WLED_GLOBAL send_notification_t notifyG _INIT(0b00001111);
|
||||
WLED_GLOBAL bool receiveNotificationBrightness _INIT(true); // apply brightness from incoming notifications
|
||||
WLED_GLOBAL bool receiveNotificationColor _INIT(true); // apply color
|
||||
WLED_GLOBAL bool receiveNotificationEffects _INIT(true); // apply effects setup
|
||||
WLED_GLOBAL bool receiveNotificationPalette _INIT(true); // apply palette
|
||||
WLED_GLOBAL bool receiveSegmentOptions _INIT(false); // apply segment options
|
||||
WLED_GLOBAL bool receiveSegmentBounds _INIT(false); // apply segment bounds (start, stop, offset)
|
||||
WLED_GLOBAL bool receiveDirect _INIT(true); // receive UDP/Hyperion realtime
|
||||
|
@ -28,7 +28,7 @@ void updateBaudRate(uint32_t rate){
|
||||
if (rate100 == currentBaud || rate100 < 96) return;
|
||||
currentBaud = rate100;
|
||||
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut){
|
||||
if (serialCanTX){
|
||||
Serial.print(F("Baud is now ")); Serial.println(rate);
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ void updateBaudRate(uint32_t rate){
|
||||
|
||||
// RGB LED data return as JSON array. Slow, but easy to use on the other end.
|
||||
void sendJSON(){
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) {
|
||||
if (serialCanTX) {
|
||||
unsigned used = strip.getLengthTotal();
|
||||
Serial.write('[');
|
||||
for (unsigned i=0; i<used; i++) {
|
||||
@ -51,7 +51,7 @@ void sendJSON(){
|
||||
|
||||
// RGB LED data returned as bytes in TPM2 format. Faster, and slightly less easy to use on the other end.
|
||||
void sendBytes(){
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) {
|
||||
if (serialCanTX) {
|
||||
Serial.write(0xC9); Serial.write(0xDA);
|
||||
unsigned used = strip.getLengthTotal();
|
||||
unsigned len = used*3;
|
||||
@ -69,10 +69,8 @@ void sendBytes(){
|
||||
|
||||
void handleSerial()
|
||||
{
|
||||
if (pinManager.isPinAllocated(hardwareRX)) return;
|
||||
if (!Serial) return; // arduino docs: `if (Serial)` indicates whether or not the USB CDC serial connection is open. For all non-USB CDC ports, this will always return true
|
||||
if (!(serialCanRX && Serial)) return; // arduino docs: `if (Serial)` indicates whether or not the USB CDC serial connection is open. For all non-USB CDC ports, this will always return true
|
||||
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
static auto state = AdaState::Header_A;
|
||||
static uint16_t count = 0;
|
||||
static uint16_t pixel = 0;
|
||||
@ -86,54 +84,43 @@ void handleSerial()
|
||||
byte next = Serial.peek();
|
||||
switch (state) {
|
||||
case AdaState::Header_A:
|
||||
if (next == 'A') state = AdaState::Header_d;
|
||||
else if (next == 0xC9) { //TPM2 start byte
|
||||
state = AdaState::TPM2_Header_Type;
|
||||
}
|
||||
else if (next == 'I') {
|
||||
handleImprovPacket();
|
||||
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);
|
||||
} else if (next == 0xB3) {updateBaudRate( 500000);
|
||||
} else if (next == 0xB4) {updateBaudRate( 576000);
|
||||
} 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 = true; // Enable Continuous Serial Streaming
|
||||
|
||||
} else if (next == '{') { //JSON API
|
||||
if (next == 'A') { state = AdaState::Header_d; }
|
||||
else if (next == 0xC9) { state = AdaState::TPM2_Header_Type; } //TPM2 start byte
|
||||
else if (next == 'I') { handleImprovPacket(); 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); }
|
||||
else if (next == 0xB3) { updateBaudRate( 500000); }
|
||||
else if (next == 0xB4) { updateBaudRate( 576000); }
|
||||
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 = true; } // Enable Continuous Serial Streaming
|
||||
else if (next == '{') { //JSON API
|
||||
bool verboseResponse = false;
|
||||
if (!requestJSONBufferLock(16)) {
|
||||
Serial.println(F("{\"error\":3}")); // ERR_NOBUF
|
||||
Serial.printf_P(PSTR("{\"error\":%d}\n"), ERR_NOBUF);
|
||||
return;
|
||||
}
|
||||
Serial.setTimeout(100);
|
||||
DeserializationError error = deserializeJson(*pDoc, Serial);
|
||||
if (error) {
|
||||
releaseJSONBufferLock();
|
||||
return;
|
||||
}
|
||||
verboseResponse = deserializeState(pDoc->as<JsonObject>());
|
||||
//only send response if TX pin is unused for other purposes
|
||||
if (verboseResponse && (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut)) {
|
||||
pDoc->clear();
|
||||
JsonObject state = pDoc->createNestedObject("state");
|
||||
serializeState(state);
|
||||
JsonObject info = pDoc->createNestedObject("info");
|
||||
serializeInfo(info);
|
||||
if (!error) {
|
||||
verboseResponse = deserializeState(pDoc->as<JsonObject>());
|
||||
//only send response if TX pin is unused for other purposes
|
||||
if (verboseResponse && serialCanTX) {
|
||||
pDoc->clear();
|
||||
JsonObject state = pDoc->createNestedObject("state");
|
||||
serializeState(state);
|
||||
JsonObject info = pDoc->createNestedObject("info");
|
||||
serializeInfo(info);
|
||||
|
||||
serializeJson(*pDoc, Serial);
|
||||
Serial.println();
|
||||
serializeJson(*pDoc, Serial);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
@ -199,11 +186,10 @@ void handleSerial()
|
||||
// All other received bytes will disable Continuous Serial Streaming
|
||||
if (continuousSendLED && next != 'O'){
|
||||
continuousSendLED = false;
|
||||
}
|
||||
}
|
||||
|
||||
Serial.read(); //discard the byte
|
||||
}
|
||||
#endif
|
||||
|
||||
// If Continuous Serial Streaming is enabled, send new LED data as bytes
|
||||
if (continuousSendLED && (lastUpdate != strip.getLastShow())){
|
||||
|
@ -18,6 +18,7 @@ static const char s_unlock_ota [] PROGMEM = "Please unlock OTA in security setti
|
||||
static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!";
|
||||
static const char s_notimplemented[] PROGMEM = "Not implemented";
|
||||
static const char s_accessdenied[] PROGMEM = "Access Denied";
|
||||
static const char _common_js[] PROGMEM = "/common.js";
|
||||
|
||||
//Is this an IP?
|
||||
static bool isIp(String str) {
|
||||
@ -237,6 +238,10 @@ void initServer()
|
||||
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveview, PAGE_liveview_length);
|
||||
});
|
||||
|
||||
server.on(_common_js, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length);
|
||||
});
|
||||
|
||||
//settings page
|
||||
server.on(F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
serveSettings(request);
|
||||
@ -391,7 +396,7 @@ void initServer()
|
||||
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||
WLED::instance().disableWatchdog();
|
||||
#endif
|
||||
usermods.onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init)
|
||||
UsermodManager::onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init)
|
||||
lastEditTime = millis(); // make sure PIN does not lock during update
|
||||
strip.suspend();
|
||||
#ifdef ESP8266
|
||||
@ -407,7 +412,7 @@ void initServer()
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Update Failed"));
|
||||
strip.resume();
|
||||
usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init)
|
||||
UsermodManager::onUpdateBegin(false); // notify usermods that update has failed (some may require task init)
|
||||
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||
WLED::instance().enableWatchdog();
|
||||
#endif
|
||||
@ -511,6 +516,10 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro
|
||||
|
||||
void serveSettingsJS(AsyncWebServerRequest* request)
|
||||
{
|
||||
if (request->url().indexOf(FPSTR(_common_js)) > 0) {
|
||||
handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length);
|
||||
return;
|
||||
}
|
||||
char buf[SETTINGS_STACK_BUF_SIZE+37];
|
||||
buf[0] = 0;
|
||||
byte subPage = request->arg(F("p")).toInt();
|
||||
|
@ -135,7 +135,7 @@ void appendGPIOinfo() {
|
||||
if (requestJSONBufferLock(6)) {
|
||||
// if we can't allocate JSON buffer ignore usermod pins
|
||||
JsonObject mods = pDoc->createNestedObject(F("um"));
|
||||
usermods.addToConfig(mods);
|
||||
UsermodManager::addToConfig(mods);
|
||||
if (!mods.isNull()) fillUMPins(mods);
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
@ -144,7 +144,7 @@ void appendGPIOinfo() {
|
||||
// add reserved (unusable) pins
|
||||
oappend(SET_F("d.rsvd=["));
|
||||
for (unsigned i = 0; i < WLED_NUM_PINS; i++) {
|
||||
if (!pinManager.isPinOk(i, false)) { // include readonly pins
|
||||
if (!PinManager::isPinOk(i, false)) { // include readonly pins
|
||||
oappendi(i); oappend(",");
|
||||
}
|
||||
}
|
||||
@ -181,7 +181,7 @@ void appendGPIOinfo() {
|
||||
oappend(SET_F("d.ro_gpio=["));
|
||||
bool firstPin = true;
|
||||
for (unsigned i = 0; i < WLED_NUM_PINS; i++) {
|
||||
if (pinManager.isReadOnlyPin(i)) {
|
||||
if (PinManager::isReadOnlyPin(i)) {
|
||||
// No comma before the first pin
|
||||
if (!firstPin) oappend(SET_F(","));
|
||||
oappendi(i);
|
||||
@ -370,7 +370,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
int nPins = bus->getPins(pins);
|
||||
for (int i = 0; i < nPins; i++) {
|
||||
lp[1] = offset+i;
|
||||
if (pinManager.isPinOk(pins[i]) || bus->isVirtual()) sappend('v',lp,pins[i]);
|
||||
if (PinManager::isPinOk(pins[i]) || bus->isVirtual()) sappend('v',lp,pins[i]);
|
||||
}
|
||||
sappend('v',lc,bus->getLength());
|
||||
sappend('v',lt,bus->getType());
|
||||
@ -481,6 +481,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',SET_F("RB"),receiveNotificationBrightness);
|
||||
sappend('c',SET_F("RC"),receiveNotificationColor);
|
||||
sappend('c',SET_F("RX"),receiveNotificationEffects);
|
||||
sappend('c',SET_F("RP"),receiveNotificationPalette);
|
||||
sappend('c',SET_F("SO"),receiveSegmentOptions);
|
||||
sappend('c',SET_F("SG"),receiveSegmentBounds);
|
||||
sappend('c',SET_F("SS"),sendNotifications);
|
||||
@ -567,6 +568,9 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappend(SET_F("toggle('Hue');")); // hide Hue Sync settings
|
||||
#endif
|
||||
sappend('v',SET_F("BD"),serialBaud);
|
||||
#ifndef WLED_ENABLE_ADALIGHT
|
||||
oappend(SET_F("toggle('Serial);"));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (subPage == SUBPAGE_TIME)
|
||||
@ -687,7 +691,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
{
|
||||
appendGPIOinfo();
|
||||
oappend(SET_F("numM="));
|
||||
oappendi(usermods.getModCount());
|
||||
oappendi(UsermodManager::getModCount());
|
||||
oappend(";");
|
||||
sappend('v',SET_F("SDA"),i2c_sda);
|
||||
sappend('v',SET_F("SCL"),i2c_scl);
|
||||
@ -699,7 +703,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappend(SET_F("addInfo('MOSI','")); oappendi(HW_PIN_DATASPI); oappend(SET_F("');"));
|
||||
oappend(SET_F("addInfo('MISO','")); oappendi(HW_PIN_MISOSPI); oappend(SET_F("');"));
|
||||
oappend(SET_F("addInfo('SCLK','")); oappendi(HW_PIN_CLOCKSPI); oappend(SET_F("');"));
|
||||
usermods.appendConfigData();
|
||||
UsermodManager::appendConfigData();
|
||||
}
|
||||
|
||||
if (subPage == SUBPAGE_UPDATE) // update
|
||||
|
Loading…
x
Reference in New Issue
Block a user