#include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_log.h" #include "esp_err.h" #include "esp_event.h" #include "esp_netif.h" #include "esp_spiffs.h" #include "esp_system.h" #include "nvs_flash.h" #include "driver/gpio.h" #include "wifi.h" #include "board_config.h" #include "logger.h" #include "rest_main.h" #include "peripherals.h" #include "protocols.h" #include "evse_manager.h" #include "evse_api.h" #include "auth.h" #include "loadbalancer.h" #include "meter_manager.h" #define EVSE_MANAGER_TICK_PERIOD_MS 1000 #define AP_CONNECTION_TIMEOUT 120000 #define RESET_HOLD_TIME 10000 #define DEBOUNCE_TIME_MS 50 #define PRESS_BIT BIT0 #define RELEASED_BIT BIT1 static const char *TAG = "app_main"; static TaskHandle_t user_input_task; static TickType_t press_tick = 0; static TickType_t last_interrupt_tick = 0; static bool pressed = false; // // File system (SPIFFS) init and info // static void fs_info(esp_vfs_spiffs_conf_t *conf) { size_t total = 0, used = 0; esp_err_t ret = esp_spiffs_info(conf->partition_label, &total, &used); if (ret == ESP_OK) ESP_LOGI(TAG, "Partition %s: total: %d, used: %d", conf->partition_label, total, used); else ESP_LOGE(TAG, "Failed to get SPIFFS info: %s", esp_err_to_name(ret)); } static void fs_init(void) { esp_vfs_spiffs_conf_t cfg_conf = { .base_path = "/cfg", .partition_label = "cfg", .max_files = 1, .format_if_mount_failed = false }; esp_vfs_spiffs_conf_t data_conf = { .base_path = "/data", .partition_label = "data", .max_files = 5, .format_if_mount_failed = true }; ESP_ERROR_CHECK(esp_vfs_spiffs_register(&cfg_conf)); ESP_ERROR_CHECK(esp_vfs_spiffs_register(&data_conf)); fs_info(&cfg_conf); fs_info(&data_conf); } // // Wi-Fi event monitoring task // static void wifi_event_task_func(void *param) { EventBits_t mode_bits; while (1) { mode_bits = xEventGroupWaitBits(wifi_event_group, WIFI_AP_MODE_BIT | WIFI_STA_MODE_BIT, pdFALSE, pdFALSE, portMAX_DELAY); if (mode_bits & WIFI_AP_MODE_BIT) { if (xEventGroupWaitBits(wifi_event_group, WIFI_AP_CONNECTED_BIT, pdFALSE, pdFALSE, pdMS_TO_TICKS(AP_CONNECTION_TIMEOUT)) & WIFI_AP_CONNECTED_BIT) { xEventGroupWaitBits(wifi_event_group, WIFI_AP_DISCONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY); } else { if (xEventGroupGetBits(wifi_event_group) & WIFI_AP_MODE_BIT) { //wifi_ap_stop(); } } } else if (mode_bits & WIFI_STA_MODE_BIT) { xEventGroupWaitBits(wifi_event_group, WIFI_STA_DISCONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY); } } } // // Botão e tratamento // static void handle_button_press(void) { ESP_LOGI(TAG, "Ativando modo AP"); if (!(xEventGroupGetBits(wifi_event_group) & WIFI_AP_MODE_BIT)) { wifi_ap_start(); } } static void user_input_task_func(void *param) { uint32_t notification; while (1) { if (xTaskNotifyWait(0x00, 0xFF, ¬ification, portMAX_DELAY)) { if (notification & PRESS_BIT) { press_tick = xTaskGetTickCount(); pressed = true; ESP_LOGI(TAG, "Botão pressionado"); } if (notification & RELEASED_BIT && pressed) { pressed = false; ESP_LOGI(TAG, "Botão liberado"); handle_button_press(); } } } } static void IRAM_ATTR button_isr_handler(void *arg) { BaseType_t higher_task_woken = pdFALSE; TickType_t now = xTaskGetTickCountFromISR(); if (now - last_interrupt_tick < pdMS_TO_TICKS(DEBOUNCE_TIME_MS)) return; last_interrupt_tick = now; if (!gpio_get_level(board_config.button_wifi_gpio)) { xTaskNotifyFromISR(user_input_task, RELEASED_BIT, eSetBits, &higher_task_woken); } else { xTaskNotifyFromISR(user_input_task, PRESS_BIT, eSetBits, &higher_task_woken); } if (higher_task_woken) { portYIELD_FROM_ISR(); } } static void button_init(void) { gpio_config_t conf = { .pin_bit_mask = BIT64(board_config.button_wifi_gpio), .mode = GPIO_MODE_INPUT, .pull_down_en = GPIO_PULLDOWN_DISABLE, .pull_up_en = GPIO_PULLUP_ENABLE, .intr_type = GPIO_INTR_ANYEDGE }; ESP_ERROR_CHECK(gpio_config(&conf)); ESP_ERROR_CHECK(gpio_isr_handler_add(board_config.button_wifi_gpio, button_isr_handler, NULL)); } // // Inicialização dos módulos do sistema // static void init_modules(void) { peripherals_init(); //api_init(); ESP_ERROR_CHECK(rest_server_init("/data")); protocols_init(); evse_manager_init(); evse_init(); // Cria a task para FSM button_init(); auth_init(); loadbalancer_init(); meter_manager_grid_init(); meter_manager_grid_start(); //meter_manager_evse_init(); // Outros módulos (descomente conforme necessário) // meter_init(); // ocpp_start(); // orno_modbus_start(); // currentshaper_start(); // initWiegand(); // meter_zigbee_start(); // master_sync_start(); // slave_sync_start(); } // // Função principal do firmware // void app_main(void) { logger_init(); esp_log_set_vprintf(logger_vprintf); esp_reset_reason_t reason = esp_reset_reason(); ESP_LOGI(TAG, "Reset reason: %d", reason); esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "Erasing NVS flash"); ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); fs_init(); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(gpio_install_isr_service(0)); board_config_load(); wifi_ini(); //wifi_ap_start(); init_modules(); xTaskCreate(wifi_event_task_func, "wifi_event_task", 8 * 1024, NULL, 3, NULL); xTaskCreate(user_input_task_func, "user_input_task", 4 * 1024, NULL, 3, &user_input_task); }