new release
This commit is contained in:
@@ -1,205 +1,466 @@
|
||||
// buzzer.c
|
||||
#include "buzzer_events.h"
|
||||
#include "evse_events.h"
|
||||
#include "auth_events.h"
|
||||
#include "network_events.h"
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/ledc.h" // Para buzzer passivo
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#define BUZZER_GPIO GPIO_NUM_27
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/ledc.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
// ===================== Configuração padrão (pode migrar para Kconfig) =====================
|
||||
#ifndef CONFIG_BUZZER_GPIO
|
||||
#define CONFIG_BUZZER_GPIO GPIO_NUM_27
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_MODE_PASSIVE // 1 = PASSIVE (PWM), 0 = ACTIVE (on/off)
|
||||
#define CONFIG_BUZZER_MODE_PASSIVE 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_FREQ_HZ
|
||||
#define CONFIG_BUZZER_FREQ_HZ 3500
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_DUTY_PCT
|
||||
#define CONFIG_BUZZER_DUTY_PCT 70
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_QUEUE_LEN
|
||||
#define CONFIG_BUZZER_QUEUE_LEN 8
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_TASK_STACK
|
||||
#define CONFIG_BUZZER_TASK_STACK 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_TASK_PRIO
|
||||
#define CONFIG_BUZZER_TASK_PRIO (tskIDLE_PRIORITY + 1)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_MIN_GAP_MS // anti-spam (gap mínimo entre toques)
|
||||
#define CONFIG_BUZZER_MIN_GAP_MS 70
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_ENABLE_DEFAULT
|
||||
#define CONFIG_BUZZER_ENABLE_DEFAULT 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_QUIET_START_MIN // quiet hours start (minutos desde 00:00)
|
||||
#define CONFIG_BUZZER_QUIET_START_MIN (22 * 60)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BUZZER_QUIET_END_MIN // quiet hours end (minutos desde 00:00)
|
||||
#define CONFIG_BUZZER_QUIET_END_MIN (7 * 60)
|
||||
#endif
|
||||
|
||||
// ===================== Tipos e estado =====================
|
||||
static const char *TAG = "Buzzer";
|
||||
|
||||
// --- Configuração de modo ---
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
BUZZER_MODE_ACTIVE = 0,
|
||||
BUZZER_MODE_PASSIVE
|
||||
} buzzer_mode_t;
|
||||
|
||||
typedef struct {
|
||||
buzzer_mode_t mode;
|
||||
gpio_num_t gpio;
|
||||
|
||||
// Apenas para PASSIVE
|
||||
uint32_t freq_hz; // ex: 4000
|
||||
uint8_t duty_percent; // 0–100
|
||||
ledc_mode_t ledc_speed_mode; // LEDC_LOW_SPEED_MODE
|
||||
ledc_timer_t ledc_timer; // LEDC_TIMER_1
|
||||
ledc_channel_t ledc_channel; // LEDC_CHANNEL_1
|
||||
ledc_timer_bit_t duty_resolution; // LEDC_TIMER_10_BIT
|
||||
} buzzer_config_t;
|
||||
|
||||
static buzzer_config_t s_buzzer_cfg = {
|
||||
.mode = BUZZER_MODE_PASSIVE, // Mude para PASSIVE se for buzzer passivo
|
||||
.gpio = BUZZER_GPIO,
|
||||
.freq_hz = 4000,
|
||||
.duty_percent = 50,
|
||||
.ledc_speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.ledc_timer = LEDC_TIMER_1,
|
||||
.ledc_channel = LEDC_CHANNEL_1,
|
||||
.duty_resolution = LEDC_TIMER_10_BIT
|
||||
};
|
||||
|
||||
// --- Estrutura de passos ---
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
uint16_t on_ms;
|
||||
uint16_t off_ms;
|
||||
} buzzer_step_t;
|
||||
|
||||
// Padrões de buzzer
|
||||
static const buzzer_step_t pattern_plugged[] = {{200, 100}};
|
||||
static const buzzer_step_t pattern_unplugged[] = {{150, 150}, {150, 150}, {150, 0}};
|
||||
static const buzzer_step_t pattern_charging[] = {{80, 150}, {100, 120}, {120, 100}, {140, 0}};
|
||||
static const buzzer_step_t pattern_ap_start[] = {{300, 150}, {300, 0}};
|
||||
static const buzzer_step_t pattern_card_read[] = {{50, 50}, {50, 0}};
|
||||
static const buzzer_step_t pattern_card_add[] = {{100, 100}, {100, 100}, {100, 0}};
|
||||
static const buzzer_step_t pattern_card_denied[] = {{300, 100}, {300, 0}};
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
const buzzer_step_t *steps;
|
||||
size_t length;
|
||||
} buzzer_pattern_t;
|
||||
|
||||
static const buzzer_pattern_t buzzer_patterns[] = {
|
||||
[BUZZER_PATTERN_PLUGGED] = {pattern_plugged, sizeof(pattern_plugged) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_UNPLUGGED] = {pattern_unplugged, sizeof(pattern_unplugged) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CHARGING] = {pattern_charging, sizeof(pattern_charging) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_AP_START] = {pattern_ap_start, sizeof(pattern_ap_start) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CARD_READ] = {pattern_card_read, sizeof(pattern_card_read) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CARD_ADD] = {pattern_card_add, sizeof(pattern_card_add) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CARD_DENIED] = {pattern_card_denied, sizeof(pattern_card_denied) / sizeof(buzzer_step_t)},
|
||||
typedef struct
|
||||
{
|
||||
buzzer_mode_t mode;
|
||||
gpio_num_t gpio;
|
||||
|
||||
// PASSIVE (PWM)
|
||||
uint32_t freq_hz;
|
||||
uint8_t duty_percent; // 0–100
|
||||
ledc_mode_t ledc_speed_mode; // LEDC_LOW_SPEED_MODE
|
||||
ledc_timer_t ledc_timer; // LEDC_TIMER_1
|
||||
ledc_channel_t ledc_channel; // LEDC_CHANNEL_1
|
||||
ledc_timer_bit_t duty_resolution; // LEDC_TIMER_10_BIT
|
||||
} buzzer_config_t;
|
||||
|
||||
// Controlo runtime
|
||||
static struct
|
||||
{
|
||||
bool enabled;
|
||||
uint16_t quiet_start_min; // [0..1440)
|
||||
uint16_t quiet_end_min; // [0..1440)
|
||||
bool quiet_enabled;
|
||||
} s_buzzer_ctl = {
|
||||
.enabled = CONFIG_BUZZER_ENABLE_DEFAULT,
|
||||
.quiet_start_min = CONFIG_BUZZER_QUIET_START_MIN,
|
||||
.quiet_end_min = CONFIG_BUZZER_QUIET_END_MIN,
|
||||
.quiet_enabled = false,
|
||||
};
|
||||
|
||||
// --- Funções de controle ---
|
||||
static inline uint32_t duty_from_percent(uint8_t pct, ledc_timer_bit_t res) {
|
||||
if (pct == 0) return 0;
|
||||
// Hardware cfg
|
||||
static buzzer_config_t s_buzzer_cfg = {
|
||||
.mode = CONFIG_BUZZER_MODE_PASSIVE ? BUZZER_MODE_PASSIVE : BUZZER_MODE_ACTIVE,
|
||||
.gpio = CONFIG_BUZZER_GPIO,
|
||||
.freq_hz = CONFIG_BUZZER_FREQ_HZ,
|
||||
.duty_percent = CONFIG_BUZZER_DUTY_PCT,
|
||||
.ledc_speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.ledc_timer = LEDC_TIMER_1,
|
||||
.ledc_channel = LEDC_CHANNEL_1,
|
||||
.duty_resolution = LEDC_TIMER_10_BIT};
|
||||
|
||||
// Fila e task
|
||||
static QueueHandle_t s_buzzer_q = NULL;
|
||||
static TaskHandle_t s_buzzer_task = NULL;
|
||||
|
||||
// Anti-spam básico
|
||||
static TickType_t s_last_play_tick = 0;
|
||||
static const TickType_t s_min_gap_ticks = pdMS_TO_TICKS(CONFIG_BUZZER_MIN_GAP_MS);
|
||||
|
||||
// ===================== Padrões (afinados) =====================
|
||||
// NOTA: os enums BUZZER_PATTERN_* vêm de buzzer_events.h
|
||||
|
||||
// Curtos e claros
|
||||
static const buzzer_step_t pattern_plugged[] = {{180, 120}}; // ~300 ms
|
||||
static const buzzer_step_t pattern_card_read[] = {{80, 80}, {80, 0}}; // 160 ms audível
|
||||
|
||||
// Um pouco mais longos, ritmo marcante
|
||||
static const buzzer_step_t pattern_unplugged[] = {{140, 140}, {140, 140}, {140, 0}}; // ~700 ms
|
||||
static const buzzer_step_t pattern_card_add[] = {{100, 100}, {100, 100}, {120, 0}}; // ~520 ms
|
||||
static const buzzer_step_t pattern_ap_start[] = {{250, 150}, {250, 0}}; // ~650 ms
|
||||
|
||||
// Charging mais curta (evento frequente)
|
||||
static const buzzer_step_t pattern_charging[] = {{80, 90}, {90, 80}, {100, 0}}; // ~440 ms
|
||||
|
||||
// Denied mais “duro”
|
||||
static const buzzer_step_t pattern_card_denied[] = {{250, 120}, {300, 0}}; // ~670 ms
|
||||
|
||||
// Fault crítico (duas trincas, ~1.7 s)
|
||||
static const buzzer_step_t pattern_fault[] = {
|
||||
{350, 120}, {350, 120}, {450, 250}, // bloco 1
|
||||
{350, 120},
|
||||
{350, 120},
|
||||
{450, 0} // bloco 2
|
||||
};
|
||||
|
||||
static const buzzer_pattern_t buzzer_patterns[] = {
|
||||
[BUZZER_PATTERN_PLUGGED] = {pattern_plugged, sizeof(pattern_plugged) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_UNPLUGGED] = {pattern_unplugged, sizeof(pattern_unplugged) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CHARGING] = {pattern_charging, sizeof(pattern_charging) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_AP_START] = {pattern_ap_start, sizeof(pattern_ap_start) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CARD_READ] = {pattern_card_read, sizeof(pattern_card_read) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CARD_ADD] = {pattern_card_add, sizeof(pattern_card_add) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_CARD_DENIED] = {pattern_card_denied, sizeof(pattern_card_denied) / sizeof(buzzer_step_t)},
|
||||
[BUZZER_PATTERN_FAULT] = {pattern_fault, sizeof(pattern_fault) / sizeof(buzzer_step_t)},
|
||||
};
|
||||
|
||||
// ===================== Helpers HW =====================
|
||||
static inline uint32_t duty_from_percent(uint8_t pct, ledc_timer_bit_t res)
|
||||
{
|
||||
if (pct == 0)
|
||||
return 0;
|
||||
if (pct > 100)
|
||||
pct = 100;
|
||||
uint32_t max = (1U << res) - 1U;
|
||||
return (uint32_t)((pct * max) / 100U);
|
||||
}
|
||||
|
||||
static void buzzer_on(void) {
|
||||
if (s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE) {
|
||||
ledc_set_freq(s_buzzer_cfg.ledc_speed_mode,
|
||||
s_buzzer_cfg.ledc_timer,
|
||||
s_buzzer_cfg.freq_hz);
|
||||
ledc_set_duty(s_buzzer_cfg.ledc_speed_mode,
|
||||
s_buzzer_cfg.ledc_channel,
|
||||
duty_from_percent(s_buzzer_cfg.duty_percent, s_buzzer_cfg.duty_resolution));
|
||||
ledc_update_duty(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_channel);
|
||||
} else {
|
||||
static inline bool is_pattern_valid(buzzer_pattern_id_t id)
|
||||
{
|
||||
return (id > BUZZER_PATTERN_NONE && id < BUZZER_PATTERN_MAX);
|
||||
}
|
||||
|
||||
static void buzzer_on(void)
|
||||
{
|
||||
if (s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE)
|
||||
{
|
||||
// Não mudar freq a cada beep; já foi configurada na init.
|
||||
esp_err_t err1 = ledc_set_duty(s_buzzer_cfg.ledc_speed_mode,
|
||||
s_buzzer_cfg.ledc_channel,
|
||||
duty_from_percent(s_buzzer_cfg.duty_percent, s_buzzer_cfg.duty_resolution));
|
||||
if (err1 != ESP_OK)
|
||||
ESP_LOGW(TAG, "ledc_set_duty err=%s", esp_err_to_name(err1));
|
||||
esp_err_t err2 = ledc_update_duty(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_channel);
|
||||
if (err2 != ESP_OK)
|
||||
ESP_LOGW(TAG, "ledc_update_duty err=%s", esp_err_to_name(err2));
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_level(s_buzzer_cfg.gpio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void buzzer_off(void) {
|
||||
if (s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE) {
|
||||
ledc_set_duty(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_channel, 0);
|
||||
ledc_update_duty(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_channel);
|
||||
} else {
|
||||
static void buzzer_off(void)
|
||||
{
|
||||
if (s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE)
|
||||
{
|
||||
esp_err_t err1 = ledc_set_duty(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_channel, 0);
|
||||
if (err1 != ESP_OK)
|
||||
ESP_LOGW(TAG, "ledc_set_duty(0) err=%s", esp_err_to_name(err1));
|
||||
esp_err_t err2 = ledc_update_duty(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_channel);
|
||||
if (err2 != ESP_OK)
|
||||
ESP_LOGW(TAG, "ledc_update_duty err=%s", esp_err_to_name(err2));
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_level(s_buzzer_cfg.gpio, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Execução de padrões ---
|
||||
static void buzzer_execute(buzzer_pattern_id_t pattern_id) {
|
||||
if ((int)pattern_id <= BUZZER_PATTERN_NONE || pattern_id >= BUZZER_PATTERN_MAX) {
|
||||
static bool in_quiet_hours(void)
|
||||
{
|
||||
if (!s_buzzer_ctl.quiet_enabled)
|
||||
return false;
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm lt;
|
||||
if (localtime_r(&now, <) == NULL)
|
||||
return false;
|
||||
|
||||
uint16_t minutes = (uint16_t)(lt.tm_hour * 60 + lt.tm_min);
|
||||
uint16_t start = s_buzzer_ctl.quiet_start_min;
|
||||
uint16_t end = s_buzzer_ctl.quiet_end_min;
|
||||
|
||||
if (start == end)
|
||||
return false; // desativado
|
||||
if (start < end)
|
||||
{
|
||||
return (minutes >= start && minutes < end);
|
||||
}
|
||||
else
|
||||
{ // janela cruza meia-noite
|
||||
return (minutes >= start || minutes < end);
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== Execução do padrão (apenas dentro da task) =====================
|
||||
static void buzzer_execute(buzzer_pattern_id_t pattern_id)
|
||||
{
|
||||
if (!is_pattern_valid(pattern_id))
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid buzzer pattern id: %d", pattern_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Executing buzzer pattern ID: %d", pattern_id);
|
||||
const buzzer_pattern_t *pattern = &buzzer_patterns[pattern_id];
|
||||
for (size_t i = 0; i < pattern->length; i++) {
|
||||
for (size_t i = 0; i < pattern->length; i++)
|
||||
{
|
||||
buzzer_on();
|
||||
vTaskDelay(pdMS_TO_TICKS(pattern->steps[i].on_ms));
|
||||
buzzer_off();
|
||||
if (pattern->steps[i].off_ms > 0) {
|
||||
if (pattern->steps[i].off_ms > 0)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(pattern->steps[i].off_ms));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Event Handlers ---
|
||||
static void buzzer_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data) {
|
||||
if (base != BUZZER_EVENTS || id != BUZZER_EVENT_PLAY_PATTERN || data == NULL) return;
|
||||
// ===================== Task & Fila =====================
|
||||
static void buzzer_task(void *arg)
|
||||
{
|
||||
buzzer_pattern_id_t id;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (xQueueReceive(s_buzzer_q, &id, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
|
||||
ESP_LOGD(TAG, "dequeue pattern %d", id); // na buzzer_task()
|
||||
|
||||
if (!s_buzzer_ctl.enabled)
|
||||
continue;
|
||||
|
||||
// Quiet hours: permitir apenas alertas críticos/negativos
|
||||
if (in_quiet_hours())
|
||||
{
|
||||
if (!(id == BUZZER_PATTERN_FAULT || id == BUZZER_PATTERN_CARD_DENIED))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Anti-spam global
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
if ((now - s_last_play_tick) < s_min_gap_ticks)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
s_last_play_tick = now;
|
||||
|
||||
buzzer_execute(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== API pública =====================
|
||||
void buzzer_play(buzzer_pattern_id_t id)
|
||||
{
|
||||
|
||||
ESP_LOGD(TAG, "enqueue pattern %d", id); // dentro de buzzer_play()
|
||||
|
||||
if (!is_pattern_valid(id) || s_buzzer_q == NULL)
|
||||
return;
|
||||
(void)xQueueSend(s_buzzer_q, &id, 0);
|
||||
}
|
||||
|
||||
void buzzer_stop(void)
|
||||
{
|
||||
// Interrompe imediatamente: esvazia fila e desliga
|
||||
if (s_buzzer_q)
|
||||
xQueueReset(s_buzzer_q);
|
||||
buzzer_off();
|
||||
}
|
||||
|
||||
void buzzer_set_enabled(bool enabled)
|
||||
{
|
||||
s_buzzer_ctl.enabled = enabled;
|
||||
if (!enabled)
|
||||
buzzer_off();
|
||||
}
|
||||
|
||||
bool buzzer_get_enabled(void)
|
||||
{
|
||||
return s_buzzer_ctl.enabled;
|
||||
}
|
||||
|
||||
void buzzer_set_quiet_hours(bool enabled, uint16_t start_min, uint16_t end_min)
|
||||
{
|
||||
s_buzzer_ctl.quiet_enabled = enabled;
|
||||
if (start_min < 1440)
|
||||
s_buzzer_ctl.quiet_start_min = start_min;
|
||||
if (end_min < 1440)
|
||||
s_buzzer_ctl.quiet_end_min = end_min;
|
||||
}
|
||||
|
||||
// Opcional: mudar tom dinamicamente (apenas se o timer for exclusivo do buzzer)
|
||||
esp_err_t buzzer_set_frequency(uint32_t hz)
|
||||
{
|
||||
if (s_buzzer_cfg.mode != BUZZER_MODE_PASSIVE)
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
if (hz < 50 || hz > 20000)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
s_buzzer_cfg.freq_hz = hz;
|
||||
return ledc_set_freq(s_buzzer_cfg.ledc_speed_mode, s_buzzer_cfg.ledc_timer, hz);
|
||||
}
|
||||
|
||||
void buzzer_set_duty_percent(uint8_t pct)
|
||||
{
|
||||
if (pct > 100)
|
||||
pct = 100;
|
||||
s_buzzer_cfg.duty_percent = pct;
|
||||
}
|
||||
|
||||
// ===================== Event Handlers =====================
|
||||
static void buzzer_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
|
||||
{
|
||||
if (base != BUZZER_EVENTS || id != BUZZER_EVENT_PLAY_PATTERN || data == NULL)
|
||||
return;
|
||||
|
||||
buzzer_event_data_t *evt = (buzzer_event_data_t *)data;
|
||||
if ((int)evt->pattern < BUZZER_PATTERN_NONE || evt->pattern >= BUZZER_PATTERN_MAX) {
|
||||
if (!is_pattern_valid(evt->pattern))
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid buzzer pattern received: %d", evt->pattern);
|
||||
return;
|
||||
}
|
||||
|
||||
buzzer_execute(evt->pattern);
|
||||
buzzer_play(evt->pattern);
|
||||
}
|
||||
|
||||
static void evse_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data) {
|
||||
if (base != EVSE_EVENTS || id != EVSE_EVENT_STATE_CHANGED || data == NULL) return;
|
||||
static void evse_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
|
||||
{
|
||||
if (base != EVSE_EVENTS || id != EVSE_EVENT_STATE_CHANGED || data == NULL)
|
||||
return;
|
||||
|
||||
const evse_state_event_data_t *evt = (const evse_state_event_data_t *)data;
|
||||
ESP_LOGI(TAG, "EVSE event received: state = %d", evt->state);
|
||||
ESP_LOGD(TAG, "EVSE event: state=%d", evt->state);
|
||||
|
||||
buzzer_event_data_t buzzer_evt = {0};
|
||||
|
||||
switch (evt->state) {
|
||||
case EVSE_STATE_EVENT_IDLE:
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_UNPLUGGED;
|
||||
break;
|
||||
case EVSE_STATE_EVENT_WAITING:
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_PLUGGED;
|
||||
break;
|
||||
case EVSE_STATE_EVENT_CHARGING:
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_CHARGING;
|
||||
break;
|
||||
case EVSE_STATE_EVENT_FAULT:
|
||||
default:
|
||||
return;
|
||||
switch (evt->state)
|
||||
{
|
||||
case EVSE_STATE_EVENT_IDLE:
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_UNPLUGGED;
|
||||
break;
|
||||
case EVSE_STATE_EVENT_WAITING:
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_PLUGGED;
|
||||
break;
|
||||
case EVSE_STATE_EVENT_CHARGING:
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_CHARGING;
|
||||
break;
|
||||
case EVSE_STATE_EVENT_FAULT:
|
||||
// Preempta qualquer beep em andamento
|
||||
buzzer_stop();
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_FAULT;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
esp_event_post(BUZZER_EVENTS, BUZZER_EVENT_PLAY_PATTERN, &buzzer_evt, sizeof(buzzer_evt), portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void network_event_handler(void *handler_args, esp_event_base_t base, int32_t id, void *event_data) {
|
||||
if (id == NETWORK_EVENT_AP_STARTED) {
|
||||
buzzer_event_data_t evt = {
|
||||
.pattern = BUZZER_PATTERN_AP_START
|
||||
};
|
||||
static void network_event_handler(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
|
||||
{
|
||||
if (base != NETWORK_EVENTS)
|
||||
return;
|
||||
if (id == NETWORK_EVENT_AP_STARTED)
|
||||
{
|
||||
buzzer_event_data_t evt = {.pattern = BUZZER_PATTERN_AP_START};
|
||||
esp_event_post(BUZZER_EVENTS, BUZZER_EVENT_PLAY_PATTERN, &evt, sizeof(evt), portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
static void auth_event_handler(void *arg, esp_event_base_t base, int32_t id, void *event_data) {
|
||||
if (base != AUTH_EVENTS || event_data == NULL) return;
|
||||
static void auth_event_handler(void *arg, esp_event_base_t base, int32_t id, void *event_data)
|
||||
{
|
||||
if (base != AUTH_EVENTS || event_data == NULL)
|
||||
return;
|
||||
|
||||
buzzer_event_data_t buzzer_evt = {0};
|
||||
|
||||
if (id == AUTH_EVENT_TAG_PROCESSED) {
|
||||
if (id == AUTH_EVENT_TAG_PROCESSED)
|
||||
{
|
||||
const auth_tag_event_data_t *evt = (const auth_tag_event_data_t *)event_data;
|
||||
ESP_LOGI(TAG, "AUTH processed: tag=%s authorized=%d", evt->tag, evt->authorized);
|
||||
ESP_LOGD(TAG, "AUTH processed: tag=%s authorized=%d", evt->tag, evt->authorized);
|
||||
buzzer_evt.pattern = evt->authorized ? BUZZER_PATTERN_CARD_READ : BUZZER_PATTERN_CARD_DENIED;
|
||||
} else if (id == AUTH_EVENT_TAG_SAVED) {
|
||||
}
|
||||
else if (id == AUTH_EVENT_TAG_SAVED)
|
||||
{
|
||||
buzzer_evt.pattern = BUZZER_PATTERN_CARD_ADD;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
esp_event_post(BUZZER_EVENTS, BUZZER_EVENT_PLAY_PATTERN, &buzzer_evt, sizeof(buzzer_evt), portMAX_DELAY);
|
||||
}
|
||||
|
||||
// --- Inicialização ---
|
||||
void buzzer_init(void) {
|
||||
if (s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE) {
|
||||
// Configura temporizador do PWM
|
||||
// ===================== Inicialização / Deinit =====================
|
||||
void buzzer_init(void)
|
||||
{
|
||||
// Config HW
|
||||
if (s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE)
|
||||
{
|
||||
ledc_timer_config_t tcfg = {
|
||||
.speed_mode = s_buzzer_cfg.ledc_speed_mode,
|
||||
.duty_resolution = s_buzzer_cfg.duty_resolution,
|
||||
.timer_num = s_buzzer_cfg.ledc_timer,
|
||||
.freq_hz = s_buzzer_cfg.freq_hz,
|
||||
.clk_cfg = LEDC_AUTO_CLK
|
||||
};
|
||||
.clk_cfg = LEDC_AUTO_CLK};
|
||||
ESP_ERROR_CHECK(ledc_timer_config(&tcfg));
|
||||
|
||||
// Configura canal PWM
|
||||
ledc_channel_config_t ccfg = {
|
||||
.gpio_num = s_buzzer_cfg.gpio,
|
||||
.speed_mode = s_buzzer_cfg.ledc_speed_mode,
|
||||
@@ -207,45 +468,74 @@ void buzzer_init(void) {
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.timer_sel = s_buzzer_cfg.ledc_timer,
|
||||
.duty = 0,
|
||||
.hpoint = 0
|
||||
};
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ccfg));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_config_t io = {
|
||||
.pin_bit_mask = (1ULL << s_buzzer_cfg.gpio),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_down_en = 0,
|
||||
.pull_up_en = 0,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io);
|
||||
.intr_type = GPIO_INTR_DISABLE};
|
||||
ESP_ERROR_CHECK(gpio_config(&io));
|
||||
gpio_set_level(s_buzzer_cfg.gpio, 0);
|
||||
}
|
||||
|
||||
buzzer_set_quiet_hours(false, 0, 0);
|
||||
buzzer_set_enabled(true);
|
||||
|
||||
buzzer_off();
|
||||
|
||||
// Registro de handlers
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(BUZZER_EVENTS,
|
||||
BUZZER_EVENT_PLAY_PATTERN,
|
||||
buzzer_event_handler,
|
||||
NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(EVSE_EVENTS,
|
||||
EVSE_EVENT_STATE_CHANGED,
|
||||
evse_event_handler,
|
||||
NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS,
|
||||
AUTH_EVENT_TAG_PROCESSED,
|
||||
auth_event_handler,
|
||||
NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS,
|
||||
AUTH_EVENT_TAG_SAVED,
|
||||
auth_event_handler,
|
||||
NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(NETWORK_EVENTS,
|
||||
NETWORK_EVENT_AP_STARTED,
|
||||
network_event_handler,
|
||||
NULL));
|
||||
// Fila + Task
|
||||
s_buzzer_q = xQueueCreate(CONFIG_BUZZER_QUEUE_LEN, sizeof(buzzer_pattern_id_t));
|
||||
configASSERT(s_buzzer_q != NULL);
|
||||
BaseType_t ok = xTaskCreatePinnedToCore(
|
||||
buzzer_task,
|
||||
"buzzer_task",
|
||||
CONFIG_BUZZER_TASK_STACK,
|
||||
NULL,
|
||||
CONFIG_BUZZER_TASK_PRIO,
|
||||
&s_buzzer_task,
|
||||
tskNO_AFFINITY);
|
||||
configASSERT(ok == pdPASS);
|
||||
|
||||
ESP_LOGI(TAG, "Buzzer initialized on GPIO %d (%s)",
|
||||
// Handlers
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(BUZZER_EVENTS, BUZZER_EVENT_PLAY_PATTERN, buzzer_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(EVSE_EVENTS, EVSE_EVENT_STATE_CHANGED, evse_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS, AUTH_EVENT_TAG_PROCESSED, auth_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS, AUTH_EVENT_TAG_SAVED, auth_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(NETWORK_EVENTS, NETWORK_EVENT_AP_STARTED, network_event_handler, NULL));
|
||||
|
||||
ESP_LOGI(TAG, "Buzzer initialized on GPIO %d (%s), freq=%lu Hz, duty=%u%%, enabled=%d",
|
||||
s_buzzer_cfg.gpio,
|
||||
s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE ? "passive/PWM" : "active/ON-OFF");
|
||||
s_buzzer_cfg.mode == BUZZER_MODE_PASSIVE ? "passive/PWM" : "active/ON-OFF",
|
||||
(unsigned long)s_buzzer_cfg.freq_hz,
|
||||
(unsigned)s_buzzer_cfg.duty_percent,
|
||||
(int)s_buzzer_ctl.enabled);
|
||||
}
|
||||
|
||||
void buzzer_deinit(void)
|
||||
{
|
||||
(void)esp_event_handler_unregister(BUZZER_EVENTS, BUZZER_EVENT_PLAY_PATTERN, buzzer_event_handler);
|
||||
(void)esp_event_handler_unregister(EVSE_EVENTS, EVSE_EVENT_STATE_CHANGED, evse_event_handler);
|
||||
(void)esp_event_handler_unregister(AUTH_EVENTS, AUTH_EVENT_TAG_PROCESSED, auth_event_handler);
|
||||
(void)esp_event_handler_unregister(AUTH_EVENTS, AUTH_EVENT_TAG_SAVED, auth_event_handler);
|
||||
(void)esp_event_handler_unregister(NETWORK_EVENTS, NETWORK_EVENT_AP_STARTED, network_event_handler);
|
||||
|
||||
if (s_buzzer_q)
|
||||
{
|
||||
vQueueDelete(s_buzzer_q);
|
||||
s_buzzer_q = NULL;
|
||||
}
|
||||
|
||||
if (s_buzzer_task)
|
||||
{
|
||||
vTaskDelete(s_buzzer_task);
|
||||
s_buzzer_task = NULL;
|
||||
}
|
||||
|
||||
buzzer_off();
|
||||
ESP_LOGI(TAG, "Buzzer deinitialized");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user