init: initial commit

This commit is contained in:
2026-05-13 14:44:38 +02:00
commit 3fc50e797d
26 changed files with 4845 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
idf_component_register(
SRCS "src/provisioning.c"
INCLUDE_DIRS "include"
REQUIRES
network_provisioning
esp_wifi
esp_event
nvs_flash
config_store
led_indicator
bt
)
@@ -0,0 +1,5 @@
dependencies:
espressif/network_provisioning: "^1.2.4"
espressif/cjson: "*"
idf:
version: ">=5.1.0"
@@ -0,0 +1,12 @@
#pragma once
#include "esp_err.h"
/**
* Start BLE provisioning mode. Blocks until provisioning is complete,
* then deinits the provisioning manager so BLE memory can be reclaimed.
*
* WiFi credentials are stored automatically by wifi_prov_mgr.
* MQTT broker override (if sent by companion app) is stored via config_store.
*/
esp_err_t provisioning_run(void);
+133
View File
@@ -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;
}