refact auth

This commit is contained in:
2025-06-08 10:06:28 +01:00
parent 71b6cb7878
commit 214cf1ee04
236 changed files with 466 additions and 251 deletions

View File

@@ -1,17 +1,39 @@
#ifndef AUTH_H #ifndef AUTH_H
#define AUTH_H #define AUTH_H
#pragma once
#include <stdbool.h> #include <stdbool.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
void auth_init(void); // Iniciar serviço #ifdef __cplusplus
void auth_set_enabled(bool enabled); // Habilitar ou desabilitar leitura extern "C" {
bool auth_is_enabled(void); // Verificar estado #endif
bool auth_add_tag(const char *tag); // Adiciona uma tag válida #define AUTH_TAG_MAX_LEN 20
bool auth_remove_tag(const char *tag); // Remove tag
bool auth_tag_exists(const char *tag); // Verifica se tag é válida typedef struct {
void auth_list_tags(void); // Opcional: listar no log char tag[AUTH_TAG_MAX_LEN];
bool authorized;
} auth_event_t;
// Inicializa autenticação (ex: tabela de tags)
void auth_init(void);
// Ativa ou desativa o sistema de autenticação
void auth_set_enabled(bool value);
bool auth_is_enabled(void);
// Gerenciamento de tags
bool auth_add_tag(const char *tag);
bool auth_remove_tag(const char *tag);
bool auth_tag_exists(const char *tag);
void auth_list_tags(void);
// Integração com fila de eventos
void auth_set_event_queue(QueueHandle_t queue);
#ifdef __cplusplus
}
#endif
#endif // AUTH_H #endif // AUTH_H

View File

@@ -1,15 +1,14 @@
/* #ifndef WIEGAND_READER_H
* rc522.h #define WIEGAND_READER_H
*
* Created on:
* Author:
*/
#ifndef MAIN_WIEGAND_H_ #ifdef __cplusplus
#define MAIN_WIEGAND_H_ extern "C" {
#endif
#include <stdio.h> void initWiegand(void);
void initWiegand(); #ifdef __cplusplus
}
#endif
#endif /* MAIN_WIEGAND_H_ */ #endif // WIEGAND_READER_H

View File

