add yamaha speaker discovery via tcp:50000 and move pollNode to tendrils.go

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ian Gulliver
2026-01-23 22:21:35 -08:00
parent a374b34b18
commit 528f58dca1
4 changed files with 80 additions and 32 deletions

View File

@@ -17,6 +17,7 @@ func main() {
noDante := flag.Bool("no-dante", false, "disable Dante discovery") noDante := flag.Bool("no-dante", false, "disable Dante discovery")
noBMD := flag.Bool("no-bmd", false, "disable Blackmagic discovery") noBMD := flag.Bool("no-bmd", false, "disable Blackmagic discovery")
noShure := flag.Bool("no-shure", false, "disable Shure discovery") noShure := flag.Bool("no-shure", false, "disable Shure discovery")
noYamaha := flag.Bool("no-yamaha", false, "disable Yamaha discovery")
logEvents := flag.Bool("log-events", false, "log node events") logEvents := flag.Bool("log-events", false, "log node events")
logNodes := flag.Bool("log-nodes", false, "log full node details on changes") logNodes := flag.Bool("log-nodes", false, "log full node details on changes")
debugARP := flag.Bool("debug-arp", false, "debug ARP discovery") debugARP := flag.Bool("debug-arp", false, "debug ARP discovery")
@@ -28,6 +29,7 @@ func main() {
debugDante := flag.Bool("debug-dante", false, "debug Dante discovery") debugDante := flag.Bool("debug-dante", false, "debug Dante discovery")
debugBMD := flag.Bool("debug-bmd", false, "debug Blackmagic discovery") debugBMD := flag.Bool("debug-bmd", false, "debug Blackmagic discovery")
debugShure := flag.Bool("debug-shure", false, "debug Shure discovery") debugShure := flag.Bool("debug-shure", false, "debug Shure discovery")
debugYamaha := flag.Bool("debug-yamaha", false, "debug Yamaha discovery")
flag.Parse() flag.Parse()
t := tendrils.New() t := tendrils.New()
@@ -41,6 +43,7 @@ func main() {
t.DisableDante = *noDante t.DisableDante = *noDante
t.DisableBMD = *noBMD t.DisableBMD = *noBMD
t.DisableShure = *noShure t.DisableShure = *noShure
t.DisableYamaha = *noYamaha
t.LogEvents = *logEvents t.LogEvents = *logEvents
t.LogNodes = *logNodes t.LogNodes = *logNodes
t.DebugARP = *debugARP t.DebugARP = *debugARP
@@ -52,5 +55,6 @@ func main() {
t.DebugDante = *debugDante t.DebugDante = *debugDante
t.DebugBMD = *debugBMD t.DebugBMD = *debugBMD
t.DebugShure = *debugShure t.DebugShure = *debugShure
t.DebugYamaha = *debugYamaha
t.Run() t.Run()
} }

32
snmp.go
View File

@@ -79,38 +79,6 @@ func (t *Tendrils) connectSNMP(ip net.IP) (*gosnmp.GoSNMP, error) {
return snmp, nil return snmp, nil
} }
func (t *Tendrils) pollNode(node *Node) {
t.nodes.mu.RLock()
var ips []net.IP
for _, iface := range node.Interfaces {
for _, ip := range iface.IPs {
if ip.To4() != nil {
ips = append(ips, ip)
}
}
}
nodeName := node.DisplayName()
t.nodes.mu.RUnlock()
if !t.DisableSNMP {
for _, ip := range ips {
t.querySNMPDevice(node, ip)
}
}
if !t.DisableBMD && nodeName == "" {
for _, ip := range ips {
t.probeBMDDevice(ip)
}
}
if !t.DisableDante {
for _, ip := range ips {
t.probeDanteDevice(ip)
}
}
}
func (t *Tendrils) querySNMPDevice(node *Node, ip net.IP) { func (t *Tendrils) querySNMPDevice(node *Node, ip net.IP) {
snmp, err := t.connectSNMP(ip) snmp, err := t.connectSNMP(ip)
if err != nil { if err != nil {

View File

@@ -26,6 +26,7 @@ type Tendrils struct {
DisableDante bool DisableDante bool
DisableBMD bool DisableBMD bool
DisableShure bool DisableShure bool
DisableYamaha bool
LogEvents bool LogEvents bool
LogNodes bool LogNodes bool
DebugARP bool DebugARP bool
@@ -37,6 +38,7 @@ type Tendrils struct {
DebugDante bool DebugDante bool
DebugBMD bool DebugBMD bool
DebugShure bool DebugShure bool
DebugYamaha bool
} }
func New() *Tendrils { func New() *Tendrils {
@@ -213,3 +215,41 @@ func (t *Tendrils) startInterface(ctx context.Context, iface net.Interface) {
go t.listenShure(ctx, iface) go t.listenShure(ctx, iface)
} }
} }
func (t *Tendrils) pollNode(node *Node) {
t.nodes.mu.RLock()
var ips []net.IP
for _, iface := range node.Interfaces {
for _, ip := range iface.IPs {
if ip.To4() != nil {
ips = append(ips, ip)
}
}
}
nodeName := node.DisplayName()
t.nodes.mu.RUnlock()
if !t.DisableSNMP {
for _, ip := range ips {
t.querySNMPDevice(node, ip)
}
}
if !t.DisableBMD && nodeName == "" {
for _, ip := range ips {
t.probeBMDDevice(ip)
}
}
if !t.DisableYamaha && nodeName == "" {
for _, ip := range ips {
t.probeYamahaDevice(ip)
}
}
if !t.DisableDante {
for _, ip := range ips {
t.probeDanteDevice(ip)
}
}
}

36
yamaha.go Normal file
View File

@@ -0,0 +1,36 @@
package tendrils
import (
"bufio"
"log"
"net"
"regexp"
"time"
)
var yamahaModelRegex = regexp.MustCompile(`PA-Platform:ModelId\s*=\s*0x[0-9a-fA-F]+\(([^)]+)\)`)
func (t *Tendrils) probeYamahaDevice(ip net.IP) string {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(ip.String(), "50000"), 2*time.Second)
if err != nil {
return ""
}
defer conn.Close()
conn.SetReadDeadline(time.Now().Add(2 * time.Second))
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
line := scanner.Text()
if match := yamahaModelRegex.FindStringSubmatch(line); match != nil {
model := match[1]
if t.DebugYamaha {
log.Printf("[yamaha] %s: found model %s", ip, model)
}
t.nodes.Update(nil, nil, []net.IP{ip}, "", model, "yamaha")
return model
}
}
return ""
}