226 lines
7.0 KiB
Go
226 lines
7.0 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import "fmt"
|
||
|
|
|
||
|
|
// ArtNet Protocol Constants from Art-Net 4 Specification
|
||
|
|
|
||
|
|
// ArtNetID is the magic identifier at the start of every Art-Net packet
|
||
|
|
var ArtNetID = [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00}
|
||
|
|
|
||
|
|
// Protocol Version - Current is 14
|
||
|
|
const (
|
||
|
|
ProtocolVersionHi = 0
|
||
|
|
ProtocolVersionLo = 14
|
||
|
|
)
|
||
|
|
|
||
|
|
// OpCodes - Table 1 from the spec
|
||
|
|
type OpCode uint16
|
||
|
|
|
||
|
|
const (
|
||
|
|
OpPoll OpCode = 0x2000
|
||
|
|
OpPollReply OpCode = 0x2100
|
||
|
|
OpDiagData OpCode = 0x2300
|
||
|
|
OpCommand OpCode = 0x2400
|
||
|
|
OpDataRequest OpCode = 0x2700
|
||
|
|
OpDataReply OpCode = 0x2800
|
||
|
|
OpDmx OpCode = 0x5000 // Also called OpOutput
|
||
|
|
OpNzs OpCode = 0x5100
|
||
|
|
OpSync OpCode = 0x5200
|
||
|
|
OpAddress OpCode = 0x6000
|
||
|
|
OpInput OpCode = 0x7000
|
||
|
|
OpTodRequest OpCode = 0x8000
|
||
|
|
OpTodData OpCode = 0x8100
|
||
|
|
OpTodControl OpCode = 0x8200
|
||
|
|
OpRdm OpCode = 0x8300
|
||
|
|
OpRdmSub OpCode = 0x8400
|
||
|
|
OpVideoSetup OpCode = 0xa010
|
||
|
|
OpVideoPalette OpCode = 0xa020
|
||
|
|
OpVideoData OpCode = 0xa040
|
||
|
|
OpMacMaster OpCode = 0xf000 // Deprecated
|
||
|
|
OpMacSlave OpCode = 0xf100 // Deprecated
|
||
|
|
OpFirmwareMaster OpCode = 0xf200
|
||
|
|
OpFirmwareReply OpCode = 0xf300
|
||
|
|
OpFileTnMaster OpCode = 0xf400
|
||
|
|
OpFileFnMaster OpCode = 0xf500
|
||
|
|
OpFileFnReply OpCode = 0xf600
|
||
|
|
OpIpProg OpCode = 0xf800
|
||
|
|
OpIpProgReply OpCode = 0xf900
|
||
|
|
OpMedia OpCode = 0x9000
|
||
|
|
OpMediaPatch OpCode = 0x9100
|
||
|
|
OpMediaControl OpCode = 0x9200
|
||
|
|
OpMediaCtrlReply OpCode = 0x9300
|
||
|
|
OpTimeCode OpCode = 0x9700
|
||
|
|
OpTimeSync OpCode = 0x9800
|
||
|
|
OpTrigger OpCode = 0x9900
|
||
|
|
OpDirectory OpCode = 0x9a00
|
||
|
|
OpDirectoryReply OpCode = 0x9b00
|
||
|
|
)
|
||
|
|
|
||
|
|
func (o OpCode) String() string {
|
||
|
|
names := map[OpCode]string{
|
||
|
|
OpPoll: "OpPoll",
|
||
|
|
OpPollReply: "OpPollReply",
|
||
|
|
OpDiagData: "OpDiagData",
|
||
|
|
OpCommand: "OpCommand",
|
||
|
|
OpDataRequest: "OpDataRequest",
|
||
|
|
OpDataReply: "OpDataReply",
|
||
|
|
OpDmx: "OpDmx/OpOutput",
|
||
|
|
OpNzs: "OpNzs",
|
||
|
|
OpSync: "OpSync",
|
||
|
|
OpAddress: "OpAddress",
|
||
|
|
OpInput: "OpInput",
|
||
|
|
OpTodRequest: "OpTodRequest",
|
||
|
|
OpTodData: "OpTodData",
|
||
|
|
OpTodControl: "OpTodControl",
|
||
|
|
OpRdm: "OpRdm",
|
||
|
|
OpRdmSub: "OpRdmSub",
|
||
|
|
OpVideoSetup: "OpVideoSetup",
|
||
|
|
OpVideoPalette: "OpVideoPalette",
|
||
|
|
OpVideoData: "OpVideoData",
|
||
|
|
OpMacMaster: "OpMacMaster (Deprecated)",
|
||
|
|
OpMacSlave: "OpMacSlave (Deprecated)",
|
||
|
|
OpFirmwareMaster: "OpFirmwareMaster",
|
||
|
|
OpFirmwareReply: "OpFirmwareReply",
|
||
|
|
OpFileTnMaster: "OpFileTnMaster",
|
||
|
|
OpFileFnMaster: "OpFileFnMaster",
|
||
|
|
OpFileFnReply: "OpFileFnReply",
|
||
|
|
OpIpProg: "OpIpProg",
|
||
|
|
OpIpProgReply: "OpIpProgReply",
|
||
|
|
OpMedia: "OpMedia",
|
||
|
|
OpMediaPatch: "OpMediaPatch",
|
||
|
|
OpMediaControl: "OpMediaControl",
|
||
|
|
OpMediaCtrlReply: "OpMediaCtrlReply",
|
||
|
|
OpTimeCode: "OpTimeCode",
|
||
|
|
OpTimeSync: "OpTimeSync",
|
||
|
|
OpTrigger: "OpTrigger",
|
||
|
|
OpDirectory: "OpDirectory",
|
||
|
|
OpDirectoryReply: "OpDirectoryReply",
|
||
|
|
}
|
||
|
|
if name, ok := names[o]; ok {
|
||
|
|
return name
|
||
|
|
}
|
||
|
|
return fmt.Sprintf("Unknown(0x%04X)", uint16(o))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Minimum packet lengths per spec
|
||
|
|
const (
|
||
|
|
MinArtPollLength = 14 // Spec: "accept as valid a packet of length 14 bytes or larger"
|
||
|
|
MinArtPollReplyLength = 207 // Spec: "accept as valid a packet of length 207 bytes or larger"
|
||
|
|
)
|
||
|
|
|
||
|
|
// NodeReport Codes - Table 3
|
||
|
|
type NodeReportCode uint16
|
||
|
|
|
||
|
|
const (
|
||
|
|
RcDebug NodeReportCode = 0x0000
|
||
|
|
RcPowerOk NodeReportCode = 0x0001
|
||
|
|
RcPowerFail NodeReportCode = 0x0002
|
||
|
|
RcSocketWr1 NodeReportCode = 0x0003
|
||
|
|
RcParseFail NodeReportCode = 0x0004
|
||
|
|
RcUdpFail NodeReportCode = 0x0005
|
||
|
|
RcShNameOk NodeReportCode = 0x0006
|
||
|
|
RcLoNameOk NodeReportCode = 0x0007
|
||
|
|
RcDmxError NodeReportCode = 0x0008
|
||
|
|
RcDmxUdpFull NodeReportCode = 0x0009
|
||
|
|
RcDmxRxFull NodeReportCode = 0x000a
|
||
|
|
RcSwitchErr NodeReportCode = 0x000b
|
||
|
|
RcConfigErr NodeReportCode = 0x000c
|
||
|
|
RcDmxShort NodeReportCode = 0x000d
|
||
|
|
RcFirmwareFail NodeReportCode = 0x000e
|
||
|
|
RcUserFail NodeReportCode = 0x000f
|
||
|
|
RcFactoryRes NodeReportCode = 0x0010
|
||
|
|
)
|
||
|
|
|
||
|
|
func (n NodeReportCode) String() string {
|
||
|
|
names := map[NodeReportCode]string{
|
||
|
|
RcDebug: "RcDebug - Booted in debug mode",
|
||
|
|
RcPowerOk: "RcPowerOk - Power On Tests successful",
|
||
|
|
RcPowerFail: "RcPowerFail - Hardware tests failed at Power On",
|
||
|
|
RcSocketWr1: "RcSocketWr1 - Last UDP truncated (collision?)",
|
||
|
|
RcParseFail: "RcParseFail - Unable to identify last UDP",
|
||
|
|
RcUdpFail: "RcUdpFail - Unable to open UDP Socket",
|
||
|
|
RcShNameOk: "RcShNameOk - Port Name programming successful",
|
||
|
|
RcLoNameOk: "RcLoNameOk - Long Name programming successful",
|
||
|
|
RcDmxError: "RcDmxError - DMX512 receive errors detected",
|
||
|
|
RcDmxUdpFull: "RcDmxUdpFull - Ran out of DMX transmit buffers",
|
||
|
|
RcDmxRxFull: "RcDmxRxFull - Ran out of DMX Rx buffers",
|
||
|
|
RcSwitchErr: "RcSwitchErr - Rx Universe switches conflict",
|
||
|
|
RcConfigErr: "RcConfigErr - Config does not match firmware",
|
||
|
|
RcDmxShort: "RcDmxShort - DMX output short detected",
|
||
|
|
RcFirmwareFail: "RcFirmwareFail - Firmware upload failed",
|
||
|
|
RcUserFail: "RcUserFail - User changes ignored (locked)",
|
||
|
|
RcFactoryRes: "RcFactoryRes - Factory reset occurred",
|
||
|
|
}
|
||
|
|
if name, ok := names[n]; ok {
|
||
|
|
return name
|
||
|
|
}
|
||
|
|
return fmt.Sprintf("Unknown(0x%04X)", uint16(n))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Style Codes - Table 4
|
||
|
|
type StyleCode uint8
|
||
|
|
|
||
|
|
const (
|
||
|
|
StNode StyleCode = 0x00
|
||
|
|
StController StyleCode = 0x01
|
||
|
|
StMedia StyleCode = 0x02
|
||
|
|
StRoute StyleCode = 0x03
|
||
|
|
StBackup StyleCode = 0x04
|
||
|
|
StConfig StyleCode = 0x05
|
||
|
|
StVisual StyleCode = 0x06
|
||
|
|
)
|
||
|
|
|
||
|
|
func (s StyleCode) String() string {
|
||
|
|
names := map[StyleCode]string{
|
||
|
|
StNode: "StNode - DMX to/from Art-Net device",
|
||
|
|
StController: "StController - Lighting console",
|
||
|
|
StMedia: "StMedia - Media Server",
|
||
|
|
StRoute: "StRoute - Network routing device",
|
||
|
|
StBackup: "StBackup - Backup device",
|
||
|
|
StConfig: "StConfig - Configuration/diagnostic tool",
|
||
|
|
StVisual: "StVisual - Visualiser",
|
||
|
|
}
|
||
|
|
if name, ok := names[s]; ok {
|
||
|
|
return name
|
||
|
|
}
|
||
|
|
return fmt.Sprintf("Unknown(0x%02X)", uint8(s))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Priority Codes - Table 5
|
||
|
|
type PriorityCode uint8
|
||
|
|
|
||
|
|
const (
|
||
|
|
DpLow PriorityCode = 0x10
|
||
|
|
DpMed PriorityCode = 0x40
|
||
|
|
DpHigh PriorityCode = 0x80
|
||
|
|
DpCritical PriorityCode = 0xe0
|
||
|
|
DpVolatile PriorityCode = 0xf0
|
||
|
|
)
|
||
|
|
|
||
|
|
func (p PriorityCode) String() string {
|
||
|
|
names := map[PriorityCode]string{
|
||
|
|
DpLow: "DpLow - Low priority",
|
||
|
|
DpMed: "DpMed - Medium priority",
|
||
|
|
DpHigh: "DpHigh - High priority",
|
||
|
|
DpCritical: "DpCritical - Critical priority",
|
||
|
|
DpVolatile: "DpVolatile - Volatile (single line display)",
|
||
|
|
}
|
||
|
|
if name, ok := names[p]; ok {
|
||
|
|
return name
|
||
|
|
}
|
||
|
|
return fmt.Sprintf("Unknown(0x%02X)", uint8(p))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Port Types bit definitions
|
||
|
|
const (
|
||
|
|
PortTypeOutput = 0x80 // Bit 7: Can output data from Art-Net
|
||
|
|
PortTypeInput = 0x40 // Bit 6: Can input onto Art-Net
|
||
|
|
PortTypeDMX512 = 0x00 // Bits 5-0: Protocol
|
||
|
|
PortTypeMIDI = 0x01
|
||
|
|
PortTypeAvab = 0x02
|
||
|
|
PortTypeCMX = 0x03
|
||
|
|
PortTypeADB = 0x04
|
||
|
|
PortTypeArtNet = 0x05
|
||
|
|
PortTypeDALI = 0x06
|
||
|
|
)
|