new upgrade

This commit is contained in:
2025-12-21 23:28:26 +00:00
parent 82fa194bd8
commit 023644a887
99 changed files with 7457 additions and 7079 deletions

View File

@@ -5,5 +5,4 @@ set(srcs
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include"
PRIV_REQUIRES nvs_flash
REQUIRES esp_event config esp_wifi evse mongoose MicroOcpp MicroOcppMongoose)
REQUIRES esp_event storage_service config esp_wifi evse mongoose MicroOcpp MicroOcppMongoose)

View File

@@ -1,32 +1,37 @@
// components/ocpp/src/ocpp.c
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <inttypes.h>
#include <math.h>
#include "esp_log.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ocpp.h"
#include "ocpp_events.h"
#include "esp_wifi.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "evse_error.h"
#include "auth_events.h"
#include "evse_events.h"
#include "evse_state.h"
#include "meter_events.h"
#include "esp_timer.h"
#include <math.h>
/* MicroOcpp includes */
#include <mongoose.h>
#include <MicroOcpp_c.h> // C-facade of MicroOcpp
#include <MicroOcppMongooseClient_c.h> // WebSocket integration for ESP-IDF
// NEW storage layer
#include "storage_service.h"
#define NVS_NAMESPACE "ocpp"
#define NVS_OCPP_ENABLED "enabled"
#define NVS_OCPP_SERVER "ocpp_server"
@@ -59,19 +64,18 @@ static esp_event_handler_instance_t s_evse_available_inst = NULL;
// --- cache de medições vindas de METER_EVENT_DATA_READY ---
typedef struct
{
// dados por fase
float vrms[3];
float irms[3];
int32_t watt[3]; // ativo por fase (W)
float frequency;
float power_factor;
// acumulados
float total_energy_Wh;
// derivados práticos
int32_t sum_watt; // soma das 3 fases
float avg_voltage; // média das 3 fases
float sum_current; // soma das 3 fases
// flag de validade
int32_t sum_watt;
float avg_voltage;
float sum_current;
bool have_data;
} ocpp_meter_cache_t;
@@ -82,18 +86,101 @@ static esp_event_handler_instance_t s_meter_inst = NULL;
// valor de oferta (A por conector)
static float s_current_offered_A = 16.0f;
// novo input apropriado
static float getCurrentOffered(void)
{
return s_current_offered_A;
}
/* =========================
* Task / Main Loop
* ========================= *
*/
// -----------------------------------------------------------------------------
// Storage helpers (robustos)
// -----------------------------------------------------------------------------
#define STORE_TO pdMS_TO_TICKS(800)
#define STORE_FLUSH_TO pdMS_TO_TICKS(2000)
static void storage_init_best_effort(void)
{
esp_err_t e = storage_service_init();
if (e != ESP_OK)
ESP_LOGW(TAG, "storage_service_init failed: %s", esp_err_to_name(e));
}
static esp_err_t store_flush_best_effort(void)
{
esp_err_t e = storage_flush_sync(STORE_FLUSH_TO);
if (e != ESP_OK)
ESP_LOGW(TAG, "storage_flush_sync failed: %s", esp_err_to_name(e));
return e;
}
static esp_err_t store_set_u8_best_effort(const char *ns, const char *key, uint8_t v)
{
for (int attempt = 0; attempt < 3; ++attempt)
{
esp_err_t e = storage_set_u8_async(ns, key, v);
if (e == ESP_OK)
return ESP_OK;
if (e == ESP_ERR_TIMEOUT)
{
(void)store_flush_best_effort();
vTaskDelay(pdMS_TO_TICKS(10));
continue;
}
return e;
}
return ESP_ERR_TIMEOUT;
}
static esp_err_t store_set_str_best_effort(const char *ns, const char *key, const char *s)
{
for (int attempt = 0; attempt < 3; ++attempt)
{
esp_err_t e = storage_set_str_async(ns, key, s ? s : "");
if (e == ESP_OK)
return ESP_OK;
if (e == ESP_ERR_TIMEOUT)
{
(void)store_flush_best_effort();
vTaskDelay(portMAX_DELAY);
continue;
}
return e;
}
return ESP_ERR_TIMEOUT;
}
// Lê string de forma segura (buffer grande -> truncagem segura para out)
static esp_err_t store_get_str_safe(const char *ns, const char *key, char *out, size_t out_sz)
{
if (!out || out_sz == 0)
return ESP_ERR_INVALID_ARG;
out[0] = '\0';
char tmp[STORAGE_MAX_VALUE_BYTES + 1];
memset(tmp, 0, sizeof(tmp));
esp_err_t e = storage_get_str_sync(ns, key, tmp, sizeof(tmp), STORE_TO);
if (e == ESP_ERR_NOT_FOUND)
return ESP_OK;
if (e != ESP_OK)
return e;
size_t n = strnlen(tmp, out_sz - 1);
memcpy(out, tmp, n);
out[n] = '\0';
return ESP_OK;
}
// -----------------------------------------------------------------------------
// Task / Main Loop
// -----------------------------------------------------------------------------
static void ocpp_task_func(void *param)
{
(void)param;
while (true)
{
if (enabled)
@@ -106,7 +193,6 @@ static void ocpp_task_func(void *param)
{
s_evse_enabled = operative;
// >>> enviar OCPP_EVENT (remoto → local)
ocpp_operative_event_t ev = {
.operative = operative,
.timestamp_us = esp_timer_get_time()};
@@ -115,8 +201,7 @@ static void ocpp_task_func(void *param)
&ev, sizeof(ev),
portMAX_DELAY);
ESP_LOGI(TAG, "[OCPP] ChangeAvailability remoto → operative=%d",
(int)operative);
ESP_LOGI(TAG, "[OCPP] ChangeAvailability remoto → operative=%d", (int)operative);
}
}
else
@@ -126,33 +211,21 @@ static void ocpp_task_func(void *param)
}
}
/* =========================
* NVS GETs
* ========================= */
// -----------------------------------------------------------------------------
// Storage GETs
// -----------------------------------------------------------------------------
bool ocpp_get_enabled(void)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &h);
if (err == ESP_ERR_NVS_NOT_FOUND)
{
// namespace ainda não existe -> default: disabled
return false;
}
if (err != ESP_OK)
{
ESP_LOGW(TAG, "nvs_open(%s) RO failed: %s", NVS_NAMESPACE, esp_err_to_name(err));
return false;
}
storage_init_best_effort();
uint8_t value = 0;
err = nvs_get_u8(h, NVS_OCPP_ENABLED, &value);
nvs_close(h);
esp_err_t err = storage_get_u8_sync(NVS_NAMESPACE, NVS_OCPP_ENABLED, &value, STORE_TO);
if (err == ESP_ERR_NVS_NOT_FOUND)
return false; // default
if (err == ESP_ERR_NOT_FOUND)
return false;
if (err != ESP_OK)
{
ESP_LOGW(TAG, "nvs_get_u8(enabled) failed: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "storage_get_u8_sync(enabled) failed: %s", esp_err_to_name(err));
return false;
}
return value != 0;
@@ -164,31 +237,12 @@ void ocpp_get_server(char *value /* out, size>=64 */)
return;
value[0] = '\0';
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &h);
if (err == ESP_ERR_NVS_NOT_FOUND)
{
// namespace ainda não existe -> default: ""
return;
}
if (err != ESP_OK)
{
ESP_LOGW(TAG, "nvs_open(%s) RO failed: %s", NVS_NAMESPACE, esp_err_to_name(err));
return;
}
storage_init_best_effort();
size_t len = 64;
err = nvs_get_str(h, NVS_OCPP_SERVER, value, &len);
nvs_close(h);
if (err == ESP_ERR_NVS_NOT_FOUND)
esp_err_t e = store_get_str_safe(NVS_NAMESPACE, NVS_OCPP_SERVER, value, 64);
if (e != ESP_OK)
{
value[0] = '\0';
return;
}
if (err != ESP_OK)
{
ESP_LOGW(TAG, "nvs_get_str(server) failed: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "store_get_str_safe(server) failed: %s", esp_err_to_name(e));
value[0] = '\0';
}
}
@@ -199,92 +253,81 @@ void ocpp_get_charge_id(char *value /* out, size>=64 */)
return;
value[0] = '\0';
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &h);
if (err == ESP_ERR_NVS_NOT_FOUND)
{
// namespace ainda não existe -> default: ""
return;
}
if (err != ESP_OK)
{
ESP_LOGW(TAG, "nvs_open(%s) RO failed: %s", NVS_NAMESPACE, esp_err_to_name(err));
return;
}
storage_init_best_effort();
size_t len = 64;
err = nvs_get_str(h, NVS_OCPP_CHARGE_ID, value, &len);
nvs_close(h);
if (err == ESP_ERR_NVS_NOT_FOUND)
esp_err_t e = store_get_str_safe(NVS_NAMESPACE, NVS_OCPP_CHARGE_ID, value, 64);
if (e != ESP_OK)
{
value[0] = '\0';
return;
}
if (err != ESP_OK)
{
ESP_LOGW(TAG, "nvs_get_str(charge_id) failed: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "store_get_str_safe(charge_id) failed: %s", esp_err_to_name(e));
value[0] = '\0';
}
}
/* =========================
* NVS SETs
* ========================= */
// --- SETTERS: RW (cria o namespace na 1ª escrita), commit e fecha ---
// -----------------------------------------------------------------------------
// Storage SETs
// -----------------------------------------------------------------------------
void ocpp_set_enabled(bool value)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &h);
if (err != ESP_OK)
storage_init_best_effort();
ESP_LOGI(TAG, "set enabled %d", value);
esp_err_t e = store_set_u8_best_effort(NVS_NAMESPACE, NVS_OCPP_ENABLED, value ? 1 : 0);
if (e != ESP_OK)
{
ESP_LOGE(TAG, "nvs_open(%s) RW failed: %s", NVS_NAMESPACE, esp_err_to_name(err));
ESP_LOGE(TAG, "store_set_u8_best_effort(enabled) failed: %s", esp_err_to_name(e));
return;
}
ESP_LOGI(TAG, "set enabled %d", value);
ESP_ERROR_CHECK(nvs_set_u8(h, NVS_OCPP_ENABLED, value ? 1 : 0));
ESP_ERROR_CHECK(nvs_commit(h));
nvs_close(h);
(void)store_flush_best_effort();
enabled = value;
}
void ocpp_set_server(char *value)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &h);
if (err != ESP_OK)
storage_init_best_effort();
ESP_LOGI(TAG, "set server %s", value ? value : "(null)");
esp_err_t e = store_set_str_best_effort(NVS_NAMESPACE, NVS_OCPP_SERVER, value ? value : "");
if (e != ESP_OK)
{
ESP_LOGE(TAG, "nvs_open(%s) RW failed: %s", NVS_NAMESPACE, esp_err_to_name(err));
ESP_LOGE(TAG, "store_set_str_best_effort(server) failed: %s", esp_err_to_name(e));
return;
}
ESP_LOGI(TAG, "set server %s", value ? value : "(null)");
ESP_ERROR_CHECK(nvs_set_str(h, NVS_OCPP_SERVER, value ? value : ""));
ESP_ERROR_CHECK(nvs_commit(h));
nvs_close(h);
(void)store_flush_best_effort();
}
void ocpp_set_charge_id(char *value)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &h);
if (err != ESP_OK)
storage_init_best_effort();
ESP_LOGI(TAG, "set charge_id %s", value ? value : "(null)");
esp_err_t e = store_set_str_best_effort(NVS_NAMESPACE, NVS_OCPP_CHARGE_ID, value ? value : "");
if (e != ESP_OK)
{
ESP_LOGE(TAG, "nvs_open(%s) RW failed: %s", NVS_NAMESPACE, esp_err_to_name(err));
ESP_LOGE(TAG, "store_set_str_best_effort(charge_id) failed: %s", esp_err_to_name(e));
return;
}
ESP_LOGI(TAG, "set charge_id %s", value ? value : "(null)");
ESP_ERROR_CHECK(nvs_set_str(h, NVS_OCPP_CHARGE_ID, value ? value : ""));
ESP_ERROR_CHECK(nvs_commit(h));
nvs_close(h);
(void)store_flush_best_effort();
}
// -----------------------------------------------------------------------------
// Event handlers (AUTH / EVSE / METER)
// -----------------------------------------------------------------------------
static void ocpp_on_auth_verify(void *arg, esp_event_base_t base, int32_t id, void *event_data)
{
(void)arg;
(void)base;
(void)id;
const auth_tag_verify_event_t *rq = (const auth_tag_verify_event_t *)event_data;
if (!rq)
return;
// Sanitizar/copiar a idTag
char idtag[AUTH_TAG_MAX_LEN];
if (rq->tag[0] == '\0')
{
@@ -299,16 +342,13 @@ static void ocpp_on_auth_verify(void *arg, esp_event_base_t base, int32_t id, vo
ESP_LOGI(TAG, "AUTH_EVENT_TAG_VERIFY: tag=%s req_id=%u", idtag, (unsigned)rq->req_id);
// Se não está pronto, apenas regista e sai (podes adaptar conforme política)
if (!enabled || g_ocpp_conn == NULL)
{
ESP_LOGW(TAG, "OCPP not ready (enabled=%d, conn=%p) ignoring verify", enabled, (void *)g_ocpp_conn);
ESP_LOGW(TAG, "OCPP not ready (enabled=%d, conn=%p) ignoring verify",
enabled, (void *)g_ocpp_conn);
return;
}
// Regra pedida:
// - se já existe transação/charge em andamento -> terminar
// - senão -> iniciar com a IDTAG recebida
if (ocpp_isTransactionActive())
{
ESP_LOGI(TAG, "Transaction active -> ocpp_end_transaction(\"%s\")", idtag);
@@ -323,6 +363,7 @@ static void ocpp_on_auth_verify(void *arg, esp_event_base_t base, int32_t id, vo
static void evse_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
{
(void)arg;
if (base != EVSE_EVENTS || id != EVSE_EVENT_STATE_CHANGED || data == NULL)
return;
@@ -343,12 +384,11 @@ static void evse_event_handler(void *arg, esp_event_base_t base, int32_t id, voi
case EVSE_STATE_EVENT_CHARGING:
s_ev_plugged = true;
s_ev_ready = true; // EV está a pedir/receber energia
s_ev_ready = true;
break;
case EVSE_STATE_EVENT_FAULT:
default:
// em falha, considera não pronto (mantém plugged se quiseres)
s_ev_ready = false;
break;
}
@@ -356,6 +396,7 @@ static void evse_event_handler(void *arg, esp_event_base_t base, int32_t id, voi
static void evse_enable_available_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
{
(void)arg;
if (base != EVSE_EVENTS || data == NULL)
return;
@@ -363,7 +404,8 @@ static void evse_enable_available_handler(void *arg, esp_event_base_t base, int3
{
const evse_enable_event_data_t *e = (const evse_enable_event_data_t *)data;
s_evse_enabled = e->enabled;
ESP_LOGI(TAG, "[EVSE] ENABLE_UPDATED: enabled=%d (ts=%lld)", (int)e->enabled, (long long)e->timestamp_us);
ESP_LOGI(TAG, "[EVSE] ENABLE_UPDATED: enabled=%d (ts=%lld)",
(int)e->enabled, (long long)e->timestamp_us);
return;
}
@@ -371,23 +413,24 @@ static void evse_enable_available_handler(void *arg, esp_event_base_t base, int3
{
const evse_available_event_data_t *e = (const evse_available_event_data_t *)data;
s_evse_available = e->available;
ESP_LOGI(TAG, "[EVSE] AVAILABLE_UPDATED: available=%d (ts=%lld)", (int)e->available, (long long)e->timestamp_us);
ESP_LOGI(TAG, "[EVSE] AVAILABLE_UPDATED: available=%d (ts=%lld)",
(int)e->available, (long long)e->timestamp_us);
return;
}
}
static void on_meter_event(void *arg, esp_event_base_t base, int32_t id, void *data)
{
(void)arg;
if (base != METER_EVENT || id != METER_EVENT_DATA_READY || !data)
return;
const meter_event_data_t *evt = (const meter_event_data_t *)data;
// Só queremos o medidor do EVSE (não o GRID)
if (!evt->source || strcmp(evt->source, "EVSE") != 0)
return;
// Derivados simples
int32_t sum_w = (int32_t)evt->watt[0] + (int32_t)evt->watt[1] + (int32_t)evt->watt[2];
float avg_v = (evt->vrms[0] + evt->vrms[1] + evt->vrms[2]) / 3.0f;
float sum_i = evt->irms[0] + evt->irms[1] + evt->irms[2];
@@ -408,22 +451,21 @@ static void on_meter_event(void *arg, esp_event_base_t base, int32_t id, void *d
portEXIT_CRITICAL(&s_meter_mux);
}
/* =========================
* MicroOCPP Inputs/CBs
* ========================= */
// -----------------------------------------------------------------------------
// MicroOCPP Inputs/CBs
// -----------------------------------------------------------------------------
bool setConnectorPluggedInput(void)
{
return s_ev_plugged; // EV fisicamente ligado
return s_ev_plugged;
}
bool setEvReadyInput(void)
{
return s_ev_ready; // EV pede / pronto a carregar
return s_ev_ready;
}
bool setEvseReadyInput(void)
{
// EVSE autorizado / operacional
return s_evse_enabled && s_evse_available;
}
@@ -439,13 +481,10 @@ float setPowerMeterInput(void)
portEXIT_CRITICAL(&s_meter_mux);
if (!have)
{
ESP_LOGW(TAG, "[METER] PowerMeterInput: no data (return 0)");
}
else
{
ESP_LOGD(TAG, "[METER] PowerMeterInput: %" PRId32 " W", w);
}
return (float)w;
}
@@ -461,14 +500,11 @@ float setEnergyMeterInput(void)
portEXIT_CRITICAL(&s_meter_mux);
if (!have)
{
ESP_LOGW(TAG, "[METER] EnergyMeterInput: no data (return 0)");
}
else
{
ESP_LOGD(TAG, "[METER] EnergyMeterInput: (%.1f Wh)", wh);
}
return wh; // agora devolve Wh
return wh;
}
int setEnergyInput(void)
@@ -491,13 +527,10 @@ float setCurrentInput(void)
portEXIT_CRITICAL(&s_meter_mux);
if (!have)
{
ESP_LOGW(TAG, "[METER] CurrentInput: no data (return 0)");
}
else
{
ESP_LOGD(TAG, "[METER] CurrentInput: %.2f A (total)", a);
}
return a;
}
@@ -513,19 +546,16 @@ float setVoltageInput(void)
portEXIT_CRITICAL(&s_meter_mux);
if (!have)
{
ESP_LOGW(TAG, "[METER] VoltageInput: no data (return 0)");
}
else
{
ESP_LOGD(TAG, "[METER] VoltageInput: %.1f V (avg)", v);
}
return v;
}
float setPowerInput(void)
{
float w = setPowerMeterInput(); // alias
float w = setPowerMeterInput();
ESP_LOGD(TAG, "[METER] PowerInput: %.1f W", w);
return w;
}
@@ -598,111 +628,63 @@ bool setOnResetNotify(bool value)
void notificationOutput(OCPP_Transaction *transaction, enum OCPP_TxNotification txNotification)
{
(void)transaction;
ESP_LOGI(TAG, "TxNotification: %d", txNotification);
switch (txNotification)
{
case Authorized:
ESP_LOGI(TAG, "Authorized");
// TODO: send event ocpp Authorized
// evse_authorize();
// Opcional: enviar idTag no payload (se tiveres como obter do transaction)
// ocpp_idtag_event_t ev = {0};
// strlcpy(ev.idTag, ocpp_tx_get_idTag(transaction), sizeof(ev.idTag));
// esp_event_post(OCPP_EVENTS, OCPP_EVENT_AUTHORIZED, &ev, sizeof(ev), portMAX_DELAY);
esp_event_post(OCPP_EVENTS, OCPP_EVENT_AUTHORIZED, NULL, 0, portMAX_DELAY);
break;
case AuthorizationRejected:
ESP_LOGI(TAG, "AuthorizationRejected");
// TODO: send event ocpp AuthorizationRejected
// ocpp_idtag_event_t ev = {0};
// strlcpy(ev.idTag, ocpp_tx_get_idTag(transaction), sizeof(ev.idTag));
// esp_event_post(OCPP_EVENTS, OCPP_EVENT_AUTH_REJECTED, &ev, sizeof(ev), portMAX_DELAY);
esp_event_post(OCPP_EVENTS, OCPP_EVENT_AUTH_REJECTED, NULL, 0, portMAX_DELAY);
break;
case AuthorizationTimeout:
ESP_LOGI(TAG, "AuthorizationTimeout");
// TODO: send event ocpp AuthorizationTimeout
esp_event_post(OCPP_EVENTS, OCPP_EVENT_AUTH_TIMEOUT, NULL, 0, portMAX_DELAY);
break;
case ReservationConflict:
ESP_LOGI(TAG, "ReservationConflict");
// TODO: send event ocpp ReservationConflict
// (Se quiseres, cria um ID específico no enum e publica aqui)
break;
case ConnectionTimeout:
ESP_LOGI(TAG, "ConnectionTimeout");
// TODO: send event ocpp ConnectionTimeout
// (Se quiseres, cria um ID específico no enum e publica aqui)
break;
case DeAuthorized:
ESP_LOGI(TAG, "DeAuthorized");
// TODO: send event ocpp DeAuthorized
// TODO: adapt to the new interface
// evse_set_authorized(false);
// evse_set_limit_reached(2);
// Poderias mapear para AUTH_REJECTED ou STOP_TX por política da aplicação:
// esp_event_post(OCPP_EVENTS, OCPP_EVENT_AUTH_REJECTED, NULL, 0, portMAX_DELAY);
break;
case RemoteStart:
ESP_LOGI(TAG, "RemoteStart");
// TODO: send event ocpp RemoteStart
// ocpp_idtag_event_t ev = {0};
// strlcpy(ev.idTag, ocpp_tx_get_idTag(transaction), sizeof(ev.idTag));
// esp_event_post(OCPP_EVENTS, OCPP_EVENT_REMOTE_START, &ev, sizeof(ev), portMAX_DELAY);
esp_event_post(OCPP_EVENTS, OCPP_EVENT_REMOTE_START, NULL, 0, portMAX_DELAY);
break;
case RemoteStop:
ESP_LOGI(TAG, "RemoteStop");
// TODO: send event ocpp RemoteStop
esp_event_post(OCPP_EVENTS, OCPP_EVENT_REMOTE_STOP, NULL, 0, portMAX_DELAY);
break;
case StartTx:
ESP_LOGI(TAG, "StartTx");
// TODO: send event ocpp StartTx
// ocpp_tx_event_t tx = { .tx_id = ocpp_tx_get_id(transaction) };
// esp_event_post(OCPP_EVENTS, OCPP_EVENT_START_TX, &tx, sizeof(tx), portMAX_DELAY);
esp_event_post(OCPP_EVENTS, OCPP_EVENT_START_TX, NULL, 0, portMAX_DELAY);
break;
case StopTx:
ESP_LOGI(TAG, "StopTx");
// TODO: send event ocpp StopTx
// TODO: adapt to the new interface
// evse_set_authorized(false);
// evse_set_limit_reached(2);
// ocpp_reason_event_t rs = {0};
// strlcpy(rs.reason, "Local", sizeof(rs.reason));
// esp_event_post(OCPP_EVENTS, OCPP_EVENT_STOP_TX, &rs, sizeof(rs), portMAX_DELAY);
esp_event_post(OCPP_EVENTS, OCPP_EVENT_STOP_TX, NULL, 0, portMAX_DELAY);
break;
}
}
// Estado de conexão simples do OCPP
bool ocpp_is_connected(void)
{
// Se quiser algo mais preciso (WS aberto), substitui por uma chamada da MicroOcpp,
// mas como fallback isto já evita o undefined symbol.
return g_ocpp_conn != NULL;
}
@@ -728,12 +710,12 @@ const char *addErrorCodeInput(void)
else if (error & EVSE_ERR_TEMPERATURE_FAULT_BIT)
ptr = "OtherError";
return ptr; // NULL => sem erro
return ptr;
}
/* =========================
* Start / Stop OCPP
* ========================= */
// -----------------------------------------------------------------------------
// Start / Stop OCPP
// -----------------------------------------------------------------------------
void ocpp_start(void)
{
ESP_LOGI(TAG, "Starting OCPP");
@@ -744,6 +726,8 @@ void ocpp_start(void)
return;
}
storage_init_best_effort();
enabled = ocpp_get_enabled();
if (!enabled)
{
@@ -767,15 +751,14 @@ void ocpp_start(void)
return;
}
/* Inicializar Mongoose + MicroOcpp */
mg_mgr_init(&mgr);
mg_log_set(MG_LL_ERROR);
struct OCPP_FilesystemOpt fsopt = {.use = true, .mount = true, .formatFsOnFail = true};
g_ocpp_conn = ocpp_makeConnection(&mgr,
serverstr, /* ex: ws://host:port/OCPP16/... */
charge_id, /* ChargeBoxId / identity */
serverstr,
charge_id,
"",
"",
fsopt);
@@ -788,19 +771,16 @@ void ocpp_start(void)
ocpp_initialize(g_ocpp_conn, "EPower M1", "Plixin", fsopt, false);
/* Inputs/outputs e callbacks */
ocpp_setEvReadyInput(&setEvReadyInput);
ocpp_setEvseReadyInput(&setEvseReadyInput);
ocpp_setConnectorPluggedInput(&setConnectorPluggedInput);
ocpp_setOnResetExecute(&OnResetExecute);
ocpp_setTxNotificationOutput(&notificationOutput);
// ocpp_setStartTxReadyInput(&setStartTxReadyInput);
ocpp_setStopTxReadyInput(&setStopTxReadyInput);
ocpp_setOnResetNotify(&setOnResetNotify);
ocpp_setEnergyMeterInput(&setEnergyInput); // inteiro Wh
ocpp_setEnergyMeterInput(&setEnergyInput);
/* Metering */
ocpp_addMeterValueInputFloat(&setCurrentInput, "Current.Import", "A", NULL, NULL);
ocpp_addMeterValueInputFloat(&getCurrentOffered, "Current.Offered", "A", NULL, NULL);
ocpp_addMeterValueInputFloat(&setVoltageInput, "Voltage", "V", NULL, NULL);
@@ -810,8 +790,7 @@ void ocpp_start(void)
ocpp_addErrorCodeInput(&addErrorCodeInput);
/* Task */
xTaskCreate(ocpp_task_func, "ocpp_task", 5 * 1024, NULL, 5, &ocpp_task);
xTaskCreate(ocpp_task_func, "ocpp_task", 5 * 1024, NULL, 3, &ocpp_task);
if (!s_auth_verify_inst)
{
@@ -821,7 +800,6 @@ void ocpp_start(void)
ESP_LOGI(TAG, "Registered AUTH_EVENT_TAG_VERIFY listener");
}
// ouvir mudanças de estado do EVSE
if (!s_evse_state_inst)
{
ESP_ERROR_CHECK(esp_event_handler_instance_register(
@@ -829,7 +807,6 @@ void ocpp_start(void)
&evse_event_handler, NULL, &s_evse_state_inst));
}
// ouvir mudanças de ENABLE / AVAILABLE do EVSE (Local → OCPP)
if (!s_evse_enable_inst)
{
ESP_ERROR_CHECK(esp_event_handler_instance_register(