diff options
| author | Filip Wandzio <contact@philw.dev> | 2025-10-29 13:29:27 +0100 |
|---|---|---|
| committer | Filip Wandzio <contact@philw.dev> | 2025-10-29 13:29:27 +0100 |
| commit | a27af14e815ef993e9a0c94e5bc8b32dbf989a94 (patch) | |
| tree | fed25911f251f95c7f2c71d1d770a5013452664c /firmware/src/main.c | |
| parent | 4698910f842c322b80ebd1cf19a4e32c0fb2249d (diff) | |
| download | e1-a27af14e815ef993e9a0c94e5bc8b32dbf989a94.tar.gz e1-a27af14e815ef993e9a0c94e5bc8b32dbf989a94.zip | |
Solve baud detection bug, fix wifi searching task scheduling bug, improve documentation, implement additional mqtt topicsHEADmaster
Diffstat (limited to 'firmware/src/main.c')
| -rw-r--r-- | firmware/src/main.c | 152 |
1 files changed, 86 insertions, 66 deletions
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 @@ | |||
| 1 | #include "esp_event.h" | 1 | #include "esp_event.h" |
| 2 | #include "esp_log.h" | 2 | #include "esp_log.h" |
| 3 | #include "esp_netif.h" | ||
| 4 | #include "esp_sntp.h" | ||
| 3 | #include "esp_system.h" | 5 | #include "esp_system.h" |
| 4 | #include "esp_timer.h" | 6 | #include "esp_timer.h" |
| 5 | #include "nvs_flash.h" | 7 | #include "nvs_flash.h" |
| @@ -8,21 +10,26 @@ | |||
| 8 | #include "wifi.h" | 10 | #include "wifi.h" |
| 9 | 11 | ||
| 10 | #include <stdio.h> | 12 | #include <stdio.h> |
| 13 | #include <time.h> | ||
| 14 | |||
| 11 | static const char *TAG = "app"; | 15 | static const char *TAG = "app"; |
| 16 | static EventGroupHandle_t wifi_event_group; | ||
| 17 | #define WIFI_CONNECTED_BIT BIT0 | ||
| 12 | 18 | ||
| 13 | /** | 19 | /** |
| 14 | * @brief Initialize NVS (Non-Volatile Storage) flash storage, handling full or | 20 | * @brief Initialize NVS (Non-Volatile Storage) flash storage, handling full or |
| 15 | * incompatible pages. | 21 | * incompatible pages. |
| 16 | * | 22 | * |
| 17 | * This function checks the NVS flash storage to ensure that there is enough | 23 | * This function checks the NVS flash storage to ensure that there is enough |
| 18 | * space and that the version of NVS is compatible. If the partition is full or | 24 | * space and that the version of NVS is compatible. If the partition |
| 19 | * incompatible, it will erase the NVS partition and attempt initialization | 25 | is full or |
| 20 | * again. | 26 | * incompatible, it will erase the NVS partition and attempt initialization |
| 21 | * | 27 | * again. |
| 22 | * @return esp_err_t | 28 | * |
| 23 | * - ESP_OK: Initialization successful. | 29 | * @return esp_err_t |
| 24 | * - Other error codes if initialization or erasure fails. | 30 | * - ESP_OK: Initialization successful. |
| 25 | */ | 31 | * - Other error codes if initialization or erasure fails. |
| 32 | */ | ||
| 26 | static esp_err_t nvs_flash_init_check(void) | 33 | static esp_err_t nvs_flash_init_check(void) |
| 27 | { | 34 | { |
| 28 | esp_err_t ret = nvs_flash_init(); | 35 | esp_err_t ret = nvs_flash_init(); |
| @@ -31,13 +38,7 @@ static esp_err_t nvs_flash_init_check(void) | |||
| 31 | ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { | 38 | ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { |
| 32 | ESP_LOGW(TAG, | 39 | ESP_LOGW(TAG, |
| 33 | "NVS partition is full or incompatible, erasing..."); | 40 | "NVS partition is full or incompatible, erasing..."); |
| 34 | ret = nvs_flash_erase(); | 41 | ESP_ERROR_CHECK(nvs_flash_erase()); |
| 35 | |||
| 36 | if (ret != ESP_OK) { | ||
| 37 | ESP_LOGE(TAG, "Failed to erase NVS partition (%s)", | ||
| 38 | esp_err_to_name(ret)); | ||
| 39 | return ret; | ||
| 40 | } | ||
| 41 | ret = nvs_flash_init(); | 42 | ret = nvs_flash_init(); |
| 42 | } | 43 | } |
| 43 | 44 | ||
| @@ -64,69 +65,88 @@ static esp_err_t nvs_flash_init_check(void) | |||
| 64 | * - ESP_OK: If initialization is successful. | 65 | * - ESP_OK: If initialization is successful. |
| 65 | * - Other error codes if initialization fails. | 66 | * - Other error codes if initialization fails. |
| 66 | */ | 67 | */ |
| 67 | static esp_err_t init_component(esp_err_t (*init_func)(void), | 68 | static void wifi_event_handler(void *arg, esp_event_base_t event_base, |
| 68 | const char *component_name) | 69 | int32_t event_id, void *event_data) |
| 69 | { | 70 | { |
| 70 | esp_err_t ret = init_func(); | 71 | if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { |
| 71 | 72 | esp_wifi_connect(); | |
| 72 | if (ret != ESP_OK) { | 73 | } else if (event_base == WIFI_EVENT && |
| 73 | ESP_LOGE(TAG, "Failed to initialize %s (%s)", component_name, | 74 | event_id == WIFI_EVENT_STA_DISCONNECTED) { |
| 74 | esp_err_to_name(ret)); | 75 | ESP_LOGW(TAG, "Wi-Fi disconnected, reconnecting..."); |
| 75 | return ret; | 76 | esp_wifi_connect(); |
| 77 | xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); | ||
| 78 | } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { | ||
| 79 | ESP_LOGI(TAG, "Wi-Fi connected and got IP!"); | ||
| 80 | xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); | ||
| 76 | } | 81 | } |
| 77 | |||
| 78 | return ESP_OK; | ||
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | /** | 84 | /** |
| 82 | * @brief Initializes all the essential components for the application. | 85 | * @TODO missing doc |
| 83 | * | ||
| 84 | * This function initializes the NVS storage, network interface, and event loop | ||
| 85 | * in sequence. If any of these components fail to initialize, the function | ||
| 86 | * returns an error, and the application will stop early. | ||
| 87 | * | ||
| 88 | * @return esp_err_t | ||
| 89 | * - ESP_OK: If all components are successfully initialized. | ||
| 90 | * - ESP_FAIL: If any component fails to initialize. | ||
| 91 | */ | 86 | */ |
| 92 | esp_err_t init_app_components(void) | 87 | static void obtain_time(void) |
| 93 | { | 88 | { |
| 94 | if (init_component(nvs_flash_init_check, "NVS") != ESP_OK) { | 89 | ESP_LOGI(TAG, "Starting SNTP time sync..."); |
| 95 | ESP_LOGE(TAG, "NVS initialization failed, aborting app start."); | 90 | sntp_setoperatingmode(SNTP_OPMODE_POLL); |
| 96 | return ESP_FAIL; | 91 | sntp_setservername(0, "pool.ntp.org"); |
| 92 | sntp_init(); | ||
| 93 | |||
| 94 | time_t now = 0; | ||
| 95 | struct tm timeinfo = {0}; | ||
| 96 | int retry = 0; | ||
| 97 | const int retry_count = 10; | ||
| 98 | |||
| 99 | while (timeinfo.tm_year < (2022 - 1900) && ++retry < retry_count) { | ||
| 100 | ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", | ||
| 101 | retry, retry_count); | ||
| 102 | vTaskDelay(pdMS_TO_TICKS(1000)); | ||
| 103 | time(&now); | ||
| 104 | localtime_r(&now, &timeinfo); | ||
| 97 | } | 105 | } |
| 98 | 106 | ||
| 99 | if (init_component(esp_netif_init, "network interface") != ESP_OK) | 107 | if (timeinfo.tm_year >= (2022 - 1900)) { |
| 100 | return ESP_FAIL; | 108 | char buf[64]; |
| 101 | 109 | strftime(buf, sizeof(buf), "%c", &timeinfo); | |
| 102 | if (init_component(esp_event_loop_create_default, "event loop") != | 110 | ESP_LOGI(TAG, "System time synchronized: %s", buf); |
| 103 | ESP_OK) | 111 | } else { |
| 104 | return ESP_FAIL; | 112 | ESP_LOGW(TAG, "Failed to synchronize time."); |
| 105 | 113 | } | |
| 106 | return ESP_OK; | ||
| 107 | } | 114 | } |
| 108 | 115 | ||
| 109 | /** | 116 | /** |
| 110 | * @brief Main entry point of the application. | 117 | * @brief Main entry point of the application. |
| 111 | * | 118 | * |
| 112 | * This function is responsible for initializing the core components of the | 119 | * This function is responsible for initializing the core components |
| 113 | * application, including the NVS storage, network interface, and event loop. If | 120 | of the |
| 114 | * any initialization step fails, the application will log the error and stop. | 121 | * application, including the NVS storage, network interface, and event loop. If |
| 115 | * | 122 | * any initialization step fails, the application will log the error |
| 116 | * After initialization, this function will configure the WiFi station and start | 123 | and stop. |
| 117 | * the MQTT client. | 124 | * |
| 118 | */ | 125 | * After initialization, this function will configure the WiFi station and start |
| 119 | 126 | * the MQTT client. | |
| 127 | */ | ||
| 120 | void app_main(void) | 128 | void app_main(void) |
| 121 | { | 129 | { |
| 122 | if (init_app_components() != ESP_OK) { | 130 | ESP_ERROR_CHECK(nvs_flash_init_check()); |
| 123 | ESP_LOGE(TAG, "App initialization failed, aborting."); | 131 | ESP_ERROR_CHECK(esp_netif_init()); |
| 124 | return; | 132 | ESP_ERROR_CHECK(esp_event_loop_create_default()); |
| 125 | } | 133 | |
| 134 | wifi_event_group = xEventGroupCreate(); | ||
| 126 | 135 | ||
| 127 | ESP_LOGI(TAG, "Initializing WiFi in station mode"); | 136 | ESP_LOGI(TAG, "Initializing WiFi (station mode)"); |
| 128 | wifi_init_sta(); | 137 | wifi_init_sta(); |
| 129 | 138 | ||
| 130 | ESP_LOGI(TAG, "Starting MQTT client"); | 139 | ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, |
| 140 | &wifi_event_handler, NULL)); | ||
| 141 | ESP_ERROR_CHECK(esp_event_handler_register( | ||
| 142 | IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL)); | ||
| 143 | |||
| 144 | ESP_LOGI(TAG, "Waiting for Wi-Fi connection..."); | ||
| 145 | xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, | ||
| 146 | pdFALSE, portMAX_DELAY); | ||
| 147 | |||
| 148 | obtain_time(); | ||
| 149 | |||
| 150 | ESP_LOGI(TAG, "Starting MQTT client..."); | ||
| 131 | mqtt_app_start(); | 151 | mqtt_app_start(); |
| 132 | } | 152 | } |
