Refactor notification system to use HTTP POST for buzz events, updating configuration and documentation accordingly.
This commit is contained in:
+12
-14
@@ -91,20 +91,18 @@ menu "Door Buzzer Detector"
|
||||
default ""
|
||||
endmenu
|
||||
|
||||
menu "ntfy notifications"
|
||||
config BUZZ_NTFY_SERVER
|
||||
string "ntfy server URL"
|
||||
default "https://ntfy.sh"
|
||||
config BUZZ_NTFY_TOPIC
|
||||
string "Alert topic (anyone who knows it can read it: make it unguessable)"
|
||||
default "change-me-door-buzzer"
|
||||
config BUZZ_NTFY_HB_TOPIC
|
||||
string "Heartbeat topic"
|
||||
default "change-me-door-buzzer-heartbeat"
|
||||
config BUZZ_HEARTBEAT_HOURS
|
||||
int "Heartbeat interval in hours (0 = disabled)"
|
||||
default 0
|
||||
range 0 720
|
||||
menu "Buzz event HTTP endpoint"
|
||||
config BUZZ_EVENT_URL
|
||||
string "POST endpoint URL"
|
||||
default ""
|
||||
help
|
||||
Full URL for the JSON event POST. Use an address reachable from the ESP32;
|
||||
localhost refers to the ESP32 itself, not your development computer.
|
||||
config BUZZ_EVENT_SECRET
|
||||
string "Event secret key"
|
||||
default ""
|
||||
help
|
||||
Secret sent in the JSON request body. Keep it private and configure it for the endpoint.
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
+30
-20
@@ -13,11 +13,19 @@
|
||||
static const char *TAG = "config";
|
||||
#define NVS_NS "buzz"
|
||||
#define CFG_KEY "cfg"
|
||||
#define CFG_MAGIC 0xB0220003u
|
||||
#define CFG_MAGIC 0xB0220004u
|
||||
#define CFG_MAGIC_PRE_EVENT_POST 0xB0220003u
|
||||
#define CFG_MAGIC_PRE_500MS 0xB0220002u
|
||||
#define CFG_MAGIC_PRE_COOLDOWN_MS 0xB0220001u
|
||||
|
||||
typedef struct { uint32_t magic; app_config_t cfg; } cfg_blob_t;
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
float threshold, min_rms;
|
||||
uint32_t win_n, win_m, cooldown_ms;
|
||||
float noise_mult, adapt_weight;
|
||||
uint32_t monitor_ms, heartbeat_h;
|
||||
} legacy_cfg_blob_t;
|
||||
|
||||
typedef enum { PT_FLOAT, PT_UINT } ptype_t;
|
||||
typedef struct {
|
||||
@@ -38,7 +46,6 @@ static const param_t s_params[] = {
|
||||
P(noise_mult, PT_FLOAT, 1.0, 100.0, "learn/adapt gate = noise floor x this"),
|
||||
P(adapt_weight, PT_FLOAT, 0.0, 1.0, "weight of new template in adapt"),
|
||||
P(monitor_ms, PT_UINT, 10, 60000, "min interval between monitor lines (ms)"),
|
||||
P(heartbeat_h, PT_UINT, 0, 720, "heartbeat period (h), 0 = off"),
|
||||
};
|
||||
#define NPARAMS (sizeof(s_params) / sizeof(s_params[0]))
|
||||
|
||||
@@ -55,7 +62,6 @@ static void load_defaults(app_config_t *c)
|
||||
c->noise_mult = CONFIG_BUZZ_NOISE_MULT_X10 / 10.0f;
|
||||
c->adapt_weight = CONFIG_BUZZ_ADAPT_WEIGHT_PCT / 100.0f;
|
||||
c->monitor_ms = CONFIG_BUZZ_MONITOR_MS;
|
||||
c->heartbeat_h = CONFIG_BUZZ_HEARTBEAT_HOURS;
|
||||
if (c->win_m > c->win_n) c->win_m = c->win_n;
|
||||
}
|
||||
|
||||
@@ -94,25 +100,29 @@ esp_err_t config_init(void)
|
||||
load_defaults(&s_cfg);
|
||||
nvs_handle_t h;
|
||||
if (nvs_open(NVS_NS, NVS_READONLY, &h) == ESP_OK) {
|
||||
cfg_blob_t blob;
|
||||
union {
|
||||
cfg_blob_t current;
|
||||
legacy_cfg_blob_t legacy;
|
||||
} blob;
|
||||
size_t len = sizeof(blob);
|
||||
if (nvs_get_blob(h, CFG_KEY, &blob, &len) == ESP_OK && len == sizeof(blob)) {
|
||||
if (blob.magic == CFG_MAGIC) {
|
||||
s_cfg = blob.cfg;
|
||||
if (nvs_get_blob(h, CFG_KEY, &blob, &len) == ESP_OK) {
|
||||
if (len == sizeof(cfg_blob_t) && blob.current.magic == CFG_MAGIC) {
|
||||
s_cfg = blob.current.cfg;
|
||||
ESP_LOGI(TAG, "loaded saved config from NVS");
|
||||
} else if (blob.magic == CFG_MAGIC_PRE_COOLDOWN_MS) {
|
||||
s_cfg = blob.cfg;
|
||||
s_cfg.cooldown_ms = CONFIG_BUZZ_COOLDOWN_MS;
|
||||
ESP_LOGI(TAG, "migrating saved config to event-grouping cooldown");
|
||||
err = save_locked();
|
||||
if (err != ESP_OK) {
|
||||
nvs_close(h);
|
||||
return err;
|
||||
}
|
||||
} else if (blob.magic == CFG_MAGIC_PRE_500MS) {
|
||||
s_cfg = blob.cfg;
|
||||
s_cfg.cooldown_ms = CONFIG_BUZZ_COOLDOWN_MS;
|
||||
ESP_LOGI(TAG, "updating saved cooldown for buzz-event grouping");
|
||||
} else if (len == sizeof(legacy_cfg_blob_t) &&
|
||||
(blob.legacy.magic == CFG_MAGIC_PRE_EVENT_POST ||
|
||||
blob.legacy.magic == CFG_MAGIC_PRE_500MS ||
|
||||
blob.legacy.magic == CFG_MAGIC_PRE_COOLDOWN_MS)) {
|
||||
s_cfg.threshold = blob.legacy.threshold;
|
||||
s_cfg.min_rms = blob.legacy.min_rms;
|
||||
s_cfg.win_n = blob.legacy.win_n;
|
||||
s_cfg.win_m = blob.legacy.win_m;
|
||||
s_cfg.cooldown_ms = blob.legacy.magic == CFG_MAGIC_PRE_EVENT_POST
|
||||
? blob.legacy.cooldown_ms : CONFIG_BUZZ_COOLDOWN_MS;
|
||||
s_cfg.noise_mult = blob.legacy.noise_mult;
|
||||
s_cfg.adapt_weight = blob.legacy.adapt_weight;
|
||||
s_cfg.monitor_ms = blob.legacy.monitor_ms;
|
||||
ESP_LOGI(TAG, "migrating saved detector settings; heartbeat setting removed");
|
||||
err = save_locked();
|
||||
if (err != ESP_OK) {
|
||||
nvs_close(h);
|
||||
|
||||
@@ -14,7 +14,6 @@ typedef struct {
|
||||
float noise_mult; // learn/adapt gate = noise floor * this
|
||||
float adapt_weight; // weight of the NEW template in `adapt` (0..1)
|
||||
uint32_t monitor_ms; // min interval between `monitor` lines
|
||||
uint32_t heartbeat_h; // heartbeat period in hours, 0 = off
|
||||
} app_config_t;
|
||||
|
||||
esp_err_t config_init(void); // nvs_flash_init + load
|
||||
|
||||
+5
-5
@@ -139,9 +139,9 @@ static int cmd_status(int argc, char **argv)
|
||||
(unsigned long)ps.proc_max_us, HOP_LEN * 1000000 / FS_HZ);
|
||||
printf("wifi: %s%s%s\n", ns.wifi_configured ? (ns.wifi_connected ? "connected " : "DISCONNECTED") : "not configured",
|
||||
ns.wifi_connected ? ns.ip : "", "");
|
||||
printf("notifications: ok %lu, failed %lu, dropped %lu, topic %s%s\n", (unsigned long)ns.sent_ok,
|
||||
(unsigned long)ns.sent_failed, (unsigned long)ns.dropped, CONFIG_BUZZ_NTFY_TOPIC,
|
||||
cfg.heartbeat_h ? " (heartbeat on)" : "");
|
||||
printf("event POST: %s, ok %lu, failed %lu, dropped %lu\n",
|
||||
ns.endpoint_configured ? "endpoint configured" : "endpoint not configured",
|
||||
(unsigned long)ns.sent_ok, (unsigned long)ns.sent_failed, (unsigned long)ns.dropped);
|
||||
printf("heap free: %lu bytes\n", (unsigned long)esp_get_free_heap_size());
|
||||
return 0;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ static int cmd_fingerprint(int argc, char **argv)
|
||||
|
||||
static int cmd_alert(int argc, char **argv)
|
||||
{
|
||||
printf(notifier_send(NOTIF_TEST, "Test notification") ? "queued\n" : "queue full\n");
|
||||
printf(notifier_send(42) ? "queued test event (delay_ms=42)\n" : "queue full\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ esp_err_t console_start(void)
|
||||
reg("get", "show parameters", "[param]", cmd_get);
|
||||
reg("status", "template source, detector state, timing, Wi-Fi", NULL, cmd_status);
|
||||
reg("fingerprint", "print live fingerprint and active template", NULL, cmd_fingerprint);
|
||||
reg("alert", "send a test notification", NULL, cmd_alert);
|
||||
reg("alert", "send a test event POST", NULL, cmd_alert);
|
||||
reg("reboot", "restart", NULL, cmd_reboot);
|
||||
|
||||
err = esp_console_start_repl(repl);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Door buzzer detector: spectral-template matching on an I2S MEMS mic, ntfy push alerts.
|
||||
// Door buzzer detector: spectral-template matching on an I2S MEMS mic, event HTTP POST.
|
||||
#include <stdio.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
+99
-78
@@ -1,5 +1,5 @@
|
||||
// Wi-Fi station with exponential-backoff reconnect + ntfy.sh HTTPS notifications.
|
||||
// Sending happens in its own task fed by a queue so networking can never block audio.
|
||||
// Wi-Fi station with exponential-backoff reconnect and queued event POSTs.
|
||||
// HTTP requests run in their own task so networking cannot block audio.
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_crt_bundle.h"
|
||||
@@ -13,29 +13,26 @@
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "config_store.h"
|
||||
#include "notifier.h"
|
||||
|
||||
static const char *TAG = "notify";
|
||||
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define SEND_ATTEMPTS 4
|
||||
#define NET_TASK_STACK 8192
|
||||
#define NET_TASK_PRIO 5
|
||||
#define BACKOFF_MIN_MS 1000
|
||||
#define BACKOFF_MAX_MS 60000
|
||||
#define EVENT_BODY_SIZE 512
|
||||
|
||||
typedef struct {
|
||||
notif_kind_t kind;
|
||||
char msg[96];
|
||||
} notif_msg_t;
|
||||
uint32_t delay_ms;
|
||||
} event_msg_t;
|
||||
|
||||
static QueueHandle_t s_q;
|
||||
static EventGroupHandle_t s_eg;
|
||||
static esp_timer_handle_t s_reconnect_timer;
|
||||
static uint32_t s_backoff_ms = BACKOFF_MIN_MS;
|
||||
static notifier_stats_t s_stats;
|
||||
static bool s_wifi_configured;
|
||||
|
||||
static void reconnect_cb(void *arg)
|
||||
{
|
||||
@@ -53,7 +50,7 @@ static void wifi_event_handler(void *arg, esp_event_base_t base, int32_t id, voi
|
||||
xEventGroupClearBits(s_eg, WIFI_CONNECTED_BIT);
|
||||
s_stats.wifi_connected = false;
|
||||
ESP_LOGW(TAG, "Wi-Fi disconnected, retry in %lu ms", (unsigned long)s_backoff_ms);
|
||||
esp_timer_stop(s_reconnect_timer); // ok if not running
|
||||
esp_timer_stop(s_reconnect_timer);
|
||||
esp_timer_start_once(s_reconnect_timer, (uint64_t)s_backoff_ms * 1000ULL);
|
||||
s_backoff_ms = s_backoff_ms * 2 > BACKOFF_MAX_MS ? BACKOFF_MAX_MS : s_backoff_ms * 2;
|
||||
} else if (base == IP_EVENT && id == IP_EVENT_STA_GOT_IP) {
|
||||
@@ -66,93 +63,107 @@ static void wifi_event_handler(void *arg, esp_event_base_t base, int32_t id, voi
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t post_ntfy(const char *topic, const char *title, const char *prio, const char *tags, const char *body)
|
||||
static bool make_event_body(uint32_t delay_ms, char *body, size_t body_size)
|
||||
{
|
||||
char url[192];
|
||||
size_t sl = strlen(CONFIG_BUZZ_NTFY_SERVER);
|
||||
while (sl > 0 && CONFIG_BUZZ_NTFY_SERVER[sl - 1] == '/') sl--;
|
||||
snprintf(url, sizeof(url), "%.*s/%s", (int)sl, CONFIG_BUZZ_NTFY_SERVER, topic);
|
||||
int n = snprintf(body, body_size, "{\"delay_ms\":%lu,\"secret\":\"",
|
||||
(unsigned long)delay_ms);
|
||||
if (n < 0 || (size_t)n >= body_size) return false;
|
||||
size_t used = (size_t)n;
|
||||
|
||||
for (const unsigned char *p = (const unsigned char *)CONFIG_BUZZ_EVENT_SECRET; *p; p++) {
|
||||
char escaped[7];
|
||||
const char *text = (const char *)p;
|
||||
size_t len = 1;
|
||||
if (*p == '"' || *p == '\\') {
|
||||
escaped[0] = '\\';
|
||||
escaped[1] = (char)*p;
|
||||
text = escaped;
|
||||
len = 2;
|
||||
} else if (*p < 0x20) {
|
||||
snprintf(escaped, sizeof(escaped), "\\u%04x", *p);
|
||||
text = escaped;
|
||||
len = 6;
|
||||
}
|
||||
if (len >= body_size - used) return false;
|
||||
memcpy(body + used, text, len);
|
||||
used += len;
|
||||
}
|
||||
if (body_size - used < 3) return false;
|
||||
body[used++] = '"';
|
||||
body[used++] = '}';
|
||||
body[used] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
// One queue item produces at most one HTTP request: there is deliberately no retry.
|
||||
static bool post_event(uint32_t delay_ms)
|
||||
{
|
||||
EventBits_t bits = xEventGroupWaitBits(s_eg, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE,
|
||||
pdMS_TO_TICKS(15000));
|
||||
if (!(bits & WIFI_CONNECTED_BIT)) {
|
||||
ESP_LOGE(TAG, "Wi-Fi unavailable; event was not sent");
|
||||
return false;
|
||||
}
|
||||
|
||||
char body[EVENT_BODY_SIZE];
|
||||
if (!make_event_body(delay_ms, body, sizeof(body))) {
|
||||
ESP_LOGE(TAG, "event body exceeds buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *url = "http://192.168.0.154:3000/event/buzz";
|
||||
esp_http_client_config_t cfg = {
|
||||
.url = url,
|
||||
.method = HTTP_METHOD_POST,
|
||||
.timeout_ms = 10000,
|
||||
.disable_auto_redirect = true,
|
||||
.crt_bundle_attach = esp_crt_bundle_attach,
|
||||
};
|
||||
esp_http_client_handle_t c = esp_http_client_init(&cfg);
|
||||
if (!c) return ESP_ERR_NO_MEM;
|
||||
esp_http_client_set_header(c, "Title", title);
|
||||
esp_http_client_set_header(c, "Priority", prio);
|
||||
esp_http_client_set_header(c, "Tags", tags);
|
||||
esp_http_client_set_post_field(c, body, (int)strlen(body));
|
||||
esp_err_t err = esp_http_client_perform(c);
|
||||
if (err == ESP_OK) {
|
||||
int st = esp_http_client_get_status_code(c);
|
||||
if (st != 200) {
|
||||
ESP_LOGW(TAG, "ntfy HTTP status %d", st);
|
||||
err = ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "HTTP perform: %s", esp_err_to_name(err));
|
||||
if (!c) {
|
||||
ESP_LOGE(TAG, "could not create HTTP client");
|
||||
return false;
|
||||
}
|
||||
esp_err_t err = esp_http_client_set_header(c, "Content-Type", "application/json");
|
||||
if (err == ESP_OK) err = esp_http_client_set_post_field(c, body, (int)strlen(body));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "configure event POST: %s", esp_err_to_name(err));
|
||||
esp_http_client_cleanup(c);
|
||||
return false;
|
||||
}
|
||||
esp_http_client_cleanup(c);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Retry a few times with backoff while Wi-Fi is down / the request fails, then drop.
|
||||
static bool deliver(const char *topic, const char *title, const char *prio, const char *tags, const char *body)
|
||||
{
|
||||
uint32_t wait_ms = 2000;
|
||||
for (int attempt = 1; attempt <= SEND_ATTEMPTS; attempt++) {
|
||||
EventBits_t bits = xEventGroupWaitBits(s_eg, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, pdMS_TO_TICKS(15000));
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
if (post_ntfy(topic, title, prio, tags, body) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "sent '%s' to %s (attempt %d)", body, topic, attempt);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Wi-Fi down (attempt %d/%d)", attempt, SEND_ATTEMPTS);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(wait_ms));
|
||||
wait_ms *= 2;
|
||||
err = esp_http_client_perform(c);
|
||||
int status = err == ESP_OK ? esp_http_client_get_status_code(c) : 0;
|
||||
esp_http_client_cleanup(c);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "event POST failed: %s", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
ESP_LOGE(TAG, "giving up on '%s', dropped", body);
|
||||
return false;
|
||||
if (status < 200 || status >= 300) {
|
||||
ESP_LOGE(TAG, "event endpoint returned HTTP %d", status);
|
||||
return false;
|
||||
}
|
||||
ESP_LOGI(TAG, "sent buzz duration %lu ms (HTTP %d)", (unsigned long)delay_ms, status);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void net_task(void *arg)
|
||||
{
|
||||
int64_t last_hb_us = esp_timer_get_time();
|
||||
notif_msg_t m;
|
||||
event_msg_t msg;
|
||||
for (;;) {
|
||||
if (xQueueReceive(s_q, &m, pdMS_TO_TICKS(30000)) == pdTRUE) {
|
||||
bool ok = deliver(CONFIG_BUZZ_NTFY_TOPIC, "Door buzzer",
|
||||
m.kind == NOTIF_ALERT ? "high" : "default",
|
||||
m.kind == NOTIF_ALERT ? "bell" : "wrench", m.msg);
|
||||
if (ok) s_stats.sent_ok++; else s_stats.sent_failed++;
|
||||
last_hb_us = esp_timer_get_time(); // an alert proves liveness; restart the heartbeat timer
|
||||
}
|
||||
app_config_t cfg;
|
||||
config_get(&cfg);
|
||||
if (cfg.heartbeat_h > 0 &&
|
||||
(esp_timer_get_time() - last_hb_us) >= (int64_t)cfg.heartbeat_h * 3600LL * 1000000LL) {
|
||||
last_hb_us = esp_timer_get_time();
|
||||
if (deliver(CONFIG_BUZZ_NTFY_HB_TOPIC, "Door buzzer heartbeat", "min", "green_heart", "alive")) {
|
||||
s_stats.sent_ok++;
|
||||
} else {
|
||||
s_stats.sent_failed++;
|
||||
}
|
||||
if (xQueueReceive(s_q, &msg, portMAX_DELAY) == pdTRUE) {
|
||||
if (post_event(msg.delay_ms)) s_stats.sent_ok++;
|
||||
else s_stats.sent_failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool notifier_send(notif_kind_t kind, const char *msg)
|
||||
bool notifier_send(uint32_t delay_ms)
|
||||
{
|
||||
notif_msg_t m = { .kind = kind };
|
||||
snprintf(m.msg, sizeof(m.msg), "%s", msg);
|
||||
if (xQueueSend(s_q, &m, 0) != pdTRUE) {
|
||||
event_msg_t msg = { .delay_ms = delay_ms };
|
||||
if (xQueueSend(s_q, &msg, 0) != pdTRUE) {
|
||||
s_stats.dropped++;
|
||||
ESP_LOGW(TAG, "notification queue full, dropped");
|
||||
ESP_LOGW(TAG, "event queue full, dropped");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -161,17 +172,26 @@ bool notifier_send(notif_kind_t kind, const char *msg)
|
||||
void notifier_get_stats(notifier_stats_t *out)
|
||||
{
|
||||
*out = s_stats;
|
||||
out->wifi_configured = s_wifi_configured;
|
||||
out->wifi_configured = strlen(CONFIG_BUZZ_WIFI_SSID) > 0;
|
||||
out->endpoint_configured = strlen(CONFIG_BUZZ_EVENT_URL) > 0;
|
||||
}
|
||||
|
||||
esp_err_t notifier_init(void)
|
||||
{
|
||||
s_q = xQueueCreate(4, sizeof(notif_msg_t));
|
||||
s_q = xQueueCreate(4, sizeof(event_msg_t));
|
||||
s_eg = xEventGroupCreate();
|
||||
if (!s_q || !s_eg) return ESP_ERR_NO_MEM;
|
||||
|
||||
s_wifi_configured = strlen(CONFIG_BUZZ_WIFI_SSID) > 0;
|
||||
if (s_wifi_configured) {
|
||||
s_stats.endpoint_configured = strlen(CONFIG_BUZZ_EVENT_URL) > 0;
|
||||
if (!s_stats.endpoint_configured) {
|
||||
ESP_LOGW(TAG, "no event endpoint configured; buzz events will be dropped");
|
||||
}
|
||||
if (!strlen(CONFIG_BUZZ_EVENT_SECRET)) {
|
||||
ESP_LOGW(TAG, "event secret is empty; configure it before using the endpoint");
|
||||
}
|
||||
|
||||
s_stats.wifi_configured = strlen(CONFIG_BUZZ_WIFI_SSID) > 0;
|
||||
if (s_stats.wifi_configured) {
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
@@ -193,8 +213,9 @@ esp_err_t notifier_init(void)
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wc));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "no Wi-Fi SSID configured (menuconfig): notifications will be dropped");
|
||||
ESP_LOGW(TAG, "no Wi-Fi SSID configured; event requests cannot be sent");
|
||||
}
|
||||
|
||||
BaseType_t ok = xTaskCreatePinnedToCore(net_task, "net", NET_TASK_STACK, NULL, NET_TASK_PRIO, NULL, 0);
|
||||
return ok == pdPASS ? ESP_OK : ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
+3
-4
@@ -3,15 +3,14 @@
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef enum { NOTIF_ALERT = 0, NOTIF_TEST } notif_kind_t;
|
||||
|
||||
typedef struct {
|
||||
bool wifi_connected;
|
||||
char ip[16];
|
||||
uint32_t sent_ok, sent_failed, dropped;
|
||||
bool wifi_configured;
|
||||
bool endpoint_configured;
|
||||
} notifier_stats_t;
|
||||
|
||||
esp_err_t notifier_init(void); // Wi-Fi + network task
|
||||
bool notifier_send(notif_kind_t kind, const char *msg); // non-blocking enqueue, false if queue full
|
||||
esp_err_t notifier_init(void); // Wi-Fi + event POST task
|
||||
bool notifier_send(uint32_t delay_ms); // queue one duration event; non-blocking
|
||||
void notifier_get_stats(notifier_stats_t *out);
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ static void processing_task(void *arg)
|
||||
(unsigned long)buzz_duration_ms);
|
||||
ESP_LOGW(TAG, "BUZZER EVENT ended, detected duration %lu ms",
|
||||
(unsigned long)buzz_duration_ms);
|
||||
notifier_send(NOTIF_ALERT, message);
|
||||
notifier_send(buzz_duration_ms);
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&s_lock);
|
||||
|
||||
Reference in New Issue
Block a user