ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
e131.cpp
Go to the documentation of this file.
1#include "e131.h"
2#ifdef USE_NETWORK
5#include "esphome/core/log.h"
6
7#include <algorithm>
8
9namespace esphome::e131 {
10
11ESPHOME_LOG_TAG(TAG, "e131");
12static const int PORT = 5568;
13
15
17 if (this->socket_) {
18 this->socket_->close();
19 }
20}
21
23 this->socket_ = socket::socket_ip_udp(IPPROTO_IP);
24 if (!this->socket_) {
25 ESP_LOGW(TAG, "Could not create socket: errno %d", errno);
26 this->mark_failed();
27 return;
28 }
29
30 int enable = 1;
31 int err = this->socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
32 if (err != 0) {
33 ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
34 // we can still continue
35 }
36 err = this->socket_->setblocking(false);
37 if (err != 0) {
38 ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
39 this->mark_failed();
40 return;
41 }
42
43 struct sockaddr_storage server;
44
45 socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), PORT);
46 if (sl == 0) {
47 ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
48 this->mark_failed();
49 return;
50 }
51
52 err = this->socket_->bind((struct sockaddr *) &server, sizeof(server));
53 if (err != 0) {
54 ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
55 this->mark_failed();
56 return;
57 }
58
60}
61
64 this->join_igmp_groups_();
65 E131Packet packet;
66 int universe = 0;
67 uint8_t buf[1460];
69
70 // Drain all queued packets so multi-universe frames are applied
71 // atomically before the light writes. Without this, each universe
72 // packet would trigger a separate full-strip write causing tearing.
73 while ((len = this->socket_->read(buf, sizeof(buf))) > 0) {
74 if (!this->packet_(buf, (size_t) len, universe, packet)) {
75 ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len);
76 continue;
77 }
78
79 if (!this->process_(universe, packet)) {
80 ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count);
81 }
82 }
83}
84
86 if (std::find(light_effects_.begin(), light_effects_.end(), light_effect) != light_effects_.end()) {
87 return;
88 }
89
90 auto effect_name = light_effect->get_name();
91 ESP_LOGD(TAG, "Registering '%.*s' for universes %d-%d.", (int) effect_name.size(), effect_name.c_str(),
92 light_effect->get_first_universe(), light_effect->get_last_universe());
93
94 light_effects_.push_back(light_effect);
95
96 for (auto universe = light_effect->get_first_universe(); universe <= light_effect->get_last_universe(); ++universe) {
98 }
99}
100
102 auto it = std::find(light_effects_.begin(), light_effects_.end(), light_effect);
103 if (it == light_effects_.end()) {
104 return;
105 }
106
107 auto effect_name = light_effect->get_name();
108 ESP_LOGD(TAG, "Unregistering '%.*s' for universes %d-%d.", (int) effect_name.size(), effect_name.c_str(),
109 light_effect->get_first_universe(), light_effect->get_last_universe());
110
111 // Swap with last element and pop for O(1) removal (order doesn't matter)
112 *it = light_effects_.back();
113 light_effects_.pop_back();
114
115 for (auto universe = light_effect->get_first_universe(); universe <= light_effect->get_last_universe(); ++universe) {
117 }
118}
119
121 bool handled = false;
122
123 ESP_LOGV(TAG, "Received E1.31 packet for %d universe, with %d bytes", universe, packet.count);
124
125 for (auto *light_effect : light_effects_) {
126 handled = light_effect->process_(universe, packet) || handled;
127 }
128
129 return handled;
130}
131
132} // namespace esphome::e131
133
134#endif
void mark_failed()
Mark this component as failed.
std::vector< E131AddressableLightEffect * > light_effects_
Definition e131.h:55
void loop() override
Definition e131.cpp:62
void add_effect(E131AddressableLightEffect *light_effect)
Definition e131.cpp:85
void remove_effect(E131AddressableLightEffect *light_effect)
Definition e131.cpp:101
bool packet_(const uint8_t *data, size_t len, int &universe, E131Packet &packet)
std::unique_ptr< socket::UDPSocket > socket_
Definition e131.h:54
bool process_(int universe, const E131Packet &packet)
Definition e131.cpp:120
void setup() override
Definition e131.cpp:22
StringRef get_name() const
Returns the name of this effect.
uint16_t universe
uint32_t socklen_t
Definition headers.h:109
__int64 ssize_t
Definition httplib.h:178
ESPHOME_LOG_TAG(TAG, "e131")
ESPHOME_ALWAYS_INLINE bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition util.h:36
std::unique_ptr< UDPSocket > socket_ip_udp(int protocol)
Definition socket.h:154
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port)
Set a sockaddr to the any address and specified port for the IP version used by socket_ip().
const void size_t len
Definition hal.h:68