From a27af14e815ef993e9a0c94e5bc8b32dbf989a94 Mon Sep 17 00:00:00 2001 From: Filip Wandzio Date: Wed, 29 Oct 2025 13:29:27 +0100 Subject: Solve baud detection bug, fix wifi searching task scheduling bug, improve documentation, implement additional mqtt topics --- firmware/src/main.c | 152 +++++++++++++++++++++++++++++----------------------- 1 file changed, 86 insertions(+), 66 deletions(-) (limited to 'firmware/src/main.c') diff --git a/firmware/src/main.c b/firmware/src/main.c index 3f186f8..9fa4c61 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -1,5 +1,7 @@ #include "esp_event.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_sntp.h" #include "esp_system.h" #include "esp_timer.h" #include "nvs_flash.h" @@ -8,21 +10,26 @@ #include "wifi.h" #include +#include + static const char *TAG = "app"; +static EventGroupHandle_t wifi_event_group; +#define WIFI_CONNECTED_BIT BIT0 /** - * @brief Initialize NVS (Non-Volatile Storage) flash storage, handling full or - * incompatible pages. - * - * This function checks the NVS flash storage to ensure that there is enough - * space and that the version of NVS is compatible. If the partition is full or - * incompatible, it will erase the NVS partition and attempt initialization - * again. - * - * @return esp_err_t - * - ESP_OK: Initialization successful. - * - Other error codes if initialization or erasure fails. - */ +* @brief Initialize NVS (Non-Volatile Storage) flash storage, handling full or +* incompatible pages. +* +* This function checks the NVS flash storage to ensure that there is enough +* space and that the version of NVS is compatible. If the partition +is full or +* incompatible, it will erase the NVS partition and attempt initialization +* again. +* +* @return esp_err_t +* - ESP_OK: Initialization successful. +* - Other error codes if initialization or erasure fails. +*/ static esp_err_t nvs_flash_init_check(void) { esp_err_t ret = nvs_flash_init(); @@ -31,13 +38,7 @@ static esp_err_t nvs_flash_init_check(void) ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "NVS partition is full or incompatible, erasing..."); - ret = nvs_flash_erase(); - - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to erase NVS partition (%s)", - esp_err_to_name(ret)); - return ret; - } + ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } @@ -64,69 +65,88 @@ static esp_err_t nvs_flash_init_check(void) * - ESP_OK: If initialization is successful. * - Other error codes if initialization fails. */ -static esp_err_t init_component(esp_err_t (*init_func)(void), - const char *component_name) +static void wifi_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { - esp_err_t ret = init_func(); - - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize %s (%s)", component_name, - esp_err_to_name(ret)); - return ret; + 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) { + ESP_LOGW(TAG, "Wi-Fi disconnected, reconnecting..."); + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ESP_LOGI(TAG, "Wi-Fi connected and got IP!"); + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); } - - return ESP_OK; } /** - * @brief Initializes all the essential components for the application. - * - * This function initializes the NVS storage, network interface, and event loop - * in sequence. If any of these components fail to initialize, the function - * returns an error, and the application will stop early. - * - * @return esp_err_t - * - ESP_OK: If all components are successfully initialized. - * - ESP_FAIL: If any component fails to initialize. + * @TODO missing doc */ -esp_err_t init_app_components(void) +static void obtain_time(void) { - if (init_component(nvs_flash_init_check, "NVS") != ESP_OK) { - ESP_LOGE(TAG, "NVS initialization failed, aborting app start."); - return ESP_FAIL; + ESP_LOGI(TAG, "Starting SNTP time sync..."); + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, "pool.ntp.org"); + sntp_init(); + + time_t now = 0; + struct tm timeinfo = {0}; + int retry = 0; + const int retry_count = 10; + + while (timeinfo.tm_year < (2022 - 1900) && ++retry < retry_count) { + ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", + retry, retry_count); + vTaskDelay(pdMS_TO_TICKS(1000)); + time(&now); + localtime_r(&now, &timeinfo); } - if (init_component(esp_netif_init, "network interface") != ESP_OK) - return ESP_FAIL; - - if (init_component(esp_event_loop_create_default, "event loop") != - ESP_OK) - return ESP_FAIL; - - return ESP_OK; + if (timeinfo.tm_year >= (2022 - 1900)) { + char buf[64]; + strftime(buf, sizeof(buf), "%c", &timeinfo); + ESP_LOGI(TAG, "System time synchronized: %s", buf); + } else { + ESP_LOGW(TAG, "Failed to synchronize time."); + } } /** - * @brief Main entry point of the application. - * - * This function is responsible for initializing the core components of the - * application, including the NVS storage, network interface, and event loop. If - * any initialization step fails, the application will log the error and stop. - * - * After initialization, this function will configure the WiFi station and start - * the MQTT client. - */ - +* @brief Main entry point of the application. +* +* This function is responsible for initializing the core components +of the +* application, including the NVS storage, network interface, and event loop. If +* any initialization step fails, the application will log the error +and stop. +* +* After initialization, this function will configure the WiFi station and start +* the MQTT client. +*/ void app_main(void) { - if (init_app_components() != ESP_OK) { - ESP_LOGE(TAG, "App initialization failed, aborting."); - return; - } + ESP_ERROR_CHECK(nvs_flash_init_check()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_event_group = xEventGroupCreate(); - ESP_LOGI(TAG, "Initializing WiFi in station mode"); + ESP_LOGI(TAG, "Initializing WiFi (station mode)"); wifi_init_sta(); - ESP_LOGI(TAG, "Starting MQTT client"); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, + &wifi_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register( + IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL)); + + ESP_LOGI(TAG, "Waiting for Wi-Fi connection..."); + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, + pdFALSE, portMAX_DELAY); + + obtain_time(); + + ESP_LOGI(TAG, "Starting MQTT client..."); mqtt_app_start(); } -- cgit v1.2.3