Page 1 of 1

Re-provisioning ESP32 chip using wifi provisioning example

Posted: Fri Mar 25, 2022 4:01 am
by karunt
Using the example for wifi-provisioning to re-provision chip by implementing the following logic in custom_prov_data_handler:

Code: Select all

esp_err_t custom_prov_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen,
                                          uint8_t **outbuf, ssize_t *outlen, void *priv_data)
{       if (strncmp((char *)inbuf, "reboot", inlen) == 0) {
        wifi_prov_mgr_stop_provisioning();
        ESP_ERROR_CHECK(esp_wifi_restore());
        char service_name[12];
        get_device_service_name(service_name, sizeof(service_name));
        wifi_prov_security_t security = WIFI_PROV_SECURITY_0;
        const char *pop = "abcd1234";
        const char *service_key = NULL;
        ESP_ERROR_CHECK(wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key));
    }

    char response[] = "SUCCESS";
    *outbuf = (uint8_t *)strdup(response);
    if (*outbuf == NULL) {
        ESP_LOGE(TAG, "System out of memory");
        return ESP_ERR_NO_MEM;
    }
    *outlen = strlen(response) + 1; // +1 for NULL terminating byte

    return ESP_OK;
}
The problem I encounter with this logic is that the response to my BLE.write command always returns in an error because before the chip is able to write a response back to the GATT characteristic, it gets instructions to stop provisioning, restore and restart provisioning. My question is - what function can I invoke before stopping/restarting provisioning that will allow the code to write a response to the GATT characteristic so my BLE.write command gets a response indicating that the peripheral device successfully wrote to the chip's GATT characteristic? While I can assume that an error response to BLE.write means that the chip is rebooting itself, it's a poor assumption to make because I can't tell for sure if the write error is a result of the reboot process or that something else went wrong with BLE.write that prevented the reboot instructions from being written to the ESP32 chip to begin with.

Re: Re-provisioning ESP32 chip using wifi provisioning example

Posted: Fri Mar 25, 2022 10:07 am
by karunt
I'm not sure if this is the best approach to solving my problem, but I registered a custom event loop. The custom handler, after receiving instructions at the particular GATT characteristic, posts an event which invokes the custom event loop. It is in that custom event loop that I stop and restart provisioning service. Meanwhile, the custom event handler has time to respond to the BLE write request from the peripheral to let it know that the write operation was successful. Here's my code for the custom event loop:

Outside app_main:

Code: Select all

esp_event_loop_handle_t custom_loop_handle;
ESP_EVENT_DEFINE_BASE(CUSTOM_EVENT);

enum {
    REBOOT
};

void custom_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
    if (base == CUSTOM_EVENT){
        switch (id){
            case REBOOT:
                vTaskDelay(1000); //used as a buffer to ensure custom handler has time to respond to BLE write request before reboot begins
                wifi_prov_mgr_stop_provisioning();
                ESP_ERROR_CHECK(esp_wifi_restore());
                char service_name[12];
                get_device_service_name(service_name, sizeof(service_name));
                wifi_prov_security_t security = WIFI_PROV_SECURITY_0;
                const char *pop = "abcd1234";
                const char *service_key = NULL;
                ESP_ERROR_CHECK(wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key));
                break;
        }
    }
}
Inside app_main:

Code: Select all

    esp_event_loop_args_t custom_loop_args = {//arguments chosen from event loop example, but not sure what they mean and how they work
        .queue_size = 5,
        .task_name = "loop_task",
        .task_priority = uxTaskPriorityGet(NULL),
        .task_stack_size = 3072,
        .task_core_id = tskNO_AFFINITY
    };

    ESP_ERROR_CHECK(esp_event_loop_create(&custom_loop_args, &custom_loop_handle));
    ESP_ERROR_CHECK(esp_event_handler_instance_register_with(custom_loop_handle, CUSTOM_EVENT, REBOOT, &custom_event_handler, custom_loop_handle, NULL));
}
Here's my code for the custom handler:

Code: Select all

esp_err_t custom_prov_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen,
                                          uint8_t **outbuf, ssize_t *outlen, void *priv_data)
{   

    if (strncmp((char *)inbuf, "reboot", inlen) == 0) {
        esp_event_post_to(custom_loop_handle, CUSTOM_EVENT, REBOOT, NULL, 0, 0); //invokes custom event loop
    }
    char response[] = "SUCCESS";
    *outbuf = (uint8_t *)strdup(response);
    if (*outbuf == NULL) {
        ESP_LOGE(TAG, "System out of memory");
        return ESP_ERR_NO_MEM;
    }
    *outlen = strlen(response) + 1; // +1 for NULL terminating byte

    return ESP_OK;
}