#include "meter_manager.h" #include "esp_log.h" #include "meter_ade7758.h" #include "meter_orno513.h" #include "meter_orno516.h" #include "meter_orno526.h" #include "meter_dts6619.h" #include "meter_dds661.h" #include "meter_zigbee.h" #include "meter_ea777.h" #include "meter_dts024m.h" #include #include "network_events.h" #include "meter_events.h" #include "esp_event.h" #include "esp_timer.h" // NEW: #include "storage_service.h" static const char *TAG = "meter_manager"; // Tipos de medidores EVSE e GRID static meter_type_t meter_evse_type = METER_TYPE_NONE; static meter_type_t meter_grid_type = METER_TYPE_NONE; #define STORE_NAMESPACE "meterconfig" #define STORE_EVSE_MODEL "evse_model" #define STORE_GRID_MODEL "grid_model" // timeouts storage #define STORAGE_TO pdMS_TO_TICKS(800) // ------------------------------------------------------------------ // Helpers storage (robustos a queue cheia) // ------------------------------------------------------------------ static esp_err_t storage_try_flush(void) { return storage_flush_sync(pdMS_TO_TICKS(2000)); } static esp_err_t storage_try_set_u8(const char *ns, const char *key, uint8_t v) { for (int attempt = 0; attempt < 3; ++attempt) { esp_err_t err = storage_set_u8_async(ns, key, v); if (err == ESP_OK) return ESP_OK; if (err == ESP_ERR_TIMEOUT) { (void)storage_try_flush(); continue; } return err; } return ESP_ERR_TIMEOUT; } static esp_err_t storage_get_u8_default(const char *ns, const char *key, uint8_t *out, uint8_t def) { if (!out) return ESP_ERR_INVALID_ARG; uint8_t v = def; esp_err_t err = storage_get_u8_sync(ns, key, &v, STORAGE_TO); if (err == ESP_OK) { *out = v; return ESP_OK; } // se não existir / erro, devolve default *out = def; return err; } // ------------------------------------------------------------------ /* static void meter_manager_network_event_handler(void *arg, esp_event_base_t base, int32_t event_id, void *data) { (void)arg; (void)data; if (base != NETWORK_EVENTS) return; switch (event_id) { case NETWORK_EVENT_AP_STARTED: ESP_LOGD(TAG, "Recebido NETWORK_EVENT_AP_STARTED, parando medidor de grid"); break; case NETWORK_EVENT_AP_STOP: ESP_LOGD(TAG, "Recebido NETWORK_EVENT_AP_STOP, reiniciando medidor de grid"); break; case NETWORK_EVENT_STA_GOT_IP: ESP_LOGD(TAG, "Recebido NETWORK_EVENT_STA_GOT_IP"); break; default: break; } } */ // Função unificada para ler ou inicializar um modelo de medidor (via storage_service) static esp_err_t load_or_init_meter_model(const char *key, meter_type_t *type) { if (!type) return ESP_ERR_INVALID_ARG; // tenta ler uint8_t value = 0xFF; esp_err_t err = storage_get_u8_sync(STORE_NAMESPACE, key, &value, STORAGE_TO); if (err == ESP_OK && value < 255) { *type = (meter_type_t)value; ESP_LOGD(TAG, "Loaded meter type %u from storage key '%s/%s'", (unsigned)value, STORE_NAMESPACE, key); return ESP_OK; } // se não existir / inválido -> default NONE e grava *type = METER_TYPE_NONE; esp_err_t w = storage_try_set_u8(STORE_NAMESPACE, key, (uint8_t)(*type)); if (w != ESP_OK) ESP_LOGE(TAG, "Failed to init key '%s/%s' to NONE: %s", STORE_NAMESPACE, key, esp_err_to_name(w)); (void)storage_try_flush(); ESP_LOGW(TAG, "Invalid/missing key '%s/%s' (read=%s), setting default (NONE)", STORE_NAMESPACE, key, esp_err_to_name(err)); return ESP_OK; // seguimos com default } static esp_err_t write_meter_model_to_storage(const char *key, meter_type_t meter_type) { esp_err_t err = storage_try_set_u8(STORE_NAMESPACE, key, (uint8_t)meter_type); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to write meter type to storage key '%s/%s': %s", STORE_NAMESPACE, key, esp_err_to_name(err)); return err; } (void)storage_try_flush(); ESP_LOGD(TAG, "Saved meter type %d to storage key '%s/%s'", (int)meter_type, STORE_NAMESPACE, key); return ESP_OK; } /** * @brief Inicializa o sistema de meter manager. */ esp_err_t meter_manager_init(void) { // garantir storage pronto esp_err_t s = storage_service_init(); if (s != ESP_OK) ESP_LOGE(TAG, "storage_service_init failed: %s", esp_err_to_name(s)); esp_err_t err; // Initialize GRID meter err = meter_manager_grid_init(); if (err != ESP_OK) return err; // Regista handler para eventos de rede /* ESP_LOGD(TAG, "Registering network event handler"); err = esp_event_handler_register( NETWORK_EVENTS, ESP_EVENT_ANY_ID, meter_manager_network_event_handler, NULL); */ if (err != ESP_OK) return err; // Emite um evento inicial de configuração meter_config_event_t ev = { .grid_type = meter_manager_grid_get_model(), .evse_type = meter_manager_evse_get_model(), .timestamp_us = esp_timer_get_time()}; esp_event_post(METER_EVENT, METER_EVENT_CONFIG_UPDATED, &ev, sizeof(ev), 0); return ESP_OK; } esp_err_t meter_manager_start(void) { // Start GRID meter return meter_manager_grid_start(); } esp_err_t meter_manager_stop(void) { // Stop GRID meter return meter_manager_grid_stop(); } // ---------- EVSE ---------- esp_err_t meter_manager_evse_init() { esp_err_t err = load_or_init_meter_model(STORE_EVSE_MODEL, &meter_evse_type); if (err != ESP_OK) return err; ESP_LOGD(TAG, "Initializing EVSE meter of type %s", meter_type_to_str(meter_evse_type)); switch (meter_evse_type) { case METER_TYPE_NONE: return ESP_OK; case METER_TYPE_ADE7758: return meter_ade7758_init(); case METER_TYPE_ORNO513: return meter_orno513_init(); case METER_TYPE_ORNO516: return meter_orno516_init(); case METER_TYPE_ORNO526: return meter_orno526_init(); case METER_TYPE_DTS6619: return meter_dts6619_init(); case METER_TYPE_DDS661: return meter_dds661_init(); case METER_TYPE_EA777: return meter_ea777_init(); case METER_TYPE_DTS024M: return meter_dts024m_init(); case METER_TYPE_MONO_ZIGBEE: case METER_TYPE_TRIF_ZIGBEE: return meter_zigbee_init(); default: return ESP_ERR_INVALID_ARG; } } esp_err_t meter_manager_evse_start() { meter_type_t type = meter_manager_evse_get_model(); switch (type) { case METER_TYPE_NONE: return ESP_OK; case METER_TYPE_ADE7758: return meter_ade7758_start(); case METER_TYPE_ORNO513: return meter_orno513_start(); case METER_TYPE_ORNO516: return meter_orno516_start(); case METER_TYPE_ORNO526: return meter_orno526_start(); case METER_TYPE_DTS6619: return meter_dts6619_start(); case METER_TYPE_DDS661: return meter_dds661_start(); case METER_TYPE_EA777: return meter_ea777_start(); case METER_TYPE_DTS024M: return meter_dts024m_start(); case METER_TYPE_MONO_ZIGBEE: case METER_TYPE_TRIF_ZIGBEE: return meter_zigbee_start(); default: return ESP_ERR_INVALID_ARG; } } esp_err_t meter_manager_evse_stop(void) { meter_type_t type = meter_manager_evse_get_model(); switch (type) { case METER_TYPE_NONE: return ESP_OK; case METER_TYPE_ADE7758: meter_ade7758_stop(); break; case METER_TYPE_ORNO513: meter_orno513_stop(); break; case METER_TYPE_ORNO516: meter_orno516_stop(); break; case METER_TYPE_ORNO526: meter_orno526_stop(); break; case METER_TYPE_DTS6619: meter_dts6619_stop(); break; case METER_TYPE_DDS661: meter_dds661_stop(); break; case METER_TYPE_EA777: meter_ea777_stop(); break; case METER_TYPE_DTS024M: meter_dts024m_stop(); break; case METER_TYPE_MONO_ZIGBEE: case METER_TYPE_TRIF_ZIGBEE: meter_zigbee_stop(); break; default: return ESP_ERR_INVALID_ARG; } return ESP_OK; } // ---------- GRID ---------- esp_err_t meter_manager_grid_init() { esp_err_t err = load_or_init_meter_model(STORE_GRID_MODEL, &meter_grid_type); if (err != ESP_OK) return err; ESP_LOGD(TAG, "Initializing GRID meter of type %s", meter_type_to_str(meter_grid_type)); switch (meter_grid_type) { case METER_TYPE_NONE: return ESP_OK; case METER_TYPE_ADE7758: return meter_ade7758_init(); case METER_TYPE_ORNO513: return meter_orno513_init(); case METER_TYPE_ORNO516: return meter_orno516_init(); case METER_TYPE_ORNO526: return meter_orno526_init(); case METER_TYPE_DTS6619: return meter_dts6619_init(); case METER_TYPE_DDS661: return meter_dds661_init(); case METER_TYPE_EA777: return meter_ea777_init(); case METER_TYPE_DTS024M: return meter_dts024m_init(); case METER_TYPE_MONO_ZIGBEE: case METER_TYPE_TRIF_ZIGBEE: return meter_zigbee_init(); default: return ESP_ERR_INVALID_ARG; } } esp_err_t meter_manager_grid_start() { meter_type_t type = meter_manager_grid_get_model(); switch (type) { case METER_TYPE_NONE: return ESP_OK; case METER_TYPE_ADE7758: return meter_ade7758_start(); case METER_TYPE_ORNO513: return meter_orno513_start(); case METER_TYPE_ORNO516: return meter_orno516_start(); case METER_TYPE_ORNO526: return meter_orno526_start(); case METER_TYPE_DTS6619: return meter_dts6619_start(); case METER_TYPE_DDS661: return meter_dds661_start(); case METER_TYPE_EA777: return meter_ea777_start(); case METER_TYPE_DTS024M: return meter_dts024m_start(); case METER_TYPE_MONO_ZIGBEE: case METER_TYPE_TRIF_ZIGBEE: return meter_zigbee_start(); default: return ESP_ERR_INVALID_ARG; } } esp_err_t meter_manager_grid_stop(void) { meter_type_t type = meter_manager_grid_get_model(); switch (type) { case METER_TYPE_NONE: return ESP_OK; case METER_TYPE_ADE7758: meter_ade7758_stop(); break; case METER_TYPE_ORNO513: meter_orno513_stop(); break; case METER_TYPE_ORNO516: meter_orno516_stop(); break; case METER_TYPE_ORNO526: meter_orno526_stop(); break; case METER_TYPE_DTS6619: meter_dts6619_stop(); break; case METER_TYPE_DDS661: meter_dds661_stop(); break; case METER_TYPE_EA777: meter_ea777_stop(); break; case METER_TYPE_DTS024M: meter_dts024m_stop(); break; case METER_TYPE_MONO_ZIGBEE: case METER_TYPE_TRIF_ZIGBEE: meter_zigbee_stop(); break; default: return ESP_ERR_INVALID_ARG; } return ESP_OK; } // ---------- Utilidades / setters com evento ---------- esp_err_t meter_manager_evse_set_model(meter_type_t meter_type) { esp_err_t err; err = meter_manager_evse_stop(); if (err != ESP_OK) ESP_LOGW(TAG, "Failed to stop EVSE meter before changing model: %s", esp_err_to_name(err)); meter_evse_type = meter_type; err = write_meter_model_to_storage(STORE_EVSE_MODEL, meter_evse_type); if (err != ESP_OK) return err; err = meter_manager_evse_init(); if (err == ESP_OK) err = meter_manager_evse_start(); meter_config_event_t ev = { .grid_type = meter_manager_grid_get_model(), .evse_type = meter_manager_evse_get_model(), .timestamp_us = esp_timer_get_time()}; esp_err_t evt_err = esp_event_post(METER_EVENT, METER_EVENT_CONFIG_UPDATED, &ev, sizeof(ev), portMAX_DELAY); if (evt_err != ESP_OK) ESP_LOGW(TAG, "Failed to post METER_EVENT_CONFIG_UPDATED (EVSE): %s", esp_err_to_name(evt_err)); return err; } esp_err_t meter_manager_grid_set_model(meter_type_t meter_type) { esp_err_t err; err = meter_manager_grid_stop(); if (err != ESP_OK) ESP_LOGW(TAG, "Failed to stop GRID meter before changing model: %s", esp_err_to_name(err)); meter_grid_type = meter_type; err = write_meter_model_to_storage(STORE_GRID_MODEL, meter_grid_type); if (err != ESP_OK) return err; err = meter_manager_grid_init(); if (err == ESP_OK) err = meter_manager_grid_start(); meter_config_event_t ev = { .grid_type = meter_manager_grid_get_model(), .evse_type = meter_manager_evse_get_model(), .timestamp_us = esp_timer_get_time()}; esp_err_t evt_err = esp_event_post(METER_EVENT, METER_EVENT_CONFIG_UPDATED, &ev, sizeof(ev), portMAX_DELAY); if (evt_err != ESP_OK) ESP_LOGW(TAG, "Failed to post METER_EVENT_CONFIG_UPDATED (GRID): %s", esp_err_to_name(evt_err)); return err; } bool meter_manager_evse_is_enabled(void) { return meter_manager_evse_get_model() != METER_TYPE_NONE; } meter_type_t meter_manager_evse_get_model(void) { return meter_evse_type; } meter_type_t meter_manager_grid_get_model(void) { return meter_grid_type; } const char *meter_type_to_str(meter_type_t type) { switch (type) { case METER_TYPE_NONE: return "NENHUM"; case METER_TYPE_ADE7758: return "IC ADE"; case METER_TYPE_ORNO513: return "ORNO-513"; case METER_TYPE_ORNO516: return "ORNO-516"; case METER_TYPE_ORNO526: return "ORNO-526"; case METER_TYPE_DTS6619: return "DTS-6619"; case METER_TYPE_DDS661: return "DDS-661"; case METER_TYPE_MONO_ZIGBEE: return "MONO-ZIGBEE"; case METER_TYPE_TRIF_ZIGBEE: return "TRIF-ZIGBEE"; case METER_TYPE_EA777: return "EA-777"; case METER_TYPE_DTS024M: return "DTS-024M"; default: return "NENHUM"; } } meter_type_t string_to_meter_type(const char *str) { if (!str) return METER_TYPE_NONE; if (strcmp(str, "IC ADE") == 0) return METER_TYPE_ADE7758; if (strcmp(str, "ORNO-513") == 0) return METER_TYPE_ORNO513; if (strcmp(str, "ORNO-516") == 0) return METER_TYPE_ORNO516; if (strcmp(str, "ORNO-526") == 0) return METER_TYPE_ORNO526; if (strcmp(str, "DTS-6619") == 0) return METER_TYPE_DTS6619; if (strcmp(str, "DDS-661") == 0) return METER_TYPE_DDS661; if (strcmp(str, "MONO-ZIGBEE") == 0) return METER_TYPE_MONO_ZIGBEE; if (strcmp(str, "TRIF-ZIGBEE") == 0) return METER_TYPE_TRIF_ZIGBEE; if (strcmp(str, "EA-777") == 0) return METER_TYPE_EA777; if (strcmp(str, "DTS-024M") == 0) return METER_TYPE_DTS024M; return METER_TYPE_NONE; }