2020-03-25 09:00:55 +01:00
|
|
|
#include "wled.h"
|
2020-03-31 02:38:08 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* LED methods
|
|
|
|
*/
|
2022-02-25 10:24:00 +01:00
|
|
|
|
|
|
|
void setValuesFromMainSeg() { setValuesFromSegment(strip.getMainSegmentId()); }
|
|
|
|
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
|
|
|
|
void setValuesFromSegment(uint8_t s)
|
2019-12-03 14:15:12 +01:00
|
|
|
{
|
2022-07-06 13:13:54 +02:00
|
|
|
Segment& seg = strip.getSegment(s);
|
2022-02-09 17:16:22 +01:00
|
|
|
col[0] = R(seg.colors[0]);
|
|
|
|
col[1] = G(seg.colors[0]);
|
|
|
|
col[2] = B(seg.colors[0]);
|
|
|
|
col[3] = W(seg.colors[0]);
|
|
|
|
colSec[0] = R(seg.colors[1]);
|
|
|
|
colSec[1] = G(seg.colors[1]);
|
|
|
|
colSec[2] = B(seg.colors[1]);
|
|
|
|
colSec[3] = W(seg.colors[1]);
|
2022-02-21 19:44:12 +01:00
|
|
|
effectCurrent = seg.mode;
|
|
|
|
effectSpeed = seg.speed;
|
2019-12-03 14:15:12 +01:00
|
|
|
effectIntensity = seg.intensity;
|
2022-02-21 19:44:12 +01:00
|
|
|
effectPalette = seg.palette;
|
2019-12-03 14:15:12 +01:00
|
|
|
}
|
2016-12-31 00:38:51 +01:00
|
|
|
|
2019-12-13 01:23:07 +01:00
|
|
|
|
2022-02-23 19:20:07 +01:00
|
|
|
// applies global legacy values (col, colSec, effectCurrent...)
|
|
|
|
// problem: if the first selected segment already has the value to be set, other selected segments are not updated
|
2022-02-20 22:24:11 +01:00
|
|
|
void applyValuesToSelectedSegs()
|
|
|
|
{
|
2022-02-23 19:20:07 +01:00
|
|
|
// copy of first selected segment to tell if value was updated
|
|
|
|
uint8_t firstSel = strip.getFirstSelectedSegId();
|
2022-07-06 13:13:54 +02:00
|
|
|
Segment selsegPrev = strip.getSegment(firstSel);
|
2022-07-19 16:16:43 +02:00
|
|
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
2022-07-06 13:13:54 +02:00
|
|
|
Segment& seg = strip.getSegment(i);
|
2022-02-23 19:20:07 +01:00
|
|
|
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
|
2022-02-20 22:24:11 +01:00
|
|
|
|
2022-02-24 13:43:12 +01:00
|
|
|
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
|
|
|
if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
|
|
|
|
if (effectPalette != selsegPrev.palette) {seg.palette = effectPalette; stateChanged = true;}
|
|
|
|
if (effectCurrent != selsegPrev.mode) {strip.setMode(i, effectCurrent); stateChanged = true;}
|
2022-02-22 10:42:00 +01:00
|
|
|
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
2022-02-20 22:24:11 +01:00
|
|
|
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
2022-07-10 22:23:25 +02:00
|
|
|
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0); stateChanged = true;}
|
|
|
|
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1); stateChanged = true;}
|
2022-02-20 22:24:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-13 01:23:07 +01:00
|
|
|
void resetTimebase()
|
|
|
|
{
|
|
|
|
strip.timebase = 0 - millis();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-22 00:09:30 +01:00
|
|
|
void toggleOnOff()
|
|
|
|
{
|
|
|
|
if (bri == 0)
|
|
|
|
{
|
|
|
|
bri = briLast;
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
briLast = bri;
|
|
|
|
bri = 0;
|
|
|
|
}
|
2022-09-09 17:21:13 +02:00
|
|
|
stateChanged = true;
|
2018-11-22 00:09:30 +01:00
|
|
|
}
|
|
|
|
|
2018-11-24 11:52:23 +01:00
|
|
|
|
2020-10-29 01:23:04 +01:00
|
|
|
//scales the brightness with the briMultiplier factor
|
|
|
|
byte scaledBri(byte in)
|
|
|
|
{
|
2021-10-22 21:31:03 +02:00
|
|
|
uint16_t val = ((uint16_t)in*briMultiplier)/100;
|
2020-10-29 01:23:04 +01:00
|
|
|
if (val > 255) val = 255;
|
|
|
|
return (byte)val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-20 22:24:11 +01:00
|
|
|
//applies global brightness
|
|
|
|
void applyBri() {
|
2021-08-10 17:11:17 +02:00
|
|
|
if (!realtimeMode || !arlsForceMaxBri)
|
|
|
|
{
|
|
|
|
strip.setBrightness(scaledBri(briT));
|
|
|
|
}
|
2016-11-19 19:39:17 +01:00
|
|
|
}
|
|
|
|
|
2018-11-24 11:52:23 +01:00
|
|
|
|
2022-02-20 22:24:11 +01:00
|
|
|
//applies global brightness and sets it as the "current" brightness (no transition)
|
|
|
|
void applyFinalBri() {
|
2018-03-14 13:16:28 +01:00
|
|
|
briOld = bri;
|
|
|
|
briT = bri;
|
2022-02-20 22:24:11 +01:00
|
|
|
applyBri();
|
2016-11-19 19:39:17 +01:00
|
|
|
}
|
|
|
|
|
2018-11-24 11:52:23 +01:00
|
|
|
|
2022-02-20 22:24:11 +01:00
|
|
|
//called after every state changes, schedules interface updates, handles brightness transition and nightlight activation
|
|
|
|
//unlike colorUpdated(), does NOT apply any colors or FX to segments
|
|
|
|
void stateUpdated(byte callMode) {
|
2018-11-24 11:52:23 +01:00
|
|
|
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
2021-12-11 23:44:21 +01:00
|
|
|
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa 11: ws send only 12: button preset
|
2022-02-23 19:20:07 +01:00
|
|
|
setValuesFromFirstSelectedSeg();
|
2020-12-14 23:32:57 +01:00
|
|
|
|
2022-02-21 22:12:13 +01:00
|
|
|
if (bri != briOld || stateChanged) {
|
|
|
|
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2022-01-15 00:06:06 +01:00
|
|
|
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2023-02-21 17:07:32 +01:00
|
|
|
//set flag to update ws and mqtt
|
2020-12-10 16:27:23 +01:00
|
|
|
interfaceUpdateCallMode = callMode;
|
2022-02-21 22:12:13 +01:00
|
|
|
stateChanged = false;
|
2020-02-24 17:25:40 +01:00
|
|
|
} else {
|
2022-01-14 14:27:11 +01:00
|
|
|
if (nightlightActive && !nightlightActiveOld && callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) {
|
2023-01-06 09:24:29 +01:00
|
|
|
notify(CALL_MODE_NIGHTLIGHT);
|
2021-07-09 18:54:28 +02:00
|
|
|
interfaceUpdateCallMode = CALL_MODE_NIGHTLIGHT;
|
2019-04-14 19:31:25 +02:00
|
|
|
}
|
2016-11-19 19:39:17 +01:00
|
|
|
}
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2022-01-14 14:27:11 +01:00
|
|
|
if (callMode != CALL_MODE_NO_NOTIFY && nightlightActive && (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE)) {
|
2018-03-14 13:16:28 +01:00
|
|
|
briNlT = bri;
|
2017-04-26 14:04:53 +02:00
|
|
|
nightlightDelayMs -= (millis() - nightlightStartTime);
|
|
|
|
nightlightStartTime = millis();
|
|
|
|
}
|
2022-01-14 14:27:11 +01:00
|
|
|
if (briT == 0) {
|
2021-07-09 18:54:28 +02:00
|
|
|
if (callMode != CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
|
2020-02-09 10:35:32 +01:00
|
|
|
}
|
|
|
|
|
2018-03-14 13:16:28 +01:00
|
|
|
if (bri > 0) briLast = bri;
|
2020-06-22 12:30:31 +02:00
|
|
|
|
|
|
|
//deactivate nightlight if target brightness is reached
|
2021-07-09 18:54:28 +02:00
|
|
|
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2023-02-05 12:23:05 +01:00
|
|
|
// notify usermods of state change
|
|
|
|
usermods.onStateChange(callMode);
|
|
|
|
|
2022-01-14 14:27:11 +01:00
|
|
|
if (fadeTransition) {
|
2018-03-15 13:03:50 +01:00
|
|
|
//set correct delay if not using notification delay
|
2022-07-29 12:15:56 +02:00
|
|
|
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration
|
2019-10-29 02:21:23 +01:00
|
|
|
jsonTransitionOnce = false;
|
2021-01-09 00:35:48 +01:00
|
|
|
strip.setTransition(transitionDelayTemp);
|
2022-01-14 14:27:11 +01:00
|
|
|
if (transitionDelayTemp == 0) {
|
2022-02-20 22:24:11 +01:00
|
|
|
applyFinalBri();
|
2022-01-14 14:27:11 +01:00
|
|
|
strip.trigger();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (transitionActive) {
|
2018-03-14 13:16:28 +01:00
|
|
|
briOld = briT;
|
|
|
|
tperLast = 0;
|
2016-11-19 19:39:17 +01:00
|
|
|
}
|
2022-07-29 12:15:56 +02:00
|
|
|
strip.setTransitionMode(true); // force all segments to transition mode
|
2016-11-19 19:39:17 +01:00
|
|
|
transitionActive = true;
|
|
|
|
transitionStartTime = millis();
|
2022-01-14 14:27:11 +01:00
|
|
|
} else {
|
2021-01-09 00:35:48 +01:00
|
|
|
strip.setTransition(0);
|
2022-02-20 22:24:11 +01:00
|
|
|
applyFinalBri();
|
2017-11-19 15:31:17 +01:00
|
|
|
strip.trigger();
|
2016-11-19 19:39:17 +01:00
|
|
|
}
|
2018-10-04 16:50:12 +02:00
|
|
|
}
|
|
|
|
|
2018-11-24 11:52:23 +01:00
|
|
|
|
2018-10-04 16:50:12 +02:00
|
|
|
void updateInterfaces(uint8_t callMode)
|
|
|
|
{
|
2020-06-26 17:28:35 +02:00
|
|
|
sendDataWs();
|
2022-01-25 12:47:14 +01:00
|
|
|
lastInterfaceUpdate = millis();
|
2022-01-02 14:27:24 +01:00
|
|
|
if (callMode == CALL_MODE_WS_SEND) return;
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2019-03-01 17:10:42 +01:00
|
|
|
#ifndef WLED_DISABLE_ALEXA
|
2021-07-09 18:54:28 +02:00
|
|
|
if (espalexaDevice != nullptr && callMode != CALL_MODE_ALEXA) {
|
2019-03-01 17:10:42 +01:00
|
|
|
espalexaDevice->setValue(bri);
|
|
|
|
espalexaDevice->setColor(col[0], col[1], col[2]);
|
|
|
|
}
|
|
|
|
#endif
|
2019-10-20 17:38:25 +02:00
|
|
|
doPublishMqtt = true;
|
2022-04-16 16:28:43 +02:00
|
|
|
interfaceUpdateCallMode = 0; //disable
|
2016-11-19 19:39:17 +01:00
|
|
|
}
|
|
|
|
|
2018-11-24 11:52:23 +01:00
|
|
|
|
2016-11-19 19:39:17 +01:00
|
|
|
void handleTransitions()
|
|
|
|
{
|
2018-10-04 16:50:12 +02:00
|
|
|
//handle still pending interface update
|
2022-04-16 16:28:43 +02:00
|
|
|
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > INTERFACE_UPDATE_COOLDOWN) updateInterfaces(interfaceUpdateCallMode);
|
2023-01-12 20:35:34 +01:00
|
|
|
#ifndef WLED_DISABLE_MQTT
|
2019-10-20 17:38:25 +02:00
|
|
|
if (doPublishMqtt) publishMqtt();
|
2023-01-12 20:35:34 +01:00
|
|
|
#endif
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2018-03-15 13:03:50 +01:00
|
|
|
if (transitionActive && transitionDelayTemp > 0)
|
2016-11-19 19:39:17 +01:00
|
|
|
{
|
2018-03-15 13:03:50 +01:00
|
|
|
float tper = (millis() - transitionStartTime)/(float)transitionDelayTemp;
|
2016-11-19 19:39:17 +01:00
|
|
|
if (tper >= 1.0)
|
|
|
|
{
|
2018-09-06 02:05:56 +02:00
|
|
|
strip.setTransitionMode(false);
|
2016-11-19 19:39:17 +01:00
|
|
|
transitionActive = false;
|
2018-03-14 13:16:28 +01:00
|
|
|
tperLast = 0;
|
2022-02-20 22:24:11 +01:00
|
|
|
applyFinalBri();
|
2016-11-19 19:39:17 +01:00
|
|
|
return;
|
|
|
|
}
|
2019-02-05 19:40:24 +01:00
|
|
|
if (tper - tperLast < 0.004) return;
|
2018-03-14 13:16:28 +01:00
|
|
|
tperLast = tper;
|
2022-12-03 20:55:17 +01:00
|
|
|
briT = briOld + ((bri - briOld) * tper);
|
2023-01-06 09:24:29 +01:00
|
|
|
|
2022-02-20 22:24:11 +01:00
|
|
|
applyBri();
|
2016-11-27 16:45:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-24 11:52:23 +01:00
|
|
|
|
2022-12-03 20:55:17 +01:00
|
|
|
// legacy method, applies values from col, effectCurrent, ... to selected segments
|
2022-02-20 22:24:11 +01:00
|
|
|
void colorUpdated(byte callMode){
|
|
|
|
applyValuesToSelectedSegs();
|
|
|
|
stateUpdated(callMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-27 16:45:54 +01:00
|
|
|
void handleNightlight()
|
|
|
|
{
|
2022-01-15 00:06:06 +01:00
|
|
|
static unsigned long lastNlUpdate;
|
|
|
|
unsigned long now = millis();
|
2022-12-03 20:55:17 +01:00
|
|
|
if (now < 100 && lastNlUpdate > 0) lastNlUpdate = 0; // take care of millis() rollover
|
|
|
|
if (now - lastNlUpdate < 100) return; // allow only 10 NL updates per second
|
2022-01-15 00:06:06 +01:00
|
|
|
lastNlUpdate = now;
|
|
|
|
|
2016-11-27 16:45:54 +01:00
|
|
|
if (nightlightActive)
|
|
|
|
{
|
2018-03-14 13:16:28 +01:00
|
|
|
if (!nightlightActiveOld) //init
|
2016-11-27 16:45:54 +01:00
|
|
|
{
|
2016-12-11 20:11:14 +01:00
|
|
|
nightlightStartTime = millis();
|
2016-11-27 16:45:54 +01:00
|
|
|
nightlightDelayMs = (int)(nightlightDelayMins*60000);
|
2018-03-14 13:16:28 +01:00
|
|
|
nightlightActiveOld = true;
|
|
|
|
briNlT = bri;
|
2020-09-10 11:01:05 +02:00
|
|
|
for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nightlightMode == NL_MODE_SUN)
|
|
|
|
{
|
|
|
|
//save current
|
|
|
|
colNlT[0] = effectCurrent;
|
|
|
|
colNlT[1] = effectSpeed;
|
|
|
|
colNlT[2] = effectPalette;
|
|
|
|
|
2022-02-23 19:20:07 +01:00
|
|
|
strip.setMode(strip.getFirstSelectedSegId(), FX_MODE_STATIC); // make sure seg runtime is reset if it was in sunrise mode
|
2020-06-22 12:30:31 +02:00
|
|
|
effectCurrent = FX_MODE_SUNRISE;
|
|
|
|
effectSpeed = nightlightDelayMins;
|
|
|
|
effectPalette = 0;
|
|
|
|
if (effectSpeed > 60) effectSpeed = 60; //currently limited to 60 minutes
|
|
|
|
if (bri) effectSpeed += 60; //sunset if currently on
|
|
|
|
briNlT = !bri; //true == sunrise, false == sunset
|
|
|
|
if (!bri) bri = briLast;
|
2021-07-09 18:54:28 +02:00
|
|
|
colorUpdated(CALL_MODE_NO_NOTIFY);
|
2020-06-22 12:30:31 +02:00
|
|
|
}
|
2016-11-27 16:45:54 +01:00
|
|
|
}
|
|
|
|
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE)
|
2017-04-26 14:04:53 +02:00
|
|
|
{
|
2018-11-09 17:00:36 +01:00
|
|
|
bri = briNlT + ((nightlightTargetBri - briNlT)*nper);
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nightlightMode == NL_MODE_COLORFADE) // color fading only is enabled with "NF=2"
|
2020-01-08 12:00:25 +01:00
|
|
|
{
|
2020-02-24 17:27:59 +01:00
|
|
|
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
|
2020-01-08 12:00:25 +01:00
|
|
|
}
|
2021-07-09 18:54:28 +02:00
|
|
|
colorUpdated(CALL_MODE_NO_NOTIFY);
|
2017-04-26 14:04:53 +02:00
|
|
|
}
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nper >= 1) //nightlight duration over
|
2016-11-27 16:45:54 +01:00
|
|
|
{
|
|
|
|
nightlightActive = false;
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nightlightMode == NL_MODE_SET)
|
2016-12-11 20:11:14 +01:00
|
|
|
{
|
2018-02-20 22:29:48 +01:00
|
|
|
bri = nightlightTargetBri;
|
2021-07-09 18:54:28 +02:00
|
|
|
colorUpdated(CALL_MODE_NO_NOTIFY);
|
2016-12-11 20:11:14 +01:00
|
|
|
}
|
2018-03-14 13:16:28 +01:00
|
|
|
if (bri == 0) briLast = briNlT;
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nightlightMode == NL_MODE_SUN)
|
|
|
|
{
|
|
|
|
if (!briNlT) { //turn off if sunset
|
|
|
|
effectCurrent = colNlT[0];
|
|
|
|
effectSpeed = colNlT[1];
|
|
|
|
effectPalette = colNlT[2];
|
|
|
|
toggleOnOff();
|
2022-02-20 22:24:11 +01:00
|
|
|
applyFinalBri();
|
2020-06-22 12:30:31 +02:00
|
|
|
}
|
|
|
|
}
|
2023-02-21 17:07:32 +01:00
|
|
|
|
2020-06-22 12:30:31 +02:00
|
|
|
if (macroNl > 0)
|
2020-11-06 22:12:48 +01:00
|
|
|
applyPreset(macroNl);
|
2020-06-22 12:30:31 +02:00
|
|
|
nightlightActiveOld = false;
|
2016-11-27 16:45:54 +01:00
|
|
|
}
|
2018-03-14 13:16:28 +01:00
|
|
|
} else if (nightlightActiveOld) //early de-init
|
2016-11-27 16:45:54 +01:00
|
|
|
{
|
2020-06-22 12:30:31 +02:00
|
|
|
if (nightlightMode == NL_MODE_SUN) { //restore previous effect
|
|
|
|
effectCurrent = colNlT[0];
|
|
|
|
effectSpeed = colNlT[1];
|
|
|
|
effectPalette = colNlT[2];
|
2021-07-09 18:54:28 +02:00
|
|
|
colorUpdated(CALL_MODE_NO_NOTIFY);
|
2020-06-22 12:30:31 +02:00
|
|
|
}
|
2018-03-14 13:16:28 +01:00
|
|
|
nightlightActiveOld = false;
|
2016-11-27 16:45:54 +01:00
|
|
|
}
|
|
|
|
}
|
2020-08-25 17:23:17 +02:00
|
|
|
|
|
|
|
//utility for FastLED to use our custom timer
|
|
|
|
uint32_t get_millisecond_timer()
|
|
|
|
{
|
|
|
|
return strip.now;
|
|
|
|
}
|