mirror of
https://github.com/jwetzell/psn-go.git
synced 2026-08-24 00:19:24 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b1dc4bfd6 | |||
| 7dd6d45a08 | |||
| 631537b473 | |||
| bdaf7fd327 | |||
| d53fe09bfc | |||
| a0ba854fee | |||
| 4c508c37f3 | |||
| c7f503ee99 | |||
| 75ba023226 | |||
| b1e1367662 | |||
| 3271c0f82c | |||
| 15cf2e8052 | |||
| f7ceefc203 | |||
| 3af4413e84 | |||
| 017f8ea20f | |||
| 65947914b3 | |||
| 1bf0c7c0f0 | |||
| 8c2a580b75 | |||
| f8fde1a796 | |||
| 610344e706 | |||
| 0e03f68a59 | |||
| 0877357b78 | |||
| 6bc6fb3668 | |||
| 0c297d606d | |||
| f5b944579d | |||
| ea184a936d |
@@ -0,0 +1,31 @@
|
||||
name: "Test Decoders"
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
paths:
|
||||
- 'internal/decoders/**'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
test_decoders:
|
||||
name: "test decoders"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: "./go.mod"
|
||||
|
||||
- name: Test
|
||||
run: go test -cover -coverprofile=decoders_coverage.txt ./internal/decoders/...
|
||||
|
||||
- name: Archive code coverage results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: decoders-code-coverage
|
||||
path: decoders_coverage.txt
|
||||
@@ -0,0 +1,31 @@
|
||||
name: "Test Encoders"
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
paths:
|
||||
- 'internal/encoders/**'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
test_encoders:
|
||||
name: "test encoders"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: "./go.mod"
|
||||
|
||||
- name: Test
|
||||
run: go test -cover -coverprofile=encoders_coverage.txt ./internal/encoders/...
|
||||
|
||||
- name: Archive code coverage results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: encoders-code-coverage
|
||||
path: encoders_coverage.txt
|
||||
+5
-3
@@ -1,5 +1,7 @@
|
||||
package psn
|
||||
|
||||
var PACKET_HEADER_SIZE = 16
|
||||
var MAX_UDP_PACKET_SIZE = 1500
|
||||
var CHUNK_HEADER_SIZE = 4
|
||||
const (
|
||||
PACKET_HEADER_SIZE = 16
|
||||
MAX_UDP_PACKET_SIZE = 1500
|
||||
CHUNK_HEADER_SIZE = 4
|
||||
)
|
||||
|
||||
+29
-15
@@ -1,25 +1,28 @@
|
||||
package psn
|
||||
|
||||
import "github.com/jwetzell/psn-go/internal/decoders"
|
||||
import (
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
"github.com/jwetzell/psn-go/internal/decoders"
|
||||
)
|
||||
|
||||
type Decoder struct {
|
||||
lastInfoPacketHeader *decoders.PacketHeaderChunk
|
||||
lastDataPacketHeader *decoders.PacketHeaderChunk
|
||||
infoPacketFrames map[uint8][]decoders.InfoPacketChunk
|
||||
dataPacketFrames map[uint8][]decoders.DataPacketChunk
|
||||
lastInfoPacketHeader *chunks.PacketHeaderChunk
|
||||
lastDataPacketHeader *chunks.PacketHeaderChunk
|
||||
infoPacketFrames map[uint8][]chunks.InfoPacketChunk
|
||||
dataPacketFrames map[uint8][]chunks.DataPacketChunk
|
||||
Trackers map[uint16]*Tracker
|
||||
SystemName string
|
||||
}
|
||||
|
||||
func NewDecoder() *Decoder {
|
||||
var decoder Decoder
|
||||
decoder.infoPacketFrames = map[uint8][]decoders.InfoPacketChunk{}
|
||||
decoder.dataPacketFrames = map[uint8][]decoders.DataPacketChunk{}
|
||||
decoder.infoPacketFrames = map[uint8][]chunks.InfoPacketChunk{}
|
||||
decoder.dataPacketFrames = map[uint8][]chunks.DataPacketChunk{}
|
||||
decoder.Trackers = map[uint16]*Tracker{}
|
||||
return &decoder
|
||||
}
|
||||
|
||||
func (d *Decoder) updateInfo(framePackets []decoders.InfoPacketChunk) {
|
||||
func (d *Decoder) updateInfo(framePackets []chunks.InfoPacketChunk) {
|
||||
for _, framePacket := range framePackets {
|
||||
d.SystemName = framePacket.Data.SystemName.Data.SystemName
|
||||
for _, infoTrackerChunk := range framePacket.Data.TrackerList.Data.Trackers {
|
||||
@@ -34,7 +37,7 @@ func (d *Decoder) updateInfo(framePackets []decoders.InfoPacketChunk) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) updateData(framePackets []decoders.DataPacketChunk) {
|
||||
func (d *Decoder) updateData(framePackets []chunks.DataPacketChunk) {
|
||||
for _, framePacket := range framePackets {
|
||||
for _, dataTrackerChunk := range framePacket.Data.TrackerList.Data.Trackers {
|
||||
tracker, ok := d.Trackers[dataTrackerChunk.Chunk.Header.Id]
|
||||
@@ -48,17 +51,24 @@ func (d *Decoder) updateData(framePackets []decoders.DataPacketChunk) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) Decode(bytes []byte) {
|
||||
chunk := decoders.DecodeChunk(bytes)
|
||||
func (d *Decoder) Decode(bytes []byte) error {
|
||||
chunk, err := decoders.DecodeChunk(bytes)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if chunk.Header.Id == 0x6756 {
|
||||
infoPacket := decoders.DecodeInfoPacketChunk(bytes)
|
||||
infoPacket, err := decoders.DecodeInfoPacketChunk(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentInfoPacketHeader := infoPacket.Data.PacketHeader
|
||||
|
||||
_, ok := d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId]
|
||||
|
||||
if !ok {
|
||||
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = []decoders.InfoPacketChunk{}
|
||||
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = []chunks.InfoPacketChunk{}
|
||||
}
|
||||
d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId] = append(d.infoPacketFrames[currentInfoPacketHeader.Data.FrameId], infoPacket)
|
||||
|
||||
@@ -67,13 +77,16 @@ func (d *Decoder) Decode(bytes []byte) {
|
||||
delete(d.infoPacketFrames, currentInfoPacketHeader.Data.FrameId)
|
||||
}
|
||||
} else if chunk.Header.Id == 0x6755 {
|
||||
dataPacket := decoders.DecodeDataPacketChunk(bytes)
|
||||
dataPacket, err := decoders.DecodeDataPacketChunk(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentInfoPacketHeader := dataPacket.Data.PacketHeader
|
||||
|
||||
_, ok := d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId]
|
||||
|
||||
if !ok {
|
||||
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = []decoders.DataPacketChunk{}
|
||||
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = []chunks.DataPacketChunk{}
|
||||
}
|
||||
d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId] = append(d.dataPacketFrames[currentInfoPacketHeader.Data.FrameId], dataPacket)
|
||||
|
||||
@@ -82,4 +95,5 @@ func (d *Decoder) Decode(bytes []byte) {
|
||||
delete(d.dataPacketFrames, currentInfoPacketHeader.Data.FrameId)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ func (e *Encoder) GetInfoPackets(timestamp uint64, trackers []Tracker) [][]byte
|
||||
}
|
||||
|
||||
func (e *Encoder) GetDataPackets(timestamp uint64, trackers []Tracker) [][]byte {
|
||||
|
||||
trackerChunks := [][]byte{}
|
||||
|
||||
for _, tracker := range trackers {
|
||||
|
||||
@@ -25,7 +25,6 @@ func getNTrackers(n int) []psn.Tracker {
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
testSizes := []int{1, 10, 100, 1000}
|
||||
encoder := psn.Encoder{
|
||||
SystemName: "test encoder",
|
||||
@@ -39,7 +38,6 @@ func main() {
|
||||
benchmark(trackerCount, iterations, encoder, *decoder)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type BenchmarkResults struct {
|
||||
|
||||
+19
-8
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jwetzell/psn-go"
|
||||
)
|
||||
@@ -10,18 +11,28 @@ import (
|
||||
func main() {
|
||||
decoder := psn.NewDecoder()
|
||||
|
||||
infoPacketBytes := []byte{0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
infoPacketBytes := []byte{
|
||||
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31}
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||
}
|
||||
|
||||
dataPacketBytes := []byte{0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
dataPacketBytes := []byte{
|
||||
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f}
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||
}
|
||||
|
||||
decoder.Decode(infoPacketBytes)
|
||||
decoder.Decode(dataPacketBytes)
|
||||
err := decoder.Decode(infoPacketBytes)
|
||||
if err != nil {
|
||||
slog.Error("error decoding", "err", err)
|
||||
}
|
||||
err = decoder.Decode(dataPacketBytes)
|
||||
if err != nil {
|
||||
slog.Error("error decoding", "err", err)
|
||||
}
|
||||
|
||||
fmt.Printf("decoded: %+v\n", decoder.SystemName)
|
||||
fmt.Printf("decoded system name: %s\n", decoder.SystemName)
|
||||
|
||||
trackers, err := json.MarshalIndent(decoder.Trackers, "", " ")
|
||||
if err != nil {
|
||||
@@ -29,5 +40,5 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(trackers))
|
||||
fmt.Printf("decoded trackers: \n%s\n", string(trackers))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
encoder := psn.Encoder{
|
||||
SystemName: "Server Name",
|
||||
VersionHigh: 2,
|
||||
@@ -41,5 +40,4 @@ func main() {
|
||||
fmt.Printf("%v\n", infoPacket)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
@@ -11,14 +12,13 @@ import (
|
||||
func main() {
|
||||
addr, err := net.ResolveUDPAddr("udp", "236.10.10.10:56565")
|
||||
if err != nil {
|
||||
fmt.Printf("Error %v\n", err)
|
||||
slog.Error("error making UDP address", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
client, err := net.ListenMulticastUDP("udp", nil, addr)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error %v\n", err)
|
||||
slog.Error("error listening to UDP", "err", err)
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
@@ -31,13 +31,15 @@ func main() {
|
||||
buffer := make([]byte, 2048)
|
||||
|
||||
length, _, err := client.ReadFromUDP(buffer)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error %v", err)
|
||||
slog.Error("error reading from UDP", "err", err)
|
||||
}
|
||||
|
||||
if length > 0 {
|
||||
decoder.Decode(buffer)
|
||||
err := decoder.Decode(buffer)
|
||||
if err != nil {
|
||||
slog.Error("error decoding", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
if time.Now().UnixMilli()-lastPrintMillis > 1000 {
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
"net"
|
||||
"time"
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
|
||||
func main() {
|
||||
client, err := net.Dial("udp", "236.10.10.10:56565")
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error %v\n", err)
|
||||
return
|
||||
@@ -46,7 +46,7 @@ func main() {
|
||||
|
||||
for {
|
||||
if (time.Now().UnixMilli() - lastInfoMillis) > 500 {
|
||||
fmt.Println("Sending Info Packets")
|
||||
slog.Info("Sending Info Packets")
|
||||
infoPackets := encoder.GetInfoPackets(uint64(timestamp), trackers)
|
||||
for _, infoPacket := range infoPackets {
|
||||
client.Write(infoPacket)
|
||||
@@ -71,7 +71,7 @@ func main() {
|
||||
trackers[index].SetTimestamp(uint64(timestamp))
|
||||
}
|
||||
|
||||
fmt.Println("Sending Data Packets")
|
||||
slog.Info("Sending Data Packets")
|
||||
dataPackets := encoder.GetDataPackets(uint64(timestamp), trackers)
|
||||
for _, DataPacket := range dataPackets {
|
||||
client.Write(DataPacket)
|
||||
@@ -81,5 +81,4 @@ func main() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package chunks
|
||||
|
||||
type ChunkHeader struct {
|
||||
Id uint16
|
||||
DataLen uint16
|
||||
HasSubchunks bool
|
||||
}
|
||||
|
||||
type Chunk struct {
|
||||
ChunkData []byte
|
||||
Header ChunkHeader
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package chunks
|
||||
|
||||
type DataPacketChunkData struct {
|
||||
PacketHeader *PacketHeaderChunk
|
||||
TrackerList *DataTrackerListChunk
|
||||
}
|
||||
|
||||
type DataPacketChunk struct {
|
||||
Data DataPacketChunkData
|
||||
Chunk Chunk
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package chunks
|
||||
|
||||
type DataTrackerChunkData struct {
|
||||
Pos *DataTrackerXYZChunk
|
||||
Speed *DataTrackerXYZChunk
|
||||
Ori *DataTrackerXYZChunk
|
||||
Status *DataTrackerStatusChunk
|
||||
Accel *DataTrackerXYZChunk
|
||||
TrgtPos *DataTrackerXYZChunk
|
||||
Timestamp *DataTrackerTimestampChunk
|
||||
}
|
||||
|
||||
type DataTrackerChunk struct {
|
||||
Data DataTrackerChunkData
|
||||
Chunk Chunk
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package chunks
|
||||
|
||||
type DataTrackerListChunkData struct {
|
||||
Trackers []DataTrackerChunk
|
||||
}
|
||||
type DataTrackerListChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerListChunkData
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package chunks
|
||||
|
||||
type DataTrackerStatusChunkData struct {
|
||||
Validity float32
|
||||
}
|
||||
|
||||
type DataTrackerStatusChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerStatusChunkData
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package chunks
|
||||
|
||||
type DataTrackerTimestampChunkData struct {
|
||||
Timestamp uint64
|
||||
}
|
||||
|
||||
type DataTrackerTimestampChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerTimestampChunkData
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package chunks
|
||||
|
||||
type DataTrackerXYZChunkData struct {
|
||||
X float32
|
||||
Y float32
|
||||
Z float32
|
||||
}
|
||||
|
||||
type DataTrackerXYZChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerXYZChunkData
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package chunks
|
||||
|
||||
type InfoPacketChunkData struct {
|
||||
PacketHeader *PacketHeaderChunk
|
||||
SystemName *InfoSystemNameChunk
|
||||
TrackerList *InfoTrackerListChunk
|
||||
}
|
||||
|
||||
type InfoPacketChunk struct {
|
||||
Data InfoPacketChunkData
|
||||
Chunk Chunk
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package chunks
|
||||
|
||||
type InfoSystemNameChunkData struct {
|
||||
SystemName string
|
||||
}
|
||||
|
||||
type InfoSystemNameChunk struct {
|
||||
Data InfoSystemNameChunkData
|
||||
Chunk Chunk
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package chunks
|
||||
|
||||
type InfoTrackerChunkData struct {
|
||||
TrackerName *InfoTrackerNameChunk
|
||||
}
|
||||
|
||||
type InfoTrackerChunk struct {
|
||||
Data InfoTrackerChunkData
|
||||
Chunk Chunk
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package chunks
|
||||
|
||||
type InfoTrackerListChunkData struct {
|
||||
Trackers []InfoTrackerChunk
|
||||
}
|
||||
|
||||
type InfoTrackerListChunk struct {
|
||||
Chunk Chunk
|
||||
Data InfoTrackerListChunkData
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package chunks
|
||||
|
||||
type InfoTrackerNameChunkData struct {
|
||||
TrackerName string
|
||||
}
|
||||
|
||||
type InfoTrackerNameChunk struct {
|
||||
Data InfoTrackerNameChunkData
|
||||
Chunk Chunk
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package chunks
|
||||
|
||||
type PacketHeaderChunkData struct {
|
||||
PacketTimestamp uint64
|
||||
VersionHigh uint8
|
||||
VersionLow uint8
|
||||
FrameId uint8
|
||||
FramePacketCount uint8
|
||||
}
|
||||
|
||||
type PacketHeaderChunk struct {
|
||||
Chunk Chunk
|
||||
Data PacketHeaderChunkData
|
||||
}
|
||||
+10
-14
@@ -2,20 +2,17 @@ package decoders
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type ChunkHeader struct {
|
||||
Id uint16
|
||||
DataLen uint16
|
||||
HasSubchunks bool
|
||||
}
|
||||
func DecodeChunk(bytes []byte) (chunks.Chunk, error) {
|
||||
|
||||
type Chunk struct {
|
||||
Header ChunkHeader
|
||||
ChunkData []byte
|
||||
}
|
||||
if len(bytes) < 4 {
|
||||
return chunks.Chunk{}, errors.New("chunk must be at least 4 bytes")
|
||||
}
|
||||
|
||||
func DecodeChunk(bytes []byte) Chunk {
|
||||
id := binary.LittleEndian.Uint16(bytes[0:2])
|
||||
lengthAndFlag := binary.LittleEndian.Uint16(bytes[2:4])
|
||||
|
||||
@@ -27,7 +24,7 @@ func DecodeChunk(bytes []byte) Chunk {
|
||||
data_len = data_len - 32768
|
||||
}
|
||||
|
||||
header := ChunkHeader{
|
||||
header := chunks.ChunkHeader{
|
||||
Id: id,
|
||||
DataLen: data_len,
|
||||
HasSubchunks: has_subchunks,
|
||||
@@ -35,9 +32,8 @@ func DecodeChunk(bytes []byte) Chunk {
|
||||
|
||||
chunk_data := bytes[4 : 4+header.DataLen]
|
||||
|
||||
return Chunk{
|
||||
return chunks.Chunk{
|
||||
Header: header,
|
||||
ChunkData: chunk_data,
|
||||
}
|
||||
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -3,53 +3,68 @@ package decoders
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestChunkDecoding(t *testing.T) {
|
||||
|
||||
func TestGoodChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected Chunk
|
||||
expected chunks.Chunk
|
||||
}{
|
||||
{
|
||||
description: "info packet",
|
||||
bytes: []byte{0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
bytes: []byte{
|
||||
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31},
|
||||
expected: Chunk{
|
||||
Header: ChunkHeader{
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||
},
|
||||
expected: chunks.Chunk{
|
||||
Header: chunks.ChunkHeader{
|
||||
Id: uint16(26454),
|
||||
DataLen: uint16(52),
|
||||
HasSubchunks: true,
|
||||
},
|
||||
ChunkData: []byte{0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
ChunkData: []byte{
|
||||
0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31},
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "data packet",
|
||||
bytes: []byte{0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
bytes: []byte{
|
||||
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f},
|
||||
expected: Chunk{
|
||||
Header: ChunkHeader{
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||
},
|
||||
expected: chunks.Chunk{
|
||||
Header: chunks.ChunkHeader{
|
||||
Id: uint16(26453),
|
||||
DataLen: uint16(40),
|
||||
HasSubchunks: true,
|
||||
},
|
||||
ChunkData: []byte{0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
ChunkData: []byte{
|
||||
0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f},
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := DecodeChunk(testCase.bytes)
|
||||
actual, err := DecodeChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
@@ -58,3 +73,33 @@ func TestChunkDecoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
errorShouldContain string
|
||||
}{
|
||||
{
|
||||
description: "empty packet",
|
||||
bytes: []byte{},
|
||||
errorShouldContain: "must be at least 4 bytes",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
_, err := DecodeChunk(testCase.bytes)
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Test '%s' should have failed fail to decode chunk properly", testCase.description)
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), testCase.errorShouldContain) {
|
||||
t.Errorf("Test '%s' did not return the correct error", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.errorShouldContain)
|
||||
fmt.Printf("actual: %v\n", err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,37 +3,39 @@ package decoders
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type DataPacketChunkData struct {
|
||||
PacketHeader *PacketHeaderChunk
|
||||
TrackerList *DataTrackerListChunk
|
||||
}
|
||||
func DecodeDataPacketChunk(bytes []byte) (chunks.DataPacketChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
type DataPacketChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataPacketChunkData
|
||||
}
|
||||
if err != nil {
|
||||
return chunks.DataPacketChunk{}, err
|
||||
}
|
||||
|
||||
func DecodeDataPacketChunk(bytes []byte) DataPacketChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
data := DataPacketChunkData{}
|
||||
data := chunks.DataPacketChunkData{}
|
||||
|
||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||
offset := 0
|
||||
|
||||
for offset < int(chunk.Header.DataLen) {
|
||||
|
||||
switch id := binary.LittleEndian.Uint16(chunk.ChunkData[offset : offset+2]); id {
|
||||
case 0:
|
||||
packet_header := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
||||
case 0x0000:
|
||||
packet_header, err := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataPacketChunk{}, err
|
||||
}
|
||||
data.PacketHeader = &packet_header
|
||||
offset += 4
|
||||
if packet_header.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(packet_header.Chunk.Header.DataLen)
|
||||
}
|
||||
case 1:
|
||||
tracker_list := DecodeDataTrackerListChunk(chunk.ChunkData[offset:])
|
||||
case 0x0001:
|
||||
tracker_list, err := DecodeDataTrackerListChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataPacketChunk{}, err
|
||||
}
|
||||
data.TrackerList = &tracker_list
|
||||
offset += 4
|
||||
if tracker_list.Chunk.Header.DataLen > 0 {
|
||||
@@ -46,8 +48,9 @@ func DecodeDataPacketChunk(bytes []byte) DataPacketChunk {
|
||||
}
|
||||
}
|
||||
|
||||
return DataPacketChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
return chunks.DataPacketChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodDataPacketChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.DataPacketChunk
|
||||
}{
|
||||
{
|
||||
description: "DataPacketChunk",
|
||||
bytes: []byte{
|
||||
85, 103, 124, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 104, 128, 1, 0, 100, 128, 0, 0,
|
||||
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12,
|
||||
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
|
||||
0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
expected: chunks.DataPacketChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0,
|
||||
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0,
|
||||
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0,
|
||||
64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
Header: chunks.ChunkHeader{
|
||||
DataLen: 124, Id: 26453, HasSubchunks: true,
|
||||
},
|
||||
},
|
||||
Data: chunks.DataPacketChunkData{
|
||||
PacketHeader: &chunks.PacketHeaderChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.PacketHeaderChunkData{
|
||||
PacketTimestamp: 1234567890,
|
||||
VersionHigh: 2,
|
||||
VersionLow: 3,
|
||||
FrameId: 1,
|
||||
FramePacketCount: 123,
|
||||
},
|
||||
},
|
||||
TrackerList: &chunks.DataTrackerListChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0,
|
||||
0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4,
|
||||
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
Header: chunks.ChunkHeader{DataLen: 104, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.DataTrackerListChunkData{
|
||||
Trackers: []chunks.DataTrackerChunk{
|
||||
chunks.DataTrackerChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0,
|
||||
0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
|
||||
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
|
||||
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
Header: chunks.ChunkHeader{DataLen: 100, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.DataTrackerChunkData{
|
||||
Pos: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Speed: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Ori: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Status: &chunks.DataTrackerStatusChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63},
|
||||
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerStatusChunkData{
|
||||
Validity: 1.0,
|
||||
},
|
||||
},
|
||||
Accel: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
TrgtPos: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Timestamp: &chunks.DataTrackerTimestampChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerTimestampChunkData{
|
||||
Timestamp: 1234567890,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeDataPacketChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,77 +3,89 @@ package decoders
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type DataTrackerChunkData struct {
|
||||
Pos *DataTrackerXYZChunk
|
||||
Speed *DataTrackerXYZChunk
|
||||
Ori *DataTrackerXYZChunk
|
||||
Status *DataTrackerStatusChunk
|
||||
Accel *DataTrackerXYZChunk
|
||||
TrgtPos *DataTrackerXYZChunk
|
||||
Timestamp *DataTrackerTimestampChunk
|
||||
}
|
||||
func DecodeDataTrackerChunk(bytes []byte) (chunks.DataTrackerChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
type DataTrackerChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerChunkData
|
||||
}
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
|
||||
func DecodeDataTrackerChunk(bytes []byte) DataTrackerChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
data := DataTrackerChunkData{}
|
||||
data := chunks.DataTrackerChunkData{}
|
||||
|
||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||
offset := 0
|
||||
|
||||
for offset < int(chunk.Header.DataLen) {
|
||||
|
||||
switch id := binary.LittleEndian.Uint16(chunk.ChunkData[offset : offset+2]); id {
|
||||
case 0:
|
||||
pos := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
case 0x0000:
|
||||
pos, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.Pos = &pos
|
||||
offset += 4
|
||||
if data.Pos.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(data.Pos.Chunk.Header.DataLen)
|
||||
}
|
||||
case 1:
|
||||
speed := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
case 0x0001:
|
||||
speed, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.Speed = &speed
|
||||
offset += 4
|
||||
if data.Speed.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(data.Speed.Chunk.Header.DataLen)
|
||||
}
|
||||
case 2:
|
||||
ori := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
case 0x0002:
|
||||
ori, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.Ori = &ori
|
||||
offset += 4
|
||||
if data.Ori.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(data.Ori.Chunk.Header.DataLen)
|
||||
}
|
||||
case 3:
|
||||
status := DecodeDataTrackerStatusChunk(chunk.ChunkData[offset:])
|
||||
case 0x0003:
|
||||
status, err := DecodeDataTrackerStatusChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.Status = &status
|
||||
offset += 4
|
||||
if data.Status.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(data.Status.Chunk.Header.DataLen)
|
||||
}
|
||||
case 4:
|
||||
accel := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
case 0x0004:
|
||||
accel, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.Accel = &accel
|
||||
offset += 4
|
||||
if data.Accel.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(data.Accel.Chunk.Header.DataLen)
|
||||
}
|
||||
case 5:
|
||||
trgtpos := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
case 0x0005:
|
||||
trgtpos, err := DecodeDataTrackerXYZChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.TrgtPos = &trgtpos
|
||||
offset += 4
|
||||
if data.TrgtPos.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(data.TrgtPos.Chunk.Header.DataLen)
|
||||
}
|
||||
case 6:
|
||||
timestamp := DecodeDataTrackerTimestampChunk(chunk.ChunkData[offset:])
|
||||
case 0x0006:
|
||||
timestamp, err := DecodeDataTrackerTimestampChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerChunk{}, err
|
||||
}
|
||||
data.Timestamp = ×tamp
|
||||
offset += 4
|
||||
if data.Timestamp.Chunk.Header.DataLen > 0 {
|
||||
@@ -86,8 +98,9 @@ func DecodeDataTrackerChunk(bytes []byte) DataTrackerChunk {
|
||||
}
|
||||
}
|
||||
|
||||
return DataTrackerChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
return chunks.DataTrackerChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodDataTrackerChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.DataTrackerChunk
|
||||
}{
|
||||
{
|
||||
description: "DataTracker",
|
||||
bytes: []byte{
|
||||
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12,
|
||||
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
|
||||
0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
expected: chunks.DataTrackerChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0,
|
||||
0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
|
||||
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
|
||||
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
Header: chunks.ChunkHeader{DataLen: 100, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.DataTrackerChunkData{
|
||||
Pos: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Speed: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Ori: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Status: &chunks.DataTrackerStatusChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63},
|
||||
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerStatusChunkData{
|
||||
Validity: 1.0,
|
||||
},
|
||||
},
|
||||
Accel: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
TrgtPos: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Timestamp: &chunks.DataTrackerTimestampChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerTimestampChunkData{
|
||||
Timestamp: 1234567890,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeDataTrackerChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
package decoders
|
||||
|
||||
type DataTrackerListChunkData struct {
|
||||
Trackers []DataTrackerChunk
|
||||
}
|
||||
type DataTrackerListChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerListChunkData
|
||||
}
|
||||
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||
|
||||
func DecodeDataTrackerListChunk(bytes []byte) DataTrackerListChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
func DecodeDataTrackerListChunk(bytes []byte) (chunks.DataTrackerListChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
trackers := []DataTrackerChunk{}
|
||||
if err != nil {
|
||||
return chunks.DataTrackerListChunk{}, err
|
||||
}
|
||||
|
||||
trackers := []chunks.DataTrackerChunk{}
|
||||
if chunk.Header.HasSubchunks && chunk.Header.DataLen > 0 {
|
||||
offset := 0
|
||||
for offset < int(chunk.Header.DataLen) {
|
||||
trackerChunk := DecodeDataTrackerChunk(chunk.ChunkData[offset:])
|
||||
trackerChunk, err := DecodeDataTrackerChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.DataTrackerListChunk{}, err
|
||||
}
|
||||
offset += 4
|
||||
if trackerChunk.Chunk.Header.DataLen > 0 {
|
||||
offset += int(trackerChunk.Chunk.Header.DataLen)
|
||||
@@ -24,13 +25,13 @@ func DecodeDataTrackerListChunk(bytes []byte) DataTrackerListChunk {
|
||||
}
|
||||
}
|
||||
|
||||
data := DataTrackerListChunkData{
|
||||
data := chunks.DataTrackerListChunkData{
|
||||
Trackers: trackers,
|
||||
}
|
||||
|
||||
return DataTrackerListChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
return chunks.DataTrackerListChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodDataTrackerListChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.DataTrackerListChunk
|
||||
}{
|
||||
{
|
||||
description: "DataTrackerListChunk",
|
||||
bytes: []byte{
|
||||
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0,
|
||||
64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0, 128,
|
||||
63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
expected: chunks.DataTrackerListChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0,
|
||||
0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4,
|
||||
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
Header: chunks.ChunkHeader{DataLen: 104, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.DataTrackerListChunkData{
|
||||
Trackers: []chunks.DataTrackerChunk{
|
||||
{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0,
|
||||
0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
|
||||
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
|
||||
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
Header: chunks.ChunkHeader{DataLen: 100, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.DataTrackerChunkData{
|
||||
Pos: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Speed: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Ori: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Status: &chunks.DataTrackerStatusChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63},
|
||||
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerStatusChunkData{
|
||||
Validity: 1.0,
|
||||
},
|
||||
},
|
||||
Accel: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
TrgtPos: &chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
Timestamp: &chunks.DataTrackerTimestampChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerTimestampChunkData{
|
||||
Timestamp: 1234567890,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeDataTrackerListChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,30 +2,32 @@ package decoders
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type DataTrackerStatusChunkData struct {
|
||||
Validity float32
|
||||
}
|
||||
func DecodeDataTrackerStatusChunk(bytes []byte) (chunks.DataTrackerStatusChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
type DataTrackerStatusChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerStatusChunkData
|
||||
}
|
||||
if err != nil {
|
||||
return chunks.DataTrackerStatusChunk{}, err
|
||||
}
|
||||
|
||||
func DecodeDataTrackerStatusChunk(bytes []byte) DataTrackerStatusChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
if len(chunk.ChunkData) < 4 {
|
||||
return chunks.DataTrackerStatusChunk{}, errors.New("DATA_TRACKER_STATUS chunk must be at least 4 bytes")
|
||||
}
|
||||
|
||||
statusBits := binary.LittleEndian.Uint32(chunk.ChunkData[0:4])
|
||||
|
||||
data := DataTrackerStatusChunkData{
|
||||
data := chunks.DataTrackerStatusChunkData{
|
||||
Validity: math.Float32frombits(statusBits),
|
||||
}
|
||||
|
||||
return DataTrackerStatusChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
return chunks.DataTrackerStatusChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodDataTrackerStatusChunk(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.DataTrackerStatusChunk
|
||||
}{
|
||||
{
|
||||
description: "DataTrackerStatusChunk",
|
||||
bytes: []byte{3, 0, 4, 0, 0, 0, 128, 63},
|
||||
expected: chunks.DataTrackerStatusChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63},
|
||||
Header: chunks.ChunkHeader{DataLen: 4, Id: 3, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerStatusChunkData{
|
||||
Validity: 1.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeDataTrackerStatusChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,29 +2,31 @@ package decoders
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type DataTrackerTimestampChunkData struct {
|
||||
Timestamp uint64
|
||||
}
|
||||
func DecodeDataTrackerTimestampChunk(bytes []byte) (chunks.DataTrackerTimestampChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
type DataTrackerTimestampChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerTimestampChunkData
|
||||
}
|
||||
if err != nil {
|
||||
return chunks.DataTrackerTimestampChunk{}, err
|
||||
}
|
||||
|
||||
func DecodeDataTrackerTimestampChunk(bytes []byte) DataTrackerTimestampChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
if len(chunk.ChunkData) < 8 {
|
||||
return chunks.DataTrackerTimestampChunk{}, errors.New("DATA_TRACKER_TIMESTAMP chunk must be at least 8 bytes")
|
||||
}
|
||||
|
||||
timestamp := binary.LittleEndian.Uint64(chunk.ChunkData[0:8])
|
||||
|
||||
data := DataTrackerTimestampChunkData{
|
||||
data := chunks.DataTrackerTimestampChunkData{
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
|
||||
return DataTrackerTimestampChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
return chunks.DataTrackerTimestampChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodDataTrackerTimestampChunk(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.DataTrackerTimestampChunk
|
||||
}{
|
||||
{
|
||||
description: "DataTrackerTimestampChunk",
|
||||
bytes: []byte{6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0},
|
||||
expected: chunks.DataTrackerTimestampChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0},
|
||||
Header: chunks.ChunkHeader{DataLen: 8, Id: 6, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerTimestampChunkData{
|
||||
Timestamp: 1234567890,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeDataTrackerTimestampChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,36 +2,35 @@ package decoders
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type DataTrackerXYZChunkData struct {
|
||||
X float32
|
||||
Y float32
|
||||
Z float32
|
||||
}
|
||||
func DecodeDataTrackerXYZChunk(bytes []byte) (chunks.DataTrackerXYZChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
type DataTrackerXYZChunk struct {
|
||||
Chunk Chunk
|
||||
Data DataTrackerXYZChunkData
|
||||
}
|
||||
if err != nil {
|
||||
return chunks.DataTrackerXYZChunk{}, err
|
||||
}
|
||||
|
||||
func DecodeDataTrackerXYZChunk(bytes []byte) DataTrackerXYZChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
if len(chunk.ChunkData) < 12 {
|
||||
return chunks.DataTrackerXYZChunk{}, errors.New("DATA_TRACKER_XYZ chunk must be at least 12 bytes")
|
||||
}
|
||||
|
||||
xBits := binary.LittleEndian.Uint32(chunk.ChunkData[0:4])
|
||||
yBits := binary.LittleEndian.Uint32(chunk.ChunkData[4:8])
|
||||
zBits := binary.LittleEndian.Uint32(chunk.ChunkData[8:12])
|
||||
|
||||
data := DataTrackerXYZChunkData{
|
||||
data := chunks.DataTrackerXYZChunkData{
|
||||
X: math.Float32frombits(xBits),
|
||||
Y: math.Float32frombits(yBits),
|
||||
Z: math.Float32frombits(zBits),
|
||||
}
|
||||
|
||||
return DataTrackerXYZChunk{
|
||||
return chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodDataTrackerXYZChunk(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.DataTrackerXYZChunk
|
||||
}{
|
||||
{
|
||||
description: "DataTrackerPosChunk",
|
||||
bytes: []byte{0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
expected: chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "DataTrackerSpeedChunk",
|
||||
bytes: []byte{1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
expected: chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 1, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "DataTrackerOriChunk",
|
||||
bytes: []byte{2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
expected: chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 2, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "DataTrackerAccelChunk",
|
||||
bytes: []byte{4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
expected: chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 4, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "DataTrackerTrgtPosChunk",
|
||||
bytes: []byte{5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
expected: chunks.DataTrackerXYZChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 5, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1.0,
|
||||
Y: 2.0,
|
||||
Z: 3.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeDataTrackerXYZChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,45 +3,47 @@ package decoders
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type InfoPacketChunkData struct {
|
||||
PacketHeader *PacketHeaderChunk
|
||||
SystemName *InfoSystemNameChunk
|
||||
TrackerList *InfoTrackerListChunk
|
||||
}
|
||||
|
||||
type InfoPacketChunk struct {
|
||||
Chunk Chunk
|
||||
Data InfoPacketChunkData
|
||||
}
|
||||
|
||||
func DecodeInfoPacketChunk(bytes []byte) InfoPacketChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
data := InfoPacketChunkData{}
|
||||
func DecodeInfoPacketChunk(bytes []byte) (chunks.InfoPacketChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
if err != nil {
|
||||
return chunks.InfoPacketChunk{}, err
|
||||
}
|
||||
data := chunks.InfoPacketChunkData{}
|
||||
|
||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||
offset := 0
|
||||
|
||||
for offset < int(chunk.Header.DataLen) {
|
||||
|
||||
switch id := binary.LittleEndian.Uint16(chunk.ChunkData[offset : offset+2]); id {
|
||||
case 0:
|
||||
packet_header := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
||||
case 0x0000:
|
||||
packet_header, err := DecodePacketHeaderChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.InfoPacketChunk{}, err
|
||||
}
|
||||
data.PacketHeader = &packet_header
|
||||
offset += 4
|
||||
if packet_header.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(packet_header.Chunk.Header.DataLen)
|
||||
}
|
||||
case 1:
|
||||
system_name := DecodeInfoSystemNameChunk(chunk.ChunkData[offset:])
|
||||
case 0x0001:
|
||||
system_name, err := DecodeInfoSystemNameChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.InfoPacketChunk{}, err
|
||||
}
|
||||
data.SystemName = &system_name
|
||||
offset += 4
|
||||
if system_name.Chunk.Header.DataLen > 0 {
|
||||
offset = offset + int(system_name.Chunk.Header.DataLen)
|
||||
}
|
||||
case 2:
|
||||
tracker_list := DecodeInfoTrackerListChunk(chunk.ChunkData[offset:])
|
||||
case 0x0002:
|
||||
tracker_list, err := DecodeInfoTrackerListChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.InfoPacketChunk{}, err
|
||||
}
|
||||
data.TrackerList = &tracker_list
|
||||
offset += 4
|
||||
if tracker_list.Chunk.Header.DataLen > 0 {
|
||||
@@ -54,8 +56,9 @@ func DecodeInfoPacketChunk(bytes []byte) InfoPacketChunk {
|
||||
}
|
||||
}
|
||||
|
||||
return InfoPacketChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
return chunks.InfoPacketChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodInfoPacketChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.InfoPacketChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoPacketChunk",
|
||||
bytes: []byte{
|
||||
86, 103, 51, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 10, 0, 80, 83, 78, 32, 83, 101,
|
||||
114, 118, 101, 114, 2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
expected: chunks.InfoPacketChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{
|
||||
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101,
|
||||
114, 2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
Header: chunks.ChunkHeader{DataLen: 51, Id: 26454, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoPacketChunkData{
|
||||
PacketHeader: &chunks.PacketHeaderChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.PacketHeaderChunkData{
|
||||
PacketTimestamp: 1234567890,
|
||||
VersionHigh: 2,
|
||||
VersionLow: 3,
|
||||
FrameId: 1,
|
||||
FramePacketCount: 123,
|
||||
},
|
||||
},
|
||||
SystemName: &chunks.InfoSystemNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{80, 83, 78, 32, 83, 101, 114, 118, 101, 114},
|
||||
Header: chunks.ChunkHeader{DataLen: 10, Id: 1, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoSystemNameChunkData{
|
||||
SystemName: "PSN Server",
|
||||
},
|
||||
},
|
||||
TrackerList: &chunks.InfoTrackerListChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 17, Id: 2, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerListChunkData{
|
||||
Trackers: []chunks.InfoTrackerChunk{
|
||||
{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerChunkData{
|
||||
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeInfoPacketChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,20 @@
|
||||
package decoders
|
||||
|
||||
type InfoSystemNameChunkData struct {
|
||||
SystemName string
|
||||
}
|
||||
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||
|
||||
type InfoSystemNameChunk struct {
|
||||
Chunk Chunk
|
||||
Data InfoSystemNameChunkData
|
||||
}
|
||||
func DecodeInfoSystemNameChunk(bytes []byte) (chunks.InfoSystemNameChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
if err != nil {
|
||||
return chunks.InfoSystemNameChunk{}, err
|
||||
}
|
||||
data := chunks.InfoSystemNameChunkData{}
|
||||
|
||||
func DecodeInfoSystemNameChunk(bytes []byte) InfoSystemNameChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
system_name := string(chunk.ChunkData[0:chunk.Header.DataLen])
|
||||
|
||||
data := InfoSystemNameChunkData{
|
||||
SystemName: system_name,
|
||||
if chunk.Header.DataLen > 0 {
|
||||
data.SystemName = string(chunk.ChunkData[0:chunk.Header.DataLen])
|
||||
}
|
||||
|
||||
return InfoSystemNameChunk{
|
||||
return chunks.InfoSystemNameChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodInfoSystemNameChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.InfoSystemNameChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoSystemNameChunk",
|
||||
bytes: []byte{
|
||||
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
|
||||
},
|
||||
expected: chunks.InfoSystemNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{80, 83, 78, 32, 83, 101, 114, 118, 101, 114},
|
||||
Header: chunks.ChunkHeader{DataLen: 10, Id: 1, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoSystemNameChunkData{
|
||||
SystemName: "PSN Server",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeInfoSystemNameChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,29 +3,27 @@ package decoders
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type InfoTrackerChunkData struct {
|
||||
TrackerName *InfoTrackerNameChunk
|
||||
}
|
||||
|
||||
type InfoTrackerChunk struct {
|
||||
Chunk Chunk
|
||||
Data InfoTrackerChunkData
|
||||
}
|
||||
|
||||
func DecodeInfoTrackerChunk(bytes []byte) InfoTrackerChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
data := InfoTrackerChunkData{}
|
||||
func DecodeInfoTrackerChunk(bytes []byte) (chunks.InfoTrackerChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
if err != nil {
|
||||
return chunks.InfoTrackerChunk{}, err
|
||||
}
|
||||
data := chunks.InfoTrackerChunkData{}
|
||||
|
||||
if chunk.Header.HasSubchunks && chunk.ChunkData != nil && chunk.Header.DataLen > 0 {
|
||||
offset := 0
|
||||
|
||||
for offset < int(chunk.Header.DataLen) {
|
||||
|
||||
switch id := binary.LittleEndian.Uint16(chunk.ChunkData[offset : offset+2]); id {
|
||||
case 0:
|
||||
tracker_name := DecodeInfoTrackerNameChunk(chunk.ChunkData[offset:])
|
||||
case 0x0000:
|
||||
tracker_name, err := DecodeInfoTrackerNameChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.InfoTrackerChunk{}, err
|
||||
}
|
||||
data.TrackerName = &tracker_name
|
||||
offset += 4
|
||||
if tracker_name.Chunk.Header.DataLen > 0 {
|
||||
@@ -37,8 +35,9 @@ func DecodeInfoTrackerChunk(bytes []byte) InfoTrackerChunk {
|
||||
}
|
||||
}
|
||||
|
||||
return InfoTrackerChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
return chunks.InfoTrackerChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodInfoTrackerChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.InfoTrackerChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoTrackerChunk",
|
||||
bytes: []byte{
|
||||
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
expected: chunks.InfoTrackerChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerChunkData{
|
||||
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeInfoTrackerChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
package decoders
|
||||
|
||||
type InfoTrackerListChunkData struct {
|
||||
Trackers []InfoTrackerChunk
|
||||
}
|
||||
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||
|
||||
type InfoTrackerListChunk struct {
|
||||
Chunk Chunk
|
||||
Data InfoTrackerListChunkData
|
||||
}
|
||||
func DecodeInfoTrackerListChunk(bytes []byte) (chunks.InfoTrackerListChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
if err != nil {
|
||||
return chunks.InfoTrackerListChunk{}, err
|
||||
}
|
||||
|
||||
func DecodeInfoTrackerListChunk(bytes []byte) InfoTrackerListChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
|
||||
trackers := []InfoTrackerChunk{}
|
||||
trackers := []chunks.InfoTrackerChunk{}
|
||||
if chunk.Header.HasSubchunks && chunk.Header.DataLen > 0 {
|
||||
offset := 0
|
||||
for offset < int(chunk.Header.DataLen) {
|
||||
trackerChunk := DecodeInfoTrackerChunk(chunk.ChunkData[offset:])
|
||||
trackerChunk, err := DecodeInfoTrackerChunk(chunk.ChunkData[offset:])
|
||||
if err != nil {
|
||||
return chunks.InfoTrackerListChunk{}, err
|
||||
}
|
||||
offset += 4
|
||||
if trackerChunk.Chunk.Header.DataLen > 0 {
|
||||
offset += int(trackerChunk.Chunk.Header.DataLen)
|
||||
@@ -25,13 +24,13 @@ func DecodeInfoTrackerListChunk(bytes []byte) InfoTrackerListChunk {
|
||||
}
|
||||
}
|
||||
|
||||
data := InfoTrackerListChunkData{
|
||||
data := chunks.InfoTrackerListChunkData{
|
||||
Trackers: trackers,
|
||||
}
|
||||
|
||||
return InfoTrackerListChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
return chunks.InfoTrackerListChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodInfoTrackerListChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.InfoTrackerListChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoTrackerListChunk",
|
||||
bytes: []byte{
|
||||
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
expected: chunks.InfoTrackerListChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 17, Id: 2, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerListChunkData{
|
||||
Trackers: []chunks.InfoTrackerChunk{
|
||||
{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerChunkData{
|
||||
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeInfoTrackerListChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,23 @@
|
||||
package decoders
|
||||
|
||||
type InfoTrackerNameChunkData struct {
|
||||
TrackerName string
|
||||
}
|
||||
import "github.com/jwetzell/psn-go/internal/chunks"
|
||||
|
||||
type InfoTrackerNameChunk struct {
|
||||
Chunk Chunk
|
||||
Data InfoTrackerNameChunkData
|
||||
}
|
||||
func DecodeInfoTrackerNameChunk(bytes []byte) (chunks.InfoTrackerNameChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
|
||||
func DecodeInfoTrackerNameChunk(bytes []byte) InfoTrackerNameChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
|
||||
tracker_name := string(chunk.ChunkData[0:chunk.Header.DataLen])
|
||||
|
||||
data := InfoTrackerNameChunkData{
|
||||
TrackerName: tracker_name,
|
||||
if err != nil {
|
||||
return chunks.InfoTrackerNameChunk{}, err
|
||||
}
|
||||
|
||||
return InfoTrackerNameChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
data := chunks.InfoTrackerNameChunkData{}
|
||||
|
||||
if chunk.Header.DataLen > 0 {
|
||||
data.TrackerName = string(chunk.ChunkData[0:chunk.Header.DataLen])
|
||||
}
|
||||
|
||||
return chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodInfoTrackerNameChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.InfoTrackerNameChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoTrackerNameChunk",
|
||||
bytes: []byte{
|
||||
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
expected: chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodeInfoTrackerNameChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,16 @@
|
||||
package decoders
|
||||
|
||||
import "encoding/binary"
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
type PacketHeaderChunkData struct {
|
||||
PacketTimestamp uint64
|
||||
VersionHigh uint8
|
||||
VersionLow uint8
|
||||
FrameId uint8
|
||||
FramePacketCount uint8
|
||||
}
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
type PacketHeaderChunk struct {
|
||||
Chunk Chunk
|
||||
Data PacketHeaderChunkData
|
||||
}
|
||||
|
||||
func DecodePacketHeaderChunk(bytes []byte) PacketHeaderChunk {
|
||||
chunk := DecodeChunk(bytes)
|
||||
func DecodePacketHeaderChunk(bytes []byte) (chunks.PacketHeaderChunk, error) {
|
||||
chunk, err := DecodeChunk(bytes)
|
||||
if err != nil {
|
||||
return chunks.PacketHeaderChunk{}, err
|
||||
}
|
||||
|
||||
packet_timestamp := binary.LittleEndian.Uint64(chunk.ChunkData[0:8])
|
||||
version_high := chunk.ChunkData[8]
|
||||
@@ -24,7 +18,7 @@ func DecodePacketHeaderChunk(bytes []byte) PacketHeaderChunk {
|
||||
frame_id := chunk.ChunkData[10]
|
||||
frame_packet_count := chunk.ChunkData[11]
|
||||
|
||||
data := PacketHeaderChunkData{
|
||||
data := chunks.PacketHeaderChunkData{
|
||||
PacketTimestamp: packet_timestamp,
|
||||
VersionHigh: version_high,
|
||||
VersionLow: version_low,
|
||||
@@ -32,9 +26,9 @@ func DecodePacketHeaderChunk(bytes []byte) PacketHeaderChunk {
|
||||
FramePacketCount: frame_packet_count,
|
||||
}
|
||||
|
||||
return PacketHeaderChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
return chunks.PacketHeaderChunk{
|
||||
Chunk: chunk,
|
||||
Data: data,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestGoodPacketHeaderChunkDecoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
bytes []byte
|
||||
expected chunks.PacketHeaderChunk
|
||||
}{
|
||||
{
|
||||
description: "PacketHeaderChunk",
|
||||
bytes: []byte{
|
||||
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
|
||||
},
|
||||
expected: chunks.PacketHeaderChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123},
|
||||
Header: chunks.ChunkHeader{DataLen: 12, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.PacketHeaderChunkData{
|
||||
PacketTimestamp: 1234567890,
|
||||
VersionHigh: 2,
|
||||
VersionLow: 3,
|
||||
FrameId: 1,
|
||||
FramePacketCount: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual, err := DecodePacketHeaderChunk(testCase.bytes)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to decode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %+v\n", testCase.expected)
|
||||
fmt.Printf("actual: %+v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package encoders
|
||||
import "encoding/binary"
|
||||
|
||||
func EncodeChunk(id uint16, chunkData []byte, hasSubchunks bool) []byte {
|
||||
|
||||
header := []byte{}
|
||||
|
||||
header = binary.LittleEndian.AppendUint16(header, id)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
chunk chunks.Chunk
|
||||
}{
|
||||
{
|
||||
description: "info packet",
|
||||
expected: []byte{
|
||||
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||
},
|
||||
chunk: chunks.Chunk{
|
||||
Header: chunks.ChunkHeader{
|
||||
Id: uint16(26454),
|
||||
DataLen: uint16(52),
|
||||
HasSubchunks: true,
|
||||
},
|
||||
ChunkData: []byte{
|
||||
0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
|
||||
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "data packet",
|
||||
expected: []byte{
|
||||
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||
},
|
||||
chunk: chunks.Chunk{
|
||||
Header: chunks.ChunkHeader{
|
||||
Id: uint16(26453),
|
||||
DataLen: uint16(40),
|
||||
HasSubchunks: true,
|
||||
},
|
||||
ChunkData: []byte{
|
||||
0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
|
||||
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
||||
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeChunk(testCase.chunk.Header.Id, testCase.chunk.ChunkData, testCase.chunk.Header.HasSubchunks)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerAccelChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerXYZChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic acceleration",
|
||||
expected: []byte{
|
||||
4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
},
|
||||
data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1,
|
||||
Y: 2,
|
||||
Z: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerAccelChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerOriChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerXYZChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic orientation",
|
||||
expected: []byte{
|
||||
2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
},
|
||||
data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1,
|
||||
Y: 2,
|
||||
Z: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerOriChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerPosChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerXYZChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic position",
|
||||
expected: []byte{
|
||||
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
},
|
||||
data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1,
|
||||
Y: 2,
|
||||
Z: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerPosChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerSpeedChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerXYZChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic speed",
|
||||
expected: []byte{
|
||||
1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
},
|
||||
data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1,
|
||||
Y: 2,
|
||||
Z: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerSpeedChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerStatusChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerStatusChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic status",
|
||||
expected: []byte{
|
||||
3, 0, 4, 0, 0, 0, 128, 63,
|
||||
},
|
||||
data: chunks.DataTrackerStatusChunkData{
|
||||
Validity: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerStatusChunk(testCase.data.Validity)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerTimestampChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerTimestampChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic timestamp",
|
||||
expected: []byte{
|
||||
6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
|
||||
},
|
||||
data: chunks.DataTrackerTimestampChunkData{
|
||||
Timestamp: 1234567890,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerTimestampChunk(testCase.data.Timestamp)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestDataTrackerTrgtPosChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.DataTrackerXYZChunkData
|
||||
}{
|
||||
{
|
||||
description: "basic target position",
|
||||
expected: []byte{
|
||||
5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
|
||||
},
|
||||
data: chunks.DataTrackerXYZChunkData{
|
||||
X: 1,
|
||||
Y: 2,
|
||||
Z: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeDataTrackerTrgtPosChunk(testCase.data.X, testCase.data.Y, testCase.data.Z)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestInfoSystemNameChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.InfoSystemNameChunkData
|
||||
}{
|
||||
{
|
||||
description: "InfoSystemNameChunk",
|
||||
expected: []byte{
|
||||
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
|
||||
},
|
||||
data: chunks.InfoSystemNameChunkData{
|
||||
SystemName: "PSN Server",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeInfoSystemNameChunk(testCase.data.SystemName)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestInfoTrackerChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
chunk chunks.InfoTrackerChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoTrackerChunk",
|
||||
expected: []byte{
|
||||
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
chunk: chunks.InfoTrackerChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerChunkData{
|
||||
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeInfoTrackerChunk(testCase.chunk.Chunk.Header.Id, EncodeInfoTrackerNameChunk(testCase.chunk.Data.TrackerName.Data.TrackerName))
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestInfoTrackerListChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
chunk chunks.InfoTrackerListChunk
|
||||
}{
|
||||
{
|
||||
description: "InfoTrackerListChunk",
|
||||
expected: []byte{
|
||||
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
chunk: chunks.InfoTrackerListChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 17, Id: 2, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerListChunkData{
|
||||
Trackers: []chunks.InfoTrackerChunk{
|
||||
{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 13, Id: 1, HasSubchunks: true},
|
||||
},
|
||||
Data: chunks.InfoTrackerChunkData{
|
||||
TrackerName: &chunks.InfoTrackerNameChunk{
|
||||
Chunk: chunks.Chunk{
|
||||
ChunkData: []byte{84, 114, 97, 99, 107, 101, 114, 32, 49},
|
||||
Header: chunks.ChunkHeader{DataLen: 9, Id: 0, HasSubchunks: false},
|
||||
},
|
||||
Data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
trackerChunks := [][]byte{}
|
||||
for _, tracker := range testCase.chunk.Data.Trackers {
|
||||
trackerChunks = append(trackerChunks, EncodeInfoTrackerChunk(tracker.Chunk.Header.Id, EncodeInfoTrackerNameChunk(tracker.Data.TrackerName.Data.TrackerName)))
|
||||
}
|
||||
|
||||
actual := EncodeInfoTrackerListChunk(trackerChunks)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestInfoTrackerNameChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.InfoTrackerNameChunkData
|
||||
}{
|
||||
{
|
||||
description: "InfoTrackerNameChunk",
|
||||
expected: []byte{
|
||||
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
|
||||
},
|
||||
data: chunks.InfoTrackerNameChunkData{
|
||||
TrackerName: "Tracker 1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodeInfoTrackerNameChunk(testCase.data.TrackerName)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package encoders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
)
|
||||
|
||||
func TestPacketHeaderChunkEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
expected []byte
|
||||
data chunks.PacketHeaderChunkData
|
||||
}{
|
||||
{
|
||||
description: "PacketHeaderChunk",
|
||||
expected: []byte{
|
||||
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
|
||||
},
|
||||
data: chunks.PacketHeaderChunkData{
|
||||
PacketTimestamp: 1234567890,
|
||||
VersionHigh: 2,
|
||||
VersionLow: 3,
|
||||
FrameId: 1,
|
||||
FramePacketCount: 123,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
actual := EncodePacketHeaderChunk(testCase.data.PacketTimestamp, testCase.data.VersionHigh, testCase.data.VersionLow, testCase.data.FrameId, testCase.data.FramePacketCount)
|
||||
|
||||
if !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Test '%s' failed to encode chunk properly", testCase.description)
|
||||
fmt.Printf("expected: %v\n", testCase.expected)
|
||||
fmt.Printf("actual: %v\n", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
package psn
|
||||
|
||||
import (
|
||||
"github.com/jwetzell/psn-go/internal/decoders"
|
||||
"github.com/jwetzell/psn-go/internal/chunks"
|
||||
"github.com/jwetzell/psn-go/internal/encoders"
|
||||
)
|
||||
|
||||
@@ -12,8 +12,6 @@ type XYZData struct {
|
||||
}
|
||||
|
||||
type Tracker struct {
|
||||
Id uint16
|
||||
Name string
|
||||
Pos *XYZData
|
||||
Speed *XYZData
|
||||
Ori *XYZData
|
||||
@@ -21,6 +19,8 @@ type Tracker struct {
|
||||
Accel *XYZData
|
||||
TrgtPos *XYZData
|
||||
Timestamp *uint64
|
||||
Name string
|
||||
Id uint16
|
||||
}
|
||||
|
||||
func (t *Tracker) SetPos(x float32, y float32, z float32) {
|
||||
@@ -138,12 +138,12 @@ func (t *Tracker) GetInfoChunk() []byte {
|
||||
return encoders.EncodeInfoTrackerChunk(t.Id, encoders.EncodeInfoTrackerNameChunk(t.Name))
|
||||
}
|
||||
|
||||
func (t *Tracker) UpdateInfo(infoTrackerChunk decoders.InfoTrackerChunk) {
|
||||
func (t *Tracker) UpdateInfo(infoTrackerChunk chunks.InfoTrackerChunk) {
|
||||
t.Id = infoTrackerChunk.Chunk.Header.Id
|
||||
t.Name = infoTrackerChunk.Data.TrackerName.Data.TrackerName
|
||||
}
|
||||
|
||||
func (t *Tracker) UpdateData(dataTrackerChunk decoders.DataTrackerChunk) {
|
||||
func (t *Tracker) UpdateData(dataTrackerChunk chunks.DataTrackerChunk) {
|
||||
if dataTrackerChunk.Data.Pos != nil {
|
||||
t.SetPos(dataTrackerChunk.Data.Pos.Data.X, dataTrackerChunk.Data.Pos.Data.Y, dataTrackerChunk.Data.Pos.Data.Z)
|
||||
}
|
||||
@@ -173,13 +173,13 @@ func (t *Tracker) UpdateData(dataTrackerChunk decoders.DataTrackerChunk) {
|
||||
}
|
||||
}
|
||||
|
||||
func TrackerFromInfo(infoTrackerChunk decoders.InfoTrackerChunk) *Tracker {
|
||||
func TrackerFromInfo(infoTrackerChunk chunks.InfoTrackerChunk) *Tracker {
|
||||
var tracker Tracker
|
||||
tracker.UpdateInfo(infoTrackerChunk)
|
||||
return &tracker
|
||||
}
|
||||
|
||||
func TrackerFromData(dataTrackerChunk decoders.DataTrackerChunk) *Tracker {
|
||||
func TrackerFromData(dataTrackerChunk chunks.DataTrackerChunk) *Tracker {
|
||||
var tracker Tracker
|
||||
tracker.UpdateData(dataTrackerChunk)
|
||||
return &tracker
|
||||
|
||||
Reference in New Issue
Block a user