ESPHome  2023.8.3
wifi_component.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "esphome/core/defines.h"
6 #include "esphome/core/helpers.h"
8 
9 #include <string>
10 #include <vector>
11 
12 #ifdef USE_ESP32_FRAMEWORK_ARDUINO
13 #include <esp_wifi.h>
14 #include <WiFiType.h>
15 #include <WiFi.h>
16 #endif
17 
18 #ifdef USE_ESP8266
19 #include <ESP8266WiFi.h>
20 #include <ESP8266WiFiType.h>
21 
22 #if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE < VERSION_CODE(2, 4, 0)
23 extern "C" {
24 #include <user_interface.h>
25 };
26 #endif
27 #endif
28 
29 #ifdef USE_RP2040
30 extern "C" {
31 #include "cyw43.h"
32 #include "cyw43_country.h"
33 #include "pico/cyw43_arch.h"
34 }
35 
36 #include <WiFi.h>
37 #endif
38 
39 namespace esphome {
40 namespace wifi {
41 
43  char ssid[33];
44  char password[65];
45 } PACKED; // NOLINT
46 
68 };
69 
70 enum class WiFiSTAConnectStatus : int {
71  IDLE,
72  CONNECTING,
73  CONNECTED,
76 };
77 
79 struct ManualIP {
85 };
86 
87 #ifdef USE_WIFI_WPA2_EAP
88 struct EAPAuth {
89  std::string identity; // required for all auth types
90  std::string username;
91  std::string password;
92  const char *ca_cert; // optionally verify authentication server
93  // used for EAP-TLS
94  const char *client_cert;
95  const char *client_key;
96 };
97 #endif // USE_WIFI_WPA2_EAP
98 
99 using bssid_t = std::array<uint8_t, 6>;
100 
101 class WiFiAP {
102  public:
103  void set_ssid(const std::string &ssid);
104  void set_bssid(bssid_t bssid);
105  void set_bssid(optional<bssid_t> bssid);
106  void set_password(const std::string &password);
107 #ifdef USE_WIFI_WPA2_EAP
108  void set_eap(optional<EAPAuth> eap_auth);
109 #endif // USE_WIFI_WPA2_EAP
110  void set_channel(optional<uint8_t> channel);
111  void set_priority(float priority) { priority_ = priority; }
112  void set_manual_ip(optional<ManualIP> manual_ip);
113  void set_hidden(bool hidden);
114  const std::string &get_ssid() const;
115  const optional<bssid_t> &get_bssid() const;
116  const std::string &get_password() const;
117 #ifdef USE_WIFI_WPA2_EAP
118  const optional<EAPAuth> &get_eap() const;
119 #endif // USE_WIFI_WPA2_EAP
120  const optional<uint8_t> &get_channel() const;
121  float get_priority() const { return priority_; }
122  const optional<ManualIP> &get_manual_ip() const;
123  bool get_hidden() const;
124 
125  protected:
126  std::string ssid_;
128  std::string password_;
129 #ifdef USE_WIFI_WPA2_EAP
131 #endif // USE_WIFI_WPA2_EAP
133  float priority_{0};
135  bool hidden_{false};
136 };
137 
139  public:
140  WiFiScanResult(const bssid_t &bssid, std::string ssid, uint8_t channel, int8_t rssi, bool with_auth, bool is_hidden);
141 
142  bool matches(const WiFiAP &config);
143 
144  bool get_matches() const;
145  void set_matches(bool matches);
146  const bssid_t &get_bssid() const;
147  const std::string &get_ssid() const;
148  uint8_t get_channel() const;
149  int8_t get_rssi() const;
150  bool get_with_auth() const;
151  bool get_is_hidden() const;
152  float get_priority() const { return priority_; }
153  void set_priority(float priority) { priority_ = priority; }
154 
155  bool operator==(const WiFiScanResult &rhs) const;
156 
157  protected:
158  bool matches_{false};
160  std::string ssid_;
161  uint8_t channel_;
162  int8_t rssi_;
165  float priority_{0.0f};
166 };
167 
170  float priority;
171 };
172 
177 };
178 
179 #ifdef USE_ESP_IDF
180 struct IDFWiFiEvent;
181 #endif
182 
184 class WiFiComponent : public Component {
185  public:
187  WiFiComponent();
188 
189  void set_sta(const WiFiAP &ap);
190  void add_sta(const WiFiAP &ap);
191  void clear_sta();
192 
200  void set_ap(const WiFiAP &ap);
201  WiFiAP get_ap() { return this->ap_; }
202 
203  void enable();
204  void disable();
205  bool is_disabled();
206  void start_scanning();
207  void check_scanning_finished();
208  void start_connecting(const WiFiAP &ap, bool two);
209  void set_fast_connect(bool fast_connect);
210  void set_ap_timeout(uint32_t ap_timeout) { ap_timeout_ = ap_timeout; }
211 
212  void check_connecting_finished();
213 
214  void retry_connect();
215 
216  bool can_proceed() override;
217 
218  void set_reboot_timeout(uint32_t reboot_timeout);
219 
220  bool is_connected();
221 
222  void set_power_save_mode(WiFiPowerSaveMode power_save);
223  void set_output_power(float output_power) { output_power_ = output_power; }
224 
225  void set_passive_scan(bool passive);
226 
227  void save_wifi_sta(const std::string &ssid, const std::string &password);
228  // ========== INTERNAL METHODS ==========
229  // (In most use cases you won't need these)
231  void setup() override;
232  void start();
233  void dump_config() override;
235  float get_setup_priority() const override;
236  float get_loop_priority() const override;
237 
239  void loop() override;
240 
241  bool has_sta() const;
242  bool has_ap() const;
243 
244 #ifdef USE_WIFI_11KV_SUPPORT
245  void set_btm(bool btm);
246  void set_rrm(bool rrm);
247 #endif
248 
249  network::IPAddress get_dns_address(int num);
251  std::string get_use_address() const;
252  void set_use_address(const std::string &use_address);
253 
254  const std::vector<WiFiScanResult> &get_scan_result() const { return scan_result_; }
255 
256  network::IPAddress wifi_soft_ap_ip();
257 
258  bool has_sta_priority(const bssid_t &bssid) {
259  for (auto &it : this->sta_priorities_) {
260  if (it.bssid == bssid)
261  return true;
262  }
263  return false;
264  }
265  float get_sta_priority(const bssid_t bssid) {
266  for (auto &it : this->sta_priorities_) {
267  if (it.bssid == bssid)
268  return it.priority;
269  }
270  return 0.0f;
271  }
272  void set_sta_priority(const bssid_t bssid, float priority) {
273  for (auto &it : this->sta_priorities_) {
274  if (it.bssid == bssid) {
275  it.priority = priority;
276  return;
277  }
278  }
279  this->sta_priorities_.push_back(WiFiSTAPriority{
280  .bssid = bssid,
281  .priority = priority,
282  });
283  }
284 
285  network::IPAddress wifi_sta_ip();
286  std::string wifi_ssid();
287  bssid_t wifi_bssid();
288 
289  int8_t wifi_rssi();
290 
291  void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
292 
293  protected:
294  static std::string format_mac_addr(const uint8_t mac[6]);
295  void setup_ap_config_();
296  void print_connect_params_();
297 
298  void wifi_loop_();
299  bool wifi_mode_(optional<bool> sta, optional<bool> ap);
300  bool wifi_sta_pre_setup_();
301  bool wifi_apply_output_power_(float output_power);
302  bool wifi_apply_power_save_();
303  bool wifi_sta_ip_config_(optional<ManualIP> manual_ip);
304  bool wifi_apply_hostname_();
305  bool wifi_sta_connect_(const WiFiAP &ap);
306  void wifi_pre_setup_();
307  WiFiSTAConnectStatus wifi_sta_connect_status_();
308  bool wifi_scan_start_(bool passive);
309  bool wifi_ap_ip_config_(optional<ManualIP> manual_ip);
310  bool wifi_start_ap_(const WiFiAP &ap);
311  bool wifi_disconnect_();
312  int32_t wifi_channel_();
313  network::IPAddress wifi_subnet_mask_();
314  network::IPAddress wifi_gateway_ip_();
315  network::IPAddress wifi_dns_ip_(int num);
316 
317  bool is_captive_portal_active_();
318  bool is_esp32_improv_active_();
319 
320 #ifdef USE_ESP8266
321  static void wifi_event_callback(System_Event_t *event);
322  void wifi_scan_done_callback_(void *arg, STATUS status);
323  static void s_wifi_scan_done_callback(void *arg, STATUS status);
324 #endif
325 
326 #ifdef USE_ESP32_FRAMEWORK_ARDUINO
327 #if ESP_IDF_VERSION_MAJOR >= 4
328  void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
329 #else
330  void wifi_event_callback_(system_event_id_t event, system_event_info_t info);
331 #endif
332  void wifi_scan_done_callback_();
333 #endif
334 #ifdef USE_ESP_IDF
335  void wifi_process_event_(IDFWiFiEvent *data);
336 #endif
337 
338 #ifdef USE_RP2040
339  static int s_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result);
340  void wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result);
341 #endif
342 
343  std::string use_address_;
344  std::vector<WiFiAP> sta_;
345  std::vector<WiFiSTAPriority> sta_priorities_;
347  bool fast_connect_{false};
348 
349  bool has_ap_{false};
352  uint32_t action_started_;
353  uint8_t num_retried_{0};
354  uint32_t last_connected_{0};
355  uint32_t reboot_timeout_{};
356  uint32_t ap_timeout_{};
358  bool error_from_callback_{false};
359  std::vector<WiFiScanResult> scan_result_;
360  bool scan_done_{false};
361  bool ap_setup_{false};
363  bool passive_scan_{false};
365  bool has_saved_wifi_settings_{false};
366 #ifdef USE_WIFI_11KV_SUPPORT
367  bool btm_{false};
368  bool rrm_{false};
369 #endif
371 };
372 
373 extern WiFiComponent *global_wifi_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
374 
375 template<typename... Ts> class WiFiConnectedCondition : public Condition<Ts...> {
376  public:
377  bool check(Ts... x) override { return global_wifi_component->is_connected(); }
378 };
379 
380 template<typename... Ts> class WiFiEnabledCondition : public Condition<Ts...> {
381  public:
382  bool check(Ts... x) override { return !global_wifi_component->is_disabled(); }
383 };
384 
385 template<typename... Ts> class WiFiEnableAction : public Action<Ts...> {
386  public:
387  void play(Ts... x) override { global_wifi_component->enable(); }
388 };
389 
390 template<typename... Ts> class WiFiDisableAction : public Action<Ts...> {
391  public:
392  void play(Ts... x) override { global_wifi_component->disable(); }
393 };
394 
395 } // namespace wifi
396 } // 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:44
float get_priority() const
void set_output_power(float output_power)
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_
WiFiComponent * global_wifi_component
optional< uint8_t > channel_
uint8_t priority
uint8_t status
Definition: bl0942.h:23
ESPPreferenceObject pref_
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
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:32