-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ABM,ACK,ACN,ALC,ALF,ALR,ARC,BBM,HBT,TLB,TTD,VSD sentences (#100)
- Loading branch information
Showing
32 changed files
with
2,380 additions
and
439 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,19 +15,19 @@ jobs: | |
strategy: | ||
fail-fast: false | ||
matrix: | ||
go: ["1.17", "1.16", "1.15", "1.14"] | ||
go: ["1.20", "1.19", "1.18", "1.17"] | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@v2 | ||
uses: actions/setup-go@v3 | ||
with: | ||
go-version: ${{ matrix.go }} | ||
|
||
- name: Install dependencies | ||
run: | | ||
go get -u golang.org/x/lint/golint@latest | ||
go get -u github.com/mattn/[email protected].9 | ||
go install golang.org/x/lint/golint@latest | ||
go install github.com/mattn/[email protected].11 | ||
- name: Lint | ||
run: | | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package nmea | ||
|
||
const ( | ||
// TypeABM type of ABM sentence for AIS addressed binary and safety related message | ||
TypeABM = "ABM" | ||
) | ||
|
||
// ABM - AIS addressed binary and safety related message | ||
// https://fcc.report/FCC-ID/ADB9ZWRTR100/2768717.pdf (page 6) FURUNO MARINE RADAR, model FAR-15XX manual | ||
// | ||
// Format: !--ABM,x,x,x,xxxxxxxxx,x,xx,s--s,x,*hh<CR><LF> | ||
// Example: !AIABM,26,2,1,3381581370,3,8,177KQJ5000G?tO`K>RA1wUbN0TKH,0*02 | ||
type ABM struct { | ||
BaseSentence | ||
|
||
// NumFragments is total number of fragments/sentences need to transfer the message (1 - 9) | ||
NumFragments int64 // 0 | ||
|
||
// FragmentNumber is current fragment/sentence number (1 - 9) | ||
FragmentNumber int64 // 1 | ||
|
||
// MessageID is sequential message identifier (0 - 3) | ||
MessageID int64 // 2 | ||
|
||
// MMSI is The MMSI of destination AIS unit for the ITU-R M.1371 message (10 digits or empty) | ||
MMSI string // 3 | ||
|
||
// Channel is AIS channel for broadcast of the radio message (0 - 3) | ||
// 0 - no broadcast | ||
// 1 - on AIS channel A | ||
// 2 - on AIS channel B | ||
// 3 - broadcast on both AIS channels | ||
Channel string // 4 | ||
|
||
// VDLMessageNumber is VDL message number (6/12), see ITU-R M.1371 | ||
VDLMessageNumber int64 // 5 | ||
|
||
// Payload is encapsulated data (6 bit binary-converted data) (1 - 63 bytes) | ||
Payload []byte // 6 | ||
// 7 - Number of fill bits (0 - 5) | ||
} | ||
|
||
// newABM constructor | ||
func newABM(s BaseSentence) (ABM, error) { | ||
p := NewParser(s) | ||
p.AssertType(TypeABM) | ||
return ABM{ | ||
BaseSentence: s, | ||
NumFragments: p.Int64(0, "number of fragments"), | ||
FragmentNumber: p.Int64(1, "fragment number"), | ||
MessageID: p.Int64(2, "message ID"), | ||
MMSI: p.String(3, "MMSI"), | ||
Channel: p.String(4, "channel"), | ||
VDLMessageNumber: p.Int64(5, "VDL message number"), | ||
Payload: p.SixBitASCIIArmour(6, int(p.Int64(7, "number of padding bits")), "payload"), | ||
}, p.Err() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package nmea | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestABM(t *testing.T) { | ||
var tests = []struct { | ||
name string | ||
raw string | ||
err string | ||
msg ABM | ||
}{ | ||
{ | ||
name: "Good single fragment message", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,177KQJ5000G?tO`K>RA1wUbN0TKH,0*02", | ||
msg: ABM{ | ||
NumFragments: 26, | ||
FragmentNumber: 2, | ||
MessageID: 1, | ||
MMSI: "3381581370", | ||
Channel: "3", | ||
VDLMessageNumber: 8, | ||
Payload: []byte{ | ||
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, // 10 | ||
0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, // 20 | ||
0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, // 30 | ||
0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, // 40 | ||
0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // 50 | ||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // 60 | ||
0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, // 70 | ||
0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, // 80 | ||
0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, // 90 | ||
0x0, 0x1, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, // 100 | ||
0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, // 110 | ||
0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, // 120 | ||
0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, // 130 | ||
0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, // 140 | ||
0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // 150 | ||
0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, // 160 | ||
0x1, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, // 168 | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Good single fragment message with padding", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,H77nSfPh4U=<E`H4U8G;:222220,2*42", | ||
msg: ABM{ | ||
NumFragments: 26, | ||
FragmentNumber: 2, | ||
MessageID: 1, | ||
MMSI: "3381581370", | ||
Channel: "3", | ||
VDLMessageNumber: 8, | ||
Payload: []byte{ | ||
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, | ||
1, 1, 0, 0, 0, 1, 1, 1, 1, 1, | ||
0, 1, 1, 0, 1, 0, 0, 0, 1, 1, | ||
1, 0, 1, 1, 1, 0, 1, 0, 0, 0, | ||
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, | ||
0, 1, 0, 0, 1, 0, 0, 1, 0, 1, | ||
0, 0, 1, 1, 0, 1, 0, 0, 1, 1, | ||
0, 0, 0, 1, 0, 1, 0, 1, 1, 0, | ||
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, | ||
0, 0, 0, 1, 0, 0, 1, 0, 0, 1, | ||
0, 1, 0, 0, 1, 0, 0, 0, 0, 1, | ||
0, 1, 1, 1, 0, 0, 1, 0, 1, 1, | ||
0, 0, 1, 0, 1, 0, 0, 0, 0, 0, | ||
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, | ||
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, | ||
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Empty payload", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,,0*7b", | ||
msg: ABM{ | ||
NumFragments: 26, | ||
FragmentNumber: 2, | ||
MessageID: 1, | ||
MMSI: "3381581370", | ||
Channel: "3", | ||
VDLMessageNumber: 8, | ||
Payload: []byte{}, | ||
}, | ||
}, | ||
{ | ||
name: "Invalid number of fragments", | ||
raw: "!AIABM,x,2,1,3381581370,3,8,177KQJ5000G?tO`K>RA1wUbN0TKH,0*7e", | ||
err: "nmea: AIABM invalid number of fragments: x", | ||
}, | ||
{ | ||
name: "Invalid VDLMessageNumber", | ||
raw: "!AIABM,26,2,1,3381581370,3,x,177KQJ5000G?tO`K>RA1wUbN0TKH,0*42", | ||
err: "nmea: AIABM invalid VDL message number: x", | ||
}, | ||
{ | ||
name: "Invalid symbol in payload", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,1 1,0*5b", | ||
err: "nmea: AIABM invalid payload: data byte", | ||
}, | ||
{ | ||
name: "Negative number of fill bits", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,177KQJ5000G?tO`K>RA1wUbN0TKH,-1*2e", | ||
err: "nmea: AIABM invalid payload: fill bits", | ||
}, | ||
{ | ||
name: "Too high number of fill bits", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,177KQJ5000G?tO`K>RA1wUbN0TKH,20*30", | ||
err: "nmea: AIABM invalid payload: fill bits", | ||
}, | ||
{ | ||
name: "Negative number of bits", | ||
raw: "!AIABM,26,2,1,3381581370,3,8,,2*79", | ||
err: "nmea: AIABM invalid payload: num bits", | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
m, err := Parse(tt.raw) | ||
if tt.err != "" { | ||
assert.Error(t, err) | ||
assert.EqualError(t, err, tt.err) | ||
} else { | ||
assert.NoError(t, err) | ||
abm := m.(ABM) | ||
abm.BaseSentence = BaseSentence{} | ||
assert.Equal(t, tt.msg, abm) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package nmea | ||
|
||
const ( | ||
// TypeACK type of ACK sentence for alert acknowledge | ||
TypeACK = "ACK" | ||
) | ||
|
||
// ACK - Acknowledge. This sentence is used to acknowledge an alarm condition reported by a device. | ||
// http://www.nmea.de/nmea0183datensaetze.html#ack | ||
// https://www.furuno.it/docs/INSTALLATION%20MANUALgp170_installation_manual.pdf GPS NAVIGATOR Model GP-170 (page 42) | ||
// https://www.manualslib.com/manual/2226813/Jrc-Jln-900.html?page=239#manual (JRC JLN-900: Installation And Instruction Manual) | ||
// | ||
// Format: $--ACK,xxx*hh<CR><LF> | ||
// Example: $VRACK,001*50 | ||
type ACK struct { | ||
BaseSentence | ||
|
||
// AlertIdentifier is alert identifier (001 to 99999) | ||
AlertIdentifier int64 // 0 | ||
} | ||
|
||
// newACKN constructor | ||
func newACK(s BaseSentence) (ACK, error) { | ||
p := NewParser(s) | ||
p.AssertType(TypeACK) | ||
return ACK{ | ||
BaseSentence: s, | ||
AlertIdentifier: p.Int64(0, "alert identifier"), | ||
}, p.Err() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package nmea | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestACK(t *testing.T) { | ||
var tests = []struct { | ||
name string | ||
raw string | ||
err string | ||
msg ACK | ||
}{ | ||
{ | ||
name: "good sentence", | ||
raw: "$VRACK,001*50", | ||
msg: ACK{ | ||
AlertIdentifier: 1, | ||
}, | ||
}, | ||
{ | ||
name: "invalid nmea: AlertIdentifier", | ||
raw: "$VRACK,x*19", | ||
err: "nmea: VRACK invalid alert identifier: x", | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
m, err := Parse(tt.raw) | ||
if tt.err != "" { | ||
assert.Error(t, err) | ||
assert.EqualError(t, err, tt.err) | ||
} else { | ||
assert.NoError(t, err) | ||
ack := m.(ACK) | ||
ack.BaseSentence = BaseSentence{} | ||
assert.Equal(t, tt.msg, ack) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package nmea | ||
|
||
const ( | ||
// TypeACN type of ACN sentence for alert command | ||
TypeACN = "ACN" | ||
) | ||
|
||
// ACN - Alert command. Used for acknowledge, silence, responsibility transfer and to request repeat of alert. | ||
// https://www.furuno.it/docs/INSTALLATION%20MANUALIME44900D_FA170.pdf Furuno CLASS A AIS Model FA-170 (page 49) | ||
// https://www.furuno.it/docs/INSTALLATION%20MANUALgp170_installation_manual.pdf GPS NAVIGATOR Model GP-170 (page 42) | ||
// | ||
// Format: $--ACN,hhmmss.ss,AAA,x.x,x.x,A,A*hh<CR><LF> | ||
// Example: $VRACN,220516,BPMP1,A,A,Bilge pump alarm1*43 | ||
type ACN struct { | ||
BaseSentence | ||
|
||
// Time is time of alarm condition change, UTC (000000.00 - 240001.00) | ||
Time Time // 0 | ||
|
||
// ManufacturerMnemonicCode is manufacturer mnemonic code | ||
ManufacturerMnemonicCode string // 1 | ||
|
||
// AlertIdentifier is alert identifier (001 to 99999) | ||
AlertIdentifier int64 // 2 | ||
|
||
// AlertInstance is alert instance | ||
AlertInstance int64 // 3 | ||
|
||
// Command is Alert command | ||
// * A - acknowledge, | ||
// * Q - request/repeat information | ||
// * O - responsibility transfer | ||
// * S - silence | ||
Command string // 4 | ||
|
||
// State is alarm state | ||
// * C - command | ||
// * possible more classifier values but these are not mentioned in manual | ||
State string // 5 | ||
} | ||
|
||
// newACN constructor | ||
func newACN(s BaseSentence) (ACN, error) { | ||
p := NewParser(s) | ||
p.AssertType(TypeACN) | ||
return ACN{ | ||
BaseSentence: s, | ||
Time: p.Time(0, "time"), | ||
ManufacturerMnemonicCode: p.String(1, "manufacturer mnemonic code"), | ||
AlertIdentifier: p.Int64(2, "alert identifier"), | ||
AlertInstance: p.Int64(3, "alert instance"), | ||
Command: p.EnumString(4, "alert command", AlertCommandAcknowledge, AlertCommandRequestRepeatInformation, AlertCommandResponsibilityTransfer, AlertCommandSilence), | ||
State: p.String(5, "alarm state"), | ||
}, p.Err() | ||
} |
Oops, something went wrong.