@@ -1,22 +1,32 @@
/*
* auth.c
*/
#include "auth.h" #include "auth.h"
#include "wiegand_reader.h"
#include "wiegand_handler.h"
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
#include <freertos/queue.h>
#include <esp_log.h> #include <esp_log.h>
#include <string.h> #include <string.h>
#include "wiegand_reader.h" // necessário para initWiegand()
#define MAX_TAGS 50 #define MAX_TAGS 50
#define TAG_LEN 20
static const char *TAG = "Auth"; static const char *TAG = "Auth";
static bool enabled = true; static bool enabled = true;
static char valid_tags[MAX_TAGS][TAG_LEN]; static char valid_tags[MAX_TAGS][AUTH_TAG_MAX_LEN];
static int tag_count = 0; static int tag_count = 0;
// Fila para enviar eventos de autenticação
static QueueHandle_t event_queue = NULL;
void auth_set_event_queue(QueueHandle_t queue) {
event_queue = queue;
}
static bool is_tag_valid(const char *tag) { static bool is_tag_valid(const char *tag) {
for (int i = 0; i < tag_count; i++) { for (int i = 0; i < tag_count; i++) {
if (strncmp(valid_tags[i], tag, TAG_LEN) == 0) { if (strncmp(valid_tags[i], tag, AUTH_TAG_MAX_LEN) == 0) {
return true; return true;
} }
} }
@@ -25,7 +35,7 @@ static bool is_tag_valid(const char *tag) {
void auth_set_enabled(bool value) { void auth_set_enabled(bool value) {
enabled = value; enabled = value;
ESP_LOGI(TAG, "Wiegand reader %s", enabled ? "ENABLED" : "DISABLED"); ESP_LOGI(TAG, "Auth %s", enabled ? "ENABLED" : "DISABLED");
} }
bool auth_is_enabled(void) { bool auth_is_enabled(void) {
@@ -34,10 +44,11 @@ bool auth_is_enabled(void) {
bool auth_add_tag(const char *tag) { bool auth_add_tag(const char *tag) {
if (tag_count >= MAX_TAGS) return false; if (tag_count >= MAX_TAGS) return false;
if (auth_tag_exists(tag)) return true; if (!tag || strlen(tag) >= AUTH_TAG_MAX_LEN) return false;
if (is_tag_valid(tag)) return true;
strncpy(valid_tags[tag_count], tag, TAG_LEN - 1); strncpy(valid_tags[tag_count], tag, AUTH_TAG_MAX_LEN - 1);
valid_tags[tag_count][TAG_LEN - 1] = '\0'; valid_tags[tag_count][AUTH_TAG_MAX_LEN - 1] = '\0';
tag_count++; tag_count++;
ESP_LOGI(TAG, "Tag added: %s", tag); ESP_LOGI(TAG, "Tag added: %s", tag);
return true; return true;
@@ -45,9 +56,9 @@ bool auth_add_tag(const char *tag) {
bool auth_remove_tag(const char *tag) { bool auth_remove_tag(const char *tag) {
for (int i = 0; i < tag_count; i++) { for (int i = 0; i < tag_count; i++) {
if (strncmp(valid_tags[i], tag, TAG_LEN) == 0) { if (strncmp(valid_tags[i], tag, AUTH_TAG_MAX_LEN) == 0) {
for (int j = i; j < tag_count - 1; j++) { for (int j = i; j < tag_count - 1; j++) {
strncpy(valid_tags[j], valid_tags[j + 1], TAG_LEN); strncpy(valid_tags[j], valid_tags[j + 1], AUTH_TAG_MAX_LEN);
} }
tag_count--; tag_count--;
ESP_LOGI(TAG, "Tag removed: %s", tag); ESP_LOGI(TAG, "Tag removed: %s", tag);
@@ -68,41 +79,29 @@ void auth_list_tags(void) {
} }
} }
// Função de callback para o reader void auth_init(void) {
static void on_card_read(const wiegand_packet_t *packet) { auth_set_enabled(true); // Default: enabled
if (!enabled) { initWiegand(); // Inicializa automaticamente o leitor Wiegand 26
ESP_LOGW(TAG, "Ignoring Wiegand data: reader is disabled"); }
void auth_process_tag(const char *tag) {
if (!tag || !auth_is_enabled()) {
ESP_LOGW(TAG, "Auth disabled or NULL tag received.");
return; return;
} }
char tag[TAG_LEN]; auth_event_t event;
memset(tag, 0, TAG_LEN); strncpy(event.tag, tag, AUTH_TAG_MAX_LEN - 1);
event.tag[AUTH_TAG_MAX_LEN - 1] = '\0';
event.authorized = is_tag_valid(tag);
if (packet->bits == 26) { ESP_LOGI(TAG, "Tag %s: %s", tag, event.authorized ? "AUTHORIZED" : "DENIED");
snprintf(tag, TAG_LEN, "%03d%03d%03d", packet->data[0], packet->data[1], packet->data[2]);
} else if (packet->bits == 34) {
snprintf(tag, TAG_LEN, "%03d%03d%03d%03d", packet->data[0], packet->data[1], packet->data[2], packet->data[3]);
} else {
ESP_LOGW(TAG, "Unsupported bit length: %d", packet->bits);
return;
}
ESP_LOGI(TAG, "Tag read: %s", tag); if (event_queue) {
if (xQueueSend(event_queue, &event, pdMS_TO_TICKS(100)) != pdPASS) {
if (is_tag_valid(tag)) { ESP_LOGW(TAG, "Auth event queue full, dropping tag: %s", tag);
ESP_LOGI(TAG, "Authorized tag.");
evse_authorize();
if (ocpp_is_TransactionActive()) {
ocpp_end_transaction(tag);
} else {
ocpp_begin_transaction(tag);
} }
} else { } else {
ESP_LOGW(TAG, "Unauthorized tag."); ESP_LOGW(TAG, "Auth event queue not set");
} }
} }
void auth_init(void) {
wiegand_reader_init(19, 18, on_card_read);
}

View File

@@ -1,18 +1,181 @@
#include "wiegand_reader.h" /**
#include "wiegand.h" * @file wiegand.c
*
* ESP-IDF Wiegand protocol receiver
*/
#include <esp_log.h> #include <esp_log.h>
#include <freertos/FreeRTOS.h> #include <string.h>
#include <stdlib.h>
#include <esp_idf_lib_helpers.h>
#include "wiegand.h"
static const char *TAG = "WiegandReader"; static const char *TAG = "wiegand";
static wiegand_reader_t reader; #define TIMER_INTERVAL_US 50000 // 50ms
void wiegand_reader_init(int pin_d0, int pin_d1, wiegand_callback_t callback) #define CHECK(x) \
do \
{ \
esp_err_t __; \
if ((__ = x) != ESP_OK) \
return __; \
} while (0)
#define CHECK_ARG(VAL) \
do \
{ \
if (!(VAL)) \
return ESP_ERR_INVALID_ARG; \
} while (0)
static void isr_disable(wiegand_reader_t *reader)
{ {
esp_err_t err = wiegand_reader_config(&reader, pin_d0, pin_d1, gpio_set_intr_type(reader->gpio_d0, GPIO_INTR_DISABLE);
callback, gpio_set_intr_type(reader->gpio_d1, GPIO_INTR_DISABLE);
WIEGAND_MSB_FIRST, WIEGAND_LSB_FIRST); }
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to init Wiegand reader: %s", esp_err_to_name(err)); static void isr_enable(wiegand_reader_t *reader)
} {
gpio_set_intr_type(reader->gpio_d0, GPIO_INTR_NEGEDGE);
gpio_set_intr_type(reader->gpio_d1, GPIO_INTR_NEGEDGE);
}
#if HELPER_TARGET_IS_ESP32
static void IRAM_ATTR isr_handler(void *arg)
#else
static void isr_handler(void *arg)
#endif
{
wiegand_reader_t *reader = (wiegand_reader_t *)arg;
if (!reader->enabled)
return;
int d0 = gpio_get_level(reader->gpio_d0);
int d1 = gpio_get_level(reader->gpio_d1);
// ignore equal
if (d0 == d1)
return;
// overflow
if (reader->bits >= reader->size * 8)
return;
esp_timer_stop(reader->timer);
uint8_t value;
if (reader->bit_order == WIEGAND_MSB_FIRST)
value = (d0 ? 0x80 : 0) >> (reader->bits % 8);
else
value = (d0 ? 1 : 0) << (reader->bits % 8);
if (reader->byte_order == WIEGAND_MSB_FIRST)
reader->buf[reader->size - reader->bits / 8 - 1] |= value;
else
reader->buf[reader->bits / 8] |= value;
reader->bits++;
esp_timer_start_once(reader->timer, TIMER_INTERVAL_US);
}
static void timer_handler(void *arg)
{
wiegand_reader_t *reader = (wiegand_reader_t *)arg;
ESP_LOGI(TAG, "Got %d bits of data", reader->bits);
wiegand_reader_disable(reader);
if (reader->callback)
reader->callback(reader);
wiegand_reader_enable(reader);
isr_enable(reader);
}
////////////////////////////////////////////////////////////////////////////////
esp_err_t wiegand_reader_init(wiegand_reader_t *reader, gpio_num_t gpio_d0, gpio_num_t gpio_d1,
bool internal_pullups, size_t buf_size, wiegand_callback_t callback, wiegand_order_t bit_order,
wiegand_order_t byte_order)
{
CHECK_ARG(reader && buf_size && callback);
esp_err_t res = gpio_install_isr_service(0);
if (res != ESP_OK && res != ESP_ERR_INVALID_STATE)
return res;
memset(reader, 0, sizeof(wiegand_reader_t));
reader->gpio_d0 = gpio_d0;
reader->gpio_d1 = gpio_d1;
reader->size = buf_size;
reader->buf = calloc(buf_size, 1);
reader->bit_order = bit_order;
reader->byte_order = byte_order;
reader->callback = callback;
esp_timer_create_args_t timer_args = {
.name = TAG,
.arg = reader,
.callback = timer_handler,
.dispatch_method = ESP_TIMER_TASK};
CHECK(esp_timer_create(&timer_args, &reader->timer));
CHECK(gpio_set_direction(gpio_d0, GPIO_MODE_INPUT));
CHECK(gpio_set_direction(gpio_d1, GPIO_MODE_INPUT));
CHECK(gpio_set_pull_mode(gpio_d0, internal_pullups ? GPIO_PULLUP_ONLY : GPIO_FLOATING));
CHECK(gpio_set_pull_mode(gpio_d1, internal_pullups ? GPIO_PULLUP_ONLY : GPIO_FLOATING));
isr_disable(reader);
CHECK(gpio_isr_handler_add(gpio_d0, isr_handler, reader));
CHECK(gpio_isr_handler_add(gpio_d1, isr_handler, reader));
isr_enable(reader);
reader->enabled = true;
ESP_LOGI(TAG, "Reader initialized on D0=%d, D1=%d", gpio_d0, gpio_d1);
return ESP_OK;
}
esp_err_t wiegand_reader_disable(wiegand_reader_t *reader)
{
CHECK_ARG(reader);
isr_disable(reader);
esp_timer_stop(reader->timer);
reader->enabled = false;
ESP_LOGI(TAG, "Reader on D0=%d, D1=%d disabled", reader->gpio_d0, reader->gpio_d1);
return ESP_OK;
}
esp_err_t wiegand_reader_enable(wiegand_reader_t *reader)
{
CHECK_ARG(reader);
reader->bits = 0;
memset(reader->buf, 0, reader->size);
isr_enable(reader);
reader->enabled = true;
ESP_LOGI(TAG, "Reader on D0=%d, D1=%d enabled", reader->gpio_d0, reader->gpio_d1);
return ESP_OK;
}
esp_err_t wiegand_reader_done(wiegand_reader_t *reader)
{
CHECK_ARG(reader && reader->buf);
isr_disable(reader);
CHECK(gpio_isr_handler_remove(reader->gpio_d0));
CHECK(gpio_isr_handler_remove(reader->gpio_d1));
esp_timer_stop(reader->timer);
CHECK(esp_timer_delete(reader->timer));
free(reader->buf);
ESP_LOGI(TAG, "Reader removed");
return ESP_OK;
} }

View File

@@ -1,138 +1,90 @@
/* /*
* wiegand.c * wiegand_reader.c
*
* Created on:
* Author:
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
#include <freertos/queue.h> #include <freertos/queue.h>
#include <wiegand.h>
#include <esp_log.h> #include <esp_log.h>
#include <string.h> #include <wiegand.h>
#include <evse_api.h> #include <evse_api.h>
#include <ocpp.h> #include <ocpp.h>
#include "auth.h"
static const char *TAG = "Wiegand_reader"; #define CONFIG_EXAMPLE_BUF_SIZE 50
static const char *TAG = "WiegandReader";
static wiegand_reader_t reader; static wiegand_reader_t reader;
static QueueHandle_t queue = NULL; static QueueHandle_t queue = NULL;
#define CONFIG_EXAMPLE_BUF_SIZE 50 typedef struct {
// Single data packet
typedef struct
{
uint8_t data[CONFIG_EXAMPLE_BUF_SIZE]; uint8_t data[CONFIG_EXAMPLE_BUF_SIZE];
size_t bits; size_t bits;
} data_packet_t; } data_packet_t;
// callback on new data in reader static void reader_callback(wiegand_reader_t *r) {
static void reader_callback(wiegand_reader_t *r)
{
// you can decode raw data from reader buffer here, but remember:
// reader will ignore any new incoming data while executing callback
// create simple undecoded data packet
data_packet_t p; data_packet_t p;
p.bits = r->bits; p.bits = r->bits;
memcpy(p.data, r->buf, CONFIG_EXAMPLE_BUF_SIZE); memcpy(p.data, r->buf, CONFIG_EXAMPLE_BUF_SIZE);
// Send it to the queue
xQueueSendToBack(queue, &p, 0); xQueueSendToBack(queue, &p, 0);
} }
static void wiegand_task(void *arg) static void wiegand_task(void *arg) {
{
// Create queue
queue = xQueueCreate(5, sizeof(data_packet_t)); queue = xQueueCreate(5, sizeof(data_packet_t));
if (!queue) if (!queue) {
{ ESP_LOGE(TAG, "Failed to create queue");
ESP_LOGE(TAG, "Error creating queue"); vTaskDelete(NULL);
ESP_ERROR_CHECK(ESP_ERR_NO_MEM); return;
} }
// Initialize reader
ESP_ERROR_CHECK(wiegand_reader_init(&reader, 19, 18, ESP_ERROR_CHECK(wiegand_reader_init(&reader, 19, 18,
true, CONFIG_EXAMPLE_BUF_SIZE, reader_callback, WIEGAND_MSB_FIRST, WIEGAND_LSB_FIRST)); true, CONFIG_EXAMPLE_BUF_SIZE, reader_callback, WIEGAND_MSB_FIRST, WIEGAND_LSB_FIRST));
data_packet_t p; data_packet_t p;
while (1) while (1) {
{
ESP_LOGI(TAG, "Waiting for Wiegand data..."); ESP_LOGI(TAG, "Waiting for Wiegand data...");
xQueueReceive(queue, &p, portMAX_DELAY); if (xQueueReceive(queue, &p, portMAX_DELAY) == pdPASS) {
ESP_LOGI(TAG, "Bits received: %d", p.bits);
// dump received data char tag[20] = {0};
// ESP_LOGI(TAG, "==========================================");
ESP_LOGI(TAG, "Bits received: %d\n", p.bits);
ESP_LOGI(TAG, "Received data:");
int bytes = p.bits / 8;
int tail = p.bits % 8;
for (size_t i = 0; i < bytes + (tail ? 1 : 0); i++)
printf(" 0x%02x", p.data[i]);
char str[20]; if (p.bits == 26) {
if (p.bits == 26) snprintf(tag, sizeof(tag), "%03d%03d%03d", p.data[0], p.data[1], p.data[2]);
{ } else if (p.bits == 34) {
evse_authorize(); snprintf(tag, sizeof(tag), "%03d%03d%03d%03d", p.data[0], p.data[1], p.data[2], p.data[3]);
/* } else {
sprintf(str, "%03d%03d%03d", p.data[0], p.data[1], p.data[2]); ESP_LOGW(TAG, "Unsupported bit length: %d", (int)p.bits);
continue;
if (ocpp_is_TransactionActive())
{
ocpp_end_transaction(str);
} }
else
{
ocpp_begin_transaction(str);
}*/
}
else if (p.bits == 34)
{
evse_authorize();
/*
sprintf(str, "%03d%03d%03d%03d", p.data[0], p.data[1], p.data[2], p.data[3]);
if (ocpp_is_TransactionActive()) ESP_LOGI(TAG, "Tag read: %s", tag);
{
ocpp_end_transaction(str); if (!auth_is_enabled()) {
ESP_LOGW(TAG, "Auth disabled, ignoring tag.");
continue;
} }
else
{ if (auth_tag_exists(tag)) {
ocpp_begin_transaction(str); ESP_LOGI(TAG, "Authorized tag. Proceeding...");
evse_authorize();
if (ocpp_is_TransactionActive()) {
ocpp_end_transaction(tag);
} else {
ocpp_begin_transaction(tag);
}
} else {
ESP_LOGW(TAG, "Unauthorized tag: %s", tag);
} }
*/
} }
} }
// ESP_LOGI(TAG, "==========================================");
} }
/* void initWiegand(void) {
static void wiegand_task(void *arg) ESP_LOGI(TAG, "Initializing Wiegand reader");
{
while (1)
{
vTaskDelay(pdMS_TO_TICKS(15000));
ocpp_begin_transaction("AAAAAA");
vTaskDelay(pdMS_TO_TICKS(15000));
ocpp_end_transaction("AAAAAA");
vTaskDelay(pdMS_TO_TICKS(15000));
ocpp_begin_transaction("AAAAAB");
vTaskDelay(pdMS_TO_TICKS(15000));
ocpp_end_transaction("AAAAAB");
}
}
*/
void initWiegand()
{
ESP_LOGI(TAG, "Starting wiegand");
// xTaskCreate(&wiegand_task, "wiegandtask", 8192, NULL, 5, NULL);
xTaskCreate(wiegand_task, TAG, configMINIMAL_STACK_SIZE * 4, NULL, 5, NULL); xTaskCreate(wiegand_task, TAG, configMINIMAL_STACK_SIZE * 4, NULL, 5, NULL);
} }

View File

@@ -14,5 +14,5 @@ idf_component_register(
SRCS ${srcs} SRCS ${srcs}
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
PRIV_REQUIRES nvs_flash PRIV_REQUIRES nvs_flash
REQUIRES peripherals REQUIRES peripherals auth
) )

View File

@@ -45,13 +45,8 @@ void evse_process(void) {
evse_error_check(pilot_voltage, is_n12v); evse_error_check(pilot_voltage, is_n12v);
if (evse_get_error() == 0 && !evse_is_error_cleared()) { if (evse_get_error() == 0 && !evse_is_error_cleared()) {
// Autorização temporária se exigida
if (!authorized && evse_is_require_auth()) { bool authorized = evse_state_get_authorized();
authorized = auth_grant_to >= xTaskGetTickCount();
if (auth_grant_to) auth_grant_to = 0;
} else {
authorized = true;
}
evse_fsm_process( evse_fsm_process(
pilot_voltage, pilot_voltage,
@@ -109,7 +104,7 @@ bool evse_is_pending_auth(void) {
void evse_authorize(void) { void evse_authorize(void) {
ESP_LOGI(TAG, "Authorize"); ESP_LOGI(TAG, "Authorize");
auth_grant_to = xTaskGetTickCount() + pdMS_TO_TICKS(60000); evse_state_set_authorized(true);
} }
void evse_set_authorized(bool value) { void evse_set_authorized(bool value) {

View File

@@ -3,59 +3,102 @@
#include "evse_error.h" #include "evse_error.h"
#include "evse_hardware.h" #include "evse_hardware.h"
#include "evse_config.h" #include "evse_config.h"
#include "evse_api.h"
#include "auth.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/queue.h"
#include "esp_log.h" #include "esp_log.h"
#include <string.h>
static const char *TAG = "evse_manager"; static const char *TAG = "EVSE_Manager";
static TickType_t auth_expiration = 0;
static SemaphoreHandle_t evse_mutex; static SemaphoreHandle_t evse_mutex;
static QueueHandle_t auth_event_queue = NULL;
#define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo #define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo
// ===== Task de ciclo principal =====
static void evse_manager_task(void *arg) {
void evse_manager_init(void) {
evse_mutex = xSemaphoreCreateMutex();
evse_config_init();
evse_error_init();
evse_hardware_init();
evse_state_init();
ESP_LOGI(TAG, "EVSE Manager initialized");
xTaskCreate(
evse_manager_task,
"evse_manager_task",
4096, // stack size
NULL, // param
5, // priority
NULL // handle
);
}
void evse_manager_task(void *arg) {
while (true) { while (true) {
evse_manager_tick(); evse_manager_tick();
vTaskDelay(pdMS_TO_TICKS(EVSE_MANAGER_TICK_PERIOD_MS)); vTaskDelay(pdMS_TO_TICKS(EVSE_MANAGER_TICK_PERIOD_MS));
} }
} }
static void evse_auth_event_task(void *arg) {
auth_event_t evt;
while (true) {
if (xQueueReceive(auth_event_queue, &evt, portMAX_DELAY)) {
ESP_LOGI(TAG, "Evento de autenticação recebido: %s (%s)",
evt.tag, evt.authorized ? "AUTORIZADO" : "NEGADO");
if (evt.authorized) {
evse_authorize();
auth_expiration = xTaskGetTickCount() + pdMS_TO_TICKS(2 * 60 * 1000); // 2 minutos
} else {
evse_manager_set_authorized(false);
ESP_LOGW(TAG, "Tag inválida, carregamento negado.");
}
}
}
}
// ===== Inicialização dos módulos do EVSE =====
void evse_manager_init(void) {
evse_mutex = xSemaphoreCreateMutex();
evse_config_init();
evse_error_init();
evse_hardware_init();
evse_state_init();
ESP_LOGI(TAG, "EVSE Manager inicializado.");
xTaskCreate(evse_manager_task, "evse_manager_task", 4096, NULL, 5, NULL);
}
// ===== Inicia processamento de eventos de autenticação =====
void evse_manager_start(QueueHandle_t queue) {
auth_event_queue = queue;
xTaskCreate(evse_auth_event_task, "evse_auth_evt", 4096, NULL, 5, NULL);
}
void evse_manager_tick(void) { void evse_manager_tick(void) {
xSemaphoreTake(evse_mutex, portMAX_DELAY); xSemaphoreTake(evse_mutex, portMAX_DELAY);
// Atualizações cíclicas de módulos
evse_hardware_tick(); evse_hardware_tick();
evse_error_tick(); evse_error_tick();
evse_state_tick(); evse_state_tick();
evse_temperature_check(); evse_temperature_check();
// Verifica expiração de autorização somente se auth está habilitado
if (auth_is_enabled()) {
if (evse_state_get_authorized() && auth_expiration > 0 &&
xTaskGetTickCount() >= auth_expiration) {
ESP_LOGI(TAG, "Autorização expirada após 2 minutos.");
evse_state_set_authorized(false);
auth_expiration = 0;
}
} else {
// Se autenticação não é necessária, sempre considera autorizado
if (!evse_state_get_authorized()) {
evse_state_set_authorized(true);
ESP_LOGI(TAG, "Autenticação desativada: autorização forçada.");
}
}
xSemaphoreGive(evse_mutex); xSemaphoreGive(evse_mutex);
} }
// ===== Controles e status =====
bool evse_manager_is_available(void) { bool evse_manager_is_available(void) {
return evse_config_is_available(); return evse_config_is_available();
} }

View File

@@ -1,13 +1,24 @@
#include "evse_state.h" #include "evse_state.h"
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
static evse_state_t current_state = EVSE_STATE_A; static evse_state_t current_state = EVSE_STATE_A;
static bool is_authorized = false;
// Proteção básica para variáveis globais em sistemas concorrentes
static portMUX_TYPE state_mux = portMUX_INITIALIZER_UNLOCKED;
void evse_set_state(evse_state_t state) { void evse_set_state(evse_state_t state) {
portENTER_CRITICAL(&state_mux);
current_state = state; current_state = state;
portEXIT_CRITICAL(&state_mux);
} }
evse_state_t evse_get_state(void) { evse_state_t evse_get_state(void) {
return current_state; portENTER_CRITICAL(&state_mux);
evse_state_t s = current_state;
portEXIT_CRITICAL(&state_mux);
return s;
} }
const char* evse_state_to_str(evse_state_t state) { const char* evse_state_to_str(evse_state_t state) {
@@ -26,10 +37,12 @@ const char* evse_state_to_str(evse_state_t state) {
} }
void evse_state_init(void) { void evse_state_init(void) {
// Inicialização do estado EVSE portENTER_CRITICAL(&state_mux);
current_state = EVSE_STATE_A;
is_authorized = false;
portEXIT_CRITICAL(&state_mux);
} }
void evse_state_tick(void) { void evse_state_tick(void) {
// Tick do estado (placeholder) // Tick do estado (placeholder)
} }
@@ -47,3 +60,16 @@ bool evse_state_is_plugged(evse_state_t state) {
bool evse_state_is_session(evse_state_t state) { bool evse_state_is_session(evse_state_t state) {
return state == EVSE_STATE_B2 || state == EVSE_STATE_C1 || state == EVSE_STATE_C2; 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;
}

View File

@@ -6,46 +6,54 @@ extern "C" {
#endif #endif
#include <stdbool.h> #include <stdbool.h>
#include "evse_state.h" #include <freertos/FreeRTOS.h>
#include "evse_error.h" #include <freertos/queue.h>
#include "evse_config.h"
/** /**
* @brief Inicializa todos os módulos do EVSE e inicia a tarefa de supervisão periódica. * @brief Inicializa os módulos internos do EVSE (hardware, estado, erros, etc.)
* e inicia a tarefa de supervisão periódica (tick).
*/ */
void evse_manager_init(void); void evse_manager_init(void);
/** /**
* @brief Executa uma iteração do ciclo de controle do EVSE (chamada automaticamente pela task). * @brief Inicia a tarefa que processa eventos de autenticação recebidos via fila.
* *
* Você normalmente não precisa chamar isso manualmente. * @param queue Fila de eventos do tipo auth_event_t enviada pelo módulo auth.
*/
void evse_manager_start(QueueHandle_t queue);
/**
* @brief Executa uma iteração do ciclo de controle do EVSE.
*
* Esta função é chamada automaticamente pela task periódica,
* mas pode ser chamada manualmente em testes.
*/ */
void evse_manager_tick(void); void evse_manager_tick(void);
/** /**
* @brief Verifica se o EVSE está disponível para conexão (não bloqueado, sem falha crítica, etc). * @brief Verifica se o EVSE está disponível para uso.
*
* Isso considera falhas críticas, disponibilidade configurada, etc.
*/ */
bool evse_manager_is_available(void); bool evse_manager_is_available(void);
/** /**
* @brief Define se o EVSE deve estar disponível. * @brief Define se o EVSE deve estar disponível (ex: via controle remoto).
*
* Pode ser usado, por exemplo, para bloquear carregamento via comando remoto.
*/ */
void evse_manager_set_available(bool available); void evse_manager_set_available(bool available);
/** /**
* @brief Define se o EVSE está autorizado a iniciar carregamento (ex: após autenticação). * @brief Define se o EVSE está autorizado a carregar (ex: após autenticação).
*/ */
void evse_manager_set_authorized(bool authorized); void evse_manager_set_authorized(bool authorized);
/** /**
* @brief Verifica se o EVSE está em estado de carregamento ativo. * @brief Verifica se o EVSE está atualmente carregando.
*/ */
bool evse_manager_is_charging(void); bool evse_manager_is_charging(void);
/** /**
* @brief Ativa ou desativa o EVSE (liga/desliga logicamente o carregamento). * @brief Ativa ou desativa logicamente o EVSE (controla habilitação geral).
*/ */
void evse_manager_set_enabled(bool enabled); void evse_manager_set_enabled(bool enabled);
@@ -54,8 +62,6 @@ void evse_manager_set_enabled(bool enabled);
*/ */
bool evse_manager_is_enabled(void); bool evse_manager_is_enabled(void);
void evse_manager_task(void *arg);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -22,6 +22,8 @@ void evse_state_init(void);
void evse_state_tick(void); void evse_state_tick(void);
void evse_state_set_authorized(bool authorized); void evse_state_set_authorized(bool authorized);
bool evse_state_get_authorized(void);
evse_state_t evse_get_state(void); evse_state_t evse_get_state(void);

View File

@@ -16,7 +16,10 @@
#include "cJSON.h" #include "cJSON.h"
#include "rest.h" #include "rest.h"
#include "evse_api.h" #include "evse_api.h"
#include "cJSON.h"
#include "esp_log.h"
#include "esp_http_server.h"
#include "auth.h"
static const char *REST_TAG = "esp-rest"; static const char *REST_TAG = "esp-rest";
#define REST_CHECK(a, str, goto_tag, ...) \ #define REST_CHECK(a, str, goto_tag, ...) \
@@ -72,14 +75,6 @@ static struct {
int temperatureLimit; int temperatureLimit;
} settings_config = {0, 0, 0, 0, 0}; } settings_config = {0, 0, 0, 0, 0};
// Estruturas para armazenar as configurações de autenticação e usuários
static struct {
bool RFID;
bool App;
bool Password;
} auth_methods = {false, false, false};
static struct { static struct {
char username[128]; char username[128];
} users[10] = {{"admin"}, {"user1"}}; } users[10] = {{"admin"}, {"user1"}};
@@ -586,65 +581,67 @@ static esp_err_t config_mqtt_post_handler(httpd_req_t *req)
return ESP_OK; return ESP_OK;
} }
// Manipulador para o endpoint GET /api/v1/config/auth-methods // GET /api/v1/config/auth-methods
static esp_err_t config_auth_methods_get_handler(httpd_req_t *req) static esp_err_t config_auth_methods_get_handler(httpd_req_t *req)
{ {
httpd_resp_set_type(req, "application/json"); httpd_resp_set_type(req, "application/json");
// Criar objeto JSON com as configurações de métodos de autenticação
cJSON *config = cJSON_CreateObject(); cJSON *config = cJSON_CreateObject();
cJSON_AddBoolToObject(config, "RFID", evse_is_require_auth()); cJSON_AddBoolToObject(config, "RFID", auth_is_enabled());
cJSON_AddBoolToObject(config, "App", auth_methods.App); cJSON_AddBoolToObject(config, "App", false);
cJSON_AddBoolToObject(config, "Password", auth_methods.Password); cJSON_AddBoolToObject(config, "Password", false);
// Convertendo para string e enviando a resposta char *config_str = cJSON_PrintUnformatted(config);
const char *config_str = cJSON_Print(config);
httpd_resp_sendstr(req, config_str); httpd_resp_sendstr(req, config_str);
// Liberando a memória free(config_str);
free((void *)config_str);
cJSON_Delete(config); cJSON_Delete(config);
return ESP_OK; return ESP_OK;
} }
// Manipulador para o endpoint POST /api/v1/config/auth-methods // POST /api/v1/config/auth-methods
static esp_err_t config_auth_methods_post_handler(httpd_req_t *req) static esp_err_t config_auth_methods_post_handler(httpd_req_t *req)
{ {
char buf[512]; // Buffer para armazenar a requisição char buf[512];
int len = httpd_req_recv(req, buf, sizeof(buf) - 1); int len = httpd_req_recv(req, buf, sizeof(buf) - 1);
if (len <= 0) { if (len <= 0) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid request body");
return ESP_FAIL; return ESP_FAIL;
} }
buf[len] = '\0'; // Garantir que a string esteja terminada buf[len] = '\0';
// Parse JSON recebido
cJSON *json = cJSON_Parse(buf); cJSON *json = cJSON_Parse(buf);
if (json == NULL) { if (!json) {
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
return ESP_FAIL; return ESP_FAIL;
} }
// Atualizando as configurações de autenticação
cJSON *RFID = cJSON_GetObjectItem(json, "RFID"); cJSON *RFID = cJSON_GetObjectItem(json, "RFID");
if (RFID) evse_set_require_auth(RFID->valueint != 0); if (cJSON_IsBool(RFID)) {
auth_set_enabled(cJSON_IsTrue(RFID));
}
/*
cJSON *App = cJSON_GetObjectItem(json, "App"); cJSON *App = cJSON_GetObjectItem(json, "App");
if (App) auth_methods.App = App->valueint; if (cJSON_IsBool(App)) {
auth_methods.App = cJSON_IsTrue(App);
}
cJSON *Password = cJSON_GetObjectItem(json, "Password"); cJSON *Password = cJSON_GetObjectItem(json, "Password");
if (Password) auth_methods.Password = Password->valueint; if (cJSON_IsBool(Password)) {
auth_methods.Password = cJSON_IsTrue(Password);
}*/
cJSON_Delete(json); cJSON_Delete(json);
// Responder com uma mensagem de sucesso httpd_resp_sendstr(req, "Configurações de autenticação atualizadas com sucesso");
httpd_resp_sendstr(req, "Configurações de Autenticação atualizadas com sucesso");
return ESP_OK; return ESP_OK;
} }
// Manipulador para o endpoint GET /api/v1/config/users // Manipulador para o endpoint GET /api/v1/config/users
static esp_err_t config_users_get_handler(httpd_req_t *req) static esp_err_t config_users_get_handler(httpd_req_t *req)
{ {

View File

@@ -28,6 +28,6 @@ dependencies:
source: source:
type: idf type: idf
version: 5.3.0 version: 5.3.0
manifest_hash: 6af5391b91eb4808a8ae46a80daf7d26b00bdb70ad4377769006c20c8de33787 manifest_hash: 5c32be3773ff644cc40e814191fb19975a757deef1b686db5b80724d8d562fde
target: esp32 target: esp32
version: 1.0.0 version: 1.0.0

View File

@@ -24,6 +24,9 @@
#include "wifi.h" #include "wifi.h"
#include "logger.h" #include "logger.h"
#include "auth.h"
#define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo #define EVSE_MANAGER_TICK_PERIOD_MS 1000 // 1 segundo
#define AP_CONNECTION_TIMEOUT 60000 // 60sec #define AP_CONNECTION_TIMEOUT 60000 // 60sec
#define RESET_HOLD_TIME 10000 // 10sec #define RESET_HOLD_TIME 10000 // 10sec
@@ -211,6 +214,10 @@ static bool ota_diagnostic(void)
static void init_modules(void) static void init_modules(void)
{ {
QueueHandle_t auth_queue = xQueueCreate(10, sizeof(auth_event_t));
wifi_ini(); wifi_ini();
peripherals_init(); peripherals_init();
api_init(); api_init();
@@ -219,12 +226,16 @@ static void init_modules(void)
evse_init(); // Cria a task para FSM evse_init(); // Cria a task para FSM
button_init(); button_init();
auth_init();
auth_set_event_queue(auth_queue);
evse_manager_start(auth_queue);
// Outros módulos (descomente conforme necessário) // Outros módulos (descomente conforme necessário)
// meter_init(); // meter_init();
// ocpp_start(); // ocpp_start();
// serial_mdb_start(); // serial_mdb_start();
// currentshaper_start(); // currentshaper_start();
// initRc522();
// initWiegand(); // initWiegand();
// serial_mt_start(); // serial_mt_start();
// master_sync_start(); // master_sync_start();

View File

View File

View File

0
managed_components/espressif__cmake_utilities/Kconfig Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

0
managed_components/espressif__esp-modbus/.gitignore vendored Executable file → Normal file
View File

View File

0
managed_components/espressif__esp-modbus/Kconfig Executable file → Normal file
View File

0
managed_components/espressif__esp-modbus/LICENSE Executable file → Normal file
View File

0
managed_components/espressif__esp-modbus/README.md Executable file → Normal file
View File

0
managed_components/espressif__esp-modbus/build_all.sh Executable file → Normal file
View File

0
managed_components/espressif__esp-modbus/component.mk Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

Some files were not shown because too many files have changed in this diff Show More