ESPHome 2026.5.0b1
Loading...
Searching...
No Matches
wake_on_lan.cpp
Go to the documentation of this file.
1#include "wake_on_lan.h"
2#ifdef USE_NETWORK
3#include "esphome/core/log.h"
6
8
9static const char *const TAG = "wake_on_lan.button";
10static const uint8_t PREFIX[6] = {255, 255, 255, 255, 255, 255};
11
12void WakeOnLanButton::set_macaddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f) {
13 macaddr_[0] = a;
14 macaddr_[1] = b;
15 macaddr_[2] = c;
16 macaddr_[3] = d;
17 macaddr_[4] = e;
18 macaddr_[5] = f;
19}
20
22 LOG_BUTTON("", "Wake-on-LAN Button", this);
23 ESP_LOGCONFIG(TAG, " Target MAC address: %02X:%02X:%02X:%02X:%02X:%02X", this->macaddr_[0], this->macaddr_[1],
24 this->macaddr_[2], this->macaddr_[3], this->macaddr_[4], this->macaddr_[5]);
25}
26
28 if (!network::is_connected()) {
29 ESP_LOGW(TAG, "Network not connected");
30 return;
31 }
32 ESP_LOGI(TAG, "Sending Wake-on-LAN Packet");
33#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
34 struct sockaddr_storage saddr {};
35 auto addr_len =
36 socket::set_sockaddr(reinterpret_cast<sockaddr *>(&saddr), sizeof(saddr), "255.255.255.255", this->port_);
37 uint8_t buffer[6 + sizeof this->macaddr_ * 16];
38 memcpy(buffer, PREFIX, sizeof(PREFIX));
39 for (size_t i = 0; i != 16; i++) {
40 memcpy(buffer + i * sizeof(this->macaddr_) + sizeof(PREFIX), this->macaddr_, sizeof(this->macaddr_));
41 }
42 if (this->broadcast_socket_->sendto(buffer, sizeof(buffer), 0, reinterpret_cast<const sockaddr *>(&saddr),
43 addr_len) <= 0)
44 ESP_LOGW(TAG, "sendto() error %d", errno);
45#else
46 IPAddress broadcast = IPAddress(255, 255, 255, 255);
47 for (auto ip : esphome::network::get_ip_addresses()) {
48 if (ip.is_ip4()) {
49 if (this->udp_client_.beginPacketMulticast(broadcast, 9, ip, 128) != 0) {
50 this->udp_client_.write(PREFIX, 6);
51 for (size_t i = 0; i < 16; i++) {
52 this->udp_client_.write(macaddr_, 6);
53 }
54 if (this->udp_client_.endPacket() != 0)
55 return;
56 ESP_LOGW(TAG, "WOL broadcast failed");
57 return;
58 }
59 }
60 }
61 ESP_LOGW(TAG, "No ip4 addresses to broadcast to");
62#endif
63}
64
66#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
67 this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
68 if (this->broadcast_socket_ == nullptr) {
69 this->status_set_error(LOG_STR("Could not create socket"));
70 this->mark_failed();
71 return;
72 }
73 int enable = 1;
74 auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
75 if (err != 0) {
76 this->status_set_warning(LOG_STR("Socket unable to set reuseaddr"));
77 // we can still continue
78 }
79 err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int));
80 if (err != 0) {
81 this->status_set_warning(LOG_STR("Socket unable to set broadcast"));
82 }
83#endif
84}
85
86} // namespace esphome::wake_on_lan
87
88#endif
void mark_failed()
Mark this component as failed.
ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", "2026.2.0") void set_retry(const std uint32_t uint8_t std::function< RetryResult(uint8_t)> && f
Definition component.h:454
void set_macaddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f)
std::unique_ptr< socket::Socket > broadcast_socket_
Definition wake_on_lan.h:24
uint16_t addr_len
ESPHOME_ALWAYS_INLINE bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition util.h:27
network::IPAddresses get_ip_addresses()
Definition util.cpp:23
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port)
Set a sockaddr to the specified address and port for the IP version used by socket_ip().
Definition socket.cpp:107
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.