1
0
mirror of https://github.com/esphome/esphome.git synced 2025-04-06 10:50:28 +01:00
justdaniel-gh 41f29c46d0
Fix e131 and voice_assistant sockets (#5502)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-10-10 23:42:38 +00:00

121 lines
3.2 KiB
C++

#include "e131.h"
#include "e131_addressable_light_effect.h"
#include "esphome/core/log.h"
namespace esphome {
namespace e131 {
static const char *const TAG = "e131";
static const int PORT = 5568;
E131Component::E131Component() {}
E131Component::~E131Component() {
if (this->socket_) {
this->socket_->close();
}
}
void E131Component::setup() {
this->socket_ = socket::socket_ip(SOCK_DGRAM, IPPROTO_IP);
int enable = 1;
int err = this->socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
// we can still continue
}
err = this->socket_->setblocking(false);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
this->mark_failed();
return;
}
struct sockaddr_storage server;
socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), PORT);
if (sl == 0) {
ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
this->mark_failed();
return;
}
err = this->socket_->bind((struct sockaddr *) &server, sizeof(server));
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
this->mark_failed();
return;
}
join_igmp_groups_();
}
void E131Component::loop() {
std::vector<uint8_t> payload;
E131Packet packet;
int universe = 0;
uint8_t buf[1460];
ssize_t len = this->socket_->read(buf, sizeof(buf));
if (len == -1) {
return;
}
payload.resize(len);
memmove(&payload[0], buf, len);
if (!this->packet_(payload, universe, packet)) {
ESP_LOGV(TAG, "Invalid packet received of size %zu.", payload.size());
return;
}
if (!this->process_(universe, packet)) {
ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count);
}
}
void E131Component::add_effect(E131AddressableLightEffect *light_effect) {
if (light_effects_.count(light_effect)) {
return;
}
ESP_LOGD(TAG, "Registering '%s' for universes %d-%d.", light_effect->get_name().c_str(),
light_effect->get_first_universe(), light_effect->get_last_universe());
light_effects_.insert(light_effect);
for (auto universe = light_effect->get_first_universe(); universe <= light_effect->get_last_universe(); ++universe) {
join_(universe);
}
}
void E131Component::remove_effect(E131AddressableLightEffect *light_effect) {
if (!light_effects_.count(light_effect)) {
return;
}
ESP_LOGD(TAG, "Unregistering '%s' for universes %d-%d.", light_effect->get_name().c_str(),
light_effect->get_first_universe(), light_effect->get_last_universe());
light_effects_.erase(light_effect);
for (auto universe = light_effect->get_first_universe(); universe <= light_effect->get_last_universe(); ++universe) {
leave_(universe);
}
}
bool E131Component::process_(int universe, const E131Packet &packet) {
bool handled = false;
ESP_LOGV(TAG, "Received E1.31 packet for %d universe, with %d bytes", universe, packet.count);
for (auto *light_effect : light_effects_) {
handled = light_effect->process_(universe, packet) || handled;
}
return handled;
}
} // namespace e131
} // namespace esphome