ESPHome 2025.5.0
Loading...
Searching...
No Matches
wifi_component.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_WIFI
9
10#include <string>
11#include <vector>
12
13#ifdef USE_ESP32_FRAMEWORK_ARDUINO
14#include <WiFi.h>
15#include <WiFiType.h>
16#include <esp_wifi.h>
17#endif
18
19#ifdef USE_LIBRETINY
20#include <WiFi.h>
21#endif
22
23#if defined(USE_ESP_IDF) && defined(USE_WIFI_WPA2_EAP)
24#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1)
25#include <esp_eap_client.h>
26#else
27#include <esp_wpa2.h>
28#endif
29#endif
30
31#ifdef USE_ESP8266
32#include <ESP8266WiFi.h>
33#include <ESP8266WiFiType.h>
34
35#if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE < VERSION_CODE(2, 4, 0)
36extern "C" {
37#include <user_interface.h>
38};
39#endif
40#endif
41
42#ifdef USE_RP2040
43extern "C" {
44#include "cyw43.h"
45#include "cyw43_country.h"
46#include "pico/cyw43_arch.h"
47}
48
49#include <WiFi.h>
50#endif
51
52namespace esphome {
53namespace wifi {
54
56 char ssid[33];
57 char password[65];
58} PACKED; // NOLINT
59
61 uint8_t bssid[6];
62 uint8_t channel;
63} PACKED; // NOLINT
64
87
95
104
105#ifdef USE_WIFI_WPA2_EAP
106struct EAPAuth {
107 std::string identity; // required for all auth types
108 std::string username;
109 std::string password;
110 const char *ca_cert; // optionally verify authentication server
111 // used for EAP-TLS
112 const char *client_cert;
113 const char *client_key;
114// used for EAP-TTLS
115#ifdef USE_ESP_IDF
116 esp_eap_ttls_phase2_types ttls_phase_2;
117#endif
118};
119#endif // USE_WIFI_WPA2_EAP
120
121using bssid_t = std::array<uint8_t, 6>;
122
123class WiFiAP {
124 public:
125 void set_ssid(const std::string &ssid);
126 void set_bssid(bssid_t bssid);
127 void set_bssid(optional<bssid_t> bssid);
128 void set_password(const std::string &password);
129#ifdef USE_WIFI_WPA2_EAP
130 void set_eap(optional<EAPAuth> eap_auth);
131#endif // USE_WIFI_WPA2_EAP
132 void set_channel(optional<uint8_t> channel);
134 void set_manual_ip(optional<ManualIP> manual_ip);
135 void set_hidden(bool hidden);
136 const std::string &get_ssid() const;
137 const optional<bssid_t> &get_bssid() const;
138 const std::string &get_password() const;
139#ifdef USE_WIFI_WPA2_EAP
140 const optional<EAPAuth> &get_eap() const;
141#endif // USE_WIFI_WPA2_EAP
142 const optional<uint8_t> &get_channel() const;
143 float get_priority() const { return priority_; }
144 const optional<ManualIP> &get_manual_ip() const;
145 bool get_hidden() const;
146
147 protected:
148 std::string ssid_;
150 std::string password_;
151#ifdef USE_WIFI_WPA2_EAP
153#endif // USE_WIFI_WPA2_EAP
155 float priority_{0};
157 bool hidden_{false};
158};
159
161 public:
162 WiFiScanResult(const bssid_t &bssid, std::string ssid, uint8_t channel, int8_t rssi, bool with_auth, bool is_hidden);
163
164 bool matches(const WiFiAP &config);
165
166 bool get_matches() const;
167 void set_matches(bool matches);
168 const bssid_t &get_bssid() const;
169 const std::string &get_ssid() const;
170 uint8_t get_channel() const;
171 int8_t get_rssi() const;
172 bool get_with_auth() const;
173 bool get_is_hidden() const;
174 float get_priority() const { return priority_; }
176
177 bool operator==(const WiFiScanResult &rhs) const;
178
179 protected:
180 bool matches_{false};
182 std::string ssid_;
183 uint8_t channel_;
184 int8_t rssi_;
187 float priority_{0.0f};
188};
189
194
200
201#ifdef USE_ESP_IDF
202struct IDFWiFiEvent;
203#endif
204
206class WiFiComponent : public Component {
207 public:
210
211 void set_sta(const WiFiAP &ap);
212 WiFiAP get_sta() { return this->selected_ap_; }
213 void add_sta(const WiFiAP &ap);
214 void clear_sta();
215
216#ifdef USE_WIFI_AP
224 void set_ap(const WiFiAP &ap);
225 WiFiAP get_ap() { return this->ap_; }
226#endif // USE_WIFI_AP
227
228 void enable();
229 void disable();
230 bool is_disabled();
231 void start_scanning();
233 void start_connecting(const WiFiAP &ap, bool two);
234 void set_fast_connect(bool fast_connect);
235 void set_ap_timeout(uint32_t ap_timeout) { ap_timeout_ = ap_timeout; }
236
238
239 void retry_connect();
240
241 bool can_proceed() override;
242
243 void set_reboot_timeout(uint32_t reboot_timeout);
244
245 bool is_connected();
246
247 void set_power_save_mode(WiFiPowerSaveMode power_save);
248 void set_output_power(float output_power) { output_power_ = output_power; }
249
250 void set_passive_scan(bool passive);
251
252 void save_wifi_sta(const std::string &ssid, const std::string &password);
253 // ========== INTERNAL METHODS ==========
254 // (In most use cases you won't need these)
256 void setup() override;
257 void start();
258 void dump_config() override;
260 float get_setup_priority() const override;
261 float get_loop_priority() const override;
262
264 void loop() override;
265
266 bool has_sta() const;
267 bool has_ap() const;
268
269#ifdef USE_WIFI_11KV_SUPPORT
270 void set_btm(bool btm);
271 void set_rrm(bool rrm);
272#endif
273
276 std::string get_use_address() const;
277 void set_use_address(const std::string &use_address);
278
279 const std::vector<WiFiScanResult> &get_scan_result() const { return scan_result_; }
280
282
283 bool has_sta_priority(const bssid_t &bssid) {
284 for (auto &it : this->sta_priorities_) {
285 if (it.bssid == bssid)
286 return true;
287 }
288 return false;
289 }
290 float get_sta_priority(const bssid_t bssid) {
291 for (auto &it : this->sta_priorities_) {
292 if (it.bssid == bssid)
293 return it.priority;
294 }
295 return 0.0f;
296 }
297 void set_sta_priority(const bssid_t bssid, float priority) {
298 for (auto &it : this->sta_priorities_) {
299 if (it.bssid == bssid) {
300 it.priority = priority;
301 return;
302 }
303 }
304 this->sta_priorities_.push_back(WiFiSTAPriority{
305 .bssid = bssid,
306 .priority = priority,
307 });
308 }
309
311 std::string wifi_ssid();
313
314 int8_t wifi_rssi();
315
316 void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
317
320
321 int32_t get_wifi_channel();
322
323 protected:
324 static std::string format_mac_addr(const uint8_t mac[6]);
325
326#ifdef USE_WIFI_AP
327 void setup_ap_config_();
328#endif // USE_WIFI_AP
329
331
332 void wifi_loop_();
334 bool wifi_sta_pre_setup_();
335 bool wifi_apply_output_power_(float output_power);
339 bool wifi_sta_connect_(const WiFiAP &ap);
340 void wifi_pre_setup_();
342 bool wifi_scan_start_(bool passive);
343
344#ifdef USE_WIFI_AP
346 bool wifi_start_ap_(const WiFiAP &ap);
347#endif // USE_WIFI_AP
348
349 bool wifi_disconnect_();
350
354
357
360
361#ifdef USE_ESP8266
362 static void wifi_event_callback(System_Event_t *event);
363 void wifi_scan_done_callback_(void *arg, STATUS status);
364 static void s_wifi_scan_done_callback(void *arg, STATUS status);
365#endif
366
367#ifdef USE_ESP32_FRAMEWORK_ARDUINO
368 void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
370#endif
371#ifdef USE_ESP_IDF
372 void wifi_process_event_(IDFWiFiEvent *data);
373#endif
374
375#ifdef USE_RP2040
376 static int s_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result);
377 void wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result);
378#endif
379
380#ifdef USE_LIBRETINY
381 void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
383#endif
384
385 std::string use_address_;
386 std::vector<WiFiAP> sta_;
387 std::vector<WiFiSTAPriority> sta_priorities_;
389 bool fast_connect_{false};
390 bool retry_hidden_{false};
391
392 bool has_ap_{false};
397 uint8_t num_retried_{0};
398 uint32_t last_connected_{0};
399 uint32_t reboot_timeout_{};
400 uint32_t ap_timeout_{};
403 std::vector<WiFiScanResult> scan_result_;
404 bool scan_done_{false};
405 bool ap_setup_{false};
407 bool passive_scan_{false};
411#ifdef USE_WIFI_11KV_SUPPORT
412 bool btm_{false};
413 bool rrm_{false};
414#endif
416 bool got_ipv4_address_{false};
417#if USE_NETWORK_IPV6
419#endif /* USE_NETWORK_IPV6 */
420
423};
424
425extern WiFiComponent *global_wifi_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
426
427template<typename... Ts> class WiFiConnectedCondition : public Condition<Ts...> {
428 public:
429 bool check(Ts... x) override { return global_wifi_component->is_connected(); }
430};
431
432template<typename... Ts> class WiFiEnabledCondition : public Condition<Ts...> {
433 public:
434 bool check(Ts... x) override { return !global_wifi_component->is_disabled(); }
435};
436
437template<typename... Ts> class WiFiEnableAction : public Action<Ts...> {
438 public:
439 void play(Ts... x) override { global_wifi_component->enable(); }
440};
441
442template<typename... Ts> class WiFiDisableAction : public Action<Ts...> {
443 public:
444 void play(Ts... x) override { global_wifi_component->disable(); }
445};
446
447template<typename... Ts> class WiFiConfigureAction : public Action<Ts...>, public Component {
448 public:
449 TEMPLATABLE_VALUE(std::string, ssid)
450 TEMPLATABLE_VALUE(std::string, password)
451 TEMPLATABLE_VALUE(bool, save)
452 TEMPLATABLE_VALUE(uint32_t, connection_timeout)
453
454 void play(Ts... x) override {
455 auto ssid = this->ssid_.value(x...);
456 auto password = this->password_.value(x...);
457 // Avoid multiple calls
458 if (this->connecting_)
459 return;
460 // If already connected to the same AP, do nothing
461 if (global_wifi_component->wifi_ssid() == ssid) {
462 // Callback to notify the user that the connection was successful
463 this->connect_trigger_->trigger();
464 return;
465 }
466 // Create a new WiFiAP object with the new SSID and password
467 this->new_sta_.set_ssid(ssid);
468 this->new_sta_.set_password(password);
469 // Save the current STA
470 this->old_sta_ = global_wifi_component->get_sta();
471 // Disable WiFi
473 // Set the state to connecting
474 this->connecting_ = true;
475 // Store the new STA so once the WiFi is enabled, it will connect to it
476 // This is necessary because the WiFiComponent will raise an error and fallback to the saved STA
477 // if trying to connect to a new STA while already connected to another one
478 if (this->save_.value(x...)) {
479 global_wifi_component->save_wifi_sta(new_sta_.get_ssid(), new_sta_.get_password());
480 } else {
482 }
483 // Enable WiFi
485 // Set timeout for the connection
486 this->set_timeout("wifi-connect-timeout", this->connection_timeout_.value(x...), [this]() {
487 this->connecting_ = false;
488 // If the timeout is reached, stop connecting and revert to the old AP
489 global_wifi_component->disable();
490 global_wifi_component->save_wifi_sta(old_sta_.get_ssid(), old_sta_.get_password());
491 global_wifi_component->enable();
492 // Callback to notify the user that the connection failed
493 this->error_trigger_->trigger();
494 });
495 }
496
497 Trigger<> *get_connect_trigger() const { return this->connect_trigger_; }
498 Trigger<> *get_error_trigger() const { return this->error_trigger_; }
499
500 void loop() override {
501 if (!this->connecting_)
502 return;
504 // The WiFi is connected, stop the timeout and reset the connecting flag
505 this->cancel_timeout("wifi-connect-timeout");
506 this->connecting_ = false;
507 if (global_wifi_component->wifi_ssid() == this->new_sta_.get_ssid()) {
508 // Callback to notify the user that the connection was successful
509 this->connect_trigger_->trigger();
510 } else {
511 // Callback to notify the user that the connection failed
512 this->error_trigger_->trigger();
513 }
514 }
515 }
516
517 protected:
518 bool connecting_{false};
523};
524
525} // namespace wifi
526} // namespace esphome
527#endif
virtual void play(Ts... x)=0
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
Definition component.cpp:76
virtual void loop()
This method will be called repeatedly.
Definition component.cpp:53
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.cpp:72
Base class for all automation conditions.
Definition automation.h:75
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition automation.h:96
void set_priority(float priority)
const optional< bssid_t > & get_bssid() const
const std::string & get_ssid() const
void set_ssid(const std::string &ssid)
const optional< uint8_t > & get_channel() const
const optional< EAPAuth > & get_eap() const
void set_channel(optional< uint8_t > channel)
const std::string & get_password() const
void set_bssid(bssid_t bssid)
optional< uint8_t > channel_
optional< EAPAuth > eap_
optional< bssid_t > bssid_
optional< ManualIP > manual_ip_
void set_eap(optional< EAPAuth > eap_auth)
void set_password(const std::string &password)
void set_manual_ip(optional< ManualIP > manual_ip)
float get_priority() const
const optional< ManualIP > & get_manual_ip() const
void set_hidden(bool hidden)
This component is responsible for managing the ESP WiFi interface.
Trigger * get_connect_trigger() const
void add_sta(const WiFiAP &ap)
void set_ap(const WiFiAP &ap)
Setup an Access Point that should be created if no connection to a station can be made.
void set_sta(const WiFiAP &ap)
bool has_sta_priority(const bssid_t &bssid)
std::string get_use_address() const
void save_wifi_sta(const std::string &ssid, const std::string &password)
void loop() override
Reconnect WiFi if required.
bool wifi_sta_ip_config_(optional< ManualIP > manual_ip)
void set_enable_on_boot(bool enable_on_boot)
float get_sta_priority(const bssid_t bssid)
static int s_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result)
network::IPAddress get_dns_address(int num)
static void wifi_event_callback(System_Event_t *event)
WiFiComponent()
Construct a WiFiComponent.
std::vector< WiFiScanResult > scan_result_
void wifi_process_event_(IDFWiFiEvent *data)
std::vector< WiFiSTAPriority > sta_priorities_
bool wifi_ap_ip_config_(optional< ManualIP > manual_ip)
void start_connecting(const WiFiAP &ap, bool two)
void set_passive_scan(bool passive)
void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info)
const std::vector< WiFiScanResult > & get_scan_result() const
static void s_wifi_scan_done_callback(void *arg, STATUS status)
void set_power_save_mode(WiFiPowerSaveMode power_save)
void set_use_address(const std::string &use_address)
ESPPreferenceObject fast_connect_pref_
void wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result)
float get_loop_priority() const override
network::IPAddresses get_ip_addresses()
std::vector< WiFiAP > sta_
float get_setup_priority() const override
WIFI setup_priority.
void set_output_power(float output_power)
Trigger * get_disconnect_trigger() const
optional< float > output_power_
static std::string format_mac_addr(const uint8_t mac[6])
void set_ap_timeout(uint32_t ap_timeout)
void set_sta_priority(const bssid_t bssid, float priority)
void set_fast_connect(bool fast_connect)
bool wifi_apply_output_power_(float output_power)
bool wifi_mode_(optional< bool > sta, optional< bool > ap)
void set_reboot_timeout(uint32_t reboot_timeout)
void setup() override
Setup WiFi interface.
TEMPLATABLE_VALUE(std::string, ssid) TEMPLATABLE_VALUE(std WiFiAP new_sta_
void play(Ts... x) override
const std::string & get_ssid() const
void set_priority(float priority)
const bssid_t & get_bssid() const
WiFiScanResult(const bssid_t &bssid, std::string ssid, uint8_t channel, int8_t rssi, bool with_auth, bool is_hidden)
bool matches(const WiFiAP &config)
bool operator==(const WiFiScanResult &rhs) const
uint8_t priority
std::array< IPAddress, 5 > IPAddresses
Definition ip_address.h:143
std::array< uint8_t, 6 > bssid_t
struct esphome::wifi::SavedWifiSettings PACKED
@ WIFI_COMPONENT_STATE_DISABLED
WiFi is disabled.
@ WIFI_COMPONENT_STATE_AP
WiFi is in AP-only mode and internal AP is already enabled.
@ WIFI_COMPONENT_STATE_STA_CONNECTING
WiFi is in STA(+AP) mode and currently connecting to an AP.
@ WIFI_COMPONENT_STATE_OFF
Nothing has been initialized yet.
@ WIFI_COMPONENT_STATE_STA_SCANNING
WiFi is in STA-only mode and currently scanning for APs.
@ WIFI_COMPONENT_STATE_STA_CONNECTING_2
WiFi is in STA(+AP) mode and currently connecting to an AP a second time.
@ WIFI_COMPONENT_STATE_COOLDOWN
WiFi is in cooldown mode because something went wrong, scanning will begin after a short period of ti...
@ WIFI_COMPONENT_STATE_STA_CONNECTED
WiFi is in STA(+AP) mode and successfully connected.
WiFiComponent * global_wifi_component
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
esp_eap_ttls_phase2_types ttls_phase_2
Struct for setting static IPs in WiFiComponent.
network::IPAddress static_ip
network::IPAddress dns1
The first DNS server. 0.0.0.0 for default.
network::IPAddress gateway
network::IPAddress dns2
The second DNS server. 0.0.0.0 for default.
network::IPAddress subnet
uint16_t x
Definition tt21100.cpp:5