ESPHome 2026.10.2
Loading...
Searching...
No Matches
wake_on_lan.cpp
Go to the documentation of this file.
1#include "wake_on_lan.h"
2#if defined(USE_NETWORK) && !defined(USE_ZEPHYR)
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 if (addr_len == 0) {
38 ESP_LOGW(TAG, "Invalid broadcast address");
39 return;
40 }
41 uint8_t buffer[6 + sizeof this->macaddr_ * 16];
42 memcpy(buffer, PREFIX, sizeof(PREFIX));
43 for (size_t i = 0; i != 16; i++) {
44 memcpy(buffer + i * sizeof(this->macaddr_) + sizeof(PREFIX), this->macaddr_, sizeof(this->macaddr_));
45 }
46 if (this->broadcast_socket_->sendto(buffer, sizeof(buffer), 0, reinterpret_cast<const sockaddr *>(&saddr),
47 addr_len) <= 0) {
48 ESP_LOGW(TAG, "sendto() error %d", errno);
49 }
50#else
51 IPAddress broadcast = IPAddress(255, 255, 255, 255);
52 for (auto ip : esphome::network::get_ip_addresses()) {
53 if (ip.is_ip4()) {
54 if (this->udp_client_.beginPacketMulticast(broadcast, 9, ip, 128) != 0) {
55 this->udp_client_.write(PREFIX, 6);
56 for (size_t i = 0; i < 16; i++) {
57 this->udp_client_.write(macaddr_, 6);
58 }
59 if (this->udp_client_.endPacket() != 0)
60 return;
61 ESP_LOGW(TAG, "WOL broadcast failed");
62 return;
63 }
64 }
65 }
66 ESP_LOGW(TAG, "No ip4 addresses to broadcast to");
67#endif
68}
69
71#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
72 this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
73 if (this->broadcast_socket_ == nullptr) {
74 this->status_set_error(LOG_STR("Could not create socket"));
75 this->mark_failed();
76 return;
77 }
78 int enable = 1;
79 auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
80 if (err != 0) {
81 this->status_set_warning(LOG_STR("Socket unable to set reuseaddr"));
82 // we can still continue
83 }
84 err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int));
85 if (err != 0) {
86 this->status_set_warning(LOG_STR("Socket unable to set broadcast"));
87 }
88#endif
89}
90
91} // namespace esphome::wake_on_lan
92
93#endif
void mark_failed()
Mark this component as failed.
void set_macaddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f)
uint8_t macaddr_[MAC_ADDRESS_SIZE]
Definition wake_on_lan.h:31
std::unique_ptr< socket::Socket > broadcast_socket_
Definition wake_on_lan.h:25
uint16_t addr_len
uint32_t buffer
Definition gif.cpp:50
ESPHOME_ALWAYS_INLINE bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition util.h:28
network::IPAddresses get_ip_addresses()
Definition util.cpp:68
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:142
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.