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

@@ -3,5 +3,5 @@ set(srcs "src/auth_types.c" "src/auth.c" "src/wiegand.c" "src/wiegand_reader.c"
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include"
PRIV_INCLUDE_DIRS "src"
PRIV_REQUIRES nvs_flash driver esp_timer
REQUIRES esp_event evse ocpp evse_link)
PRIV_REQUIRES driver esp_timer
REQUIRES esp_event evse ocpp evse_link storage_service)

View File

@@ -4,19 +4,22 @@
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/task.h>
#include <esp_log.h>
#include <esp_err.h>
#include <string.h>
#include <strings.h> // strcasecmp
#include <strings.h>
#include <stdio.h>
#include "wiegand_reader.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "storage_service.h"
#include "evse_link.h"
#include "evse_link_events.h"
#define MAX_TAGS 50
static const char *TAG = "Auth";
/* ===== Estado ===== */
@@ -25,162 +28,16 @@ static bool waiting_for_registration = false;
static char valid_tags[MAX_TAGS][AUTH_TAG_MAX_LEN];
static int tag_count = 0;
static uint32_t s_next_req_id = 1;
static bool s_wiegand_started = false; // controla se o Wiegand já foi iniciado
static bool s_wiegand_started = false;
/* ===== NVS keys ===== */
/* ===== Storage keys ===== */
#define NVS_NAMESPACE "auth"
#define NVS_TAG_PREFIX "tag_"
#define NVS_TAG_COUNT_KEY "count"
#define NVS_MODE_KEY "mode" // uint8_t
/* =========================
* NVS Persistence (tags)
* ========================= */
static void load_tags_from_nvs(void)
{
nvs_handle_t handle;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);
if (err != ESP_OK)
{
ESP_LOGW(TAG, "No stored tags in NVS (nvs_open: %s)", esp_err_to_name(err));
return;
}
uint8_t count = 0;
err = nvs_get_u8(handle, NVS_TAG_COUNT_KEY, &count);
if (err != ESP_OK)
{
ESP_LOGW(TAG, "No tag count key in NVS (nvs_get_u8: %s)", esp_err_to_name(err));
nvs_close(handle);
return;
}
tag_count = 0;
for (int i = 0; i < count && i < MAX_TAGS; i++)
{
char key[16];
char tag_buf[AUTH_TAG_MAX_LEN];
size_t len = sizeof(tag_buf);
snprintf(key, sizeof(key), "%s%d", NVS_TAG_PREFIX, i);
err = nvs_get_str(handle, key, tag_buf, &len);
if (err == ESP_OK)
{
strncpy(valid_tags[tag_count], tag_buf, AUTH_TAG_MAX_LEN - 1);
valid_tags[tag_count][AUTH_TAG_MAX_LEN - 1] = '\0';
tag_count++;
}
else
{
ESP_LOGW(TAG, "Failed to load tag %d from NVS (%s)", i, esp_err_to_name(err));
}
}
nvs_close(handle);
ESP_LOGI(TAG, "Loaded %d tags from NVS", tag_count);
}
static void save_tags_to_nvs(void)
{
nvs_handle_t handle;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "Failed to open NVS to save tags: %s", esp_err_to_name(err));
return;
}
err = nvs_set_u8(handle, NVS_TAG_COUNT_KEY, tag_count);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "nvs_set_u8(count) failed: %s", esp_err_to_name(err));
nvs_close(handle);
return;
}
for (int i = 0; i < tag_count; i++)
{
char key[16];
snprintf(key, sizeof(key), "%s%d", NVS_TAG_PREFIX, i);
err = nvs_set_str(handle, key, valid_tags[i]);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "nvs_set_str(%s) failed: %s", key, esp_err_to_name(err));
nvs_close(handle);
return;
}
}
err = nvs_commit(handle);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "nvs_commit failed when saving tags: %s", esp_err_to_name(err));
nvs_close(handle);
return;
}
nvs_close(handle);
ESP_LOGI(TAG, "Tags saved to NVS (%d tags)", tag_count);
}
/* =========================
* NVS Persistence (mode)
* ========================= */
static void load_mode_from_nvs(void)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &h);
if (err == ESP_OK)
{
uint8_t u = (uint8_t)AUTH_MODE_OPEN;
err = nvs_get_u8(h, NVS_MODE_KEY, &u);
if (err == ESP_OK)
{
if (u <= (uint8_t)AUTH_MODE_OCPP_RFID)
s_mode = (auth_mode_t)u;
}
else
{
ESP_LOGW(TAG, "No stored auth mode in NVS (nvs_get_u8: %s). Default OPEN", esp_err_to_name(err));
}
nvs_close(h);
}
else
{
ESP_LOGW(TAG, "No stored auth mode in NVS (nvs_open: %s). Default OPEN", esp_err_to_name(err));
}
ESP_LOGI(TAG, "Loaded mode = %d (%s)", (int)s_mode, auth_mode_to_str(s_mode));
}
static void save_mode_to_nvs(auth_mode_t mode)
{
nvs_handle_t h;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &h);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "Failed to open NVS to save auth mode: %s", esp_err_to_name(err));
return;
}
err = nvs_set_u8(h, NVS_MODE_KEY, (uint8_t)mode);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "nvs_set_u8(mode) failed: %s", esp_err_to_name(err));
nvs_close(h);
return;
}
err = nvs_commit(h);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "nvs_commit failed when saving mode: %s", esp_err_to_name(err));
nvs_close(h);
return;
}
nvs_close(h);
ESP_LOGI(TAG, "Saved mode = %d (%s)", (int)mode, auth_mode_to_str(mode));
}
// timeout para operações sync do storage
#define STORAGE_TO pdMS_TO_TICKS(2000)
/* =========================
* Helpers
@@ -190,37 +47,155 @@ static bool is_tag_valid(const char *tag)
for (int i = 0; i < tag_count; i++)
{
if (strncmp(valid_tags[i], tag, AUTH_TAG_MAX_LEN) == 0)
{
return true;
}
}
return false;
}
/* =========================
* Storage Persistence (tags)
* ========================= */
static void load_tags_from_storage(void)
{
uint8_t count = 0;
esp_err_t err = storage_get_u8_sync(NVS_NAMESPACE, NVS_TAG_COUNT_KEY, &count, STORAGE_TO);
if (err == ESP_ERR_NOT_FOUND)
{
ESP_LOGD(TAG, "No stored tags (count not found)");
tag_count = 0;
return;
}
if (err != ESP_OK)
{
ESP_LOGW(TAG, "Failed to read tag count (%s)", esp_err_to_name(err));
tag_count = 0;
return;
}
tag_count = 0;
for (int i = 0; i < (int)count && i < MAX_TAGS; i++)
{
char key[16];
char tag_buf[AUTH_TAG_MAX_LEN] = {0};
snprintf(key, sizeof(key), "%s%d", NVS_TAG_PREFIX, i);
err = storage_get_str_sync(NVS_NAMESPACE, key, tag_buf, sizeof(tag_buf), STORAGE_TO);
if (err == ESP_OK)
{
if (tag_buf[0] != '\0')
{
strncpy(valid_tags[tag_count], tag_buf, AUTH_TAG_MAX_LEN - 1);
valid_tags[tag_count][AUTH_TAG_MAX_LEN - 1] = '\0';
tag_count++;
}
}
else if (err == ESP_ERR_NOT_FOUND)
{
// pode acontecer se count estiver desfasado; ignora
continue;
}
else
{
ESP_LOGW(TAG, "Failed to load tag %d (%s)", i, esp_err_to_name(err));
}
}
ESP_LOGI(TAG, "Loaded %d tags from storage", tag_count);
}
static void save_tags_to_storage(void)
{
// ler count antigo (para apagar keys antigas se removemos tags)
uint8_t old_count = 0;
esp_err_t err = storage_get_u8_sync(NVS_NAMESPACE, NVS_TAG_COUNT_KEY, &old_count, STORAGE_TO);
if (err == ESP_ERR_NOT_FOUND)
old_count = 0;
// grava count + tags
(void)storage_set_u8_async(NVS_NAMESPACE, NVS_TAG_COUNT_KEY, (uint8_t)tag_count);
for (int i = 0; i < tag_count; i++)
{
char key[16];
snprintf(key, sizeof(key), "%s%d", NVS_TAG_PREFIX, i);
(void)storage_set_str_async(NVS_NAMESPACE, key, valid_tags[i]);
}
// se removemos tags: apagar chaves antigas
if (old_count > (uint8_t)tag_count)
{
for (int i = tag_count; i < (int)old_count && i < MAX_TAGS; i++)
{
char key[16];
snprintf(key, sizeof(key), "%s%d", NVS_TAG_PREFIX, i);
(void)storage_erase_key_async(NVS_NAMESPACE, key);
}
}
// opcional: forçar commit “já”
(void)storage_flush_async();
ESP_LOGD(TAG, "Tags saved to storage (%d tags)", tag_count);
}
/* =========================
* Storage Persistence (mode)
* ========================= */
static void load_mode_from_storage(void)
{
uint8_t u = (uint8_t)AUTH_MODE_OPEN;
esp_err_t err = storage_get_u8_sync(NVS_NAMESPACE, NVS_MODE_KEY, &u, STORAGE_TO);
if (err == ESP_OK)
{
if (u <= (uint8_t)AUTH_MODE_OCPP_RFID)
s_mode = (auth_mode_t)u;
else
s_mode = AUTH_MODE_OPEN;
}
else if (err == ESP_ERR_NOT_FOUND)
{
s_mode = AUTH_MODE_OPEN;
ESP_LOGD(TAG, "No stored mode -> default OPEN");
}
else
{
s_mode = AUTH_MODE_OPEN;
ESP_LOGW(TAG, "Failed to read mode (%s) -> default OPEN", esp_err_to_name(err));
}
ESP_LOGI(TAG, "Loaded mode = %d (%s)", (int)s_mode, auth_mode_to_str(s_mode));
}
static void save_mode_to_storage(auth_mode_t mode)
{
(void)storage_set_u8_async(NVS_NAMESPACE, NVS_MODE_KEY, (uint8_t)mode);
(void)storage_flush_async(); // opcional: commit mais rápido
ESP_LOGD(TAG, "Saved mode = %d (%s)", (int)mode, auth_mode_to_str(mode));
}
/* =========================
* Bridge: EVSE-Link -> AUTH (remote AUTH_GRANTED no slave)
* ========================= */
static void on_remote_auth_grant(void *arg, esp_event_base_t base, int32_t id, void *data)
{
(void)arg;
if (base != EVSE_LINK_EVENTS || id != LINK_EVENT_REMOTE_AUTH_GRANTED || data == NULL)
{
return;
}
const evse_link_auth_grant_event_t *src = (const evse_link_auth_grant_event_t *)data;
// Só faz sentido em SLAVE; em MASTER este evento não deve aparecer
if (evse_link_get_mode() != EVSE_LINK_MODE_SLAVE)
{
return;
}
auth_tag_event_data_t ev = {0};
strncpy(ev.tag, src->tag, AUTH_TAG_MAX_LEN - 1);
ev.tag[AUTH_TAG_MAX_LEN - 1] = '\0';
ev.authorized = true;
ESP_LOGI(TAG, "Remote auth grant on SLAVE for tag=%s", ev.tag);
ESP_LOGD(TAG, "Remote auth grant on SLAVE for tag=%s", ev.tag);
esp_err_t err = esp_event_post(
AUTH_EVENTS,
@@ -241,8 +216,11 @@ static void on_remote_auth_grant(void *arg, esp_event_base_t base, int32_t id, v
* ========================= */
void auth_init(void)
{
load_mode_from_nvs();
load_tags_from_nvs();
// garantir que o storage service está pronto
ESP_ERROR_CHECK(storage_service_init());
load_mode_from_storage();
load_tags_from_storage();
bool need_wiegand = (s_mode == AUTH_MODE_LOCAL_RFID || s_mode == AUTH_MODE_OCPP_RFID);
if (need_wiegand)
@@ -256,7 +234,7 @@ void auth_init(void)
ESP_LOGI(TAG, "Mode OPEN: Wiegand not started");
}
// Registar bridge para autorizações remotas vindas do EVSE-Link
// bridge EVSE-Link -> AUTH
{
esp_err_t err = esp_event_handler_register(
EVSE_LINK_EVENTS,
@@ -285,44 +263,34 @@ void auth_set_mode(auth_mode_t mode)
if (mode == s_mode)
{
ESP_LOGI(TAG, "Mode unchanged: %s", auth_mode_to_str(mode));
ESP_LOGD(TAG, "Mode unchanged: %s", auth_mode_to_str(mode));
return;
}
auth_mode_t old = s_mode;
s_mode = mode;
save_mode_to_nvs(mode);
save_mode_to_storage(mode);
bool need_wiegand = (s_mode == AUTH_MODE_LOCAL_RFID || s_mode == AUTH_MODE_OCPP_RFID);
if (need_wiegand && !s_wiegand_started)
{
ESP_LOGI(TAG, "Mode changed %s -> %s, starting Wiegand",
ESP_LOGD(TAG, "Mode changed %s -> %s, starting Wiegand",
auth_mode_to_str(old), auth_mode_to_str(s_mode));
initWiegand();
s_wiegand_started = true;
}
else if (!need_wiegand && s_wiegand_started)
{
// Aqui poderias implementar um wiegand_deinit() se o driver o expuser.
ESP_LOGI(TAG, "Mode changed %s -> %s, Wiegand remains started (no deinit implemented)",
ESP_LOGD(TAG, "Mode changed %s -> %s, Wiegand remains started (no deinit implemented)",
auth_mode_to_str(old), auth_mode_to_str(s_mode));
}
else
{
ESP_LOGI(TAG, "Mode changed %s -> %s, no change in Wiegand state",
ESP_LOGD(TAG, "Mode changed %s -> %s, no change in Wiegand state",
auth_mode_to_str(old), auth_mode_to_str(s_mode));
}
if (s_mode == AUTH_MODE_OPEN)
{
ESP_LOGI(TAG, "Mode set to OPEN");
}
else
{
ESP_LOGI(TAG, "Mode set to %s", auth_mode_to_str(s_mode));
}
auth_mode_event_data_t evt = {.mode = s_mode};
esp_event_post(AUTH_EVENTS, AUTH_EVENT_MODE_CHANGED, &evt, sizeof(evt), portMAX_DELAY);
}
@@ -338,15 +306,16 @@ bool auth_add_tag(const char *tag)
return false;
if (tag_count >= MAX_TAGS)
return false;
if (is_tag_valid(tag))
return true; // já existe
return true;
strncpy(valid_tags[tag_count], tag, AUTH_TAG_MAX_LEN - 1);
valid_tags[tag_count][AUTH_TAG_MAX_LEN - 1] = '\0';
tag_count++;
save_tags_to_nvs();
ESP_LOGI(TAG, "Tag added: %s", tag);
save_tags_to_storage();
ESP_LOGD(TAG, "Tag added: %s", tag);
return true;
}
@@ -366,8 +335,8 @@ bool auth_remove_tag(const char *tag)
}
tag_count--;
save_tags_to_nvs();
ESP_LOGI(TAG, "Tag removed: %s", tag);
save_tags_to_storage();
ESP_LOGD(TAG, "Tag removed: %s", tag);
return true;
}
}
@@ -383,11 +352,9 @@ bool auth_tag_exists(const char *tag)
void auth_list_tags(void)
{
ESP_LOGI(TAG, "Registered Tags (%d):", tag_count);
ESP_LOGD(TAG, "Registered Tags (%d):", tag_count);
for (int i = 0; i < tag_count; i++)
{
ESP_LOGI(TAG, "- %s", valid_tags[i]);
}
ESP_LOGD(TAG, "- %s", valid_tags[i]);
}
void auth_wait_for_tag_registration(void)
@@ -398,7 +365,7 @@ void auth_wait_for_tag_registration(void)
return;
}
waiting_for_registration = true;
ESP_LOGI(TAG, "Tag registration mode enabled.");
ESP_LOGD(TAG, "Tag registration mode enabled.");
}
void auth_process_tag(const char *tag)
@@ -412,11 +379,8 @@ void auth_process_tag(const char *tag)
switch (s_mode)
{
case AUTH_MODE_OPEN:
{
// Sem verificação; normalmente nem é necessário evento.
ESP_LOGI(TAG, "Mode OPEN: tag=%s (no verification)", tag);
ESP_LOGD(TAG, "Mode OPEN: tag=%s (no verification)", tag);
break;
}
case AUTH_MODE_LOCAL_RFID:
{
@@ -430,9 +394,10 @@ void auth_process_tag(const char *tag)
strncpy(ev.tag, tag, AUTH_TAG_MAX_LEN - 1);
ev.tag[AUTH_TAG_MAX_LEN - 1] = '\0';
ev.authorized = true;
esp_event_post(AUTH_EVENTS, AUTH_EVENT_TAG_SAVED,
&ev, sizeof(ev), portMAX_DELAY);
ESP_LOGI(TAG, "Tag registered: %s", tag);
ESP_LOGD(TAG, "Tag registered: %s", tag);
}
else
{
@@ -446,8 +411,9 @@ void auth_process_tag(const char *tag)
ev.tag[AUTH_TAG_MAX_LEN - 1] = '\0';
ev.authorized = is_tag_valid(tag);
ESP_LOGI(TAG, "LOCAL tag %s: %s", tag,
ESP_LOGD(TAG, "LOCAL tag %s: %s", tag,
ev.authorized ? "AUTHORIZED" : "DENIED");
esp_event_post(AUTH_EVENTS, AUTH_EVENT_TAG_PROCESSED,
&ev, sizeof(ev), portMAX_DELAY);
break;
@@ -455,13 +421,14 @@ void auth_process_tag(const char *tag)
case AUTH_MODE_OCPP_RFID:
{
// Não decide localmente. Pede validação ao OCPP.
auth_tag_verify_event_t rq = {0};
strncpy(rq.tag, tag, AUTH_TAG_MAX_LEN - 1);
rq.tag[AUTH_TAG_MAX_LEN - 1] = '\0';
rq.req_id = s_next_req_id++;
ESP_LOGI(TAG, "OCPP VERIFY requested for tag=%s (req_id=%u)",
ESP_LOGD(TAG, "OCPP VERIFY requested for tag=%s (req_id=%u)",
rq.tag, (unsigned)rq.req_id);
esp_event_post(AUTH_EVENTS, AUTH_EVENT_TAG_VERIFY,
&rq, sizeof(rq), portMAX_DELAY);
break;

View File

@@ -301,7 +301,7 @@ void initWiegand(void)
xTaskCreate(wiegand_task, TAG, configMINIMAL_STACK_SIZE * 4, NULL, 4, NULL);
// Para testes, podes ativar o simulador:
//ESP_LOGI(TAG, "Inicializando Wiegand simulado");
//xTaskCreate(wiegand_sim_task, "WiegandSim",
// ESP_LOGI(TAG, "Inicializando Wiegand simulado");
// xTaskCreate(wiegand_sim_task, "WiegandSim",
// configMINIMAL_STACK_SIZE * 3, NULL, 3, NULL);
}