562 lines
15 KiB
C
Executable File
562 lines
15 KiB
C
Executable File
#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 <string.h>
|
|
|
|
#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;
|
|
}
|