mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-20 01:45:55 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "app_main.c"
|
||||
"app_prov.c"
|
||||
"app_prov_handlers.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,40 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_USE_SEC_1
|
||||
bool
|
||||
default y
|
||||
prompt "Use Security Version 1"
|
||||
help
|
||||
Security version 1 used Curve25519 key exchange for establishing
|
||||
secure session between device and client during provisioning
|
||||
|
||||
config EXAMPLE_USE_POP
|
||||
bool
|
||||
depends on EXAMPLE_USE_SEC_1
|
||||
default y
|
||||
prompt "Use proof-of-possession"
|
||||
help
|
||||
Proof-of-possession can be optionally used to prove that the device is indeed
|
||||
in possession of the user who is provisioning the device. This proof-of-possession
|
||||
is internally used to generate the shared secret through key exchange.
|
||||
|
||||
config EXAMPLE_POP
|
||||
string "Proof-of-possession"
|
||||
default "abcd1234"
|
||||
depends on EXAMPLE_USE_POP
|
||||
|
||||
config EXAMPLE_RESET_PROVISIONED
|
||||
bool
|
||||
default n
|
||||
prompt "Reset provisioned status of the device"
|
||||
help
|
||||
This erases the NVS to reset provisioned status of the device on every reboot.
|
||||
Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS.
|
||||
|
||||
config EXAMPLE_AP_RECONN_ATTEMPTS
|
||||
int "Maximum AP connection attempts"
|
||||
default 5
|
||||
help
|
||||
Set the maximum connection attempts to perform when connecting to a Wi-Fi AP.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,116 @@
|
||||
/* Console based Provisioning Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_event.h>
|
||||
#include <esp_log.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/sys.h>
|
||||
|
||||
#include "app_prov.h"
|
||||
|
||||
#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_EXAMPLE_AP_RECONN_ATTEMPTS
|
||||
|
||||
static const char *TAG = "app";
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
int event_id, void* event_data)
|
||||
{
|
||||
static int s_retry_num = 0;
|
||||
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_retry_num < EXAMPLE_AP_RECONN_ATTEMPTS) {
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||
}
|
||||
ESP_LOGI(TAG,"connect to the AP fail");
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
s_retry_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_init_sta(void)
|
||||
{
|
||||
/* Set our event handling */
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL));
|
||||
|
||||
/* Start Wi-Fi in station mode with credentials set during provisioning */
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
}
|
||||
|
||||
static void start_console_provisioning(void)
|
||||
{
|
||||
/* Security version */
|
||||
int security = 0;
|
||||
/* Proof of possession */
|
||||
const protocomm_security_pop_t *pop = NULL;
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_USE_SEC_1
|
||||
security = 1;
|
||||
#endif
|
||||
|
||||
/* Having proof of possession is optional */
|
||||
#ifdef CONFIG_EXAMPLE_USE_POP
|
||||
const static protocomm_security_pop_t app_pop = {
|
||||
.data = (uint8_t *) CONFIG_EXAMPLE_POP,
|
||||
.len = (sizeof(CONFIG_EXAMPLE_POP)-1)
|
||||
};
|
||||
pop = &app_pop;
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(app_prov_start_console_provisioning(security, pop));
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Initialize networking stack */
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
|
||||
/* Create default event loop needed by the
|
||||
* main app and the provisioning service */
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
/* Initialize NVS needed by Wi-Fi */
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
|
||||
/* Initialize Wi-Fi including netif with default config */
|
||||
esp_netif_create_default_wifi_sta();
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
/* Check if device is provisioned */
|
||||
bool provisioned;
|
||||
if (app_prov_is_provisioned(&provisioned) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error getting device provisioning state");
|
||||
return;
|
||||
}
|
||||
|
||||
if (provisioned == false) {
|
||||
/* If not provisioned, start provisioning via console */
|
||||
ESP_LOGI(TAG, "Starting console provisioning");
|
||||
start_console_provisioning();
|
||||
} else {
|
||||
/* Else start as station with credentials set during provisioning */
|
||||
ESP_LOGI(TAG, "Starting WiFi station");
|
||||
wifi_init_sta();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
/* Console based Provisioning Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <nvs.h>
|
||||
#include <esp_event.h>
|
||||
|
||||
#include <protocomm.h>
|
||||
#include <protocomm_console.h>
|
||||
#include <protocomm_security0.h>
|
||||
#include <protocomm_security1.h>
|
||||
#include <wifi_provisioning/wifi_config.h>
|
||||
|
||||
#include "app_prov.h"
|
||||
|
||||
static const char *TAG = "app_prov";
|
||||
|
||||
/* Handler for catching WiFi events */
|
||||
static void app_prov_event_handler(void* handler_arg, esp_event_base_t base, int id, void* data);
|
||||
|
||||
/* Handlers for wifi_config provisioning endpoint */
|
||||
extern wifi_prov_config_handlers_t wifi_prov_handlers;
|
||||
|
||||
/**
|
||||
* @brief Data relevant to provisioning application
|
||||
*/
|
||||
struct app_prov_data {
|
||||
protocomm_t *pc; /*!< Protocomm handler */
|
||||
int security; /*!< Type of security to use with protocomm */
|
||||
const protocomm_security_pop_t *pop; /*!< Pointer to proof of possession */
|
||||
esp_timer_handle_t timer; /*!< Handle to timer */
|
||||
|
||||
/* State of WiFi Station */
|
||||
wifi_prov_sta_state_t wifi_state;
|
||||
|
||||
/* Code for WiFi station disconnection (if disconnected) */
|
||||
wifi_prov_sta_fail_reason_t wifi_disconnect_reason;
|
||||
};
|
||||
|
||||
/* Pointer to provisioning application data */
|
||||
static struct app_prov_data *g_prov;
|
||||
|
||||
static esp_err_t app_prov_start_service(void)
|
||||
{
|
||||
/* Create new protocomm instance */
|
||||
g_prov->pc = protocomm_new();
|
||||
if (g_prov->pc == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create new protocomm instance");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Config for protocomm_console_start() */
|
||||
protocomm_console_config_t config = PROTOCOMM_CONSOLE_DEFAULT_CONFIG();
|
||||
|
||||
/* Start protocomm using console */
|
||||
if (protocomm_console_start(g_prov->pc, &config) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start console provisioning");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Set protocomm version verification endpoint for protocol */
|
||||
protocomm_set_version(g_prov->pc, "proto-ver", "V0.1");
|
||||
|
||||
/* Set protocomm security type for endpoint */
|
||||
if (g_prov->security == 0) {
|
||||
protocomm_set_security(g_prov->pc, "prov-session", &protocomm_security0, NULL);
|
||||
} else if (g_prov->security == 1) {
|
||||
protocomm_set_security(g_prov->pc, "prov-session", &protocomm_security1, g_prov->pop);
|
||||
}
|
||||
|
||||
/* Add endpoint for provisioning to set wifi station config */
|
||||
if (protocomm_add_endpoint(g_prov->pc, "prov-config",
|
||||
wifi_prov_config_data_handler,
|
||||
(void *) &wifi_prov_handlers) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set provisioning endpoint");
|
||||
protocomm_console_stop(g_prov->pc);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Provisioning started");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void app_prov_stop_service(void)
|
||||
{
|
||||
/* Remove provisioning endpoint */
|
||||
protocomm_remove_endpoint(g_prov->pc, "prov-config");
|
||||
/* Unset provisioning security */
|
||||
protocomm_unset_security(g_prov->pc, "prov-session");
|
||||
/* Unset provisioning version endpoint */
|
||||
protocomm_unset_version(g_prov->pc, "proto-ver");
|
||||
/* Stop protocomm console service */
|
||||
protocomm_console_stop(g_prov->pc);
|
||||
/* Delete protocomm instance */
|
||||
protocomm_delete(g_prov->pc);
|
||||
|
||||
/* Remove event handler */
|
||||
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler);
|
||||
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler);
|
||||
}
|
||||
|
||||
/* Task spawned by timer callback */
|
||||
static void stop_prov_task(void * arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "Stopping provisioning");
|
||||
app_prov_stop_service();
|
||||
|
||||
/* Timer not needed anymore */
|
||||
esp_timer_handle_t timer = g_prov->timer;
|
||||
esp_timer_delete(timer);
|
||||
g_prov->timer = NULL;
|
||||
|
||||
/* Free provisioning process data */
|
||||
free(g_prov);
|
||||
g_prov = NULL;
|
||||
ESP_LOGI(TAG, "Provisioning stopped");
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/* Callback to be invoked by timer */
|
||||
static void _stop_prov_cb(void * arg)
|
||||
{
|
||||
xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL);
|
||||
}
|
||||
|
||||
/* Event handler for starting/stopping provisioning */
|
||||
static void app_prov_event_handler(void* handler_arg, esp_event_base_t event_base,
|
||||
int event_id, void* event_data)
|
||||
{
|
||||
/* If pointer to provisioning application data is NULL
|
||||
* then provisioning is not running */
|
||||
if (!g_prov) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
ESP_LOGI(TAG, "STA Start");
|
||||
/* Once configuration is received through protocomm,
|
||||
* device is started as station. Once station starts,
|
||||
* wait for connection to establish with configured
|
||||
* host SSID and password */
|
||||
g_prov->wifi_state = WIFI_PROV_STA_CONNECTING;
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ESP_LOGI(TAG, "STA Got IP");
|
||||
/* Station got IP. That means configuration is successful.
|
||||
* Schedule timer to stop provisioning app after 30 seconds. */
|
||||
g_prov->wifi_state = WIFI_PROV_STA_CONNECTED;
|
||||
if (g_prov && g_prov->timer) {
|
||||
esp_timer_start_once(g_prov->timer, 30000*1000U);
|
||||
}
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
ESP_LOGE(TAG, "STA Disconnected");
|
||||
/* Station couldn't connect to configured host SSID */
|
||||
g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED;
|
||||
|
||||
wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;
|
||||
ESP_LOGE(TAG, "Disconnect reason : %d", disconnected->reason);
|
||||
|
||||
/* Set code corresponding to the reason for disconnection */
|
||||
switch (disconnected->reason) {
|
||||
case WIFI_REASON_AUTH_EXPIRE:
|
||||
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
|
||||
case WIFI_REASON_BEACON_TIMEOUT:
|
||||
case WIFI_REASON_AUTH_FAIL:
|
||||
case WIFI_REASON_ASSOC_FAIL:
|
||||
case WIFI_REASON_HANDSHAKE_TIMEOUT:
|
||||
ESP_LOGI(TAG, "STA Auth Error");
|
||||
g_prov->wifi_disconnect_reason = WIFI_PROV_STA_AUTH_ERROR;
|
||||
break;
|
||||
case WIFI_REASON_NO_AP_FOUND:
|
||||
ESP_LOGI(TAG, "STA AP Not found");
|
||||
g_prov->wifi_disconnect_reason = WIFI_PROV_STA_AP_NOT_FOUND;
|
||||
break;
|
||||
default:
|
||||
/* If none of the expected reasons,
|
||||
* retry connecting to host SSID */
|
||||
g_prov->wifi_state = WIFI_PROV_STA_CONNECTING;
|
||||
}
|
||||
esp_wifi_connect();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state)
|
||||
{
|
||||
if (g_prov == NULL || state == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*state = g_prov->wifi_state;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason)
|
||||
{
|
||||
if (g_prov == NULL || reason == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (g_prov->wifi_state != WIFI_PROV_STA_DISCONNECTED) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*reason = g_prov->wifi_disconnect_reason;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t app_prov_is_provisioned(bool *provisioned)
|
||||
{
|
||||
*provisioned = false;
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_RESET_PROVISIONED
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
|
||||
/* Get WiFi Station configuration */
|
||||
wifi_config_t wifi_cfg;
|
||||
if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (strlen((const char*) wifi_cfg.sta.ssid)) {
|
||||
*provisioned = true;
|
||||
ESP_LOGI(TAG, "Found ssid %s", (const char*) wifi_cfg.sta.ssid);
|
||||
ESP_LOGI(TAG, "Found password %s", (const char*) wifi_cfg.sta.password);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg)
|
||||
{
|
||||
/* Configure WiFi as station */
|
||||
if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set WiFi mode");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
/* Configure WiFi station with host credentials
|
||||
* provided during provisioning */
|
||||
if (esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_cfg) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set WiFi configuration");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
/* Start WiFi */
|
||||
if (esp_wifi_start() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set WiFi configuration");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
/* Connect to AP */
|
||||
if (esp_wifi_connect() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to connect WiFi");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (g_prov) {
|
||||
/* Reset wifi station state for provisioning app */
|
||||
g_prov->wifi_state = WIFI_PROV_STA_CONNECTING;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t app_prov_start_console_provisioning(int security, const protocomm_security_pop_t *pop)
|
||||
{
|
||||
/* If provisioning app data present,
|
||||
* means provisioning app is already running */
|
||||
if (g_prov) {
|
||||
ESP_LOGI(TAG, "Invalid provisioning state");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Allocate memory for provisioning app data */
|
||||
g_prov = (struct app_prov_data *) calloc(1, sizeof(struct app_prov_data));
|
||||
if (!g_prov) {
|
||||
ESP_LOGI(TAG, "Unable to allocate prov data");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
/* Initialize app data */
|
||||
g_prov->pop = pop;
|
||||
g_prov->security = security;
|
||||
|
||||
/* Create timer object as a member of app data */
|
||||
esp_timer_create_args_t timer_conf = {
|
||||
.callback = _stop_prov_cb,
|
||||
.arg = NULL,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "stop_console_tm"
|
||||
};
|
||||
esp_err_t err = esp_timer_create(&timer_conf, &g_prov->timer);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create timer");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler, NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register WiFi event handler");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler, NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register IP event handler");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Start provisioning service through console */
|
||||
err = app_prov_start_service();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Provisioning failed to start");
|
||||
return err;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Console provisioning started");
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* Console based Provisioning Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <protocomm_security.h>
|
||||
#include <wifi_provisioning/wifi_config.h>
|
||||
|
||||
/**
|
||||
* @brief Get state of WiFi Station during provisioning
|
||||
*
|
||||
* @note WiFi is initially configured as AP, when
|
||||
* provisioning starts. After provisioning data
|
||||
* is provided by user, the WiFi is reconfigured
|
||||
* to run as both AP and Station.
|
||||
*
|
||||
* @param[out] state Pointer to wifi_prov_sta_state_t variable to be filled
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Successfully retrieved wifi state
|
||||
* - ESP_FAIL : Provisioning app not running
|
||||
*/
|
||||
esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state);
|
||||
|
||||
/**
|
||||
* @brief Get reason code in case of WiFi station
|
||||
* disconnection during provisioning
|
||||
*
|
||||
* @param[out] reason Pointer to wifi_prov_sta_fail_reason_t variable to be filled
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Successfully retrieved wifi disconnect reason
|
||||
* - ESP_FAIL : Provisioning app not running
|
||||
*/
|
||||
esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason);
|
||||
|
||||
/**
|
||||
* @brief Checks if device is provisioned
|
||||
* *
|
||||
* @param[out] provisioned True if provisioned, else false
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Retrieved provision state successfully
|
||||
* - ESP_FAIL : Failed to retrieve provision state
|
||||
*/
|
||||
esp_err_t app_prov_is_provisioned(bool *provisioned);
|
||||
|
||||
/**
|
||||
* @brief Runs WiFi as Station
|
||||
*
|
||||
* Configures the WiFi station mode to connect to the
|
||||
* SSID and password specified in config structure,
|
||||
* and starts WiFi to run as station
|
||||
*
|
||||
* @param[in] wifi_cfg Pointer to WiFi cofiguration structure
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : WiFi configured and started successfully
|
||||
* - ESP_FAIL : Failed to set configuration
|
||||
*/
|
||||
esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg);
|
||||
|
||||
/**
|
||||
* @brief Start provisioning via Console
|
||||
*
|
||||
* @param[in] security Security mode
|
||||
* @param[in] pop Pointer to proof of possession (NULL if not present)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Provisioning started successfully
|
||||
* - ESP_FAIL : Failed to start
|
||||
*/
|
||||
esp_err_t app_prov_start_console_provisioning(int security, const protocomm_security_pop_t *pop);
|
||||
@@ -0,0 +1,135 @@
|
||||
/* Console based Provisioning Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
/* This file is mostly a boiler-plate code that applications can use without much change */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_netif.h>
|
||||
|
||||
#include <wifi_provisioning/wifi_config.h>
|
||||
|
||||
#include "app_prov.h"
|
||||
|
||||
static const char* TAG = "app_prov_handler";
|
||||
|
||||
/* Provide definition of wifi_prov_ctx_t */
|
||||
struct wifi_prov_ctx {
|
||||
wifi_config_t wifi_cfg;
|
||||
};
|
||||
|
||||
static wifi_config_t *get_config(wifi_prov_ctx_t **ctx)
|
||||
{
|
||||
return (*ctx ? &(*ctx)->wifi_cfg : NULL);
|
||||
}
|
||||
|
||||
static wifi_config_t *new_config(wifi_prov_ctx_t **ctx)
|
||||
{
|
||||
free(*ctx);
|
||||
(*ctx) = (wifi_prov_ctx_t *) calloc(1, sizeof(wifi_prov_ctx_t));
|
||||
return get_config(ctx);
|
||||
}
|
||||
|
||||
static void free_config(wifi_prov_ctx_t **ctx)
|
||||
{
|
||||
free(*ctx);
|
||||
*ctx = NULL;
|
||||
}
|
||||
|
||||
static esp_err_t get_status_handler(wifi_prov_config_get_data_t *resp_data, wifi_prov_ctx_t **ctx)
|
||||
{
|
||||
/* Initialize to zero */
|
||||
memset(resp_data, 0, sizeof(wifi_prov_config_get_data_t));
|
||||
|
||||
if (app_prov_get_wifi_state(&resp_data->wifi_state) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Prov app not running");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (resp_data->wifi_state == WIFI_PROV_STA_CONNECTED) {
|
||||
ESP_LOGI(TAG, "Connected state");
|
||||
|
||||
/* IP Addr assigned to STA */
|
||||
esp_netif_ip_info_t ip_info;
|
||||
esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info);
|
||||
esp_ip4addr_ntoa(&ip_info.ip, resp_data->conn_info.ip_addr, sizeof(resp_data->conn_info.ip_addr));
|
||||
|
||||
/* AP information to which STA is connected */
|
||||
wifi_ap_record_t ap_info;
|
||||
esp_wifi_sta_get_ap_info(&ap_info);
|
||||
memcpy(resp_data->conn_info.bssid, (char *)ap_info.bssid, sizeof(ap_info.bssid));
|
||||
memcpy(resp_data->conn_info.ssid, (char *)ap_info.ssid, sizeof(ap_info.ssid));
|
||||
resp_data->conn_info.channel = ap_info.primary;
|
||||
resp_data->conn_info.auth_mode = ap_info.authmode;
|
||||
} else if (resp_data->wifi_state == WIFI_PROV_STA_DISCONNECTED) {
|
||||
ESP_LOGI(TAG, "Disconnected state");
|
||||
|
||||
/* If disconnected, convey reason */
|
||||
app_prov_get_wifi_disconnect_reason(&resp_data->fail_reason);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Connecting state");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t set_config_handler(const wifi_prov_config_set_data_t *req_data, wifi_prov_ctx_t **ctx)
|
||||
{
|
||||
wifi_config_t *wifi_cfg = get_config(ctx);
|
||||
if (wifi_cfg) {
|
||||
free_config(ctx);
|
||||
}
|
||||
|
||||
wifi_cfg = new_config(ctx);
|
||||
if (!wifi_cfg) {
|
||||
ESP_LOGE(TAG, "Unable to alloc wifi config");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "WiFi Credentials Received : \n\tssid %s \n\tpassword %s",
|
||||
req_data->ssid, req_data->password);
|
||||
|
||||
/* Using memcpy allows the max SSID length to be 32 bytes (as per 802.11 standard).
|
||||
* But this doesn't guarantee that the saved SSID will be null terminated, because
|
||||
* wifi_cfg->sta.ssid is also 32 bytes long (without extra 1 byte for null character).
|
||||
* Although, this is not a matter for concern because esp_wifi library reads the SSID
|
||||
* upto 32 bytes in absence of null termination */
|
||||
const size_t ssid_len = strnlen(req_data->ssid, sizeof(wifi_cfg->sta.ssid));
|
||||
/* Ensure SSID less than 32 bytes is null terminated */
|
||||
memset(wifi_cfg->sta.ssid, 0, sizeof(wifi_cfg->sta.ssid));
|
||||
memcpy(wifi_cfg->sta.ssid, req_data->ssid, ssid_len);
|
||||
|
||||
strlcpy((char *) wifi_cfg->sta.password, req_data->password, sizeof(wifi_cfg->sta.password));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t apply_config_handler(wifi_prov_ctx_t **ctx)
|
||||
{
|
||||
wifi_config_t *wifi_cfg = get_config(ctx);
|
||||
if (!wifi_cfg) {
|
||||
ESP_LOGE(TAG, "WiFi config not set");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
app_prov_configure_sta(wifi_cfg);
|
||||
ESP_LOGI(TAG, "WiFi Credentials Applied");
|
||||
|
||||
free_config(ctx);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
wifi_prov_config_handlers_t wifi_prov_handlers = {
|
||||
.get_status_handler = get_status_handler,
|
||||
.set_config_handler = set_config_handler,
|
||||
.apply_config_handler = apply_config_handler,
|
||||
.ctx = NULL
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# Main component makefile.
|
||||
#
|
||||
# This Makefile can be left empty. By default, it will take the sources in the
|
||||
# src/ directory, compile them and link them into lib(subdirectory_name).a
|
||||
# in the build directory. This behaviour is entirely configurable,
|
||||
# please read the ESP-IDF documents if you need to do this.
|
||||
#
|
||||
Reference in New Issue
Block a user