add ocpp
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
set(srcs "src/auth.c" "src/wiegand.c" "src/wiegand_reader.c" "src/auth_events.c")
|
||||
set(srcs "src/auth_types.c" "src/auth.c" "src/wiegand.c" "src/wiegand_reader.c" "src/auth_events.c")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "include"
|
||||
|
||||
@@ -1,115 +1,32 @@
|
||||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include "auth_types.h" // enum + MAX LEN para API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Maximum length of an RFID tag (including null terminator)
|
||||
#define AUTH_TAG_MAX_LEN 30
|
||||
|
||||
/// Event structure emitted after a tag is read
|
||||
/* Evento auxiliar legado/útil (resultado local) */
|
||||
typedef struct {
|
||||
char tag[AUTH_TAG_MAX_LEN]; ///< The tag that was read
|
||||
bool authorized; ///< true if the tag is valid
|
||||
char tag[AUTH_TAG_MAX_LEN];
|
||||
bool authorized;
|
||||
} auth_event_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes the authentication system.
|
||||
*
|
||||
* - Loads configuration (enabled/disabled) from NVS
|
||||
* - Starts the Wiegand reader
|
||||
* - Emits AUTH_EVENT_INIT with current status
|
||||
*/
|
||||
void auth_init(void);
|
||||
void auth_init(void);
|
||||
void auth_set_mode(auth_mode_t mode);
|
||||
auth_mode_t auth_get_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Enables or disables RFID-based authentication.
|
||||
*
|
||||
* This setting is persisted in NVS. If disabled,
|
||||
* all tags will be treated as authorized.
|
||||
*
|
||||
* @param value true to enable authentication, false to disable
|
||||
*/
|
||||
void auth_set_enabled(bool value);
|
||||
|
||||
/**
|
||||
* @brief Checks whether authentication is currently enabled.
|
||||
*
|
||||
* @return true if enabled, false if disabled
|
||||
*/
|
||||
bool auth_is_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Adds a new RFID tag to the authorized list.
|
||||
*
|
||||
* @param tag The RFID tag (max AUTH_TAG_MAX_LEN-1 characters)
|
||||
* @return true if the tag was added successfully,
|
||||
* false if it already exists or is invalid
|
||||
*/
|
||||
bool auth_add_tag(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Removes an existing RFID tag from the authorized list.
|
||||
*
|
||||
* @param tag The tag to remove
|
||||
* @return true if the tag was removed, false if not found
|
||||
*/
|
||||
bool auth_remove_tag(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Checks whether a tag is already registered.
|
||||
*
|
||||
* @param tag The tag to check
|
||||
* @return true if the tag exists, false otherwise
|
||||
*/
|
||||
bool auth_tag_exists(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Logs all currently registered tags via ESP logging.
|
||||
*/
|
||||
void auth_list_tags(void);
|
||||
|
||||
/**
|
||||
* @brief Processes a read RFID tag.
|
||||
*
|
||||
* - Checks whether it's authorized
|
||||
* - Emits AUTH_EVENT_TAG_PROCESSED event
|
||||
* - Starts expiration timer if authorized
|
||||
*
|
||||
* @param tag The tag that was read
|
||||
*/
|
||||
void auth_process_tag(const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Enables registration mode for the next tag read.
|
||||
*
|
||||
* When registration mode is active, the next tag read
|
||||
* will be added to the authorized list automatically.
|
||||
* Mode is deactivated after one tag is registered.
|
||||
*/
|
||||
void auth_wait_for_tag_registration(void);
|
||||
|
||||
/**
|
||||
* @brief Returns the total number of registered tags.
|
||||
*
|
||||
* @return Number of valid tags
|
||||
*/
|
||||
int auth_get_tag_count(void);
|
||||
|
||||
/**
|
||||
* @brief Returns the tag string at the given index.
|
||||
*
|
||||
* @param index The index (0 ≤ index < auth_get_tag_count())
|
||||
* @return Pointer to the tag string, or NULL if index is invalid
|
||||
*/
|
||||
int auth_get_tag_count(void);
|
||||
const char *auth_get_tag_by_index(int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AUTH_H
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
#pragma once
|
||||
#include "esp_event.h"
|
||||
|
||||
#define AUTH_EVENT_TAG_MAX_LEN 32
|
||||
#include "auth_types.h" // só tipos comuns; evita incluir auth.h
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(AUTH_EVENTS);
|
||||
|
||||
/* IDs de eventos */
|
||||
typedef enum {
|
||||
AUTH_EVENT_TAG_PROCESSED,
|
||||
AUTH_EVENT_TAG_SAVED,
|
||||
AUTH_EVENT_ENABLED_CHANGED,
|
||||
AUTH_EVENT_INIT,
|
||||
AUTH_EVENT_TAG_PROCESSED = 0, // resultado LOCAL -> auth_tag_event_data_t
|
||||
AUTH_EVENT_TAG_VERIFY, // pedir validação OCPP -> auth_tag_verify_event_t
|
||||
AUTH_EVENT_TAG_SAVED, // registada (modo registo) -> auth_tag_event_data_t
|
||||
AUTH_EVENT_MODE_CHANGED, // modo alterado -> auth_mode_event_data_t
|
||||
AUTH_EVENT_INIT, // estado inicial -> auth_mode_event_data_t
|
||||
} auth_event_id_t;
|
||||
|
||||
/* Payloads */
|
||||
typedef struct {
|
||||
char tag[AUTH_EVENT_TAG_MAX_LEN];
|
||||
char tag[AUTH_TAG_MAX_LEN];
|
||||
bool authorized;
|
||||
} auth_tag_event_data_t;
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
} auth_enabled_event_data_t;
|
||||
char tag[AUTH_TAG_MAX_LEN];
|
||||
uint32_t req_id; // opcional p/ correlacionar
|
||||
} auth_tag_verify_event_t;
|
||||
|
||||
typedef struct {
|
||||
auth_mode_t mode;
|
||||
} auth_mode_event_data_t;
|
||||
|
||||
26
components/auth/include/auth_types.h
Normal file
26
components/auth/include/auth_types.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Tamanho máx. da tag (inclui NUL) */
|
||||
#define AUTH_TAG_MAX_LEN 30
|
||||
|
||||
/* Modos de autorização */
|
||||
typedef enum {
|
||||
AUTH_MODE_OPEN = 0, // Sem autenticação
|
||||
AUTH_MODE_LOCAL_RFID, // Lista local (NVS)
|
||||
AUTH_MODE_OCPP_RFID // Validação via OCPP/CSMS
|
||||
} auth_mode_t;
|
||||
|
||||
/* Converte enum -> "open"|"local"|"ocpp" (nunca NULL) */
|
||||
const char *auth_mode_to_str(auth_mode_t mode);
|
||||
|
||||
/* Converte "open"|"local"|"ocpp" (case-insensitive) -> enum */
|
||||
bool auth_mode_from_str(const char *s, auth_mode_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,62 +1,40 @@
|
||||
// components/auth/src/auth.c
|
||||
|
||||
#include "auth.h"
|
||||
#include "auth_events.h"
|
||||
#include "esp_event.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <string.h>
|
||||
#include <strings.h> // <-- necessário para strcasecmp
|
||||
#include "wiegand_reader.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
|
||||
#define MAX_TAGS 50
|
||||
|
||||
static const char *TAG = "Auth";
|
||||
|
||||
static bool enabled = false;
|
||||
/* ===== Estado ===== */
|
||||
static auth_mode_t s_mode = AUTH_MODE_OPEN;
|
||||
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;
|
||||
|
||||
// NVS keys
|
||||
/* ===== NVS keys ===== */
|
||||
#define NVS_NAMESPACE "auth"
|
||||
#define NVS_TAG_PREFIX "tag_"
|
||||
#define NVS_TAG_COUNT_KEY "count"
|
||||
#define NVS_ENABLED_KEY "enabled"
|
||||
|
||||
// ===========================
|
||||
// NVS Persistence
|
||||
// ===========================
|
||||
|
||||
static void load_auth_config(void) {
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);
|
||||
if (err == ESP_OK) {
|
||||
uint8_t val;
|
||||
if (nvs_get_u8(handle, NVS_ENABLED_KEY, &val) == ESP_OK) {
|
||||
enabled = val;
|
||||
ESP_LOGI(TAG, "Loaded auth enabled = %d", enabled);
|
||||
}
|
||||
nvs_close(handle);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No stored auth config found. Using default.");
|
||||
}
|
||||
}
|
||||
|
||||
static void save_auth_config(void) {
|
||||
nvs_handle_t handle;
|
||||
if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle) == ESP_OK) {
|
||||
nvs_set_u8(handle, NVS_ENABLED_KEY, enabled);
|
||||
nvs_commit(handle);
|
||||
nvs_close(handle);
|
||||
ESP_LOGI(TAG, "Auth config saved: enabled = %d", enabled);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to save auth config.");
|
||||
}
|
||||
}
|
||||
#define NVS_MODE_KEY "mode" // uint8_t
|
||||
|
||||
/* =========================
|
||||
* NVS Persistence (tags)
|
||||
* ========================= */
|
||||
static void load_tags_from_nvs(void) {
|
||||
nvs_handle_t handle;
|
||||
if (nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle) != ESP_OK) {
|
||||
@@ -71,7 +49,6 @@ static void load_tags_from_nvs(void) {
|
||||
}
|
||||
|
||||
tag_count = 0;
|
||||
|
||||
for (int i = 0; i < count && i < MAX_TAGS; i++) {
|
||||
char key[16];
|
||||
char tag_buf[AUTH_TAG_MAX_LEN];
|
||||
@@ -109,10 +86,38 @@ static void save_tags_to_nvs(void) {
|
||||
ESP_LOGI(TAG, "Tags saved to NVS (%d tags)", tag_count);
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Internal Helpers
|
||||
// ===========================
|
||||
/* =========================
|
||||
* NVS Persistence (mode)
|
||||
* ========================= */
|
||||
static void load_mode_from_nvs(void) {
|
||||
nvs_handle_t h;
|
||||
if (nvs_open(NVS_NAMESPACE, NVS_READONLY, &h) == ESP_OK) {
|
||||
uint8_t u = (uint8_t)AUTH_MODE_OPEN;
|
||||
if (nvs_get_u8(h, NVS_MODE_KEY, &u) == ESP_OK) {
|
||||
if (u <= (uint8_t)AUTH_MODE_OCPP_RFID) s_mode = (auth_mode_t)u;
|
||||
}
|
||||
nvs_close(h);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No stored auth mode in NVS; default OPEN");
|
||||
}
|
||||
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;
|
||||
if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &h) == ESP_OK) {
|
||||
nvs_set_u8(h, NVS_MODE_KEY, (uint8_t)mode);
|
||||
nvs_commit(h);
|
||||
nvs_close(h);
|
||||
ESP_LOGI(TAG, "Saved mode = %d (%s)", (int)mode, auth_mode_to_str(mode));
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to save auth mode to NVS");
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================
|
||||
* Helpers
|
||||
* ========================= */
|
||||
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) {
|
||||
@@ -122,44 +127,74 @@ static bool is_tag_valid(const char *tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Public API
|
||||
// ===========================
|
||||
|
||||
|
||||
/* =========================
|
||||
* Public API
|
||||
* ========================= */
|
||||
void auth_init(void) {
|
||||
load_auth_config();
|
||||
load_mode_from_nvs();
|
||||
load_tags_from_nvs();
|
||||
|
||||
if (enabled) {
|
||||
if (s_mode == AUTH_MODE_LOCAL_RFID || s_mode == AUTH_MODE_OCPP_RFID) {
|
||||
initWiegand();
|
||||
ESP_LOGI(TAG, "Wiegand reader initialized (Auth enabled)");
|
||||
ESP_LOGI(TAG, "Wiegand reader initialized (mode=%s)", auth_mode_to_str(s_mode));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Auth disabled, Wiegand reader not started");
|
||||
ESP_LOGI(TAG, "Mode OPEN: Wiegand not started");
|
||||
}
|
||||
|
||||
auth_enabled_event_data_t evt = { .enabled = enabled };
|
||||
auth_mode_event_data_t evt = { .mode = s_mode };
|
||||
esp_event_post(AUTH_EVENTS, AUTH_EVENT_INIT, &evt, sizeof(evt), portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "Initial AUTH state sent (enabled = %d)", enabled);
|
||||
ESP_LOGI(TAG, "AUTH INIT sent (mode=%s)", auth_mode_to_str(s_mode));
|
||||
}
|
||||
|
||||
void auth_set_enabled(bool value) {
|
||||
enabled = value;
|
||||
save_auth_config();
|
||||
ESP_LOGI(TAG, "Auth %s", enabled ? "ENABLED" : "DISABLED");
|
||||
void auth_set_mode(auth_mode_t mode) {
|
||||
if (mode < AUTH_MODE_OPEN || mode > AUTH_MODE_OCPP_RFID) {
|
||||
ESP_LOGW(TAG, "Invalid mode: %d", (int)mode);
|
||||
return;
|
||||
}
|
||||
if (mode == s_mode) {
|
||||
ESP_LOGI(TAG, "Mode unchanged: %s", auth_mode_to_str(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
auth_enabled_event_data_t event = { .enabled = enabled };
|
||||
esp_event_post(AUTH_EVENTS, AUTH_EVENT_ENABLED_CHANGED, &event, sizeof(event), portMAX_DELAY);
|
||||
s_mode = mode;
|
||||
save_mode_to_nvs(mode);
|
||||
|
||||
// Nota: se precisares, aqui podes parar/iniciar o Wiegand consoante o modo.
|
||||
if (s_mode == AUTH_MODE_OPEN) {
|
||||
ESP_LOGI(TAG, "Mode set to OPEN");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Mode set to %s; ensure Wiegand reader is running", 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);
|
||||
}
|
||||
|
||||
bool auth_is_enabled(void) {
|
||||
return enabled;
|
||||
auth_mode_t auth_get_mode(void) {
|
||||
return s_mode;
|
||||
}
|
||||
|
||||
const char *auth_mode_to_str(auth_mode_t mode) {
|
||||
switch (mode) {
|
||||
case AUTH_MODE_OPEN: return "open";
|
||||
case AUTH_MODE_LOCAL_RFID: return "local";
|
||||
case AUTH_MODE_OCPP_RFID: return "ocpp";
|
||||
default: return "open";
|
||||
}
|
||||
}
|
||||
|
||||
bool auth_mode_from_str(const char *s, auth_mode_t *out) {
|
||||
if (!s || !out) return false;
|
||||
if (!strcasecmp(s, "open")) { *out = AUTH_MODE_OPEN; return true; }
|
||||
if (!strcasecmp(s, "local")) { *out = AUTH_MODE_LOCAL_RFID; return true; }
|
||||
if (!strcasecmp(s, "ocpp")) { *out = AUTH_MODE_OCPP_RFID; return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
bool auth_add_tag(const char *tag) {
|
||||
if (tag_count >= MAX_TAGS) return false;
|
||||
if (!tag || strlen(tag) >= AUTH_TAG_MAX_LEN) return false;
|
||||
if (is_tag_valid(tag)) return true; // Already exists
|
||||
if (is_tag_valid(tag)) return true; // já existe
|
||||
|
||||
strncpy(valid_tags[tag_count], tag, AUTH_TAG_MAX_LEN - 1);
|
||||
valid_tags[tag_count][AUTH_TAG_MAX_LEN - 1] = '\0';
|
||||
@@ -198,40 +233,62 @@ void auth_list_tags(void) {
|
||||
}
|
||||
|
||||
void auth_wait_for_tag_registration(void) {
|
||||
if (s_mode != AUTH_MODE_LOCAL_RFID) {
|
||||
ESP_LOGW(TAG, "Registration is only available in LOCAL mode");
|
||||
return;
|
||||
}
|
||||
waiting_for_registration = true;
|
||||
ESP_LOGI(TAG, "Tag registration mode enabled.");
|
||||
}
|
||||
|
||||
void auth_process_tag(const char *tag) {
|
||||
if (!tag || !auth_is_enabled()) {
|
||||
ESP_LOGW(TAG, "Auth disabled or NULL tag received.");
|
||||
if (!tag || !*tag) {
|
||||
ESP_LOGW(TAG, "NULL/empty tag received");
|
||||
return;
|
||||
}
|
||||
|
||||
if (waiting_for_registration) {
|
||||
if (auth_add_tag(tag)) {
|
||||
auth_tag_event_data_t event;
|
||||
strncpy(event.tag, tag, AUTH_EVENT_TAG_MAX_LEN - 1);
|
||||
event.tag[AUTH_EVENT_TAG_MAX_LEN - 1] = '\0';
|
||||
event.authorized = true;
|
||||
|
||||
esp_event_post(AUTH_EVENTS, AUTH_EVENT_TAG_SAVED, &event, sizeof(event), portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "Tag registered: %s", tag);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Failed to register tag: %s", 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);
|
||||
break;
|
||||
}
|
||||
|
||||
case AUTH_MODE_LOCAL_RFID: {
|
||||
if (waiting_for_registration) {
|
||||
waiting_for_registration = false;
|
||||
|
||||
if (auth_add_tag(tag)) {
|
||||
auth_tag_event_data_t ev = {0};
|
||||
strncpy(ev.tag, tag, AUTH_TAG_MAX_LEN - 1);
|
||||
ev.authorized = true;
|
||||
esp_event_post(AUTH_EVENTS, AUTH_EVENT_TAG_SAVED, &ev, sizeof(ev), portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "Tag registered: %s", tag);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Failed to register tag: %s", tag);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auth_tag_event_data_t ev = {0};
|
||||
strncpy(ev.tag, tag, AUTH_TAG_MAX_LEN - 1);
|
||||
ev.authorized = is_tag_valid(tag);
|
||||
|
||||
ESP_LOGI(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;
|
||||
}
|
||||
|
||||
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.req_id = s_next_req_id++;
|
||||
ESP_LOGI(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;
|
||||
}
|
||||
waiting_for_registration = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auth_tag_event_data_t event;
|
||||
strncpy(event.tag, tag, AUTH_EVENT_TAG_MAX_LEN - 1);
|
||||
event.tag[AUTH_EVENT_TAG_MAX_LEN - 1] = '\0';
|
||||
event.authorized = is_tag_valid(tag);
|
||||
|
||||
ESP_LOGI(TAG, "Tag %s: %s", tag, event.authorized ? "AUTHORIZED" : "DENIED");
|
||||
|
||||
esp_event_post(AUTH_EVENTS, AUTH_EVENT_TAG_PROCESSED, &event, sizeof(event), portMAX_DELAY);
|
||||
}
|
||||
|
||||
int auth_get_tag_count(void) {
|
||||
|
||||
19
components/auth/src/auth_types.c
Executable file
19
components/auth/src/auth_types.c
Executable file
@@ -0,0 +1,19 @@
|
||||
#include "auth_types.h"
|
||||
#include <strings.h> // strcasecmp
|
||||
|
||||
const char *auth_mode_to_str(auth_mode_t mode) {
|
||||
switch (mode) {
|
||||
case AUTH_MODE_OPEN: return "open";
|
||||
case AUTH_MODE_LOCAL_RFID: return "local";
|
||||
case AUTH_MODE_OCPP_RFID: return "ocpp";
|
||||
default: return "open";
|
||||
}
|
||||
}
|
||||
|
||||
bool auth_mode_from_str(const char *s, auth_mode_t *out) {
|
||||
if (!s || !out) return false;
|
||||
if (!strcasecmp(s, "open")) { *out = AUTH_MODE_OPEN; return true; }
|
||||
if (!strcasecmp(s, "local")) { *out = AUTH_MODE_LOCAL_RFID; return true; }
|
||||
if (!strcasecmp(s, "ocpp")) { *out = AUTH_MODE_OCPP_RFID; return true; }
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user