feat(wifi) save credential on successful connection and auto connect to it
This commit is contained in:
parent
a4d65c367d
commit
6fdfa76a14
|
@ -0,0 +1,7 @@
|
|||
file(GLOB SOURCES *.c)
|
||||
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCES}
|
||||
INCLUDE_DIRS "."
|
||||
)
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef LIST_H_GUARD
|
||||
#define LIST_H_GUARD
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* struct dl_list - Doubly-linked list
|
||||
*/
|
||||
struct dl_list {
|
||||
struct dl_list *next;
|
||||
struct dl_list *prev;
|
||||
};
|
||||
|
||||
static inline void dl_list_init(struct dl_list *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
static inline void dl_list_add(struct dl_list *list, struct dl_list *item)
|
||||
{
|
||||
item->next = list->next;
|
||||
item->prev = list;
|
||||
list->next->prev = item;
|
||||
list->next = item;
|
||||
}
|
||||
|
||||
static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item)
|
||||
{
|
||||
dl_list_add(list->prev, item);
|
||||
}
|
||||
|
||||
static inline void dl_list_del(struct dl_list *item)
|
||||
{
|
||||
item->next->prev = item->prev;
|
||||
item->prev->next = item->next;
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
}
|
||||
|
||||
static inline int dl_list_empty(struct dl_list *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
static inline unsigned int dl_list_len(struct dl_list *list)
|
||||
{
|
||||
struct dl_list *item;
|
||||
int count = 0;
|
||||
for (item = list->next; item != list; item = item->next)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ((long) &((type *) 0)->member)
|
||||
#endif
|
||||
|
||||
#define dl_list_entry(item, type, member) \
|
||||
((type *) ((char *) item - offsetof(type, member)))
|
||||
|
||||
#define dl_list_first(list, type, member) \
|
||||
(dl_list_empty((list)) ? NULL : \
|
||||
dl_list_entry((list)->next, type, member))
|
||||
|
||||
#define dl_list_last(list, type, member) \
|
||||
(dl_list_empty((list)) ? NULL : \
|
||||
dl_list_entry((list)->prev, type, member))
|
||||
|
||||
#define dl_list_for_each(item, list, type, member) \
|
||||
for (item = dl_list_entry((list)->next, type, member); \
|
||||
&item->member != (list); \
|
||||
item = dl_list_entry(item->member.next, type, member))
|
||||
|
||||
#define dl_list_for_each_safe(item, n, list, type, member) \
|
||||
for (item = dl_list_entry((list)->next, type, member), \
|
||||
n = dl_list_entry(item->member.next, type, member); \
|
||||
&item->member != (list); \
|
||||
item = n, n = dl_list_entry(n->member.next, type, member))
|
||||
|
||||
#define dl_list_for_each_reverse(item, list, type, member) \
|
||||
for (item = dl_list_entry((list)->prev, type, member); \
|
||||
&item->member != (list); \
|
||||
item = dl_list_entry(item->member.prev, type, member))
|
||||
|
||||
#define DEFINE_DL_LIST(name) \
|
||||
struct dl_list name = { &(name), &(name) }
|
||||
|
||||
#endif //LIST_H_GUARD
|
|
@ -26,13 +26,13 @@ _Noreturn void req_long_task(void *arg)
|
|||
if (unlikely(xQueueReceive(long_run_queue, &req, portMAX_DELAY) != pdTRUE)) {
|
||||
continue;
|
||||
}
|
||||
int status = req->module.helper_cb(req->module.arg);
|
||||
req->status = req->module.helper_cb(req->module.arg);
|
||||
|
||||
/* if send out queue is busy, set status and let the cb to cancel send out
|
||||
* */
|
||||
if (req_queue_push_send_out(req, pdMS_TO_TICKS(20)) != 0) {
|
||||
status = -1;
|
||||
req->send_out.cb(req->send_out.arg, status);
|
||||
req->status = -1;
|
||||
req->send_out.cb(req->send_out.arg, req->status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ _Noreturn void req_send_out_task(void *arg)
|
|||
req_task_cb_t *req;
|
||||
while (1) {
|
||||
if (likely(xQueueReceive(send_out_queue, &req, portMAX_DELAY))) {
|
||||
req->send_out.cb(req->send_out.arg, 0);
|
||||
req->send_out.cb(req->send_out.arg, req->status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ typedef struct req_module_cb_t {
|
|||
typedef struct req_task_cb_t {
|
||||
req_module_cb_t module;
|
||||
req_send_out_cb_t send_out;
|
||||
int status;
|
||||
} req_task_cb_t;
|
||||
|
||||
int request_runner_init();
|
||||
|
|
|
@ -20,7 +20,7 @@ typedef struct post_request_t {
|
|||
} post_request_t;
|
||||
|
||||
static void async_send_out_cb(void *arg, int module_status);
|
||||
static int uri_api_send_out(httpd_req_t *req, post_request_t *post_req);
|
||||
static int uri_api_send_out(httpd_req_t *req, post_request_t *post_req, int err);
|
||||
|
||||
|
||||
static esp_err_t api_post_handler(httpd_req_t *req)
|
||||
|
@ -87,7 +87,7 @@ static esp_err_t api_post_handler(httpd_req_t *req)
|
|||
}
|
||||
|
||||
/* api function returns something, send back to http client */
|
||||
err = uri_api_send_out(req, post_req);
|
||||
err = uri_api_send_out(req, post_req, 0);
|
||||
goto put_buf;
|
||||
|
||||
end:
|
||||
|
@ -101,19 +101,21 @@ put_buf:
|
|||
return err;
|
||||
}
|
||||
|
||||
int uri_api_send_out(httpd_req_t *req, post_request_t *post_req)
|
||||
int uri_api_send_out(httpd_req_t *req, post_request_t *post_req, int err)
|
||||
{
|
||||
int err;
|
||||
char *buf;
|
||||
uint32_t buf_len;
|
||||
|
||||
buf = post_req->buf;
|
||||
buf_len = static_buffer_get_buf_size() - sizeof(post_request_t);
|
||||
|
||||
httpd_resp_set_type(req, HTTPD_TYPE_JSON);
|
||||
err = !cJSON_PrintPreallocated(post_req->json.out, buf, buf_len - 5, 0);
|
||||
cJSON_Delete(post_req->json.out);
|
||||
cJSON_Delete(post_req->json.in);
|
||||
if (post_req->json.out) {
|
||||
ESP_LOGI(TAG, "json out ok");
|
||||
httpd_resp_set_type(req, HTTPD_TYPE_JSON);
|
||||
err = !cJSON_PrintPreallocated(post_req->json.out, buf, buf_len - 5, 0);
|
||||
cJSON_Delete(post_req->json.out);
|
||||
}
|
||||
|
||||
if (unlikely(err)) {
|
||||
httpd_resp_set_status(req, HTTPD_500);
|
||||
return httpd_resp_send(req, NULL, 0);
|
||||
|
@ -126,11 +128,13 @@ void async_send_out_cb(void *arg, int module_status)
|
|||
{
|
||||
post_request_t *req = arg;
|
||||
if (module_status != API_JSON_OK) {
|
||||
httpd_sess_trigger_close(req->req_out->handle,
|
||||
httpd_req_to_sockfd(req->req_out->handle));
|
||||
/* BUG: httpd_req_to_sockfd cause crash, fd not closed for the moment
|
||||
* issue is opened on esp-idf github */
|
||||
// httpd_sess_trigger_close(req->req_out->handle,
|
||||
// httpd_req_to_sockfd(req->req_out->handle));
|
||||
}
|
||||
|
||||
uri_api_send_out(req->req_out, req);
|
||||
uri_api_send_out(req->req_out, req, module_status);
|
||||
|
||||
/* clean resources */
|
||||
httpd_req_async_handler_complete(req->req_out);
|
||||
|
@ -150,7 +154,6 @@ static const httpd_uri_t uri_api = {
|
|||
|
||||
static int URI_API_INIT(const httpd_uri_t **uri_conf) {
|
||||
*uri_conf = &uri_api;
|
||||
api_json_router_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,13 +136,11 @@ static const httpd_uri_t uri_api = {
|
|||
.user_ctx = NULL,
|
||||
.is_websocket = true,
|
||||
.supported_subprotocol = NULL,
|
||||
/* in esp-idf v5.2.0, set to false cause infinite queue_work fail on wifi disconnect when at least 1 ws client */
|
||||
.handle_ws_control_frames = true,
|
||||
};
|
||||
|
||||
static int WS_REQ_INIT(const httpd_uri_t **uri_conf) {
|
||||
*uri_conf = &uri_api;
|
||||
api_json_router_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,14 @@ file(GLOB SOURCES
|
|||
wifi_api_json.c
|
||||
wifi_api.c
|
||||
wifi_json_utils.c
|
||||
wifi_storage.c
|
||||
)
|
||||
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCES}
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES mdns esp_wifi esp_event api_router
|
||||
PRIV_REQUIRES mdns esp_wifi esp_event api_router wt_storage
|
||||
)
|
||||
|
||||
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)
|
||||
|
|
|
@ -27,9 +27,6 @@ static int rssi_comp(const void *a, const void *b)
|
|||
|
||||
/**
|
||||
* @brief blocking function
|
||||
* @param number
|
||||
* @param ap_info
|
||||
* @return
|
||||
*/
|
||||
int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_info_t *ap_info)
|
||||
{
|
||||
|
@ -76,13 +73,12 @@ static void wifi_manager_scan_done(uint16_t ap_found, wifi_ap_record_t *records,
|
|||
scan_done_cb(ap_found, ap_info, arg);
|
||||
}
|
||||
|
||||
int wifi_api_trigger_scan(uint16_t *max_ap_count, wifi_api_scan_done_cb cb, void *cb_arg)
|
||||
int wifi_api_connect(const char *ssid, const char *password)
|
||||
{
|
||||
int err;
|
||||
err = wifi_manager_trigger_scan(wifi_manager_scan_done, cb_arg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
scan_done_cb = cb;
|
||||
return 0;
|
||||
return wifi_manager_connect(ssid, password);
|
||||
}
|
||||
|
||||
int wifi_api_disconnect(void)
|
||||
{
|
||||
return wifi_manager_disconnect();
|
||||
}
|
||||
|
|
|
@ -20,5 +20,9 @@ int wifi_api_trigger_scan(uint16_t *max_ap_count, wifi_api_scan_done_cb cb, void
|
|||
|
||||
int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_info_t *ap_info);
|
||||
|
||||
int wifi_api_connect(const char *ssid, const char *password);
|
||||
|
||||
int wifi_api_disconnect(void);
|
||||
|
||||
|
||||
#endif //WIFI_API_H_GUARD
|
|
@ -10,34 +10,44 @@ static int wifi_api_json_get_ap_info(api_json_req_t *req);
|
|||
|
||||
static int wifi_api_json_get_scan(api_json_req_t *req);
|
||||
|
||||
static int on_async_call(void *arg)
|
||||
static int wifi_api_json_connect(api_json_req_t *req);
|
||||
|
||||
static int wifi_api_json_disconnect(api_json_req_t *req);
|
||||
|
||||
|
||||
static int async_helper_cb(void *arg)
|
||||
{
|
||||
api_json_module_req_t *req = arg;
|
||||
return req->func(req->arg);
|
||||
}
|
||||
|
||||
static inline int set_async(api_json_req_t *req, api_json_module_async_t *async, int (*func)(api_json_req_t *))
|
||||
{
|
||||
async->module.func = func;
|
||||
async->module.arg = req;
|
||||
async->req_task.module.helper_cb = async_helper_cb;
|
||||
async->req_task.module.arg = &async->module;
|
||||
return API_JSON_ASYNC;
|
||||
}
|
||||
|
||||
static int on_json_req(uint16_t cmd, api_json_req_t *req, api_json_module_async_t *async)
|
||||
{
|
||||
wifi_api_json_cmd_t wifi_cmd = cmd;
|
||||
switch (wifi_cmd) {
|
||||
case WIFI_API_JSON_GET_AP_INFO:
|
||||
return wifi_api_json_get_ap_info(req);
|
||||
case WIFI_API_JSON_CONNECT:
|
||||
|
||||
break;
|
||||
case WIFI_API_JSON_GET_SCAN:
|
||||
async->module.func = wifi_api_json_get_scan;
|
||||
async->module.arg = req;
|
||||
async->req_task.module.helper_cb = on_async_call;
|
||||
async->req_task.module.arg = &async->module;
|
||||
return API_JSON_ASYNC;
|
||||
case UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
case WIFI_API_JSON_GET_AP_INFO:
|
||||
return wifi_api_json_get_ap_info(req);
|
||||
case WIFI_API_JSON_CONNECT:
|
||||
return set_async(req, async, wifi_api_json_connect);
|
||||
case WIFI_API_JSON_GET_SCAN:
|
||||
return set_async(req, async, wifi_api_json_get_scan);
|
||||
case WIFI_API_JSON_DISCONNECT:
|
||||
return wifi_api_json_disconnect(req);
|
||||
}
|
||||
|
||||
printf("cmd %d\n", cmd);
|
||||
|
||||
printf("cmd %d not executed\n", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -70,6 +80,26 @@ static int wifi_api_json_get_scan(api_json_req_t *req)
|
|||
}
|
||||
|
||||
|
||||
int wifi_api_json_connect(api_json_req_t *req)
|
||||
{
|
||||
char *ssid;
|
||||
char *password;
|
||||
|
||||
ssid = cJSON_GetStringValue(cJSON_GetObjectItem(req->in, "ssid"));
|
||||
password = cJSON_GetStringValue(cJSON_GetObjectItem(req->in, "password"));
|
||||
if (ssid == NULL || password == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("trigger connect\n");
|
||||
return wifi_api_connect(ssid, password);
|
||||
};
|
||||
|
||||
int wifi_api_json_disconnect(api_json_req_t *req)
|
||||
{
|
||||
return wifi_api_disconnect();
|
||||
}
|
||||
|
||||
/* ****
|
||||
* register module
|
||||
* */
|
||||
|
@ -81,6 +111,6 @@ static int wifi_api_json_init(api_json_module_cfg_t *cfg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
API_JSON_MODULE_REGISTER(0x90, wifi_api_json_init);
|
||||
API_JSON_MODULE_REGISTER(0x90, wifi_api_json_init)
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ typedef enum wifi_api_json_cmd_t {
|
|||
WIFI_API_JSON_GET_AP_INFO,
|
||||
WIFI_API_JSON_CONNECT,
|
||||
WIFI_API_JSON_GET_SCAN,
|
||||
WIFI_API_JSON_DISCONNECT,
|
||||
|
||||
} wifi_api_json_cmd_t;
|
||||
|
||||
|
|
|
@ -44,42 +44,52 @@ void ip_event_handler(void *handler_arg __attribute__((unused)),
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct wifi_scan_ctx_t {
|
||||
wifi_ap_record_t *ap;
|
||||
wifi_event_scan_done_cb cb;
|
||||
uint16_t number;
|
||||
} wifi_scan_ctx_t;
|
||||
typedef struct wifi_event_ctx_t {
|
||||
/* WIFI scan */
|
||||
struct {
|
||||
wifi_ap_record_t *ap;
|
||||
wifi_event_scan_done_cb cb;
|
||||
uint16_t number;
|
||||
};
|
||||
/* WIFI connect */
|
||||
struct {
|
||||
wifi_event_connect_done_cb cb;
|
||||
void *arg;
|
||||
void (*disconn_handler)(void);
|
||||
uint8_t attempt;
|
||||
} conn;
|
||||
uint8_t is_connected;
|
||||
} wifi_event_ctx_t;
|
||||
|
||||
static wifi_scan_ctx_t scan_ctx = {
|
||||
static wifi_event_ctx_t event_ctx = {
|
||||
.ap = NULL,
|
||||
.is_connected = 0,
|
||||
.conn.disconn_handler = NULL,
|
||||
};
|
||||
|
||||
static void wifi_on_scan_done(wifi_event_sta_scan_done_t *event)
|
||||
{
|
||||
int err;
|
||||
if (!scan_ctx.cb || !scan_ctx.ap) {
|
||||
scan_ctx.number = 0;
|
||||
if (!event_ctx.cb || !event_ctx.ap) {
|
||||
event_ctx.number = 0;
|
||||
} else if (event->status == 1) {
|
||||
/* error */
|
||||
scan_ctx.number = 0;
|
||||
event_ctx.number = 0;
|
||||
} else if (event->number == 0) {
|
||||
/* no ap found on current channel */
|
||||
scan_ctx.number = 0;
|
||||
event_ctx.number = 0;
|
||||
}
|
||||
|
||||
err = esp_wifi_scan_get_ap_records(&scan_ctx.number, scan_ctx.ap);
|
||||
if (err) {
|
||||
esp_wifi_clear_ap_list();
|
||||
}
|
||||
esp_wifi_scan_get_ap_records(&event_ctx.number, event_ctx.ap);
|
||||
esp_wifi_clear_ap_list();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < scan_ctx.number; ++i) {
|
||||
if (scan_ctx.ap[i].rssi < -80)
|
||||
for (i = 0; i < event_ctx.number; ++i) {
|
||||
if (event_ctx.ap[i].rssi < -80)
|
||||
break;
|
||||
}
|
||||
|
||||
scan_ctx.number = i;
|
||||
return scan_ctx.cb(scan_ctx.number, scan_ctx.ap);
|
||||
event_ctx.number = i;
|
||||
return event_ctx.cb(event_ctx.number, event_ctx.ap);
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,12 +118,20 @@ int wifi_event_trigger_scan(uint8_t channel, wifi_event_scan_done_cb cb, uint16_
|
|||
return err;
|
||||
}
|
||||
|
||||
scan_ctx.cb = cb;
|
||||
scan_ctx.number = number;
|
||||
scan_ctx.ap = aps;
|
||||
event_ctx.cb = cb;
|
||||
event_ctx.number = number;
|
||||
event_ctx.ap = aps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* WIFI EVENT
|
||||
* */
|
||||
|
||||
static void reconnect_after_disco();
|
||||
|
||||
void event_on_connected(wifi_event_sta_connected_t *event);
|
||||
|
||||
void wifi_event_handler(void *handler_arg __attribute__((unused)),
|
||||
esp_event_base_t event_base __attribute__((unused)),
|
||||
int32_t event_id,
|
||||
|
@ -128,13 +146,12 @@ void wifi_event_handler(void *handler_arg __attribute__((unused)),
|
|||
// printf("event: WIFI_EVENT_SCAN_DONE: ok: %lu, nr: %u, seq: %u\n",
|
||||
// event->status, event->number, event->scan_id);
|
||||
wifi_on_scan_done(event);
|
||||
scan_ctx.ap = NULL;
|
||||
scan_ctx.cb = NULL;
|
||||
event_ctx.ap = NULL;
|
||||
event_ctx.cb = NULL;
|
||||
break;
|
||||
}
|
||||
case WIFI_EVENT_STA_START:
|
||||
printf("event: WIFI_EVENT_STA_START\n");
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case WIFI_EVENT_STA_CONNECTED: {
|
||||
wifi_event_sta_connected_t *event = event_data;
|
||||
|
@ -145,6 +162,8 @@ void wifi_event_handler(void *handler_arg __attribute__((unused)),
|
|||
#ifdef CONFIG_EXAMPLE_IPV6
|
||||
tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA);
|
||||
#endif
|
||||
event_ctx.is_connected = 1;
|
||||
event_on_connected(event);
|
||||
break;
|
||||
}
|
||||
case WIFI_EVENT_STA_DISCONNECTED: {
|
||||
|
@ -153,8 +172,8 @@ void wifi_event_handler(void *handler_arg __attribute__((unused)),
|
|||
printf("event: WIFI_EVENT_STA_DISCONNECTED ");
|
||||
printf("sta %02X:%02X:%02X:%02X:%02X:%02X disconnect reason %d\n",
|
||||
m[0], m[1], m[2], m[3], m[4], m[5], event->reason);
|
||||
/* auto reconnect after disconnection */
|
||||
esp_wifi_connect();
|
||||
event_ctx.is_connected = 0;
|
||||
reconnect_after_disco();
|
||||
break;
|
||||
}
|
||||
case WIFI_EVENT_AP_START:
|
||||
|
@ -181,3 +200,65 @@ void wifi_event_handler(void *handler_arg __attribute__((unused)),
|
|||
}
|
||||
}
|
||||
|
||||
void wifi_event_set_disco_handler(void (*disconn_handler)(void))
|
||||
{
|
||||
event_ctx.conn.disconn_handler = disconn_handler;
|
||||
}
|
||||
|
||||
int wifi_event_trigger_connect(uint8_t attempt, wifi_event_connect_done_cb cb, void *arg)
|
||||
{
|
||||
int err;
|
||||
event_ctx.conn.attempt = attempt;
|
||||
event_ctx.conn.cb = cb;
|
||||
event_ctx.conn.arg = arg;
|
||||
if (event_ctx.is_connected) {
|
||||
err = esp_wifi_disconnect();
|
||||
} else {
|
||||
err = esp_wifi_connect();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void event_on_connected(wifi_event_sta_connected_t *event)
|
||||
{
|
||||
if (event_ctx.conn.cb) {
|
||||
event_ctx.conn.cb(event_ctx.conn.arg, event);
|
||||
}
|
||||
event_ctx.conn.attempt = 0;
|
||||
event_ctx.conn.cb = NULL;
|
||||
event_ctx.conn.arg = NULL;
|
||||
}
|
||||
|
||||
void reconnect_after_disco()
|
||||
{
|
||||
int err;
|
||||
|
||||
ESP_LOGI(TAG, "reco... atempt %d", event_ctx.conn.attempt);
|
||||
|
||||
if (event_ctx.conn.attempt == 0) {
|
||||
goto call;
|
||||
}
|
||||
|
||||
err = esp_wifi_connect();
|
||||
if (err) {
|
||||
event_ctx.conn.attempt = 0;
|
||||
/* connect err: stop connect and call cb */
|
||||
ESP_LOGE(TAG, "wifi connect error %s", esp_err_to_name(err));
|
||||
goto call;
|
||||
}
|
||||
|
||||
event_ctx.conn.attempt--;
|
||||
return;
|
||||
|
||||
call:
|
||||
if (event_ctx.conn.cb) {
|
||||
event_ctx.conn.cb(event_ctx.conn.arg, NULL);
|
||||
} else {
|
||||
/* disconnected from extern environment, notify */
|
||||
if (event_ctx.conn.disconn_handler) {
|
||||
event_ctx.conn.disconn_handler();
|
||||
}
|
||||
}
|
||||
event_ctx.conn.cb = NULL;
|
||||
event_ctx.conn.arg = NULL;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,17 @@ void ip_event_handler(void *handler_arg, esp_event_base_t event_base, int32_t ev
|
|||
|
||||
void wifi_event_handler(void *handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
|
||||
|
||||
typedef void (*wifi_event_scan_done_cb)(uint16_t ap_count, wifi_ap_record_t *aps_info);
|
||||
|
||||
int wifi_event_trigger_scan(uint8_t channel, wifi_event_scan_done_cb cb, uint16_t number, wifi_ap_record_t *aps);
|
||||
void wifi_event_set_disco_handler(void (*disconn_handler)(void));
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param connect_status 0: SUCCESS, OTHER: ERROR
|
||||
*/
|
||||
typedef void (*wifi_event_connect_done_cb)(void *arg, wifi_event_sta_connected_t *event);
|
||||
int wifi_event_trigger_connect(uint8_t attempt, wifi_event_connect_done_cb cb, void *arg);
|
||||
|
||||
|
||||
#endif //WIFI_EVENT_HANDLER_H_GUARD
|
|
@ -1,6 +1,7 @@
|
|||
#include "wifi_manager.h"
|
||||
#include "wifi_configuration.h"
|
||||
#include "wifi_event_handler.h"
|
||||
#include "wifi_storage.h"
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <esp_netif.h>
|
||||
|
@ -16,26 +17,41 @@
|
|||
|
||||
#define TAG __FILENAME__
|
||||
|
||||
typedef struct wifi_scan_ctx_t {
|
||||
wifi_ap_record_t *ap;
|
||||
wifi_manager_scan_done_cb cb;
|
||||
void *arg;
|
||||
typedef struct wifi_ctx_t {
|
||||
SemaphoreHandle_t lock;
|
||||
TaskHandle_t task;
|
||||
uint16_t total_aps;
|
||||
uint16_t nr_aps_in_channel;
|
||||
uint8_t status;
|
||||
uint8_t max_ap;
|
||||
} wifi_scan_ctx_t;
|
||||
union {
|
||||
struct {
|
||||
wifi_ap_record_t *ap;
|
||||
wifi_manager_scan_done_cb cb;
|
||||
void *arg;
|
||||
uint16_t total_aps;
|
||||
uint16_t nr_aps_in_channel;
|
||||
uint8_t max_ap;
|
||||
} scan;
|
||||
struct {
|
||||
wifi_event_sta_connected_t *event;
|
||||
uint8_t need_unlock; /* used when trigger connection from wifi_manager instead of wifi_api */
|
||||
} conn;
|
||||
};
|
||||
uint8_t is_endless_connect:1;
|
||||
uint8_t auto_reconnect:1;
|
||||
uint8_t reserved:6;
|
||||
} wifi_ctx_t;
|
||||
|
||||
static esp_netif_t *ap_netif;
|
||||
static esp_netif_t *sta_netif;
|
||||
|
||||
static wifi_scan_ctx_t scan_ctx;
|
||||
static wifi_ctx_t ctx;
|
||||
|
||||
static void set_sta_cred(const char *ssid, const char *password);
|
||||
static void disconn_handler(void);
|
||||
static int set_default_sta_cred(void);
|
||||
|
||||
void wifi_manager_init(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint8_t do_connect = 0;
|
||||
|
||||
ap_netif = esp_netif_create_default_wifi_ap();
|
||||
assert(ap_netif);
|
||||
|
@ -54,26 +70,21 @@ void wifi_manager_init(void)
|
|||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||
|
||||
wifi_config_t ap_config = {0};
|
||||
{
|
||||
wifi_config_t ap_config = {0};
|
||||
|
||||
strncpy((char *) ap_config.ap.ssid, WIFI_DEFAULT_AP_SSID, 32);
|
||||
strncpy((char *) ap_config.ap.password, WIFI_DEFAULT_AP_PASS, 64);
|
||||
ap_config.ap.authmode = WIFI_AUTH_WPA2_WPA3_PSK;
|
||||
ap_config.ap.max_connection = 4;
|
||||
ap_config.ap.channel = 6;
|
||||
ap_config.ap.ssid_hidden = 0;
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
strncpy((char *) ap_config.ap.ssid, WIFI_DEFAULT_AP_SSID, 32);
|
||||
strncpy((char *) ap_config.ap.password, WIFI_DEFAULT_AP_PASS, 64);
|
||||
ap_config.ap.authmode = WIFI_AUTH_WPA2_WPA3_PSK;
|
||||
ap_config.ap.max_connection = 4;
|
||||
ap_config.ap.channel = 6;
|
||||
ap_config.ap.ssid_hidden = 0;
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
}
|
||||
|
||||
// TODO: scan once and connect to known wifi
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = WIFI_DEFAULT_STA_SSID,
|
||||
.password = WIFI_DEFAULT_STA_PASS,
|
||||
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
if (set_default_sta_cred() == 0) {
|
||||
do_connect = 1;
|
||||
}
|
||||
|
||||
/* TODO: Read from nvs */
|
||||
esp_netif_ip_info_t ip_info;
|
||||
|
@ -96,35 +107,42 @@ void wifi_manager_init(void)
|
|||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
ESP_LOGI(TAG, "wifi started");
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
|
||||
scan_ctx.lock = xSemaphoreCreateBinary();
|
||||
scan_ctx.status = 0;
|
||||
xSemaphoreGive(scan_ctx.lock);
|
||||
ctx.lock = xSemaphoreCreateBinary();
|
||||
ctx.is_endless_connect = 0;
|
||||
ctx.auto_reconnect = 1;
|
||||
xSemaphoreGive(ctx.lock);
|
||||
|
||||
wifi_event_set_disco_handler(disconn_handler);
|
||||
if (do_connect) {
|
||||
disconn_handler();
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_event_scan_channel_done(uint16_t number, wifi_ap_record_t *aps)
|
||||
{
|
||||
scan_ctx.nr_aps_in_channel = number;
|
||||
scan_ctx.total_aps += number;
|
||||
if (scan_ctx.task) {
|
||||
xTaskNotifyGive(scan_ctx.task);
|
||||
ctx.scan.nr_aps_in_channel = number;
|
||||
ctx.scan.total_aps += number;
|
||||
if (ctx.task) {
|
||||
xTaskNotifyGive(ctx.task);
|
||||
}
|
||||
}
|
||||
|
||||
static void scan_loop()
|
||||
static int scan_loop()
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t number;
|
||||
|
||||
scan_ctx.total_aps = 0;
|
||||
ctx.scan.total_aps = 0;
|
||||
|
||||
for (int scan_channel = 1; scan_channel <= 13; ++scan_channel) {
|
||||
number = scan_ctx.max_ap - scan_ctx.total_aps;
|
||||
number = ctx.scan.max_ap - ctx.scan.total_aps;
|
||||
if (wifi_event_trigger_scan(scan_channel,
|
||||
wifi_event_scan_channel_done, number,
|
||||
&scan_ctx.ap[scan_ctx.total_aps])) {
|
||||
&ctx.scan.ap[ctx.scan.total_aps])) {
|
||||
ESP_LOGE(TAG, "trigger scan %d error", scan_channel);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
/* shadow wifi_event_scan_channel_done() called */
|
||||
vTaskDelay(100);
|
||||
|
@ -133,59 +151,51 @@ static void scan_loop()
|
|||
if (ret == 0) {
|
||||
/* timeout */
|
||||
ESP_LOGE(TAG, "scan channel %d timeout", scan_channel);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_manager_scan_task(void *arg)
|
||||
{
|
||||
scan_loop();
|
||||
free(scan_ctx.ap);
|
||||
/* callback */
|
||||
if (scan_ctx.cb) {
|
||||
scan_ctx.cb(scan_ctx.total_aps, scan_ctx.ap, arg);
|
||||
}
|
||||
xSemaphoreGive(scan_ctx.lock);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
int wifi_manager_trigger_scan(wifi_manager_scan_done_cb cb, void *arg)
|
||||
{
|
||||
if (xSemaphoreTake(scan_ctx.lock, pdMS_TO_TICKS(0)) != pdTRUE) {
|
||||
return 1;
|
||||
}
|
||||
/* TODO: let API allocate ? */
|
||||
scan_ctx.ap = malloc(sizeof(wifi_scan_ctx_t) * 32);
|
||||
if (scan_ctx.ap == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
scan_ctx.cb = cb;
|
||||
scan_ctx.arg = arg;
|
||||
scan_ctx.max_ap = 32;
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, 0);
|
||||
xTaskCreatePinnedToCore(wifi_manager_scan_task, "scan task", 4 * 1024,
|
||||
arg, 7, &scan_ctx.task, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_manager_get_scan_list(uint16_t *number, wifi_ap_record_t *aps)
|
||||
{
|
||||
if (xSemaphoreTake(scan_ctx.lock, pdMS_TO_TICKS(0)) != pdTRUE) {
|
||||
return 1;
|
||||
int err;
|
||||
int broke_endless_connect = 0;
|
||||
if (xSemaphoreTake(ctx.lock, pdMS_TO_TICKS(0)) != pdTRUE) {
|
||||
if (ctx.is_endless_connect == 0) {
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "deleting connecting %p", ctx.task);
|
||||
vTaskDelete(ctx.task);
|
||||
/* in case lock is released when deleting the task */
|
||||
xSemaphoreTake(ctx.lock, pdMS_TO_TICKS(0));
|
||||
esp_wifi_disconnect();
|
||||
ctx.is_endless_connect = 0;
|
||||
broke_endless_connect = 1;
|
||||
|
||||
} else if (ctx.is_endless_connect == 1) {
|
||||
ESP_LOGI(TAG, "deleting delay %p", ctx.task);
|
||||
vTaskDelete(ctx.task);
|
||||
ctx.is_endless_connect = 0;
|
||||
broke_endless_connect = 1;
|
||||
}
|
||||
|
||||
scan_ctx.ap = aps;
|
||||
scan_ctx.max_ap = *number;
|
||||
scan_ctx.cb = NULL;
|
||||
scan_ctx.task = xTaskGetCurrentTaskHandle();
|
||||
ctx.scan.ap = aps;
|
||||
ctx.scan.max_ap = *number;
|
||||
ctx.scan.cb = NULL;
|
||||
ctx.task = xTaskGetCurrentTaskHandle();
|
||||
|
||||
scan_loop();
|
||||
xSemaphoreGive(scan_ctx.lock);
|
||||
*number = scan_ctx.total_aps;
|
||||
return 0;
|
||||
err = scan_loop();
|
||||
xSemaphoreGive(ctx.lock);
|
||||
*number = ctx.scan.total_aps;
|
||||
|
||||
if (broke_endless_connect) {
|
||||
if (set_default_sta_cred() == 0) {
|
||||
disconn_handler();
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void *wifi_manager_get_ap_netif()
|
||||
|
@ -197,3 +207,147 @@ void *wifi_manager_get_sta_netif()
|
|||
{
|
||||
return sta_netif;
|
||||
}
|
||||
|
||||
|
||||
static void try_connect_done(void *arg, wifi_event_sta_connected_t *event)
|
||||
{
|
||||
ctx.conn.event = event;
|
||||
if (ctx.task) {
|
||||
xTaskNotifyGive(ctx.task);
|
||||
}
|
||||
if (ctx.conn.need_unlock) {
|
||||
ctx.conn.need_unlock = 0;
|
||||
xSemaphoreGive(ctx.lock);
|
||||
}
|
||||
ESP_LOGI(TAG, "event done %p", ctx.task);
|
||||
}
|
||||
|
||||
int set_default_sta_cred()
|
||||
{
|
||||
int err;
|
||||
wifi_credential_t credential;
|
||||
err = wifi_data_get_last_conn_cred(&credential);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
set_sta_cred(credential.ssid, credential.password);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_manager_connect(const char *ssid, const char *password)
|
||||
{
|
||||
if (xSemaphoreTake(ctx.lock, pdMS_TO_TICKS(0)) != pdTRUE) {
|
||||
if (ctx.is_endless_connect == 0) {
|
||||
return 1;
|
||||
}
|
||||
vTaskDelete(ctx.task);
|
||||
ctx.is_endless_connect = 0;
|
||||
}
|
||||
int ret;
|
||||
set_sta_cred(ssid, password);
|
||||
|
||||
ctx.task = xTaskGetCurrentTaskHandle();
|
||||
ctx.auto_reconnect = 1;
|
||||
|
||||
wifi_event_trigger_connect(2, try_connect_done, NULL);
|
||||
ret = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10000));
|
||||
|
||||
xSemaphoreGive(ctx.lock);
|
||||
if (ret == 0 || ctx.conn.event == NULL) {
|
||||
ESP_LOGI(TAG, "conn error");
|
||||
if (set_default_sta_cred() == 0) {
|
||||
disconn_handler();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
wifi_credential_t credential;
|
||||
memcpy(credential.ssid, ssid, 32);
|
||||
memcpy(credential.password, password, 64);
|
||||
ret = wifi_save_ap_credential(&credential);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "nvs save error: %s", esp_err_to_name(ret));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_sta_cred(const char *ssid, const char *password)
|
||||
{
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.threshold.rssi = -80,
|
||||
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
|
||||
},
|
||||
};
|
||||
memcpy((char *) wifi_config.sta.ssid, ssid, 32);
|
||||
memcpy((char *) wifi_config.sta.password, password, 64);
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
}
|
||||
|
||||
static void reconnection_task(void *arg)
|
||||
{
|
||||
int err;
|
||||
|
||||
ctx.is_endless_connect = 1;
|
||||
ctx.task = xTaskGetCurrentTaskHandle();
|
||||
|
||||
do {
|
||||
ESP_LOGI(TAG, "reco task: try connect, task %p", xTaskGetCurrentTaskHandle());
|
||||
err = wifi_event_trigger_connect(0, try_connect_done, NULL);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "trigger connect err: %s", esp_err_to_name(err));
|
||||
break;
|
||||
}
|
||||
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(20000));
|
||||
if (ctx.conn.event || ctx.auto_reconnect == 0) {
|
||||
/* reconnection successful or stop reconnect */
|
||||
break;
|
||||
}
|
||||
|
||||
/* long wait to not spam try to reconnect */
|
||||
xSemaphoreGive(ctx.lock);
|
||||
ESP_LOGI(TAG, "retry connection in 5 seconds");
|
||||
vTaskDelay(pdMS_TO_TICKS(5 * 1000));
|
||||
if (xSemaphoreTake(ctx.lock, pdMS_TO_TICKS(0)) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "reconnection failed");
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
ctx.is_endless_connect = 0;
|
||||
xSemaphoreGive(ctx.lock);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void disconn_handler(void)
|
||||
{
|
||||
/* disconnected
|
||||
* 1. WI-FI AP is far away
|
||||
* 2. WI-FI AP or AP device is closed
|
||||
* 3. this device is ejected by AP
|
||||
* */
|
||||
|
||||
if (ctx.auto_reconnect == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(ctx.lock, pdMS_TO_TICKS(0)) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "disconn_handler failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "start reconn task");
|
||||
xTaskCreate(reconnection_task, "reconn task", 4 * 1024, NULL, 7, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief kill reconnection task
|
||||
* @return
|
||||
*/
|
||||
int wifi_manager_disconnect(void)
|
||||
{
|
||||
ctx.auto_reconnect = 0;
|
||||
return esp_wifi_disconnect();
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ void *wifi_manager_get_ap_netif();
|
|||
void *wifi_manager_get_sta_netif();
|
||||
|
||||
typedef void (*wifi_manager_scan_done_cb)(uint16_t ap_found, wifi_ap_record_t *record, void *arg);
|
||||
int wifi_manager_scan(uint16_t *number, wifi_ap_record_t *records, uint8_t is_async);
|
||||
int wifi_manager_trigger_scan(wifi_manager_scan_done_cb cb, void *arg);
|
||||
int wifi_manager_get_scan_list(uint16_t *number, wifi_ap_record_t *aps);
|
||||
int wifi_manager_connect(const char *ssid, const char *password);
|
||||
int wifi_manager_disconnect(void);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
#include "wifi_storage.h"
|
||||
#include "wifi_storage_priv.h"
|
||||
#include "wt_nvs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define NVS_NAMESPACE "wifi"
|
||||
|
||||
int wifi_data_get_last_conn_cred(wifi_credential_t *ap_credential)
|
||||
{
|
||||
uint32_t ap_bitmap = 0;
|
||||
nvs_handle_t handle;
|
||||
int err;
|
||||
|
||||
err = wt_nvs_open(NVS_NAMESPACE, &handle);
|
||||
if (err) {
|
||||
return WT_NVS_ERR;
|
||||
}
|
||||
|
||||
err = wt_nvs_get(handle, KEY_WIFI_STA_AP_BITMAP, &ap_bitmap, sizeof(ap_bitmap));
|
||||
if (err || ap_bitmap == 0) {
|
||||
return WT_NVS_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
err = wt_nvs_get(handle, KEY_WIFI_STA_LAST_AP_CRED,
|
||||
ap_credential, sizeof(wifi_credential_t));
|
||||
if (err) {
|
||||
return WT_NVS_ERR;
|
||||
}
|
||||
|
||||
wt_nvs_close(handle);
|
||||
return WT_NVS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when connect to an AP,
|
||||
*/
|
||||
int wifi_save_ap_credential(wifi_credential_t *ap_credential)
|
||||
{
|
||||
uint32_t ap_bitmap;
|
||||
int err;
|
||||
nvs_handle_t handle;
|
||||
|
||||
err = wt_nvs_open(NVS_NAMESPACE, &handle);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = wt_nvs_get(handle, KEY_WIFI_STA_AP_BITMAP, &ap_bitmap, sizeof(ap_bitmap));
|
||||
if (err) {
|
||||
if (err != ESP_ERR_NVS_NOT_FOUND) {
|
||||
return err;
|
||||
}
|
||||
ap_bitmap = 0;
|
||||
}
|
||||
if (ap_bitmap == 0) {
|
||||
ap_bitmap = 1;
|
||||
err = wt_nvs_set(handle, KEY_WIFI_STA_AP_BITMAP, &ap_bitmap, sizeof(ap_bitmap));
|
||||
}
|
||||
|
||||
|
||||
wifi_credential_t credential;
|
||||
err = wt_nvs_get(handle, KEY_WIFI_STA_LAST_AP_CRED, &credential, sizeof(ap_bitmap));
|
||||
if (err) {
|
||||
if (err != ESP_ERR_NVS_NOT_FOUND) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err |= wt_nvs_set(handle, KEY_WIFI_STA_LAST_AP_CRED, ap_credential, sizeof(wifi_credential_t));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
wt_nvs_close(handle);
|
||||
return WT_NVS_OK;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef WIFI_STORAGE_H_GUARD
|
||||
#define WIFI_STORAGE_H_GUARD
|
||||
|
||||
#include <stdint-gcc.h>
|
||||
|
||||
typedef struct nvs_wifi_credential_t {
|
||||
char ssid[32];
|
||||
char password[64];
|
||||
} wifi_credential_t;
|
||||
|
||||
int wifi_data_get_last_conn_cred(wifi_credential_t *ap_credential);
|
||||
|
||||
int wifi_get_ap_password_of_ssid(wifi_credential_t *ap_credential);
|
||||
int wifi_save_ap_credential(wifi_credential_t *ap_credential);
|
||||
int wifi_rm_ap_credential(const char *ssid);
|
||||
|
||||
void wifi_cache_enable(uint8_t en);
|
||||
|
||||
|
||||
#endif //WIFI_STORAGE_H_GUARD
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef WIFI_STORAGE_PRIV_H_GUARD
|
||||
#define WIFI_STORAGE_PRIV_H_GUARD
|
||||
|
||||
#define WIFI_MAX_AP_CRED_RECORD 1
|
||||
|
||||
typedef struct w_cache_t {
|
||||
uint32_t ap_bitmap;
|
||||
wifi_credential_t ap_creds[WIFI_MAX_AP_CRED_RECORD];
|
||||
} w_cache_t;
|
||||
|
||||
typedef enum wt_wifi_key_enum {
|
||||
KEY_WIFI_RESERVED = 0x000,
|
||||
/* WIFI */
|
||||
KEY_WIFI_AP_SSID,
|
||||
KEY_WIFI_AP_PASSWORD,
|
||||
|
||||
/* TODO: should have 1 for each AP */
|
||||
KEY_WIFI_STA_USE_STATIC, /* bit[0:31]=[IP, MASK, GATEWAY, DNS] */
|
||||
KEY_WIFI_STA_STATIC_IP, /* 4B */
|
||||
KEY_WIFI_STA_STATIC_MASK, /* 4B */
|
||||
KEY_WIFI_STA_STATIC_GATEWAY, /* 4B */
|
||||
KEY_WIFI_STA_STATIC_DNS, /* 4B */
|
||||
|
||||
/* AP's information */
|
||||
KEY_WIFI_STA_LAST_AP_CRED, /*!< ssid[32] + password[64] */
|
||||
KEY_WIFI_STA_AP_BITMAP,
|
||||
} wt_wifi_key;
|
||||
|
||||
#endif //WIFI_STORAGE_PRIV_H_GUARD
|
|
@ -3,5 +3,6 @@ file(GLOB SOURCES wt_nvs.c wt_storage.c)
|
|||
idf_component_register(
|
||||
SRCS ${SOURCES}
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES nvs_flash
|
||||
PRIV_REQUIRES
|
||||
REQUIRES nvs_flash
|
||||
)
|
|
@ -14,3 +14,73 @@ void wt_nvs_init()
|
|||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
int wt_nvs_open(const char* namespace, nvs_handle_t *out_handle)
|
||||
{
|
||||
return nvs_open(namespace, NVS_READWRITE, out_handle);
|
||||
}
|
||||
|
||||
void wt_nvs_close(nvs_handle_t handle)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_commit(handle));
|
||||
nvs_close(handle);
|
||||
}
|
||||
|
||||
int wt_nvs_get(nvs_handle_t handle, const uint32_t key, void *data, uint32_t data_size)
|
||||
{
|
||||
switch (data_size) {
|
||||
case 0: {
|
||||
uint8_t tmp;
|
||||
return nvs_get_u8(handle, (const char *) &key, &tmp);
|
||||
}
|
||||
case 1:
|
||||
return nvs_get_u8(handle, (const char *) &key, data);
|
||||
case 2:
|
||||
return nvs_get_u16(handle, (const char *) &key, data);
|
||||
case 4:
|
||||
return nvs_get_u32(handle, (const char *) &key, data);
|
||||
case 8:
|
||||
return nvs_get_u64(handle, (const char *) &key, data);
|
||||
default:
|
||||
return nvs_get_blob(handle, (const char *) &key, data,
|
||||
(size_t *) &data_size);
|
||||
}
|
||||
}
|
||||
|
||||
int wt_nvs_set(nvs_handle_t handle, const uint32_t key, void *data, uint32_t data_size)
|
||||
{
|
||||
switch (data_size) {
|
||||
case 0: {
|
||||
uint8_t tmp = 0xFF;
|
||||
return nvs_set_u8(handle, (const char *) &key, tmp);
|
||||
}
|
||||
case 1:
|
||||
return nvs_set_u8(handle, (const char *) &key, *(uint8_t *)data);
|
||||
case 2:
|
||||
return nvs_set_u16(handle, (const char *) &key, *(uint16_t *)data);
|
||||
case 4:
|
||||
return nvs_set_u32(handle, (const char *) &key, *(uint32_t *)data);
|
||||
case 8:
|
||||
return nvs_set_u64(handle, (const char *) &key, *(uint64_t *)data);
|
||||
default:
|
||||
return nvs_set_blob(handle, (const char *) &key, data, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
int wt_nvs_get_once(const char* namespace, const uint32_t key, void *data, uint32_t data_size)
|
||||
{
|
||||
nvs_handle_t handle;
|
||||
int err;
|
||||
err = wt_nvs_open(namespace, &handle);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = wt_nvs_get(handle, key, data, data_size);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
wt_nvs_close(handle);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,25 @@
|
|||
#define WT_NVS_H_GUARD
|
||||
|
||||
#include <stdint.h>
|
||||
#include <nvs.h>
|
||||
|
||||
typedef enum wt_nvs_error_enum {
|
||||
WT_NVS_OK = 0,
|
||||
WT_NVS_ERR,
|
||||
WT_NVS_NO_MEM,
|
||||
WT_NVS_ERR_NOT_FOUND,
|
||||
|
||||
} wt_nvs_key_error;
|
||||
|
||||
int wt_nvs_open(const char* namespace, nvs_handle_t *out_handle);
|
||||
|
||||
void wt_nvs_close(nvs_handle_t handle);
|
||||
|
||||
int wt_nvs_get(nvs_handle_t handle, uint32_t key, void *data, uint32_t data_size);
|
||||
|
||||
int wt_nvs_set(nvs_handle_t handle, uint32_t key, void *data, uint32_t data_size);
|
||||
|
||||
int wt_nvs_flush(nvs_handle_t handle);
|
||||
|
||||
void wt_nvs_init();
|
||||
|
||||
|
|
Loading…
Reference in New Issue