mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-03-09 15:40:03 +00:00
547 lines
No EOL
20 KiB
Lua
547 lines
No EOL
20 KiB
Lua
common_path = '/usr/share/gpoint/tests/luaunitlib/?.lua;'
|
||
package.path = common_path .. package.path
|
||
|
||
lu = require('luaunit')
|
||
----------------------------------------------------------------------------
|
||
-- nmea test
|
||
|
||
-- Bitxor
|
||
-- checkcrc
|
||
-- getcropdata
|
||
----------------------------------------------------------------------------
|
||
|
||
function createGnssForm()
|
||
local GnssData = {
|
||
warning = {app, gga, rmc, vtg, gsa, gp}
|
||
}
|
||
return GnssData
|
||
end
|
||
-- To calculate the checksum
|
||
-- Bitwise xor
|
||
local function BitXOR(a, b)
|
||
local p, c = 1, 0
|
||
while a > 0 and b > 0 do
|
||
local ra, rb = a % 2, b % 2
|
||
if ra ~= rb then c = c + p end
|
||
a, b, p = (a - ra) / 2, (b - rb) / 2, p * 2
|
||
end
|
||
|
||
if a < b then a = b end
|
||
while a > 0 do
|
||
local ra = a % 2
|
||
if ra > 0 then c = c + p end
|
||
a, p = (a - ra) / 2, p * 2
|
||
end
|
||
return c
|
||
end
|
||
|
||
-- To calculate the checksum
|
||
function decimalToHex(num)
|
||
if num == 0 then
|
||
return '0'
|
||
end
|
||
|
||
local neg = false
|
||
if num < 0 then
|
||
neg = true
|
||
num = num * -1
|
||
end
|
||
|
||
local hexstr = "0123456789ABCDEF"
|
||
local result = ""
|
||
while num > 0 do
|
||
local n = math.mod(num, 16)
|
||
result = string.sub(hexstr, n + 1, n + 1) .. result
|
||
num = math.floor(num / 16)
|
||
end
|
||
|
||
if neg then
|
||
result = '-' .. result
|
||
end
|
||
return result
|
||
end
|
||
|
||
-- Сalculate the checksum (CRC-8)
|
||
function checkCRC(data)
|
||
local crc8 = string.sub(data, #data - 1)
|
||
data = string.sub(data, 2, #data - 3)
|
||
|
||
local b_sum = string.byte(data, 1)
|
||
for i = 2, #data do
|
||
b_sum = BitXOR(b_sum, string.byte(data, i))
|
||
end
|
||
|
||
return decimalToHex(b_sum) == crc8 and true or false
|
||
end
|
||
|
||
--Converting coordinates from the NMEA protocol to degrees
|
||
function nmeaCoordinatesToDouble(coord)
|
||
local deg = math.floor(coord / 100)
|
||
return deg + (coord - 100 * deg) / 60
|
||
end
|
||
|
||
--We are looking for the desired data line in the line received from the device
|
||
function findInResp(data, begin)
|
||
local err = true
|
||
local b = string.find(data, begin)
|
||
local e = string.find(data, "\r\n", b)
|
||
|
||
if b and e then
|
||
err = false
|
||
else
|
||
b = nil
|
||
e = nil
|
||
end
|
||
return err, b, e
|
||
end
|
||
|
||
function getCropData(data, msg)
|
||
local err, b, e = findInResp(data, msg)
|
||
if not err then
|
||
data = string.gsub(string.sub(data, b, e), '%c', "")
|
||
if checkCRC(data) then
|
||
data = string.gsub(data, msg, '', 1)
|
||
data = string.gsub(data, "*%d+%w+", '', 1)
|
||
err = {false, "OK"}
|
||
else
|
||
err = {true, "Checksum error"}
|
||
data = nil
|
||
end
|
||
else
|
||
err = {true, "No data found"}
|
||
data = nil
|
||
end
|
||
return err, data
|
||
end
|
||
|
||
-- Creating a table with data before adding data to a single space
|
||
function doTable(data, keys)
|
||
local tabl = {}
|
||
|
||
while string.find(data, ',,') do
|
||
data = string.gsub(data, ',,', ",-,")
|
||
end
|
||
|
||
local i = 1
|
||
for val in string.gmatch(data, "[^,]+") do
|
||
tabl[keys[i]] = val
|
||
i = i + 1
|
||
end
|
||
return tabl
|
||
end
|
||
|
||
-- The function of searching the time zone by the received coordinates
|
||
function findTimeZone(time, date, lon)
|
||
local datetime = { year,month,day,hour,min,sec }
|
||
-- calculate the time zone by coordinates
|
||
local timeZone = math.floor((tonumber(lon) + (7.5 * (tonumber(lon) > 0 and 1.0 or -1.0))) / 15.0)
|
||
|
||
datetime.hour, datetime.min, datetime.sec = string.match(time, "(%d%d)(%d%d)(%d%d)")
|
||
datetime.day, datetime.month, datetime.year = string.match(date,"(%d%d)(%d%d)(%d%d)")
|
||
datetime.year = "20" .. datetime.year -- Someone change this to 21 in the 2100 year
|
||
|
||
--we request the unix time and then add the time zone
|
||
local unix = os.time(datetime)
|
||
unix = unix + ((math.floor(timeZone* 100)) % 100) * 36
|
||
unix = unix + math.floor(timeZone) * 3600
|
||
|
||
return os.date("*t", unix)
|
||
end
|
||
-- Add 0 for the time and date values if < 10
|
||
function addZero(val)
|
||
return tonumber(val) > 9 and tostring(val) or '0' .. tostring(val)
|
||
end
|
||
|
||
---------------------------------------------------------------------------------------------------------------
|
||
-- GGA - Global Positioning System Fix Data
|
||
function getGGA(resp)
|
||
local err, gga = getCropData(resp, "$GPGGA,")
|
||
if not err[1] then
|
||
local ggakeys = {
|
||
"utc", -- UTC of this position report, hh is hours, mm is minutes, ss.ss is seconds.
|
||
"latitude", -- Latitude, dd is degrees, mm.mm is minutes
|
||
"ne", -- N or S (North or South)
|
||
"longitude", -- Longitude, dd is degrees, mm.mm is minutes
|
||
"ew", -- E or W (East or West)
|
||
"qual", -- GPS Quality Indicator (non null)
|
||
"sat", -- Number of satellites in use, 00 - 12
|
||
"hdp", -- Horizontal Dilution of precision (meters)
|
||
"alt", -- Antenna Altitude above/below mean-sea-level (geoid) (in meters)
|
||
"ualt", -- Units of antenna altitude, meters
|
||
"gsep", -- Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level
|
||
"ugsep", -- Units of geoidal separation, meters
|
||
"age", -- Age of differential GPS data, time in seconds since last SC104 type 1 or 9 update, null field when DGPS is not used
|
||
"drs" -- Differential reference station ID, 0000-1023
|
||
}
|
||
|
||
if string.gsub(gga, ',', '') ~= '0' then
|
||
gga = doTable(gga, ggakeys)
|
||
else
|
||
err = {true, "Bad GGA data"}
|
||
gga = nil
|
||
end
|
||
end
|
||
return err, gga
|
||
end
|
||
|
||
-- RMC - Recommended Minimum Navigation Information
|
||
function getRMC(resp)
|
||
local err, rmc = getCropData(resp, "$GPRMC,")
|
||
if not err[1] then
|
||
local rmckeys = {
|
||
"utc", -- UTC of position fix, hh is hours, mm is minutes, ss.ss is seconds.
|
||
"valid", -- Status, A = Valid, V = Warning
|
||
"latitude", -- Latitude, dd is degrees. mm.mm is minutes.
|
||
"ns", -- N or S
|
||
"longitude", -- Longitude, ddd is degrees. mm.mm is minutes.
|
||
"ew", -- E or W
|
||
"knots", -- Speed over ground, knots
|
||
"tmgdt", -- Track made good, degrees true
|
||
"date", -- Date, ddmmyy
|
||
"mv", -- Magnetic Variation, degrees
|
||
"ewm", -- E or W
|
||
"nstat" -- Nav Status (NMEA 4.1 and later) A=autonomous, D=differential, E=Estimated, ->
|
||
-- -> M=Manual input mode N=not valid, S=Simulator, V = Valid
|
||
}
|
||
|
||
if not string.find(rmc, 'V') then
|
||
rmc = doTable(rmc, rmckeys)
|
||
else
|
||
err = {true, "Bad RMC data"}
|
||
rmc = nil
|
||
end
|
||
end
|
||
return err, rmc
|
||
end
|
||
|
||
-- VTG - Track made good and Ground speed
|
||
function getVTG(resp)
|
||
local err, vtg = getCropData(resp, "$GPVTG,")
|
||
if not err[1] then
|
||
local vtgkeys = {
|
||
"course_t", -- Course over ground, degrees True
|
||
't', -- T = True
|
||
"course_m", -- Course over ground, degrees Magnetic
|
||
'm', -- M = Magnetic
|
||
"knots", -- Speed over ground, knots
|
||
'n', -- N = Knots
|
||
"speed", -- Speed over ground, km/hr
|
||
'k', -- K = Kilometers Per Hour
|
||
"faa" -- FAA mode indicator (NMEA 2.3 and later)
|
||
}
|
||
|
||
if string.find(vtg, 'A') or string.find(vtg, 'D') then
|
||
vtg = doTable(vtg, vtgkeys)
|
||
else
|
||
err = {true, "Bad VTG data"}
|
||
vtg = nil
|
||
end
|
||
end
|
||
return err, vtg
|
||
end
|
||
|
||
--GSA - GPS DOP and active satellites
|
||
function getGSA(resp)
|
||
local err, gsa = getCropData(resp, "$GPGSA,")
|
||
if not err[1] then
|
||
local gsakeys = {
|
||
"smode", -- Selection mode: M=Manual, forced to operate in 2D or 3D, A=Automatic, 2D/3D
|
||
"mode", -- Mode (1 = no fix, 2 = 2D fix, 3 = 3D fix)
|
||
"id1", -- ID of 1st satellite used for fix
|
||
"id2", -- ID of 2nd satellite used for fix
|
||
"id3", -- ID of 3rd satellite used for fix
|
||
"id4", -- ID of 4th satellite used for fix
|
||
"id5", -- ID of 5th satellite used for fix
|
||
"id6", -- ID of 6th satellite used for fix
|
||
"id7", -- ID of 7th satellite used for fix
|
||
"id8", -- ID of 8th satellite used for fix
|
||
"id9", -- ID of 9th satellite used for fix
|
||
"id10", -- ID of 10th satellite used for fix
|
||
"id11", -- ID of 11th satellite used for fix
|
||
"id12", -- ID of 12th satellite used for fix
|
||
"pdop", -- PDOP
|
||
"hdop", -- HDOP
|
||
"vdop" -- VDOP
|
||
}
|
||
|
||
if string.find(gsa, '2') then
|
||
gsa = doTable(gsa, gsakeys)
|
||
else
|
||
err = {true, "Bad GSA data"}
|
||
gsa = nil
|
||
end
|
||
end
|
||
return err, gsa
|
||
end
|
||
|
||
function parseAllData(resp)
|
||
local GnssData = createGnssForm()
|
||
GnssData.warning.gga, GnssData["GGA"] = getGGA(resp)
|
||
GnssData.warning.rmc, GnssData["RMC"] = getRMC(resp)
|
||
GnssData.warning.vtg, GnssData["VTG"] = getVTG(resp)
|
||
GnssData.warning.gsa, GnssData["GSA"] = getGSA(resp)
|
||
return GnssData
|
||
end
|
||
|
||
-- This function prepares data for the web application (Some custom data)
|
||
function getGPoint(resp)
|
||
|
||
local web = {
|
||
longitude = '-',
|
||
latitude = '-',
|
||
altitude = '-',
|
||
utc = '-',
|
||
date = '-',
|
||
nsat = '-',
|
||
hdop = '-',
|
||
cog = '-',
|
||
spkm = '-'
|
||
}
|
||
|
||
local GnssData = parseAllData(resp)
|
||
local err = {true, ""}
|
||
|
||
if not GnssData.warning.gga[1] then
|
||
web.latitude = string.format("%0.6f", nmeaCoordinatesToDouble(GnssData.GGA.latitude))
|
||
web.longitude = string.format("%0.6f",nmeaCoordinatesToDouble(GnssData.GGA.longitude))
|
||
web.altitude = GnssData.GGA.alt
|
||
web.nsat = GnssData.GGA.sat
|
||
web.hdop = GnssData.GGA.hdp
|
||
else
|
||
err[2] = "GGA: " .. GnssData.warning.gga[2] .. ' '
|
||
end
|
||
|
||
if not GnssData.warning.vtg[1] then
|
||
web.cog = GnssData.VTG.course_t
|
||
web.spkm = GnssData.VTG.speed
|
||
else
|
||
err[2] = err[2] .. "VTG: " .. GnssData.warning.vtg[2] .. ' '
|
||
end
|
||
|
||
if not GnssData.warning.rmc[1] then
|
||
local dateTime = findTimeZone(GnssData.RMC.utc, GnssData.RMC.date, nmeaCoordinatesToDouble(GnssData.RMC.longitude))
|
||
|
||
web.utc = string.format("%s:%s", addZero(dateTime.hour), addZero(dateTime.min))
|
||
web.date = string.format("%s.%s.%d", addZero(dateTime.day), addZero(dateTime.month), dateTime.year)
|
||
else
|
||
err[2] = err[2] .. "RMC: " .. GnssData.warning.vtg[2]
|
||
end
|
||
|
||
if GnssData.warning.gga[1] and GnssData.warning.vtg[1] and GnssData.warning.rmc[1] then
|
||
err[2] = "Updating data..."
|
||
else
|
||
err = {false, "OK"}
|
||
end
|
||
|
||
return err, web
|
||
end
|
||
|
||
-----------------------------------------------------------------------------------
|
||
-- public
|
||
-----------------------------------------------------------------------------------
|
||
|
||
function getData(line, port)
|
||
local err, resp = serial.read(port)
|
||
local GnssData = createGnssForm()
|
||
if err[1] then
|
||
GnssData.warning.app = {true, err[2]}
|
||
return GnssData
|
||
end
|
||
|
||
GnssData.warning.app = {false, "OK"}
|
||
|
||
if line == "GP" then
|
||
GnssData.warning.gp, GnssData["gp"] = getGPoint(resp)
|
||
elseif line == "GGA" then
|
||
GnssData.warning.gga, GnssData["gga"] = getGGA(resp)
|
||
elseif line == "RMC" then
|
||
GnssData.warning.rmc, GnssData["rmc"] = getRMC(resp)
|
||
elseif line == "VTG" then
|
||
GnssData.warning.vtg, GnssData["vtg"] = getVTG(resp)
|
||
elseif line == "GSA" then
|
||
GnssData.warning.gsa, GnssData["gsa"] = getGSA(resp)
|
||
else
|
||
GnssData.warning.app = {true, "Bad argument..."}
|
||
end
|
||
return GnssData
|
||
end
|
||
|
||
function getAllData(port)
|
||
local err, resp = serial.read(port)
|
||
local GnssData = createGnssForm()
|
||
if err[1] then
|
||
GnssData.warning.app = {true, err[2]}
|
||
return GnssData
|
||
end
|
||
|
||
GnssData = parseAllData(resp)
|
||
GnssData.warning.gp, GnssData["gp"] = getGPoint(resp)
|
||
GnssData.warning.app = {false, "OK"}
|
||
return GnssData
|
||
end
|
||
|
||
------------------------------------------------------------------------------
|
||
|
||
local goodGNSSSdata = {
|
||
"$GPRMC,113702.568,V,4154.931,N,08002.497,W,95.5,0.02,220721,,E*4E",
|
||
"$GPGGA,113703.568,4154.931,N,08002.497,W,0,00,,,M,,M,,*52",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.1,0.8,0.6*3F",
|
||
"$GPRMC,113705.568,V,4154.933,N,08002.497,W,86.0,-0.05,220721,,E*66",
|
||
"$GPGGA,113706.568,4154.933,N,08002.497,W,0,00,0.8,,M,,M,,*73",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.2,0.0,0.4*36",
|
||
"$GPRMC,113708.568,V,4154.935,N,08002.498,W,55.1,-0.10,220721,,E*69",
|
||
"$GPGGA,113709.568,4154.935,N,08002.498,W,0,00,0.0,,M,,M,,*7D",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.7,0.2,0.8*3C",
|
||
"$GPRMC,113711.568,V,4154.937,N,08002.498,W,95.0,-0.10,220721,,E*6E",
|
||
"$GPGGA,113712.568,4154.937,N,08002.498,W,0,00,0.2,,M,,M,,*77",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.7,0.6,0.3*32",
|
||
"$GPRMC,113714.568,V,4154.939,N,08002.498,W,28.0,-0.07,220721,,E*65",
|
||
"$GPGGA,113715.568,4154.939,N,08002.498,W,0,00,0.6,,M,,M,,*7A",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,1.0,1.0,0.5*34",
|
||
"$GPRMC,113717.568,V,4154.940,N,08002.498,W,30.1,0.03,220721,,E*49",
|
||
"$GPGGA,113718.568,4154.940,N,08002.498,W,0,00,1.0,,M,,M,,*7E",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.5,0.1,0.2*36",
|
||
"$GPRMC,113720.568,V,4154.942,N,08002.498,W,0.2,-0.02,220721,,E*53",
|
||
"$GPGGA,113721.568,4154.942,N,08002.498,W,0,00,0.1,,M,,M,,*76",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.2,0.5,0.7*30",
|
||
"$GPRMC,113723.568,V,4154.944,N,08002.498,W,53.6,0.05,220721,,E*4E",
|
||
"$GPGGA,113724.568,4154.944,N,08002.498,W,0,00,0.5,,M,,M,,*71",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,1.0,0.6,0.1*37",
|
||
"$GPRMC,113726.568,V,4154.946,N,08002.498,W,76.6,0.04,220721,,E*4F",
|
||
"$GPGGA,113727.568,4154.946,N,08002.498,W,0,00,0.6,,M,,M,,*73",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.2,0.3,0.7*37",
|
||
"$GPRMC,113729.568,V,4154.948,N,08002.497,W,30.9,0.12,220721,,E*4B",
|
||
"$GPGGA,113730.568,4154.948,N,08002.497,W,0,00,0.3,,M,,M,,*71",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.5,0.2,0.2*34",
|
||
"$GPRMC,113732.568,V,4154.949,N,08002.497,W,47.2,0.20,220721,,E*4A",
|
||
"$GPGGA,113733.568,4154.949,N,08002.497,W,0,00,0.2,,M,,M,,*72",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.3,0.8,0.2*39",
|
||
"$GPRMC,113735.568,V,4154.951,N,08002.496,W,31.1,0.13,220721,,E*47",
|
||
"$GPGGA,113736.568,4154.951,N,08002.496,W,0,00,0.8,,M,,M,,*75",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.2,0.6,0.1*35",
|
||
"$GPRMC,113738.568,V,4154.953,N,08002.496,W,58.2,0.10,220721,,E*47",
|
||
"$GPGGA,113739.568,4154.953,N,08002.496,W,0,00,0.6,,M,,M,,*76",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.6,0.9,0.7*39",
|
||
"$GPRMC,113741.568,V,4154.955,N,08002.496,W,88.3,0.03,220721,,E*41",
|
||
"$GPGGA,113742.568,4154.955,N,08002.496,W,0,00,0.9,,M,,M,,*73",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.8,0.8,0.1*30",
|
||
"$GPRMC,113744.568,V,4154.956,N,08002.496,W,89.3,0.10,220721,,E*44",
|
||
"$GPGGA,113745.568,4154.956,N,08002.496,W,0,00,0.8,,M,,M,,*76",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.9,0.2,1.0*3B",
|
||
"$GPRMC,113747.568,V,4154.958,N,08002.495,W,99.1,0.14,220721,,E*4D",
|
||
"$GPGGA,113748.568,4154.958,N,08002.495,W,0,00,0.2,,M,,M,,*7C",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.7,0.1,0.2*35",
|
||
"$GPRMC,113750.568,V,4154.960,N,08002.495,W,84.0,0.19,220721,,E*40",
|
||
"$GPGGA,113751.568,4154.960,N,08002.495,W,0,00,0.1,,M,,M,,*7C",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.3,1.0,0.5*36",
|
||
"$GPRMC,113753.568,V,4154.962,N,08002.495,W,24.0,0.13,220721,,E*41",
|
||
"$GPGGA,113754.568,4154.962,N,08002.495,W,0,00,1.0,,M,,M,,*7B",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.7,0.8,0.9*37",
|
||
"$GPRMC,113756.568,V,4154.963,N,08002.494,W,27.8,0.03,220721,,E*4E",
|
||
"$GPGGA,113757.568,4154.963,N,08002.494,W,0,00,0.8,,M,,M,,*71",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.5,0.4,0.7*37"
|
||
}
|
||
|
||
local badGNSSSdata = {
|
||
"$GPRMC,113702.568,V,4154.931,N,08002.497,W,95.5,0.02,220721,,E*48",
|
||
"$GPGGA,113703.568,4154.931,N,08002.497,W,0,00,,,M,,M,,*54",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.1,0.8,0.6*33",
|
||
"$GPRMC,113720.568,V,4154.942,N,08002.498,W,0.2,-0.02,220721,,E*5F",
|
||
"$GPGGA,113721.568,4154.942,N,08002.498,W,0,00,0.1,,M,,M,,*82",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.2,0.5,0.7*35",
|
||
"$GPRMC,113723.568,V,4154.944,N,08002.498,W,53.6,0.05,220721,,E*5A",
|
||
"$GPGGA,113724.568,4154.944,N,08002.498,W,0,00,0.5,,M,,M,,*12",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,1.0,0.6,0.1*35",
|
||
"$GPRMC,113726.568,V,4154.946,N,08002.498,W,76.6,0.04,220721,,E*9E",
|
||
"$GPGGA,113727.568,4154.946,N,08002.498,W,0,00,0.6,,M,,M,,*94",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.2,0.3,0.7*32",
|
||
"$GPRMC,113729.568,V,4154.948,N,08002.497,W,30.9,0.12,220721,,E*9C",
|
||
"$GPGGA,113730.568,4154.948,N,08002.497,W,0,00,0.3,,M,,M,,*79",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.5,0.2,0.2*39",
|
||
"$GPRMC,113705.568,V,4154.933,N,08002.497,W,86.0,-0.05,220721,,E*90",
|
||
"$GPGGA,113706.568,4154.933,N,08002.497,W,0,00,0.8,,M,,M,,*42",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.2,0.0,0.4*43",
|
||
"$GPRMC,113708.568,V,4154.935,N,08002.498,W,55.1,-0.10,220721,,E*44",
|
||
"$GPGGA,113709.568,4154.935,N,08002.498,W,0,00,0.0,,M,,M,,*4A",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.7,0.2,0.8*4D",
|
||
"$GPRMC,113711.568,V,4154.937,N,08002.498,W,95.0,-0.10,220721,,E*44",
|
||
"$GPGGA,113712.568,4154.937,N,08002.498,W,0,00,0.2,,M,,M,,*44",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.7,0.6,0.3*4D",
|
||
"$GPRMC,113714.568,V,4154.939,N,08002.498,W,28.0,-0.07,220721,,E*4D",
|
||
"$GPGGA,113715.568,4154.939,N,08002.498,W,0,00,0.6,,M,,M,,*4D",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,1.0,1.0,0.5*24",
|
||
"$GPRMC,113717.568,V,4154.940,N,08002.498,W,30.1,0.03,220721,,E*59",
|
||
"$GPGGA,113718.568,4154.940,N,08002.498,W,0,00,1.0,,M,,M,,*4D",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.5,0.1,0.2*39",
|
||
"$GPGGA,113736.568,4154.951,N,08002.496,W,0,00,0.8,,M,,M,,*79",
|
||
"$GPGSA,A,3,09,02,08,05,11,15,,,,,,,0.2,0.6,0.1*39",
|
||
"$GPRMC,113738.568,V,4154.953,N,08002.496,W,58.2,0.10,220721,,E*67",
|
||
"$GPGGA,113739.568,4154.953,N,08002.496,W,0,00,0.6,,M,,M,,*79",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.6,0.9,0.7*35",
|
||
"$GPRMC,113741.568,V,4154.955,N,08002.496,W,88.3,0.03,220721,,E*31",
|
||
"$GPGGA,113742.568,4154.955,N,08002.496,W,0,00,0.9,,M,,M,,*33",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.8,0.8,0.1*34",
|
||
"$GPRMC,113744.568,V,4154.956,N,08002.496,W,89.3,0.10,220721,,E*34",
|
||
"$GPGGA,113745.568,4154.956,N,08002.496,W,0,00,0.8,,M,,M,,*75",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.9,0.2,1.0*4B",
|
||
"$GPRMC,113747.568,V,4154.958,N,08002.495,W,99.1,0.14,220721,,E*5D",
|
||
"$GPGGA,113748.568,4154.958,N,08002.495,W,0,00,0.2,,M,,M,,*5C",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.7,0.1,0.2*55",
|
||
"$GPRMC,113750.568,V,4154.960,N,08002.495,W,84.0,0.19,220721,,E*50",
|
||
"$GPGGA,113751.568,4154.960,N,08002.495,W,0,00,0.1,,M,,M,,*5C",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.3,1.0,0.5*35",
|
||
"$GPRMC,113753.568,V,4154.962,N,08002.495,W,24.0,0.13,220721,,E*51",
|
||
"$GPGGA,113754.568,4154.962,N,08002.495,W,0,00,1.0,,M,,M,,*5B",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.7,0.8,0.9*35",
|
||
"$GPRMC,113756.568,V,4154.963,N,08002.494,W,27.8,0.03,220721,,E*5E",
|
||
"$GPGGA,113757.568,4154.963,N,08002.494,W,0,00,0.8,,M,,M,,*51",
|
||
"$GPGSA,A,2,09,02,08,05,11,15,,,,,,,0.5,0.4,0.7*57"
|
||
}
|
||
|
||
local GNSStr = "$GPRMC,143753.498,V,3854.930,N,07902.496,W,91.3,0.75,220721,,E*4B\r\n\
|
||
$GPGGA,143754.498,3854.930,N,07902.496,W,0,00,,,M,,M,,*53\r\n\
|
||
$GPGSA,A,2,13,09,13,09,18,16,,,,,,,0.1,0.0,0.2*3E\r\n\
|
||
$GPRMC,143756.498,V,3854.931,N,07902.494,W,92.7,0.76,220721,,E*49\r\n\
|
||
$GPGGA,143757.498,3854.931,N,07902.494,W,0,00,0.0,,M,,M,,*7D\r\n\
|
||
$GPGSA,A,2,13,09,13,09,18,16,,,,,,,0.4,0.4,0.5*38\r\n\
|
||
$GPRMC,143759.498,V,3854.932,N,07902.492,W,15.5,0.75,220721,,E*4D\r\n"
|
||
|
||
local badCRC = "$GPRMC,143753.498,V,3854.930,N,07902.496,W,91.3,0.75,220721,,E*6B\r\n\
|
||
$GPGGA,143754.498,3854.930,N,07902.496,W,0,00,,,M,,M,,*43\r\n\
|
||
$GPGSA,A,2,13,09,13,09,18,16,,,,,,,0.1,0.0,0.2*5E\r\n\
|
||
$GPRMC,143756.498,V,3854.931,N,07902.494,W,92.7,0.76,220721,,E*48\r\n\
|
||
$GPGGA,143757.498,3854.931,N,07902.494,W,0,00,0.0,,M,,M,,*4D\r\n\
|
||
$GPGSA,A,2,13,09,13,09,18,16,,,,,,,0.4,0.4,0.5*39\r\n\
|
||
$GPRMC,143759.498,V,3854.932,N,07902.492,W,15.5,0.75,220721,,E*3D\r\n"
|
||
|
||
local nmeaDataType = {"$GPGSA,", "$GPRMC,", "$GPGGA,"}
|
||
local badString = "oskdsajdij232391i*&^^&7^&^(*&*YDUDHJSBDNBNVyywfdywf"
|
||
|
||
function testBitXOR()
|
||
lu.assertEquals(BitXOR(string.byte('q'), string.byte('r')), 3)
|
||
lu.assertEquals(BitXOR(string.byte('a'), string.byte('b')), 3)
|
||
lu.assertEquals(BitXOR(string.byte('1'), string.byte('5')), 4)
|
||
lu.assertEquals(BitXOR(string.byte('0'), string.byte('0')), 0)
|
||
lu.assertEquals(BitXOR(string.byte('9'), string.byte('1')), 8)
|
||
lu.assertEquals(BitXOR(string.byte('f'), string.byte('w')), 17)
|
||
end
|
||
|
||
function testCRC()
|
||
for i = 1, #goodGNSSSdata do
|
||
lu.assertEquals(checkCRC(goodGNSSSdata[i]), true)
|
||
end
|
||
for i = 1, #badGNSSSdata do
|
||
lu.assertEquals(checkCRC(badGNSSSdata[i]), false)
|
||
end
|
||
end
|
||
|
||
function testCropData()
|
||
for i = 1, #nmeaDataType do
|
||
lu.assertEquals(getCropData("", nmeaDataType[i]), {true, "No data found"})
|
||
lu.assertEquals(getCropData(badString, nmeaDataType[i]), {true, "No data found"})
|
||
lu.assertEquals(getCropData(badCRC, nmeaDataType[i]), {true, "Checksum error"})
|
||
lu.assertEquals(getCropData(GNSStr, nmeaDataType[i]), {false, "OK"})
|
||
end
|
||
end
|
||
|
||
os.exit(lu.LuaUnit.run()) |