diff --git a/firmware/esp32/include/config.h b/firmware/esp32/include/config.h new file mode 100644 index 0000000..43de798 --- /dev/null +++ b/firmware/esp32/include/config.h @@ -0,0 +1,17 @@ +#ifndef CONFIG_H +#define CONFIG_H + +// TODO: make this a config.h + +// WI-FI +#define SSID "your_wifi_ssid" +#define PASSWORD "your_wifi_password" +#define AUTH_MODE WIFI_AUTH_WPA2_PSK + +// MQTT +#define MQTT_ADDR "mqtt://yourmqttserver" +#define MQTT_PORT 1883 +#define MQTT_USER "your_username" +#define MQTT_PASS "your_password" + +#endif diff --git a/firmware/esp32/include/main.hpp b/firmware/esp32/include/main.hpp index 1433a50..7fad7f3 100644 --- a/firmware/esp32/include/main.hpp +++ b/firmware/esp32/include/main.hpp @@ -1,9 +1,13 @@ - #ifdef __cplusplus - extern "C" { - #endif + #ifndef MAIN_HPP + #define MAIN_HPP + + #include "freertos/FreeRTOS.h" + #include "freertos/event_groups.h" extern volatile bool criticalErrorFlag; + extern EventGroupHandle_t connectivity_event_group; + + #define WIFI_CONNECTED_BIT BIT0 + #define MQTT_CONNECTED_BIT BIT1 - #ifdef __cplusplus - } #endif diff --git a/firmware/esp32/include/mqtt.hpp b/firmware/esp32/include/mqtt.hpp new file mode 100644 index 0000000..440c395 --- /dev/null +++ b/firmware/esp32/include/mqtt.hpp @@ -0,0 +1,6 @@ +#ifndef MQTT_HPP +#define MQTT_HPP + +void mqttTask(void *pvParameters); + +#endif diff --git a/firmware/esp32/include/wifi-credentials.h b/firmware/esp32/include/wifi-credentials.h deleted file mode 100644 index 271369b..0000000 --- a/firmware/esp32/include/wifi-credentials.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef WIFI_CREDENTIALS_H -#define WIFI_CREDENTIALS_H - -#define SSID "your_wifi_ssid" -#define PASSWORD "your_wifi_password" -#define AUTH_MODE WIFI_AUTH_WPA2_PSK - -#endif diff --git a/firmware/esp32/main/CMakeLists.txt b/firmware/esp32/main/CMakeLists.txt index cc39a7b..d06dc88 100644 --- a/firmware/esp32/main/CMakeLists.txt +++ b/firmware/esp32/main/CMakeLists.txt @@ -1,6 +1,7 @@ idf_component_register(SRCS "./main.cpp" "./wifi.cpp" "./i2c.c" + "./mqtt.cpp" INCLUDE_DIRS "../include" REQUIRES esp_wifi nvs_flash @@ -10,3 +11,4 @@ idf_component_register(SRCS "./main.cpp" freertos log i2c_master) + mqtt) diff --git a/firmware/esp32/main/idf_component.yml b/firmware/esp32/main/idf_component.yml new file mode 100644 index 0000000..5334d28 --- /dev/null +++ b/firmware/esp32/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + espressif/mqtt: "*" diff --git a/firmware/esp32/main/main.cpp b/firmware/esp32/main/main.cpp index 5627dcf..f1e1f8b 100644 --- a/firmware/esp32/main/main.cpp +++ b/firmware/esp32/main/main.cpp @@ -7,6 +7,11 @@ #include "esp_task_wdt.h" #include "wifi.hpp" #include "i2c.cpp" +#include "mqtt.hpp" + +#define WATCHDOG_KEEPALIVE_MS 8000 + +EventGroupHandle_t connectivity_event_group; static const char* TAG = "MAIN"; @@ -23,18 +28,16 @@ static void watchdogTask(void *pvParameters) { ESP_ERROR_CHECK(esp_task_wdt_add(NULL)); - const TickType_t keepAlivePeriod = pdMS_TO_TICKS(8000); - for(;;) { - if (criticalErrorFlag) { + if(criticalErrorFlag) { ESP_LOGE(TAG, "Critical error flag raised. Rebooting."); esp_restart(); } ESP_ERROR_CHECK(esp_task_wdt_reset()); - ESP_LOGI(TAG, "WDT reset"); + ESP_LOGV(TAG, "WDT reset"); - vTaskDelay(keepAlivePeriod); + vTaskDelay(pdMS_TO_TICKS(WATCHDOG_KEEPALIVE_MS)); } } @@ -47,7 +50,10 @@ extern "C" void app_main(void) }; esp_pm_configure(&pm_cfg); + connectivity_event_group = xEventGroupCreate(); + xTaskCreate(watchdogTask, "watchdogs", 2048, NULL, configMAX_PRIORITIES-1, NULL); xTaskCreate(wifiTask, "wifi", 4096, NULL, configMAX_PRIORITIES-4, NULL); xTaskCreate(i2cTask, "i2c", 1024, NULL, configMAX_PRIORITIES-6, &i2c_task_handle); + xTaskCreate(mqttTask, "mqtt", 2048, NULL, configMAX_PRIORITIES-8, NULL); } diff --git a/firmware/esp32/main/mqtt.cpp b/firmware/esp32/main/mqtt.cpp new file mode 100644 index 0000000..a9bd99b --- /dev/null +++ b/firmware/esp32/main/mqtt.cpp @@ -0,0 +1,106 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_task_wdt.h" +#include "esp_event.h" +#include "esp_log.h" +#include "mqtt_client.h" +#include "main.hpp" +//#include "i2c.hpp" +#include "config-erick.h" + +#define MQTT_TASK_TIMEOUT_MS 3000 + +static const char* TAG = "MQTT"; + +static esp_mqtt_client_handle_t mqtt_client = NULL; + +static char global_rx_buffer[50]; + +static void mqtt_subscribe(void) { + esp_mqtt_client_subscribe(mqtt_client, "/topic/qos0", 0); +} + +static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { + esp_mqtt_event_handle_t event =(esp_mqtt_event_handle_t)event_data; + + switch(event->event_id) { + case MQTT_EVENT_CONNECTED: + xEventGroupSetBits(connectivity_event_group, MQTT_CONNECTED_BIT); + mqtt_subscribe(); + ESP_LOGV(TAG, "Connected to broker"); + break; + + case MQTT_EVENT_DISCONNECTED: + xEventGroupClearBits(connectivity_event_group, MQTT_CONNECTED_BIT); + ESP_LOGW(TAG, "Disconnected from broker"); + break; + + case MQTT_EVENT_DATA: + { + ESP_LOGD(TAG, "Data received"); + + int len = event->data_len; + if(len > sizeof(global_rx_buffer) - 1) len = sizeof(global_rx_buffer) - 1; + + memcpy(global_rx_buffer, event->data, len); + global_rx_buffer[len] = '\0'; + break; + } + + case MQTT_EVENT_ERROR: + ESP_LOGE(TAG, "Error event"); + if(event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) ESP_LOGE(TAG, "Network Error: %s", strerror(event->error_handle->esp_transport_sock_errno)); + else if(event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) ESP_LOGE(TAG, "Connection Refused! Reason code: 0x%x", event->error_handle->connect_return_code); + break; + + default: + break; + } +} + +static void mqtt_init(void) { + esp_mqtt_client_config_t mqtt_cfg = {}; + + mqtt_cfg.broker.address.uri = MQTT_ADDR; + mqtt_cfg.broker.address.port = MQTT_PORT; + mqtt_cfg.credentials.username = MQTT_USER; + mqtt_cfg.credentials.authentication.password = MQTT_PASS; + + mqtt_client = esp_mqtt_client_init(&mqtt_cfg); + if(mqtt_client == NULL) { + ESP_LOGE(TAG, "esp_mqtt_client_init returned NULL"); + criticalErrorFlag = true; + } + + esp_mqtt_client_register_event(mqtt_client, (esp_mqtt_event_id_t)ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); + + esp_mqtt_client_start(mqtt_client); +} + +void mqtt_publish(void) {} + +void mqttTask(void *pvParameters) { + ESP_LOGV(TAG, "Task started"); + + ESP_LOGV(TAG, "Waiting for Wi-Fi before initializing server"); + xEventGroupWaitBits(connectivity_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY); + ESP_LOGV(TAG, "Server initialized"); + + mqtt_init(); + ESP_ERROR_CHECK(esp_task_wdt_add(NULL)); + + for(;;) { + ESP_LOGV(TAG, "Checking Wi-Fi connection..."); + EventBits_t bits = xEventGroupWaitBits(connectivity_event_group, WIFI_CONNECTED_BIT | MQTT_CONNECTED_BIT, pdFALSE, pdTRUE, pdMS_TO_TICKS(MQTT_TASK_TIMEOUT_MS)); + + if ((bits & (WIFI_CONNECTED_BIT | MQTT_CONNECTED_BIT)) == (WIFI_CONNECTED_BIT | MQTT_CONNECTED_BIT)) { + ESP_LOGV(TAG, "Wi-Fi and MQTT up"); + + + + } else ESP_LOGV(TAG, "Wi-Fi or MQTT down"); + + ESP_ERROR_CHECK(esp_task_wdt_reset()); + ESP_LOGV(TAG, "Task reset"); + } +} diff --git a/firmware/esp32/main/wifi.cpp b/firmware/esp32/main/wifi.cpp index 0dc72c8..fc8311f 100644 --- a/firmware/esp32/main/wifi.cpp +++ b/firmware/esp32/main/wifi.cpp @@ -6,28 +6,26 @@ #include "esp_log.h" #include "nvs_flash.h" #include "main.hpp" -#include "wifi-credentials.h" +#include "config-erick.h" -#define WIFI_TIMEOUT_TICKS pdMS_TO_TICKS(8000) +#define WIFI_TIMEOUT_MS 4500 static const char* TAG = "WIFI"; -const int WIFI_CONNECTED_BIT = BIT0; - -EventGroupHandle_t wifi_event_group; static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { - if (event_base == WIFI_EVENT) { - switch (event_id) { + if(event_base == WIFI_EVENT) { + switch(event_id) { case WIFI_EVENT_STA_START: - ESP_LOGI(TAG, "Wi-Fi process started, connecting..."); - + ESP_LOGV(TAG, "Process started, connecting..."); esp_wifi_connect(); break; + case WIFI_EVENT_STA_DISCONNECTED: { - wifi_event_sta_disconnected_t* disconn = (wifi_event_sta_disconnected_t*) event_data; + wifi_event_sta_disconnected_t* disconn =(wifi_event_sta_disconnected_t*) event_data; ESP_LOGW(TAG, "Disconnected, reason: %d", disconn->reason); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + xEventGroupClearBits(connectivity_event_group, WIFI_CONNECTED_BIT); + esp_wifi_connect(); break; } @@ -35,26 +33,23 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t e break; } } - else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; - ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); + else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event =(ip_event_got_ip_t*) event_data; + ESP_LOGD(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip)); + + xEventGroupSetBits(connectivity_event_group, WIFI_CONNECTED_BIT); } } - static void wifi_init_sta(void) { esp_err_t nvs_err = nvs_flash_init(); - if (nvs_err == ESP_ERR_NVS_NO_FREE_PAGES || nvs_err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + if(nvs_err == ESP_ERR_NVS_NO_FREE_PAGES || nvs_err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_init()); } - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); @@ -77,16 +72,14 @@ static void wifi_init_sta(void) { } void wifiTask(void *pvParameters) { - ESP_LOGI(TAG, "WiFi task started"); + ESP_LOGV(TAG, "Task started"); wifi_init_sta(); ESP_ERROR_CHECK(esp_task_wdt_add(NULL)); for(;;) { - EventBits_t bits = xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, WIFI_TIMEOUT_TICKS); - ESP_ERROR_CHECK(esp_task_wdt_reset()); - ESP_LOGI(TAG, "Wi-Fi task reset"); - vTaskDelay(pdMS_TO_TICKS(4000)); + ESP_LOGV(TAG, "Task reset"); + vTaskDelay(pdMS_TO_TICKS(WIFI_TIMEOUT_MS)); } }