Add software LiPo UV protection with energy-save boot.
Detect under-voltage on GPIO1/11, persist UV state in NVS, enter a minimal power mode without ESP-NOW, and recover after charge; expose LED mode 6 battery-low for host testing via goTool. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -33,7 +33,7 @@ go run . -port /dev/ttyUSB0 clients
|
||||
| `serve` | — | Web dashboard at `http://localhost:8080` (WebSocket live updates) |
|
||||
| `ota` | 16–19 | UART firmware upload to master; firmware then pushes to slaves via ESP-NOW |
|
||||
| `ota-progress` | 21 | Query per-slave ESP-NOW OTA progress on the master (`-client N`, default all) |
|
||||
| `led-ring` | 8 | LED ring: `-mode clear\|color\|progress\|digit\|blink\|find-me`, `-client`, `-all` |
|
||||
| `led-ring` | 8 | LED ring: `-mode clear\|color\|progress\|digit\|blink\|find-me\|battery-low`, `-client`, `-all` |
|
||||
| `find-me` | 22 | Locate pod (`-client 0` master, `>0` slave via ESP-NOW) |
|
||||
| `restart` | 23 | Reboot master or slave (`-client 0` / `>0`) |
|
||||
| `log-level` | `0x1f` | Get/set master ESP-IDF log level for tag `"*"` (`-set`, `-level` 0–5); output on UART0 debug, not host UART |
|
||||
|
||||
@@ -347,6 +347,8 @@ func ledRingModeValue(mode string) (uint32, error) {
|
||||
return 3, nil
|
||||
case "find_me", "findme":
|
||||
return 4, nil
|
||||
case "battery_low", "batterylow":
|
||||
return 6, nil
|
||||
case "color", "solid", "fill":
|
||||
return 5, nil
|
||||
default:
|
||||
|
||||
@@ -12,6 +12,7 @@ func TestLedRingModeValue(t *testing.T) {
|
||||
{"digit", 2},
|
||||
{"blink", 3},
|
||||
{"find-me", 4},
|
||||
{"battery-low", 6},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
got, err := ledRingModeValue(tc.mode)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
func runLedRing(sp *serialPort, args []string) error {
|
||||
fs := flag.NewFlagSet("led-ring", flag.ExitOnError)
|
||||
mode := fs.String("mode", "progress", "clear, color, progress, digit, blink, or find-me")
|
||||
mode := fs.String("mode", "progress", "clear, color, progress, digit, blink, find-me, or battery-low")
|
||||
clientID := fs.Uint("client", 0, "0=master ring, >0=slave via ESP-NOW")
|
||||
allClients := fs.Bool("all", false, "broadcast to all slaves")
|
||||
slavesOnly := fs.Bool("slaves-only", false, "with -all: do not change master ring")
|
||||
|
||||
@@ -96,6 +96,7 @@ Body:
|
||||
| `digit` | `digit` 0–10 |
|
||||
| `blink` | `blink_ms`, `blink_count` |
|
||||
| `find-me` | Locate pod |
|
||||
| `battery-low` | First 4 LEDs red at ~10 % for 5 s (UV indicator test) |
|
||||
|
||||
Use `client_id` (`0` = master) or `all_clients` (+ optional `slaves_only`) for broadcast.
|
||||
|
||||
|
||||
@@ -214,11 +214,12 @@ Response `tap_notify_status`:
|
||||
| `digit` | `digit` 0–10 |
|
||||
| `blink` | `blink_ms`, `blink_count` |
|
||||
| `find-me` | Locate pod |
|
||||
| `battery-low` | UV indicator (4 LEDs, 5 s) |
|
||||
|
||||
|
||||
Target: `client_id` (`0` = master) or `all_clients` (+ optional `slaves_only`).
|
||||
|
||||
Response `led_ring_status` — `mode` is numeric: 0=clear, 1=progress, 2=digit, 3=blink, 4=find-me, 5=color.
|
||||
Response `led_ring_status` — `mode` is numeric: 0=clear, 1=progress, 2=digit, 3=blink, 4=find-me, 5=color, 6=battery-low.
|
||||
|
||||
```json
|
||||
{"type":"led_ring_status","success":true,"mode":5,"client_id":16,"slaves_updated":1}
|
||||
|
||||
@@ -14,6 +14,7 @@ const (
|
||||
ledRingModeBlink = 3
|
||||
ledRingModeFindMe = 4
|
||||
ledRingModeColor = 5
|
||||
ledRingModeBatteryLow = 6
|
||||
)
|
||||
|
||||
type ledRingAPIRequest struct {
|
||||
@@ -56,8 +57,10 @@ func ledRingModeFromString(s string) (uint32, error) {
|
||||
return ledRingModeBlink, nil
|
||||
case "find-me", "find_me", "findme":
|
||||
return ledRingModeFindMe, nil
|
||||
case "battery-low", "battery_low", "batterylow":
|
||||
return ledRingModeBatteryLow, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown mode %q (clear, color, progress, digit, blink, find-me)", s)
|
||||
return 0, fmt.Errorf("unknown mode %q (clear, color, progress, digit, blink, find-me, battery-low)", s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2526,7 +2526,7 @@ func (x *EspNowEchoPingResponse) GetEspRttUs() uint32 {
|
||||
}
|
||||
|
||||
// Host → master: LED ring on master (client_id=0) and/or slaves via ESP-NOW.
|
||||
// mode: 0=clear, 1=progress (0–100 %), 2=digit (0–10), 3=blink, 4=find-me, 5=all LEDs solid color.
|
||||
// mode: 0=clear, 1=progress (0–100 %), 2=digit (0–10), 3=blink, 4=find-me, 5=all LEDs solid color, 6=battery-low.
|
||||
type LedRingProgressRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Mode uint32 `protobuf:"varint,1,opt,name=mode,proto3" json:"mode,omitempty"`
|
||||
|
||||
Vendored
+1
-1
@@ -44,7 +44,7 @@ Ordered steps: UART commands, delays, or esptool reset.
|
||||
**unicast_test** — `input`: `slave` or `client_id`, `seq`
|
||||
`expect`: `success`, `seq`
|
||||
|
||||
**led_ring** — `input`: `mode` (`clear`, `progress`, `digit`, `blink`, `find_me`), `progress`, `digit`, `r`/`g`/`b`, `intensity`, `blink_ms`, `blink_count`
|
||||
**led_ring** — `input`: `mode` (`clear`, `progress`, `digit`, `blink`, `find_me`, `battery_low`), `progress`, `digit`, `r`/`g`/`b`, `intensity`, `blink_ms`, `blink_count`
|
||||
`expect`: `success`, `mode`, `progress`, `digit`
|
||||
|
||||
**find_me** — `input`: `client` / `client_id` or `slave` (`0` = master ring)
|
||||
|
||||
@@ -471,7 +471,7 @@
|
||||
<div class="card-body">
|
||||
<p class="text-muted small mb-3">
|
||||
Modi: <code>clear</code>, <code>color</code> (ganzer Ring), <code>progress</code> (0–100 %),
|
||||
<code>digit</code> (0–10), <code>blink</code>, <code>find-me</code>.
|
||||
<code>digit</code> (0–10), <code>blink</code>, <code>find-me</code>, <code>battery-low</code>.
|
||||
Ziel: Master (<code>client_id=0</code>), ein Slave oder alle Slaves (Broadcast).
|
||||
</p>
|
||||
<div class="row g-3 align-items-end">
|
||||
@@ -484,6 +484,7 @@
|
||||
<option value="digit">Ziffer/Symbol</option>
|
||||
<option value="blink">Blink</option>
|
||||
<option value="find-me">Find me</option>
|
||||
<option value="battery-low">Battery low</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
|
||||
Reference in New Issue
Block a user