esp-idf/examples/provisioning/legacy/softap_prov/main/app_main.c

174 lines
5.5 KiB
C

/* SoftAP 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"
#include "qrcode.h"
#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_EXAMPLE_AP_RECONN_ATTEMPTS
#define PROV_QR_VERSION "v1"
#define PROV_TRANSPORT_SOFTAP "softap"
#define QRCODE_BASE_URL "https://espressif.github.io/esp-jumpstart/qrcode.html"
static const char *TAG = "app";
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t 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_softap_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
const char *ssid = NULL;
#ifdef CONFIG_EXAMPLE_SSID
ssid = CONFIG_EXAMPLE_SSID;
#else
uint8_t eth_mac[6];
esp_wifi_get_mac(WIFI_IF_STA, eth_mac);
char ssid_with_mac[33];
snprintf(ssid_with_mac, sizeof(ssid_with_mac), "PROV_%02X%02X%02X",
eth_mac[3], eth_mac[4], eth_mac[5]);
ssid = ssid_with_mac;
#endif
ESP_ERROR_CHECK(app_prov_start_softap_provisioning(
ssid, CONFIG_EXAMPLE_PASS, security, pop));
}
static void get_device_service_name(char *service_name, size_t max)
{
uint8_t eth_mac[6];
const char *ssid_prefix = "PROV_";
esp_wifi_get_mac(WIFI_IF_STA, eth_mac);
snprintf(service_name, max, "%s%02X%02X%02X",
ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]);
}
static void softap_prov_print_qr(void)
{
char payload[150] = {0};
char name[12] = {0};
char *pop = NULL;
#ifdef CONFIG_EXAMPLE_USE_POP
pop = CONFIG_EXAMPLE_POP;
#endif
get_device_service_name(name, sizeof(name));
if (pop) {
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"pop\":\"%s\",\"transport\":\"%s\"}",
PROV_QR_VERSION, name, pop, PROV_TRANSPORT_SOFTAP);
} else {
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"transport\":\"%s\"}",
PROV_QR_VERSION, name, PROV_TRANSPORT_SOFTAP);
}
#ifdef CONFIG_EXAMPLE_PROV_SHOW_QR
ESP_LOGI(TAG, "Scan this QR code from the provisioning application for Provisioning.");
esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT();
esp_qrcode_generate(&cfg, payload);
#endif /* CONFIG_APP_WIFI_PROV_SHOW_QR */
ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL, payload);
}
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();
esp_netif_create_default_wifi_ap();
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 soft AP */
ESP_LOGI(TAG, "Starting WiFi SoftAP provisioning");
start_softap_provisioning();
softap_prov_print_qr();
} else {
/* Start WiFi station with credentials set during provisioning */
ESP_LOGI(TAG, "Starting WiFi station");
wifi_init_sta();
}
}