Merge pull request #2601 from Aircoookie/minseg-udp
UDP on main segment only.
This commit is contained in:
commit
d2ced93e58
@ -46,6 +46,11 @@
|
|||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//color mangling macros
|
||||||
|
#ifndef RGBW32
|
||||||
|
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Not used in all effects yet */
|
/* Not used in all effects yet */
|
||||||
#define WLED_FPS 42
|
#define WLED_FPS 42
|
||||||
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
||||||
@ -637,12 +642,13 @@ class WS2812FX {
|
|||||||
resetSegments(),
|
resetSegments(),
|
||||||
makeAutoSegments(bool forceReset = false),
|
makeAutoSegments(bool forceReset = false),
|
||||||
fixInvalidSegments(),
|
fixInvalidSegments(),
|
||||||
setPixelColor(uint16_t n, uint32_t c),
|
|
||||||
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||||
show(void),
|
show(void),
|
||||||
setTargetFps(uint8_t fps),
|
setTargetFps(uint8_t fps),
|
||||||
deserializeMap(uint8_t n=0);
|
deserializeMap(uint8_t n=0);
|
||||||
|
|
||||||
|
inline void setPixelColor(uint16_t n, uint32_t c) {setPixelColor(n, byte(c>>16), byte(c>>8), byte(c), byte(c>>24));}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
gammaCorrectBri = false,
|
gammaCorrectBri = false,
|
||||||
gammaCorrectCol = true,
|
gammaCorrectCol = true,
|
||||||
@ -910,7 +916,6 @@ class WS2812FX {
|
|||||||
friend class ColorTransition;
|
friend class ColorTransition;
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
realPixelIndex(uint16_t i),
|
|
||||||
transitionProgress(uint8_t tNr);
|
transitionProgress(uint8_t tNr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -131,6 +131,8 @@ void WS2812FX::service() {
|
|||||||
|
|
||||||
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
||||||
{
|
{
|
||||||
|
//if (realtimeMode && useMainSegmentOnly && i == getMainSegmentId()) continue;
|
||||||
|
|
||||||
_segment_index = i;
|
_segment_index = i;
|
||||||
|
|
||||||
// reset the segment runtime data if needed, called before isActive to ensure deleted
|
// reset the segment runtime data if needed, called before isActive to ensure deleted
|
||||||
@ -185,34 +187,11 @@ void WS2812FX::service() {
|
|||||||
_triggered = false;
|
_triggered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
|
|
||||||
setPixelColor(n, R(c), G(c), B(c), W(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
//used to map from segment index to physical pixel, taking into account grouping, offsets, reverse and mirroring
|
|
||||||
uint16_t IRAM_ATTR WS2812FX::realPixelIndex(uint16_t i) {
|
|
||||||
int16_t iGroup = i * SEGMENT.groupLength();
|
|
||||||
|
|
||||||
/* reverse just an individual segment */
|
|
||||||
int16_t realIndex = iGroup;
|
|
||||||
if (IS_REVERSE) {
|
|
||||||
if (IS_MIRROR) {
|
|
||||||
realIndex = (SEGMENT.length() - 1) / 2 - iGroup; //only need to index half the pixels
|
|
||||||
} else {
|
|
||||||
realIndex = (SEGMENT.length() - 1) - iGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
realIndex += SEGMENT.start;
|
|
||||||
return realIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
||||||
{
|
{
|
||||||
if (SEGLEN) {//from segment
|
uint8_t segIdx;
|
||||||
uint16_t realIndex = realPixelIndex(i);
|
|
||||||
uint16_t len = SEGMENT.length();
|
|
||||||
|
|
||||||
|
if (SEGLEN) { // SEGLEN!=0 -> from segment/FX
|
||||||
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
|
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
r = scale8(r, _bri_t);
|
r = scale8(r, _bri_t);
|
||||||
@ -220,30 +199,48 @@ void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte
|
|||||||
b = scale8(b, _bri_t);
|
b = scale8(b, _bri_t);
|
||||||
w = scale8(w, _bri_t);
|
w = scale8(w, _bri_t);
|
||||||
}
|
}
|
||||||
|
segIdx = _segment_index;
|
||||||
|
} else // from live/realtime
|
||||||
|
segIdx = _mainSegment;
|
||||||
|
|
||||||
|
if (SEGLEN || (realtimeMode && useMainSegmentOnly)) {
|
||||||
uint32_t col = RGBW32(r, g, b, w);
|
uint32_t col = RGBW32(r, g, b, w);
|
||||||
|
uint16_t len = _segments[segIdx].length();
|
||||||
|
|
||||||
/* Set all the pixels in the group */
|
// get physical pixel address (taking into account start, grouping, spacing [and offset])
|
||||||
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
|
i = i * _segments[segIdx].groupLength();
|
||||||
uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j);
|
if (_segments[segIdx].options & REVERSE) { // is segment reversed?
|
||||||
if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) {
|
if (_segments[segIdx].options & MIRROR) { // is segment mirrored?
|
||||||
if (IS_MIRROR) { //set the corresponding mirrored pixel
|
i = (len - 1) / 2 - i; //only need to index half the pixels
|
||||||
uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1;
|
} else {
|
||||||
/* offset/phase */
|
i = (len - 1) - i;
|
||||||
indexMir += SEGMENT.offset;
|
}
|
||||||
if (indexMir >= SEGMENT.stop) indexMir -= len;
|
}
|
||||||
|
i += _segments[segIdx].start;
|
||||||
|
|
||||||
|
// set all the pixels in the group
|
||||||
|
for (uint16_t j = 0; j < _segments[segIdx].grouping; j++) {
|
||||||
|
uint16_t indexSet = i + ((_segments[segIdx].options & REVERSE) ? -j : j);
|
||||||
|
if (indexSet >= _segments[segIdx].start && indexSet < _segments[segIdx].stop) {
|
||||||
|
|
||||||
|
if (_segments[segIdx].options & MIRROR) { //set the corresponding mirrored pixel
|
||||||
|
uint16_t indexMir = _segments[segIdx].stop - indexSet + _segments[segIdx].start - 1;
|
||||||
|
indexMir += _segments[segIdx].offset; // offset/phase
|
||||||
|
|
||||||
|
if (indexMir >= _segments[segIdx].stop) indexMir -= len;
|
||||||
if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir];
|
if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir];
|
||||||
|
|
||||||
busses.setPixelColor(indexMir, col);
|
busses.setPixelColor(indexMir, col);
|
||||||
}
|
}
|
||||||
/* offset/phase */
|
indexSet += _segments[segIdx].offset; // offset/phase
|
||||||
indexSet += SEGMENT.offset;
|
|
||||||
if (indexSet >= SEGMENT.stop) indexSet -= len;
|
|
||||||
|
|
||||||
|
if (indexSet >= _segments[segIdx].stop) indexSet -= len;
|
||||||
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
|
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
|
||||||
|
|
||||||
busses.setPixelColor(indexSet, col);
|
busses.setPixelColor(indexSet, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { //live data, etc.
|
} else {
|
||||||
if (i < customMappingSize) i = customMappingTable[i];
|
if (i < customMappingSize) i = customMappingTable[i];
|
||||||
busses.setPixelColor(i, RGBW32(r, g, b, w));
|
busses.setPixelColor(i, RGBW32(r, g, b, w));
|
||||||
}
|
}
|
||||||
@ -508,7 +505,13 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
|||||||
|
|
||||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||||
{
|
{
|
||||||
i = realPixelIndex(i);
|
// get physical pixel
|
||||||
|
i = i * SEGMENT.groupLength();;
|
||||||
|
if (IS_REVERSE) {
|
||||||
|
if (IS_MIRROR) i = (SEGMENT.length() - 1) / 2 - i; //only need to index half the pixels
|
||||||
|
else i = (SEGMENT.length() - 1) - i;
|
||||||
|
}
|
||||||
|
i += SEGMENT.start;
|
||||||
|
|
||||||
if (SEGLEN) {
|
if (SEGLEN) {
|
||||||
/* offset/phase */
|
/* offset/phase */
|
||||||
@ -523,7 +526,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
|
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
|
||||||
if (id >= MAX_NUM_SEGMENTS) return _segments[0];
|
if (id >= MAX_NUM_SEGMENTS) return _segments[getMainSegmentId()];
|
||||||
return _segments[id];
|
return _segments[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +291,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
|
|
||||||
JsonObject if_live = interfaces["live"];
|
JsonObject if_live = interfaces["live"];
|
||||||
CJSON(receiveDirect, if_live["en"]);
|
CJSON(receiveDirect, if_live["en"]);
|
||||||
|
CJSON(useMainSegmentOnly, if_live[F("mso")]);
|
||||||
CJSON(e131Port, if_live["port"]); // 5568
|
CJSON(e131Port, if_live["port"]); // 5568
|
||||||
if (e131Port == DDP_DEFAULT_PORT) e131Port = E131_DEFAULT_PORT; // prevent double DDP port allocation
|
if (e131Port == DDP_DEFAULT_PORT) e131Port = E131_DEFAULT_PORT; // prevent double DDP port allocation
|
||||||
CJSON(e131Multicast, if_live[F("mc")]);
|
CJSON(e131Multicast, if_live[F("mc")]);
|
||||||
@ -704,6 +705,7 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonObject if_live = interfaces.createNestedObject("live");
|
JsonObject if_live = interfaces.createNestedObject("live");
|
||||||
if_live["en"] = receiveDirect;
|
if_live["en"] = receiveDirect;
|
||||||
|
if_live[F("mso")] = useMainSegmentOnly;
|
||||||
if_live["port"] = e131Port;
|
if_live["port"] = e131Port;
|
||||||
if_live[F("mc")] = e131Multicast;
|
if_live[F("mc")] = e131Multicast;
|
||||||
|
|
||||||
|
@ -864,6 +864,19 @@ input[type=number]::-webkit-outer-spin-button {
|
|||||||
right: 8px;
|
right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.frz {
|
||||||
|
left: 36px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO expanded does not seem to apply to .frz, what is this for? */
|
||||||
|
.expanded .frz {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.check, .radio {
|
.check, .radio {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -137,7 +137,7 @@
|
|||||||
<div id="Effects" class="tabcontent">
|
<div id="Effects" class="tabcontent">
|
||||||
<p class="labels">Effect speed</p>
|
<p class="labels">Effect speed</p>
|
||||||
<div class="staytop">
|
<div class="staytop">
|
||||||
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglFreeze()"></i>
|
<i class="icons slider-icon" style="cursor: pointer;" title="Freeze" onclick="tglFreeze()"></i>
|
||||||
<div class="sliderwrap il">
|
<div class="sliderwrap il">
|
||||||
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||||
<output class="sliderbubble hidden"></output>
|
<output class="sliderbubble hidden"></output>
|
||||||
|
@ -566,6 +566,7 @@ function populateInfo(i)
|
|||||||
function populateSegments(s)
|
function populateSegments(s)
|
||||||
{
|
{
|
||||||
var cn = "";
|
var cn = "";
|
||||||
|
let li = lastinfo;
|
||||||
segCount = 0; lowestUnused = 0; lSeg = 0;
|
segCount = 0; lowestUnused = 0; lSeg = 0;
|
||||||
|
|
||||||
for (var y = 0; y < (s.seg||[]).length; y++)
|
for (var y = 0; y < (s.seg||[]).length; y++)
|
||||||
@ -584,6 +585,7 @@ function populateSegments(s)
|
|||||||
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>
|
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark schk"></span>
|
||||||
</label>
|
</label>
|
||||||
|
<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});" style="display:${inst.frz?"inline":"none"}">&#x${li.live && li.liveseg==i?'e410':'e325'};</i>
|
||||||
<div class="segname">
|
<div class="segname">
|
||||||
<div class="segntxt" onclick="selSegEx(${i})">${inst.n ? inst.n : "Segment "+i}</div>
|
<div class="segntxt" onclick="selSegEx(${i})">${inst.n ? inst.n : "Segment "+i}</div>
|
||||||
<i class="icons edit-icon ${expanded[i] ? "expanded":""}" id="seg${i}nedit" onclick="tglSegn(${i})"></i>
|
<i class="icons edit-icon ${expanded[i] ? "expanded":""}" id="seg${i}nedit" onclick="tglSegn(${i})"></i>
|
||||||
@ -964,7 +966,7 @@ function updateUI()
|
|||||||
|
|
||||||
function displayRover(i,s)
|
function displayRover(i,s)
|
||||||
{
|
{
|
||||||
d.getElementById('rover').style.transform = (i.live && s.lor == 0) ? "translateY(0px)":"translateY(100%)";
|
d.getElementById('rover').style.transform = (i.live && s.lor == 0 && i.liveseg<0) ? "translateY(0px)":"translateY(100%)";
|
||||||
var sour = i.lip ? i.lip:""; if (sour.length > 2) sour = " from " + sour;
|
var sour = i.lip ? i.lip:""; if (sour.length > 2) sour = " from " + sour;
|
||||||
d.getElementById('lv').innerHTML = `WLED is receiving live ${i.lm} data${sour}`;
|
d.getElementById('lv').innerHTML = `WLED is receiving live ${i.lm} data${sour}`;
|
||||||
d.getElementById('roverstar').style.display = (i.live && s.lor) ? "block":"none";
|
d.getElementById('roverstar').style.display = (i.live && s.lor) ? "block":"none";
|
||||||
@ -1643,7 +1645,11 @@ function setSegBri(s){
|
|||||||
function tglFreeze(s=null)
|
function tglFreeze(s=null)
|
||||||
{
|
{
|
||||||
var obj = {"seg": {"frz": "t"}}; // toggle
|
var obj = {"seg": {"frz": "t"}}; // toggle
|
||||||
if (s!==null) obj.id = s;
|
if (s!==null) {
|
||||||
|
obj.seg.id = s;
|
||||||
|
// if live segment, enter live override (which also unfreezes)
|
||||||
|
if (lastinfo && s==lastinfo.liveseg && lastinfo.live) obj = {"lor":1};
|
||||||
|
}
|
||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,8 @@ Send notifications twice: <input type="checkbox" name="S2"><br>
|
|||||||
Enable instance list: <input type="checkbox" name="NL"><br>
|
Enable instance list: <input type="checkbox" name="NL"><br>
|
||||||
Make this instance discoverable: <input type="checkbox" name="NB">
|
Make this instance discoverable: <input type="checkbox" name="NB">
|
||||||
<h3>Realtime</h3>
|
<h3>Realtime</h3>
|
||||||
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
|
Receive UDP realtime: <input type="checkbox" name="RD"><br>
|
||||||
|
Use main segment only: <input type="checkbox" name="MO"><br><br>
|
||||||
<i>Network DMX input</i><br>
|
<i>Network DMX input</i><br>
|
||||||
Type:
|
Type:
|
||||||
<select name=DI onchange="SP(); adj();">
|
<select name=DI onchange="SP(); adj();">
|
||||||
|
@ -206,6 +206,7 @@ bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte
|
|||||||
void notify(byte callMode, bool followUp=false);
|
void notify(byte callMode, bool followUp=false);
|
||||||
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
|
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
|
||||||
void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
|
void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
|
||||||
|
void exitRealtime();
|
||||||
void handleNotifications();
|
void handleNotifications();
|
||||||
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
|
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
|
||||||
void refreshNodeList();
|
void refreshNodeList();
|
||||||
|
@ -290,7 +290,8 @@ Send notifications twice: <input type="checkbox" name="S2"><br><i>
|
|||||||
Reboot required to apply changes.</i><h3>Instance List</h3>
|
Reboot required to apply changes.</i><h3>Instance List</h3>
|
||||||
Enable instance list: <input type="checkbox" name="NL"><br>
|
Enable instance list: <input type="checkbox" name="NL"><br>
|
||||||
Make this instance discoverable: <input type="checkbox" name="NB"><h3>Realtime
|
Make this instance discoverable: <input type="checkbox" name="NB"><h3>Realtime
|
||||||
</h3>Receive UDP realtime: <input type="checkbox" name="RD"><br><br><i>
|
</h3>Receive UDP realtime: <input type="checkbox" name="RD"><br>
|
||||||
|
Use main segment only: <input type="checkbox" name="MO"><br><br><i>
|
||||||
Network DMX input</i><br>Type: <select name="DI" onchange="SP(),adj()"><option
|
Network DMX input</i><br>Type: <select name="DI" onchange="SP(),adj()"><option
|
||||||
value="5568">E1.31 (sACN)</option><option value="6454">Art-Net</option><option
|
value="5568">E1.31 (sACN)</option><option value="6454">Art-Net</option><option
|
||||||
value="0" selected="selected">Custom port</option></select><br><div id="xp">
|
value="0" selected="selected">Custom port</option></select><br><div id="xp">
|
||||||
|
4437
wled00/html_ui.h
4437
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -228,8 +228,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
}
|
}
|
||||||
strip.setPixelSegment(oldSegId);
|
strip.setPixelSegment(oldSegId);
|
||||||
strip.trigger();
|
strip.trigger();
|
||||||
} else if (!elem["frz"] && iarr.isNull()) { //return to regular effect
|
// } else if (!elem["frz"] && iarr.isNull()) { //return to regular effect
|
||||||
seg.setOption(SEG_OPTION_FREEZE, false);
|
// seg.setOption(SEG_OPTION_FREEZE, false);
|
||||||
}
|
}
|
||||||
// send UDP if not in preset and something changed that is not just selection
|
// send UDP if not in preset and something changed that is not just selection
|
||||||
//if (!presetId && (seg.differs(prev) & 0x7F)) stateChanged = true;
|
//if (!presetId && (seg.differs(prev) & 0x7F)) stateChanged = true;
|
||||||
@ -243,6 +243,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
{
|
{
|
||||||
bool stateResponse = root[F("v")] | false;
|
bool stateResponse = root[F("v")] | false;
|
||||||
|
|
||||||
|
bool onBefore = bri;
|
||||||
getVal(root["bri"], &bri);
|
getVal(root["bri"], &bri);
|
||||||
|
|
||||||
bool on = root["on"] | (bri > 0);
|
bool on = root["on"] | (bri > 0);
|
||||||
@ -250,6 +251,15 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
|
|
||||||
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
||||||
|
|
||||||
|
if (bri && !onBefore) { // unfreeze all segments when turning on
|
||||||
|
for (uint8_t s=0; s < strip.getMaxSegments(); s++) {
|
||||||
|
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false, s);
|
||||||
|
}
|
||||||
|
if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live
|
||||||
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int tr = -1;
|
int tr = -1;
|
||||||
if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times
|
if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times
|
||||||
tr = root[F("transition")] | -1;
|
tr = root[F("transition")] | -1;
|
||||||
@ -292,23 +302,24 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
|
|
||||||
doReboot = root[F("rb")] | doReboot;
|
doReboot = root[F("rb")] | doReboot;
|
||||||
|
|
||||||
|
strip.setMainSegmentId(root[F("mainseg")] | strip.getMainSegmentId()); // must be before realtimeLock() if "live"
|
||||||
|
|
||||||
realtimeOverride = root[F("lor")] | realtimeOverride;
|
realtimeOverride = root[F("lor")] | realtimeOverride;
|
||||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||||
|
if (realtimeMode && useMainSegmentOnly) {
|
||||||
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride, strip.getMainSegmentId());
|
||||||
|
}
|
||||||
|
|
||||||
bool liveEnabled = false;
|
|
||||||
if (root.containsKey("live")) {
|
if (root.containsKey("live")) {
|
||||||
bool lv = root["live"];
|
if (root["live"].as<bool>()) {
|
||||||
if (lv) {
|
|
||||||
transitionDelayTemp = 0;
|
transitionDelayTemp = 0;
|
||||||
jsonTransitionOnce = true;
|
jsonTransitionOnce = true;
|
||||||
liveEnabled = true; // triggers realtimeLock() below
|
|
||||||
realtimeLock(65000);
|
realtimeLock(65000);
|
||||||
|
} else {
|
||||||
|
exitRealtime();
|
||||||
}
|
}
|
||||||
else realtimeTimeout = 0; //cancel realtime mode immediately
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strip.setMainSegmentId(root[F("mainseg")] | strip.getMainSegmentId());
|
|
||||||
|
|
||||||
int it = 0;
|
int it = 0;
|
||||||
JsonVariant segVar = root["seg"];
|
JsonVariant segVar = root["seg"];
|
||||||
if (segVar.is<JsonObject>())
|
if (segVar.is<JsonObject>())
|
||||||
@ -381,7 +392,6 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stateUpdated(callMode);
|
stateUpdated(callMode);
|
||||||
if (liveEnabled) realtimeTimeout = UINT32_MAX; // force indefinite timeout if this request contained {"live":true}
|
|
||||||
|
|
||||||
return stateResponse;
|
return stateResponse;
|
||||||
}
|
}
|
||||||
@ -536,6 +546,8 @@ void serializeInfo(JsonObject root)
|
|||||||
root[F("name")] = serverDescription;
|
root[F("name")] = serverDescription;
|
||||||
root[F("udpport")] = udpPort;
|
root[F("udpport")] = udpPort;
|
||||||
root["live"] = (bool)realtimeMode;
|
root["live"] = (bool)realtimeMode;
|
||||||
|
root[F("liveseg")] = useMainSegmentOnly ? strip.getMainSegmentId() : -1; // if using main segment only for live
|
||||||
|
//root[F("mso")] = useMainSegmentOnly; // using main segment only for live
|
||||||
|
|
||||||
switch (realtimeMode) {
|
switch (realtimeMode) {
|
||||||
case REALTIME_MODE_INACTIVE: root["lm"] = ""; break;
|
case REALTIME_MODE_INACTIVE: root["lm"] = ""; break;
|
||||||
|
@ -100,7 +100,6 @@ void stateUpdated(byte callMode) {
|
|||||||
setValuesFromFirstSelectedSeg();
|
setValuesFromFirstSelectedSeg();
|
||||||
|
|
||||||
if (bri != briOld || stateChanged) {
|
if (bri != briOld || stateChanged) {
|
||||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
|
||||||
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
|
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
|
||||||
|
|
||||||
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
|
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
|
||||||
|
@ -237,6 +237,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
nodeBroadcastEnabled = request->hasArg(F("NB"));
|
nodeBroadcastEnabled = request->hasArg(F("NB"));
|
||||||
|
|
||||||
receiveDirect = request->hasArg(F("RD"));
|
receiveDirect = request->hasArg(F("RD"));
|
||||||
|
useMainSegmentOnly = request->hasArg(F("MO"));
|
||||||
e131SkipOutOfSequence = request->hasArg(F("ES"));
|
e131SkipOutOfSequence = request->hasArg(F("ES"));
|
||||||
e131Multicast = request->hasArg(F("EM"));
|
e131Multicast = request->hasArg(F("EM"));
|
||||||
t = request->arg(F("EP")).toInt();
|
t = request->arg(F("EP")).toInt();
|
||||||
@ -933,6 +934,9 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
realtimeOverride = getNumVal(&req, pos);
|
realtimeOverride = getNumVal(&req, pos);
|
||||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||||
|
if (realtimeMode && useMainSegmentOnly) {
|
||||||
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride, strip.getMainSegmentId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = req.indexOf(F("RB"));
|
pos = req.indexOf(F("RB"));
|
||||||
|
@ -141,27 +141,52 @@ void notify(byte callMode, bool followUp)
|
|||||||
void realtimeLock(uint32_t timeoutMs, byte md)
|
void realtimeLock(uint32_t timeoutMs, byte md)
|
||||||
{
|
{
|
||||||
if (!realtimeMode && !realtimeOverride) {
|
if (!realtimeMode && !realtimeOverride) {
|
||||||
uint16_t totalLen = strip.getLengthTotal();
|
uint16_t stop, start;
|
||||||
for (uint16_t i = 0; i < totalLen; i++)
|
if (useMainSegmentOnly) {
|
||||||
{
|
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
||||||
strip.setPixelColor(i,0,0,0,0);
|
start = mainseg.start;
|
||||||
|
stop = mainseg.stop;
|
||||||
|
mainseg.setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
||||||
|
} else {
|
||||||
|
start = 0;
|
||||||
|
stop = strip.getLengthTotal();
|
||||||
}
|
}
|
||||||
|
// clear strip/segment
|
||||||
|
for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0);
|
||||||
|
// if WLED was off and using main segment only, freeze non-main segments so they stay off
|
||||||
|
if (useMainSegmentOnly && bri == 0) {
|
||||||
|
for (uint8_t s=0; s < strip.getMaxSegments(); s++) {
|
||||||
|
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if strip is off (bri==0) and not already in RTM
|
||||||
|
if (briT == 0 && !realtimeMode && !realtimeOverride) {
|
||||||
|
strip.setBrightness(scaledBri(briLast), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realtimeTimeout != UINT32_MAX) {
|
if (realtimeTimeout != UINT32_MAX) {
|
||||||
realtimeTimeout = millis() + timeoutMs;
|
realtimeTimeout = (timeoutMs == 255001 || timeoutMs == 65000) ? UINT32_MAX : millis() + timeoutMs;
|
||||||
if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX;
|
|
||||||
}
|
|
||||||
// if strip is off (bri==0) and not already in RTM
|
|
||||||
if (briT == 0 && !realtimeMode) {
|
|
||||||
strip.setBrightness(scaledBri(briLast), true);
|
|
||||||
}
|
}
|
||||||
realtimeMode = md;
|
realtimeMode = md;
|
||||||
|
|
||||||
if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(scaledBri(255), true);
|
if (realtimeOverride) return;
|
||||||
|
if (arlsForceMaxBri) strip.setBrightness(scaledBri(255), true);
|
||||||
if (briT > 0 && md == REALTIME_MODE_GENERIC) strip.show();
|
if (briT > 0 && md == REALTIME_MODE_GENERIC) strip.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exitRealtime() {
|
||||||
|
if (!realtimeMode) return;
|
||||||
|
if (realtimeOverride == REALTIME_OVERRIDE_ONCE) realtimeOverride = REALTIME_OVERRIDE_NONE;
|
||||||
|
strip.setBrightness(scaledBri(bri));
|
||||||
|
realtimeTimeout = 0; // cancel realtime mode immediately
|
||||||
|
realtimeMode = REALTIME_MODE_INACTIVE; // inform UI immediately
|
||||||
|
realtimeIP[0] = 0;
|
||||||
|
if (useMainSegmentOnly) { // unfreeze live segment again
|
||||||
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, false, strip.getMainSegmentId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define TMP2NET_OUT_PORT 65442
|
#define TMP2NET_OUT_PORT 65442
|
||||||
|
|
||||||
@ -189,13 +214,7 @@ void handleNotifications()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//unlock strip when realtime UDP times out
|
//unlock strip when realtime UDP times out
|
||||||
if (realtimeMode && millis() > realtimeTimeout)
|
if (realtimeMode && millis() > realtimeTimeout) exitRealtime();
|
||||||
{
|
|
||||||
if (realtimeOverride == REALTIME_OVERRIDE_ONCE) realtimeOverride = REALTIME_OVERRIDE_NONE;
|
|
||||||
strip.setBrightness(scaledBri(bri));
|
|
||||||
realtimeMode = REALTIME_MODE_INACTIVE;
|
|
||||||
realtimeIP[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//receive UDP notifications
|
//receive UDP notifications
|
||||||
if (!udpConnected) return;
|
if (!udpConnected) return;
|
||||||
|
@ -148,7 +148,9 @@ void WLED::loop()
|
|||||||
yield();
|
yield();
|
||||||
handleIO();
|
handleIO();
|
||||||
handleIR();
|
handleIR();
|
||||||
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
handleAlexa();
|
handleAlexa();
|
||||||
|
#endif
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
@ -159,21 +161,24 @@ void WLED::loop()
|
|||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!realtimeMode || realtimeOverride) // block stuff if WARLS/Adalight is enabled
|
if (!realtimeMode || realtimeOverride || (realtimeMode && useMainSegmentOnly)) // block stuff if WARLS/Adalight is enabled
|
||||||
{
|
{
|
||||||
if (apActive)
|
if (apActive) dnsServer.processNextRequest();
|
||||||
dnsServer.processNextRequest();
|
|
||||||
#ifndef WLED_DISABLE_OTA
|
#ifndef WLED_DISABLE_OTA
|
||||||
if (WLED_CONNECTED && aOtaEnabled)
|
if (WLED_CONNECTED && aOtaEnabled) ArduinoOTA.handle();
|
||||||
ArduinoOTA.handle();
|
|
||||||
#endif
|
#endif
|
||||||
handleNightlight();
|
handleNightlight();
|
||||||
handlePlaylist();
|
handlePlaylist();
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_HUESYNC
|
||||||
handleHue();
|
handleHue();
|
||||||
|
yield();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_BLYNK
|
#ifndef WLED_DISABLE_BLYNK
|
||||||
handleBlynk();
|
handleBlynk();
|
||||||
|
yield();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
@ -537,6 +537,7 @@ WLED_GLOBAL IPAddress realtimeIP _INIT_N(((0, 0, 0, 0)));
|
|||||||
WLED_GLOBAL unsigned long realtimeTimeout _INIT(0);
|
WLED_GLOBAL unsigned long realtimeTimeout _INIT(0);
|
||||||
WLED_GLOBAL uint8_t tpmPacketCount _INIT(0);
|
WLED_GLOBAL uint8_t tpmPacketCount _INIT(0);
|
||||||
WLED_GLOBAL uint16_t tpmPayloadFrameSize _INIT(0);
|
WLED_GLOBAL uint16_t tpmPayloadFrameSize _INIT(0);
|
||||||
|
WLED_GLOBAL bool useMainSegmentOnly _INIT(false);
|
||||||
|
|
||||||
// mqtt
|
// mqtt
|
||||||
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0);
|
WLED_GLOBAL unsigned long lastMqttReconnectAttempt _INIT(0);
|
||||||
|
@ -493,6 +493,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('c',SET_F("NB"),nodeBroadcastEnabled);
|
sappend('c',SET_F("NB"),nodeBroadcastEnabled);
|
||||||
|
|
||||||
sappend('c',SET_F("RD"),receiveDirect);
|
sappend('c',SET_F("RD"),receiveDirect);
|
||||||
|
sappend('c',SET_F("MO"),useMainSegmentOnly);
|
||||||
sappend('v',SET_F("EP"),e131Port);
|
sappend('v',SET_F("EP"),e131Port);
|
||||||
sappend('c',SET_F("ES"),e131SkipOutOfSequence);
|
sappend('c',SET_F("ES"),e131SkipOutOfSequence);
|
||||||
sappend('c',SET_F("EM"),e131Multicast);
|
sappend('c',SET_F("EM"),e131Multicast);
|
||||||
|
Loading…
Reference in New Issue
Block a user