go-ais
go-ais copied to clipboard
Handle multipart messages
Looks like this package is having issues with multi part messages. This test can be added to nmea_test.go to show the issue:
func TestMultiMessage(t *testing.T) {
nm := NMEACodecNew(ais.CodecNew(false, false))
_, err := nm.ParseSentence("!AIVDM,2,1,0,B,539S:k40000000c3G04PPh63<00000000080000o1PVG2uGD:00000000000,0*34\n!AIVDM,2,2,0,B,00000000000,2*27")
if err != nil {
t.Error(err)
t.Error("Can't handle multipart message")
}
}
@VictorNine ParseSentence
parses one sentence at a time. To read a multi-sentence message, call it on each sentence, checking both for errors and whether the first return value is nil.
This test passes:
func TestMultiMessage(t *testing.T) {
nm := NMEACodecNew(ais.CodecNew(false, false))
_, err := nm.ParseSentence("!AIVDM,2,1,0,B,539S:k40000000c3G04PPh63<00000000080000o1PVG2uGD:00000000000,0*34")
_, err = nm.ParseSentence("!AIVDM,2,2,0,B,00000000000,2*27")
if err != nil {
t.Error(err)
t.Error("Can't handle multipart message")
}
}
That's true, but it does not read anything without both messages. Or am I missing something?
func TestMultiMessage(t *testing.T) {
nm := NMEACodecNew(ais.CodecNew(false, false))
msg, err := nm.ParseSentence("!AIVDM,2,1,0,B,539S:k40000000c3G04PPh63<00000000080000o1PVG2uGD:00000000000,0*34")
if err != nil {
t.Error(err)
t.Error("Can't handle multipart message")
}
if msg == nil {
t.Error("Can't handle multipart message")
}
}
Hi, I'm also interested in how to properly read multipart messages. @simeonmiteff could you let me know whether the below code looks sensible?
package internal
import (
"testing"
"github.com/BertoldVdb/go-ais"
"github.com/BertoldVdb/go-ais/aisnmea"
)
func TestProperUseOfParseSentence(t *testing.T) {
// given some (multipart) messages
messages := []string{
`\s:2573210,c:1610637868*0E\!BSVDM,2,1,9,B,55UmS>81VSWtcQPSJ00hth74000000000000001J58>544GS08R0EAiDmCQ0,0*15`,
`\s:2573210,c:1610637868*0E\!BSVDM,2,2,9,B,00000000000,2*37`,
`\s:2573205,c:1610637868*0A\!BSVDM,2,1,6,A,53n0LR42BoKthAMN221<d4p@V0l58uV2222222162Pv894G30=E0CPCQiD` + "`" + `8,0*57`,
`\s:2573205,c:1610637868*0A\!BSVDM,2,2,6,A,88888888880,2*3B`,
`\s:2573445,c:1610637868*08\!BSVDM,2,1,0,B,53mro7400000hhm0000P5=@TpL0000000000000N1p63340Ht:8888888888,0*5C`,
`\s:2573445,c:1610637868*08\!BSVDM,2,2,0,B,88888888880,2*3E`,
}
// we'd like to parse messages into this slice
decodedMessages := make([]aisnmea.VdmPacket, 0)
nm := aisnmea.NMEACodecNew(ais.CodecNew(false, false))
for _, message := range messages {
decodedMessage, err := nm.ParseSentence(message)
if err != nil {
t.Error("Oops! Something went wrong while parsing:", err)
}
if decodedMessage == nil {
// Nothing to do here, message we passed was probably a fragment of
// a multipart message, and happened to not be the last fragment.
// This is fine (?)
continue
}
decodedMessages = append(decodedMessages, *decodedMessage)
}
// Perform some basic checks against what we got back
if len(decodedMessages) != 3 {
t.Error("Incorrect number of parsed messages")
}
if decodedMessages[0].TagBlock.Time != 1610637868 {
t.Error("Incorrect tagblock time for first message")
}
}
The message says how many parts there are. !BSVDM,2,1 would mean first of 2. But the easiest is probably that the package receives the two messages with a \n between?
The message says how many parts there are. !BSVDM,2,1 would mean first of 2. But the easiest is probably that the package receives the two messages with a \n between?
Hi @VictorNine. I'm curious: Why is parsing the individual parts one by one and expecting return values of nil
when the parser has incomplete info about a multipart message not sufficient? I might use this lib, and your previuos comment makes it seem like it's a bad thing, but I don't understand why. It would be of great help if you could mention why the example in your comment (& the example I posted above) is not OK.
Basically there is no way to parse multi part messages now (as far as I know).
Hello,
You should be able to pass the multipart messages one by one to ParseSentence. You will get a non-nil result when a message is completely decoded. If you supply only one part the message does not get decoded as it is not complete. You don't need to send the messages in order.
I will verify this in a few hours.
Sincerely, Bertold
What's the status on this? Using this clip of live AIS data, fed to the decoder line by line, I get a nil response to both parts of the fragmented sentence, all others decode fine.
!BSVDM,1,1,,B,13mqtQ70001FmVlWnt37LFuP0<1F,0*3D
!BSVDM,1,1,,B,13nELB?P000qjJpUij:nBgwL05cH,0*57
!BSVDM,2,1,5,A,53cA4F02Ae>e0<eR221=@u8pE>2222222222221JC0G4F4RT0BTQDlk1CC@C,0*1A
!BSVDM,2,2,5,A,`8888888880,2*60
!BSVDM,1,1,,B,13nG3k001n0UC2lT59g35RQJ00S2,0*79
!BSVDM,1,1,,B,13mB7d0000Pr;EnVed9JjrWN0<0C,0*2A
If you are feeding the lines one-by-one you should indeed get one result for the two-part message. If this does not happen you might have found a bug, I will investigate sometime next week!