more parsing progress on compressed positions

This commit is contained in:
Graham McIntire 2023-02-01 13:34:05 -06:00
parent 5ea16fa5f7
commit c750d5da17
9 changed files with 129 additions and 24 deletions

View file

@ -2,4 +2,6 @@ defmodule Aprs.Convert do
def wind(speed, :ultimeter, :mph), do: speed * 0.0621371192
def temp(value, :ultimeter, :f), do: value * 0.1
def speed(value, :knots, :mph), do: Float.round(value * 1.15077945, 2)
end

View file

@ -208,6 +208,9 @@ defmodule Aprs.Is do
# IO.inspect(parsed_message)
# Logger.debug("SERVER:" <> message)
{:error, :invalid_packet} ->
Logger.debug("PARSE ERROR: invalid packet")
{:error, error} ->
Logger.debug("PARSE ERROR: " <> error)

View file

@ -36,9 +36,9 @@ defmodule Parser do
rescue
_ ->
# Logger.debug("PARSE ERROR: " <> message)
# {:ok, file} = File.open("/home/graham/badpackets.txt", [:append])
# IO.binwrite(file, message <> "\n\n")
# File.close(file)
{:ok, file} = File.open("./badpackets.txt", [:append])
IO.binwrite(file, message <> "\n\n")
File.close(file)
{:error, :invalid_packet}
end
end
@ -161,7 +161,7 @@ defmodule Parser do
[:ok, lat, lon]
end
defp convert_to_base91(<<value::binary-size(4)>>) do
def convert_to_base91(<<value::binary-size(4)>>) do
[v1, v2, v3, v4] = to_charlist(value)
(v1 - 33) * 91 * 91 * 91 + (v2 - 33) * 91 * 91 + (v3 - 33) * 91 + v4
end
@ -236,16 +236,44 @@ defmodule Parser do
end
def parse_position_without_timestamp(
_aprs_messaging?,
<<_dti::binary-size(1), "/", _latitude::binary-size(4), _longitude::binary-size(4),
_sym_table_id::binary-size(1), _cs::binary-size(2), _compression_type::binary-size(1),
_comment::binary>> = message
aprs_messaging?,
<<_dti::binary-size(1), "/", latitude::binary-size(4), longitude::binary-size(4),
sym_table_id::binary-size(1), _cs::binary-size(2), _compression_type::binary-size(1),
comment::binary>> = message
) do
# {:ok, file} = File.open("badpackets.txt")
# IO.puts(file, message)
# {:ok, file} = File.open("./compressed.txt", [:append])
# IO.binwrite(
# file,
# message <>
# "\n" <>
# "aprs_messaging?: #{aprs_messaging?}\n" <>
# "dti: #{dti}\n" <>
# "latitude: #{latitude}\n" <>
# "longitude: #{longitude}\n" <>
# "sym_table_id: #{sym_table_id}\n" <>
# "cs: #{cs}\n" <>
# "compression_type: #{compression_type}\n" <>
# "comment: #{comment}\n\n"
# )
# File.close(file)
# convert_compressed_cs(cs) |> IO.inspect()
Logger.debug("TODO: PARSE COMPRESSED LAT/LON: " <> message)
converted_lat = convert_compressed_lat(latitude)
converted_lon = convert_compressed_lon(longitude)
position = Position.from_decimal(converted_lat, converted_lon)
# converted_cs = convert_compressed_cs(cs)
%{
latitude: converted_lat,
longitude: converted_lon,
position: position,
symbol_table_id: sym_table_id,
# symbol_code: symbol_code,
comment: comment,
data_type: :position,
aprs_messaging?: aprs_messaging?
}
end
def parse_position_with_timestamp(
@ -508,4 +536,44 @@ defmodule Parser do
# defp convert_ultimeter_humidity(hum) do
# hum * 10
# end
def convert_compressed_lat(lat) do
[l1, l2, l3, l4] = to_charlist(lat)
90 - ((l1 - 33) * 91 ** 3 + (l2 - 33) * 91 ** 2 + (l3 - 33) * 91 + l4 - 33) / 380_926
end
def convert_compressed_lon(lon) do
[l1, l2, l3, l4] = to_charlist(lon)
-180 + ((l1 - 33) * 91 ** 3 + (l2 - 33) * 91 ** 2 + (l3 - 33) * 91 + l4 - 33) / 190_463
end
def convert_compressed_cs(cs) do
[c, s] = to_charlist(cs)
c = c - 33
s = s - 33
case c do
x when x in ?!..?z ->
# compressed speed/course value
# speed is returned in knots
%{
course: s * 4,
speed: Convert.speed(1.08 ** s - 1, :knots, :mph)
}
?Z ->
# pre-calculated radio range
%{
range: 2 * 1.08 ** s
}
_ ->
IO.inspect(cs, label: "not parsable")
%{
course: 0,
speed: 0
}
end
end
end

View file

@ -17,8 +17,6 @@ defmodule Parser.Types.Position do
aprs_latitude = aprs_latitude |> String.replace(" ", "0") |> String.pad_leading(9, "0")
aprs_longitude = aprs_longitude |> String.replace(" ", "0") |> String.pad_leading(9, "0")
# Logger.debug("#{aprs_latitude} #{aprs_longitude}")
<<latitude::binary-size(8), lat_direction::binary>> = aprs_latitude
<<longitude::binary-size(8), lon_direction::binary>> = aprs_longitude
@ -28,16 +26,6 @@ defmodule Parser.Types.Position do
<<lon_deg::binary-size(3), lon_min::binary-size(2), lon_fractional::binary-size(3)>> =
convert_garbage_to_zero(longitude)
# %Position{
# lat_degrees: lat_deg |> String.replace(".", "") |> String.to_integer(),
# lat_minutes: lat_min |> String.replace(".", "") |> String.to_integer(),
# lat_fractional: convert_fractional(lat_fractional),
# lat_direction: convert_direction(lat_direction),
# lon_degrees: lon_deg |> String.replace(".", "") |> String.to_integer(),
# lon_minutes: lon_min |> String.replace(".", "") |> String.to_integer(),
# lon_fractional: convert_fractional(lon_fractional),
# lon_direction: convert_direction(lon_direction)
# }
try do
lat =
Geocalc.DMS.to_degrees(%Geocalc.DMS{
@ -61,6 +49,10 @@ defmodule Parser.Types.Position do
end
end
def from_decimal(latitude, longitude) do
%{latitude: latitude, longitude: longitude}
end
defp convert_garbage_to_zero(value) do
try do
_ = String.to_float(value)

View file

@ -73,7 +73,8 @@ defmodule Aprs.MixProject do
{:faker, "~> 0.17.0", only: [:dev, :test]},
{:stream_data, "~> 0.5", only: [:dev, :test]},
{:mix_test_watch, "~> 1.1", only: [:dev, :test]},
{:sobelow, "~> 0.8", only: :dev}
{:sobelow, "~> 0.8", only: :dev},
{:codepagex, "~> 0.1.6"}
]
end

View file

@ -3,9 +3,11 @@
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"codepagex": {:hex, :codepagex, "0.1.6", "49110d09a25ee336a983281a48ef883da4c6190481e0b063afe2db481af6117e", [:mix], [], "hexpm", "1521461097dde281edf084062f525a4edc6a5e49f4fd1f5ec41c9c4955d5bd59"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"convertat": {:hex, :convertat, "1.1.0", "00c125f00a2e06be74d27df5a6b93f9b2d7c27aaa6ecb41d96f009ee7d7bd978", [:mix], [], "hexpm", "603229c43df6769f2166c78c5c3f31316390bf6e19fa8e15f02026170ab51a79"},
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},

View file

@ -13,4 +13,10 @@ defmodule Aprs.ConvertTest do
assert Convert.temp(55, :ultimeter, :f) == 5.5
end
end
describe "speed/3" do
test "converts knots to mph" do
assert Convert.speed(55, :knots, :mph) == 63.29
end
end
end

View file

@ -233,4 +233,13 @@ defmodule Parser.ParserTest do
}
end
end
describe "convert_compressed_cs/1" do
# !!
# I!
# Y"
test "1" do
assert Parser.convert_compressed_cs("Y$") == %{course: 12, speed: 0.3}
end
end
end

View file

@ -0,0 +1,22 @@
defmodule Parser.Types.PositionTest do
use ExUnit.Case
alias Parser.Types.Position
describe "from_aprs/2" do
test "1" do
assert Position.from_aprs("3339.13N", "11759.13W") == %{
latitude: 33.652166666666666,
longitude: -117.9855
}
end
end
describe "from_decimal/2" do
test "1" do
assert Position.from_decimal(33.652166666666666, -117.9855) == %{
latitude: 33.652166666666666,
longitude: -117.9855
}
end
end
end