Skip to content

Commit

Permalink
feat: add support for WiFi scanning
Browse files Browse the repository at this point in the history
  • Loading branch information
Tasssadar committed Apr 30, 2024
1 parent 63d14e3 commit 1b97798
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 18 deletions.
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"maintainer": true
}
],
"version": "13.0.0",
"version": "13.1.0",
"frameworks": ["espidf", "arduino"],
"platforms": "espressif32"
}
33 changes: 32 additions & 1 deletion src/rbwifi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

#include <atomic>
#include <string>
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <vector>

#include "esp_wifi.h"

#if defined(ESP_IDF_VERSION_VAL)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
Expand All @@ -26,6 +31,30 @@ class WiFi {
friend class WiFiInitializer;

public:
// Results are sent to queue results. They are of type wifi_ap_record_t.
//
// Scan done can be awaited using the semaphore returned in out_scan_done_event.
// Use normal WiFi APIs, eg. esp_wifi_scan_get_ap_record to get the results.
// Example:
// SemaphoreHandle_t wifiScanDone;
// ESP_ERROR_CHECK(rb::WiFi::scanAsync(&wifiScanDone));
//
// xSemaphoreTake(wifiScanDone, portMAX_DELAY);
//
// uint16_t num;
// ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&num));
//
// printf("Found %d networks:\n", num);
//
// wifi_ap_record_t record;
// while(esp_wifi_scan_get_ap_record(&record) == ESP_OK) {
// printf(" %.32s #%d rssi %d auth %d\n",
// record.ssid, record.primary, record.rssi, record.authmode);
// }
static esp_err_t scanAsync(SemaphoreHandle_t *out_scan_done_event);

static std::vector<wifi_ap_record_t> scanSync(esp_err_t *err_out = NULL);

//!< Connect to a wifi network with given ssid (name) and password
static void connect(const char* ssid, const char* password);

Expand Down Expand Up @@ -58,7 +87,9 @@ class WiFi {
#ifndef RBPROTOCOL_USE_NETIF
static esp_err_t eventHandler_tcpip(void* ctx, system_event_t* event);
#else
static void eventHandler_netif(void* arg, esp_event_base_t event_base,
static void eventHandler_netif_wifi(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data);
static void eventHandler_netif_ip(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data);
#endif
static std::atomic<uint32_t> m_ip;
Expand Down
107 changes: 91 additions & 16 deletions src/rbwifi_netif.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "esp_wifi.h"
#include "rbwifi.h"

// This is implementation for IDF >= 4.1
#ifdef RBPROTOCOL_USE_NETIF

#include "esp_log.h"
Expand All @@ -12,7 +13,8 @@

#define TAG "RbWifi"

static esp_netif_t* gNetIf = nullptr;
static esp_netif_t *gNetIf = nullptr;
static SemaphoreHandle_t gScanDoneEv = nullptr;

namespace rb {

Expand All @@ -21,21 +23,24 @@ class WiFiInitializer {

public:
WiFiInitializer() {
ESP_ERROR_CHECK(nvs_flash_init());
//ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());

ESP_ERROR_CHECK(esp_event_loop_create_default());
auto err = esp_event_loop_create_default();
if(err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
ESP_ERROR_CHECK(err);
}

esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&WiFi::eventHandler_netif,
&WiFi::eventHandler_netif_wifi,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&WiFi::eventHandler_netif,
&WiFi::eventHandler_netif_ip,
NULL,
&instance_got_ip));

Expand All @@ -62,7 +67,7 @@ void WiFi::connect(const char* ssid, const char* pass) {
esp_wifi_stop();

if (gNetIf) {
esp_netif_destroy(gNetIf);
esp_netif_destroy_default_wifi(gNetIf);
}

gNetIf = esp_netif_create_default_wifi_sta();
Expand All @@ -83,7 +88,7 @@ void WiFi::startAp(const char* ssid, const char* pass, uint8_t channel) {
esp_wifi_stop();

if (gNetIf) {
esp_netif_destroy(gNetIf);
esp_netif_destroy_default_wifi(gNetIf);
}

gNetIf = esp_netif_create_default_wifi_ap();
Expand Down Expand Up @@ -114,17 +119,87 @@ void WiFi::startAp(const char* ssid, const char* pass, uint8_t channel) {
m_ip.store(ip_info.ip.addr);
}

void WiFi::eventHandler_netif(void* arg, esp_event_base_t event_base,
esp_err_t WiFi::scanAsync(SemaphoreHandle_t *out_scan_done_event) {
init();

if(!out_scan_done_event) {
return ESP_ERR_INVALID_ARG;
}

if(!gScanDoneEv) {
gScanDoneEv = xSemaphoreCreateBinary();
}
*out_scan_done_event = gScanDoneEv;

auto err = esp_wifi_scan_start(NULL, false);
if(err == ESP_ERR_WIFI_NOT_STARTED) {
WiFi::connect("", ""); // just start WiFi in station mode, with no target
err = esp_wifi_scan_start(NULL, false);
}

if(err != ESP_OK) {
return err;
}

return ESP_OK;
}

std::vector<wifi_ap_record_t> WiFi::scanSync(esp_err_t *err_out) {
SemaphoreHandle_t done_ev;
auto err = WiFi::scanAsync(&done_ev);
if(err_out) {
*err_out = err;
}

if(err != ESP_OK) {
return {};
}

xSemaphoreTake(done_ev, pdMS_TO_TICKS(15000));

uint16_t num = 0;
err = esp_wifi_scan_get_ap_num(&num);
if(err != ESP_OK) {
if(err_out) {
*err_out = err;
}
return {};
}

std::vector<wifi_ap_record_t> results(num);
err = esp_wifi_scan_get_ap_records(&num, results.data());
if(err_out) {
*err_out = err;
}
return results;
}

void WiFi::eventHandler_netif_wifi(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {

switch(event_id) {
case WIFI_EVENT_STA_START:
ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START");
esp_wifi_connect();
break;
case WIFI_EVENT_STA_DISCONNECTED:
m_ip.store(0);
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
esp_wifi_connect();
break;
case WIFI_EVENT_SCAN_DONE: {
if(gScanDoneEv) {
xSemaphoreGive(gScanDoneEv);
}
break;
}
}
}

void WiFi::eventHandler_netif_ip(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {

if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
m_ip.store(0);
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
esp_wifi_connect();
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
if (event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;

char buf[16];
Expand Down
12 changes: 12 additions & 0 deletions src/rbwifi_tcpip.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "esp_wifi.h"
#include "rbwifi.h"

// This is implementation for IDF < 4.1
#ifndef RBPROTOCOL_USE_NETIF

#include "esp_log.h"
Expand Down Expand Up @@ -83,6 +84,17 @@ void WiFi::startAp(const char* ssid, const char* pass, uint8_t channel) {
esp_wifi_set_bandwidth(WIFI_IF_AP, WIFI_BW_HT20);
}

esp_err_t WiFi::scanAsync(SemaphoreHandle_t *out_scan_done_event) {
return ESP_ERR_NOT_SUPPORTED;
}

std::vector<wifi_ap_record_t> WiFi::scanSync(esp_err_t *err_out) {
if(err_out) {
*err_out = ESP_ERR_NOT_SUPPORTED;
}
return {};
}

esp_err_t WiFi::eventHandler_tcpip(void* ctx, system_event_t* event) {
switch (event->event_id) {
case SYSTEM_EVENT_STA_START:
Expand Down

0 comments on commit 1b97798

Please sign in to comment.