Assign sequential pod IDs from the master with NVS-stable bindings.

Replaces MAC-byte self-IDs with master allocation (1–255), slave preferred-ID reconnect, debug reset via UART/UI, and rate-limited ASSIGN to avoid ESP-NOW NO_MEM storms.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-01 17:25:07 +01:00
co-authored by Cursor
parent af20635047
commit 567dab6d0a
26 changed files with 1261 additions and 163 deletions
+4 -7
View File
@@ -84,13 +84,7 @@ func NewBench(cfg Config) (*Bench, error) {
return nil, fmt.Errorf("config %q slave %q: %w", cfg.ID, s.ID, err)
}
s.MAC = mac
if s.ClientID == nil {
parts := strings.Split(mac, ":")
var last byte
fmt.Sscanf(parts[5], "%02x", &last)
id := uint(last)
s.ClientID = &id
}
/* client_id is master-assigned (sequential); omit until known from `gotool clients`. */
b.slaveByID[s.ID] = s
}
return b, nil
@@ -112,6 +106,9 @@ func (b *Bench) ResolveClientID(slaveID string) (uint32, error) {
if err != nil {
return 0, err
}
if s.ClientID == nil {
return 0, fmt.Errorf("slave %q: client_id required (master-assigned; set in config after join)", slaveID)
}
return uint32(*s.ClientID), nil
}
+34 -3
View File
@@ -2,7 +2,7 @@ package autotest
import "testing"
func TestNewBenchClientIDFromMAC(t *testing.T) {
func TestNewBenchNoDefaultClientIDFromMAC(t *testing.T) {
cfg := Config{
ID: "t",
Network: 1,
@@ -20,8 +20,39 @@ func TestNewBenchClientIDFromMAC(t *testing.T) {
t.Fatal(err)
}
s, _ := b.Slave("pod")
if *s.ClientID != 16 {
t.Fatalf("client_id=%d want 16", *s.ClientID)
if s.ClientID != nil {
t.Fatalf("client_id should be unset, got %d", *s.ClientID)
}
if _, err := b.ResolveClientID("pod"); err == nil {
t.Fatal("ResolveClientID should fail without client_id")
}
}
func TestNewBenchExplicitClientID(t *testing.T) {
id := uint(3)
cfg := Config{
ID: "t",
Network: 1,
MasterMAC: "aa:bb:cc:dd:ee:ff",
UART: UARTConfig{
Master: "/dev/ttyUSB0",
},
Slaves: []SlaveNode{{
ID: "pod",
MAC: "50:78:7d:18:01:10",
ClientID: &id,
}},
}
b, err := NewBench(cfg)
if err != nil {
t.Fatal(err)
}
got, err := b.ResolveClientID("pod")
if err != nil {
t.Fatal(err)
}
if got != 3 {
t.Fatalf("client_id=%d want 3", got)
}
}
+1 -1
View File
@@ -195,7 +195,7 @@ func checkClients(bench *Bench, step Step, client MasterClient) error {
if found == nil {
return fmt.Errorf("slave %q mac %s not in client list", name, want.MAC)
}
if uint32(*want.ClientID) != found.GetId() {
if want.ClientID != nil && uint32(*want.ClientID) != found.GetId() {
return fmt.Errorf("slave %q id=%d want client_id=%d", name, found.GetId(), *want.ClientID)
}
if e.Available != nil && found.GetAvailable() != *e.Available {