#ifndef CLIENT_REGISTRY_H #define CLIENT_REGISTRY_H #include "esp_err.h" #include #include #include #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; } client_info_t; 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]); #endif