#include "evse_state.h" #include "evse_api.h" #include "evse_limits.h" #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 // ======================== // Concurrency protection // ======================== 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; // ======================== // Limit status flag // ======================== bool evse_get_limit_reached(void) { bool val; portENTER_CRITICAL(&evse_mux); val = limit_reached; portEXIT_CRITICAL(&evse_mux); return val; } void evse_set_limit_reached(bool v) { portENTER_CRITICAL(&evse_mux); limit_reached = v; portEXIT_CRITICAL(&evse_mux); } // ======================== // Runtime limit accessors // ======================== uint32_t evse_get_consumption_limit(void) { uint32_t val; portENTER_CRITICAL(&evse_mux); val = consumption_limit; portEXIT_CRITICAL(&evse_mux); return val; } void evse_set_consumption_limit(uint32_t value) { portENTER_CRITICAL(&evse_mux); consumption_limit = value; portEXIT_CRITICAL(&evse_mux); } uint32_t evse_get_charging_time_limit(void) { uint32_t val; portENTER_CRITICAL(&evse_mux); val = charging_time_limit; portEXIT_CRITICAL(&evse_mux); return val; } void evse_set_charging_time_limit(uint32_t value) { portENTER_CRITICAL(&evse_mux); charging_time_limit = value; portEXIT_CRITICAL(&evse_mux); } uint16_t evse_get_under_power_limit(void) { uint16_t val; portENTER_CRITICAL(&evse_mux); val = under_power_limit; portEXIT_CRITICAL(&evse_mux); return val; } void evse_set_under_power_limit(uint16_t value) { portENTER_CRITICAL(&evse_mux); under_power_limit = value; portEXIT_CRITICAL(&evse_mux); } // ======================== // Default (persistent) limit accessors // These values can be stored/restored via NVS // ======================== uint32_t evse_get_default_consumption_limit(void) { return default_consumption_limit; } 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(); } // ======================== // 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) { evse_state_t state = evse_get_state(); if (!evse_state_is_charging(state)) return; bool reached = false; uint32_t energy = evse_get_total_energy(); uint32_t power = evse_get_instant_power(); TickType_t now = xTaskGetTickCount(); TickType_t start = evse_get_session_start(); if (consumption_limit > 0 && energy >= consumption_limit) { ESP_LOGW("EVSE", "Energy limit reached"); reached = true; } if (charging_time_limit > 0 && (now - start) >= pdMS_TO_TICKS(charging_time_limit * 1000)) { ESP_LOGW("EVSE", "Charging time limit reached"); reached = true; } if (under_power_limit > 0 && power < under_power_limit) { ESP_LOGW("EVSE", "Under power limit reached"); reached = true; } if (reached) { evse_set_limit_reached(true); } }