Remove ArtRDM TOD discovery support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
36
discovery.go
36
discovery.go
@@ -14,7 +14,6 @@ type Node struct {
|
|||||||
LongName string
|
LongName string
|
||||||
Inputs []Universe
|
Inputs []Universe
|
||||||
Outputs []Universe
|
Outputs []Universe
|
||||||
RDMUIDs map[Universe][]RDMUID
|
|
||||||
LastSeen time.Time
|
LastSeen time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +130,6 @@ func (d *Discovery) HandlePollReply(src *net.UDPAddr, pkt *PollReplyPacket) {
|
|||||||
node = &Node{
|
node = &Node{
|
||||||
IP: src.IP,
|
IP: src.IP,
|
||||||
Port: pkt.Port,
|
Port: pkt.Port,
|
||||||
RDMUIDs: map[Universe][]RDMUID{},
|
|
||||||
}
|
}
|
||||||
d.nodes[ip] = node
|
d.nodes[ip] = node
|
||||||
}
|
}
|
||||||
@@ -141,7 +139,6 @@ func (d *Discovery) HandlePollReply(src *net.UDPAddr, pkt *PollReplyPacket) {
|
|||||||
node.MAC = pkt.MACAddr()
|
node.MAC = pkt.MACAddr()
|
||||||
node.LastSeen = time.Now()
|
node.LastSeen = time.Now()
|
||||||
|
|
||||||
var newOutputs []Universe
|
|
||||||
for _, u := range pkt.InputUniverses() {
|
for _, u := range pkt.InputUniverses() {
|
||||||
if !containsUniverse(node.Inputs, u) {
|
if !containsUniverse(node.Inputs, u) {
|
||||||
node.Inputs = append(node.Inputs, u)
|
node.Inputs = append(node.Inputs, u)
|
||||||
@@ -150,45 +147,12 @@ func (d *Discovery) HandlePollReply(src *net.UDPAddr, pkt *PollReplyPacket) {
|
|||||||
for _, u := range pkt.OutputUniverses() {
|
for _, u := range pkt.OutputUniverses() {
|
||||||
if !containsUniverse(node.Outputs, u) {
|
if !containsUniverse(node.Outputs, u) {
|
||||||
node.Outputs = append(node.Outputs, u)
|
node.Outputs = append(node.Outputs, u)
|
||||||
newOutputs = append(newOutputs, u)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.onChange != nil {
|
if d.onChange != nil {
|
||||||
d.onChange(node)
|
d.onChange(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(newOutputs) > 0 {
|
|
||||||
go d.requestTod(src, newOutputs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Discovery) requestTod(addr *net.UDPAddr, universes []Universe) {
|
|
||||||
for _, u := range universes {
|
|
||||||
d.sender.SendTodRequest(addr, u)
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Discovery) HandleTodData(src *net.UDPAddr, pkt *TodDataPacket) {
|
|
||||||
d.nodesMu.Lock()
|
|
||||||
defer d.nodesMu.Unlock()
|
|
||||||
|
|
||||||
ip := src.IP.String()
|
|
||||||
node, exists := d.nodes[ip]
|
|
||||||
if !exists {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if node.RDMUIDs == nil {
|
|
||||||
node.RDMUIDs = map[Universe][]RDMUID{}
|
|
||||||
}
|
|
||||||
|
|
||||||
node.RDMUIDs[pkt.Universe] = pkt.UIDs
|
|
||||||
|
|
||||||
if d.onChange != nil {
|
|
||||||
d.onChange(node)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discovery) HandlePoll(src *net.UDPAddr) {
|
func (d *Discovery) HandlePoll(src *net.UDPAddr) {
|
||||||
|
|||||||
80
protocol.go
80
protocol.go
@@ -19,7 +19,6 @@ const (
|
|||||||
OpSync uint16 = 0x5200
|
OpSync uint16 = 0x5200
|
||||||
OpAddress uint16 = 0x6000
|
OpAddress uint16 = 0x6000
|
||||||
OpInput uint16 = 0x7000
|
OpInput uint16 = 0x7000
|
||||||
OpTodRequest uint16 = 0x8000
|
|
||||||
OpTodData uint16 = 0x8100
|
OpTodData uint16 = 0x8100
|
||||||
OpTodControl uint16 = 0x8200
|
OpTodControl uint16 = 0x8200
|
||||||
OpRdm uint16 = 0x8300
|
OpRdm uint16 = 0x8300
|
||||||
@@ -30,8 +29,6 @@ const (
|
|||||||
GoodOutputDataTransmitted uint8 = 0x80
|
GoodOutputDataTransmitted uint8 = 0x80
|
||||||
GoodInputDataReceived uint8 = 0x80
|
GoodInputDataReceived uint8 = 0x80
|
||||||
|
|
||||||
TodCommandFull uint8 = 0x00
|
|
||||||
|
|
||||||
StyleNode uint8 = 0x00
|
StyleNode uint8 = 0x00
|
||||||
StyleController uint8 = 0x01
|
StyleController uint8 = 0x01
|
||||||
StyleMedia uint8 = 0x02
|
StyleMedia uint8 = 0x02
|
||||||
@@ -151,33 +148,6 @@ func (p *PollReplyPacket) OutputUniverses() []Universe {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
type RDMUID [6]byte
|
|
||||||
|
|
||||||
func (u RDMUID) Manufacturer() uint16 {
|
|
||||||
return uint16(u[0])<<8 | uint16(u[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u RDMUID) Device() uint32 {
|
|
||||||
return uint32(u[2])<<24 | uint32(u[3])<<16 | uint32(u[4])<<8 | uint32(u[5])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u RDMUID) String() string {
|
|
||||||
return fmt.Sprintf("%04x:%08x", u.Manufacturer(), u.Device())
|
|
||||||
}
|
|
||||||
|
|
||||||
type TodDataPacket struct {
|
|
||||||
RdmVer uint8
|
|
||||||
Port uint8
|
|
||||||
BindIndex uint8
|
|
||||||
Net uint8
|
|
||||||
Command uint8
|
|
||||||
Universe Universe
|
|
||||||
UidTotal uint16
|
|
||||||
BlockCount uint8
|
|
||||||
UidCount uint8
|
|
||||||
UIDs []RDMUID
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParsePacket(data []byte) (uint16, interface{}, error) {
|
func ParsePacket(data []byte) (uint16, interface{}, error) {
|
||||||
if len(data) < 10 {
|
if len(data) < 10 {
|
||||||
return 0, nil, ErrPacketTooShort
|
return 0, nil, ErrPacketTooShort
|
||||||
@@ -199,9 +169,6 @@ func ParsePacket(data []byte) (uint16, interface{}, error) {
|
|||||||
case OpPollReply:
|
case OpPollReply:
|
||||||
pkt, err := parsePollReplyPacket(data)
|
pkt, err := parsePollReplyPacket(data)
|
||||||
return opCode, pkt, err
|
return opCode, pkt, err
|
||||||
case OpTodData:
|
|
||||||
pkt, err := parseTodDataPacket(data)
|
|
||||||
return opCode, pkt, err
|
|
||||||
default:
|
default:
|
||||||
return opCode, nil, nil
|
return opCode, nil, nil
|
||||||
}
|
}
|
||||||
@@ -312,53 +279,6 @@ func BuildPollPacket() []byte {
|
|||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTodDataPacket(data []byte) (*TodDataPacket, error) {
|
|
||||||
if len(data) < 28 {
|
|
||||||
return nil, ErrPacketTooShort
|
|
||||||
}
|
|
||||||
|
|
||||||
pkt := &TodDataPacket{
|
|
||||||
RdmVer: data[10],
|
|
||||||
Port: data[11],
|
|
||||||
BindIndex: data[20],
|
|
||||||
Net: data[21],
|
|
||||||
Command: data[22],
|
|
||||||
Universe: NewUniverse(data[21], data[23]>>4, data[23]&0x0F),
|
|
||||||
UidTotal: binary.BigEndian.Uint16(data[24:26]),
|
|
||||||
BlockCount: data[26],
|
|
||||||
UidCount: data[27],
|
|
||||||
}
|
|
||||||
|
|
||||||
uidCount := int(pkt.UidCount)
|
|
||||||
if uidCount > 200 {
|
|
||||||
uidCount = 200
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedLen := 28 + uidCount*6
|
|
||||||
if len(data) < expectedLen {
|
|
||||||
uidCount = (len(data) - 28) / 6
|
|
||||||
}
|
|
||||||
|
|
||||||
pkt.UIDs = make([]RDMUID, uidCount)
|
|
||||||
for i := 0; i < uidCount; i++ {
|
|
||||||
copy(pkt.UIDs[i][:], data[28+i*6:28+i*6+6])
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildTodRequestPacket(net, subnet, universe uint8) []byte {
|
|
||||||
buf := make([]byte, 25)
|
|
||||||
copy(buf[0:8], ID[:])
|
|
||||||
binary.LittleEndian.PutUint16(buf[8:10], OpTodRequest)
|
|
||||||
binary.BigEndian.PutUint16(buf[10:12], ProtocolVersion)
|
|
||||||
buf[20] = net
|
|
||||||
buf[21] = TodCommandFull
|
|
||||||
buf[22] = 1
|
|
||||||
buf[23] = subnet<<4 | (universe & 0x0F)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildPollReplyPacket(ip [4]byte, mac [6]byte, shortName, longName string, universes []Universe, isInput bool) []byte {
|
func BuildPollReplyPacket(ip [4]byte, mac [6]byte, shortName, longName string, universes []Universe, isInput bool) []byte {
|
||||||
buf := make([]byte, 240)
|
buf := make([]byte, 240)
|
||||||
copy(buf[0:8], ID[:])
|
copy(buf[0:8], ID[:])
|
||||||
|
|||||||
10
receiver.go
10
receiver.go
@@ -13,10 +13,6 @@ type Handler interface {
|
|||||||
HandlePollReply(src *net.UDPAddr, pkt *PollReplyPacket)
|
HandlePollReply(src *net.UDPAddr, pkt *PollReplyPacket)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TodDataHandler interface {
|
|
||||||
HandleTodData(src *net.UDPAddr, pkt *TodDataPacket)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Receiver struct {
|
type Receiver struct {
|
||||||
conn *net.UDPConn
|
conn *net.UDPConn
|
||||||
handler Handler
|
handler Handler
|
||||||
@@ -132,11 +128,5 @@ func (r *Receiver) handle(src *net.UDPAddr, data []byte) {
|
|||||||
if reply, ok := pkt.(*PollReplyPacket); ok {
|
if reply, ok := pkt.(*PollReplyPacket); ok {
|
||||||
r.handler.HandlePollReply(src, reply)
|
r.handler.HandlePollReply(src, reply)
|
||||||
}
|
}
|
||||||
case OpTodData:
|
|
||||||
if todHandler, ok := r.handler.(TodDataHandler); ok {
|
|
||||||
if tod, ok := pkt.(*TodDataPacket); ok {
|
|
||||||
todHandler.HandleTodData(src, tod)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,12 +81,6 @@ func (s *Sender) SendPollReply(addr *net.UDPAddr, localIP [4]byte, localMAC [6]b
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sender) SendTodRequest(addr *net.UDPAddr, universe Universe) error {
|
|
||||||
pkt := BuildTodRequestPacket(universe.Net(), universe.SubNet(), universe.Universe())
|
|
||||||
_, err := s.conn.WriteToUDP(pkt, addr)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sender) SendRaw(addr *net.UDPAddr, data []byte) error {
|
func (s *Sender) SendRaw(addr *net.UDPAddr, data []byte) error {
|
||||||
_, err := s.conn.WriteToUDP(data, addr)
|
_, err := s.conn.WriteToUDP(data, addr)
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user