Added Radio.ID and refactored the Stats interface
Some checks failed
Run tests / test (1.25) (push) Failing after 1m0s
Run tests / test (stable) (push) Failing after 1m0s

This commit is contained in:
2026-03-17 08:33:06 +01:00
parent 8ec85821e4
commit 27e2da1943
15 changed files with 2045 additions and 22 deletions

View File

@@ -3,6 +3,7 @@ package meshcore
import (
"bufio"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"math"
@@ -23,7 +24,7 @@ type repeaterDriver struct {
lastFrame []byte
lastFrameAt time.Time
info repeaterInfo
stats map[string]any
stats chan map[string]any
err error
}
@@ -78,7 +79,7 @@ type repeaterInfo struct {
Type NodeType
Power byte // in dBm
MaxPower byte // in dBm
PublicKey [32]byte
PublicKey string
Latitude float64
Longitude float64
HasMultiACKs bool
@@ -98,15 +99,20 @@ type repeaterInfo struct {
Manufacturer string
}
func newRepeaterDriver(conn io.ReadWriteCloser, hasSNR bool) *repeaterDriver {
func newRepeaterDriver(conn io.ReadWriteCloser) *repeaterDriver {
return &repeaterDriver{
conn: conn,
waiting: make(chan *repeaterDriverWaiting, 16),
hasSNR: hasSNR,
stats: make(map[string]any),
stats: make(chan map[string]any, 2),
}
}
func newRepeaterDriverWithSNRPatch(conn io.ReadWriteCloser) *repeaterDriver {
driver := newRepeaterDriver(conn)
driver.hasSNR = true
return driver
}
func (drv *repeaterDriver) Close() error {
return drv.conn.Close()
}
@@ -150,6 +156,7 @@ func (drv *repeaterDriver) Info() *radio.Info {
}
return &radio.Info{
ID: drv.info.PublicKey,
Name: drv.info.Name,
Manufacturer: manufacturer,
Device: device,
@@ -179,7 +186,7 @@ func (drv *repeaterDriver) RawPackets() <-chan *protocol.Packet {
return drv.rawPackets
}
func (drv *repeaterDriver) Stats() map[string]any {
func (drv *repeaterDriver) Stats() <-chan map[string]any {
return drv.stats
}
@@ -193,6 +200,11 @@ func (drv *repeaterDriver) queryDeviceInfo() (err error) {
return
}
// Fetch public key
if drv.info.PublicKey, err = drv.writeCommand("get", "public.key"); err != nil {
return
}
var line string
// Fetch frequency, bandwidth and LoRa settings
@@ -412,24 +424,26 @@ func (drv *repeaterDriver) poll() {
}
func (drv *repeaterDriver) pollStats() {
ticker := time.NewTicker(time.Minute)
ticker := time.NewTicker(time.Second * 10)
defer ticker.Stop()
for {
stats := make(map[string]any)
neighbors, err := drv.getNeighbors()
if err != nil {
Logger.Warnf("meshcore: failed to get neighbors: %v", err)
} else {
drv.stats["neighbors"] = neighbors
stats["neighbors"] = neighbors
}
response, err := drv.writeCommand("stats")
response, err := drv.writeCommand("stats-core")
if err != nil {
Logger.Warnf("meshcore: failed to get stats: %v", err)
return
}
stats := make(map[string]any)
neighborStats := make(map[string]any)
for _, line := range strings.Split(response, "\n") {
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
@@ -439,15 +453,53 @@ func (drv *repeaterDriver) pollStats() {
value := parts[1]
if i, err := strconv.Atoi(value); err == nil {
stats[key] = i
neighborStats[key] = i
} else if f, err := strconv.ParseFloat(value, 64); err == nil {
stats[key] = f
neighborStats[key] = f
} else {
stats[key] = value
neighborStats[key] = value
}
}
drv.stats = stats
var (
coreStats = make(map[string]any)
radioStats = make(map[string]any)
packetStats = make(map[string]any)
)
if response, err := drv.writeCommand("stats-core"); err == nil {
if err = json.Unmarshal([]byte(response), &coreStats); err != nil {
Logger.Warnf("meshcore: failed to decode core stats: %v", err)
}
} else {
Logger.Warnf("meshcore: failed to get core stats: %v", err)
}
if response, err := drv.writeCommand("stats-radio"); err == nil {
if err = json.Unmarshal([]byte(response), &radioStats); err != nil {
Logger.Warnf("meshcore: failed to decode radio stats: %v", err)
}
} else {
Logger.Warnf("meshcore: failed to get radio stats: %v", err)
}
if response, err := drv.writeCommand("stats-packets"); err == nil {
if err = json.Unmarshal([]byte(response), &packetStats); err != nil {
Logger.Warnf("meshcore: failed to decode packet stats: %v", err)
}
} else {
Logger.Warnf("meshcore: failed to get packet stats: %v", err)
}
stats["neighbors"] = neighborStats
stats["core"] = coreStats
stats["radio"] = radioStats
stats["packets"] = packetStats
select {
case drv.stats <- stats:
default:
Logger.Warn("meshcore: stats channel full, dropping stats")
}
<-ticker.C
}