[erlang-questions] decoding nmea messages
Hynek Vychodil
hynek@REDACTED
Fri Aug 13 00:00:51 CEST 2010
Basic message parsing is very simple
-module(nmea0183).
-export([parse_msg/1, split/1]).
split(Bin) ->
[ X || <<$$,_/binary>> = X <- binary:split(Bin, <<"\r\n">>)].
parse_msg(Bin) ->
[<<$$, Msg/binary>>, Crc] = binary:split(Bin, <<$*>>),
IsCrc = checkcrc(Msg, Crc),
<<Sender:2/binary, Type:3/binary, Rest/binary>> = Msg,
Values = case Rest of
<<>> -> [];
_ -> tl(binary:split(Rest, <<$,>>, [global]))
end,
{Sender, Type, Values, IsCrc}.
checkcrc(_, <<>>) -> nocrc;
checkcrc(Msg, <<H,L>>) ->
Crc = hdv(H)*16 + hdv(L),
Crc = crc(Msg),
crc.
crc(Msg) ->
lists:foldl(fun(X, A) -> X bxor A end, 0, binary_to_list(Msg)).
hdv(X) when X >= $0, X =< $9 -> X band 15;
hdv(X) -> 9 + (X band 15).
43> nmea0183:parse_msg(<<"$GPGSV,2,1,08,11,74,137,45,20,58,248,43,07,27,309,00,14,23,044,36*7A">>).
{<<"GP">>,<<"GSV">>,
[<<"2">>,<<"1">>,<<"08">>,<<"11">>,<<"74">>,<<"137">>,
<<"45">>,<<"20">>,<<"58">>,<<"248">>,<<"43">>,<<"07">>,
<<"27">>,<<"309">>,<<"00">>,<<"14">>,<<"23">>,<<"044">>,
<<"36">>],
crc}
44> nmea0183:parse_msg(<<"$GPGSA,A,3,20,11,25,01,14,31,,,,,,,2.6,1.7,1.9*3B">>).
{<<"GP">>,<<"GSA">>,
[<<"A">>,<<"3">>,<<"20">>,<<"11">>,<<"25">>,<<"01">>,
<<"14">>,<<"31">>,<<>>,<<>>,<<>>,<<>>,<<>>,<<>>,<<"2.6">>,
<<"1.7">>,<<"1.9">>],
crc}
45> nmea0183:parse_msg(<<"$GPAAM,A,A,0.10,N,WPTNME*32">>)).
{<<"GP">>,<<"AAM">>,
[<<"A">>,<<"A">>,<<"0.10">>,<<"N">>,<<"WPTNME">>],
crc}
But if you want parse value of each field you have to do more work.
On Thu, Aug 12, 2010 at 4:19 PM, info <info@REDACTED> wrote:
> Hi Richard,
> The fields don't contain commas but sometimes they are empty. Therefore the size of the messages is not a constant.
> And what about the syntax analysis if each field is considered as a binary ?
> Someone suggest to use regexp ...
> John
> On Aug 12, 2010, at 5:44 AM, info wrote:
>
>> Hi All,
>> According to your experience, what is the best method for decoding an NMEA 0183 message ? I mean:
>> - extract each field,
>> - detect those which are missing,
>> - check syntax
>
> You mean things like the example in the Wikipedia?
>
> $GPAAM,A,A,0.10,N,WPTNME*32
>
> Binary matching will let you
> - check for $
> - extract GP (talker)
> - extract AAM (type)
> - extract the rest (because you know how long the binary is)
> - check for *
> - extract the two hex digits
> - check for "\r\n"
> As for "the rest", I haven't read the standard, so I don't know
> whether the fields can contain commas or not. If not, you can
> break "the rest" up using binary:split/[2,3]. Where you go from
> there depends on what the kind of message at hand expects to find.
>
--
--Hynek (Pichi) Vychodil
Analyze your data in minutes. Share your insights instantly. Thrill
your boss. Be a data hero!
Try GoodData now for free: www.gooddata.com
More information about the erlang-questions
mailing list