new module

This commit is contained in:
2025-12-09 11:48:31 +00:00
parent 4820d9111e
commit e6e2622a95
98 changed files with 5349 additions and 8607 deletions

View File

@@ -7,14 +7,8 @@
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// ========================
// External state references
// ========================
//extern evse_state_t current_state; // Current EVSE FSM state
//extern TickType_t session_start_tick; // Timestamp of charging session start
#include "esp_err.h"
#include "nvs.h"
// ========================
// Concurrency protection
@@ -26,24 +20,17 @@ static portMUX_TYPE evse_mux = portMUX_INITIALIZER_UNLOCKED;
// Runtime state (volatile)
// ========================
static bool limit_reached = false;
static uint32_t consumption_limit = 0; // Energy limit in Wh
static uint32_t charging_time_limit = 0; // Time limit in seconds
static uint16_t under_power_limit = 0; // Minimum acceptable power in W
// ========================
// Default (persistent) limits
// ========================
static uint32_t default_consumption_limit = 0;
static uint32_t default_charging_time_limit = 0;
static uint16_t default_under_power_limit = 0;
static bool limit_reached = false;
static uint32_t consumption_limit = 0; // Energy limit in Wh
static uint32_t charging_time_limit = 0; // Time limit in seconds
static uint16_t under_power_limit = 0; // Minimum acceptable power in W
// ========================
// Limit status flag
// ========================
bool evse_get_limit_reached(void) {
bool evse_get_limit_reached(void)
{
bool val;
portENTER_CRITICAL(&evse_mux);
val = limit_reached;
@@ -51,17 +38,24 @@ bool evse_get_limit_reached(void) {
return val;
}
void evse_set_limit_reached(bool v) {
void evse_set_limit_reached(bool v)
{
portENTER_CRITICAL(&evse_mux);
limit_reached = v;
portEXIT_CRITICAL(&evse_mux);
}
bool evse_is_limit_reached(void)
{
return evse_get_limit_reached();
}
// ========================
// Runtime limit accessors
// ========================
uint32_t evse_get_consumption_limit(void) {
uint32_t evse_get_consumption_limit(void)
{
uint32_t val;
portENTER_CRITICAL(&evse_mux);
val = consumption_limit;
@@ -69,13 +63,47 @@ uint32_t evse_get_consumption_limit(void) {
return val;
}
void evse_set_consumption_limit(uint32_t value) {
void evse_set_consumption_limit(uint32_t value)
{
bool changed = false;
portENTER_CRITICAL(&evse_mux);
consumption_limit = value;
if (consumption_limit != value)
{
consumption_limit = value;
changed = true;
}
portEXIT_CRITICAL(&evse_mux);
if (!changed)
return;
nvs_handle_t h;
esp_err_t err = nvs_open("evse", NVS_READWRITE, &h);
if (err == ESP_OK)
{
err = nvs_set_u32(h, "def_cons_lim", value);
if (err == ESP_OK)
err = nvs_commit(h);
nvs_close(h);
if (err != ESP_OK)
{
ESP_LOGE("EVSE_LIMITS",
"Failed to persist consumption limit (%" PRIu32 " Wh): %s",
value, esp_err_to_name(err));
}
}
else
{
ESP_LOGE("EVSE_LIMITS",
"Failed to open NVS for consumption limit: %s",
esp_err_to_name(err));
}
}
uint32_t evse_get_charging_time_limit(void) {
uint32_t evse_get_charging_time_limit(void)
{
uint32_t val;
portENTER_CRITICAL(&evse_mux);
val = charging_time_limit;
@@ -83,13 +111,47 @@ uint32_t evse_get_charging_time_limit(void) {
return val;
}
void evse_set_charging_time_limit(uint32_t value) {
void evse_set_charging_time_limit(uint32_t value)
{
bool changed = false;
portENTER_CRITICAL(&evse_mux);
charging_time_limit = value;
if (charging_time_limit != value)
{
charging_time_limit = value;
changed = true;
}
portEXIT_CRITICAL(&evse_mux);
if (!changed)
return;
nvs_handle_t h;
esp_err_t err = nvs_open("evse", NVS_READWRITE, &h);
if (err == ESP_OK)
{
err = nvs_set_u32(h, "def_ch_time_lim", value);
if (err == ESP_OK)
err = nvs_commit(h);
nvs_close(h);
if (err != ESP_OK)
{
ESP_LOGE("EVSE_LIMITS",
"Failed to persist charging time limit (%" PRIu32 " s): %s",
value, esp_err_to_name(err));
}
}
else
{
ESP_LOGE("EVSE_LIMITS",
"Failed to open NVS for charging time limit: %s",
esp_err_to_name(err));
}
}
uint16_t evse_get_under_power_limit(void) {
uint16_t evse_get_under_power_limit(void)
{
uint16_t val;
portENTER_CRITICAL(&evse_mux);
val = under_power_limit;
@@ -97,92 +159,97 @@ uint16_t evse_get_under_power_limit(void) {
return val;
}
void evse_set_under_power_limit(uint16_t value) {
void evse_set_under_power_limit(uint16_t value)
{
bool changed = false;
portENTER_CRITICAL(&evse_mux);
under_power_limit = value;
if (under_power_limit != value)
{
under_power_limit = value;
changed = true;
}
portEXIT_CRITICAL(&evse_mux);
}
// ========================
// Default (persistent) limit accessors
// These values can be stored/restored via NVS
// ========================
if (!changed)
return;
uint32_t evse_get_default_consumption_limit(void) {
return default_consumption_limit;
}
nvs_handle_t h;
esp_err_t err = nvs_open("evse", NVS_READWRITE, &h);
if (err == ESP_OK)
{
err = nvs_set_u16(h, "def_un_pwr_lim", value);
if (err == ESP_OK)
err = nvs_commit(h);
nvs_close(h);
void evse_set_default_consumption_limit(uint32_t value) {
default_consumption_limit = value;
}
uint32_t evse_get_default_charging_time_limit(void) {
return default_charging_time_limit;
}
void evse_set_default_charging_time_limit(uint32_t value) {
default_charging_time_limit = value;
}
uint16_t evse_get_default_under_power_limit(void) {
return default_under_power_limit;
}
void evse_set_default_under_power_limit(uint16_t value) {
default_under_power_limit = value;
}
bool evse_is_limit_reached(void) {
return evse_get_limit_reached();
if (err != ESP_OK)
{
ESP_LOGE("EVSE_LIMITS",
"Failed to persist under-power limit (%" PRIu32 " W): %s",
(uint32_t)value, esp_err_to_name(err));
}
}
else
{
ESP_LOGE("EVSE_LIMITS",
"Failed to open NVS for under-power limit: %s",
esp_err_to_name(err));
}
}
// ========================
// Limit checking logic
// This function must be called periodically while charging.
// It will flag the session as "limit reached" when thresholds are violated.
// ========================
void evse_limits_check(void) {
// Only check during an active charging session
if (!evse_state_is_charging(evse_get_state())) {
void evse_limits_check(void)
{
// Só faz sentido durante carregamento
if (!evse_state_is_charging(evse_get_state()))
{
return;
}
evse_session_t sess;
// Retrieve accumulated data for the current session
if (!evse_session_get(&sess) || !sess.is_current) {
// If there's no active session, abort
if (!evse_session_get(&sess) || !sess.is_current)
{
// Sem sessão ativa → nada a fazer
return;
}
bool reached = false;
// 1) Energy consumption limit (Wh)
if (consumption_limit > 0 && sess.energy_wh >= consumption_limit) {
// 1) Limite de energia (Wh)
if (consumption_limit > 0 && sess.energy_wh >= consumption_limit)
{
ESP_LOGW("EVSE_LIMITS",
"Energy limit reached: %" PRIu32 " Wh ≥ %" PRIu32 " Wh",
sess.energy_wh, consumption_limit);
reached = true;
}
// 2) Charging time limit (seconds)
if (charging_time_limit > 0 && sess.duration_s >= charging_time_limit) {
// 2) Limite de tempo (s)
if (charging_time_limit > 0 && sess.duration_s >= charging_time_limit)
{
ESP_LOGW("EVSE_LIMITS",
"Charging time limit reached: %" PRIu32 " s ≥ %" PRIu32 " s",
sess.duration_s, charging_time_limit);
reached = true;
}
// 3) Under-power limit (instantaneous power)
// 3) Under-power (potência instantânea)
uint32_t inst_power = evse_meter_get_instant_power();
if (under_power_limit > 0 && inst_power < under_power_limit) {
if (under_power_limit > 0 && inst_power < under_power_limit)
{
ESP_LOGW("EVSE_LIMITS",
"Under-power limit reached: %" PRIu32 " W < %" PRIu32 " W",
(uint32_t)inst_power,
(uint32_t)under_power_limit);
"Under-power limit reached: %" PRIu32 " W < %" PRIu32 " W",
(uint32_t)inst_power,
(uint32_t)under_power_limit);
reached = true;
}
if (reached) {
if (reached)
{
evse_set_limit_reached(true);
}
}
}