ESPHome  2023.11.6
wifi_component.h
Go to the documentation of this file.
1 #pragma once
2 
6 #include "esphome/core/defines.h"
7 #include "esphome/core/helpers.h"
8 
9 #include <string>
10 #include <vector>
11 
12 #ifdef USE_ESP32_FRAMEWORK_ARDUINO
13 #include <WiFi.h>
14 #include <WiFiType.h>
15 #include <esp_wifi.h>
16 #endif
17 
18 #ifdef USE_LIBRETINY
19 #include <WiFi.h>
20 #endif
21 
22 #ifdef USE_ESP8266
23 #include <ESP8266WiFi.h>
24 #include <ESP8266WiFiType.h>
25 
26 #if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE < VERSION_CODE(2, 4, 0)
27 extern "C" {
28 #include <user_interface.h>
29 };
30 #endif
31 #endif
32 
33 #ifdef USE_RP2040
34 extern "C" {
35 #include "cyw43.h"
36 #include "cyw43_country.h"
37 #include "pico/cyw43_arch.h"
38 }
39 
40 #include <WiFi.h>
41 #endif
42 
43 namespace esphome {
44 namespace wifi {
45 
47  char ssid[33];
48  char password[65];
49 } PACKED; // NOLINT
50 
72 };
73 
74 enum class WiFiSTAConnectStatus : int {
75  IDLE,
76  CONNECTING,
77  CONNECTED,
80 };
81 
83 struct ManualIP {
89 };
90 
91 #ifdef USE_WIFI_WPA2_EAP
92 struct EAPAuth {
93  std::string identity; // required for all auth types
94  std::string username;
95  std::string password;
96  const char *ca_cert; // optionally verify authentication server
97  // used for EAP-TLS
98  const char *client_cert;
99  const char *client_key;
100 };
101 #endif // USE_WIFI_WPA2_EAP
102 
103 using bssid_t = std::array<uint8_t, 6>;
104 
105 class WiFiAP {
106  public:
107  void set_ssid(const std::string &ssid);
108  void set_bssid(bssid_t bssid);
109  void set_bssid(optional<bssid_t> bssid);
110  void set_password(const std::string &password);
111 #ifdef USE_WIFI_WPA2_EAP
112  void set_eap(optional<EAPAuth> eap_auth);
113 #endif // USE_WIFI_WPA2_EAP
114  void set_channel(optional<uint8_t> channel);
115  void set_priority(float priority) { priority_ = priority; }
116  void set_manual_ip(optional<ManualIP> manual_ip);
117  void set_hidden(bool hidden);
118  const std::string &get_ssid() const;
119  const optional<bssid_t> &get_bssid() const;
120  const std::string &get_password() const;
121 #ifdef USE_WIFI_WPA2_EAP
122  const optional<EAPAuth> &get_eap() const;
123 #endif // USE_WIFI_WPA2_EAP
124  const optional<uint8_t> &get_channel() const;
125  float get_priority() const { return priority_; }
126  const optional<ManualIP> &get_manual_ip() const;
127  bool get_hidden() const;
128 
129  protected:
130  std::string ssid_;
132  std::string password_;
133 #ifdef USE_WIFI_WPA2_EAP
135 #endif // USE_WIFI_WPA2_EAP
137  float priority_{0};
139  bool hidden_{false};
140 };
141 
143  public:
144  WiFiScanResult(const bssid_t &bssid, std::string ssid, uint8_t channel, int8_t rssi, bool with_auth, bool is_hidden);
145 
146  bool matches(const WiFiAP &config);
147 
148  bool get_matches() const;
149  void set_matches(bool matches);
150  const bssid_t &get_bssid() const;
151  const std::string &get_ssid() const;
152  uint8_t get_channel() const;
153  int8_t get_rssi() const;
154  bool get_with_auth() const;
155  bool get_is_hidden() const;
156  float get_priority() const { return priority_; }
157  void set_priority(float priority) { priority_ = priority; }
158 
159  bool operator==(const WiFiScanResult &rhs) const;
160 
161  protected:
162  bool matches_{false};
164  std::string ssid_;
165  uint8_t channel_;
166  int8_t rssi_;
169  float priority_{0.0f};
170 };
171 
174  float priority;
175 };
176 
181 };
182 
183 #ifdef USE_ESP_IDF
184 struct IDFWiFiEvent;
185 #endif
186 
188 class WiFiComponent : public Component {
189  public:
191  WiFiComponent();
192 
193  void set_sta(const WiFiAP &ap);
194  void add_sta(const WiFiAP &ap);
195  void clear_sta();
196 
204  void set_ap(const WiFiAP &ap);
205  WiFiAP get_ap() { return this->ap_; }
206 
207  void enable();
208  void disable();
209  bool is_disabled();
210  void start_scanning();
211  void check_scanning_finished();
212  void start_connecting(const WiFiAP &ap, bool two);
213  void set_fast_connect(bool fast_connect);
214  void set_ap_timeout(uint32_t ap_timeout) { ap_timeout_ = ap_timeout; }
215 
216  void check_connecting_finished();
217 
218  void retry_connect();
219 
220  bool can_proceed() override;
221 
222  void set_reboot_timeout(uint32_t reboot_timeout);
223 
224  bool is_connected();
225 
226  void set_power_save_mode(WiFiPowerSaveMode power_save);
227  void set_output_power(float output_power) { output_power_ = output_power; }
228 
229  void set_passive_scan(bool passive);
230 
231  void save_wifi_sta(const std::string &ssid, const std::string &password);
232  // ========== INTERNAL METHODS ==========
233  // (In most use cases you won't need these)
235  void setup() override;
236  void start();
237  void dump_config() override;
239  float get_setup_priority() const override;
240  float get_loop_priority() const override;
241 
243  void loop() override;
244 
245  bool has_sta() const;
246  bool has_ap() const;
247 
248 #ifdef USE_WIFI_11KV_SUPPORT
249  void set_btm(bool btm);
250  void set_rrm(bool rrm);
251 #endif
252 
253  network::IPAddress get_dns_address(int num);
255  std::string get_use_address() const;
256  void set_use_address(const std::string &use_address);
257 
258  const std::vector<WiFiScanResult> &get_scan_result() const { return scan_result_; }
259 
260  network::IPAddress wifi_soft_ap_ip();
261 
262  bool has_sta_priority(const bssid_t &bssid) {
263  for (auto &it : this->sta_priorities_) {
264  if (it.bssid == bssid)
265  return true;
266  }
267  return false;
268  }
269  float get_sta_priority(const bssid_t bssid) {
270  for (auto &it : this->sta_priorities_) {
271  if (it.bssid == bssid)
272  return it.priority;
273  }
274  return 0.0f;
275  }
276  void set_sta_priority(const bssid_t bssid, float priority) {
277  for (auto &it : this->sta_priorities_) {
278  if (it.bssid == bssid) {
279  it.priority = priority;
280  return;
281  }
282  }
283  this->sta_priorities_.push_back(WiFiSTAPriority{
284  .bssid = bssid,
285  .priority = priority,
286  });
287  }
288 
289  network::IPAddress wifi_sta_ip();
290  std::string wifi_ssid();
291  bssid_t wifi_bssid();
292 
293  int8_t wifi_rssi();
294 
295  void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
296 
297  Trigger<> *get_connect_trigger() const { return this->connect_trigger_; };
298  Trigger<> *get_disconnect_trigger() const { return this->disconnect_trigger_; };
299 
300  protected:
301  static std::string format_mac_addr(const uint8_t mac[6]);
302  void setup_ap_config_();
303  void print_connect_params_();
304 
305  void wifi_loop_();
306  bool wifi_mode_(optional<bool> sta, optional<bool> ap);
307  bool wifi_sta_pre_setup_();
308  bool wifi_apply_output_power_(float output_power);
309  bool wifi_apply_power_save_();
310  bool wifi_sta_ip_config_(optional<ManualIP> manual_ip);
311  bool wifi_apply_hostname_();
312  bool wifi_sta_connect_(const WiFiAP &ap);
313  void wifi_pre_setup_();
314  WiFiSTAConnectStatus wifi_sta_connect_status_();
315  bool wifi_scan_start_(bool passive);
316  bool wifi_ap_ip_config_(optional<ManualIP> manual_ip);
317  bool wifi_start_ap_(const WiFiAP &ap);
318  bool wifi_disconnect_();
319  int32_t wifi_channel_();
320  network::IPAddress wifi_subnet_mask_();
321  network::IPAddress wifi_gateway_ip_();
322  network::IPAddress wifi_dns_ip_(int num);
323 
324  bool is_captive_portal_active_();
325  bool is_esp32_improv_active_();
326 
327 #ifdef USE_ESP8266
328  static void wifi_event_callback(System_Event_t *event);
329  void wifi_scan_done_callback_(void *arg, STATUS status);
330  static void s_wifi_scan_done_callback(void *arg, STATUS status);
331 #endif
332 
333 #ifdef USE_ESP32_FRAMEWORK_ARDUINO
334  void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
335  void wifi_scan_done_callback_();
336 #endif
337 #ifdef USE_ESP_IDF
338  void wifi_process_event_(IDFWiFiEvent *data);
339 #endif
340 
341 #ifdef USE_RP2040
342  static int s_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result);
343  void wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result);
344 #endif
345 
346 #ifdef USE_LIBRETINY
347  void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
348  void wifi_scan_done_callback_();
349 #endif
350 
351  std::string use_address_;
352  std::vector<WiFiAP> sta_;
353  std::vector<WiFiSTAPriority> sta_priorities_;
355  bool fast_connect_{false};
356 
357  bool has_ap_{false};
360  bool handled_connected_state_{false};
361  uint32_t action_started_;
362  uint8_t num_retried_{0};
363  uint32_t last_connected_{0};
364  uint32_t reboot_timeout_{};
365  uint32_t ap_timeout_{};
367  bool error_from_callback_{false};
368  std::vector<WiFiScanResult> scan_result_;
369  bool scan_done_{false};
370  bool ap_setup_{false};
372  bool passive_scan_{false};
374  bool has_saved_wifi_settings_{false};
375 #ifdef USE_WIFI_11KV_SUPPORT
376  bool btm_{false};
377  bool rrm_{false};
378 #endif
380 
381  Trigger<> *connect_trigger_{new Trigger<>()};
382  Trigger<> *disconnect_trigger_{new Trigger<>()};
383 };
384 
385 extern WiFiComponent *global_wifi_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
386 
387 template<typename... Ts> class WiFiConnectedCondition : public Condition<Ts...> {
388  public:
389  bool check(Ts... x) override { return global_wifi_component->is_connected(); }
390 };
391 
392 template<typename... Ts> class WiFiEnabledCondition : public Condition<Ts...> {
393  public:
394  bool check(Ts... x) override { return !global_wifi_component->is_disabled(); }
395 };
396 
397 template<typename... Ts> class WiFiEnableAction : public Action<Ts...> {
398  public:
399  void play(Ts... x) override { global_wifi_component->enable(); }
400 };
401 
402 template<typename... Ts> class WiFiDisableAction : public Action<Ts...> {
403  public:
404  void play(Ts... x) override { global_wifi_component->disable(); }
405 };
406 
407 } // namespace wifi
408 } // namespace esphome
void setup()
Nothing has been initialized yet.
void loop()
This component is responsible for managing the ESP WiFi interface.
void set_enable_on_boot(bool enable_on_boot)
void set_priority(float priority)
std::array< uint8_t, 6 > bssid_t
std::string get_use_address()
Get the active network hostname.
Definition: util.cpp:52
float get_priority() const
void set_output_power(float output_power)
Trigger * get_disconnect_trigger() const
const std::vector< WiFiScanResult > & get_scan_result() const
uint16_t x
Definition: tt21100.cpp:17
void set_sta_priority(const bssid_t bssid, float priority)
optional< ManualIP > manual_ip_
struct esphome::wifi::SavedWifiSettings PACKED
WiFi is in STA(+AP) mode and currently connecting to an AP a second time.
void play(Ts... x) override
WiFi is in STA(+AP) mode and successfully connected.
void set_priority(float priority)
network::IPAddress static_ip
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition: util.cpp:15
network::IPAddress gateway
void set_ap_timeout(uint32_t ap_timeout)
std::vector< WiFiScanResult > scan_result_
WiFi is in STA-only mode and currently scanning for APs.
Struct for setting static IPs in WiFiComponent.
network::IPAddress dns1
The first DNS server. 0.0.0.0 for default.
Base class for all automation conditions.
Definition: automation.h:74
WiFi is in STA(+AP) mode and currently connecting to an AP.
bool has_sta_priority(const bssid_t &bssid)
WiFi is in cooldown mode because something went wrong, scanning will begin after a short period of ti...
optional< bssid_t > bssid_
Trigger * get_connect_trigger() const
WiFiComponent * global_wifi_component
optional< uint8_t > channel_
uint8_t priority
uint8_t status
Definition: bl0942.h:23
ESPPreferenceObject pref_
bool is_disabled()
Return whether the network is disabled (only wifi for now)
Definition: util.cpp:32
network::IPAddress dns2
The second DNS server. 0.0.0.0 for default.
const char * client_cert
std::vector< WiFiSTAPriority > sta_priorities_
bool operator==(optional< T > const &x, optional< U > const &y)
Definition: optional.h:114
std::vector< WiFiAP > sta_
optional< float > output_power_
network::IPAddress subnet
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void play(Ts... x) override
float get_sta_priority(const bssid_t bssid)
optional< EAPAuth > eap_
WiFi is in AP-only mode and internal AP is already enabled.
network::IPAddress get_ip_address()
Definition: util.cpp:40