ESPHome  2024.4.1
e131.cpp
Go to the documentation of this file.
1 #include "e131.h"
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace e131 {
7 
8 static const char *const TAG = "e131";
9 static const int PORT = 5568;
10 
12 
14  if (this->socket_) {
15  this->socket_->close();
16  }
17 }
18 
20  this->socket_ = socket::socket_ip(SOCK_DGRAM, IPPROTO_IP);
21 
22  int enable = 1;
23  int err = this->socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
24  if (err != 0) {
25  ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
26  // we can still continue
27  }
28  err = this->socket_->setblocking(false);
29  if (err != 0) {
30  ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
31  this->mark_failed();
32  return;
33  }
34 
35  struct sockaddr_storage server;
36 
37  socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), PORT);
38  if (sl == 0) {
39  ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
40  this->mark_failed();
41  return;
42  }
43 
44  err = this->socket_->bind((struct sockaddr *) &server, sizeof(server));
45  if (err != 0) {
46  ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
47  this->mark_failed();
48  return;
49  }
50 
52 }
53 
55  std::vector<uint8_t> payload;
56  E131Packet packet;
57  int universe = 0;
58  uint8_t buf[1460];
59 
60  ssize_t len = this->socket_->read(buf, sizeof(buf));
61  if (len == -1) {
62  return;
63  }
64  payload.resize(len);
65  memmove(&payload[0], buf, len);
66 
67  if (!this->packet_(payload, universe, packet)) {
68  ESP_LOGV(TAG, "Invalid packet received of size %zu.", payload.size());
69  return;
70  }
71 
72  if (!this->process_(universe, packet)) {
73  ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count);
74  }
75 }
76 
78  if (light_effects_.count(light_effect)) {
79  return;
80  }
81 
82  ESP_LOGD(TAG, "Registering '%s' for universes %d-%d.", light_effect->get_name().c_str(),
83  light_effect->get_first_universe(), light_effect->get_last_universe());
84 
85  light_effects_.insert(light_effect);
86 
87  for (auto universe = light_effect->get_first_universe(); universe <= light_effect->get_last_universe(); ++universe) {
88  join_(universe);
89  }
90 }
91 
93  if (!light_effects_.count(light_effect)) {
94  return;
95  }
96 
97  ESP_LOGD(TAG, "Unregistering '%s' for universes %d-%d.", light_effect->get_name().c_str(),
98  light_effect->get_first_universe(), light_effect->get_last_universe());
99 
100  light_effects_.erase(light_effect);
101 
102  for (auto universe = light_effect->get_first_universe(); universe <= light_effect->get_last_universe(); ++universe) {
103  leave_(universe);
104  }
105 }
106 
107 bool E131Component::process_(int universe, const E131Packet &packet) {
108  bool handled = false;
109 
110  ESP_LOGV(TAG, "Received E1.31 packet for %d universe, with %d bytes", universe, packet.count);
111 
112  for (auto *light_effect : light_effects_) {
113  handled = light_effect->process_(universe, packet) || handled;
114  }
115 
116  return handled;
117 }
118 
119 } // namespace e131
120 } // namespace esphome
std::unique_ptr< Socket > socket_ip(int type, int protocol)
Create a socket in the newest available IP domain (IPv6 or IPv4) of the given type and protocol...
Definition: socket.cpp:12
bool packet_(const std::vector< uint8_t > &data, int &universe, E131Packet &packet)
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().
Definition: socket.cpp:53
bool process_(int universe, const E131Packet &packet)
Definition: e131.cpp:107
std::unique_ptr< socket::Socket > socket_
Definition: e131.h:48
uint32_t socklen_t
Definition: headers.h:97
uint16_t universe
void join_(int universe)
Definition: e131_packet.cpp:83
void loop() override
Definition: e131.cpp:54
void setup() override
Definition: e131.cpp:19
const std::string & get_name()
Definition: light_effect.h:27
void leave_(int universe)
Definition: e131_packet.cpp:96
std::set< E131AddressableLightEffect * > light_effects_
Definition: e131.h:49
void add_effect(E131AddressableLightEffect *light_effect)
Definition: e131.cpp:77
void remove_effect(E131AddressableLightEffect *light_effect)
Definition: e131.cpp:92
std::string size_t len
Definition: helpers.h:292
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7