31 Commits

Author SHA1 Message Date
Joel Wetzell bd47dddb58 add benchmark for all marshal functions 2026-05-30 10:54:20 -05:00
Joel Wetzell 968ad64521 organize select case by OpCode 2026-05-30 10:54:05 -05:00
Joel Wetzell 6630584ae7 rework byte array calculation in marshal functions 2026-05-30 10:53:50 -05:00
Joel Wetzell 37ca97c5ab add benchmark and fuzz for tests with data 2026-05-30 10:31:37 -05:00
Joel Wetzell 07ff9daf88 fix up example 2026-05-30 09:49:48 -05:00
Joel Wetzell c179b8fc26 fill out tod control test from wireshark dissector 2026-05-30 09:21:59 -05:00
Joel Wetzell b71986eaba add test workflow 2026-05-30 09:20:33 -05:00
Joel Wetzell b7d8e8dddd switch tests to use cmp.Diff 2026-05-30 09:20:20 -05:00
Joel Wetzell d8da54172e fix opcode for tod control 2026-05-30 09:09:34 -05:00
Joel Wetzell 8f21c3968e add todcontrol packet from ACT software 2026-05-30 09:08:44 -05:00
Joel Wetzell 91206f6037 add tod control packet 2026-05-30 09:06:07 -05:00
Joel Wetzell c44996dd32 fill out address testing using wireshark dissector 2026-05-30 08:56:52 -05:00
Joel Wetzell c0701537b6 remove constants from packet structs 2026-05-30 08:56:07 -05:00
Joel Wetzell f3b6a6ef1b add some extended fields for poll 2026-05-30 07:22:54 -05:00
Joel Wetzell 3680bfb820 not all packets have ProtVer 2026-05-30 07:22:39 -05:00
Joel Wetzell 92b37e0b19 use datarequest type 2026-05-30 07:22:09 -05:00
Joel Wetzell 16f045e8fe add poll reply 2026-05-30 07:21:24 -05:00
Joel Wetzell 56614027df add test boilerplate 2026-05-30 07:21:06 -05:00
Joel Wetzell 11739370c4 fix endianness 2026-05-30 07:18:23 -05:00
Joel Wetzell 79ecda6f87 add empty tests for artnet address 2026-05-30 07:15:20 -05:00
Joel Wetzell eec90ba0c1 add tod request and tests from ACT 2026-05-30 07:13:09 -05:00
Joel Wetzell 5869f308a3 add ArtNzs 2026-05-26 17:56:34 -05:00
Joel Wetzell 06ec1acea1 add ArtAddress 2026-05-26 17:56:28 -05:00
Joel Wetzell 460ffe7bda align method receiver variable name 2026-05-26 17:56:21 -05:00
Joel Wetzell 572fa39c16 remove length property and make it calculated 2026-05-26 17:54:35 -05:00
Joel Wetzell 9546018fb7 add ip programming packet types 2026-05-26 07:27:07 -05:00
Joel Wetzell 76189580db combine multi byte fields into one field 2026-05-26 07:26:53 -05:00
Joel Wetzell 225fb8b79a some untested implementations for moore artnet packet types 2026-05-25 19:05:49 -05:00
Joel Wetzell 207a18d18e mess around with fuzzing 2026-05-23 07:43:15 -05:00
Joel Wetzell 2cb6487036 fix size check on timecode unmarshal 2026-05-23 07:42:48 -05:00
Joel Wetzell 4efa58ee25 Add LICENSE 2026-05-20 13:26:06 -05:00
38 changed files with 3425 additions and 243 deletions
+18
View File
@@ -0,0 +1,18 @@
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Run tests
run: go test -v .
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Joel Wetzell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+146
View File
@@ -0,0 +1,146 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type AddressCommand uint8
const (
AcNone AddressCommand = 0x00
AcCancelMerge AddressCommand = 0x01
AcLedNormal AddressCommand = 0x02
AcLedMute AddressCommand = 0x03
AcLedLocate AddressCommand = 0x04
AcResetRxFlags AddressCommand = 0x05
AcAnalysisOn AddressCommand = 0x06
AcAnalysisOff AddressCommand = 0x07
AcFailHold AddressCommand = 0x08
AcFailZero AddressCommand = 0x09
AcFailFull AddressCommand = 0x0A
AcFailScene AddressCommand = 0x0B
AcFailRecord AddressCommand = 0x0C
AcMergeLtp0 AddressCommand = 0x10
AcMergeLtp1 AddressCommand = 0x11
AcMergeLtp2 AddressCommand = 0x12
AcMergeLtp3 AddressCommand = 0x13
AcDirectionTx0 AddressCommand = 0x20
AcDirectionTx1 AddressCommand = 0x21
AcDirectionTx2 AddressCommand = 0x22
AcDirectionTx3 AddressCommand = 0x23
AcDirectionRx0 AddressCommand = 0x30
AcDirectionRx1 AddressCommand = 0x31
AcDirectionRx2 AddressCommand = 0x32
AcDirectionRx3 AddressCommand = 0x33
AcMergeHtp0 AddressCommand = 0x50
AcMergeHtp1 AddressCommand = 0x51
AcMergeHtp2 AddressCommand = 0x52
AcMergeHtp3 AddressCommand = 0x53
AcArtNetSel0 AddressCommand = 0x60
AcArtNetSel1 AddressCommand = 0x61
AcArtNetSel2 AddressCommand = 0x62
AcArtNetSel3 AddressCommand = 0x63
AcAcnSel0 AddressCommand = 0x70
AcAcnSel1 AddressCommand = 0x71
AcAcnSel2 AddressCommand = 0x72
AcAcnSel3 AddressCommand = 0x73
AcClearOp0 AddressCommand = 0x90
AcClearOp1 AddressCommand = 0x91
AcClearOp2 AddressCommand = 0x92
AcClearOp3 AddressCommand = 0x93
AcStyleDelta0 AddressCommand = 0xa0
AcStyleDelta1 AddressCommand = 0xa1
AcStyleDelta2 AddressCommand = 0xa2
AcStyleDelta3 AddressCommand = 0xa3
AcStyleConst0 AddressCommand = 0xb0
AcStyleConst1 AddressCommand = 0xb1
AcStyleConst2 AddressCommand = 0xb2
AcStyleConst3 AddressCommand = 0xb3
AcRdmEnable0 AddressCommand = 0xc0
AcRdmEnable1 AddressCommand = 0xc1
AcRdmEnable2 AddressCommand = 0xc2
AcRdmEnable3 AddressCommand = 0xc3
AcRdmDisable0 AddressCommand = 0xd0
AcRdmDisable1 AddressCommand = 0xd1
AcRdmDisable2 AddressCommand = 0xd2
AcRdmDisable3 AddressCommand = 0xd3
AcBqp0 AddressCommand = 0xe0
AcBqp1 AddressCommand = 0xe1
AcBqp2 AddressCommand = 0xe2
AcBqp3 AddressCommand = 0xe3
AcBqp4 AddressCommand = 0xe4
AcBqp5 AddressCommand = 0xe5
AcBqp6 AddressCommand = 0xe6
AcBqp7 AddressCommand = 0xe7
AcBqp8 AddressCommand = 0xe8
AcBqp9 AddressCommand = 0xe9
AcBqp10 AddressCommand = 0xea
AcBqp11 AddressCommand = 0xeb
AcBqp12 AddressCommand = 0xec
AcBqp13 AddressCommand = 0xed
AcBqp14 AddressCommand = 0xee
AcBqp15 AddressCommand = 0xef
)
type ArtAddress struct {
NetSwitch uint8
BindIndex uint8
PortName [18]uint8
LongName [64]uint8
SwIn [4]uint8
SwOut [4]uint8
SubSwitch uint8
AcnPriority uint8
Command AddressCommand
}
func (aa *ArtAddress) GetOpCode() uint16 {
return OpAddress
}
func (aa *ArtAddress) UnmarshalBinary(data []byte) error {
if len(data) < 107 {
return errors.New("ArtAddress packet must be at least 107 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 != OpAddress {
return errors.New("packet does not have the correct OpCode for an ArtAddress packet")
}
offset := 12
aa.NetSwitch = data[offset]
aa.BindIndex = data[offset+1]
copy(aa.PortName[:], data[offset+2:offset+20])
copy(aa.LongName[:], data[offset+20:offset+84])
copy(aa.SwIn[:], data[offset+84:offset+88])
copy(aa.SwOut[:], data[offset+88:offset+92])
aa.SubSwitch = data[offset+92]
aa.AcnPriority = data[offset+93]
aa.Command = AddressCommand(data[offset+94])
return nil
}
func (aa *ArtAddress) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+95)
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpAddress)
data[10] = 0
data[11] = 14
offset := 12
data[offset] = aa.NetSwitch
data[offset+1] = aa.BindIndex
copy(data[offset+2:offset+20], aa.PortName[:])
copy(data[offset+20:offset+84], aa.LongName[:])
copy(data[offset+84:offset+88], aa.SwIn[:])
copy(data[offset+88:offset+92], aa.SwOut[:])
data[offset+92] = aa.SubSwitch
data[offset+93] = aa.AcnPriority
data[offset+94] = uint8(aa.Command)
return data, nil
}
+976
View File
@@ -0,0 +1,976 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtAddressUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtAddress
}{
{
Name: "ACT Packet 1",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0xc7, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x05,
BindIndex: 0x00,
PortName: [18]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x00},
LongName: [64]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00},
SwIn: [4]byte{0x0e, 0x0d, 0x0c, 0x0b},
SwOut: [4]byte{0x0a, 0x09, 0x08, 0x07},
SubSwitch: 0x06,
AcnPriority: 0xc7,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 2",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x05, 0x00, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x23, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0xc7, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x05,
BindIndex: 0x00,
PortName: [18]byte{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '*'},
LongName: [64]byte{'*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '#'},
SwIn: [4]byte{0x0e, 0x0d, 0x0c, 0x0b},
SwOut: [4]byte{0x0a, 0x09, 0x08, 0x07},
SubSwitch: 0x06,
AcnPriority: 0xc7,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 3",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x05, 0x00, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x25, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0xc7, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x05,
BindIndex: 0x00,
PortName: [18]byte{'%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '&'},
LongName: [64]byte{'&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '&', '%'},
SwIn: [4]byte{0x0e, 0x0d, 0x0c, 0x0b},
SwOut: [4]byte{0x0a, 0x09, 0x08, 0x07},
SubSwitch: 0x06,
AcnPriority: 0xc7,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 4",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x83, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x83,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 5",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x8f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 6",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x8f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 7",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x8f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 8",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x85, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x85, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x7f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 9",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x8f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 10",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x8f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 11",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x8f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 12",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x8f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 13",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x8f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 14",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x7f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 15",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xe4, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{0x00, 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{0x00, 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x7f,
AcnPriority: 0xff,
Command: artnet.AcBqp4,
},
},
{
Name: "ACT Packet 16",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x7f, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x7f,
BindIndex: 0x00,
PortName: [18]byte{'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x7f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 17",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x00, 0x85, 0x86, 0x87, 0x88, 0x81, 0x82, 0x83, 0x84, 0x80, 0xc8, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0x00},
LongName: [64]byte{'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 0x00},
SwIn: [4]byte{0x85, 0x86, 0x87, 0x88},
SwOut: [4]byte{0x81, 0x82, 0x83, 0x84},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 18",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x00, 0x85, 0x86, 0x87, 0x88, 0x81, 0x82, 0x83, 0x84, 0x80, 0xc8, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0x00},
LongName: [64]byte{'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 0x00},
SwIn: [4]byte{0x85, 0x86, 0x87, 0x88},
SwOut: [4]byte{0x81, 0x82, 0x83, 0x84},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 19",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x00, 0x85, 0x86, 0x87, 0x88, 0x81, 0x82, 0x83, 0x84, 0x80, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0x00},
LongName: [64]byte{'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 0x00},
SwIn: [4]byte{0x85, 0x86, 0x87, 0x88},
SwOut: [4]byte{0x81, 0x82, 0x83, 0x84},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 20",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc8, 0x20, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x80, 0x80, 0x80, 0x80},
SwOut: [4]byte{0x80, 0x80, 0x80, 0x80},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 21",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x82, 0x83, 0x80, 0x81, 0x82, 0x83, 0x81, 0xc8, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x80, 0x81, 0x82, 0x83},
SwOut: [4]byte{0x80, 0x81, 0x82, 0x83},
SubSwitch: 0x81,
AcnPriority: 0xc8,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 22",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 23",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 24",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 25",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 26",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 27",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 28",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 29",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 30",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 31",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionTx0,
},
},
{
Name: "ACT Packet 32",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 33",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 34",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 35",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 36",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 37",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 38",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 39",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 40",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x20, 0x44, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0xc8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'B', 'i', 'n', 'd', ' ', '0'},
LongName: [64]byte{'A', 'C', 'T', ' ', 'D', 'U', 'T'},
SwIn: [4]byte{0x81, 0x81, 0x81, 0x81},
SwOut: [4]byte{0x81, 0x81, 0x81, 0x81},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcDirectionRx0,
},
},
{
Name: "ACT Packet 41",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc8, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'p', 'o', 'r', 't', ' ', 'n', 'a', 'm', 'e'},
LongName: [64]byte{'l', 'o', 'n', 'g', ' ', 'n', 'a', 'm', 'e'},
SwIn: [4]byte{0x80, 0x80, 0x80, 0x80},
SwOut: [4]byte{0x80, 0x80, 0x80, 0x80},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 42",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x82, 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x61, 0x62, 0x63, 0x64, 0x65, 0x61, 0x62, 0x63, 0x64, 0x65, 0x61, 0x62, 0x00, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x77, 0x78, 0x79, 0x00, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x8a, 0x00, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x82,
BindIndex: 0x00,
PortName: [18]byte{'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 0x00},
LongName: [64]byte{'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 'z', '{', 'w', 'x', 'y', 0x00},
SwIn: [4]byte{0x80, 0x81, 0x82, 0x83},
SwOut: [4]byte{0x84, 0x85, 0x86, 0x87},
SubSwitch: 0x8a,
AcnPriority: 0x00,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 43",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x84, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x84,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x7f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 44",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x85, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0xc7, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0x85,
BindIndex: 0x00,
PortName: [18]byte{'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x8e, 0x8d, 0x8c, 0x8b},
SwOut: [4]byte{0x8a, 0x89, 0x88, 0x87},
SubSwitch: 0x86,
AcnPriority: 0xc7,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 45",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x8f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 46",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x8f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 47",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x8f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 48",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x8f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 49",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x8f, 0x7f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 50",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x8f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 51",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x8f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 52",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x8f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 53",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x8f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 54",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x7f, 0x8f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 55",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x8f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 56",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x7f, 0x8f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 57",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x8f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 58",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x7f, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x7f, 0x8f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 59",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x8f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x0f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
{
Name: "ACT Packet 60",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x8f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x8f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtAddress{
NetSwitch: 0xff,
BindIndex: 0x00,
PortName: [18]byte{0x00, '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', 0x00},
LongName: [64]byte{0x00, ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', 0x00},
SwIn: [4]byte{0x8f, 0x7f, 0x7f, 0x7f},
SwOut: [4]byte{0x7f, 0x7f, 0x7f, 0x7f},
SubSwitch: 0x8f,
AcnPriority: 0xff,
Command: artnet.AcNone,
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtAddress{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtAddress: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtAddress{}))
if diff != "" {
t.Fatalf("ArtAddress does not match\n%s", diff)
}
})
}
}
func BenchmarkArtAddressUnmarshalBinary(b *testing.B) {
data := []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x00, 0x85, 0x86, 0x87, 0x88, 0x81, 0x82, 0x83, 0x84, 0x80, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
for b.Loop() {
got := artnet.ArtAddress{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtAddress: %s", err)
}
}
}
func BenchmarkArtAddressMarshalBinary(b *testing.B) {
data := artnet.ArtAddress{
NetSwitch: 0x80,
BindIndex: 0x00,
PortName: [18]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0x00},
LongName: [64]byte{'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 0x00},
SwIn: [4]byte{0x85, 0x86, 0x87, 0x88},
SwOut: [4]byte{0x81, 0x82, 0x83, 0x84},
SubSwitch: 0x80,
AcnPriority: 0xc8,
Command: artnet.AcNone,
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtAddress: %s", err)
}
}
}
func FuzzArtAddressUnmarshalBinary(f *testing.F) {
f.Add([]byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x60, 0x00, 0x0e, 0x80, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x00, 0x85, 0x86, 0x87, 0x88, 0x81, 0x82, 0x83, 0x84, 0x80, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
f.Fuzz(func(t *testing.T, data []byte) {
artAddress := artnet.ArtAddress{}
artAddress.UnmarshalBinary(data)
})
}
+120
View File
@@ -65,6 +65,46 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
} }
return &artPoll, nil return &artPoll, nil
case OpPollReply:
artPollReply := ArtPollReply{}
err := artPollReply.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artPollReply, nil
case OpDiagData:
artDiagData := ArtDiagData{}
err := artDiagData.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artDiagData, nil
case OpCommand:
artCommand := ArtCommand{}
err := artCommand.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artCommand, nil
case OpDataRequest:
artDataRequest := ArtDataRequest{}
err := artDataRequest.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artDataRequest, nil
case OpDmx: case OpDmx:
artDmx := ArtDmx{} artDmx := ArtDmx{}
@@ -75,6 +115,76 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
} }
return &artDmx, nil return &artDmx, nil
case OpNzs:
artNzs := ArtNzs{}
err := artNzs.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artNzs, nil
case OpSync:
artSync := ArtSync{}
err := artSync.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artSync, nil
case OpAddress:
artAddress := ArtAddress{}
err := artAddress.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artAddress, nil
case OpTodRequest:
artTodRequest := ArtTodRequest{}
err := artTodRequest.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artTodRequest, nil
case OpTodControl:
artTodControl := ArtTodControl{}
err := artTodControl.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artTodControl, nil
case OpIpProg:
artIpProg := ArtIpProg{}
err := artIpProg.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artIpProg, nil
case OpIpProgReply:
artIpProgReply := ArtIpProgReply{}
err := artIpProgReply.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artIpProgReply, nil
case OpTimeCode: case OpTimeCode:
artTimeCode := ArtTimeCode{} artTimeCode := ArtTimeCode{}
@@ -85,6 +195,16 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
} }
return &artTimeCode, nil return &artTimeCode, nil
case OpTrigger:
artTrigger := ArtTrigger{}
err := artTrigger.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artTrigger, nil
default: default:
return nil, fmt.Errorf("unhandled opcode: %#x", opCode) return nil, fmt.Errorf("unhandled opcode: %#x", opCode)
} }
+67
View File
@@ -0,0 +1,67 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type Command string
const (
SwoutText Command = "SwoutText"
SwinText Command = "SwinText"
)
type ArtCommand struct {
EstaMan uint16
Data []uint8
}
func (ac *ArtCommand) GetOpCode() uint16 {
return OpCommand
}
func (ac *ArtCommand) UnmarshalBinary(data []byte) error {
if len(data) < 16 {
return errors.New("ArtCommand packet must be at least 16 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 != OpCommand {
return errors.New("packet does not have the correct OpCode for an ArtCommand packet")
}
offset := 12
ac.EstaMan = binary.BigEndian.Uint16(data[offset : offset+2])
dataLength := int(binary.BigEndian.Uint16(data[offset+2 : offset+4]))
if len(data[offset+4:]) < dataLength {
return errors.New("[]byte length not long enough to contain data length specified in packet")
}
ac.Data = make([]uint8, dataLength)
copy(ac.Data, data[offset+4:offset+4+dataLength])
return nil
}
func (ac *ArtCommand) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+4+len(ac.Data))
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpCommand)
data[10] = 0
data[11] = 14
binary.BigEndian.PutUint16(data[12:14], ac.EstaMan)
dataLength := uint16(len(ac.Data))
if dataLength > 512 {
return nil, errors.New("data length must be less than or equal to 512 bytes")
}
binary.BigEndian.PutUint16(data[14:16], dataLength)
copy(data[16:], ac.Data)
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtCommandUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtCommand
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtCommand{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtCommand: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtCommand{}))
if diff != "" {
t.Fatalf("ArtCommand does not match\n%s", diff)
}
})
}
}
func BenchmarkArtCommandMarshalBinary(b *testing.B) {
data := artnet.ArtCommand{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtCommand: %s", err)
}
}
}
+65
View File
@@ -0,0 +1,65 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type DataRequest uint16
const (
DrPoll DataRequest = 0x0000
DrUrlProduct DataRequest = 0x0001
DrUrlUserGuide DataRequest = 0x0002
DrUrlSupport DataRequest = 0x0003
DrUrlPersUdr DataRequest = 0x0004
DrUrlPersGdtf DataRequest = 0x0005
)
type ArtDataRequest struct {
EstaMan uint16
Oem uint16
Request DataRequest
spare [22]byte
}
func (adr *ArtDataRequest) GetOpCode() uint16 {
return OpDataRequest
}
func (adr *ArtDataRequest) UnmarshalBinary(data []byte) error {
if len(data) < 40 {
return errors.New("ArtDataRequest packet must be at least 40 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 != OpDataRequest {
return errors.New("packet does not have the correct OpCode for an ArtDataRequest packet")
}
offset := 12
adr.EstaMan = binary.BigEndian.Uint16(data[offset : offset+2])
adr.Oem = binary.BigEndian.Uint16(data[offset+2 : offset+4])
adr.Request = DataRequest(binary.BigEndian.Uint16(data[offset+4 : offset+6]))
copy(adr.spare[:], data[offset+6:offset+28])
return nil
}
func (adr *ArtDataRequest) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+28)
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpDataRequest)
data[10] = 0
data[11] = 14
binary.BigEndian.PutUint16(data[12:14], adr.EstaMan)
binary.BigEndian.PutUint16(data[14:16], adr.Oem)
binary.BigEndian.PutUint16(data[16:18], uint16(adr.Request))
copy(data[18:40], adr.spare[:])
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtDataRequestUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtDataRequest
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtDataRequest{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtDataRequest: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtDataRequest{}))
if diff != "" {
t.Fatalf("ArtDataRequest does not match\n%s", diff)
}
})
}
}
func BenchmarkArtDataRequestMarshalBinary(b *testing.B) {
data := artnet.ArtDataRequest{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtDataRequest: %s", err)
}
}
}
+78
View File
@@ -0,0 +1,78 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type DiagPriority uint8
const (
DpLow DiagPriority = 0x10
DpMed DiagPriority = 0x40
DpHigh DiagPriority = 0x80
DpCritical DiagPriority = 0xe0
DpVolatile DiagPriority = 0xf0
)
type ArtDiagData struct {
filler1 uint8
DiagPriority DiagPriority
LogicalPort uint8
filler3 uint8
Data []uint8
}
func (add *ArtDiagData) GetOpCode() uint16 {
return OpDiagData
}
func (add *ArtDiagData) UnmarshalBinary(data []byte) error {
if len(data) < 18 {
return errors.New("ArtDiagData packet must be at least 18 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 != OpDiagData {
return errors.New("packet does not have the correct OpCode for an ArtDiagData packet")
}
offset := 12
add.filler1 = data[offset]
add.DiagPriority = DiagPriority(data[offset+1])
add.LogicalPort = data[offset+2]
add.filler3 = data[offset+3]
dataLength := binary.BigEndian.Uint16(data[offset+4 : offset+6])
if len(data[offset+6:]) < int(dataLength) {
return errors.New("[]byte length not long enough to contain data length specified in packet")
}
add.Data = make([]uint8, dataLength)
copy(add.Data, data[offset+6:offset+6+int(dataLength)])
return nil
}
func (add *ArtDiagData) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+6+len(add.Data))
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpDiagData)
data[10] = 0
data[11] = 14
data[12] = add.filler1
data[13] = uint8(add.DiagPriority)
data[14] = add.LogicalPort
data[15] = add.filler3
dataLength := uint16(len(add.Data))
if dataLength > 512 {
return nil, errors.New("data length must be less than or equal to 512 bytes")
}
binary.BigEndian.PutUint16(data[16:18], dataLength)
copy(data[18:], add.Data)
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtDiagDataUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtDiagData
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtDiagData{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtDiagData: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtDiagData{}))
if diff != "" {
t.Fatalf("ArtDiagData does not match\n%s", diff)
}
})
}
}
func BenchmarkArtDiagDataMarshalBinary(b *testing.B) {
data := artnet.ArtDiagData{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtDiagData: %s", err)
}
}
}
+13 -29
View File
@@ -7,10 +7,6 @@ import (
) )
type ArtDmx struct { type ArtDmx struct {
ID [8]uint8
OpCode uint16
ProtVerHi uint8
ProtVerLo uint8
Sequence uint8 Sequence uint8
Physical uint8 Physical uint8
SubUni uint8 SubUni uint8
@@ -19,19 +15,7 @@ type ArtDmx struct {
} }
func (ad *ArtDmx) GetOpCode() uint16 { func (ad *ArtDmx) GetOpCode() uint16 {
return ad.OpCode return OpDmx
}
func (ad *ArtDmx) GetProtVer() uint16 {
return uint16(ad.ProtVerHi)<<8 + uint16(ad.ProtVerLo)
}
func (ad *ArtDmx) GetID() [8]uint8 {
return ad.ID
}
func (ad *ArtDmx) Length() uint16 {
return uint16(len(ad.Data))
} }
func (ad *ArtDmx) UnmarshalBinary(data []byte) error { func (ad *ArtDmx) UnmarshalBinary(data []byte) error {
@@ -39,15 +23,14 @@ func (ad *ArtDmx) UnmarshalBinary(data []byte) error {
return errors.New("ArtDmx packet must be at least 18 bytes long") return errors.New("ArtDmx packet must be at least 18 bytes long")
} }
copy(ad.ID[:], data[0:8]) if !slices.Equal(ArtNetID[:], data[0:8]) {
if !slices.Equal(ArtNetID[:], ad.ID[:]) {
return errors.New("ID does not match Art-Net ID") return errors.New("ID does not match Art-Net ID")
} }
ad.OpCode = binary.LittleEndian.Uint16(data[8:10]) opCode := binary.LittleEndian.Uint16(data[8:10])
ad.ProtVerHi = data[10] if opCode != OpDmx {
ad.ProtVerLo = data[11] return errors.New("packet does not have the correct OpCode for an ArtDmx packet")
}
offset := 12 offset := 12
@@ -70,16 +53,17 @@ func (ad *ArtDmx) UnmarshalBinary(data []byte) error {
} }
func (ad *ArtDmx) MarshalBinary() ([]byte, error) { func (ad *ArtDmx) MarshalBinary() ([]byte, error) {
data := make([]byte, 8+10+ad.Length()) // TODO(jwetzell): check max data length
copy(data[0:8], ad.ID[:]) data := make([]byte, 12+6+len(ad.Data))
binary.LittleEndian.PutUint16(data[8:10], ad.OpCode) copy(data[0:8], ArtNetID[:])
data[10] = ad.ProtVerHi binary.LittleEndian.PutUint16(data[8:10], OpDmx)
data[11] = ad.ProtVerLo data[10] = 0
data[11] = 14
data[12] = ad.Sequence data[12] = ad.Sequence
data[13] = ad.Physical data[13] = ad.Physical
data[14] = ad.SubUni data[14] = ad.SubUni
data[15] = ad.Net data[15] = ad.Net
binary.BigEndian.PutUint16(data[16:18], ad.Length()) binary.BigEndian.PutUint16(data[16:18], uint16(len(ad.Data)))
copy(data[18:], ad.Data) copy(data[18:], ad.Data)
return data, nil return data, nil
} }
+38 -49
View File
@@ -1,24 +1,23 @@
package artnet_test package artnet_test
import ( import (
"slices"
"testing" "testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go" "github.com/jwetzell/artnet-go"
) )
func TestGoodArtDmx(t *testing.T) { func TestGoodArtDmx(t *testing.T) {
tests := []struct { tests := []struct {
Name string
Data []byte Data []byte
Expected *artnet.ArtDmx Expected *artnet.ArtDmx
}{ }{
{ {
Name: "512 All Zeroes",
Data: []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 237, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Data: []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 237, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Expected: &artnet.ArtDmx{ Expected: &artnet.ArtDmx{
ID: [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpDmx,
ProtVerHi: 0,
ProtVerLo: 14,
Sequence: 237, Sequence: 237,
Physical: 0, Physical: 0,
SubUni: 1, SubUni: 1,
@@ -26,10 +25,32 @@ func TestGoodArtDmx(t *testing.T) {
Data: make([]uint8, 512), Data: make([]uint8, 512),
}, },
}, },
{
Name: "ACT Packet 1",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x50, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtDmx{
Sequence: 0,
Physical: 0,
SubUni: 1,
Net: 0,
Data: make([]uint8, 512),
},
},
{
Name: "ACT Packet 2",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x50, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtDmx{
Sequence: 0,
Physical: 0,
SubUni: 1,
Net: 0,
Data: append([]uint8{0xff, 0x7f}, make([]uint8, 510)...),
},
},
} }
for _, test := range tests { for _, test := range tests {
got := artnet.ArtDmx{} got := &artnet.ArtDmx{}
err := got.UnmarshalBinary(test.Data) err := got.UnmarshalBinary(test.Data)
@@ -37,46 +58,10 @@ func TestGoodArtDmx(t *testing.T) {
t.Fatalf("failed to decode ArtDmx: %s", err) t.Fatalf("failed to decode ArtDmx: %s", err)
} }
if got.OpCode != test.Expected.OpCode { diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtDmx{}))
t.Fatalf("ArtDmx OpCode does not match got: %d expected: %d", got.OpCode, test.Expected.OpCode) if diff != "" {
t.Fatalf("ArtDmx does not match\n%s", diff)
} }
if !slices.Equal(got.ID[:], test.Expected.ID[:]) {
t.Fatalf("ArtDmx ID does not match got: %+v expected: %+v", got.ID, test.Expected.ID)
}
if got.ProtVerHi != test.Expected.ProtVerHi {
t.Fatalf("ArtDmx ProtVerHi does not match got: %d expected: %d", got.ProtVerHi, test.Expected.ProtVerHi)
}
if got.ProtVerLo != test.Expected.ProtVerLo {
t.Fatalf("ArtDmx ProtVerLo does not match got: %d expected: %d", got.ProtVerLo, test.Expected.ProtVerLo)
}
if got.Sequence != test.Expected.Sequence {
t.Fatalf("ArtDmx Sequence does not match got: %d expected: %d", got.Sequence, test.Expected.Sequence)
}
if got.Physical != test.Expected.Physical {
t.Fatalf("ArtDmx Physical does not match got: %d expected: %d", got.Physical, test.Expected.Physical)
}
if got.SubUni != test.Expected.SubUni {
t.Fatalf("ArtDmx SubUni does not match got: %d expected: %d", got.SubUni, test.Expected.SubUni)
}
if got.Net != test.Expected.Net {
t.Fatalf("ArtDmx Net does not match got: %d expected: %d", got.Net, test.Expected.Net)
}
if got.Length() != test.Expected.Length() {
t.Fatalf("ArtDmx Length does not match got: %d expected: %d", got.Length(), test.Expected.Length())
}
if !slices.Equal(got.Data, test.Expected.Data) {
t.Fatalf("ArtDmx Data does not match got: %+v expected: %+v", got.Data, test.Expected.Data)
}
} }
} }
@@ -95,10 +80,6 @@ func BenchmarkArtDmxUnmarshalBinary(b *testing.B) {
func BenchmarkArtDmxMarshalBinary(b *testing.B) { func BenchmarkArtDmxMarshalBinary(b *testing.B) {
data := artnet.ArtDmx{ data := artnet.ArtDmx{
ID: [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpDmx,
ProtVerHi: 0,
ProtVerLo: 14,
Sequence: 237, Sequence: 237,
Physical: 0, Physical: 0,
SubUni: 1, SubUni: 1,
@@ -113,3 +94,11 @@ func BenchmarkArtDmxMarshalBinary(b *testing.B) {
} }
} }
} }
func FuzzArtDmxUnmarshalBinary(f *testing.F) {
f.Add([]byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 237, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
f.Fuzz(func(t *testing.T, data []byte) {
artDmx := artnet.ArtDmx{}
artDmx.UnmarshalBinary(data)
})
}
-4
View File
@@ -23,10 +23,6 @@ func main() {
defer connection.Close() defer connection.Close()
buffer := make([]byte, 1024) buffer := make([]byte, 1024)
if err != nil {
panic(err)
}
for { for {
bytesRead, _, err := connection.ReadFromUDP(buffer) bytesRead, _, err := connection.ReadFromUDP(buffer)
+2
View File
@@ -1,3 +1,5 @@
module github.com/jwetzell/artnet-go module github.com/jwetzell/artnet-go
go 1.25.5 go 1.25.5
require github.com/google/go-cmp v0.7.0
+2
View File
@@ -0,0 +1,2 @@
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+114
View File
@@ -0,0 +1,114 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type ArtIpProg struct {
filler1 uint8
filler2 uint8
Command uint8
filler4 uint8
ProgIpHi uint8
ProgIp2 uint8
ProgIp1 uint8
ProgIpLo uint8
ProgSmHi uint8
ProgSm2 uint8
ProgSm1 uint8
ProgSmLo uint8
ProgPortHi uint8
ProgPortLo uint8
ProgDgHi uint8
ProgDg2 uint8
ProgDg1 uint8
ProgDgLo uint8
spare4 uint8
spare5 uint8
spare6 uint8
spare7 uint8
}
func (aip *ArtIpProg) GetOpCode() uint16 {
return OpIpProg
}
func (aip *ArtIpProg) UnmarshalBinary(data []byte) error {
if len(data) < 34 {
return errors.New("ArtIpProg packet must be at least 18 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 != OpIpProg {
return errors.New("packet does not have the correct OpCode for an ArtIpProg packet")
}
offset := 12
aip.filler1 = data[offset]
aip.filler2 = data[offset+1]
aip.Command = data[offset+2]
aip.filler4 = data[offset+3]
aip.ProgIpHi = data[offset+4]
aip.ProgIp2 = data[offset+5]
aip.ProgIp1 = data[offset+6]
aip.ProgIpLo = data[offset+7]
aip.ProgSmHi = data[offset+8]
aip.ProgSm2 = data[offset+9]
aip.ProgSm1 = data[offset+10]
aip.ProgSmLo = data[offset+11]
aip.ProgPortHi = data[offset+12]
aip.ProgPortLo = data[offset+13]
aip.ProgDgHi = data[offset+14]
aip.ProgDg2 = data[offset+15]
aip.ProgDg1 = data[offset+16]
aip.ProgDgLo = data[offset+17]
aip.spare4 = data[offset+18]
aip.spare5 = data[offset+19]
aip.spare6 = data[offset+20]
aip.spare7 = data[offset+21]
return nil
}
func (aip *ArtIpProg) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+22)
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpIpProg)
data[10] = 0
data[11] = 14
data[12] = aip.filler1
data[13] = aip.filler2
data[14] = aip.Command
data[15] = aip.filler4
data[16] = aip.ProgIpHi
data[17] = aip.ProgIp2
data[18] = aip.ProgIp1
data[19] = aip.ProgIpLo
data[20] = aip.ProgSmHi
data[21] = aip.ProgSm2
data[22] = aip.ProgSm1
data[23] = aip.ProgSmLo
data[24] = aip.ProgPortHi
data[25] = aip.ProgPortLo
data[26] = aip.ProgDgHi
data[27] = aip.ProgDg2
data[28] = aip.ProgDg1
data[29] = aip.ProgDgLo
data[30] = aip.spare4
data[31] = aip.spare5
data[32] = aip.spare6
data[33] = aip.spare7
return data, nil
}
+102
View File
@@ -0,0 +1,102 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtIpProgUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtIpProg
}{
{
Name: "ACT Packet 1",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0xf8, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtIpProg{
Command: 0x00,
ProgIpHi: 0x00,
ProgIp2: 0x00,
ProgIp1: 0x00,
ProgIpLo: 0x00,
ProgSmHi: 0x00,
ProgSm2: 0x00,
ProgSm1: 0x00,
ProgSmLo: 0x00,
ProgPortHi: 0x00,
ProgPortLo: 0x00,
ProgDgHi: 0x00,
ProgDg2: 0x00,
ProgDg1: 0x00,
ProgDgLo: 0x00,
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtIpProg{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtIpProg: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtIpProg{}))
if diff != "" {
t.Fatalf("ArtIpProg does not match\n%s", diff)
}
})
}
}
func BenchmarkArtIpProgUnmarshalBinary(b *testing.B) {
data := []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0xf8, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
for b.Loop() {
got := artnet.ArtIpProg{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtIpProg: %s", err)
}
}
}
func BenchmarkArtIpProgMarshalBinary(b *testing.B) {
data := artnet.ArtIpProg{
Command: 0x00,
ProgIpHi: 0x00,
ProgIp2: 0x00,
ProgIp1: 0x00,
ProgIpLo: 0x00,
ProgSmHi: 0x00,
ProgSm2: 0x00,
ProgSm1: 0x00,
ProgSmLo: 0x00,
ProgPortHi: 0x00,
ProgPortLo: 0x00,
ProgDgHi: 0x00,
ProgDg2: 0x00,
ProgDg1: 0x00,
ProgDgLo: 0x00,
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtIpProg: %s", err)
}
}
}
func FuzzArtIpProgUnmarshalBinary(f *testing.F) {
f.Add([]byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0xf8, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
f.Fuzz(func(t *testing.T, data []byte) {
artIpProg := artnet.ArtIpProg{}
artIpProg.UnmarshalBinary(data)
})
}
+115
View File
@@ -0,0 +1,115 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type ArtIpProgReply struct {
filler1 uint8
filler2 uint8
filler3 uint8
filler4 uint8
ProgIpHi uint8
ProgIp2 uint8
ProgIp1 uint8
ProgIpLo uint8
ProgSmHi uint8
ProgSm2 uint8
ProgSm1 uint8
ProgSmLo uint8
ProgPortHi uint8
ProgPortLo uint8
Status uint8
spare2 uint8
ProgDgHi uint8
ProgDg2 uint8
ProgDg1 uint8
ProgDgLo uint8
spare7 uint8
spare8 uint8
}
func (aipr *ArtIpProgReply) GetOpCode() uint16 {
return OpIpProgReply
}
func (aipr *ArtIpProgReply) UnmarshalBinary(data []byte) error {
if len(data) < 34 {
return errors.New("ArtIpProgReply packet must be at least 18 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 != OpIpProgReply {
return errors.New("packet does not have the correct OpCode for an ArtIpProgReply packet")
}
offset := 12
aipr.filler1 = data[offset]
aipr.filler2 = data[offset+1]
aipr.filler3 = data[offset+2]
aipr.filler4 = data[offset+3]
aipr.ProgIpHi = data[offset+4]
aipr.ProgIp2 = data[offset+5]
aipr.ProgIp1 = data[offset+6]
aipr.ProgIpLo = data[offset+7]
aipr.ProgSmHi = data[offset+8]
aipr.ProgSm2 = data[offset+9]
aipr.ProgSm1 = data[offset+10]
aipr.ProgSmLo = data[offset+11]
aipr.ProgPortHi = data[offset+12]
aipr.ProgPortLo = data[offset+13]
aipr.Status = data[offset+14]
aipr.spare2 = data[offset+15]
aipr.ProgDgHi = data[offset+16]
aipr.ProgDg2 = data[offset+17]
aipr.ProgDg1 = data[offset+18]
aipr.ProgDgLo = data[offset+19]
aipr.spare7 = data[offset+20]
aipr.spare8 = data[offset+21]
return nil
}
func (aipr *ArtIpProgReply) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+22)
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpIpProgReply)
data[10] = 0
data[11] = 14
data[12] = aipr.filler1
data[13] = aipr.filler2
data[14] = aipr.filler3
data[15] = aipr.filler4
data[16] = aipr.ProgIpHi
data[17] = aipr.ProgIp2
data[18] = aipr.ProgIp1
data[19] = aipr.ProgIpLo
data[20] = aipr.ProgSmHi
data[21] = aipr.ProgSm2
data[22] = aipr.ProgSm1
data[23] = aipr.ProgSmLo
data[24] = aipr.ProgPortHi
data[25] = aipr.ProgPortLo
data[26] = aipr.Status
data[27] = aipr.spare2
data[28] = aipr.ProgDgHi
data[29] = aipr.ProgDg2
data[30] = aipr.ProgDg1
data[31] = aipr.ProgDgLo
data[32] = aipr.spare7
data[33] = aipr.spare8
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtIpProgReplyUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtIpProgReply
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtIpProgReply{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtIpProgReply: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtIpProgReply{}))
if diff != "" {
t.Fatalf("ArtIpProgReply does not match\n%s", diff)
}
})
}
}
func BenchmarkArtIpProgReplyMarshalBinary(b *testing.B) {
data := artnet.ArtIpProgReply{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtIpProgReply: %s", err)
}
}
}
+69
View File
@@ -0,0 +1,69 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type ArtNzs struct {
Sequence uint8
StartCode uint8
SubUni uint8
Net uint8
Data []uint8
}
func (an *ArtNzs) GetOpCode() uint16 {
return OpNzs
}
func (an *ArtNzs) UnmarshalBinary(data []byte) error {
if len(data) < 18 {
return errors.New("ArtNzs packet must be at least 18 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 != OpNzs {
return errors.New("packet does not have the correct OpCode for an ArtNzs packet")
}
offset := 12
an.Sequence = data[offset]
an.StartCode = data[offset+1]
an.SubUni = data[offset+2]
an.Net = data[offset+3]
dataLength := int(binary.BigEndian.Uint16(data[offset+4 : offset+6]))
if len(data[offset+6:]) < dataLength {
return errors.New("[]byte length not long enough to contain data length specified in packet")
}
an.Data = make([]uint8, dataLength)
copy(an.Data, data[offset+6:offset+6+dataLength])
return nil
}
func (an *ArtNzs) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+6+len(an.Data))
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpNzs)
data[10] = 0
data[11] = 14
data[12] = an.Sequence
data[13] = an.StartCode
data[14] = an.SubUni
data[15] = an.Net
dataLength := uint16(len(an.Data))
if dataLength > 512 {
return nil, errors.New("data length must be less than or equal to 512 bytes")
}
binary.BigEndian.PutUint16(data[16:18], dataLength)
copy(data[18:], an.Data)
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtNzsUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtNzs
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtNzs{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtNzs: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtNzs{}))
if diff != "" {
t.Fatalf("ArtNzs does not match\n%s", diff)
}
})
}
}
func BenchmarkArtNzsMarshalBinary(b *testing.B) {
data := artnet.ArtNzs{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtNzs: %s", err)
}
}
}
-2
View File
@@ -8,6 +8,4 @@ type ArtNetPacket interface {
encoding.BinaryUnmarshaler encoding.BinaryUnmarshaler
encoding.BinaryMarshaler encoding.BinaryMarshaler
GetOpCode() uint16 GetOpCode() uint16
GetProtVer() uint16
GetID() [8]uint8
} }
+33 -34
View File
@@ -7,32 +7,17 @@ import (
) )
type ArtPoll struct { type ArtPoll struct {
ID [8]uint8
OpCode uint16
ProtVerHi uint8
ProtVerLo uint8
Flags uint8 Flags uint8
DiagPriority uint8 DiagPriority uint8
AddressTopHi uint8 // TODO(jwetzell): support extended poll fields
AddressTopLo uint8 TargetPortAddressTop uint16
AddressBottomHi uint8 TargetPortAddressBottom uint16
AddressBottomLo uint8 EstaMan uint16
EstaManHi uint8 Oem uint16
EstaManLo uint8
OemHi uint8
OemLo uint8
} }
func (ap *ArtPoll) GetOpCode() uint16 { func (ap *ArtPoll) GetOpCode() uint16 {
return ap.OpCode return OpPoll
}
func (ap *ArtPoll) GetProtVer() uint16 {
return uint16(ap.ProtVerHi)<<8 + uint16(ap.ProtVerLo)
}
func (ap *ArtPoll) GetID() [8]uint8 {
return ap.ID
} }
func (ap *ArtPoll) UnmarshalBinary(data []byte) error { func (ap *ArtPoll) UnmarshalBinary(data []byte) error {
@@ -41,31 +26,45 @@ func (ap *ArtPoll) UnmarshalBinary(data []byte) error {
return errors.New("ArtPoll packet must be at least 14 bytes long") return errors.New("ArtPoll packet must be at least 14 bytes long")
} }
copy(ap.ID[:], data[0:8]) if !slices.Equal(ArtNetID[:], data[0:8]) {
if !slices.Equal(ArtNetID[:], ap.ID[:]) {
return errors.New("ID does not match Art-Net ID") return errors.New("ID does not match Art-Net ID")
} }
ap.OpCode = binary.LittleEndian.Uint16(data[8:10]) opCode := binary.LittleEndian.Uint16(data[8:10])
ap.ProtVerHi = data[10] if opCode != OpPoll {
ap.ProtVerLo = data[11] return errors.New("packet does not have the correct OpCode for an ArtPoll packet")
}
offset := 12 offset := 12
ap.Flags = data[offset] ap.Flags = data[offset]
ap.DiagPriority = data[offset+1] ap.DiagPriority = data[offset+1]
//TODO(jwetzell): unpack extended poll fields
if len(data) >= 16 {
ap.TargetPortAddressTop = binary.BigEndian.Uint16(data[14:16])
}
if len(data) >= 18 {
ap.TargetPortAddressBottom = binary.BigEndian.Uint16(data[16:18])
}
if len(data) >= 20 {
ap.EstaMan = binary.BigEndian.Uint16(data[18:20])
}
if len(data) >= 22 {
ap.Oem = binary.BigEndian.Uint16(data[20:22])
}
return nil return nil
} }
func (ap *ArtPoll) MarshalBinary() ([]byte, error) { func (ap *ArtPoll) MarshalBinary() ([]byte, error) {
data := make([]byte, 8+6) data := make([]byte, 12+10)
copy(data[0:8], ap.ID[:]) copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], ap.OpCode) binary.LittleEndian.PutUint16(data[8:10], OpPoll)
data[10] = ap.ProtVerHi data[10] = 0
data[11] = ap.ProtVerLo data[11] = 14
data[12] = ap.Flags data[12] = ap.Flags
data[13] = ap.DiagPriority data[13] = ap.DiagPriority
//TODO(jwetzell): pack extended poll fields binary.BigEndian.PutUint16(data[14:16], ap.TargetPortAddressTop)
binary.BigEndian.PutUint16(data[16:18], ap.TargetPortAddressBottom)
binary.BigEndian.PutUint16(data[18:20], ap.EstaMan)
binary.BigEndian.PutUint16(data[20:22], ap.Oem)
return data, nil return data, nil
} }
+257
View File
@@ -0,0 +1,257 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtPollUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtPoll
}{
{
Name: "ACT Packet 1",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
},
},
{
Name: "ACT Packet 2",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
},
},
{
Name: "ACT Packet 3",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
},
},
{
Name: "ACT Packet 4",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
},
},
{
Name: "ACT Packet 5",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
},
},
{
Name: "ACT Packet 6",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
},
},
{
Name: "ACT Packet 7",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
EstaMan: 0x5379,
},
},
{
Name: "ACT Packet 8",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
EstaMan: 0x5379,
},
},
{
Name: "ACT Packet 9",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69},
Expected: &artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
EstaMan: 0x5379,
Oem: 0x2269,
},
},
// TODO(jwetzell): uncomment when extend field parsing is done
// {
// Name: "ACT Packet 10",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
// {
// Name: "ACT Packet 11",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
// {
// Name: "ACT Packet 12",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00, 0x00, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
// {
// Name: "ACT Packet 13",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00, 0x00, 0x00, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
// {
// Name: "ACT Packet 14",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
// {
// Name: "ACT Packet 15",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
// {
// Name: "ACT Packet 16",
// Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x21, 0x0a, 0x00, 0x00, 0x3e, 0x36, 0x19, 0x07, 0x33, 0x00, 0x06, 0x22, 0x69, 0x00, 0x00, 0x79, 0x53, 0x41, 0x43, 0x54, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x54, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// Expected: &artnet.ArtPoll{
// Flags: 0x00,
// DiagPriority: 0x00,
// TargetPortAddressTop: 0x7fff,
// TargetPortAddressBottom: 0x0000,
// EstaMan: 0x5379,
// Oem: 0x2269,
// },
// },
{
Name: "ACT Packet 17",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x06, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69},
Expected: &artnet.ArtPoll{
Flags: 0x06,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
EstaMan: 0x5379,
Oem: 0x2269,
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtPoll{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtPoll: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtPoll{}))
if diff != "" {
t.Fatalf("ArtPoll does not match\n%s", diff)
}
})
}
}
func BenchmarkArtPollUnmarshalBinary(b *testing.B) {
data := []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69}
for b.Loop() {
got := artnet.ArtPoll{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtPoll: %s", err)
}
}
}
func BenchmarkArtPollMarshalBinary(b *testing.B) {
data := artnet.ArtPoll{
Flags: 0x00,
DiagPriority: 0x00,
TargetPortAddressTop: 0x7fff,
TargetPortAddressBottom: 0x0000,
EstaMan: 0x5379,
Oem: 0x2269,
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtPoll: %s", err)
}
}
}
func FuzzArtPollUnmarshalBinary(f *testing.F) {
f.Add([]byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x53, 0x79, 0x22, 0x69})
f.Fuzz(func(t *testing.T, data []byte) {
artPoll := artnet.ArtPoll{}
artPoll.UnmarshalBinary(data)
})
}
+153
View File
@@ -0,0 +1,153 @@
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
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtPollReplyUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtPollReply
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtPollReply{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtPollReply: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtPollReply{}))
if diff != "" {
t.Fatalf("ArtPollReply does not match\n%s", diff)
}
})
}
}
func BenchmarkArtPollReplyMarshalBinary(b *testing.B) {
data := artnet.ArtPollReply{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtPollReply: %s", err)
}
}
}
+48
View File
@@ -0,0 +1,48 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type ArtSync struct {
Aux1 uint8
Aux2 uint8
}
func (as *ArtSync) GetOpCode() uint16 {
return OpSync
}
func (as *ArtSync) UnmarshalBinary(data []byte) error {
if len(data) < 14 {
return errors.New("ArtSync packet must be at least 14 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 != OpSync {
return errors.New("packet does not have the correct OpCode for an ArtSync packet")
}
offset := 12
as.Aux1 = data[offset]
as.Aux2 = data[offset+1]
return nil
}
func (as *ArtSync) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+2)
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpSync)
data[10] = 0
data[11] = 14
data[12] = as.Aux1
data[13] = as.Aux2
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtSyncUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtSync
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtSync{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtSync: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtSync{}))
if diff != "" {
t.Fatalf("ArtSync does not match\n%s", diff)
}
})
}
}
func BenchmarkArtSyncMarshalBinary(b *testing.B) {
data := artnet.ArtSync{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtSync: %s", err)
}
}
}
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("Art-Net\x00000000")
+15 -28
View File
@@ -7,11 +7,7 @@ import (
) )
type ArtTimeCode struct { type ArtTimeCode struct {
ID [8]uint8 filler1 uint8
OpCode uint16
ProtVerHi uint8
ProtVerLo uint8
Filler1 uint8
StreamId uint8 StreamId uint8
Frames uint8 Frames uint8
Seconds uint8 Seconds uint8
@@ -21,34 +17,25 @@ type ArtTimeCode struct {
} }
func (atc *ArtTimeCode) GetOpCode() uint16 { func (atc *ArtTimeCode) GetOpCode() uint16 {
return atc.OpCode return OpTimeCode
}
func (atc *ArtTimeCode) GetProtVer() uint16 {
return uint16(atc.ProtVerHi)<<8 + uint16(atc.ProtVerLo)
}
func (atc *ArtTimeCode) GetID() [8]uint8 {
return atc.ID
} }
func (atc *ArtTimeCode) UnmarshalBinary(data []byte) error { func (atc *ArtTimeCode) UnmarshalBinary(data []byte) error {
if len(data) < 14 { if len(data) < 19 {
return errors.New("ArtTimeCode packet must be at least 14 bytes long") return errors.New("ArtTimeCode packet must be at least 14 bytes long")
} }
copy(atc.ID[:], data[0:8]) if !slices.Equal(ArtNetID[:], data[0:8]) {
if !slices.Equal(ArtNetID[:], atc.ID[:]) {
return errors.New("ID does not match Art-Net ID") return errors.New("ID does not match Art-Net ID")
} }
atc.OpCode = binary.LittleEndian.Uint16(data[8:10]) opCode := binary.LittleEndian.Uint16(data[8:10])
atc.ProtVerHi = data[10] if opCode != OpTimeCode {
atc.ProtVerLo = data[11] return errors.New("packet does not have the correct OpCode for an ArtTimeCode packet")
}
offset := 12 offset := 12
atc.Filler1 = data[offset] atc.filler1 = data[offset]
atc.StreamId = data[offset+1] atc.StreamId = data[offset+1]
atc.Frames = data[offset+2] atc.Frames = data[offset+2]
atc.Seconds = data[offset+3] atc.Seconds = data[offset+3]
@@ -59,13 +46,13 @@ func (atc *ArtTimeCode) UnmarshalBinary(data []byte) error {
} }
func (atc *ArtTimeCode) MarshalBinary() ([]byte, error) { func (atc *ArtTimeCode) MarshalBinary() ([]byte, error) {
data := make([]byte, 8+11) data := make([]byte, 12+7)
copy(data[0:8], atc.ID[:]) copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], atc.OpCode) binary.LittleEndian.PutUint16(data[8:10], OpTimeCode)
data[10] = atc.ProtVerHi data[10] = 0
data[11] = atc.ProtVerLo data[11] = 14
offset := 12 offset := 12
data[offset] = atc.Filler1 data[offset] = atc.filler1
data[offset+1] = atc.StreamId data[offset+1] = atc.StreamId
data[offset+2] = atc.Frames data[offset+2] = atc.Frames
data[offset+3] = atc.Seconds data[offset+3] = atc.Seconds
+19 -57
View File
@@ -1,25 +1,23 @@
package artnet_test package artnet_test
import ( import (
"slices"
"testing" "testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go" "github.com/jwetzell/artnet-go"
) )
func TestGoodArtTimeCode(t *testing.T) { func TestGoodArtTimeCodeUnmarshal(t *testing.T) {
tests := []struct { tests := []struct {
Name string
Data []byte Data []byte
Expected *artnet.ArtTimeCode Expected *artnet.ArtTimeCode
}{ }{
{ {
Name: "Basic timecode",
Data: []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 151, 0, 14, 0, 0, 11, 17, 3, 0, 0}, Data: []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 151, 0, 14, 0, 0, 11, 17, 3, 0, 0},
Expected: &artnet.ArtTimeCode{ Expected: &artnet.ArtTimeCode{
ID: [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpTimeCode,
ProtVerHi: 0,
ProtVerLo: 14,
Filler1: 0,
StreamId: 0, StreamId: 0,
Frames: 11, Frames: 11,
Seconds: 17, Seconds: 17,
@@ -31,58 +29,19 @@ func TestGoodArtTimeCode(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
got := artnet.ArtTimeCode{} t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtTimeCode{}
err := got.UnmarshalBinary(test.Data) err := got.UnmarshalBinary(test.Data)
if err != nil { if err != nil {
t.Fatalf("failed to decode ArtTimeCode: %s", err) t.Fatalf("failed to decode ArtTimeCode: %s", err)
} }
if got.OpCode != test.Expected.OpCode { diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtTimeCode{}))
t.Fatalf("ArtTimeCode OpCode does not match got: %d expected: %d", got.OpCode, test.Expected.OpCode) if diff != "" {
t.Fatalf("ArtTimeCode does not match\n%s", diff)
} }
})
if !slices.Equal(got.ID[:], test.Expected.ID[:]) {
t.Fatalf("ArtTimeCode ID does not match got: %+v expected: %+v", got.ID, test.Expected.ID)
}
if got.Filler1 != test.Expected.Filler1 {
t.Fatalf("ArtTimeCode Filler1 does not match got: %d expected: %d", got.Filler1, test.Expected.Filler1)
}
if got.StreamId != test.Expected.StreamId {
t.Fatalf("ArtTimeCode StreamId does not match got: %d expected: %d", got.StreamId, test.Expected.StreamId)
}
if got.Frames != test.Expected.Frames {
t.Fatalf("ArtTimeCode Frames does not match got: %d expected: %d", got.Frames, test.Expected.Frames)
}
if got.Seconds != test.Expected.Seconds {
t.Fatalf("ArtTimeCode Seconds does not match got: %d expected: %d", got.Seconds, test.Expected.Seconds)
}
if got.Minutes != test.Expected.Minutes {
t.Fatalf("ArtTimeCode Minutes does not match got: %d expected: %d", got.Minutes, test.Expected.Minutes)
}
if got.Hours != test.Expected.Hours {
t.Fatalf("ArtTimeCode Hours does not match got: %d expected: %d", got.Hours, test.Expected.Hours)
}
if got.Type != test.Expected.Type {
t.Fatalf("ArtTimeCode Type does not match got: %d expected: %d", got.Type, test.Expected.Type)
}
if got.ProtVerHi != test.Expected.ProtVerHi {
t.Fatalf("ArtTimeCode ProtVerHi does not match got: %d expected: %d", got.ProtVerHi, test.Expected.ProtVerHi)
}
if got.ProtVerLo != test.Expected.ProtVerLo {
t.Fatalf("ArtTimeCode ProtVerLo does not match got: %d expected: %d", got.ProtVerLo, test.Expected.ProtVerLo)
}
} }
} }
@@ -101,11 +60,6 @@ func BenchmarkArtTimeCodeUnmarshalBinary(b *testing.B) {
func BenchmarkArtTimeCodeMarshalBinary(b *testing.B) { func BenchmarkArtTimeCodeMarshalBinary(b *testing.B) {
data := artnet.ArtTimeCode{ data := artnet.ArtTimeCode{
ID: [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpTimeCode,
ProtVerHi: 0,
ProtVerLo: 14,
Filler1: 0,
StreamId: 0, StreamId: 0,
Frames: 11, Frames: 11,
Seconds: 17, Seconds: 17,
@@ -121,3 +75,11 @@ func BenchmarkArtTimeCodeMarshalBinary(b *testing.B) {
} }
} }
} }
func FuzzArtTimeCodeUnmarshalBinary(f *testing.F) {
f.Add([]byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 151, 0, 14, 0, 0, 11, 17, 3, 0, 0})
f.Fuzz(func(t *testing.T, data []byte) {
artTimeCode := artnet.ArtTimeCode{}
artTimeCode.UnmarshalBinary(data)
})
}
+88
View File
@@ -0,0 +1,88 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type TodControlCommand uint8
const (
AtcNone TodControlCommand = 0x00
AtcFlush TodControlCommand = 0x01
AtcEnd TodControlCommand = 0x02
AtcIncOn TodControlCommand = 0x03
AtcIncOff TodControlCommand = 0x04
)
type ArtTodControl struct {
filler1 uint8
filler2 uint8
spare1 uint8
spare2 uint8
spare3 uint8
spare4 uint8
spare5 uint8
spare6 uint8
spare7 uint8
Net uint8
Command TodControlCommand
Address uint8
}
func (adr *ArtTodControl) GetOpCode() uint16 {
return OpTodControl
}
func (adr *ArtTodControl) UnmarshalBinary(data []byte) error {
if len(data) < 24 {
return errors.New("ArtTodControl packet must be at least 24 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 != OpTodControl {
return errors.New("packet does not have the correct OpCode for an ArtTodControl packet")
}
offset := 12
adr.filler1 = data[offset]
adr.filler2 = data[offset+1]
adr.spare1 = data[offset+2]
adr.spare2 = data[offset+3]
adr.spare3 = data[offset+4]
adr.spare4 = data[offset+5]
adr.spare5 = data[offset+6]
adr.spare6 = data[offset+7]
adr.spare7 = data[offset+8]
adr.Net = data[offset+9]
adr.Command = TodControlCommand(data[offset+10])
adr.Address = data[offset+11]
return nil
}
func (adr *ArtTodControl) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+12)
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpTodControl)
data[10] = 0
data[11] = 14
data[12] = adr.filler1
data[13] = adr.filler2
data[14] = adr.spare1
data[15] = adr.spare2
data[16] = adr.spare3
data[17] = adr.spare4
data[18] = adr.spare5
data[19] = adr.spare6
data[20] = adr.spare7
data[21] = adr.Net
data[22] = uint8(adr.Command)
data[23] = adr.Address
return data, nil
}
+78
View File
@@ -0,0 +1,78 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtTodControlUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtTodControl
}{
{
Name: "ACT Packet 1",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x82, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
Expected: &artnet.ArtTodControl{
Net: 0x00,
Command: artnet.AtcFlush,
Address: 0x00,
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtTodControl{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtTodControl: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtTodControl{}))
if diff != "" {
t.Fatalf("ArtTodControl does not match\n%s", diff)
}
})
}
}
func BenchmarkArtTodControlUnmarshalBinary(b *testing.B) {
data := []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x82, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}
for b.Loop() {
got := artnet.ArtTodControl{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtTodControl: %s", err)
}
}
}
func BenchmarkArtTodControlMarshalBinary(b *testing.B) {
data := artnet.ArtTodControl{
Net: 0x00,
Command: artnet.AtcFlush,
Address: 0x00,
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtTodControl: %s", err)
}
}
}
func FuzzArtTodControlUnmarshalBinary(f *testing.F) {
f.Add([]byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x82, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
f.Fuzz(func(t *testing.T, data []byte) {
artTodControl := artnet.ArtTodControl{}
artTodControl.UnmarshalBinary(data)
})
}
+93
View File
@@ -0,0 +1,93 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type TodRequestCommand uint8
const (
TodFull TodRequestCommand = 0x00
)
type ArtTodRequest struct {
filler1 uint8
filler2 uint8
spare1 uint8
spare2 uint8
spare3 uint8
spare4 uint8
spare5 uint8
spare6 uint8
spare7 uint8
Net uint8
Command TodRequestCommand
Address []uint8
}
func (adr *ArtTodRequest) GetOpCode() uint16 {
return OpTodRequest
}
func (adr *ArtTodRequest) UnmarshalBinary(data []byte) error {
if len(data) < 32 {
return errors.New("ArtTodRequest packet must be at least 32 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 != OpTodRequest {
return errors.New("packet does not have the correct OpCode for an ArtTodRequest packet")
}
offset := 12
adr.filler1 = data[offset]
adr.filler2 = data[offset+1]
adr.spare1 = data[offset+2]
adr.spare2 = data[offset+3]
adr.spare3 = data[offset+4]
adr.spare4 = data[offset+5]
adr.spare5 = data[offset+6]
adr.spare6 = data[offset+7]
adr.spare7 = data[offset+8]
adr.Net = data[offset+9]
adr.Command = TodRequestCommand(data[offset+10])
addCount := data[offset+11]
adr.Address = make([]uint8, addCount)
if len(data[offset+12:]) < int(addCount) {
return errors.New("[]byte length not long enough to contain address length specified in packet")
}
copy(adr.Address, data[offset+12:offset+12+int(addCount)])
return nil
}
func (adr *ArtTodRequest) MarshalBinary() ([]byte, error) {
if len(adr.Address) > 32 {
return nil, errors.New("address count must not be greater than 32")
}
data := make([]byte, 12+12+len(adr.Address))
copy(data[0:8], ArtNetID[:])
binary.LittleEndian.PutUint16(data[8:10], OpTodRequest)
data[10] = 0
data[11] = 14
data[12] = adr.filler1
data[13] = adr.filler2
data[14] = adr.spare1
data[15] = adr.spare2
data[16] = adr.spare3
data[17] = adr.spare4
data[18] = adr.spare5
data[19] = adr.spare6
data[20] = adr.spare7
data[21] = adr.Net
data[22] = uint8(adr.Command)
data[23] = uint8(len(adr.Address))
copy(data[24:], adr.Address)
return data, nil
}
+231
View File
@@ -0,0 +1,231 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtTodRequestUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtTodRequest
}{
{
Name: "ACT Packet 1",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x00},
},
},
{
Name: "ACT Packet 2",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 3",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 4",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 5",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 6",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 7",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 8",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 9",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 10",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 11",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 12",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 13",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 14",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 15",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 16",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 17",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
{
Name: "ACT Packet 18",
Data: []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Expected: &artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtTodRequest{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtTodRequest: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtTodRequest{}))
if diff != "" {
t.Fatalf("ArtTodRequest does not match\n%s", diff)
}
})
}
}
func BenchmarkArtTodRequestUnmarshalBinary(b *testing.B) {
data := []byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
for b.Loop() {
got := artnet.ArtTodRequest{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtTodRequest: %s", err)
}
}
}
func BenchmarkArtTodRequestMarshalBinary(b *testing.B) {
data := artnet.ArtTodRequest{
Command: artnet.TodFull,
Net: 0x00,
Address: []uint8{0x10},
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtTodRequest: %s", err)
}
}
}
func FuzzArtTodRequestUnmarshalBinary(f *testing.F) {
f.Add([]byte{0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
f.Fuzz(func(t *testing.T, data []byte) {
artTodRequest := artnet.ArtTodRequest{}
artTodRequest.UnmarshalBinary(data)
})
}
+78
View File
@@ -0,0 +1,78 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type Key uint8
const (
KeyASCII Key = 0
KeyMacro Key = 1
KeySoft Key = 2
KeyShow Key = 3
)
type ArtTrigger struct {
id [8]uint8
opCode uint16
ProtVerHi uint8
ProtVerLo uint8
filler1 uint8
filler2 uint8
Oem uint16
Key Key
SubKey uint8
Data []uint8
}
func (at *ArtTrigger) GetOpCode() uint16 {
return OpTrigger
}
func (at *ArtTrigger) UnmarshalBinary(data []byte) error {
if len(data) < 18 {
return errors.New("ArtTrigger packet must be at least 18 bytes long")
}
copy(at.id[:], data[0:8])
if !slices.Equal(ArtNetID[:], at.id[:]) {
return errors.New("ID does not match Art-Net ID")
}
at.opCode = binary.LittleEndian.Uint16(data[8:10])
if at.opCode != OpTrigger {
return errors.New("packet does not have the correct OpCode for an ArtTrigger packet")
}
at.ProtVerHi = data[10]
at.ProtVerLo = data[11]
offset := 12
at.filler1 = data[offset]
at.filler2 = data[offset+1]
at.Oem = binary.LittleEndian.Uint16(data[offset+2 : offset+4])
at.Key = Key(data[offset+4])
at.SubKey = data[offset+5]
at.Data = make([]uint8, len(data[offset+6:]))
copy(at.Data, data[offset+6:])
return nil
}
func (at *ArtTrigger) MarshalBinary() ([]byte, error) {
data := make([]byte, 12+6)
copy(data[0:8], at.id[:])
binary.LittleEndian.PutUint16(data[8:10], at.opCode)
data[10] = at.ProtVerHi
data[11] = at.ProtVerLo
data[12] = at.filler1
data[13] = at.filler2
binary.LittleEndian.PutUint16(data[14:16], at.Oem)
data[16] = uint8(at.Key)
data[17] = at.SubKey
data = append(data, at.Data...)
return data, nil
}
+43
View File
@@ -0,0 +1,43 @@
package artnet_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtTriggerUnmarshal(t *testing.T) {
tests := []struct {
Name string
Data []byte
Expected *artnet.ArtTrigger
}{}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
got := &artnet.ArtTrigger{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to Unmarshal ArtTrigger: %s", err)
}
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtTrigger{}))
if diff != "" {
t.Fatalf("ArtTrigger does not match\n%s", diff)
}
})
}
}
func BenchmarkArtTriggerMarshalBinary(b *testing.B) {
data := artnet.ArtTrigger{}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtTrigger: %s", err)
}
}
}