powerpods/goTool/api_battery.go
simon 3cb0b5bbe9 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>
2026-05-29 20:14:28 +02:00

61 lines
1.6 KiB
Go

package main
import (
"encoding/json"
"net/http"
"strconv"
)
func mountBatteryAPI(mux *http.ServeMux, link *managedSerial) {
mux.HandleFunc("/api/battery", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
serveBatteryGet(w, r, link)
case http.MethodPost:
serveBatteryPost(w, r, link)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
})
}
func serveBatteryGet(w http.ResponseWriter, r *http.Request, link *managedSerial) {
req := batteryAPIRequest{}
if v := r.URL.Query().Get("all_clients"); v == "1" || v == "true" {
req.AllClients = true
}
if s := r.URL.Query().Get("client_id"); s != "" {
id, err := strconv.ParseUint(s, 10, 32)
if err != nil {
writeJSON(w, http.StatusBadRequest, batteryAPIResponse{Error: "invalid client_id"})
return
}
req.ClientID = uint32(id)
} else if !req.AllClients {
req.AllClients = true
}
out := applyBatteryStatus(link, req)
status := http.StatusOK
if out.Error != "" || !out.Success {
status = http.StatusServiceUnavailable
}
writeJSON(w, status, out)
}
func serveBatteryPost(w http.ResponseWriter, r *http.Request, link *managedSerial) {
var body batteryAPIRequest
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
writeJSON(w, http.StatusBadRequest, batteryAPIResponse{Error: "invalid JSON"})
return
}
if !body.AllClients && body.ClientID == 0 {
body.AllClients = true
}
out := applyBatteryStatus(link, body)
status := http.StatusOK
if out.Error != "" || !out.Success {
status = http.StatusServiceUnavailable
}
writeJSON(w, status, out)
}