sACN/E1.31 Port Priority (#3052)

* Added E1.31 port priority handling #768

* Ignore E1.31 data when priority doesn't match #768

* Enable E1.31 priority handling for WLED_ENABLE_DMX

* Only handle e131Priority for P_E131 protocol

* Corrected comments

* Highest priority package first handling

* Removed obsolete code & comments

* Improved comments

* Reduce priority timeout to be uint8_t

* Optimized code & comments

* E1.31: Ignore non-zero start code and preview data
These are not level data, they have other purposes

* Style change cca41508 preview & ignore non-zero start code

---------

Co-authored-by: RichardTea <31507749+RichardTea@users.noreply.github.com>
This commit is contained in:
mx 2023-02-21 17:13:15 +01:00 committed by GitHub
parent 7f74a4f4b5
commit 0d3debf9b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 1 deletions

View File

@ -408,6 +408,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (!DMXAddress || DMXAddress > 510) DMXAddress = 1; if (!DMXAddress || DMXAddress > 510) DMXAddress = 1;
CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]); CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]);
if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0; if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0;
CJSON(e131Priority, if_live_dmx[F("e131prio")]);
if (e131Priority > 200) e131Priority = 200;
CJSON(DMXMode, if_live_dmx["mode"]); CJSON(DMXMode, if_live_dmx["mode"]);
tdd = if_live[F("timeout")] | -1; tdd = if_live[F("timeout")] | -1;
@ -852,6 +854,7 @@ void serializeConfig() {
JsonObject if_live_dmx = if_live.createNestedObject("dmx"); JsonObject if_live_dmx = if_live.createNestedObject("dmx");
if_live_dmx[F("uni")] = e131Universe; if_live_dmx[F("uni")] = e131Universe;
if_live_dmx[F("seqskip")] = e131SkipOutOfSequence; if_live_dmx[F("seqskip")] = e131SkipOutOfSequence;
if_live_dmx[F("e131prio")] = e131Priority;
if_live_dmx[F("addr")] = DMXAddress; if_live_dmx[F("addr")] = DMXAddress;
if_live_dmx[F("dss")] = DMXSegmentSpacing; if_live_dmx[F("dss")] = DMXSegmentSpacing;
if_live_dmx["mode"] = DMXMode; if_live_dmx["mode"] = DMXMode;

View File

@ -149,6 +149,7 @@ Start universe: <input name="EU" type="number" min="0" max="63999" required><br>
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br> Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
DMX start address: <input name="DA" type="number" min="1" max="510" required><br> DMX start address: <input name="DA" type="number" min="1" max="510" required><br>
DMX segment spacing: <input name="XX" type="number" min="0" max="150" required><br> DMX segment spacing: <input name="XX" type="number" min="0" max="150" required><br>
E1.31 port priority: <input name="PY" type="number" min="0" max="200" required><br>
DMX mode: DMX mode:
<select name=DM> <select name=DM>
<option value=0>Disabled</option> <option value=0>Disabled</option>

View File

@ -70,10 +70,20 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
seq = p->art_sequence_number; seq = p->art_sequence_number;
mde = REALTIME_MODE_ARTNET; mde = REALTIME_MODE_ARTNET;
} else if (protocol == P_E131) { } else if (protocol == P_E131) {
// Ignore PREVIEW data (E1.31: 6.2.6)
if ((p->options & 0x80) != 0) return;
dmxChannels = htons(p->property_value_count) - 1;
// DMX level data is zero start code. Ignore everything else. (E1.11: 8.5)
if (dmxChannels == 0 || p->property_values[0] != 0) return;
uni = htons(p->universe); uni = htons(p->universe);
dmxChannels = htons(p->property_value_count) -1;
e131_data = p->property_values; e131_data = p->property_values;
seq = p->sequence_number; seq = p->sequence_number;
if (e131Priority != 0) {
if (p->priority < e131Priority ) return;
// track highest priority & skip all lower priorities
if (p->priority >= highPriority.get()) highPriority.set(p->priority);
if (p->priority < highPriority.get()) return;
}
} else { //DDP } else { //DDP
realtimeIP = clientIP; realtimeIP = clientIP;
handleDDPPacket(p); handleDDPPacket(p);

View File

@ -298,6 +298,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (t >= 0 && t <= 510) DMXAddress = t; if (t >= 0 && t <= 510) DMXAddress = t;
t = request->arg(F("XX")).toInt(); t = request->arg(F("XX")).toInt();
if (t >= 0 && t <= 150) DMXSegmentSpacing = t; if (t >= 0 && t <= 150) DMXSegmentSpacing = t;
t = request->arg(F("PY")).toInt();
if (t >= 0 && t <= 200) e131Priority = t;
t = request->arg(F("DM")).toInt(); t = request->arg(F("DM")).toInt();
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_PRESET) DMXMode = t; if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_PRESET) DMXMode = t;
t = request->arg(F("ET")).toInt(); t = request->arg(F("ET")).toInt();

View File

@ -228,4 +228,30 @@ class ESPAsyncE131 {
bool begin(bool multicast, uint16_t port = E131_DEFAULT_PORT, uint16_t universe = 1, uint8_t n = 1); bool begin(bool multicast, uint16_t port = E131_DEFAULT_PORT, uint16_t universe = 1, uint8_t n = 1);
}; };
// Class to track e131 package priority
class E131Priority {
private:
uint8_t priority;
time_t setupTime;
uint8_t seconds;
public:
E131Priority(uint8_t timeout=3) {
seconds = timeout;
set(0);
};
// Set priority (+ remember time)
void set(uint8_t prio) {
setupTime = time(0);
priority = prio;
}
// Get priority (+ reset & return 0 if older timeout)
uint8_t get() {
if (time(0) > setupTime + seconds) priority = 0;
return priority;
}
};
#endif // ESPASYNCE131_H_ #endif // ESPASYNCE131_H_

View File

@ -390,6 +390,8 @@ WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this
#endif #endif
WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes) WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)
WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454 WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454
WLED_GLOBAL byte e131Priority _INIT(0); // E1.31 port priority (if != 0 priority handling is active)
WLED_GLOBAL E131Priority highPriority _INIT(3); // E1.31 highest priority tracking, init = timeout in seconds
WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.) WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.)
WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol] WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
WLED_GLOBAL uint16_t DMXSegmentSpacing _INIT(0); // Number of void/unused channels between each segments DMX channels WLED_GLOBAL uint16_t DMXSegmentSpacing _INIT(0); // Number of void/unused channels between each segments DMX channels

View File

@ -510,6 +510,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('v',SET_F("EU"),e131Universe); sappend('v',SET_F("EU"),e131Universe);
sappend('v',SET_F("DA"),DMXAddress); sappend('v',SET_F("DA"),DMXAddress);
sappend('v',SET_F("XX"),DMXSegmentSpacing); sappend('v',SET_F("XX"),DMXSegmentSpacing);
sappend('v',SET_F("PY"),e131Priority);
sappend('v',SET_F("DM"),DMXMode); sappend('v',SET_F("DM"),DMXMode);
sappend('v',SET_F("ET"),realtimeTimeoutMs); sappend('v',SET_F("ET"),realtimeTimeoutMs);
sappend('c',SET_F("FB"),arlsForceMaxBri); sappend('c',SET_F("FB"),arlsForceMaxBri);