Add LiPo battery monitoring with ESP-NOW cache and dashboard API.
Slaves report pack voltages every 30s; the master caches them for fast BATTERY_STATUS reads. goTool exposes REST/WebSocket and shows values in the dashboard, with a nanopb fix so optional lipo submessages encode. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,6 +14,11 @@ typedef struct {
|
||||
|
||||
static client_slot_t s_clients[CLIENT_REGISTRY_MAX];
|
||||
|
||||
static struct {
|
||||
board_lipo_reading_t reading;
|
||||
uint32_t updated_at;
|
||||
} s_master_battery;
|
||||
|
||||
uint32_t client_registry_now_ms(void) {
|
||||
return (uint32_t)(xTaskGetTickCount() * portTICK_PERIOD_MS);
|
||||
}
|
||||
@@ -320,6 +325,64 @@ esp_err_t client_registry_update_accel(const uint8_t mac[CLIENT_MAC_LEN],
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void client_registry_set_master_battery(const board_lipo_reading_t *reading) {
|
||||
if (reading == NULL) {
|
||||
return;
|
||||
}
|
||||
s_master_battery.reading = *reading;
|
||||
s_master_battery.updated_at = now_ms();
|
||||
}
|
||||
|
||||
bool client_registry_get_master_battery(board_lipo_reading_t *reading_out,
|
||||
uint32_t *age_ms_out) {
|
||||
if (reading_out == NULL) {
|
||||
return false;
|
||||
}
|
||||
*reading_out = s_master_battery.reading;
|
||||
if (age_ms_out != NULL) {
|
||||
*age_ms_out = client_registry_ms_since(s_master_battery.updated_at);
|
||||
}
|
||||
return s_master_battery.updated_at != 0;
|
||||
}
|
||||
|
||||
esp_err_t client_registry_update_battery(const uint8_t mac[CLIENT_MAC_LEN],
|
||||
uint32_t slave_id, bool lipo1_valid,
|
||||
uint32_t lipo1_mv, bool lipo2_valid,
|
||||
uint32_t lipo2_mv) {
|
||||
if (mac == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
client_slot_t *slot = find_slot(mac);
|
||||
if (slot == NULL) {
|
||||
bool is_new = false;
|
||||
esp_err_t err = client_registry_upsert(mac, slave_id, 0, true, false, &is_new);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
slot = find_slot(mac);
|
||||
if (slot == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
ESP_LOGI(TAG, "battery auto-registered id=%lu (report before heartbeat)",
|
||||
(unsigned long)slave_id);
|
||||
}
|
||||
|
||||
if (slot->info.id != slave_id) {
|
||||
ESP_LOGW(TAG, "battery id %lu → %lu for mac %02x:…:%02x",
|
||||
(unsigned long)slot->info.id, (unsigned long)slave_id, mac[0],
|
||||
mac[5]);
|
||||
slot->info.id = slave_id;
|
||||
}
|
||||
|
||||
slot->info.lipo1_valid = lipo1_valid;
|
||||
slot->info.lipo2_valid = lipo2_valid;
|
||||
slot->info.lipo1_mv = lipo1_mv;
|
||||
slot->info.lipo2_mv = lipo2_mv;
|
||||
slot->info.battery_updated_at = now_ms();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const client_info_t *client_registry_at(size_t index) {
|
||||
size_t n = 0;
|
||||
for (size_t i = 0; i < CLIENT_REGISTRY_MAX; i++) {
|
||||
|
||||
Reference in New Issue
Block a user