ESPHome  2023.8.3
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  server.ss_family = AF_INET;
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
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:108
std::unique_ptr< socket::Socket > socket_
Definition: e131.h:47
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:55
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:48
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:289
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:112