Slaves push BMA456 samples at 16ms when enabled; the master caches per client and exposes ACCEL_SNAPSHOT and ACCEL_STREAM over UART. goTool adds dashboard stream controls, HTTP accel-stream routes, and an external WebSocket API with per-connection receive/interval and slave stream commands. Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
3.1 KiB
C
84 lines
3.1 KiB
C
#ifndef CLIENT_REGISTRY_H
|
|
#define CLIENT_REGISTRY_H
|
|
|
|
#include "esp_err.h"
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#define CLIENT_REGISTRY_MAX 16
|
|
#define CLIENT_MAC_LEN 6
|
|
|
|
typedef struct {
|
|
uint32_t id;
|
|
bool available;
|
|
bool used;
|
|
uint8_t mac[CLIENT_MAC_LEN];
|
|
/** Milliseconds since boot when last packet was received from this client. */
|
|
uint32_t last_ping_at;
|
|
/** Milliseconds since boot when last heartbeat / SLAVE_INFO was accepted. */
|
|
uint32_t last_success_ping_at;
|
|
uint32_t version;
|
|
/** Accel deadzone in raw LSB per axis (master copy for ESP-NOW config). */
|
|
uint32_t accel_deadzone;
|
|
/** Latest accel from slave ESP-NOW stream (master only). */
|
|
bool accel_valid;
|
|
int16_t accel_x;
|
|
int16_t accel_y;
|
|
int16_t accel_z;
|
|
uint32_t accel_updated_at;
|
|
/** Host-enabled ESP-NOW accel stream to master. */
|
|
bool accel_stream_enabled;
|
|
} client_info_t;
|
|
|
|
#define CLIENT_REGISTRY_DEFAULT_ACCEL_DEADZONE 100u
|
|
|
|
void client_registry_init(void);
|
|
|
|
/** Milliseconds since boot (same clock as stored ping timestamps). */
|
|
uint32_t client_registry_now_ms(void);
|
|
|
|
/** Ms elapsed since timestamp; 0 if timestamp is 0. */
|
|
uint32_t client_registry_ms_since(uint32_t timestamp);
|
|
|
|
/** Register or refresh a client; updates both ping timestamps. */
|
|
esp_err_t client_registry_upsert(const uint8_t mac[CLIENT_MAC_LEN], uint32_t id,
|
|
uint32_t version, bool available, bool used,
|
|
bool *out_is_new);
|
|
|
|
/**
|
|
* Record a successful heartbeat (or initial slave info).
|
|
* Sets available=true and updates last_success_ping_at (and last_ping_at).
|
|
* If client was inactive, sets *out_reactivated=true.
|
|
*/
|
|
esp_err_t client_registry_heartbeat(const uint8_t mac[CLIENT_MAC_LEN],
|
|
uint32_t id, uint32_t version, bool used,
|
|
bool *out_is_new, bool *out_reactivated);
|
|
|
|
/** Mark clients inactive when last_success_ping_at is older than timeout_ms. */
|
|
void client_registry_check_timeouts(uint32_t timeout_ms);
|
|
|
|
size_t client_registry_count(void);
|
|
const client_info_t *client_registry_at(size_t index);
|
|
const client_info_t *client_registry_find_by_mac(const uint8_t mac[CLIENT_MAC_LEN]);
|
|
const client_info_t *client_registry_find_by_id(uint32_t id);
|
|
|
|
esp_err_t client_registry_set_accel_deadzone(uint32_t client_id,
|
|
uint32_t deadzone);
|
|
esp_err_t client_registry_get_accel_deadzone(uint32_t client_id,
|
|
uint32_t *deadzone_out);
|
|
|
|
/** Push deadzone to all active registry entries; returns count updated. */
|
|
size_t client_registry_set_accel_deadzone_all(uint32_t deadzone);
|
|
|
|
/** Store latest accel sample from a slave (matched by sender MAC). */
|
|
esp_err_t client_registry_update_accel(const uint8_t mac[CLIENT_MAC_LEN],
|
|
uint32_t slave_id, int16_t x, int16_t y,
|
|
int16_t z);
|
|
|
|
esp_err_t client_registry_set_accel_stream(uint32_t client_id, bool enabled);
|
|
esp_err_t client_registry_get_accel_stream(uint32_t client_id, bool *enabled_out);
|
|
size_t client_registry_set_accel_stream_all(bool enabled);
|
|
|
|
#endif
|