ESPHome 2025.5.0
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
7namespace esphome {
8namespace wake_on_lan {
9
10static const char *const TAG = "wake_on_lan.button";
11static const uint8_t PREFIX[6] = {255, 255, 255, 255, 255, 255};
12
13void WakeOnLanButton::set_macaddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f) {
14 macaddr_[0] = a;
15 macaddr_[1] = b;
16 macaddr_[2] = c;
17 macaddr_[3] = d;
18 macaddr_[4] = e;
19 macaddr_[5] = f;
20}
21
23 LOG_BUTTON("", "Wake-on-LAN Button", this);
24 ESP_LOGCONFIG(TAG, " Target MAC address: %02X:%02X:%02X:%02X:%02X:%02X", this->macaddr_[0], this->macaddr_[1],
25 this->macaddr_[2], this->macaddr_[3], this->macaddr_[4], this->macaddr_[5]);
26}
27
29 if (!network::is_connected()) {
30 ESP_LOGW(TAG, "Network not connected");
31 return;
32 }
33 ESP_LOGI(TAG, "Sending Wake-on-LAN Packet...");
34#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
35 struct sockaddr_storage saddr {};
36 auto addr_len =
37 socket::set_sockaddr(reinterpret_cast<sockaddr *>(&saddr), sizeof(saddr), "255.255.255.255", this->port_);
38 uint8_t buffer[6 + sizeof this->macaddr_ * 16];
39 memcpy(buffer, PREFIX, sizeof(PREFIX));
40 for (size_t i = 0; i != 16; i++) {
41 memcpy(buffer + i * sizeof(this->macaddr_) + sizeof(PREFIX), this->macaddr_, sizeof(this->macaddr_));
42 }
43 if (this->broadcast_socket_->sendto(buffer, sizeof(buffer), 0, reinterpret_cast<const sockaddr *>(&saddr),
44 addr_len) <= 0)
45 ESP_LOGW(TAG, "sendto() error %d", errno);
46#else
47 IPAddress broadcast = IPAddress(255, 255, 255, 255);
48 for (auto ip : esphome::network::get_ip_addresses()) {
49 if (ip.is_ip4()) {
50 if (this->udp_client_.beginPacketMulticast(broadcast, 9, ip, 128) != 0) {
51 this->udp_client_.write(PREFIX, 6);
52 for (size_t i = 0; i < 16; i++) {
53 this->udp_client_.write(macaddr_, 6);
54 }
55 if (this->udp_client_.endPacket() != 0)
56 return;
57 ESP_LOGW(TAG, "WOL broadcast failed");
58 return;
59 }
60 }
61 }
62 ESP_LOGW(TAG, "No ip4 addresses to broadcast to");
63#endif
64}
65
67#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
68 this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
69 if (this->broadcast_socket_ == nullptr) {
70 this->mark_failed();
71 this->status_set_error("Could not create socket");
72 return;
73 }
74 int enable = 1;
75 auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
76 if (err != 0) {
77 this->status_set_warning("Socket unable to set reuseaddr");
78 // we can still continue
79 }
80 err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int));
81 if (err != 0) {
82 this->status_set_warning("Socket unable to set broadcast");
83 }
84#endif
85}
86
87} // namespace wake_on_lan
88} // namespace esphome
89#endif
virtual void mark_failed()
Mark this component as failed.
void status_set_warning(const char *message="unspecified")
void status_set_error(const char *message="unspecified")
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:25
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition util.cpp:15
network::IPAddresses get_ip_addresses()
Definition util.cpp:40
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.
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().
Definition socket.cpp:21
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7