141 lines
4.3 KiB
C
Executable File
141 lines
4.3 KiB
C
Executable File
#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;
|
|
|
|
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_B2:
|
|
case EVSE_STATE_C1:
|
|
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;
|
|
}
|
|
}
|
|
|
|
// =========================
|
|
// Public API
|
|
// =========================
|
|
|
|
void evse_set_state(evse_state_t state) {
|
|
bool changed = false;
|
|
evse_state_t previous_state;
|
|
|
|
portENTER_CRITICAL(&state_mux);
|
|
previous_state = current_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", "State changed from %s to %s",
|
|
evse_state_to_str(previous_state),
|
|
evse_state_to_str(state));
|
|
|
|
evse_state_event_data_t evt = {
|
|
.state = map_state_to_event(state)
|
|
};
|
|
esp_event_post(EVSE_EVENTS, EVSE_EVENT_STATE_CHANGED, &evt, sizeof(evt), portMAX_DELAY);
|
|
}
|
|
}
|
|
|
|
evse_state_t evse_get_state(void) {
|
|
portENTER_CRITICAL(&state_mux);
|
|
evse_state_t s = current_state;
|
|
portEXIT_CRITICAL(&state_mux);
|
|
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)";
|
|
case EVSE_STATE_B1: return "B1 - EV Connected (9V, Not Authorized)";
|
|
case EVSE_STATE_B2: return "B2 - EV Connected (9V, Authorized and Ready)";
|
|
case EVSE_STATE_C1: return "C1 - Charging Requested (6V, Relay Off)";
|
|
case EVSE_STATE_C2: return "C2 - Charging Active (6V, Relay On)";
|
|
case EVSE_STATE_D1: return "D1 - Ventilation Required (3V, Relay Off)";
|
|
case EVSE_STATE_D2: return "D2 - Ventilation Active (3V, Relay On)";
|
|
case EVSE_STATE_E: return "E - Error: Control Pilot Shorted to Ground (0V)";
|
|
case EVSE_STATE_F: return "F - Fault: EVSE Unavailable or No Pilot Signal";
|
|
default: return "Unknown 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", "Initialized in state: %s", evse_state_to_str(current_state));
|
|
|
|
evse_state_event_data_t evt = {
|
|
.state = map_state_to_event(current_state)
|
|
};
|
|
esp_event_post(EVSE_EVENTS, EVSE_EVENT_INIT, &evt, sizeof(evt), portMAX_DELAY);
|
|
}
|
|
|
|
void evse_state_tick(void) {
|
|
// Placeholder for future state logic
|
|
}
|
|
|
|
bool evse_state_is_charging(evse_state_t state) {
|
|
return state == EVSE_STATE_C1 || state == EVSE_STATE_C2;
|
|
}
|
|
|
|
bool evse_state_is_plugged(evse_state_t state) {
|
|
return state == EVSE_STATE_B1 || state == EVSE_STATE_B2 ||
|
|
state == EVSE_STATE_C1 || state == EVSE_STATE_C2 ||
|
|
state == EVSE_STATE_D1 || state == EVSE_STATE_D2;
|
|
}
|
|
|
|
bool evse_state_is_session(evse_state_t state) {
|
|
return state == EVSE_STATE_B2 || state == EVSE_STATE_C1 || state == EVSE_STATE_C2;
|
|
}
|
|
|
|
void evse_state_set_authorized(bool authorized) {
|
|
portENTER_CRITICAL(&state_mux);
|
|
is_authorized = authorized;
|
|
portEXIT_CRITICAL(&state_mux);
|
|
}
|
|
|
|
bool evse_state_get_authorized(void) {
|
|
portENTER_CRITICAL(&state_mux);
|
|
bool result = is_authorized;
|
|
portEXIT_CRITICAL(&state_mux);
|
|
return result;
|
|
}
|