new upgrade
This commit is contained in:
@@ -7,22 +7,49 @@
|
||||
#include "evse_events.h"
|
||||
#include "esp_event.h"
|
||||
#include "evse_limits.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#define EVSE_EVENT_POST_TIMEOUT_MS 50
|
||||
|
||||
static const char *TAG = "evse_session";
|
||||
|
||||
static TickType_t session_start_tick = 0;
|
||||
static uint32_t watt_seconds = 0;
|
||||
|
||||
// Tempo real (microsegundos)
|
||||
static int64_t session_start_us = 0;
|
||||
static int64_t last_tick_us = 0;
|
||||
|
||||
// Energia integrada com tempo real: soma de (W * us)
|
||||
static uint64_t watt_microseconds = 0;
|
||||
|
||||
static evse_session_t last_session;
|
||||
static bool last_session_valid = false;
|
||||
static uint32_t session_counter = 0;
|
||||
|
||||
static portMUX_TYPE session_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static void post_session_event(const evse_session_event_data_t *evt)
|
||||
{
|
||||
esp_err_t err = esp_event_post(
|
||||
EVSE_EVENTS,
|
||||
EVSE_EVENT_SESSION,
|
||||
evt,
|
||||
sizeof(*evt),
|
||||
portMAX_DELAY);
|
||||
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(TAG, "esp_event_post(EVSE_EVENT_SESSION) failed: %s", esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
void evse_session_init(void)
|
||||
{
|
||||
portENTER_CRITICAL(&session_mux);
|
||||
session_start_tick = 0;
|
||||
watt_seconds = 0;
|
||||
session_start_us = 0;
|
||||
last_tick_us = 0;
|
||||
watt_microseconds = 0;
|
||||
last_session_valid = false;
|
||||
session_counter = 0;
|
||||
portEXIT_CRITICAL(&session_mux);
|
||||
@@ -31,55 +58,65 @@ void evse_session_init(void)
|
||||
void evse_session_start(void)
|
||||
{
|
||||
TickType_t tick = xTaskGetTickCount();
|
||||
int64_t now_us = esp_timer_get_time();
|
||||
|
||||
portENTER_CRITICAL(&session_mux);
|
||||
session_start_tick = tick;
|
||||
watt_seconds = 0;
|
||||
session_start_us = now_us;
|
||||
last_tick_us = now_us;
|
||||
watt_microseconds = 0;
|
||||
session_counter++;
|
||||
uint32_t id = session_counter;
|
||||
portEXIT_CRITICAL(&session_mux);
|
||||
|
||||
evse_set_limit_reached(false);
|
||||
|
||||
ESP_LOGI(TAG, "Session started at tick %u", (unsigned)tick);
|
||||
ESP_LOGI(TAG, "Session started (id=%" PRIu32 ") tick=%u us=%" PRId64,
|
||||
id, (unsigned)tick, now_us);
|
||||
|
||||
evse_session_event_data_t evt = {
|
||||
.type = EVSE_SESSION_EVENT_STARTED,
|
||||
.session_id = session_counter,
|
||||
.session_id = id,
|
||||
.duration_s = 0,
|
||||
.energy_wh = 0,
|
||||
.avg_power_w = 0,
|
||||
.is_current = true,
|
||||
};
|
||||
|
||||
esp_event_post(EVSE_EVENTS,
|
||||
EVSE_EVENT_SESSION,
|
||||
&evt,
|
||||
sizeof(evt),
|
||||
portMAX_DELAY);
|
||||
post_session_event(&evt);
|
||||
}
|
||||
|
||||
void evse_session_end(void)
|
||||
{
|
||||
TickType_t start_tick;
|
||||
uint32_t ws;
|
||||
int64_t start_us;
|
||||
uint64_t w_us;
|
||||
uint32_t id;
|
||||
|
||||
int64_t end_us = esp_timer_get_time();
|
||||
|
||||
portENTER_CRITICAL(&session_mux);
|
||||
if (session_start_tick == 0) {
|
||||
if (session_start_tick == 0)
|
||||
{
|
||||
portEXIT_CRITICAL(&session_mux);
|
||||
ESP_LOGW(TAG, "evse_session_end called without active session");
|
||||
return;
|
||||
}
|
||||
|
||||
start_tick = session_start_tick;
|
||||
ws = watt_seconds;
|
||||
start_us = session_start_us;
|
||||
w_us = watt_microseconds;
|
||||
id = session_counter;
|
||||
|
||||
session_start_tick = 0;
|
||||
session_start_us = 0;
|
||||
last_tick_us = 0;
|
||||
watt_microseconds = 0;
|
||||
portEXIT_CRITICAL(&session_mux);
|
||||
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
uint32_t duration_s = (now - start_tick) / configTICK_RATE_HZ;
|
||||
uint32_t energy_wh = ws / 3600U;
|
||||
uint32_t avg_power = duration_s > 0 ? ws / duration_s : 0;
|
||||
uint32_t duration_s = (end_us > start_us) ? (uint32_t)((end_us - start_us) / 1000000LL) : 0;
|
||||
uint32_t energy_wh = (uint32_t)(w_us / (3600ULL * 1000000ULL));
|
||||
uint64_t watt_seconds = (uint64_t)(w_us / 1000000ULL);
|
||||
uint32_t avg_power = (duration_s > 0) ? (uint32_t)(watt_seconds / duration_s) : 0;
|
||||
|
||||
portENTER_CRITICAL(&session_mux);
|
||||
last_session.start_tick = start_tick;
|
||||
@@ -91,9 +128,9 @@ void evse_session_end(void)
|
||||
portEXIT_CRITICAL(&session_mux);
|
||||
|
||||
ESP_LOGI(TAG,
|
||||
"Session ended: duration=%" PRIu32 " s, energy=%" PRIu32
|
||||
"Session ended (id=%" PRIu32 "): duration=%" PRIu32 " s, energy=%" PRIu32
|
||||
" Wh, avg_power=%" PRIu32 " W",
|
||||
duration_s, energy_wh, avg_power);
|
||||
id, duration_s, energy_wh, avg_power);
|
||||
|
||||
evse_session_event_data_t evt = {
|
||||
.type = EVSE_SESSION_EVENT_FINISHED,
|
||||
@@ -103,21 +140,36 @@ void evse_session_end(void)
|
||||
.avg_power_w = avg_power,
|
||||
.is_current = false,
|
||||
};
|
||||
|
||||
esp_event_post(EVSE_EVENTS,
|
||||
EVSE_EVENT_SESSION,
|
||||
&evt,
|
||||
sizeof(evt),
|
||||
portMAX_DELAY);
|
||||
post_session_event(&evt);
|
||||
}
|
||||
|
||||
void evse_session_tick(void)
|
||||
{
|
||||
uint32_t power_w = evse_meter_get_instant_power();
|
||||
// Potência instantânea pode ser negativa (ruído/overflow de sensor) -> clamp
|
||||
int p = evse_meter_get_instant_power();
|
||||
uint32_t power_w = (p > 0) ? (uint32_t)p : 0;
|
||||
|
||||
int64_t now_us = esp_timer_get_time();
|
||||
|
||||
portENTER_CRITICAL(&session_mux);
|
||||
if (session_start_tick != 0) {
|
||||
watt_seconds += power_w;
|
||||
if (session_start_tick != 0)
|
||||
{
|
||||
if (last_tick_us == 0)
|
||||
{
|
||||
last_tick_us = now_us;
|
||||
}
|
||||
int64_t dt_us = now_us - last_tick_us;
|
||||
if (dt_us > 0)
|
||||
{
|
||||
// Energia incremental: W * us (64-bit)
|
||||
watt_microseconds += ((uint64_t)power_w * (uint64_t)dt_us);
|
||||
last_tick_us = now_us;
|
||||
}
|
||||
else
|
||||
{
|
||||
// relógio não devia andar para trás; ignora
|
||||
last_tick_us = now_us;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&session_mux);
|
||||
}
|
||||
@@ -127,15 +179,19 @@ bool evse_session_get(evse_session_t *out)
|
||||
if (out == NULL)
|
||||
return false;
|
||||
|
||||
TickType_t start;
|
||||
uint32_t ws;
|
||||
TickType_t start_tick;
|
||||
int64_t start_us;
|
||||
uint64_t w_us;
|
||||
bool has_current;
|
||||
evse_session_t last_copy;
|
||||
bool last_valid;
|
||||
|
||||
int64_t now_us = esp_timer_get_time();
|
||||
|
||||
portENTER_CRITICAL(&session_mux);
|
||||
start = session_start_tick;
|
||||
ws = watt_seconds;
|
||||
start_tick = session_start_tick;
|
||||
start_us = session_start_us;
|
||||
w_us = watt_microseconds;
|
||||
has_current = (session_start_tick != 0);
|
||||
last_copy = last_session;
|
||||
last_valid = last_session_valid;
|
||||
@@ -143,12 +199,12 @@ bool evse_session_get(evse_session_t *out)
|
||||
|
||||
if (has_current)
|
||||
{
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
uint32_t duration_s = (now - start) / configTICK_RATE_HZ;
|
||||
uint32_t energy_wh = ws / 3600U;
|
||||
uint32_t avg_power = duration_s > 0 ? ws / duration_s : 0;
|
||||
uint32_t duration_s = (now_us > start_us) ? (uint32_t)((now_us - start_us) / 1000000LL) : 0;
|
||||
uint32_t energy_wh = (uint32_t)(w_us / (3600ULL * 1000000ULL));
|
||||
uint64_t watt_seconds = (uint64_t)(w_us / 1000000ULL);
|
||||
uint32_t avg_power = (duration_s > 0) ? (uint32_t)(watt_seconds / duration_s) : 0;
|
||||
|
||||
out->start_tick = start;
|
||||
out->start_tick = start_tick;
|
||||
out->duration_s = duration_s;
|
||||
out->energy_wh = energy_wh;
|
||||
out->avg_power_w = avg_power;
|
||||
|
||||
Reference in New Issue
Block a user