-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpacket.go
More file actions
100 lines (88 loc) · 1.99 KB
/
packet.go
File metadata and controls
100 lines (88 loc) · 1.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package ais
import (
"errors"
"strconv"
"strings"
)
// Packet represents one line of AIS data
type Packet struct {
Talker string
PacketType string
FragCount int
FragNo int
SeqId string
Channel string
Payload string
FillBits int
}
var (
ErrEmptyPacket = errors.New("empty packet")
ErrInvalidPacketPrefix = errors.New("invalid prefix")
ErrMissingChecksum = errors.New("missing checksum")
ErrIncorrectChecksum = errors.New("incorrect checksum")
ErrInvalidPacket = errors.New("invalid packet")
)
// ParsePacket parses one line of AIS data
func ParsePacket(rawPacket string) (*Packet, error) {
l := len(rawPacket)
if l == 0 {
return nil, ErrEmptyPacket
}
if rawPacket[0] != '!' {
return nil, ErrInvalidPacketPrefix
}
checksum, err := readChecksum(rawPacket)
if err != nil {
return nil, err
}
innerMessage := rawPacket[1 : l-3]
calculatedChecksum := calculateChecksum(innerMessage)
if checksum != calculatedChecksum {
return nil, ErrIncorrectChecksum
}
parts := strings.Split(innerMessage, ",")
fragCount, err := toInt(parts[1])
if err != nil {
return nil, ErrInvalidPacket
}
fragNo, err := toInt(parts[2])
if err != nil {
return nil, ErrInvalidPacket
}
fillBits, err := toInt(parts[6])
if err != nil {
return nil, ErrInvalidPacket
}
return &Packet{
Talker: parts[0][0:2],
PacketType: parts[0][2:],
FragCount: fragCount,
FragNo: fragNo,
SeqId: parts[3],
Channel: parts[4],
Payload: parts[5],
FillBits: fillBits,
}, nil
}
func readChecksum(rawPacket string) (byte, error) {
l := len(rawPacket)
if rawPacket[l-3] != '*' {
return 0, ErrMissingChecksum
}
checksumN := rawPacket[l-2:]
checksum, err := strconv.ParseUint(checksumN, 16, 8)
if err != nil {
return 0, err
}
return byte(checksum), nil
}
func calculateChecksum(s string) uint8 {
var checksum int32
for _, r := range s {
checksum ^= r
}
return uint8(checksum)
}
func toInt(s string) (int, error) {
return strconv.Atoi(s)
}