new meter
This commit is contained in:
@@ -50,7 +50,7 @@ void evse_process(void) {
|
||||
evse_config_is_enabled()
|
||||
);
|
||||
|
||||
evse_limits_check(evse_get_state());
|
||||
evse_limits_check();
|
||||
|
||||
evse_state_t current = evse_get_state();
|
||||
if (current != last_state) {
|
||||
@@ -99,3 +99,12 @@ static void evse_core_task(void *arg) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t evse_get_total_energy(void) {
|
||||
return 0; // Stub de 1 kWh
|
||||
}
|
||||
|
||||
uint32_t evse_get_instant_power(void) {
|
||||
return 0; // Stub de 2 kW
|
||||
}
|
||||
|
||||
|
||||
@@ -1,62 +1,108 @@
|
||||
#include "evse_state.h"
|
||||
#include "evse_api.h"
|
||||
#include "evse_limits.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
|
||||
// ========================
|
||||
// Estado interno
|
||||
// External state references
|
||||
// ========================
|
||||
|
||||
static bool limit_reached = false;
|
||||
static uint32_t consumption_limit = 0;
|
||||
static uint32_t charging_time_limit = 0;
|
||||
static uint16_t under_power_limit = 0;
|
||||
//extern evse_state_t current_state; // Current EVSE FSM state
|
||||
//extern TickType_t session_start_tick; // Timestamp of charging session start
|
||||
|
||||
static uint32_t default_consumption_limit = 0;
|
||||
// ========================
|
||||
// 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;
|
||||
static uint16_t default_under_power_limit = 0;
|
||||
|
||||
// ========================
|
||||
// Estado de controle
|
||||
// Limit status flag
|
||||
// ========================
|
||||
|
||||
void evse_set_limit_reached(uint8_t value) {
|
||||
limit_reached = (value != 0);
|
||||
bool evse_get_limit_reached(void) {
|
||||
bool val;
|
||||
portENTER_CRITICAL(&evse_mux);
|
||||
val = limit_reached;
|
||||
portEXIT_CRITICAL(&evse_mux);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool evse_is_limit_reached(void) {
|
||||
return limit_reached;
|
||||
void evse_set_limit_reached(bool v) {
|
||||
portENTER_CRITICAL(&evse_mux);
|
||||
limit_reached = v;
|
||||
portEXIT_CRITICAL(&evse_mux);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Limites em tempo de execução
|
||||
// Runtime limit accessors
|
||||
// ========================
|
||||
|
||||
uint32_t evse_get_consumption_limit(void) {
|
||||
return consumption_limit;
|
||||
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) {
|
||||
return charging_time_limit;
|
||||
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) {
|
||||
return under_power_limit;
|
||||
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);
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Limites padrão (persistentes)
|
||||
// Default (persistent) limit accessors
|
||||
// These values can be stored/restored via NVS
|
||||
// ========================
|
||||
|
||||
uint32_t evse_get_default_consumption_limit(void) {
|
||||
@@ -83,15 +129,45 @@ 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();
|
||||
}
|
||||
|
||||
|
||||
// ========================
|
||||
// Lógica de verificação de limites
|
||||
// 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(evse_state_t state) {
|
||||
// Se algum limite estiver ativo, verifique o estado
|
||||
if ((consumption_limit > 0 || charging_time_limit > 0 || under_power_limit > 0)
|
||||
&& evse_state_is_charging(state)) {
|
||||
// (Lógica real a ser aplicada aqui, ex: medição de consumo, tempo ou potência)
|
||||
evse_set_limit_reached(1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,41 @@
|
||||
#include "evse_api.h"
|
||||
#include "evse_state.h"
|
||||
#include "evse_events.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
// =========================
|
||||
// Internal State Variables
|
||||
// =========================
|
||||
|
||||
static evse_state_t current_state = EVSE_STATE_A;
|
||||
static bool is_authorized = false;
|
||||
static TickType_t session_start_tick = 0;
|
||||
|
||||
// Proteção básica para variáveis globais em sistemas concorrentes
|
||||
static portMUX_TYPE state_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// =========================
|
||||
// Internal Mapping
|
||||
// =========================
|
||||
|
||||
static evse_state_event_t map_state_to_event(evse_state_t s) {
|
||||
switch (s) {
|
||||
case EVSE_STATE_A:
|
||||
return EVSE_STATE_EVENT_IDLE;
|
||||
case EVSE_STATE_B1:
|
||||
return EVSE_STATE_EVENT_WAITING;
|
||||
case EVSE_STATE_A: return EVSE_STATE_EVENT_IDLE;
|
||||
case EVSE_STATE_B1: return EVSE_STATE_EVENT_WAITING;
|
||||
case EVSE_STATE_B2:
|
||||
case EVSE_STATE_C1:
|
||||
case EVSE_STATE_C2:
|
||||
return EVSE_STATE_EVENT_CHARGING;
|
||||
case EVSE_STATE_C2: return EVSE_STATE_EVENT_CHARGING;
|
||||
case EVSE_STATE_E:
|
||||
case EVSE_STATE_F:
|
||||
return EVSE_STATE_EVENT_FAULT;
|
||||
default:
|
||||
return EVSE_STATE_EVENT_IDLE;
|
||||
case EVSE_STATE_F: return EVSE_STATE_EVENT_FAULT;
|
||||
default: return EVSE_STATE_EVENT_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Public API
|
||||
// =========================
|
||||
|
||||
void evse_set_state(evse_state_t state) {
|
||||
bool changed = false;
|
||||
evse_state_t previous_state;
|
||||
@@ -36,11 +45,15 @@ void evse_set_state(evse_state_t state) {
|
||||
if (state != current_state) {
|
||||
current_state = state;
|
||||
changed = true;
|
||||
|
||||
if (evse_state_is_charging(state) && !evse_state_is_charging(previous_state)) {
|
||||
session_start_tick = xTaskGetTickCount();
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&state_mux);
|
||||
|
||||
if (changed) {
|
||||
ESP_LOGI("EVSE_STATE", "Estado alterado de %s para %s",
|
||||
ESP_LOGI("EVSE_STATE", "State changed from %s to %s",
|
||||
evse_state_to_str(previous_state),
|
||||
evse_state_to_str(state));
|
||||
|
||||
@@ -58,6 +71,13 @@ evse_state_t evse_get_state(void) {
|
||||
return s;
|
||||
}
|
||||
|
||||
TickType_t evse_get_session_start(void) {
|
||||
portENTER_CRITICAL(&state_mux);
|
||||
TickType_t t = session_start_tick;
|
||||
portEXIT_CRITICAL(&state_mux);
|
||||
return t;
|
||||
}
|
||||
|
||||
const char* evse_state_to_str(evse_state_t state) {
|
||||
switch (state) {
|
||||
case EVSE_STATE_A: return "A - EV Not Connected (12V)";
|
||||
@@ -76,10 +96,11 @@ const char* evse_state_to_str(evse_state_t state) {
|
||||
void evse_state_init(void) {
|
||||
portENTER_CRITICAL(&state_mux);
|
||||
current_state = EVSE_STATE_A;
|
||||
session_start_tick = xTaskGetTickCount();
|
||||
is_authorized = true;
|
||||
portEXIT_CRITICAL(&state_mux);
|
||||
|
||||
ESP_LOGI("EVSE_STATE", "Inicializado em estado: %s", evse_state_to_str(current_state));
|
||||
ESP_LOGI("EVSE_STATE", "Initialized in state: %s", evse_state_to_str(current_state));
|
||||
|
||||
evse_state_event_data_t evt = {
|
||||
.state = map_state_to_event(current_state)
|
||||
@@ -88,7 +109,7 @@ void evse_state_init(void) {
|
||||
}
|
||||
|
||||
void evse_state_tick(void) {
|
||||
// Tick do estado (placeholder)
|
||||
// Placeholder for future state logic
|
||||
}
|
||||
|
||||
bool evse_state_is_charging(evse_state_t state) {
|
||||
|
||||
@@ -50,7 +50,13 @@ void evse_set_charging_time_limit(uint32_t value);
|
||||
uint16_t evse_get_under_power_limit(void);
|
||||
void evse_set_under_power_limit(uint16_t value);
|
||||
|
||||
void evse_set_limit_reached(uint8_t value);
|
||||
void evse_set_limit_reached(bool value);
|
||||
|
||||
// Energia total acumulada da sessão (em Wh)
|
||||
uint32_t evse_get_total_energy(void);
|
||||
|
||||
// Potência instantânea medida (em W)
|
||||
uint32_t evse_get_instant_power(void);
|
||||
|
||||
// Limites default
|
||||
uint32_t evse_get_default_consumption_limit(void);
|
||||
@@ -60,4 +66,10 @@ void evse_set_default_charging_time_limit(uint32_t value);
|
||||
uint16_t evse_get_default_under_power_limit(void);
|
||||
void evse_set_default_under_power_limit(uint16_t value);
|
||||
|
||||
|
||||
uint32_t evse_get_total_energy(void);
|
||||
uint32_t evse_get_instant_power(void);
|
||||
|
||||
|
||||
|
||||
#endif // EVSE_API_H
|
||||
|
||||
@@ -9,24 +9,47 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Estado dos limites
|
||||
void evse_set_limit_reached(uint8_t value);
|
||||
bool evse_is_limit_reached(void);
|
||||
// ========================
|
||||
// Limit state control
|
||||
// ========================
|
||||
|
||||
/// Verifica e aplica lógica de limites com base no estado atual do EVSE
|
||||
void evse_limits_check(evse_state_t state);
|
||||
/**
|
||||
* @brief Sets the 'limit reached' flag. Used internally when a session exceeds defined thresholds.
|
||||
*/
|
||||
void evse_set_limit_reached(bool value);
|
||||
|
||||
/**
|
||||
* @brief Returns whether any session limit has been reached (energy, time or power).
|
||||
*/
|
||||
bool evse_get_limit_reached(void);
|
||||
|
||||
// ========================
|
||||
// Limit checking
|
||||
// ========================
|
||||
|
||||
/**
|
||||
* @brief Evaluates if the session has exceeded any configured limits.
|
||||
* Should be called periodically while in charging state.
|
||||
*/
|
||||
void evse_limits_check(void);
|
||||
|
||||
// ========================
|
||||
// Runtime limit configuration
|
||||
// ========================
|
||||
|
||||
/// Limites ativos (runtime)
|
||||
uint32_t evse_get_consumption_limit(void);
|
||||
void evse_set_consumption_limit(uint32_t value);
|
||||
void evse_set_consumption_limit(uint32_t value); // in Wh
|
||||
|
||||
uint32_t evse_get_charging_time_limit(void);
|
||||
void evse_set_charging_time_limit(uint32_t value);
|
||||
void evse_set_charging_time_limit(uint32_t value); // in seconds
|
||||
|
||||
uint16_t evse_get_under_power_limit(void);
|
||||
void evse_set_under_power_limit(uint16_t value);
|
||||
void evse_set_under_power_limit(uint16_t value); // in Watts
|
||||
|
||||
// ========================
|
||||
// Default (persistent) limits
|
||||
// ========================
|
||||
|
||||
/// Limites padrão (persistentes)
|
||||
uint32_t evse_get_default_consumption_limit(void);
|
||||
void evse_set_default_consumption_limit(uint32_t value);
|
||||
|
||||
|
||||
@@ -1,49 +1,95 @@
|
||||
#ifndef EVSE_STATE_H
|
||||
#define EVSE_STATE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "evse_events.h"
|
||||
|
||||
// ============================
|
||||
// EVSE Pilot Signal States
|
||||
// ============================
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
// Estado do EVSE (pilot signal)
|
||||
typedef enum {
|
||||
EVSE_STATE_A,
|
||||
EVSE_STATE_B1,
|
||||
EVSE_STATE_B2,
|
||||
EVSE_STATE_C1,
|
||||
EVSE_STATE_C2,
|
||||
EVSE_STATE_D1,
|
||||
EVSE_STATE_D2,
|
||||
EVSE_STATE_E,
|
||||
EVSE_STATE_F
|
||||
EVSE_STATE_A, // EV Not Connected (12V)
|
||||
EVSE_STATE_B1, // EV Connected (9V, Not Authorized)
|
||||
EVSE_STATE_B2, // EV Connected (9V, Authorized and Ready)
|
||||
EVSE_STATE_C1, // Charging Requested (6V, Relay Off)
|
||||
EVSE_STATE_C2, // Charging Active (6V, Relay On)
|
||||
EVSE_STATE_D1, // Ventilation Required (3V, Relay Off)
|
||||
EVSE_STATE_D2, // Ventilation Active (3V, Relay On)
|
||||
EVSE_STATE_E, // Error: Pilot Short to Ground (0V)
|
||||
EVSE_STATE_F // Fault: No Pilot or EVSE Unavailable
|
||||
} evse_state_t;
|
||||
|
||||
// ============================
|
||||
// Initialization & Core Control
|
||||
// ============================
|
||||
|
||||
// Funções públicas necessárias
|
||||
/**
|
||||
* @brief Initializes the EVSE state machine.
|
||||
*/
|
||||
void evse_state_init(void);
|
||||
|
||||
/**
|
||||
* @brief Periodic tick function for the state machine.
|
||||
*/
|
||||
void evse_state_tick(void);
|
||||
|
||||
void evse_state_set_authorized(bool authorized);
|
||||
bool evse_state_get_authorized(void);
|
||||
|
||||
// ============================
|
||||
// State Access
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Returns the current EVSE state.
|
||||
*/
|
||||
evse_state_t evse_get_state(void);
|
||||
|
||||
/**
|
||||
* @brief Updates the current EVSE state and triggers events.
|
||||
*/
|
||||
void evse_set_state(evse_state_t state);
|
||||
|
||||
// Converte o estado para string
|
||||
/**
|
||||
* @brief Returns the tick count when charging session started.
|
||||
*/
|
||||
TickType_t evse_get_session_start(void);
|
||||
|
||||
/**
|
||||
* @brief Converts the state enum to a human-readable string.
|
||||
*/
|
||||
const char* evse_state_to_str(evse_state_t state);
|
||||
|
||||
// Retorna true se o estado representa sessão ativa
|
||||
// ============================
|
||||
// State Evaluators
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Returns true if the state represents an active session (B2, C1, C2).
|
||||
*/
|
||||
bool evse_state_is_session(evse_state_t state);
|
||||
|
||||
// Retorna true se o estado representa carregamento ativo
|
||||
/**
|
||||
* @brief Returns true if the state represents active charging (C1, C2).
|
||||
*/
|
||||
bool evse_state_is_charging(evse_state_t state);
|
||||
|
||||
// Retorna true se o estado representa veículo conectado
|
||||
/**
|
||||
* @brief Returns true if the vehicle is plugged in.
|
||||
*/
|
||||
bool evse_state_is_plugged(evse_state_t state);
|
||||
|
||||
//evse_state_event_t map_state_to_event(evse_state_t state);
|
||||
// ============================
|
||||
// Authorization
|
||||
// ============================
|
||||
|
||||
/**
|
||||
* @brief Sets the vehicle authorization state.
|
||||
*/
|
||||
void evse_state_set_authorized(bool authorized);
|
||||
|
||||
/**
|
||||
* @brief Returns the current vehicle authorization state.
|
||||
*/
|
||||
bool evse_state_get_authorized(void);
|
||||
|
||||
#endif // EVSE_STATE_H
|
||||
|
||||
@@ -311,7 +311,7 @@ void notificationOutput(OCPP_Transaction *transaction, enum OCPP_TxNotification
|
||||
case DeAuthorized:
|
||||
ESP_LOGI(TAG, "DeAuthorized ---->");
|
||||
//evse_set_authorized(false);
|
||||
evse_set_limit_reached(2);
|
||||
//evse_set_limit_reached(2);
|
||||
// ocpp_set_charging(false);
|
||||
break; // server rejected StartTx
|
||||
case RemoteStart:
|
||||
|
||||
Reference in New Issue
Block a user