Circumvent problems with UDP fragmentation
The ESP’s IP stack seems not to support UDP packet fragmentation and drops such packets silently which is problematic for setups with many LEDs and huge updates. With this patch, the UDP server processes up to 3 full UDP packets per frame, allowing much larger updates. Additionally, the new END_OF_UPDATE flag allows to signal when a update sequence is finished. If this flag is encountered, no further UDP packets are processed in the current frame.
This commit is contained in:
parent
da37f32096
commit
dc8bc98193
|
@ -12,6 +12,7 @@ public:
|
|||
FADE_COLOUR = 1,
|
||||
ADD_COLOUR = 2,
|
||||
SET_FADESTEP = 3,
|
||||
END_OF_UPDATE = 254,
|
||||
ACK_REQUEST = 255
|
||||
};
|
||||
|
||||
|
@ -24,6 +25,8 @@ public:
|
|||
bool loop(void);
|
||||
|
||||
private:
|
||||
const static uint32_t MAX_PACKETS_PER_UPDATE = 3;
|
||||
|
||||
WiFiUDP m_udpServer;
|
||||
Fader *m_fader;
|
||||
};
|
||||
|
|
126
src/UDPProto.cpp
126
src/UDPProto.cpp
|
@ -39,72 +39,82 @@ bool UDPProto::loop(void)
|
|||
byte cmd[WS2801_CMD_LEN];
|
||||
byte action, strip, module, r, g, b, w;
|
||||
int len;
|
||||
int packets_processed = 0;
|
||||
bool done_something = false;
|
||||
|
||||
int32_t seq = -1;
|
||||
|
||||
int packetSize = m_udpServer.parsePacket();
|
||||
if(packetSize)
|
||||
{
|
||||
// read the packet into packetBufffer
|
||||
while((len = m_udpServer.read(cmd, WS2801_CMD_LEN)) == WS2801_CMD_LEN) {
|
||||
action = cmd[0];
|
||||
strip = cmd[1];
|
||||
module = cmd[2];
|
||||
r = cmd[3];
|
||||
g = cmd[4];
|
||||
b = cmd[5];
|
||||
w = cmd[6];
|
||||
while(packets_processed < MAX_PACKETS_PER_UPDATE) {
|
||||
int packetSize = m_udpServer.parsePacket();
|
||||
if(packetSize)
|
||||
{
|
||||
// read the packet into packetBufffer
|
||||
while((len = m_udpServer.read(cmd, WS2801_CMD_LEN)) == WS2801_CMD_LEN) {
|
||||
action = cmd[0];
|
||||
strip = cmd[1];
|
||||
module = cmd[2];
|
||||
r = cmd[3];
|
||||
g = cmd[4];
|
||||
b = cmd[5];
|
||||
w = cmd[6];
|
||||
|
||||
Fader::Color color{r,g,b,w};
|
||||
Fader::Color color{r,g,b,w};
|
||||
|
||||
if(strip >= m_fader->strips()) {
|
||||
// strip index out of range
|
||||
continue;
|
||||
if(strip >= m_fader->strips()) {
|
||||
// strip index out of range
|
||||
continue;
|
||||
}
|
||||
|
||||
if(module >= m_fader->modules_per_strip()) {
|
||||
// module index out of range
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(action) {
|
||||
case SET_COLOUR:
|
||||
m_fader->set_color(strip, module, color);
|
||||
break;
|
||||
|
||||
case FADE_COLOUR:
|
||||
m_fader->fade_color(strip, module, color);
|
||||
break;
|
||||
|
||||
case ADD_COLOUR:
|
||||
m_fader->add_color(strip, module, color);
|
||||
break;
|
||||
|
||||
case SET_FADESTEP:
|
||||
m_fader->set_fadestep(r); // red channel contains the fadestep in this case
|
||||
break;
|
||||
|
||||
case END_OF_UPDATE:
|
||||
packets_processed = MAX_PACKETS_PER_UPDATE;
|
||||
break;
|
||||
|
||||
case ACK_REQUEST:
|
||||
seq = ((int32_t)r) << 8 | (int32_t)g;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// send a reply, to the IP address and port that sent us the packet we received
|
||||
if(seq >= 0) {
|
||||
uint8_t data[2];
|
||||
data[0] = (seq >> 8) & 0xFF;
|
||||
data[1] = seq & 0xFF;
|
||||
m_udpServer.beginPacket(m_udpServer.remoteIP(), m_udpServer.remotePort());
|
||||
m_udpServer.write(data, 2);
|
||||
m_udpServer.endPacket();
|
||||
}
|
||||
|
||||
if(module >= m_fader->modules_per_strip()) {
|
||||
// module index out of range
|
||||
continue;
|
||||
}
|
||||
m_udpServer.flush();
|
||||
|
||||
switch(action) {
|
||||
case SET_COLOUR:
|
||||
m_fader->set_color(strip, module, color);
|
||||
break;
|
||||
|
||||
case FADE_COLOUR:
|
||||
m_fader->fade_color(strip, module, color);
|
||||
break;
|
||||
|
||||
case ADD_COLOUR:
|
||||
m_fader->add_color(strip, module, color);
|
||||
break;
|
||||
|
||||
case SET_FADESTEP:
|
||||
m_fader->set_fadestep(r); // red channel contains the fadestep in this case
|
||||
break;
|
||||
|
||||
case ACK_REQUEST:
|
||||
seq = ((int32_t)r) << 8 | (int32_t)g;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
done_something = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
// send a reply, to the IP address and port that sent us the packet we received
|
||||
if(seq >= 0) {
|
||||
uint8_t data[2];
|
||||
data[0] = (seq >> 8) & 0xFF;
|
||||
data[1] = seq & 0xFF;
|
||||
m_udpServer.beginPacket(m_udpServer.remoteIP(), m_udpServer.remotePort());
|
||||
m_udpServer.write(data, 2);
|
||||
m_udpServer.endPacket();
|
||||
}
|
||||
|
||||
m_udpServer.flush();
|
||||
|
||||
return true; // processed a packet
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return done_something;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue