mirror of
https://github.com/jwetzell/artnet-go.git
synced 2026-08-20 22:28:59 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bd47dddb58 | |||
| 968ad64521 | |||
| 6630584ae7 | |||
| 37ca97c5ab | |||
| 07ff9daf88 | |||
| c179b8fc26 | |||
| b71986eaba | |||
| b7d8e8dddd | |||
| d8da54172e | |||
| 8f21c3968e | |||
| 91206f6037 | |||
| c44996dd32 | |||
| c0701537b6 | |||
| f3b6a6ef1b | |||
| 3680bfb820 | |||
| 92b37e0b19 | |||
| 16f045e8fe | |||
| 56614027df | |||
| 11739370c4 | |||
| 79ecda6f87 | |||
| eec90ba0c1 | |||
| 5869f308a3 | |||
| 06ec1acea1 | |||
| 460ffe7bda | |||
| 572fa39c16 | |||
| 9546018fb7 | |||
| 76189580db | |||
| 225fb8b79a | |||
| 207a18d18e | |||
| 2cb6487036 | |||
| 4efa58ee25 |
@@ -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 .
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
})
|
||||
}
|
||||
@@ -65,6 +65,46 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
|
||||
}
|
||||
|
||||
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:
|
||||
artDmx := ArtDmx{}
|
||||
|
||||
@@ -75,6 +115,76 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
|
||||
}
|
||||
|
||||
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:
|
||||
artTimeCode := ArtTimeCode{}
|
||||
|
||||
@@ -85,6 +195,16 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
|
||||
}
|
||||
|
||||
return &artTimeCode, nil
|
||||
case OpTrigger:
|
||||
artTrigger := ArtTrigger{}
|
||||
|
||||
err := artTrigger.UnmarshalBinary(bytes)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &artTrigger, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled opcode: %#x", opCode)
|
||||
}
|
||||
|
||||
+67
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,31 +7,15 @@ import (
|
||||
)
|
||||
|
||||
type ArtDmx struct {
|
||||
ID [8]uint8
|
||||
OpCode uint16
|
||||
ProtVerHi uint8
|
||||
ProtVerLo uint8
|
||||
Sequence uint8
|
||||
Physical uint8
|
||||
SubUni uint8
|
||||
Net uint8
|
||||
Data []uint8
|
||||
Sequence uint8
|
||||
Physical uint8
|
||||
SubUni uint8
|
||||
Net uint8
|
||||
Data []uint8
|
||||
}
|
||||
|
||||
func (ad *ArtDmx) GetOpCode() uint16 {
|
||||
return ad.OpCode
|
||||
}
|
||||
|
||||
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))
|
||||
return OpDmx
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
copy(ad.ID[:], data[0:8])
|
||||
|
||||
if !slices.Equal(ArtNetID[:], ad.ID[:]) {
|
||||
if !slices.Equal(ArtNetID[:], data[0:8]) {
|
||||
return errors.New("ID does not match Art-Net ID")
|
||||
}
|
||||
|
||||
ad.OpCode = binary.LittleEndian.Uint16(data[8:10])
|
||||
ad.ProtVerHi = data[10]
|
||||
ad.ProtVerLo = data[11]
|
||||
opCode := binary.LittleEndian.Uint16(data[8:10])
|
||||
if opCode != OpDmx {
|
||||
return errors.New("packet does not have the correct OpCode for an ArtDmx packet")
|
||||
}
|
||||
|
||||
offset := 12
|
||||
|
||||
@@ -70,16 +53,17 @@ func (ad *ArtDmx) UnmarshalBinary(data []byte) error {
|
||||
}
|
||||
|
||||
func (ad *ArtDmx) MarshalBinary() ([]byte, error) {
|
||||
data := make([]byte, 8+10+ad.Length())
|
||||
copy(data[0:8], ad.ID[:])
|
||||
binary.LittleEndian.PutUint16(data[8:10], ad.OpCode)
|
||||
data[10] = ad.ProtVerHi
|
||||
data[11] = ad.ProtVerLo
|
||||
// TODO(jwetzell): check max data length
|
||||
data := make([]byte, 12+6+len(ad.Data))
|
||||
copy(data[0:8], ArtNetID[:])
|
||||
binary.LittleEndian.PutUint16(data[8:10], OpDmx)
|
||||
data[10] = 0
|
||||
data[11] = 14
|
||||
data[12] = ad.Sequence
|
||||
data[13] = ad.Physical
|
||||
data[14] = ad.SubUni
|
||||
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)
|
||||
return data, nil
|
||||
}
|
||||
|
||||
+48
-59
@@ -1,35 +1,56 @@
|
||||
package artnet_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/jwetzell/artnet-go"
|
||||
)
|
||||
|
||||
func TestGoodArtDmx(t *testing.T) {
|
||||
tests := []struct {
|
||||
Name string
|
||||
Data []byte
|
||||
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},
|
||||
Expected: &artnet.ArtDmx{
|
||||
ID: [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpDmx,
|
||||
ProtVerHi: 0,
|
||||
ProtVerLo: 14,
|
||||
Sequence: 237,
|
||||
Physical: 0,
|
||||
SubUni: 1,
|
||||
Net: 0,
|
||||
Data: make([]uint8, 512),
|
||||
Sequence: 237,
|
||||
Physical: 0,
|
||||
SubUni: 1,
|
||||
Net: 0,
|
||||
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 {
|
||||
got := artnet.ArtDmx{}
|
||||
got := &artnet.ArtDmx{}
|
||||
|
||||
err := got.UnmarshalBinary(test.Data)
|
||||
|
||||
@@ -37,46 +58,10 @@ func TestGoodArtDmx(t *testing.T) {
|
||||
t.Fatalf("failed to decode ArtDmx: %s", err)
|
||||
}
|
||||
|
||||
if got.OpCode != test.Expected.OpCode {
|
||||
t.Fatalf("ArtDmx OpCode does not match got: %d expected: %d", got.OpCode, test.Expected.OpCode)
|
||||
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtDmx{}))
|
||||
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,15 +80,11 @@ func BenchmarkArtDmxUnmarshalBinary(b *testing.B) {
|
||||
|
||||
func BenchmarkArtDmxMarshalBinary(b *testing.B) {
|
||||
data := artnet.ArtDmx{
|
||||
ID: [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpDmx,
|
||||
ProtVerHi: 0,
|
||||
ProtVerLo: 14,
|
||||
Sequence: 237,
|
||||
Physical: 0,
|
||||
SubUni: 1,
|
||||
Net: 0,
|
||||
Data: make([]uint8, 512),
|
||||
Sequence: 237,
|
||||
Physical: 0,
|
||||
SubUni: 1,
|
||||
Net: 0,
|
||||
Data: make([]uint8, 512),
|
||||
}
|
||||
|
||||
for b.Loop() {
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,10 +23,6 @@ func main() {
|
||||
defer connection.Close()
|
||||
buffer := make([]byte, 1024)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for {
|
||||
bytesRead, _, err := connection.ReadFromUDP(buffer)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
module github.com/jwetzell/artnet-go
|
||||
|
||||
go 1.25.5
|
||||
|
||||
require github.com/google/go-cmp v0.7.0
|
||||
|
||||
@@ -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=
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,4 @@ type ArtNetPacket interface {
|
||||
encoding.BinaryUnmarshaler
|
||||
encoding.BinaryMarshaler
|
||||
GetOpCode() uint16
|
||||
GetProtVer() uint16
|
||||
GetID() [8]uint8
|
||||
}
|
||||
|
||||
@@ -7,32 +7,17 @@ import (
|
||||
)
|
||||
|
||||
type ArtPoll struct {
|
||||
ID [8]uint8
|
||||
OpCode uint16
|
||||
ProtVerHi uint8
|
||||
ProtVerLo uint8
|
||||
Flags uint8
|
||||
DiagPriority uint8
|
||||
AddressTopHi uint8
|
||||
AddressTopLo uint8
|
||||
AddressBottomHi uint8
|
||||
AddressBottomLo uint8
|
||||
EstaManHi uint8
|
||||
EstaManLo uint8
|
||||
OemHi uint8
|
||||
OemLo uint8
|
||||
Flags uint8
|
||||
DiagPriority uint8
|
||||
// TODO(jwetzell): support extended poll fields
|
||||
TargetPortAddressTop uint16
|
||||
TargetPortAddressBottom uint16
|
||||
EstaMan uint16
|
||||
Oem uint16
|
||||
}
|
||||
|
||||
func (ap *ArtPoll) GetOpCode() uint16 {
|
||||
return ap.OpCode
|
||||
}
|
||||
|
||||
func (ap *ArtPoll) GetProtVer() uint16 {
|
||||
return uint16(ap.ProtVerHi)<<8 + uint16(ap.ProtVerLo)
|
||||
}
|
||||
|
||||
func (ap *ArtPoll) GetID() [8]uint8 {
|
||||
return ap.ID
|
||||
return OpPoll
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
copy(ap.ID[:], data[0:8])
|
||||
|
||||
if !slices.Equal(ArtNetID[:], ap.ID[:]) {
|
||||
if !slices.Equal(ArtNetID[:], data[0:8]) {
|
||||
return errors.New("ID does not match Art-Net ID")
|
||||
}
|
||||
|
||||
ap.OpCode = binary.LittleEndian.Uint16(data[8:10])
|
||||
ap.ProtVerHi = data[10]
|
||||
ap.ProtVerLo = data[11]
|
||||
opCode := binary.LittleEndian.Uint16(data[8:10])
|
||||
if opCode != OpPoll {
|
||||
return errors.New("packet does not have the correct OpCode for an ArtPoll packet")
|
||||
}
|
||||
|
||||
offset := 12
|
||||
ap.Flags = data[offset]
|
||||
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
|
||||
}
|
||||
|
||||
func (ap *ArtPoll) MarshalBinary() ([]byte, error) {
|
||||
data := make([]byte, 8+6)
|
||||
copy(data[0:8], ap.ID[:])
|
||||
binary.LittleEndian.PutUint16(data[8:10], ap.OpCode)
|
||||
data[10] = ap.ProtVerHi
|
||||
data[11] = ap.ProtVerLo
|
||||
data := make([]byte, 12+10)
|
||||
copy(data[0:8], ArtNetID[:])
|
||||
binary.LittleEndian.PutUint16(data[8:10], OpPoll)
|
||||
data[10] = 0
|
||||
data[11] = 14
|
||||
data[12] = ap.Flags
|
||||
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
|
||||
}
|
||||
|
||||
+257
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
+21
-34
@@ -7,48 +7,35 @@ import (
|
||||
)
|
||||
|
||||
type ArtTimeCode struct {
|
||||
ID [8]uint8
|
||||
OpCode uint16
|
||||
ProtVerHi uint8
|
||||
ProtVerLo uint8
|
||||
Filler1 uint8
|
||||
StreamId uint8
|
||||
Frames uint8
|
||||
Seconds uint8
|
||||
Minutes uint8
|
||||
Hours uint8
|
||||
Type uint8
|
||||
filler1 uint8
|
||||
StreamId uint8
|
||||
Frames uint8
|
||||
Seconds uint8
|
||||
Minutes uint8
|
||||
Hours uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
func (atc *ArtTimeCode) GetOpCode() uint16 {
|
||||
return atc.OpCode
|
||||
}
|
||||
|
||||
func (atc *ArtTimeCode) GetProtVer() uint16 {
|
||||
return uint16(atc.ProtVerHi)<<8 + uint16(atc.ProtVerLo)
|
||||
}
|
||||
|
||||
func (atc *ArtTimeCode) GetID() [8]uint8 {
|
||||
return atc.ID
|
||||
return OpTimeCode
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
copy(atc.ID[:], data[0:8])
|
||||
|
||||
if !slices.Equal(ArtNetID[:], atc.ID[:]) {
|
||||
if !slices.Equal(ArtNetID[:], data[0:8]) {
|
||||
return errors.New("ID does not match Art-Net ID")
|
||||
}
|
||||
|
||||
atc.OpCode = binary.LittleEndian.Uint16(data[8:10])
|
||||
atc.ProtVerHi = data[10]
|
||||
atc.ProtVerLo = data[11]
|
||||
opCode := binary.LittleEndian.Uint16(data[8:10])
|
||||
if opCode != OpTimeCode {
|
||||
return errors.New("packet does not have the correct OpCode for an ArtTimeCode packet")
|
||||
}
|
||||
|
||||
offset := 12
|
||||
atc.Filler1 = data[offset]
|
||||
atc.filler1 = data[offset]
|
||||
atc.StreamId = data[offset+1]
|
||||
atc.Frames = data[offset+2]
|
||||
atc.Seconds = data[offset+3]
|
||||
@@ -59,13 +46,13 @@ func (atc *ArtTimeCode) UnmarshalBinary(data []byte) error {
|
||||
}
|
||||
|
||||
func (atc *ArtTimeCode) MarshalBinary() ([]byte, error) {
|
||||
data := make([]byte, 8+11)
|
||||
copy(data[0:8], atc.ID[:])
|
||||
binary.LittleEndian.PutUint16(data[8:10], atc.OpCode)
|
||||
data[10] = atc.ProtVerHi
|
||||
data[11] = atc.ProtVerLo
|
||||
data := make([]byte, 12+7)
|
||||
copy(data[0:8], ArtNetID[:])
|
||||
binary.LittleEndian.PutUint16(data[8:10], OpTimeCode)
|
||||
data[10] = 0
|
||||
data[11] = 14
|
||||
offset := 12
|
||||
data[offset] = atc.Filler1
|
||||
data[offset] = atc.filler1
|
||||
data[offset+1] = atc.StreamId
|
||||
data[offset+2] = atc.Frames
|
||||
data[offset+3] = atc.Seconds
|
||||
|
||||
+36
-74
@@ -1,88 +1,47 @@
|
||||
package artnet_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/jwetzell/artnet-go"
|
||||
)
|
||||
|
||||
func TestGoodArtTimeCode(t *testing.T) {
|
||||
func TestGoodArtTimeCodeUnmarshal(t *testing.T) {
|
||||
tests := []struct {
|
||||
Name string
|
||||
Data []byte
|
||||
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},
|
||||
Expected: &artnet.ArtTimeCode{
|
||||
ID: [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpTimeCode,
|
||||
ProtVerHi: 0,
|
||||
ProtVerLo: 14,
|
||||
Filler1: 0,
|
||||
StreamId: 0,
|
||||
Frames: 11,
|
||||
Seconds: 17,
|
||||
Minutes: 3,
|
||||
Hours: 0,
|
||||
Type: 0,
|
||||
StreamId: 0,
|
||||
Frames: 11,
|
||||
Seconds: 17,
|
||||
Minutes: 3,
|
||||
Hours: 0,
|
||||
Type: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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 {
|
||||
t.Fatalf("failed to decode ArtTimeCode: %s", err)
|
||||
}
|
||||
|
||||
if got.OpCode != test.Expected.OpCode {
|
||||
t.Fatalf("ArtTimeCode OpCode does not match got: %d expected: %d", got.OpCode, test.Expected.OpCode)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("failed to decode ArtTimeCode: %s", err)
|
||||
}
|
||||
|
||||
diff := cmp.Diff(test.Expected, got, cmpopts.IgnoreUnexported(artnet.ArtTimeCode{}))
|
||||
if diff != "" {
|
||||
t.Fatalf("ArtTimeCode does not match\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,17 +60,12 @@ func BenchmarkArtTimeCodeUnmarshalBinary(b *testing.B) {
|
||||
|
||||
func BenchmarkArtTimeCodeMarshalBinary(b *testing.B) {
|
||||
data := artnet.ArtTimeCode{
|
||||
ID: [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpTimeCode,
|
||||
ProtVerHi: 0,
|
||||
ProtVerLo: 14,
|
||||
Filler1: 0,
|
||||
StreamId: 0,
|
||||
Frames: 11,
|
||||
Seconds: 17,
|
||||
Minutes: 3,
|
||||
Hours: 0,
|
||||
Type: 0,
|
||||
StreamId: 0,
|
||||
Frames: 11,
|
||||
Seconds: 17,
|
||||
Minutes: 3,
|
||||
Hours: 0,
|
||||
Type: 0,
|
||||
}
|
||||
|
||||
for b.Loop() {
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user