Files
chargeflow/components/evse/evse_meter.c
2025-08-24 11:17:48 +01:00

122 lines
3.4 KiB
C

#include "evse_meter.h"
#include "meter_events.h"
#include "esp_event.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include <string.h>
#include <inttypes.h>
static const char *TAG = "evse_meter";
static SemaphoreHandle_t meter_mutex;
typedef struct
{
uint32_t power_watts[EVSE_METER_PHASE_COUNT];
float voltage[EVSE_METER_PHASE_COUNT];
float current[EVSE_METER_PHASE_COUNT];
uint32_t energy_wh;
} evse_meter_data_t;
static evse_meter_data_t meter_data;
static void on_meter_event_dispatcher(void *arg, esp_event_base_t base, int32_t id, void *data)
{
if (base == METER_EVENT && id == METER_EVENT_DATA_READY && data)
{
const meter_event_data_t *evt = (const meter_event_data_t *)data;
if (strcmp(evt->source, "EVSE") == 0)
{
evse_meter_on_meter_event(arg, data);
}
}
}
void evse_meter_on_meter_event(void *arg, void *event_data)
{
const meter_event_data_t *evt = (const meter_event_data_t *)event_data;
if (!evt)
return;
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i)
{
meter_data.power_watts[i] = evt->watt[i];
meter_data.voltage[i] = evt->vrms[i];
meter_data.current[i] = evt->irms[i];
}
meter_data.energy_wh = (uint32_t)(evt->total_energy * 1000.0f);
xSemaphoreGive(meter_mutex);
ESP_LOGI(TAG,
"Meter updated: power[W]={%" PRIu32 ",%" PRIu32 ",%" PRIu32 "}, "
"voltage[V]={%.2f,%.2f,%.2f}, "
"current[A]={%.2f,%.2f,%.2f}, "
"total_energy=%" PRIu32 "Wh",
meter_data.power_watts[0], meter_data.power_watts[1], meter_data.power_watts[2],
meter_data.voltage[0], meter_data.voltage[1], meter_data.voltage[2],
meter_data.current[0], meter_data.current[1], meter_data.current[2],
meter_data.energy_wh);
}
void evse_meter_init(void)
{
meter_mutex = xSemaphoreCreateMutex();
ESP_ERROR_CHECK(meter_mutex ? ESP_OK : ESP_FAIL);
ESP_ERROR_CHECK(esp_event_handler_register(
METER_EVENT, METER_EVENT_DATA_READY,
on_meter_event_dispatcher, NULL));
memset(&meter_data, 0, sizeof(meter_data));
ESP_LOGI(TAG, "EVSE Meter listener registered.");
}
int evse_meter_get_instant_power(void)
{
xSemaphoreTake(meter_mutex, portMAX_DELAY);
int sum = 0;
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i)
{
sum += meter_data.power_watts[i];
}
xSemaphoreGive(meter_mutex);
return sum;
}
int evse_meter_get_total_energy(void)
{
xSemaphoreTake(meter_mutex, portMAX_DELAY);
int val = meter_data.energy_wh;
xSemaphoreGive(meter_mutex);
return val;
}
void evse_meter_get_power(int power[EVSE_METER_PHASE_COUNT])
{
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i)
{
power[i] = meter_data.power_watts[i];
}
xSemaphoreGive(meter_mutex);
}
void evse_meter_get_voltage(float voltage[EVSE_METER_PHASE_COUNT])
{
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i)
{
voltage[i] = meter_data.voltage[i];
}
xSemaphoreGive(meter_mutex);
}
void evse_meter_get_current(float current[EVSE_METER_PHASE_COUNT])
{
xSemaphoreTake(meter_mutex, portMAX_DELAY);
for (int i = 0; i < EVSE_METER_PHASE_COUNT; ++i)
{
current[i] = meter_data.current[i];
}
xSemaphoreGive(meter_mutex);
}