#include #include #include #include #include "app_networking.hpp" #include "app_serial.hpp" #include "app_config.hpp" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" #include "freertos/timers.h" #include "nvs_flash.h" #include "driver/uart.h" #include "esp_log.h" namespace { static const char* LOG_TAG = "App"; TaskHandle_t s_main_task = nullptr; TimerHandle_t s_timer = nullptr; QueueSetHandle_t s_queue_set = nullptr; QueueHandle_t s_esp_now_queue = nullptr; QueueHandle_t s_uart_queue = nullptr; void s_sendUartData(std::size_t len) { len = std::clamp(len, 1, 128); ESP_LOGD(LOG_TAG, "Sending %u bytes via UART.", len); std::array tx_buffer; uart_read_bytes(CONFIG_ESPTNL_UART, tx_buffer.data(), len, 0); xTimerStop(s_timer, 0); Networking::sendData(tx_buffer, len); } std::size_t s_uartBytesWaiting() { std::size_t len = 0; uart_get_buffered_data_len(CONFIG_ESPTNL_UART, &len); return std::min(len, 128); } [[noreturn]] void s_mainTask(void*) { while (true) { QueueSetMemberHandle_t queue_select = xQueueSelectFromSet(s_queue_set, portMAX_DELAY); ESP_LOGI(LOG_TAG, "Event: %s.", queue_select == s_esp_now_queue ? "ESP-NOW event" : "UART event"); if (queue_select == s_esp_now_queue) { Networking::EspNowEvent event; xQueueReceive(s_esp_now_queue, &event, 0); ESP_LOGD(LOG_TAG, "ESP-NOW event: %u, rx-length: %ull.", event.type, event.rx_length); if (event.type == Networking::EspNowEvent::MSG_RECEIVED) { std::size_t uart_free = 0; uart_get_tx_buffer_free_size(CONFIG_ESPTNL_UART, &uart_free); if (uart_free >= event.rx_length) { ESP_LOGD(LOG_TAG, "ESP-NOW event: wrote %ull bytes to UART RX.", uart_free); const auto& esp_rx_buffer = Networking::getRxBuffer(); uart_write_bytes(CONFIG_ESPTNL_UART, esp_rx_buffer.data(), event.rx_length); } else { ESP_LOGW(LOG_TAG, "ESP-NOW event: dropped RX data due to full UART RX buffer."); } } else if (event.type == Networking::EspNowEvent::MSG_SEND_COMPLETE) { ESP_LOGD(LOG_TAG, "ESP-NOW event: TX completed. Checking to send data."); const std::size_t bytes_waiting = s_uartBytesWaiting(); if (s_uartBytesWaiting() >= 128) { s_sendUartData(bytes_waiting); } } } else if (queue_select == s_uart_queue) { uart_event_t event; xQueueReceive(s_uart_queue, &event, 0); ESP_LOGD(LOG_TAG, "UART event: %d, size: %u", event.type, event.size); if (event.type == UART_DATA) { const std::size_t recv_size = s_uartBytesWaiting(); if (recv_size >= 128) s_sendUartData(recv_size); else xTimerReset(s_timer, 0); } else if (event.type == UART_BUFFER_FULL) { const std::size_t recv_size = s_uartBytesWaiting(); s_sendUartData(recv_size); } else if (event.type == UART_FIFO_OVF) { ESP_LOGE(LOG_TAG, "UART FIFO overflow. Flushing."); Serial::discardRxBuffer(CONFIG_ESPTNL_UART); } } else { ESP_LOGW(LOG_TAG, "Unknown event type."); } } } void s_cbListenTimeout(TimerHandle_t) { ESP_LOGD(LOG_TAG, "s_cbListenTimeout invoked from timer."); const std::size_t bytes_waiting = s_uartBytesWaiting(); if (bytes_waiting > 0) s_sendUartData(bytes_waiting); } }// namespace extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); esp_log_level_set("*", esp_log_level_t(CONFIG_LOG_DEFAULT_LEVEL)); esp_log_level_set(LOG_TAG, Config::appLogLevel()); esp_log_level_set(Networking::LOG_TAG, Config::appLogLevel()); ESP_LOGD(LOG_TAG, "Starting main."); Networking::setupWifi(); s_esp_now_queue = Networking::setupEspNow(); s_uart_queue = Serial::setupSerial(CONFIG_ESPTNL_UART); s_timer = xTimerCreate("autosend_timer", pdMS_TO_TICKS(100), false, nullptr, s_cbListenTimeout); s_queue_set = xQueueCreateSet(4 + 4); xQueueAddToSet(s_esp_now_queue, s_queue_set); xQueueAddToSet(s_uart_queue, s_queue_set); ESP_LOGI(LOG_TAG, "Setup completed. Sending hello."); Networking::sendHello(); xTaskCreate(s_mainTask, "main_task", 2048, nullptr, 4, &s_main_task); }