1#include "esp_wifi_client.hpp"
16constexpr uint32_t WIFI_CONNECT_TIMEOUT_MS = 15000U;
17constexpr uint32_t WIFI_DHCP_TIMEOUT_MS = 15000U;
18constexpr uint32_t WIFI_DISCONNECT_TIMEOUT_MS = 5000U;
19constexpr uint16_t MAX_SCAN_RESULTS = 20U;
21template <
typename Predicate>
22bool WaitForPredicate(Semaphore& semaphore, uint32_t timeout_ms, Predicate&& predicate)
29 if (timeout_ms == UINT32_MAX)
33 (void)semaphore.Wait(UINT32_MAX);
38 const int64_t start_us = esp_timer_get_time();
39 const int64_t timeout_us =
static_cast<int64_t
>(timeout_ms) * 1000LL;
42 const int64_t remaining_us = timeout_us - (esp_timer_get_time() - start_us);
43 if (remaining_us <= 0)
48 const uint32_t wait_ms =
static_cast<uint32_t
>((remaining_us + 999LL) / 1000LL);
49 if ((semaphore.Wait(wait_ms) !=
ErrorCode::OK) && !predicate())
57size_t BoundedStringLength(
const char* text,
size_t max_len)
59 if (text ==
nullptr)
return 0;
61 while (len < max_len && text[len] !=
'\0')
68void CopyToWifiField(uint8_t* dst,
size_t dst_size,
const char* src)
70 if (dst_size == 0)
return;
71 const size_t copy_len = BoundedStringLength(src, dst_size - 1);
74 std::memcpy(dst, src, copy_len);
79void CopyToCharField(
char* dst,
size_t dst_size,
const char* src)
81 if (dst_size == 0)
return;
82 const size_t copy_len = BoundedStringLength(src, dst_size - 1);
85 std::memcpy(dst, src, copy_len);
92ESP32WifiClient::ESP32WifiClient()
100 esp_err_t err = nvs_flash_init();
101 if ((err == ESP_ERR_NVS_NO_FREE_PAGES) || (err == ESP_ERR_NVS_NEW_VERSION_FOUND))
103 if (nvs_flash_erase() != ESP_OK)
107 err = nvs_flash_init();
114 err = esp_netif_init();
115 if ((err != ESP_OK) && (err != ESP_ERR_INVALID_STATE))
120 err = esp_event_loop_create_default();
121 if ((err != ESP_OK) && (err != ESP_ERR_INVALID_STATE))
126 netif_ = esp_netif_create_default_wifi_sta();
132 wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
133 err = esp_wifi_init(&cfg);
134 if ((err != ESP_OK) && (err != ESP_ERR_INVALID_STATE))
152 if (!RegisterHandlers())
157 if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK)
159 UnregisterHandlers();
163 ResetConnectionState();
165 if (esp_wifi_start() != ESP_OK)
167 UnregisterHandlers();
178 (void)esp_wifi_stop();
180 ResetConnectionState();
181 UnregisterHandlers();
188 ResetConnectionState();
191 wifi_config_t wifi_config{};
192 CopyToWifiField(wifi_config.sta.ssid,
sizeof(wifi_config.sta.ssid), config.
ssid);
193 CopyToWifiField(wifi_config.sta.password,
sizeof(wifi_config.sta.password),
195 if (esp_wifi_set_config(WIFI_IF_STA, &wifi_config) != ESP_OK)
199 if (esp_wifi_connect() != ESP_OK)
204 if (!WaitForPredicate(
semaphore_, WIFI_CONNECT_TIMEOUT_MS,
210 if (!WaitForPredicate(
semaphore_, WIFI_DHCP_TIMEOUT_MS,
227 if (esp_wifi_disconnect() != ESP_OK)
232 if (!WaitForPredicate(
semaphore_, WIFI_DISCONNECT_TIMEOUT_MS,
245 return IPAddressRaw::FromString(
ip_str_);
251 esp_wifi_get_mac(WIFI_IF_STA, mac);
253 std::memcpy(result.bytes, mac, 6);
265 if ((out_list ==
nullptr) && (max_count != 0U))
270 wifi_scan_config_t scan_config = {};
271 if (esp_wifi_scan_start(&scan_config,
true) != ESP_OK)
277 if (esp_wifi_scan_get_ap_num(&ap_num) != ESP_OK)
282 uint16_t copy_count = ap_num;
283 if (copy_count > max_count)
285 copy_count =
static_cast<uint16_t
>(max_count);
287 if (copy_count > MAX_SCAN_RESULTS)
289 copy_count = MAX_SCAN_RESULTS;
292 wifi_ap_record_t ap_records[MAX_SCAN_RESULTS] = {};
293 if ((copy_count > 0U) &&
294 (esp_wifi_scan_get_ap_records(©_count, ap_records) != ESP_OK))
299 out_found = copy_count;
300 for (uint16_t i = 0; i < copy_count; ++i)
302 CopyToCharField(out_list[i].ssid,
sizeof(out_list[i].ssid),
303 reinterpret_cast<const char*
>(ap_records[i].ssid));
304 out_list[i].
rssi = ap_records[i].rssi;
306 : (ap_records[i].authmode == WIFI_AUTH_WPA2_PSK)
315 int32_t event_id,
void* event_data)
319 if (event_base == WIFI_EVENT)
323 case WIFI_EVENT_STA_CONNECTED:
324 self->connected_ =
true;
325 self->semaphore_.Post();
327 case WIFI_EVENT_STA_DISCONNECTED:
328 self->connected_ =
false;
329 self->got_ip_ =
false;
330 self->ip_str_[0] =
'\0';
331 self->semaphore_.Post();
338 if (event_base == IP_EVENT)
342 case IP_EVENT_STA_GOT_IP:
344 ip_event_got_ip_t*
event =
reinterpret_cast<ip_event_got_ip_t*
>(event_data);
345 self->got_ip_ =
true;
346 esp_ip4addr_ntoa(&event->ip_info.ip, self->ip_str_,
sizeof(self->ip_str_));
347 self->semaphore_.Post();
350 case IP_EVENT_STA_LOST_IP:
351 self->got_ip_ =
false;
352 self->ip_str_[0] =
'\0';
353 self->semaphore_.Post();
365 wifi_ap_record_t ap_info;
366 if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK)
373bool ESP32WifiClient::RegisterHandlers()
375 if (handlers_registered_)
380 if ((esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
382 &wifi_connected_handler_) != ESP_OK) ||
383 (esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
385 &wifi_disconnected_handler_) != ESP_OK) ||
386 (esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &
EventHandler,
387 this, &got_ip_handler_) != ESP_OK) ||
388 (esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_LOST_IP, &
EventHandler,
389 this, &lost_ip_handler_) != ESP_OK))
391 UnregisterHandlers();
395 handlers_registered_ =
true;
399void ESP32WifiClient::UnregisterHandlers()
401 if ((wifi_connected_handler_ ==
nullptr) && (wifi_disconnected_handler_ ==
nullptr) &&
402 (got_ip_handler_ ==
nullptr) && (lost_ip_handler_ ==
nullptr))
404 handlers_registered_ =
false;
408 if (wifi_connected_handler_ !=
nullptr)
410 (void)esp_event_handler_instance_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
411 wifi_connected_handler_);
412 wifi_connected_handler_ =
nullptr;
414 if (wifi_disconnected_handler_ !=
nullptr)
416 (void)esp_event_handler_instance_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
417 wifi_disconnected_handler_);
418 wifi_disconnected_handler_ =
nullptr;
420 if (got_ip_handler_ !=
nullptr)
422 (void)esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP,
424 got_ip_handler_ =
nullptr;
426 if (lost_ip_handler_ !=
nullptr)
428 (void)esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_LOST_IP,
430 lost_ip_handler_ =
nullptr;
432 handlers_registered_ =
false;
435void ESP32WifiClient::ResetConnectionState()
442void ESP32WifiClient::DrainEvents()
ESP32 Wi-Fi 客户端实现 / ESP32 Wi-Fi client implementation.
MACAddressRaw GetMACAddress() const override
获取当前 MAC 地址 / Get MAC address
static bool is_initialized_
ESP 网络是否已初始化 / Netif initialized.
bool connected_
是否连接 / Whether WiFi is connected
IPAddressRaw GetIPAddress() const override
获取当前 IP 地址 / Get current IP address
LibXR::Semaphore semaphore_
状态同步信号量 / Event wait semaphore
WifiError Connect(const Config &config) override
连接到指定 WiFi 网络 / Connect to a WiFi network
void Disable() override
禁用网络接口(WiFi) / Disable the network interface
static esp_netif_t * netif_
ESP 默认 netif 对象 / Default netif.
bool enabled_
是否启用 / Whether WiFi is enabled
int GetRSSI() const override
获取当前 WiFi 信号强度(RSSI) / Get current signal strength
bool got_ip_
是否获取 IP / Whether IP is acquired
bool Enable() override
启用网络接口(WiFi) / Enable the network interface
WifiError Disconnect() override
断开当前 WiFi 连接 / Disconnect from the WiFi network
bool IsConnected() const override
检查是否已连接 / Check if currently connected
static void EventHandler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
事件处理回调 / Event handler callback
WifiError Scan(ScanResult *out_list, size_t max_count, size_t &out_found) override
扫描可用网络 / Scan for available WiFi networks
char ip_str_[16]
当前 IP 字符串 / Current IP string
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
@ WPA2_PSK
WPA2-PSK / WPA2-PSK.
@ UNKNOWN
未知类型 / Unknown type
@ OPEN
开放网络 / Open network
WifiError
WiFi 错误码 / Enumeration of WiFi error codes.
@ DHCP_FAILED
DHCP 获取失败 / DHCP acquisition failed.
@ INVALID_CONFIG
配置无效 / Invalid configuration
@ UNKNOWN
未知错误 / Unknown error
@ HARDWARE_FAILURE
硬件故障 / Hardware failure
@ SCAN_FAILED
扫描失败 / Scan failed
@ NOT_ENABLED
未启用 / Not enabled
@ CONNECTION_TIMEOUT
连接超时 / Connection timeout
@ OK
操作成功 | Operation successful
原始 IPv4 地址 / Raw IPv4 address
原始 MAC 地址 / Raw MAC address
WiFi 连接配置 / WiFi connection configuration.
char ssid[33]
SSID 名称 / SSID name.
char password[64]
密码 / Password
WiFi 扫描结果 / WiFi scan result.
int rssi
信号强度 / Signal strength (RSSI)
Security security
安全类型 / Security type