mirror of
https://github.com/esphome/esphome.git
synced 2026-03-02 18:58:20 -07:00
[e131] Drain all queued packets per loop iteration
Previously the BSD socket path read only one UDP packet per loop() call. With multi-universe setups (e.g. 380 RGBW LEDs across 3 universes), this caused the light to re-render the entire strip for each universe packet separately, resulting in visible tearing and ~3x unnecessary RMT writes. Now both socket backends drain all available packets before returning, so multi-universe frames are applied atomically and the light only writes once per frame. The duplicated packet processing logic is consolidated into a shared loop with a platform-specific read_() helper. Tested on ESP32-IDF with 380 SK6812 RGBW LEDs (3 universes): - Light total CPU dropped from 5820ms to 1108ms per 60s (~5x) - Combined e131+light dropped from 6944ms to 4811ms per 60s - Visible tearing eliminated
This commit is contained in:
@@ -70,27 +70,9 @@ void E131Component::loop() {
|
||||
E131Packet packet;
|
||||
int universe = 0;
|
||||
uint8_t buf[1460];
|
||||
ssize_t len;
|
||||
|
||||
#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
|
||||
ssize_t len = this->socket_->read(buf, sizeof(buf));
|
||||
if (len == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->packet_(buf, (size_t) len, universe, packet)) {
|
||||
ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->process_(universe, packet)) {
|
||||
ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count);
|
||||
}
|
||||
#elif defined(USE_SOCKET_IMPL_LWIP_TCP)
|
||||
while (auto packet_size = this->udp_.parsePacket()) {
|
||||
auto len = this->udp_.read(buf, sizeof(buf));
|
||||
if (len <= 0)
|
||||
continue;
|
||||
|
||||
while ((len = this->read_(buf, sizeof(buf))) > 0) {
|
||||
if (!this->packet_(buf, (size_t) len, universe, packet)) {
|
||||
ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len);
|
||||
continue;
|
||||
@@ -100,6 +82,15 @@ void E131Component::loop() {
|
||||
ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t E131Component::read_(uint8_t *buf, size_t len) {
|
||||
#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
|
||||
return this->socket_->read(buf, len);
|
||||
#elif defined(USE_SOCKET_IMPL_LWIP_TCP)
|
||||
if (!this->udp_.parsePacket())
|
||||
return -1;
|
||||
return this->udp_.read(buf, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ class E131Component : public esphome::Component {
|
||||
void set_method(E131ListenMethod listen_method) { this->listen_method_ = listen_method; }
|
||||
|
||||
protected:
|
||||
ssize_t read_(uint8_t *buf, size_t len);
|
||||
bool packet_(const uint8_t *data, size_t len, int &universe, E131Packet &packet);
|
||||
bool process_(int universe, const E131Packet &packet);
|
||||
bool join_igmp_groups_();
|
||||
|
||||
Reference in New Issue
Block a user