|
|
|
@@ -0,0 +1,133 @@
|
|
|
|
|
#include "provisioning.h"
|
|
|
|
|
#include "config_store.h"
|
|
|
|
|
#include "led_indicator.h"
|
|
|
|
|
|
|
|
|
|
#include "network_provisioning/manager.h"
|
|
|
|
|
#include "network_provisioning/scheme_ble.h"
|
|
|
|
|
#include "esp_wifi.h"
|
|
|
|
|
#include "esp_event.h"
|
|
|
|
|
#include "esp_log.h"
|
|
|
|
|
#include "freertos/event_groups.h"
|
|
|
|
|
#include "cJSON.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#define TAG "provisioning"
|
|
|
|
|
|
|
|
|
|
/* Custom GATT endpoint name for MQTT settings. The companion app sends:
|
|
|
|
|
* {"host":"192.168.1.100","port":1883} */
|
|
|
|
|
#define MQTT_ENDPOINT "custom-mqtt-config"
|
|
|
|
|
|
|
|
|
|
static EventGroupHandle_t s_prov_evt;
|
|
|
|
|
#define PROV_DONE_BIT BIT0
|
|
|
|
|
|
|
|
|
|
/* Called by wifi_prov_mgr when data arrives on the custom endpoint. */
|
|
|
|
|
static esp_err_t mqtt_endpoint_handler(uint32_t session_id,
|
|
|
|
|
const uint8_t *inbuf, ssize_t inlen,
|
|
|
|
|
uint8_t **outbuf, ssize_t *outlen,
|
|
|
|
|
void *priv)
|
|
|
|
|
{
|
|
|
|
|
if (!inbuf || inlen <= 0) return ESP_OK;
|
|
|
|
|
|
|
|
|
|
char *json = strndup((const char *)inbuf, inlen);
|
|
|
|
|
if (!json) return ESP_ERR_NO_MEM;
|
|
|
|
|
|
|
|
|
|
cJSON *root = cJSON_Parse(json);
|
|
|
|
|
free(json);
|
|
|
|
|
if (!root) {
|
|
|
|
|
ESP_LOGW(TAG, "Failed to parse MQTT config JSON");
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cJSON *host_j = cJSON_GetObjectItemCaseSensitive(root, "host");
|
|
|
|
|
cJSON *port_j = cJSON_GetObjectItemCaseSensitive(root, "port");
|
|
|
|
|
|
|
|
|
|
if (cJSON_IsString(host_j) && cJSON_IsNumber(port_j)) {
|
|
|
|
|
uint16_t port = (uint16_t)port_j->valuedouble;
|
|
|
|
|
esp_err_t err = config_store_set_mqtt_override(host_j->valuestring, port);
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
ESP_LOGI(TAG, "MQTT override stored: %s:%u", host_j->valuestring, port);
|
|
|
|
|
} else {
|
|
|
|
|
ESP_LOGW(TAG, "Failed to store MQTT override: %s", esp_err_to_name(err));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ESP_LOGW(TAG, "MQTT config missing 'host' or 'port'");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cJSON_Delete(root);
|
|
|
|
|
|
|
|
|
|
/* Respond with a simple ack */
|
|
|
|
|
const char *ack = "{\"status\":\"ok\"}";
|
|
|
|
|
*outlen = strlen(ack);
|
|
|
|
|
*outbuf = (uint8_t *)strdup(ack);
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void prov_event_handler(void *arg, esp_event_base_t base,
|
|
|
|
|
int32_t id, void *data)
|
|
|
|
|
{
|
|
|
|
|
if (base == NETWORK_PROV_EVENT) {
|
|
|
|
|
switch (id) {
|
|
|
|
|
case NETWORK_PROV_START:
|
|
|
|
|
ESP_LOGI(TAG, "Provisioning started");
|
|
|
|
|
break;
|
|
|
|
|
case NETWORK_PROV_WIFI_CRED_RECV:
|
|
|
|
|
ESP_LOGI(TAG, "WiFi credentials received");
|
|
|
|
|
break;
|
|
|
|
|
case NETWORK_PROV_WIFI_CRED_FAIL: {
|
|
|
|
|
network_prov_wifi_sta_fail_reason_t *reason = (network_prov_wifi_sta_fail_reason_t *)data;
|
|
|
|
|
ESP_LOGE(TAG, "Provisioning failed: %s",
|
|
|
|
|
(*reason == NETWORK_PROV_WIFI_STA_AUTH_ERROR) ? "auth error" : "AP not found");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case NETWORK_PROV_WIFI_CRED_SUCCESS:
|
|
|
|
|
ESP_LOGI(TAG, "WiFi credentials applied successfully");
|
|
|
|
|
break;
|
|
|
|
|
case NETWORK_PROV_END:
|
|
|
|
|
ESP_LOGI(TAG, "Provisioning complete");
|
|
|
|
|
network_prov_mgr_deinit();
|
|
|
|
|
xEventGroupSetBits(s_prov_evt, PROV_DONE_BIT);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
esp_err_t provisioning_run(void)
|
|
|
|
|
{
|
|
|
|
|
s_prov_evt = xEventGroupCreate();
|
|
|
|
|
|
|
|
|
|
esp_event_handler_register(NETWORK_PROV_EVENT, ESP_EVENT_ANY_ID,
|
|
|
|
|
prov_event_handler, NULL);
|
|
|
|
|
|
|
|
|
|
network_prov_mgr_config_t config = {
|
|
|
|
|
.scheme = network_prov_scheme_ble,
|
|
|
|
|
.scheme_event_handler = NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM,
|
|
|
|
|
};
|
|
|
|
|
ESP_ERROR_CHECK(network_prov_mgr_init(config));
|
|
|
|
|
|
|
|
|
|
/* Register custom endpoint for MQTT broker config */
|
|
|
|
|
network_prov_mgr_endpoint_create(MQTT_ENDPOINT);
|
|
|
|
|
|
|
|
|
|
/* Derive device name and PoP from WiFi MAC */
|
|
|
|
|
uint8_t mac[6];
|
|
|
|
|
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
|
|
|
|
char device_name[32];
|
|
|
|
|
snprintf(device_name, sizeof(device_name),
|
|
|
|
|
"anchor_%02x%02x%02x", mac[3], mac[4], mac[5]);
|
|
|
|
|
|
|
|
|
|
led_indicator_set(LED_PROVISIONING);
|
|
|
|
|
|
|
|
|
|
ESP_ERROR_CHECK(network_prov_mgr_start_provisioning(
|
|
|
|
|
NETWORK_PROV_SECURITY_0, NULL, device_name, NULL));
|
|
|
|
|
|
|
|
|
|
network_prov_mgr_endpoint_register(MQTT_ENDPOINT, mqtt_endpoint_handler, NULL);
|
|
|
|
|
|
|
|
|
|
/* Block until provisioning completes */
|
|
|
|
|
xEventGroupWaitBits(s_prov_evt, PROV_DONE_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
|
|
|
|
vEventGroupDelete(s_prov_evt);
|
|
|
|
|
|
|
|
|
|
config_store_set_provisioned();
|
|
|
|
|
ESP_LOGI(TAG, "Provisioning done, NVS flag set");
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|