mirror of
https://github.com/jwetzell/artnet-go.git
synced 2026-08-07 00:03:38 +00:00
154 lines
4.3 KiB
Go
154 lines
4.3 KiB
Go
package artnet
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"slices"
|
|
)
|
|
|
|
type ArtPollReply struct {
|
|
IPAddress [4]uint8
|
|
Port uint16
|
|
VersInfo uint16
|
|
NetSwitch uint8
|
|
SubSwitch uint8
|
|
Oem uint16
|
|
UbeaVersion uint8
|
|
Status1 uint8
|
|
EstaMan uint16
|
|
PortName [18]uint8
|
|
LongName [64]uint8
|
|
NodeReport [64]uint8
|
|
NumPorts uint16
|
|
PortTypes [4]uint8
|
|
GoodInput [4]uint8
|
|
GoodOutputA [4]uint8
|
|
SwIn [4]uint8
|
|
SwOut [4]uint8
|
|
AcnPriority uint8
|
|
SwMacro uint8
|
|
SwRemote uint8
|
|
spare1 uint8
|
|
spare2 uint8
|
|
spare3 uint8
|
|
Style uint8
|
|
MAC [6]uint8
|
|
// TODO(jwetzell): support extended poll fields
|
|
BindIp [4]uint8
|
|
BindIndex uint8
|
|
Status2 uint8
|
|
GoodOutputB [4]uint8
|
|
Status3 uint8
|
|
DefaultRespUID uint64
|
|
User uint16
|
|
RefreshRate uint8
|
|
BackgroundQueuePolicy uint8
|
|
filler [10]uint8
|
|
}
|
|
|
|
func (ap *ArtPollReply) GetOpCode() uint16 {
|
|
return OpPollReply
|
|
}
|
|
|
|
func (ap *ArtPollReply) UnmarshalBinary(data []byte) error {
|
|
|
|
if len(data) < 207 {
|
|
return errors.New("ArtPollReply packet must be at least 207 bytes long")
|
|
}
|
|
|
|
if !slices.Equal(ArtNetID[:], data[0:8]) {
|
|
return errors.New("ID does not match Art-Net ID")
|
|
}
|
|
|
|
opCode := binary.LittleEndian.Uint16(data[8:10])
|
|
if opCode != OpPollReply {
|
|
return errors.New("packet does not have the correct OpCode for an ArtPollReply packet")
|
|
}
|
|
|
|
ap.IPAddress[0] = data[10]
|
|
ap.IPAddress[1] = data[11]
|
|
ap.IPAddress[2] = data[12]
|
|
ap.IPAddress[3] = data[13]
|
|
ap.Port = binary.LittleEndian.Uint16(data[14:16])
|
|
ap.VersInfo = binary.BigEndian.Uint16(data[16:18])
|
|
ap.NetSwitch = data[18]
|
|
ap.SubSwitch = data[19]
|
|
ap.Oem = binary.BigEndian.Uint16(data[20:22])
|
|
ap.UbeaVersion = data[22]
|
|
ap.Status1 = data[23]
|
|
ap.EstaMan = binary.LittleEndian.Uint16(data[24:26])
|
|
copy(ap.PortName[:], data[26:44])
|
|
copy(ap.LongName[:], data[44:108])
|
|
copy(ap.NodeReport[:], data[108:172])
|
|
ap.NumPorts = binary.BigEndian.Uint16(data[172:174])
|
|
copy(ap.PortTypes[:], data[174:178])
|
|
copy(ap.GoodInput[:], data[178:182])
|
|
copy(ap.GoodOutputA[:], data[182:186])
|
|
copy(ap.SwIn[:], data[186:190])
|
|
copy(ap.SwOut[:], data[190:194])
|
|
ap.AcnPriority = data[194]
|
|
ap.SwMacro = data[195]
|
|
ap.SwRemote = data[196]
|
|
ap.spare1 = data[197]
|
|
ap.spare2 = data[198]
|
|
ap.spare3 = data[199]
|
|
ap.Style = data[200]
|
|
copy(ap.MAC[:], data[201:207])
|
|
return nil
|
|
}
|
|
|
|
func (ap *ArtPollReply) MarshalBinary() ([]byte, error) {
|
|
if ap.DefaultRespUID > 0xFFFFFFFFFFFF {
|
|
return nil, errors.New("DefaultRespUID must not be greater than 281474976710655")
|
|
}
|
|
data := make([]byte, 8+230)
|
|
copy(data[0:8], ArtNetID[:])
|
|
binary.LittleEndian.PutUint16(data[8:10], OpPollReply)
|
|
data[10] = ap.IPAddress[0]
|
|
data[11] = ap.IPAddress[1]
|
|
data[12] = ap.IPAddress[2]
|
|
data[13] = ap.IPAddress[3]
|
|
binary.LittleEndian.PutUint16(data[14:16], ap.Port)
|
|
binary.BigEndian.PutUint16(data[16:18], ap.VersInfo)
|
|
data[18] = ap.NetSwitch
|
|
data[19] = ap.SubSwitch
|
|
binary.BigEndian.PutUint16(data[20:22], ap.Oem)
|
|
data[22] = ap.UbeaVersion
|
|
data[23] = ap.Status1
|
|
binary.LittleEndian.PutUint16(data[24:26], ap.EstaMan)
|
|
copy(data[26:44], ap.PortName[:])
|
|
copy(data[44:108], ap.LongName[:])
|
|
copy(data[108:172], ap.NodeReport[:])
|
|
binary.BigEndian.PutUint16(data[172:174], ap.NumPorts)
|
|
copy(data[174:178], ap.PortTypes[:])
|
|
copy(data[178:182], ap.GoodInput[:])
|
|
copy(data[182:186], ap.GoodOutputA[:])
|
|
copy(data[186:190], ap.SwIn[:])
|
|
copy(data[190:194], ap.SwOut[:])
|
|
data[194] = ap.AcnPriority
|
|
data[195] = ap.SwMacro
|
|
data[196] = ap.SwRemote
|
|
data[197] = ap.spare1
|
|
data[198] = ap.spare2
|
|
data[199] = ap.spare3
|
|
data[200] = ap.Style
|
|
copy(data[201:207], ap.MAC[:])
|
|
copy(data[207:211], ap.BindIp[:])
|
|
data[211] = ap.BindIndex
|
|
data[212] = ap.Status2
|
|
copy(data[213:217], ap.GoodOutputB[:])
|
|
data[217] = ap.Status3
|
|
// DefaultRespUID is a 48-bit value, so we need to make sure we only write the lower 6 bytes
|
|
data[218] = uint8(ap.DefaultRespUID >> 40)
|
|
data[219] = uint8(ap.DefaultRespUID >> 32)
|
|
data[220] = uint8(ap.DefaultRespUID >> 24)
|
|
data[221] = uint8(ap.DefaultRespUID >> 16)
|
|
data[222] = uint8(ap.DefaultRespUID >> 8)
|
|
data[223] = uint8(ap.DefaultRespUID)
|
|
binary.BigEndian.PutUint16(data[224:226], ap.User)
|
|
data[226] = ap.RefreshRate
|
|
data[227] = ap.BackgroundQueuePolicy
|
|
copy(data[228:], ap.filler[:])
|
|
return data, nil
|
|
}
|