48 static const char *
const TAG =
"udp";
54 static const uint32_t DELTA = 0x9e3779b9;
55 #define MX ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (k[(p ^ e) & 7] ^ z))) 61 static void xxtea_encrypt(uint32_t *v,
size_t n,
const uint32_t *k) {
62 uint32_t z,
y, sum, e;
64 size_t q = 6 + 52 / n;
70 for (p = 0; p != n - 1; p++) {
79 static void xxtea_decrypt(uint32_t *v,
size_t n,
const uint32_t *k) {
80 uint32_t z,
y, sum, e;
82 size_t q = 6 + 52 / n;
87 for (p = n - 1; p != 0; p--) {
97 inline static size_t round4(
size_t value) {
return (value + 3) & ~3; }
104 static const size_t MAX_PACKET_SIZE = 508;
105 static const uint16_t MAGIC_NUMBER = 0x4553;
106 static const uint16_t MAGIC_PING = 0x5048;
107 static const uint32_t PREF_HASH = 0x45535043;
117 static const size_t MAX_PING_KEYS = 4;
119 static inline void add(std::vector<uint8_t> &vec, uint32_t data) {
120 vec.push_back(data & 0xFF);
121 vec.push_back((data >> 8) & 0xFF);
122 vec.push_back((data >> 16) & 0xFF);
123 vec.push_back((data >> 24) & 0xFF);
126 static inline uint32_t get_uint32(uint8_t *&buf) {
127 uint32_t data = *buf++;
129 data += *buf++ << 16;
130 data += *buf++ << 24;
134 static inline uint16_t get_uint16(uint8_t *&buf) {
135 uint16_t data = *buf++;
140 static inline void add(std::vector<uint8_t> &vec, uint8_t data) { vec.push_back(data); }
141 static inline void add(std::vector<uint8_t> &vec, uint16_t data) {
142 vec.push_back((uint8_t) data);
143 vec.push_back((uint8_t) (data >> 8));
145 static inline void add(std::vector<uint8_t> &vec,
DataKey data) { vec.push_back(data); }
146 static void add(std::vector<uint8_t> &vec,
const char *str) {
147 auto len = strlen(str);
149 for (
size_t i = 0; i !=
len; i++) {
150 vec.push_back(*str++);
156 if (strlen(this->name_) > 255) {
158 this->status_set_error(
"Device name exceeds 255 chars");
161 this->resend_ping_key_ = this->ping_pong_enable_;
164 this->pref_.
load(&this->rolling_code_[1]);
165 this->rolling_code_[1]++;
166 this->pref_.save(&this->rolling_code_[1]);
168 ESP_LOGV(TAG,
"Rolling code incremented, upper part now %u", (
unsigned) this->rolling_code_[1]);
170 for (
auto &
sensor : this->sensors_) {
172 this->updated_ =
true;
177 #ifdef USE_BINARY_SENSOR 178 for (
auto &
sensor : this->binary_sensors_) {
180 this->updated_ =
true;
185 this->should_send_ = this->ping_pong_enable_;
187 this->should_send_ |= !this->sensors_.empty();
189 #ifdef USE_BINARY_SENSOR 190 this->should_send_ |= !this->binary_sensors_.empty();
192 this->should_listen_ = !this->providers_.empty() || this->is_encrypted_();
194 add(this->header_, MAGIC_NUMBER);
195 add(this->header_, this->name_);
197 while (this->header_.size() & 0x3)
198 this->header_.push_back(0);
199 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) 200 for (
const auto &
address : this->addresses_) {
203 this->sockaddrs_.push_back(saddr);
206 if (this->should_send_) {
207 this->broadcast_socket_ =
socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
208 if (this->broadcast_socket_ ==
nullptr) {
210 this->status_set_error(
"Could not create socket");
214 auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(
int));
216 this->status_set_warning(
"Socket unable to set reuseaddr");
219 err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable,
sizeof(
int));
221 this->status_set_warning(
"Socket unable to set broadcast");
226 if (this->should_listen_) {
227 this->listen_socket_ =
socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
228 if (this->listen_socket_ ==
nullptr) {
230 this->status_set_error(
"Could not create socket");
233 auto err = this->listen_socket_->setblocking(
false);
235 ESP_LOGE(TAG,
"Unable to set nonblocking: errno %d", errno);
237 this->status_set_error(
"Unable to set nonblocking");
241 err = this->listen_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(enable));
243 this->status_set_warning(
"Socket unable to set reuseaddr");
250 ESP_LOGE(TAG,
"Socket unable to set sockaddr: errno %d", errno);
252 this->status_set_error(
"Unable to set sockaddr");
256 err = this->listen_socket_->bind((
struct sockaddr *) &server,
sizeof(server));
258 ESP_LOGE(TAG,
"Socket unable to bind: errno %d", errno);
260 this->status_set_error(
"Unable to bind socket");
266 for (
const auto &
address : this->addresses_) {
267 auto ipaddr = IPAddress();
268 ipaddr.fromString(
address.c_str());
269 this->ipaddrs_.push_back(ipaddr);
271 if (this->should_listen_)
272 this->udp_client_.begin(this->port_);
278 if (this->rolling_code_enable_) {
280 add(this->data_, this->rolling_code_[0]);
281 add(this->data_, this->rolling_code_[1]);
282 this->increment_code_();
286 for (
auto pkey : this->ping_keys_) {
288 add(this->data_, pkey.second);
295 uint32_t buffer[MAX_PACKET_SIZE / 4];
296 memset(buffer, 0,
sizeof buffer);
298 auto header_len = round4(this->header_.size()) / 4;
299 auto len = round4(data_.size()) / 4;
300 memcpy(buffer, this->header_.data(), this->header_.size());
301 memcpy(buffer + header_len, this->data_.data(), this->data_.size());
302 if (this->is_encrypted_()) {
303 xxtea_encrypt(buffer + header_len, len, (uint32_t *) this->encryption_key_.data());
305 auto total_len = (header_len +
len) * 4;
306 this->send_packet_(buffer, total_len);
310 auto len = 1 + 1 + 1 + strlen(
id);
311 if (
len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
314 add(this->data_, key);
315 add(this->data_, (uint8_t) data);
316 add(this->data_,
id);
319 FuData udata{.f32 = data};
320 this->add_data_(key,
id, udata.u32);
324 auto len = 4 + 1 + 1 + strlen(
id);
325 if (
len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
328 add(this->data_, key);
329 add(this->data_, data);
330 add(this->data_,
id);
337 for (
auto &
sensor : this->sensors_) {
338 if (all ||
sensor.updated) {
344 #ifdef USE_BINARY_SENSOR 345 for (
auto &
sensor : this->binary_sensors_) {
346 if (all ||
sensor.updated) {
353 this->updated_ =
false;
354 this->resend_data_ =
false;
358 this->updated_ =
true;
359 this->resend_data_ = this->should_send_;
360 auto now =
millis() / 1000;
361 if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) {
362 this->resend_ping_key_ = this->ping_pong_enable_;
363 this->last_key_time_ = now;
368 uint8_t buf[MAX_PACKET_SIZE];
369 if (this->should_listen_) {
371 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) 372 auto len = this->listen_socket_->read(buf,
sizeof(buf));
374 auto len = this->udp_client_.parsePacket();
376 len = this->udp_client_.read(buf,
sizeof(buf));
379 this->process_(buf,
len);
385 if (this->resend_ping_key_)
386 this->send_ping_pong_request_();
387 if (this->updated_) {
388 this->send_data_(this->resend_data_);
393 if (!this->is_encrypted_())
395 if (this->ping_keys_.count(name) == 0 && this->ping_keys_.size() == MAX_PING_KEYS) {
396 ESP_LOGW(TAG,
"Ping key from %s discarded", name);
399 this->ping_keys_[
name] = key;
400 this->resend_data_ =
true;
401 ESP_LOGV(TAG,
"Ping key from %s now %X", name, (
unsigned) key);
406 ESP_LOGW(TAG,
"Bad ping request");
409 auto key = get_uint32(ptr);
410 this->add_key_(name, key);
411 ESP_LOGV(TAG,
"Updated ping key for %s to %08X", name, (
unsigned) key);
414 static bool process_rolling_code(
Provider &provider, uint8_t *&buf,
const uint8_t *
end) {
417 auto code0 = get_uint32(buf);
418 auto code1 = get_uint32(buf);
420 ESP_LOGW(TAG,
"Rolling code for %s %08lX:%08lX is old", provider.
name, (
unsigned long) code1,
421 (
unsigned long) code0);
433 auto ping_key_seen = !this->ping_pong_enable_;
435 return ESP_LOGV(TAG,
"Bad length %zu", len);
439 uint8_t *start_ptr = buf;
440 const uint8_t *end = buf +
len;
442 auto magic = get_uint16(buf);
443 if (magic != MAGIC_NUMBER && magic != MAGIC_PING)
444 return ESP_LOGV(TAG,
"Bad magic %X", magic);
447 if (hlen > len - 3) {
448 return ESP_LOGV(TAG,
"Bad hostname length %u > %zu", hlen, len - 3);
450 memcpy(namebuf, buf, hlen);
451 if (strcmp(this->name_, namebuf) == 0) {
452 return ESP_LOGV(TAG,
"Ignoring our own data");
455 if (magic == MAGIC_PING)
456 return this->process_ping_request_(namebuf, buf, end - buf);
457 if (round4(len) != len) {
458 return ESP_LOGW(TAG,
"Bad length %zu", len);
460 hlen = round4(hlen + 3);
461 buf = start_ptr + hlen;
463 return ESP_LOGV(TAG,
"No data after header");
466 if (this->providers_.count(namebuf) == 0) {
467 return ESP_LOGVV(TAG,
"Unknown hostname %s", namebuf);
469 auto &provider = this->providers_[namebuf];
472 ping_key_seen =
true;
474 ESP_LOGV(TAG,
"Found hostname %s", namebuf);
476 auto &sensors = this->remote_sensors_[namebuf];
478 #ifdef USE_BINARY_SENSOR 479 auto &binary_sensors = this->remote_binary_sensors_[namebuf];
483 xxtea_decrypt((uint32_t *) buf, (end - buf) / 4, (uint32_t *) provider.
encryption_key.data());
487 if (!process_rolling_code(provider, buf, end))
490 return ESP_LOGV(TAG,
"Expected rolling_key or data_key, got %X", byte);
498 return ESP_LOGV(TAG,
"PING_KEY requires 4 more bytes");
500 auto key = get_uint32(buf);
501 if (key == this->ping_key_) {
502 ping_key_seen =
true;
503 ESP_LOGV(TAG,
"Found good ping key %X", (
unsigned) key);
505 ESP_LOGV(TAG,
"Unknown ping key %X", (
unsigned) key);
509 if (!ping_key_seen) {
510 ESP_LOGW(TAG,
"Ping key not seen");
511 this->resend_ping_key_ =
true;
516 return ESP_LOGV(TAG,
"Binary sensor key requires at least 3 more bytes");
521 return ESP_LOGV(TAG,
"Sensor key requires at least 6 more bytes");
523 rdata.u32 = get_uint32(buf);
525 return ESP_LOGW(TAG,
"Unknown key byte %X", byte);
529 if (end - buf < hlen) {
530 return ESP_LOGV(TAG,
"Name length of %u not available", hlen);
532 memset(namebuf, 0,
sizeof namebuf);
533 memcpy(namebuf, buf, hlen);
534 ESP_LOGV(TAG,
"Found sensor key %d, id %s, data %lX", byte, namebuf, (
unsigned long) rdata.u32);
537 if (byte ==
SENSOR_KEY && sensors.count(namebuf) != 0)
538 sensors[namebuf]->publish_state(rdata.f32);
540 #ifdef USE_BINARY_SENSOR 542 binary_sensors[namebuf]->publish_state(rdata.u32 != 0);
548 ESP_LOGCONFIG(TAG,
"UDP:");
549 ESP_LOGCONFIG(TAG,
" Port: %u", this->port_);
550 ESP_LOGCONFIG(TAG,
" Encrypted: %s", YESNO(this->is_encrypted_()));
551 ESP_LOGCONFIG(TAG,
" Ping-pong: %s", YESNO(this->ping_pong_enable_));
552 for (
const auto &
address : this->addresses_)
553 ESP_LOGCONFIG(TAG,
" Address: %s",
address.c_str());
555 for (
auto sensor : this->sensors_)
556 ESP_LOGCONFIG(TAG,
" Sensor: %s",
sensor.id);
558 #ifdef USE_BINARY_SENSOR 559 for (
auto sensor : this->binary_sensors_)
560 ESP_LOGCONFIG(TAG,
" Binary Sensor: %s",
sensor.id);
562 for (
const auto &host : this->providers_) {
563 ESP_LOGCONFIG(TAG,
" Remote host: %s", host.first.c_str());
564 ESP_LOGCONFIG(TAG,
" Encrypted: %s", YESNO(!host.second.encryption_key.empty()));
566 for (
const auto &
sensor : this->remote_sensors_[host.first.c_str()])
567 ESP_LOGCONFIG(TAG,
" Sensor: %s",
sensor.first.c_str());
569 #ifdef USE_BINARY_SENSOR 570 for (
const auto &
sensor : this->remote_binary_sensors_[host.first.c_str()])
571 ESP_LOGCONFIG(TAG,
" Binary Sensor: %s",
sensor.first.c_str());
576 if (this->rolling_code_enable_) {
577 if (++this->rolling_code_[0] == 0) {
578 this->rolling_code_[1]++;
579 this->pref_.save(&this->rolling_code_[1]);
584 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) 585 for (
const auto &saddr : this->sockaddrs_) {
586 auto result = this->broadcast_socket_->sendto(data, len, 0, &saddr,
sizeof(saddr));
588 ESP_LOGW(TAG,
"sendto() error %d", errno);
591 auto iface = IPAddress(0, 0, 0, 0);
592 for (
const auto &saddr : this->ipaddrs_) {
593 if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) {
594 this->udp_client_.write((
const uint8_t *) data, len);
595 auto result = this->udp_client_.endPacket();
597 ESP_LOGW(TAG,
"udp.write() error");
607 this->ping_header_.clear();
608 add(this->ping_header_, MAGIC_PING);
609 add(this->ping_header_, this->name_);
610 add(this->ping_header_, this->ping_key_);
611 this->send_packet_(this->ping_header_.data(), this->ping_header_.size());
612 this->resend_ping_key_ =
false;
613 ESP_LOGV(TAG,
"Sent new ping request %08X", (
unsigned) this->ping_key_);
void add_on_state_callback(std::function< void(float)> &&callback)
Add a callback that will be called every time a filtered value arrives.
std::vector< uint8_t > encryption_key
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().
uint32_t random_uint32()
Return a random 32-bit unsigned integer.
void add_binary_data_(uint8_t key, const char *id, bool data)
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
uint32_t IRAM_ATTR HOT millis()
void send_data_(bool all)
float state
This member variable stores the last state that has passed through all filters.
void process_(uint8_t *buf, size_t len)
Process a received packet.
ESPPreferences * global_preferences
void dump_config() override
void add_key_(const char *name, uint32_t key)
Application App
Global storage of Application pointer - only one Application can exist.
const std::string & get_name() const
Get the name of this Application set by pre_setup().
void send_packet_(void *data, size_t len)
float get_state() const
Getter-syntax for .state.
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
Implementation of SPI Controller mode.
void add_data_(uint8_t key, const char *id, float data)
void send_ping_pong_request_()
void process_ping_request_(const char *name, uint8_t *ptr, size_t len)
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port)
Set a sockaddr to the specified address and port for the IP version used by socket_ip().
esphome::sensor::Sensor * sensor
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.