new upgrade
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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(¬ificationOutput);
|
||||
// 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(
|
||||
|
||||
Reference in New Issue
Block a user