2020-01-11 12:07:58 -04:00
|
|
|
-- Script decodes, checks and prints NMEA messages
|
2023-02-13 22:45:19 -04:00
|
|
|
-- luacheck: only 0
|
2020-01-11 12:07:58 -04:00
|
|
|
|
|
|
|
-- find the serial first (0) scripting serial port instance
|
|
|
|
local port = serial:find_serial(0)
|
|
|
|
|
|
|
|
if not port then
|
|
|
|
gcs:send_text(0, "No Scripting Serial Port")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- begin the serial port
|
2020-07-18 12:18:19 -03:00
|
|
|
-- NMEA is usually 4800 or 9600
|
|
|
|
port:begin(4800)
|
2020-01-11 12:07:58 -04:00
|
|
|
port:set_flow_control(0)
|
|
|
|
|
|
|
|
-- table for strings used in decoding
|
|
|
|
local term = {}
|
|
|
|
local term_is_checksum = false
|
|
|
|
local term_number = 1
|
|
|
|
local checksum = 0
|
2020-07-18 12:18:19 -03:00
|
|
|
local string_complete = false
|
2020-01-11 12:07:58 -04:00
|
|
|
|
|
|
|
-- maximum number of terms we expect in the message
|
|
|
|
local max_terms = 15
|
|
|
|
-- maximum length of terms we expect
|
|
|
|
local max_term_length = 5
|
|
|
|
|
|
|
|
-- decode a basic NMEA string, only check the checksum
|
|
|
|
local function decode_NMEA(byte)
|
|
|
|
local char = string.char(byte)
|
2020-07-18 12:18:19 -03:00
|
|
|
if (char == ',' or char == '\r' or char == '\n' or char == '*') and not string_complete then
|
2020-01-11 12:07:58 -04:00
|
|
|
if char == ',' then
|
|
|
|
-- end of a term, but still counted for checksum
|
|
|
|
checksum = checksum ~ byte
|
|
|
|
end
|
|
|
|
|
|
|
|
-- null terminate and decode latest term
|
|
|
|
if term_is_checksum then
|
|
|
|
-- test the checksum
|
2020-07-18 12:18:19 -03:00
|
|
|
string_complete = true
|
2020-01-11 12:07:58 -04:00
|
|
|
return checksum == tonumber(term[term_number],16)
|
|
|
|
else
|
|
|
|
-- we could further decode the message data here
|
|
|
|
end
|
|
|
|
|
|
|
|
if char == '*' then
|
|
|
|
-- the next characters make up the checksum
|
|
|
|
term_is_checksum = true
|
|
|
|
end
|
|
|
|
|
2020-07-18 12:18:19 -03:00
|
|
|
-- nothing in current term, add a space, makes the print work
|
|
|
|
if not term[term_number] then
|
|
|
|
term[term_number] = ' '
|
|
|
|
end
|
|
|
|
|
2020-01-11 12:07:58 -04:00
|
|
|
-- move onto next term
|
|
|
|
term_number = term_number + 1
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
if char == '$' then
|
|
|
|
-- sentence begin
|
|
|
|
-- clear all flags, reset the term table and checksum
|
|
|
|
term_is_checksum = false
|
|
|
|
term_number = 1
|
|
|
|
checksum = 0
|
|
|
|
term = {}
|
2020-07-18 12:18:19 -03:00
|
|
|
string_complete = false
|
2020-01-11 12:07:58 -04:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- ordinary characters are added to term
|
|
|
|
-- if we have too many terms or they are too long then don't add to them
|
|
|
|
if term_number < max_terms then
|
|
|
|
if term[term_number] then
|
|
|
|
if string.len(term[term_number]) < max_term_length then
|
|
|
|
term[term_number] = term[term_number] .. char
|
|
|
|
end
|
|
|
|
else
|
|
|
|
term[term_number] = char
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- update the checksum
|
|
|
|
if not term_is_checksum then
|
|
|
|
-- checksum is bit wise xor of all characters in the string before the checksum
|
|
|
|
checksum = checksum ~ byte
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- the main update function that is used to read in data from serial port
|
|
|
|
function update()
|
|
|
|
|
|
|
|
if not port then
|
|
|
|
gcs:send_text(0, "no Scripting Serial Port")
|
|
|
|
return update, 100
|
|
|
|
end
|
|
|
|
|
|
|
|
local n_bytes = port:available()
|
|
|
|
while n_bytes > 0 do
|
|
|
|
local byte = port:read()
|
|
|
|
if decode_NMEA(byte) then
|
|
|
|
-- we have got a full NMEA message that has passed the checksum
|
|
|
|
-- concatenate back to full message and print
|
|
|
|
-- don't print the checksum
|
|
|
|
gcs:send_text(0, table.concat(term,",",1,#term-1))
|
|
|
|
|
|
|
|
end
|
|
|
|
n_bytes = n_bytes - 1
|
|
|
|
end
|
|
|
|
|
|
|
|
return update, 100
|
|
|
|
end
|
|
|
|
|
|
|
|
return update, 100
|