Merge branch 'master' into dev
This commit is contained in:
commit
b0cfcb1999
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
||||
|
||||
### Builds after release 0.12.0
|
||||
|
||||
#### Build 2107091
|
||||
|
||||
- Fixed presets using wrong call mode (e.g. causing buttons to send UDP under direct change type)
|
||||
- Increased hue buffer
|
||||
- Renamed `NOTIFIER_CALL_MODE_` to `CALL_MODE_`
|
||||
|
||||
#### Build 2107090
|
||||
|
||||
- Busses extend total configured LEDs if required
|
||||
- Fixed extra button pins defaulting to 0 on first boot
|
||||
|
||||
#### Build 2107080
|
||||
|
||||
- Made Peek use the main websocket connection instead of opening a second one
|
||||
|
@ -123,7 +123,7 @@ class Animated_Staircase : public Usermod {
|
||||
// Always mark segments as "transitional", we are animating the staircase
|
||||
segments->setOption(SEG_OPTION_TRANSITIONAL, 1, 1);
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -298,7 +298,7 @@ class Animated_Staircase : public Usermod {
|
||||
}
|
||||
segments->setOption(SEG_OPTION_ON, 1, 1);
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
DEBUG_PRINTLN(F("Animated Staircase disabled."));
|
||||
}
|
||||
enabled = enable;
|
||||
|
@ -62,7 +62,7 @@ class PIRsensorSwitch : public Usermod {
|
||||
// PIR sensor pin
|
||||
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
||||
// notification mode for colorUpdated()
|
||||
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
|
||||
const byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // CALL_MODE_DIRECT_CHANGE
|
||||
// 1 min delay before switch off after the sensor state goes LOW
|
||||
uint32_t m_switchOffDelay = 60000;
|
||||
// off timer start time
|
||||
|
@ -58,7 +58,7 @@ private:
|
||||
// PIR sensor pin
|
||||
int8_t PIRsensorPin = PIR_SENSOR_PIN;
|
||||
// notification mode for colorUpdated()
|
||||
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
|
||||
const byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // CALL_MODE_DIRECT_CHANGE
|
||||
// delay before switch off after the sensor state goes LOW
|
||||
uint32_t m_switchOffDelay = 600000; // 10min
|
||||
// off timer start time
|
||||
|
@ -54,46 +54,46 @@ void userLoop()
|
||||
switch (myKey) {
|
||||
case '1':
|
||||
applyPreset(1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '2':
|
||||
applyPreset(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '3':
|
||||
applyPreset(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '4':
|
||||
applyPreset(4);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '5':
|
||||
applyPreset(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '6':
|
||||
applyPreset(6);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'A':
|
||||
applyPreset(7);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'B':
|
||||
applyPreset(8);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '7':
|
||||
effectCurrent += 1;
|
||||
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '*':
|
||||
effectCurrent -= 1;
|
||||
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '8':
|
||||
@ -102,7 +102,7 @@ void userLoop()
|
||||
} else if (effectSpeed < 255) {
|
||||
effectSpeed += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '0':
|
||||
if (effectSpeed > 15) {
|
||||
@ -110,7 +110,7 @@ void userLoop()
|
||||
} else if (effectSpeed > 0) {
|
||||
effectSpeed -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '9':
|
||||
@ -119,7 +119,7 @@ void userLoop()
|
||||
} else if (effectIntensity < 255) {
|
||||
effectIntensity += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '#':
|
||||
if (effectIntensity > 15) {
|
||||
@ -127,18 +127,18 @@ void userLoop()
|
||||
} else if (effectIntensity > 0) {
|
||||
effectIntensity -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
effectPalette += 1;
|
||||
if (effectPalette >= 50) effectPalette = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'D':
|
||||
effectPalette -= 1;
|
||||
if (effectPalette <= 0) effectPalette = 50;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
}
|
||||
|
86
usermods/rgb-rotary-encoder/readme.md
Normal file
86
usermods/rgb-rotary-encoder/readme.md
Normal file
@ -0,0 +1,86 @@
|
||||
# RGB Encoder Board
|
||||
|
||||
This usermod-v2 adds support for the awesome RGB Rotary Encoder Board by Adam Zeloof / "Isotope Engineering" to control the overall brightness of your WLED instance: https://github.com/isotope-engineering/RGB-Encoder-Board. A great DIY rotary encoder with 20 tiny SK6805 / "NeoPixel Nano" LEDs.
|
||||
|
||||
https://user-images.githubusercontent.com/3090131/124680599-0180ab80-dec7-11eb-9065-a6d08ebe0287.mp4
|
||||
|
||||
## Credits
|
||||
The actual / original code that does the different LED modes is from Adam Zeloof. So I don't take credit for these. But I ported it to WLED, which involved replacing the LED library he used (because, guess what, WLED already has one; so no need to add another one, but use whatever WLED uses), plus the rotary encoder library, because that one was not compatible with ESP, only Arduino.
|
||||
So it was quite more work than I hoped, but I got there eventually :)
|
||||
|
||||
## Requirements
|
||||
* "ESP Rotary" by Lennart Hennigs, v1.5.0 or higher: https://github.com/LennartHennigs/ESPRotary
|
||||
|
||||
## Usermod installation
|
||||
Simply copy the below block (build task) to your `platformio_override.ini` and compile WLED using this new build task. Or use an existing one and add the buildflag `-D RGB_ROTARY_ENCODER`.
|
||||
|
||||
ESP32:
|
||||
```
|
||||
[env:custom_esp32dev_usermod_rgb_encoder_board]
|
||||
extends = env:esp32dev
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D RGB_ROTARY_ENCODER
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
lennarthennigs/ESP Rotary@^1.5.0
|
||||
```
|
||||
|
||||
ESP8266 / D1 Mini:
|
||||
```
|
||||
[env:custom_d1_mini_usermod_rgb_encoder_board]
|
||||
extends = env:d1_mini
|
||||
build_flags = ${common.build_flags_esp8266} -D RGB_ROTARY_ENCODER
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
lennarthennigs/ESP Rotary@^1.5.0
|
||||
```
|
||||
|
||||
## How to connect the board to your ESP
|
||||
We gonna need (minimum) three or (maximum) four GPIOs for the board:
|
||||
* "ea": Basically tells if the encoder goes into one or the other direction
|
||||
* "eb": Same thing, but the other direction
|
||||
* "di": LED data in. To actually control the LEDs
|
||||
* *(optional)* "sw": The integrated switch in the rotary encoder. Can be omitted for the bare functionality of just controlling the brightness
|
||||
|
||||
We also gonna need some power, so:
|
||||
|
||||
* "vdd": Needs to be connected to **+5V**.
|
||||
* "gnd": Well, it's GND.
|
||||
|
||||
You can freely pick the GPIOs, it doesn't matter. Those will be configured in the "Usermods" section in the WLED web panel:
|
||||
|
||||
## Configuration
|
||||
Navigate to the "Config" and then to the "Usermods" section. If you compiled WLED with `-D RGB_ROTARY_ENCODER`, you will see the config for it there. The settings there are the GPIOs we mentioned before (*Note: The switch pin is not there, as this can just be configured the "normal" button on the "LED Preferences" page*), plus a few more:
|
||||
* LED pin:
|
||||
* Possible values: Any valid and available GPIO
|
||||
* Default: 3
|
||||
* What it does: Pin to control the LED ring
|
||||
* ea pin:
|
||||
* Possible values: Any valid and available GPIO
|
||||
* Default: 15
|
||||
* What it does: First of the two rotary encoder pins
|
||||
* eb pin:
|
||||
* Possible values: Any valid and available GPIO
|
||||
* Default: 32
|
||||
* What it does: Second of the two rotary encoder pins
|
||||
* LED Mode:
|
||||
* Possible values: 1-3
|
||||
* Default: 3
|
||||
* What it does: The usermod provides three different modes of how the LEDs can look like. Here's an example: https://github.com/isotope-engineering/RGB-Encoder-Board/blob/master/images/rgb-encoder-animations.gif
|
||||
* Up left is "1"
|
||||
* Up right is not supported / doesn't make sense for brightness control
|
||||
* Bottom left is "2"
|
||||
* Bottom right is "3"
|
||||
* LED Brightness:
|
||||
* Possible values: 1-255
|
||||
* Default: 64
|
||||
* What it does: Brightness of the LED ring
|
||||
* Steps per click:
|
||||
* Possible values: Any positive number
|
||||
* Default: 4
|
||||
* What it does: With each "click", a rotary encoder actually increments it's "steps". Most rotary encoder do four "steps" per "click". I know this sounds super weird, so just leave this the default value, unless your rotary encoder behaves weirdly, like with one click, it makes two LEDs light up, or you sometimes need two click for one LED. Then you should play around with this value or write a small sketch using the same "ESP Rotary" library and read out the steps it does.
|
||||
* Increment per click:
|
||||
* Possible values: Any positive number
|
||||
* Default: 5
|
||||
* What it does: Most rotary encoder have 20 "clicks", so basically 20 positions. This value should be set to 100 / `number of clicks`
|
||||
|
||||
## Change log
|
||||
2021-07
|
||||
* First implementation.
|
344
usermods/rgb-rotary-encoder/rgb-rotary-encoder.h
Normal file
344
usermods/rgb-rotary-encoder/rgb-rotary-encoder.h
Normal file
@ -0,0 +1,344 @@
|
||||
#pragma once
|
||||
|
||||
#include "ESPRotary.h"
|
||||
#include <math.h>
|
||||
#include "wled.h"
|
||||
|
||||
class RgbRotaryEncoderUsermod : public Usermod
|
||||
{
|
||||
private:
|
||||
bool enabled = false;
|
||||
bool initDone = false;
|
||||
bool isDirty = false;
|
||||
BusDigital *ledBus;
|
||||
/*
|
||||
* Green - eb - Q4 - 32
|
||||
* Red - ea - Q1 - 15
|
||||
* Black - sw - Q2 - 12
|
||||
*/
|
||||
ESPRotary *rotaryEncoder;
|
||||
int8_t ledIo = 3; // GPIO to control the LEDs
|
||||
int8_t eaIo = 15; // "ea" from RGB Encoder Board
|
||||
int8_t ebIo = 32; // "eb" from RGB Encoder Board
|
||||
byte stepsPerClick = 4; // How many "steps" your rotary encoder does per click. This varies per rotary encoder
|
||||
/* This could vary per rotary encoder: Usually rotary encoders have 20 "clicks".
|
||||
If yours has less/more, adjust this to: 100% = 20 LEDs * incrementPerClick */
|
||||
byte incrementPerClick = 5;
|
||||
byte ledMode = 3;
|
||||
byte ledBrightness = 64;
|
||||
|
||||
// This is all needed to calculate the brightness, rotary position, etc.
|
||||
const byte minPos = 5; // minPos is not zero, because if we want to turn the LEDs off, we use the built-in button ;)
|
||||
const byte maxPos = 100; // maxPos=100, like 100%
|
||||
const byte numLeds = 20;
|
||||
byte lastKnownPos = 0;
|
||||
|
||||
byte currentColors[3];
|
||||
byte lastKnownBri = 0;
|
||||
|
||||
|
||||
void initRotaryEncoder()
|
||||
{
|
||||
if (!pinManager.allocatePin(eaIo, false)) {
|
||||
eaIo = -1;
|
||||
}
|
||||
if (!pinManager.allocatePin(ebIo, false)) {
|
||||
ebIo = -1;
|
||||
}
|
||||
if (eaIo == -1 || ebIo == -1) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
// I don't know why, but setting the upper bound here does not work. It results into 1717922932 O_o
|
||||
rotaryEncoder = new ESPRotary(eaIo, ebIo, stepsPerClick, incrementPerClick, maxPos, currentPos, incrementPerClick);
|
||||
rotaryEncoder->setUpperBound(maxPos); // I have to again set it here and then it works / is actually 100...
|
||||
|
||||
rotaryEncoder->setChangedHandler(RgbRotaryEncoderUsermod::cbRotate);
|
||||
}
|
||||
|
||||
void initLedBus()
|
||||
{
|
||||
byte _pins[5] = {(byte)ledIo, 255, 255, 255, 255};
|
||||
BusConfig busCfg = BusConfig(TYPE_WS2812_RGB, _pins, 0, numLeds, COL_ORDER_GRB, false, 0);
|
||||
|
||||
ledBus = new BusDigital(busCfg, WLED_MAX_BUSSES - 1);
|
||||
if (!ledBus->isOk()) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
ledBus->setBrightness(ledBrightness);
|
||||
}
|
||||
|
||||
void updateLeds()
|
||||
{
|
||||
switch (ledMode) {
|
||||
case 2:
|
||||
{
|
||||
currentColors[0] = 255; currentColors[1] = 0; currentColors[2] = 0;
|
||||
for (int i = 0; i < currentPos / incrementPerClick - 1; i++) {
|
||||
ledBus->setPixelColor(i, 0);
|
||||
}
|
||||
ledBus->setPixelColor(currentPos / incrementPerClick - 1, colorFromRgbw(currentColors));
|
||||
for (int i = currentPos / incrementPerClick; i < numLeds; i++) {
|
||||
ledBus->setPixelColor(i, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case 1:
|
||||
case 3:
|
||||
// WLED orange (of course), which we will use in mode 1
|
||||
currentColors[0] = 255; currentColors[1] = 160; currentColors[2] = 0;
|
||||
for (int i = 0; i < currentPos / incrementPerClick; i++) {
|
||||
if (ledMode == 3) {
|
||||
hsv2rgb((i) / float(numLeds), 1, .25);
|
||||
}
|
||||
ledBus->setPixelColor(i, colorFromRgbw(currentColors));
|
||||
}
|
||||
for (int i = currentPos / incrementPerClick; i < numLeds; i++) {
|
||||
ledBus->setPixelColor(i, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
// Only deallocate pins if we allocated them ;)
|
||||
if (eaIo != -1) {
|
||||
pinManager.deallocatePin(eaIo);
|
||||
}
|
||||
if (ebIo != -1) {
|
||||
pinManager.deallocatePin(ebIo);
|
||||
}
|
||||
|
||||
delete rotaryEncoder;
|
||||
delete ledBus;
|
||||
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
int getPositionForBrightness()
|
||||
{
|
||||
return int(((float)bri / (float)255) * 100);
|
||||
}
|
||||
|
||||
float fract(float x) { return x - int(x); }
|
||||
|
||||
float mix(float a, float b, float t) { return a + (b - a) * t; }
|
||||
|
||||
void hsv2rgb(float h, float s, float v) {
|
||||
currentColors[0] = int((v * mix(1.0, constrain(abs(fract(h + 1.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s)) * 255);
|
||||
currentColors[1] = int((v * mix(1.0, constrain(abs(fract(h + 0.6666666) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s)) * 255);
|
||||
currentColors[2] = int((v * mix(1.0, constrain(abs(fract(h + 0.3333333) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s)) * 255);
|
||||
}
|
||||
|
||||
public:
|
||||
static byte currentPos;
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
static const char _name[];
|
||||
static const char _enabled[];
|
||||
static const char _ledIo[];
|
||||
static const char _eaIo[];
|
||||
static const char _ebIo[];
|
||||
static const char _ledMode[];
|
||||
static const char _ledBrightness[];
|
||||
static const char _stepsPerClick[];
|
||||
static const char _incrementPerClick[];
|
||||
|
||||
|
||||
static void cbRotate(ESPRotary& r) {
|
||||
currentPos = r.getPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the usermod
|
||||
*/
|
||||
// inline void enable(bool enable) { enabled = enable; }
|
||||
/**
|
||||
* Get usermod enabled/disabled state
|
||||
*/
|
||||
// inline bool isEnabled() { return enabled; }
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
if (enabled) {
|
||||
currentPos = getPositionForBrightness();
|
||||
lastKnownBri = bri;
|
||||
|
||||
initRotaryEncoder();
|
||||
initLedBus();
|
||||
|
||||
// No updating of LEDs here, as that's sometimes not working; loop() will take care of that
|
||||
|
||||
initDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
if (!enabled || strip.isUpdating()) return;
|
||||
|
||||
rotaryEncoder->loop();
|
||||
|
||||
// If the rotary was changed
|
||||
if(lastKnownPos != currentPos) {
|
||||
lastKnownPos = currentPos;
|
||||
|
||||
bri = min(int(round((2.55 * currentPos))), 255);
|
||||
lastKnownBri = bri;
|
||||
|
||||
updateLeds();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
|
||||
// If the brightness is changed not with the rotary, update the rotary
|
||||
if (bri != lastKnownBri) {
|
||||
currentPos = lastKnownPos = getPositionForBrightness();
|
||||
lastKnownBri = bri;
|
||||
rotaryEncoder->resetPosition(currentPos);
|
||||
updateLeds();
|
||||
}
|
||||
|
||||
// Update LEDs here in loop to also validate that we can update/show
|
||||
if (isDirty && ledBus->canShow()) {
|
||||
isDirty = false;
|
||||
ledBus->show();
|
||||
}
|
||||
}
|
||||
|
||||
void addToConfig(JsonObject &root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
||||
|
||||
top[FPSTR(_enabled)] = enabled;
|
||||
top[FPSTR(_ledIo)] = ledIo;
|
||||
top[FPSTR(_eaIo)] = eaIo;
|
||||
top[FPSTR(_ebIo)] = ebIo;
|
||||
top[FPSTR(_ledMode)] = ledMode;
|
||||
top[FPSTR(_ledBrightness)] = ledBrightness;
|
||||
top[FPSTR(_stepsPerClick)] = stepsPerClick;
|
||||
top[FPSTR(_incrementPerClick)] = incrementPerClick;
|
||||
}
|
||||
|
||||
/**
|
||||
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
||||
*
|
||||
* The function should return true if configuration was successfully loaded or false if there was no configuration.
|
||||
*/
|
||||
bool readFromConfig(JsonObject &root)
|
||||
{
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
if (top.isNull()) {
|
||||
DEBUG_PRINTF("[%s] No config found. (Using defaults.)\n", _name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool oldEnabled = enabled;
|
||||
int8_t oldLedIo = ledIo;
|
||||
int8_t oldEaIo = eaIo;
|
||||
int8_t oldEbIo = ebIo;
|
||||
byte oldLedMode = ledMode;
|
||||
byte oldStepsPerClick = stepsPerClick;
|
||||
byte oldIncrementPerClick = incrementPerClick;
|
||||
byte oldLedBrightness = ledBrightness;
|
||||
|
||||
getJsonValue(top[FPSTR(_enabled)], enabled);
|
||||
getJsonValue(top[FPSTR(_ledIo)], ledIo);
|
||||
getJsonValue(top[FPSTR(_eaIo)], eaIo);
|
||||
getJsonValue(top[FPSTR(_ebIo)], ebIo);
|
||||
getJsonValue(top[FPSTR(_stepsPerClick)], stepsPerClick);
|
||||
getJsonValue(top[FPSTR(_incrementPerClick)], incrementPerClick);
|
||||
ledMode = top[FPSTR(_ledMode)] > 0 && top[FPSTR(_ledMode)] < 4 ? top[FPSTR(_ledMode)] : ledMode;
|
||||
ledBrightness = top[FPSTR(_ledBrightness)] > 0 && top[FPSTR(_ledBrightness)] <= 255 ? top[FPSTR(_ledBrightness)] : ledBrightness;
|
||||
|
||||
if (!initDone) {
|
||||
// First run: reading from cfg.json
|
||||
// Nothing to do here, will be all done in setup()
|
||||
}
|
||||
// Mod was disabled, so run setup()
|
||||
else if (enabled && enabled != oldEnabled) {
|
||||
DEBUG_PRINTF("[%s] Usermod has been re-enabled\n", _name);
|
||||
setup();
|
||||
}
|
||||
// Config has been changed, so adopt to changes
|
||||
else {
|
||||
if (!enabled) {
|
||||
DEBUG_PRINTF("[%s] Usermod has been disabled\n", _name);
|
||||
cleanup();
|
||||
}
|
||||
else {
|
||||
DEBUG_PRINTF("[%s] Usermod is enabled\n", _name);
|
||||
if (ledIo != oldLedIo) {
|
||||
delete ledBus;
|
||||
initLedBus();
|
||||
}
|
||||
|
||||
if (ledBrightness != oldLedBrightness) {
|
||||
ledBus->setBrightness(ledBrightness);
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
if (ledMode != oldLedMode) {
|
||||
updateLeds();
|
||||
}
|
||||
|
||||
if (eaIo != oldEaIo || ebIo != oldEbIo || stepsPerClick != oldStepsPerClick || incrementPerClick != oldIncrementPerClick) {
|
||||
pinManager.deallocatePin(oldEaIo);
|
||||
pinManager.deallocatePin(oldEbIo);
|
||||
|
||||
delete rotaryEncoder;
|
||||
initRotaryEncoder();
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("[%s] Config (re)loaded\n", _name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return 0x4711;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
||||
|
||||
byte RgbRotaryEncoderUsermod::currentPos = 5;
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
const char RgbRotaryEncoderUsermod::_name[] PROGMEM = "RGB-Rotary-Encoder";
|
||||
const char RgbRotaryEncoderUsermod::_enabled[] PROGMEM = "Enabled";
|
||||
const char RgbRotaryEncoderUsermod::_ledIo[] PROGMEM = "LED-pin";
|
||||
const char RgbRotaryEncoderUsermod::_eaIo[] PROGMEM = "ea-pin";
|
||||
const char RgbRotaryEncoderUsermod::_ebIo[] PROGMEM = "eb-pin";
|
||||
const char RgbRotaryEncoderUsermod::_ledMode[] PROGMEM = "LED-Mode";
|
||||
const char RgbRotaryEncoderUsermod::_ledBrightness[] PROGMEM = "LED-Brightness";
|
||||
const char RgbRotaryEncoderUsermod::_stepsPerClick[] PROGMEM = "Steps-per-Click";
|
||||
const char RgbRotaryEncoderUsermod::_incrementPerClick[] PROGMEM = "Increment-per-Click";
|
@ -39,7 +39,7 @@ void userLoop() {
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class StairwayWipeUsermod : public Usermod {
|
||||
if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete
|
||||
effectCurrent = FX_MODE_STATIC;
|
||||
timeStaticStart = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
wipeState = 2;
|
||||
}
|
||||
} else if (wipeState == 2) { //static
|
||||
@ -54,7 +54,7 @@ class StairwayWipeUsermod : public Usermod {
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
wipeState = 4;
|
||||
#else
|
||||
turnOff();
|
||||
@ -100,7 +100,7 @@ class StairwayWipeUsermod : public Usermod {
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
}
|
||||
|
||||
void turnOff()
|
||||
@ -111,7 +111,7 @@ class StairwayWipeUsermod : public Usermod {
|
||||
transitionDelayTemp = 4000; //fade out slowly
|
||||
#endif
|
||||
bri = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
wipeState = 0;
|
||||
userVar0 = 0;
|
||||
previousUserVar0 = 0;
|
||||
|
@ -47,7 +47,7 @@ void userLoop()
|
||||
if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete
|
||||
effectCurrent = FX_MODE_STATIC;
|
||||
timeStaticStart = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
wipeState = 2;
|
||||
}
|
||||
} else if (wipeState == 2) { //static
|
||||
@ -59,7 +59,7 @@ void userLoop()
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
wipeState = 4;
|
||||
#else
|
||||
turnOff();
|
||||
@ -93,7 +93,7 @@ void startWipe()
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
}
|
||||
|
||||
void turnOff()
|
||||
@ -104,7 +104,7 @@ void turnOff()
|
||||
transitionDelayTemp = 4000; //fade out slowly
|
||||
#endif
|
||||
bri = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
wipeState = 0;
|
||||
userVar0 = 0;
|
||||
previousUserVar0 = 0;
|
||||
|
@ -138,8 +138,8 @@ public:
|
||||
}
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
updateInterfaces(NOTIFIER_CALL_MODE_BUTTON);
|
||||
colorUpdated(CALL_MODE_BUTTON);
|
||||
updateInterfaces(CALL_MODE_BUTTON);
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
|
@ -267,8 +267,8 @@ public:
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
updateInterfaces(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
updateInterfaces(CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
|
||||
void changeBrightness(bool increase) {
|
||||
|
@ -64,13 +64,13 @@ void hourChime()
|
||||
{
|
||||
//strip.resetSegments();
|
||||
selectWordSegments(true);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
savePreset(13, false);
|
||||
selectWordSegments(false);
|
||||
//strip.getSegment(0).setOption(0, true);
|
||||
strip.getSegment(0).setOption(2, true);
|
||||
applyPreset(12);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||
}
|
||||
|
||||
void displayTime(byte hour, byte minute)
|
||||
|
@ -44,10 +44,10 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
if (bri == 0)
|
||||
{
|
||||
bri = briLast;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
colorUpdated(CALL_MODE_ALEXA);
|
||||
}
|
||||
} else {
|
||||
applyPreset(macroAlexaOn);
|
||||
applyPreset(macroAlexaOn, CALL_MODE_ALEXA);
|
||||
if (bri == 0) espalexaDevice->setValue(briLast); //stop Alexa from complaining if macroAlexaOn does not actually turn on
|
||||
}
|
||||
} else if (m == EspalexaDeviceProperty::off)
|
||||
@ -58,16 +58,16 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
colorUpdated(CALL_MODE_ALEXA);
|
||||
}
|
||||
} else {
|
||||
applyPreset(macroAlexaOff);
|
||||
applyPreset(macroAlexaOff, CALL_MODE_ALEXA);
|
||||
if (bri != 0) espalexaDevice->setValue(0); //stop Alexa from complaining if macroAlexaOff does not actually turn off
|
||||
}
|
||||
} else if (m == EspalexaDeviceProperty::bri)
|
||||
{
|
||||
bri = espalexaDevice->getValue();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
colorUpdated(CALL_MODE_ALEXA);
|
||||
} else //color
|
||||
{
|
||||
if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white
|
||||
@ -93,7 +93,7 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
col[2] = ( color & 0xFF);
|
||||
col[3] = 0;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
colorUpdated(CALL_MODE_ALEXA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,45 +46,45 @@ void updateBlynk()
|
||||
BLYNK_WRITE(V0)
|
||||
{
|
||||
bri = param.asInt();//bri
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V1)
|
||||
{
|
||||
blHue = param.asInt();//hue
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V2)
|
||||
{
|
||||
blSat = param.asInt();//sat
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V3)
|
||||
{
|
||||
bool on = (param.asInt()>0);
|
||||
if (!on != !bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BLYNK);}
|
||||
if (!on != !bri) {toggleOnOff(); colorUpdated(CALL_MODE_BLYNK);}
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V4)
|
||||
{
|
||||
effectCurrent = param.asInt()-1;//fx
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V5)
|
||||
{
|
||||
effectSpeed = param.asInt();//sx
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V6)
|
||||
{
|
||||
effectIntensity = param.asInt();//ix
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V7)
|
||||
|
@ -33,6 +33,18 @@ struct BusConfig {
|
||||
else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type);
|
||||
for (uint8_t i = 0; i < nPins; i++) pins[i] = ppins[i];
|
||||
}
|
||||
|
||||
//validates start and length and extends total if needed
|
||||
bool adjustBounds(uint16_t& total) {
|
||||
if (!count) count = 1;
|
||||
if (count > MAX_LEDS_PER_BUS) count = MAX_LEDS_PER_BUS;
|
||||
if (start >= MAX_LEDS) return false;
|
||||
//limit length of strip if it would exceed total permissible LEDs
|
||||
if (start + count > MAX_LEDS) count = MAX_LEDS - start;
|
||||
//extend total count accordingly
|
||||
if (start + count > total) total = start + count;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//parent class of BusDigital and BusPwm
|
||||
@ -112,11 +124,10 @@ class Bus {
|
||||
class BusDigital : public Bus {
|
||||
public:
|
||||
BusDigital(BusConfig &bc, uint8_t nr) : Bus(bc.type, bc.start) {
|
||||
uint8_t type = bc.type;
|
||||
if (!IS_DIGITAL(type) || !bc.count) return;
|
||||
if (!IS_DIGITAL(bc.type) || !bc.count) return;
|
||||
if (!pinManager.allocatePin(bc.pins[0])) return;
|
||||
_pins[0] = bc.pins[0];
|
||||
if (IS_2PIN(type)) {
|
||||
if (IS_2PIN(bc.type)) {
|
||||
if (!pinManager.allocatePin(bc.pins[1])) {
|
||||
cleanup(); return;
|
||||
}
|
||||
@ -125,8 +136,8 @@ class BusDigital : public Bus {
|
||||
reversed = bc.reversed;
|
||||
_skip = bc.skipAmount; //sacrificial pixels
|
||||
_len = bc.count + _skip;
|
||||
_rgbw = bc.rgbwOverride || Bus::isRgbw(type); // RGBW override in bit 7
|
||||
_iType = PolyBus::getI(type, _pins, nr, _rgbw);
|
||||
_rgbw = bc.rgbwOverride || Bus::isRgbw(bc.type); // RGBW override in bit 7
|
||||
_iType = PolyBus::getI(bc.type, _pins, nr, _rgbw);
|
||||
if (_iType == I_NONE) return;
|
||||
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
|
||||
_valid = (_busPtr != nullptr);
|
||||
@ -237,11 +248,11 @@ class BusPwm : public Bus {
|
||||
#endif
|
||||
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
if (!pinManager.allocatePin(bc.pins[i])) {
|
||||
deallocatePins();
|
||||
return;
|
||||
uint8_t currentPin = bc.pins[i];
|
||||
if (!pinManager.allocatePin(currentPin)) {
|
||||
deallocatePins(); return;
|
||||
}
|
||||
_pins[i] = bc.pins[i];
|
||||
_pins[i] = currentPin; // store only after allocatePin() succeeds
|
||||
#ifdef ESP8266
|
||||
pinMode(_pins[i], OUTPUT);
|
||||
#else
|
||||
|
@ -13,9 +13,9 @@ void shortPressAction(uint8_t b)
|
||||
if (!macroButton[b])
|
||||
{
|
||||
toggleOnOff();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
colorUpdated(CALL_MODE_BUTTON);
|
||||
} else {
|
||||
applyPreset(macroButton[b]);
|
||||
applyPreset(macroButton[b], CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
// publish MQTT message
|
||||
@ -62,14 +62,14 @@ void handleSwitch(uint8_t b)
|
||||
|
||||
if (millis() - buttonPressedTime[b] > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
|
||||
if (!buttonPressedBefore[b]) { // on -> off
|
||||
if (macroButton[b]) applyPreset(macroButton[b]);
|
||||
if (macroButton[b]) applyPreset(macroButton[b], CALL_MODE_BUTTON);
|
||||
else { //turn on
|
||||
if (!bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
|
||||
if (!bri) {toggleOnOff(); colorUpdated(CALL_MODE_BUTTON);}
|
||||
}
|
||||
} else { // off -> on
|
||||
if (macroLongPress[b]) applyPreset(macroLongPress[b]);
|
||||
if (macroLongPress[b]) applyPreset(macroLongPress[b], CALL_MODE_BUTTON);
|
||||
else { //turn off
|
||||
if (bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
|
||||
if (bri) {toggleOnOff(); colorUpdated(CALL_MODE_BUTTON);}
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,14 +154,14 @@ void handleAnalog(uint8_t b)
|
||||
seg.setOption(SEG_OPTION_ON, 1);
|
||||
}
|
||||
// this will notify clients of update (websockets,mqtt,etc)
|
||||
updateInterfaces(NOTIFIER_CALL_MODE_BUTTON);
|
||||
updateInterfaces(CALL_MODE_BUTTON);
|
||||
}
|
||||
} else {
|
||||
//TODO:
|
||||
// we can either trigger a preset depending on the level (between short and long entries)
|
||||
// or use it for RGBW direct control
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
void handleButton()
|
||||
@ -195,7 +195,7 @@ void handleButton()
|
||||
{
|
||||
if (!buttonLongPressed[b])
|
||||
{
|
||||
if (macroLongPress[b]) {applyPreset(macroLongPress[b]);}
|
||||
if (macroLongPress[b]) {applyPreset(macroLongPress[b], CALL_MODE_BUTTON);}
|
||||
else _setRandomColor(false,true);
|
||||
|
||||
// publish MQTT message
|
||||
@ -224,7 +224,7 @@ void handleButton()
|
||||
if (macroDoublePress[b])
|
||||
{
|
||||
if (doublePress) {
|
||||
applyPreset(macroDoublePress[b]);
|
||||
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON);
|
||||
|
||||
// publish MQTT message
|
||||
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
|
||||
|
@ -120,12 +120,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (i>4) break;
|
||||
}
|
||||
|
||||
uint16_t length = elm[F("len")];
|
||||
uint16_t length = elm[F("len")] | 1;
|
||||
if (length==0 || length+lC > MAX_LEDS) continue; // zero length or we reached max. number of LEDs, just stop
|
||||
uint8_t colorOrder = (int)elm[F("order")];
|
||||
uint8_t skipFirst = elm[F("skip")];
|
||||
uint16_t start = elm[F("start")] | 0;
|
||||
if (start > lC+length) continue; // something is very wrong :)
|
||||
uint8_t colorOrder = elm[F("order")];
|
||||
uint8_t skipFirst = elm[F("skip")];
|
||||
uint8_t ledType = elm["type"] | TYPE_WS2812_RGB;
|
||||
bool reversed = elm["rev"];
|
||||
//if ((bool)elm[F("rgbw")]) SET_BIT(ledType,7); else UNSET_BIT(ledType,7); // hack bit 7 to indicate RGBW (as an override if necessary)
|
||||
@ -134,6 +134,18 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst);
|
||||
mem += BusManager::memUsage(bc);
|
||||
if (mem <= MAX_LED_MEMORY && busses.getNumBusses() <= WLED_MAX_BUSSES) busses.add(bc); // finalization will be done in WLED::beginStrip()
|
||||
/*
|
||||
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst);
|
||||
if (bc.adjustBounds(ledCount)) {
|
||||
//RGBW mode is enabled if at least one of the strips is RGBW
|
||||
strip.isRgbw = (strip.isRgbw || BusManager::isRgbw(ledType));
|
||||
//refresh is required to remain off if at least one of the strips requires the refresh.
|
||||
strip.isOffRefreshRequred |= BusManager::isOffRefreshRequred(ledType);
|
||||
s++;
|
||||
mem += busses.memUsage(bc);
|
||||
if (mem <= MAX_LED_MEMORY) busses.add(bc);
|
||||
}
|
||||
*/
|
||||
}
|
||||
// finalization done in beginStrip()
|
||||
}
|
||||
@ -170,8 +182,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
} else {
|
||||
// new install/missing configuration (button 0 has defaults)
|
||||
if (fromFS) {
|
||||
// relies upon only being called once with fromFS == true, which is currently true.
|
||||
uint8_t s=0;
|
||||
if (pinManager.allocatePin(btnPin[0])) s++; // do not clear button 0 if pin successfully allocated
|
||||
if (pinManager.allocatePin(btnPin[0],false)) s++; // do not clear button 0 if pin successfully allocated
|
||||
for (; s<WLED_MAX_BUTTONS; s++) {
|
||||
btnPin[s] = -1;
|
||||
buttonType[s] = BTN_TYPE_NONE;
|
||||
@ -501,7 +514,7 @@ void serializeConfig() {
|
||||
|
||||
JsonObject wifi = doc.createNestedObject("wifi");
|
||||
wifi[F("sleep")] = !noWifiSleep;
|
||||
wifi[F("phy")] = 1;
|
||||
//wifi[F("phy")] = 1;
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
JsonObject ethernet = doc.createNestedObject("eth");
|
||||
@ -558,27 +571,18 @@ void serializeConfig() {
|
||||
hw_btn["max"] = WLED_MAX_BUTTONS; // just information about max number of buttons (not actually used)
|
||||
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
|
||||
|
||||
// there is always at least one button
|
||||
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
|
||||
hw_btn_ins_0["type"] = buttonType[0];
|
||||
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
|
||||
hw_btn_ins_0_pin.add(btnPin[0]);
|
||||
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
|
||||
hw_btn_ins_0_macros.add(macroButton[0]);
|
||||
hw_btn_ins_0_macros.add(macroLongPress[0]);
|
||||
hw_btn_ins_0_macros.add(macroDoublePress[0]);
|
||||
|
||||
// additional buttons
|
||||
for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) {
|
||||
hw_btn_ins_0 = hw_btn_ins.createNestedObject();
|
||||
// configuration for all buttons
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
|
||||
hw_btn_ins_0["type"] = buttonType[i];
|
||||
hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
|
||||
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
|
||||
hw_btn_ins_0_pin.add(btnPin[i]);
|
||||
hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
|
||||
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
|
||||
hw_btn_ins_0_macros.add(macroButton[i]);
|
||||
hw_btn_ins_0_macros.add(macroLongPress[i]);
|
||||
hw_btn_ins_0_macros.add(macroDoublePress[i]);
|
||||
}
|
||||
|
||||
hw_btn[F("tt")] = touchThreshold;
|
||||
hw_btn["mqtt"] = buttonPublishMqtt;
|
||||
|
||||
|
@ -66,18 +66,18 @@
|
||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
||||
|
||||
//Notifier callMode
|
||||
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
|
||||
#define NOTIFIER_CALL_MODE_BUTTON 2
|
||||
#define NOTIFIER_CALL_MODE_NOTIFICATION 3
|
||||
#define NOTIFIER_CALL_MODE_NIGHTLIGHT 4
|
||||
#define NOTIFIER_CALL_MODE_NO_NOTIFY 5
|
||||
#define NOTIFIER_CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define NOTIFIER_CALL_MODE_HUE 7
|
||||
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
|
||||
#define NOTIFIER_CALL_MODE_BLYNK 9
|
||||
#define NOTIFIER_CALL_MODE_ALEXA 10
|
||||
#define NOTIFIER_CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
|
||||
#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define CALL_MODE_DIRECT_CHANGE 1
|
||||
#define CALL_MODE_BUTTON 2
|
||||
#define CALL_MODE_NOTIFICATION 3
|
||||
#define CALL_MODE_NIGHTLIGHT 4
|
||||
#define CALL_MODE_NO_NOTIFY 5
|
||||
#define CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define CALL_MODE_HUE 7
|
||||
#define CALL_MODE_PRESET_CYCLE 8
|
||||
#define CALL_MODE_BLYNK 9
|
||||
#define CALL_MODE_ALEXA 10
|
||||
#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
|
||||
|
||||
//RGB to RGBW conversion mode
|
||||
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
||||
|
@ -156,9 +156,9 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
|
||||
col[3] = e131_data[DMXAddress+11]; //white
|
||||
colSec[3] = e131_data[DMXAddress+12];
|
||||
}
|
||||
transitionDelayTemp = 0; // act fast
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
|
||||
return; // don't activate realtime live mode
|
||||
transitionDelayTemp = 0; // act fast
|
||||
colorUpdated(CALL_MODE_NOTIFICATION); // don't send UDP
|
||||
return; // don't activate realtime live mode
|
||||
break;
|
||||
|
||||
case DMX_MODE_MULTIPLE_DRGB:
|
||||
|
@ -122,7 +122,7 @@ void handleIR();
|
||||
#include "FX.h"
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||
bool deserializeState(JsonObject root, byte presetId = 0);
|
||||
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||
void serializeInfo(JsonObject root);
|
||||
@ -183,7 +183,7 @@ void loadPlaylist(JsonObject playlistObject, byte presetId = 0);
|
||||
void handlePlaylist();
|
||||
|
||||
//presets.cpp
|
||||
bool applyPreset(byte index);
|
||||
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
|
||||
void savePreset(byte index, bool persist = true, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
||||
void deletePreset(byte index);
|
||||
|
||||
|
@ -10,7 +10,7 @@ void handleHue()
|
||||
{
|
||||
if (hueReceived)
|
||||
{
|
||||
colorUpdated(NOTIFIER_CALL_MODE_HUE); hueReceived = false;
|
||||
colorUpdated(CALL_MODE_HUE); hueReceived = false;
|
||||
if (hueStoreAllowed && hueNewKey)
|
||||
{
|
||||
serializeConfigSec(); //save api key
|
||||
@ -92,7 +92,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
if (str == nullptr) return;
|
||||
str += 4;
|
||||
|
||||
StaticJsonDocument<512> root;
|
||||
StaticJsonDocument<1024> root;
|
||||
if (str[0] == '[') //is JSON array
|
||||
{
|
||||
auto error = deserializeJson(root, str);
|
||||
|
@ -69,9 +69,9 @@ void decBrightness()
|
||||
}
|
||||
|
||||
// apply preset or fallback to a effect and palette if it doesn't exist
|
||||
void presetFallback(int8_t presetID, int8_t effectID, int8_t paletteID)
|
||||
void presetFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID)
|
||||
{
|
||||
if (!applyPreset(presetID)) {
|
||||
if (!applyPreset(presetID, CALL_MODE_BUTTON)) {
|
||||
effectCurrent = effectID;
|
||||
effectPalette = paletteID;
|
||||
}
|
||||
@ -88,11 +88,11 @@ bool decodeIRCustom(uint32_t code)
|
||||
{
|
||||
//just examples, feel free to modify or remove
|
||||
case IRCUSTOM_ONOFF : toggleOnOff(); break;
|
||||
case IRCUSTOM_MACRO1 : applyPreset(1); break;
|
||||
case IRCUSTOM_MACRO1 : applyPreset(1, CALL_MODE_BUTTON); break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
if (code != IRCUSTOM_MACRO1) colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //don't update color again if we apply macro, it already does it
|
||||
if (code != IRCUSTOM_MACRO1) colorUpdated(CALL_MODE_BUTTON); //don't update color again if we apply macro, it already does it
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
@ -187,51 +187,51 @@ void decodeIR(uint32_t code)
|
||||
}
|
||||
|
||||
if (nightlightActive && bri == 0) nightlightActive = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
|
||||
colorUpdated(CALL_MODE_BUTTON); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
void applyRepeatActions(){
|
||||
|
||||
if (lastRepeatableAction == ACTION_BRIGHT_UP)
|
||||
{
|
||||
incBrightness(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
incBrightness(); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastRepeatableAction == ACTION_BRIGHT_DOWN )
|
||||
{
|
||||
decBrightness(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
decBrightness(); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
if (lastRepeatableAction == ACTION_SPEED_UP)
|
||||
{
|
||||
changeEffectSpeed(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
changeEffectSpeed(lastRepeatableValue); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastRepeatableAction == ACTION_SPEED_DOWN )
|
||||
{
|
||||
changeEffectSpeed(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
changeEffectSpeed(lastRepeatableValue); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
if (lastRepeatableAction == ACTION_INTENSITY_UP)
|
||||
{
|
||||
changeEffectIntensity(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
changeEffectIntensity(lastRepeatableValue); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastRepeatableAction == ACTION_INTENSITY_DOWN )
|
||||
{
|
||||
changeEffectIntensity(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
changeEffectIntensity(lastRepeatableValue); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
if (lastValidCode == IR40_WPLUS)
|
||||
{
|
||||
relativeChangeWhite(10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
relativeChangeWhite(10); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastValidCode == IR40_WMINUS)
|
||||
{
|
||||
relativeChangeWhite(-10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
relativeChangeWhite(-10, 5); colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 )
|
||||
{
|
||||
nightlightActive = true;
|
||||
nightlightStartTime = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
colorUpdated(CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (irEnabled == 8)
|
||||
{
|
||||
@ -261,11 +261,11 @@ void decodeIR24(uint32_t code)
|
||||
case IR24_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; break;
|
||||
case IR24_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; break;
|
||||
case IR24_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; break;
|
||||
case IR24_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; break;
|
||||
case IR24_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_FLASH : presetFallback(1, FX_MODE_COLORTWINKLE, effectPalette); break;
|
||||
case IR24_STROBE : presetFallback(2, FX_MODE_RAINBOW_CYCLE, effectPalette); break;
|
||||
case IR24_FADE : presetFallback(3, FX_MODE_BREATH, effectPalette); break;
|
||||
case IR24_SMOOTH : presetFallback(4, FX_MODE_RAINBOW, effectPalette); break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
@ -293,11 +293,11 @@ void decodeIR24OLD(uint32_t code)
|
||||
case IR24_OLD_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_OLD_FLASH : if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
|
||||
case IR24_OLD_STROBE : if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
|
||||
case IR24_OLD_FADE : if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR24_OLD_SMOOTH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_OLD_FLASH : presetFallback(1, FX_MODE_COLORTWINKLE, 0); break;
|
||||
case IR24_OLD_STROBE : presetFallback(2, FX_MODE_RAINBOW_CYCLE, 0); break;
|
||||
case IR24_OLD_FADE : presetFallback(3, FX_MODE_BREATH, 0); break;
|
||||
case IR24_OLD_SMOOTH : presetFallback(4, FX_MODE_RAINBOW, 0); break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
@ -386,10 +386,10 @@ void decodeIR40(uint32_t code)
|
||||
case IR40_SLOW : changeEffectSpeed(-16); break;
|
||||
case IR40_JUMP7 : changeEffectIntensity( 16); break;
|
||||
case IR40_AUTO : changeEffectIntensity(-16); break;
|
||||
case IR40_JUMP3 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
|
||||
case IR40_FADE3 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR40_FADE7 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
|
||||
case IR40_FLASH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
case IR40_JUMP3 : presetFallback(1, FX_MODE_STATIC, 0); break;
|
||||
case IR40_FADE3 : presetFallback(2, FX_MODE_BREATH, 0); break;
|
||||
case IR40_FADE7 : presetFallback(3, FX_MODE_FIRE_FLICKER, 0); break;
|
||||
case IR40_FLASH : presetFallback(4, FX_MODE_RAINBOW, 0); break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
@ -441,12 +441,12 @@ void decodeIR44(uint32_t code)
|
||||
case IR44_BLUEMINUS : changeEffectIntensity(-16); break;
|
||||
case IR44_QUICK : changeEffectSpeed( 16); break;
|
||||
case IR44_SLOW : changeEffectSpeed(-16); break;
|
||||
case IR44_DIY1 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
|
||||
case IR44_DIY2 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR44_DIY3 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
|
||||
case IR44_DIY4 : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
case IR44_DIY5 : if (!applyPreset(5)) { effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; } break;
|
||||
case IR44_DIY6 : if (!applyPreset(6)) { effectCurrent = FX_MODE_RAIN; effectPalette = 0; } break;
|
||||
case IR44_DIY1 : presetFallback(1, FX_MODE_STATIC, 0); break;
|
||||
case IR44_DIY2 : presetFallback(2, FX_MODE_BREATH, 0); break;
|
||||
case IR44_DIY3 : presetFallback(3, FX_MODE_FIRE_FLICKER, 0); break;
|
||||
case IR44_DIY4 : presetFallback(4, FX_MODE_RAINBOW, 0); break;
|
||||
case IR44_DIY5 : presetFallback(5, FX_MODE_METEOR_SMOOTH, 0); break;
|
||||
case IR44_DIY6 : presetFallback(6, FX_MODE_RAIN, 0); break;
|
||||
case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break;
|
||||
case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break;
|
||||
case IR44_JUMP3 : bri = 63; break;
|
||||
@ -477,10 +477,10 @@ void decodeIR21(uint32_t code)
|
||||
case IR21_PURPLE: colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR21_PINK: colorFromUint32(COLOR_PINK); break;
|
||||
case IR21_WHITE: colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR21_FLASH: if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
|
||||
case IR21_STROBE: if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
|
||||
case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
case IR21_FLASH: presetFallback(1, FX_MODE_COLORTWINKLE, 0); break;
|
||||
case IR21_STROBE: presetFallback(2, FX_MODE_RAINBOW_CYCLE, 0); break;
|
||||
case IR21_FADE: presetFallback(3, FX_MODE_BREATH, 0); break;
|
||||
case IR21_SMOOTH: presetFallback(4, FX_MODE_RAINBOW, 0); break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
@ -522,9 +522,9 @@ void decodeIR9(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR9_POWER : toggleOnOff(); break;
|
||||
case IR9_A : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; break;
|
||||
case IR9_B : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; break;
|
||||
case IR9_C : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; break;
|
||||
case IR9_A : presetFallback(1, FX_MODE_COLORTWINKLE, effectPalette); break;
|
||||
case IR9_B : presetFallback(2, FX_MODE_RAINBOW_CYCLE, effectPalette); break;
|
||||
case IR9_C : presetFallback(3, FX_MODE_BREATH, effectPalette); break;
|
||||
case IR9_UP : incBrightness(); break;
|
||||
case IR9_DOWN : decBrightness(); break;
|
||||
//case IR9_UP : changeEffectIntensity(16); break;
|
||||
@ -616,7 +616,7 @@ void decodeIRJson(uint32_t code)
|
||||
// command is JSON object
|
||||
//allow applyPreset() to reuse JSON buffer, or it would alloc. a second buffer and run out of mem.
|
||||
fileDoc = &irDoc;
|
||||
deserializeState(jsonCmdObj);
|
||||
deserializeState(jsonCmdObj, CALL_MODE_BUTTON);
|
||||
fileDoc = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
return; // seg.hasChanged(prev);
|
||||
}
|
||||
|
||||
bool deserializeState(JsonObject root, byte presetId)
|
||||
bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
{
|
||||
DEBUG_PRINTLN(F("Deserializing state"));
|
||||
|
||||
@ -337,7 +337,7 @@ bool deserializeState(JsonObject root, byte presetId)
|
||||
if (ps >= 0) {
|
||||
DEBUG_PRINTLN(F("Applying preset"));
|
||||
if (!presetId) unloadPlaylist(); //stop playlist if preset changed manually
|
||||
applyPreset(ps);
|
||||
applyPreset(ps, callMode);
|
||||
return stateResponse;
|
||||
}
|
||||
|
||||
@ -355,10 +355,10 @@ bool deserializeState(JsonObject root, byte presetId)
|
||||
loadPlaylist(playlist, presetId);
|
||||
noNotification = true; //do not notify both for this request and the first playlist entry
|
||||
} else {
|
||||
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_WS_SEND;
|
||||
interfaceUpdateCallMode = CALL_MODE_WS_SEND;
|
||||
}
|
||||
|
||||
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated(noNotification ? CALL_MODE_NO_NOTIFY : callMode);
|
||||
|
||||
return stateResponse;
|
||||
}
|
||||
|
@ -88,13 +88,13 @@ void colorUpdated(int callMode)
|
||||
{
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
if (callMode != NOTIFIER_CALL_MODE_INIT &&
|
||||
callMode != NOTIFIER_CALL_MODE_DIRECT_CHANGE &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
|
||||
if (callMode != CALL_MODE_INIT &&
|
||||
callMode != CALL_MODE_DIRECT_CHANGE &&
|
||||
callMode != CALL_MODE_NO_NOTIFY) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
|
||||
|
||||
bool someSel = false;
|
||||
|
||||
if (callMode == NOTIFIER_CALL_MODE_NOTIFICATION) {
|
||||
if (callMode == CALL_MODE_NOTIFICATION) {
|
||||
someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
}
|
||||
|
||||
@ -119,17 +119,17 @@ void colorUpdated(int callMode)
|
||||
interfaceUpdateCallMode = callMode;
|
||||
} else {
|
||||
if (nightlightActive && !nightlightActiveOld &&
|
||||
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY)
|
||||
callMode != CALL_MODE_NOTIFICATION &&
|
||||
callMode != CALL_MODE_NO_NOTIFY)
|
||||
{
|
||||
notify(NOTIFIER_CALL_MODE_NIGHTLIGHT);
|
||||
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_NIGHTLIGHT;
|
||||
notify(CALL_MODE_NIGHTLIGHT);
|
||||
interfaceUpdateCallMode = CALL_MODE_NIGHTLIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!colChanged) return; //following code is for e.g. initiating transitions
|
||||
|
||||
if (callMode != NOTIFIER_CALL_MODE_NO_NOTIFY && nightlightActive && (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE))
|
||||
if (callMode != CALL_MODE_NO_NOTIFY && nightlightActive && (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE))
|
||||
{
|
||||
briNlT = bri;
|
||||
nightlightDelayMs -= (millis() - nightlightStartTime);
|
||||
@ -143,19 +143,19 @@ void colorUpdated(int callMode)
|
||||
if (briT == 0)
|
||||
{
|
||||
//setLedsStandard(true); //do not color transition if starting from off!
|
||||
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
|
||||
if (callMode != CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
|
||||
}
|
||||
|
||||
briIT = bri;
|
||||
if (bri > 0) briLast = bri;
|
||||
|
||||
//deactivate nightlight if target brightness is reached
|
||||
if (bri == nightlightTargetBri && callMode != NOTIFIER_CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
|
||||
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
|
||||
|
||||
if (fadeTransition)
|
||||
{
|
||||
//set correct delay if not using notification delay
|
||||
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
|
||||
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
|
||||
jsonTransitionOnce = false;
|
||||
strip.setTransition(transitionDelayTemp);
|
||||
if (transitionDelayTemp == 0) {setLedsStandard(); strip.trigger(); return;}
|
||||
@ -180,20 +180,20 @@ void colorUpdated(int callMode)
|
||||
void updateInterfaces(uint8_t callMode)
|
||||
{
|
||||
sendDataWs();
|
||||
if (callMode == NOTIFIER_CALL_MODE_WS_SEND) {
|
||||
if (callMode == CALL_MODE_WS_SEND) {
|
||||
lastInterfaceUpdate = millis();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
if (espalexaDevice != nullptr && callMode != NOTIFIER_CALL_MODE_ALEXA) {
|
||||
if (espalexaDevice != nullptr && callMode != CALL_MODE_ALEXA) {
|
||||
espalexaDevice->setValue(bri);
|
||||
espalexaDevice->setColor(col[0], col[1], col[2]);
|
||||
}
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (callMode != NOTIFIER_CALL_MODE_BLYNK &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) updateBlynk();
|
||||
if (callMode != CALL_MODE_BLYNK &&
|
||||
callMode != CALL_MODE_NO_NOTIFY) updateBlynk();
|
||||
#endif
|
||||
doPublishMqtt = true;
|
||||
lastInterfaceUpdate = millis();
|
||||
@ -256,7 +256,7 @@ void handleNightlight()
|
||||
if (bri) effectSpeed += 60; //sunset if currently on
|
||||
briNlT = !bri; //true == sunrise, false == sunset
|
||||
if (!bri) bri = briLast;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
colorUpdated(CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
}
|
||||
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
|
||||
@ -267,7 +267,7 @@ void handleNightlight()
|
||||
{
|
||||
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
colorUpdated(CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
if (nper >= 1) //nightlight duration over
|
||||
{
|
||||
@ -275,7 +275,7 @@ void handleNightlight()
|
||||
if (nightlightMode == NL_MODE_SET)
|
||||
{
|
||||
bri = nightlightTargetBri;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
colorUpdated(CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
if (bri == 0) briLast = briNlT;
|
||||
if (nightlightMode == NL_MODE_SUN)
|
||||
@ -301,7 +301,7 @@ void handleNightlight()
|
||||
effectCurrent = colNlT[0];
|
||||
effectSpeed = colNlT[1];
|
||||
effectPalette = colNlT[2];
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
colorUpdated(CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
nightlightActiveOld = false;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ void parseMQTTBriPayload(char* payload)
|
||||
uint8_t in = strtoul(payload, NULL, 10);
|
||||
if (in == 0 && bri > 0) briLast = bri;
|
||||
bri = in;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,12 +88,14 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
|
||||
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
||||
colorFromDecOrHexString(col, (char*)payloadStr);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
||||
if (payload[0] == '{') { //JSON API
|
||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||
deserializeJson(doc, payloadStr);
|
||||
fileDoc = &doc;
|
||||
deserializeState(doc.as<JsonObject>());
|
||||
fileDoc = nullptr;
|
||||
} else { //HTTP API
|
||||
String apireq = "win&";
|
||||
apireq += (char*)payloadStr;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Methods to handle saving and loading presets to/from the filesystem
|
||||
*/
|
||||
|
||||
bool applyPreset(byte index)
|
||||
bool applyPreset(byte index, byte callMode)
|
||||
{
|
||||
if (index == 0) return false;
|
||||
if (fileDoc) {
|
||||
@ -14,7 +14,7 @@ bool applyPreset(byte index)
|
||||
#ifdef WLED_DEBUG_FS
|
||||
serializeJson(*fileDoc, Serial);
|
||||
#endif
|
||||
deserializeState(fdo, index);
|
||||
deserializeState(fdo, callMode, index);
|
||||
} else {
|
||||
DEBUGFS_PRINTLN(F("Make read buf"));
|
||||
DynamicJsonDocument fDoc(JSON_BUFFER_SIZE);
|
||||
@ -24,7 +24,7 @@ bool applyPreset(byte index)
|
||||
#ifdef WLED_DEBUG_FS
|
||||
serializeJson(fDoc, Serial);
|
||||
#endif
|
||||
deserializeState(fdo, index);
|
||||
deserializeState(fdo, callMode, index);
|
||||
}
|
||||
|
||||
if (!errorFlag) {
|
||||
|
@ -918,7 +918,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
strip.applyToAllSelected = false;
|
||||
|
||||
pos = req.indexOf(F("&NN")); //do not send UDP notifications this time
|
||||
colorUpdated((pos > 0) ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
colorUpdated((pos > 0) ? CALL_MODE_NO_NOTIFY : CALL_MODE_DIRECT_CHANGE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -13,14 +13,14 @@ void notify(byte callMode, bool followUp)
|
||||
if (!udpConnected) return;
|
||||
switch (callMode)
|
||||
{
|
||||
case NOTIFIER_CALL_MODE_INIT: return;
|
||||
case NOTIFIER_CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_BUTTON: if (!notifyButton) return; break;
|
||||
case NOTIFIER_CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_HUE: if (!notifyHue) return; break;
|
||||
case NOTIFIER_CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_BLYNK: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
|
||||
case CALL_MODE_INIT: return;
|
||||
case CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_BUTTON: if (!notifyButton) return; break;
|
||||
case CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_HUE: if (!notifyHue) return; break;
|
||||
case CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_BLYNK: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
|
||||
default: return;
|
||||
}
|
||||
byte udpOut[WLEDPACKETSIZE];
|
||||
@ -300,7 +300,7 @@ void handleNotifications()
|
||||
if (nightlightActive) nightlightDelayMins = udpIn[7];
|
||||
|
||||
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
colorUpdated(CALL_MODE_NOTIFICATION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,10 @@
|
||||
#include "../usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h"
|
||||
#endif
|
||||
|
||||
#ifdef RGB_ROTARY_ENCODER
|
||||
#include "../usermods/rgb-rotary-encoder/rgb-rotary-encoder.h"
|
||||
#endif
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
@ -151,4 +155,8 @@ void registerUsermods()
|
||||
#ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR
|
||||
usermods.add(new RotaryEncoderBrightnessColor());
|
||||
#endif
|
||||
|
||||
#ifdef RGB_ROTARY_ENCODER
|
||||
usermods.add(new RgbRotaryEncoderUsermod());
|
||||
#endif
|
||||
}
|
||||
|
@ -270,6 +270,18 @@ void WLED::loop()
|
||||
if (busConfigs[i] == nullptr) break;
|
||||
mem += BusManager::memUsage(*busConfigs[i]);
|
||||
if (mem <= MAX_LED_MEMORY) busses.add(*busConfigs[i]);
|
||||
/*
|
||||
if (busConfigs[i]->adjustBounds(ledCount)) {
|
||||
mem += busses.memUsage(*busConfigs[i]);
|
||||
if (mem <= MAX_LED_MEMORY) {
|
||||
busses.add(*busConfigs[i]);
|
||||
//RGBW mode is enabled if at least one of the strips is RGBW
|
||||
strip.isRgbw = (strip.isRgbw || BusManager::isRgbw(busConfigs[i]->type));
|
||||
//refresh is required to remain off if at least one of the strips requires the refresh.
|
||||
strip.isOffRefreshRequred |= BusManager::isOffRefreshRequred(busConfigs[i]->type);
|
||||
}
|
||||
}
|
||||
*/
|
||||
delete busConfigs[i]; busConfigs[i] = nullptr;
|
||||
}
|
||||
strip.finalizeInit();
|
||||
@ -354,6 +366,8 @@ void WLED::setup()
|
||||
pinManager.allocatePin(2);
|
||||
#endif
|
||||
|
||||
for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) btnPin[i] = -1;
|
||||
|
||||
bool fsinit = false;
|
||||
DEBUGFS_PRINTLN(F("Mount FS"));
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
@ -450,9 +464,9 @@ void WLED::beginStrip()
|
||||
briLast = briS; bri = 0;
|
||||
}
|
||||
if (bootPreset > 0) {
|
||||
applyPreset(bootPreset);
|
||||
applyPreset(bootPreset, CALL_MODE_INIT);
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_INIT);
|
||||
colorUpdated(CALL_MODE_INIT);
|
||||
|
||||
// init relay pin
|
||||
if (rlyPin>=0)
|
||||
@ -504,14 +518,60 @@ void WLED::initConnection()
|
||||
// Only initialize ethernet board if not NONE
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
ethernet_settings es = ethernetBoards[ethernetType];
|
||||
ETH.begin(
|
||||
(uint8_t) es.eth_address,
|
||||
(int) es.eth_power,
|
||||
(int) es.eth_mdc,
|
||||
(int) es.eth_mdio,
|
||||
(eth_phy_type_t) es.eth_type,
|
||||
(eth_clock_mode_t) es.eth_clk_mode
|
||||
);
|
||||
// Use PinManager to ensure pins are available for
|
||||
// ethernet AND to prevent other uses of these pins.
|
||||
bool s = true;
|
||||
byte pinsAllocated[4] { 255, 255, 255, 255 };
|
||||
|
||||
if (s && (s = pinManager.allocatePin((byte)es.eth_power))) {
|
||||
pinsAllocated[0] = (byte)es.eth_power;
|
||||
}
|
||||
if (s && (s = pinManager.allocatePin((byte)es.eth_mdc))) {
|
||||
pinsAllocated[1] = (byte)es.eth_mdc;
|
||||
}
|
||||
if (s && (s = pinManager.allocatePin((byte)es.eth_mdio))) {
|
||||
pinsAllocated[2] = (byte)es.eth_mdio;
|
||||
}
|
||||
switch(es.eth_clk_mode) {
|
||||
case ETH_CLOCK_GPIO0_IN:
|
||||
s = pinManager.allocatePin(0, false);
|
||||
pinsAllocated[3] = 0;
|
||||
break;
|
||||
case ETH_CLOCK_GPIO0_OUT:
|
||||
s = pinManager.allocatePin(0);
|
||||
pinsAllocated[3] = 0;
|
||||
break;
|
||||
case ETH_CLOCK_GPIO16_OUT:
|
||||
s = pinManager.allocatePin(16);
|
||||
pinsAllocated[3] = 16;
|
||||
break;
|
||||
case ETH_CLOCK_GPIO17_OUT:
|
||||
s = pinManager.allocatePin(17);
|
||||
pinsAllocated[3] = 17;
|
||||
break;
|
||||
default:
|
||||
s = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s) {
|
||||
s = ETH.begin(
|
||||
(uint8_t) es.eth_address,
|
||||
(int) es.eth_power,
|
||||
(int) es.eth_mdc,
|
||||
(int) es.eth_mdio,
|
||||
(eth_phy_type_t) es.eth_type,
|
||||
(eth_clock_mode_t) es.eth_clk_mode
|
||||
);
|
||||
}
|
||||
|
||||
if (!s) {
|
||||
DEBUG_PRINTLN(F("Ethernet init failed"));
|
||||
// de-allocate only those pins allocated before the failure
|
||||
for (byte p : pinsAllocated) {
|
||||
pinManager.deallocatePin(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2107080
|
||||
#define VERSION 2107101
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -449,7 +449,7 @@ WLED_GLOBAL byte touchThreshold _INIT(TOUCH_THRESH
|
||||
WLED_GLOBAL bool notifyDirectDefault _INIT(notifyDirect);
|
||||
WLED_GLOBAL bool receiveNotifications _INIT(true);
|
||||
WLED_GLOBAL unsigned long notificationSentTime _INIT(0);
|
||||
WLED_GLOBAL byte notificationSentCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
|
||||
WLED_GLOBAL byte notificationSentCallMode _INIT(CALL_MODE_INIT);
|
||||
WLED_GLOBAL bool notificationTwoRequired _INIT(false);
|
||||
|
||||
// effects
|
||||
@ -515,7 +515,7 @@ WLED_GLOBAL uint16_t tpmPayloadFrameSize _INIT(0);
|
||||
// mqtt
|
||||
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0);
|
||||
WLED_GLOBAL unsigned long lastInterfaceUpdate _INIT(0);
|
||||
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
|
||||
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(CALL_MODE_INIT);
|
||||
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
|
||||
|
||||
// alexa udp
|
||||
|
Loading…
Reference in New Issue
Block a user