Refactor node storage and use proper types for protocol data

- Rename TypeID to ID throughout
- Remove re-derivable data (MACTableSize, SACNInputs now derived)
- Use typed ArtNetUniverse and SACNUniverse with methods
- Store multicast groups with lastSeen tracking in structs
- Remove int indexes in Nodes, use direct node pointers
- Parse multicast groups into typed struct instead of strings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ian Gulliver
2026-01-28 22:36:44 -08:00
parent fc5b36cd1c
commit a912d73169
11 changed files with 552 additions and 412 deletions

View File

@@ -4,7 +4,6 @@ import (
"context"
"log"
"net"
"sort"
"time"
"github.com/gopatchy/sacn"
@@ -61,29 +60,33 @@ func (n *Nodes) UpdateSACN(node *Node, outputs []int) {
n.mu.Lock()
defer n.mu.Unlock()
node.SACNOutputs = outputs
sort.Ints(node.SACNOutputs)
node.sacnLastSeen = time.Now()
if node.SACNOutputs == nil {
node.SACNOutputs = SACNUniverseSet{}
}
for _, u := range outputs {
node.SACNOutputs.Add(SACNUniverse(u))
}
}
func (n *Nodes) expireSACN() {
expireTime := time.Now().Add(-60 * time.Second)
for _, node := range n.nodes {
if !node.sacnLastSeen.IsZero() && node.sacnLastSeen.Before(expireTime) {
node.SACNOutputs = nil
node.sacnLastSeen = time.Time{}
if node.SACNOutputs != nil {
node.SACNOutputs.Expire(60 * time.Second)
}
}
}
func (n *Nodes) mergeSACN(keep, merge *Node) {
for _, u := range merge.SACNOutputs {
if !containsInt(keep.SACNOutputs, u) {
keep.SACNOutputs = append(keep.SACNOutputs, u)
if merge.SACNOutputs == nil {
return
}
if keep.SACNOutputs == nil {
keep.SACNOutputs = SACNUniverseSet{}
}
for u, lastSeen := range merge.SACNOutputs {
if existing, ok := keep.SACNOutputs[u]; !ok || lastSeen.After(existing) {
keep.SACNOutputs[u] = lastSeen
}
}
if merge.sacnLastSeen.After(keep.sacnLastSeen) {
keep.sacnLastSeen = merge.sacnLastSeen
}
sort.Ints(keep.SACNOutputs)
}