From 3b8005a28cac7ba764866d3fd64dd6419b482c75 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sat, 31 Jan 2026 07:48:02 -0800 Subject: [PATCH] Add ArtRDM TOD discovery for real ArtNet nodes Co-Authored-By: Claude Opus 4.5 --- artnet.go | 35 ++++++++++++++++++++++++++++++++++- go.mod | 2 +- go.sum | 4 ++-- types.go | 1 + 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/artnet.go b/artnet.go index 5dc53ca..ac11f95 100644 --- a/artnet.go +++ b/artnet.go @@ -28,6 +28,10 @@ func (h *artnetHandler) HandlePollReply(src *net.UDPAddr, pkt *artnet.PollReplyP h.discovery.HandlePollReply(src, pkt) } +func (h *artnetHandler) HandleTodData(src *net.UDPAddr, pkt *artnet.TodDataPacket) { + h.discovery.HandleTodData(src, pkt) +} + func (t *Tendrils) startArtNet(ctx context.Context, iface net.Interface) { srcIP, broadcast := getInterfaceIPv4(iface) if srcIP == nil || broadcast == nil { @@ -79,8 +83,19 @@ func (t *Tendrils) handleArtNetNode(node *artnet.Node) { outputs = append(outputs, int(u)) } + rdmUIDs := map[int][]string{} + for u, uids := range node.RDMUIDs { + var uidStrs []string + for _, uid := range uids { + uidStrs = append(uidStrs, uid.String()) + } + if len(uidStrs) > 0 { + rdmUIDs[int(u)] = uidStrs + } + } + if t.DebugArtNet { - log.Printf("[artnet] %s %s short=%q long=%q in=%v out=%v", ip, mac, shortName, longName, inputs, outputs) + log.Printf("[artnet] %s %s short=%q long=%q in=%v out=%v rdm=%v", ip, mac, shortName, longName, inputs, outputs, rdmUIDs) } name := longName @@ -100,6 +115,7 @@ func (t *Tendrils) handleArtNetNode(node *artnet.Node) { } if n != nil { t.nodes.UpdateArtNet(n, inputs, outputs) + t.nodes.UpdateArtNetRDM(n, rdmUIDs) } t.NotifyUpdate() } @@ -123,6 +139,23 @@ func (n *Nodes) UpdateArtNet(node *Node, inputs, outputs []int) { } } +func (n *Nodes) UpdateArtNetRDM(node *Node, rdmUIDs map[int][]string) { + n.mu.Lock() + defer n.mu.Unlock() + + if len(rdmUIDs) == 0 { + return + } + + if node.ArtNetRDMUIDs == nil { + node.ArtNetRDMUIDs = map[int][]string{} + } + + for u, uids := range rdmUIDs { + node.ArtNetRDMUIDs[u] = uids + } +} + func (n *Nodes) expireArtNet() { for _, node := range n.nodes { if node.ArtNetInputs != nil { diff --git a/go.mod b/go.mod index 6776692..5a8524e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.6 require ( github.com/fvbommel/sortorder v1.1.0 github.com/google/gopacket v1.1.19 - github.com/gopatchy/artnet v0.0.0-20260130164309-5e7400fe514e + github.com/gopatchy/artnet v0.0.0-20260131154723-a1431d527450 github.com/gopatchy/multicast v0.0.0-20260130233915-4278628690a3 github.com/gopatchy/sacn v0.0.0-20260130234631-9c2787a20064 github.com/gosnmp/gosnmp v1.43.2 diff --git a/go.sum b/go.sum index ea548ee..1c2ef60 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/gopatchy/artnet v0.0.0-20260130164309-5e7400fe514e h1:KaCtixVKARhtTzqlqWyzXurNACaesAGxjFgnFd3jYT4= -github.com/gopatchy/artnet v0.0.0-20260130164309-5e7400fe514e/go.mod h1:V/D32mh1xfK/llCKbrqI2jxw4xL4hf6Ge2yLiIrp9/4= +github.com/gopatchy/artnet v0.0.0-20260131154723-a1431d527450 h1:td8AQuJYeRey+trV9fLWShoriSrWkYFWYC5mruYWyCE= +github.com/gopatchy/artnet v0.0.0-20260131154723-a1431d527450/go.mod h1:V/D32mh1xfK/llCKbrqI2jxw4xL4hf6Ge2yLiIrp9/4= github.com/gopatchy/multicast v0.0.0-20260130233915-4278628690a3 h1:JVyjjl5wWP0NaC6b4QL7uvQ7I3G0a4bCDNFVtUoiYvU= github.com/gopatchy/multicast v0.0.0-20260130233915-4278628690a3/go.mod h1:mSeh6GX+fL6SWZYqxYHTdnddvzDx4qsGSBnlGwY5ZsA= github.com/gopatchy/sacn v0.0.0-20260130234631-9c2787a20064 h1:gyNOXY+87MjFlk1IU8QQTPhqvBaRTha4+8HjXwm4ZN4= diff --git a/types.go b/types.go index 7005d29..8a4cd54 100644 --- a/types.go +++ b/types.go @@ -455,6 +455,7 @@ type Node struct { MulticastGroups MulticastMembershipSet `json:"multicast_groups,omitempty"` ArtNetInputs ArtNetUniverseSet `json:"artnet_inputs,omitempty"` ArtNetOutputs ArtNetUniverseSet `json:"artnet_outputs,omitempty"` + ArtNetRDMUIDs map[int][]string `json:"artnet_rdm_uids,omitempty"` SACNUnicastInputs SACNUniverseSet `json:"sacn_unicast_inputs,omitempty"` SACNOutputs SACNUniverseSet `json:"sacn_outputs,omitempty"` ArtmapMappings []ArtmapMapping `json:"artmap_mappings,omitempty"`