- State machine: 7-state lifecycle (BOOT→WIFI→DISCOVERY→CONNECTED, degraded modes WIFI_LOST/MOTHERSHIP_UNAVAILABLE/CAPTIVE_PORTAL) - WiFi: STA connection with exponential backoff, mDNS discovery with cached IP fallback, captive portal AP for provisioning - WebSocket: bidirectional comms, binary CSI frames (24B header + I/Q), JSON hello/health/ble/ota_status upstream, role/config/ota/reboot downstream, OTA task with progress reporting - CSI: promiscuous mode capture, queue-based processing, passive BSSID filter, on-device variance tracking (Welford's) for motion hints - BLE: passive scanning on Core 0, 60-device cache, 5s reporting - NVS: 15-key schema with versioning, role/rate persistence Complete: ESP32 firmware skeleton, passive radar, BLE scanning Remaining: Dashboard skeleton, Docker packaging (Phase 1 items 5-6) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
104 lines
2.6 KiB
C
104 lines
2.6 KiB
C
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "esp_err.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/event_groups.h"
|
|
|
|
// System configuration
|
|
#define SPAXEL_NAMESPACE "spaxel"
|
|
#define SPAXEL_MDNS_SERVICE "_spaxel"
|
|
#define SPAXEL_MDNS_PROTO "_tcp"
|
|
#define SPAXEL_MDNS_PORT 8080
|
|
#define SPAXEL_WS_PATH "/ws/node"
|
|
|
|
// WebSocket configuration
|
|
#define SPAXEL_WS_RECONNECT_MS 5000
|
|
#define SPAXEL_WS_TIMEOUT_MS 30000
|
|
#define SPAXEL_PING_INTERVAL_SEC 30
|
|
|
|
// Health reporting interval
|
|
#define SPAXEL_HEALTH_INTERVAL_MS 10000
|
|
#define SPAXEL_BLE_INTERVAL_MS 5000
|
|
|
|
// CSI configuration
|
|
#define SPAXEL_CSI_MAX_SUBCARRIERS 64
|
|
#define SPAXEL_CSI_QUEUE_SIZE 32
|
|
|
|
// Binary frame header size
|
|
#define SPAXEL_FRAME_HEADER_SIZE 24
|
|
|
|
// Node states
|
|
typedef enum {
|
|
NODE_STATE_BOOT,
|
|
NODE_STATE_WIFI_CONNECTING,
|
|
NODE_STATE_MOTHERSHIP_DISCOVERY,
|
|
NODE_STATE_CONNECTED,
|
|
NODE_STATE_WIFI_LOST,
|
|
NODE_STATE_MOTHERSHIP_UNAVAILABLE,
|
|
NODE_STATE_CAPTIVE_PORTAL,
|
|
} node_state_t;
|
|
|
|
// Node roles
|
|
typedef enum {
|
|
NODE_ROLE_TX = 0,
|
|
NODE_ROLE_RX = 1,
|
|
NODE_ROLE_TX_RX = 2,
|
|
NODE_ROLE_PASSIVE = 3,
|
|
NODE_ROLE_IDLE = 4,
|
|
} node_role_t;
|
|
|
|
// NVS keys (max 15 chars)
|
|
#define NVS_KEY_SCHEMA_VER "schema_ver"
|
|
#define NVS_KEY_PROVISIONED "provisioned"
|
|
#define NVS_KEY_WIFI_SSID "wifi_ssid"
|
|
#define NVS_KEY_WIFI_PASS "wifi_pass"
|
|
#define NVS_KEY_NODE_ID "node_id"
|
|
#define NVS_KEY_NODE_TOKEN "node_token"
|
|
#define NVS_KEY_MS_MDNS "ms_mdns"
|
|
#define NVS_KEY_MS_IP "ms_ip"
|
|
#define NVS_KEY_MS_PORT "ms_port"
|
|
#define NVS_KEY_PASSIVE_BSS "passive_bss"
|
|
#define NVS_KEY_ROLE "role"
|
|
#define NVS_KEY_PKT_RATE "pkt_rate"
|
|
#define NVS_KEY_AP_MODE "ap_mode"
|
|
#define NVS_KEY_DEBUG "debug"
|
|
|
|
// Current NVS schema version
|
|
#define NVS_SCHEMA_VERSION 1
|
|
|
|
// Global state
|
|
typedef struct {
|
|
node_state_t state;
|
|
node_role_t role;
|
|
uint8_t packet_rate;
|
|
uint8_t passive_bssid[6];
|
|
char node_id[38];
|
|
char node_token[65];
|
|
char ms_mdns[65];
|
|
char ms_ip[47];
|
|
uint16_t ms_port;
|
|
bool provisioned;
|
|
bool debug;
|
|
uint8_t mac[6];
|
|
EventGroupHandle_t events;
|
|
} spaxel_state_t;
|
|
|
|
// Event bits
|
|
#define SPAXEL_EVENT_WIFI_CONNECTED BIT0
|
|
#define SPAXEL_EVENT_WIFI_FAILED BIT1
|
|
#define SPAXEL_EVENT_WS_CONNECTED BIT2
|
|
#define SPAXEL_EVENT_WS_DISCONNECTED BIT3
|
|
#define SPAXEL_EVENT_ROLE_CHANGED BIT4
|
|
#define SPAXEL_EVENT_OTA_TRIGGER BIT5
|
|
#define SPAXEL_EVENT_REBOOT BIT6
|
|
|
|
// Global state instance
|
|
extern spaxel_state_t g_state;
|
|
|
|
// Utility functions
|
|
const char* node_state_str(node_state_t state);
|
|
const char* node_role_str(node_role_t role);
|
|
void mac_to_str(uint8_t *mac, char *buf, size_t len);
|
|
void str_to_mac(const char *str, uint8_t *mac);
|