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