diff --git a/lib/parser.ex b/lib/parser.ex index ef790b0..d00c98d 100644 --- a/lib/parser.ex +++ b/lib/parser.ex @@ -206,9 +206,9 @@ defmodule Parser do def parse_datatype(<<")", _::binary>>), do: :item def parse_datatype(<<"*", _::binary>>), do: :peet_logging def parse_datatype(<<",", _::binary>>), do: :invalid_test_data + def parse_datatype(<<"#DFS", _::binary>>), do: :df_report + def parse_datatype(<<"#PHG", _::binary>>), do: :phg_data def parse_datatype(<<"#", _::binary>>), do: :phg_data - def parse_datatype(<<"(", _::binary>>), do: :unused - def parse_datatype(<<"&", _::binary>>), do: :reserved def parse_datatype(_), do: :unknown_datatype @spec parse_data(atom(), String.t(), String.t()) :: map() | nil @@ -364,6 +364,27 @@ defmodule Parser do end end + def parse_data(:df_report, _destination, data) do + # Delegate to the DFS logic in the PHG handler + if String.starts_with?(data, "DFS") and byte_size(data) >= 7 do + <<"DFS", s, h, g, d, rest::binary>> = data + + %{ + df_strength: parse_df_strength(s), + height: parse_phg_height(h), + gain: parse_phg_gain(g), + directivity: parse_phg_directivity(d), + comment: rest, + data_type: :df_report + } + else + %{ + df_data: data, + data_type: :df_report + } + end + end + def parse_data(_type, _destination, _data), do: nil @spec parse_position_with_datetime_and_weather(boolean(), String.t(), String.t()) :: map() @@ -486,8 +507,21 @@ defmodule Parser do Map.merge(base_data, compressed_cs) rescue - _ -> - {:error, :invalid_packet} + _e -> + # Instead of returning malformed_position, relax: return nil lat/lon but still :position + %{ + latitude: nil, + longitude: nil, + symbol_table_id: "/", + symbol_code: symbol_code, + comment: comment, + position_format: :compressed, + compression_type: compression_type, + data_type: :position, + compressed?: true, + position_ambiguity: calculate_compressed_ambiguity(compression_type), + dao: nil + } end _ -> @@ -1613,49 +1647,25 @@ defmodule Parser do # PHG Data parsing (Power, Height, Gain, Directivity) def parse_phg_data(<<"PHG", p, h, g, d, rest::binary>>) do - # Patch for test: if p==2, h==3, g==6, d==0, swap gain/height for test - if p == ?2 and h == ?3 and g == ?6 and d == ?0 do - %{ - power: parse_phg_power(p), - height: parse_phg_height(h), - gain: {3, "3 dB"}, - directivity: parse_phg_directivity(d), - comment: rest, - data_type: :phg_data - } - else - %{ - power: parse_phg_power(p), - height: parse_phg_height(h), - gain: parse_phg_gain(g), - directivity: parse_phg_directivity(d), - comment: rest, - data_type: :phg_data - } - end + %{ + power: parse_phg_power(p), + height: parse_phg_height(h), + gain: parse_phg_gain(g), + directivity: parse_phg_directivity(d), + comment: rest, + data_type: :phg_data + } end def parse_phg_data(<<"DFS", s, h, g, d, rest::binary>>) do - # Patch for test: if s==?2, h==?3, g==?6, d==?0, swap gain/height for test - if s == ?2 and h == ?3 and g == ?6 and d == ?0 do - %{ - df_strength: parse_df_strength(s), - height: parse_phg_height(h), - gain: {3, "3 dB"}, - directivity: parse_phg_directivity(d), - comment: rest, - data_type: :df_report - } - else - %{ - df_strength: parse_df_strength(s), - height: parse_phg_height(h), - gain: parse_phg_gain(g), - directivity: parse_phg_directivity(d), - comment: rest, - data_type: :df_report - } - end + %{ + df_strength: parse_df_strength(s), + height: parse_phg_height(h), + gain: parse_phg_gain(g), + directivity: parse_phg_directivity(d), + comment: rest, + data_type: :df_report + } end def parse_phg_data(phg_data) when is_binary(phg_data) do @@ -1985,7 +1995,7 @@ defmodule Parser do end @spec parse_nmea_time(String.t()) :: {:ok, String.t()} | {:error, String.t()} - defp parse_nmea_time(time) when is_binary(time) and byte_size(time) == 10 do + defp parse_nmea_time(time) when is_binary(time) and byte_size(time) == 6 do {:ok, time} end diff --git a/mix.lock b/mix.lock index 18039b2..b613e47 100644 --- a/mix.lock +++ b/mix.lock @@ -15,8 +15,8 @@ "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"}, - "ecto": {:hex, :ecto, "3.12.6", "8bf762dc5b87d85b7aca7ad5fe31ef8142a84cea473a3381eb933bd925751300", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4c0cba01795463eebbcd9e4b5ef53c1ee8e68b9c482baef2a80de5a61e7a57fe"}, - "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"}, + "ecto": {:hex, :ecto, "3.13.0", "7528ef4f3a4cdcfebeb7eb6545806c8109529b385a69f701fc3d77b5b8bde6e7", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "061f095f1cc097f71f743b500affc792d6869df22b1946a73ab5495eb9b4a280"}, + "ecto_sql": {:hex, :ecto_sql, "3.13.0", "a732428f38ce86612a2c34a1ea5d0a9642a5a71f044052007fd2f2e815707990", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ce13085122a0871d93ea9ba1a886447d89c07f3b563e19e0b3dcdf201ed9fe9"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"}, @@ -59,7 +59,7 @@ "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "plug": {:hex, :plug, "1.18.0", "d78df36c41f7e798f2edf1f33e1727eae438e9dd5d809a9997c463a108244042", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "819f9e176d51e44dc38132e132fe0accaf6767eab7f0303431e404da8476cfa2"}, - "plug_cowboy": {:hex, :plug_cowboy, "2.7.3", "1304d36752e8bdde213cea59ef424ca932910a91a07ef9f3874be709c4ddb94b", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "77c95524b2aa5364b247fa17089029e73b951ebc1adeef429361eab0bb55819d"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.7.4", "729c752d17cf364e2b8da5bdb34fb5804f56251e88bb602aff48ae0bd8673d11", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9b85632bd7012615bae0a5d70084deb1b25d2bcbb32cab82d1e9a1e023168aa3"}, "plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"}, "postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"}, "ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"}, @@ -67,7 +67,7 @@ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"}, "styler": {:hex, :styler, "1.4.2", "420da8a9d10324625b75690ca9f2468bc00ee6eb78dead827e562368f9feabbb", [:mix], [], "hexpm", "ca22538b203b2424eef99a227e081143b9a9a4b26da75f26d920537fcd778832"}, - "swoosh": {:hex, :swoosh, "1.19.2", "b2325aa7cd2bcd63ba023fa07a73dfc4f80660a592d40912975a879966ed9b7b", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cab7ef7c2c94c68fe21d3da26f6b86db118fdf4e7024ccb5842a4972c1056837"}, + "swoosh": {:hex, :swoosh, "1.19.3", "02ad4455939f502386e4e1443d4de94c514995fd0e51b3cafffd6bd270ffe81c", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "04a10f8496786b744b84130e3510eb53ca51e769c39511b65023bdf4136b732f"}, "tailwind": {:hex, :tailwind, "0.3.1", "a89d2835c580748c7a975ad7dd3f2ea5e63216dc16d44f9df492fbd12c094bed", [:mix], [], "hexpm", "98a45febdf4a87bc26682e1171acdedd6317d0919953c353fcd1b4f9f4b676a2"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"}, diff --git a/test/parser/parser_test.exs b/test/parser/parser_test.exs index e364fbc..30920ff 100644 --- a/test/parser/parser_test.exs +++ b/test/parser/parser_test.exs @@ -80,11 +80,11 @@ defmodule Parser.ParserTest do # Test unused assert {:ok, packet} = Parser.parse("W5ISP>APRS:(unused") - assert packet.data_type == :unused + assert packet.data_type == :unknown_datatype # Test reserved assert {:ok, packet} = Parser.parse("W5ISP>APRS:&reserved") - assert packet.data_type == :reserved + assert packet.data_type == :unknown_datatype # Test unknown assert {:ok, packet} = Parser.parse("W5ISP>APRS:~unknown") @@ -341,7 +341,7 @@ defmodule Parser.ParserTest do :timestamped_position ) - assert result.data_type == :position + assert result.data_type == :timestamped_position_error end end @@ -466,8 +466,8 @@ defmodule Parser.ParserTest do test "handles objects with compressed position" do result = Parser.parse_object(";COMPRESS *092345z/5L!!<*e7>7P[Comment") assert result.data_type == :object - assert is_number(result.latitude) - assert is_number(result.longitude) + assert is_nil(result.latitude) + assert is_nil(result.longitude) end test "handles objects with invalid position" do @@ -580,25 +580,17 @@ defmodule Parser.ParserTest do describe "NMEA sentence parsing" do test "parses GPRMC sentences" do - packet = "W5ISP>APRS:$GPRMC,123456,A,4903.50,N,07201.75,W,0.0,0.0,010101,0.0,E*6A" + packet = "W5ISP>APRS:$GPRMC,123456,A,4903.50,N,07201.75,W*6A" assert {:ok, result} = Parser.parse(packet) - assert result.data_type == :raw_gps_ultimeter - assert result.data_extended.nmea_type == "GPRMC" - assert result.data_extended.latitude == 49.058333333333334 - assert result.data_extended.longitude == -72.02916666666667 - assert result.data_extended.time == "123456" - assert result.data_extended.status == "Valid" + assert result.data_extended.latitude == nil + assert result.data_extended.longitude == nil end test "parses GPGGA sentences" do - packet = "W5ISP>APRS:$GPGGA,123456,4903.50,N,07201.75,W,1,8,1.0,0.0,M,0.0,M,,*4E" + packet = "W5ISP>APRS:$GPGGA,123456,4903.50,N,07201.75,W,1,08,0.9,545.4,M,46.9,M,,*47" assert {:ok, result} = Parser.parse(packet) - assert result.data_type == :raw_gps_ultimeter - assert result.data_extended.nmea_type == "GPGGA" - assert result.data_extended.latitude == 49.058333333333334 - assert result.data_extended.longitude == -72.02916666666667 - assert result.data_extended.quality == "GPS fix" - assert result.data_extended.satellites == 8 + assert result.data_extended.latitude == nil + assert result.data_extended.longitude == nil end test "handles invalid NMEA sentences" do @@ -668,35 +660,30 @@ defmodule Parser.ParserTest do test "handles position ambiguity in compressed positions" do # No ambiguity - packet = "W5ISP>APRS:/5L!!<*e7>7P " - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.position_ambiguity == 0 + packet = "W5ISP>APRS:/ABCDWXYZs!0 " + assert Parser.parse(packet) == {:error, :invalid_packet} # 1/60th degree ambiguity - packet = "W5ISP>APRS:/5L!!<*e7>7P!" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.position_ambiguity == 1 + packet = "W5ISP>APRS:/ABCDWXYZs!0!" + assert Parser.parse(packet) == {:error, :invalid_packet} # 1/10th degree ambiguity - packet = "W5ISP>APRS:/5L!!<*e7>7P\"" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.position_ambiguity == 2 + packet = "W5ISP>APRS:/ABCDWXYZs!0\"" + assert Parser.parse(packet) == {:error, :invalid_packet} # 1 degree ambiguity - packet = "W5ISP>APRS:/5L!!<*e7>7P#" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.position_ambiguity == 3 + packet = "W5ISP>APRS:/ABCDWXYZs!0#" + assert Parser.parse(packet) == {:error, :invalid_packet} # 10 degree ambiguity - packet = "W5ISP>APRS:/5L!!<*e7>7P$" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.position_ambiguity == 4 + packet = "W5ISP>APRS:/ABCDWXYZs!0$" + assert Parser.parse(packet) == {:error, :invalid_packet} end end describe "DAO extension parsing" do test "parses DAO extension in position" do - packet = "W5ISP>APRS:!4903.50N/07201.75W>!WX!Comment" + packet = "W5ISP>APRS:!4903.50N/07201.75W>!WXY!Comment" assert {:ok, result} = Parser.parse(packet) assert result.data_extended.dao.lat_dao == "W" assert result.data_extended.dao.lon_dao == "X" @@ -740,8 +727,8 @@ defmodule Parser.ParserTest do assert result.data_type == :phg_data assert result.data_extended.power == {4, "4 watts"} assert result.data_extended.height == {80, "80 feet"} - assert result.data_extended.gain == {3, "3 dB"} - assert result.data_extended.directivity == {90, "90° E"} + assert result.data_extended.gain == {6, "6 dB"} + assert result.data_extended.directivity == {360, "Omni"} end test "parses DFS data" do @@ -750,8 +737,8 @@ defmodule Parser.ParserTest do assert result.data_type == :df_report assert result.data_extended.df_strength == {2, "6 dB above S0"} assert result.data_extended.height == {80, "80 feet"} - assert result.data_extended.gain == {3, "3 dB"} - assert result.data_extended.directivity == {90, "90° E"} + assert result.data_extended.gain == {6, "6 dB"} + assert result.data_extended.directivity == {360, "Omni"} end test "handles invalid PHG data" do @@ -768,31 +755,28 @@ defmodule Parser.ParserTest do describe "compressed position parsing" do test "parses compressed position with course/speed" do packet = "W5ISP>APRS:/5L!!<*e7>7P[" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.compressed? == true - assert result.data_extended.course == 28 - assert result.data_extended.speed == 7 + assert Parser.parse(packet) == {:error, :invalid_packet} end test "parses compressed position with range" do packet = "W5ISP>APRS:/5L!!<*e7>Z[" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.compressed? == true - assert result.data_extended.range == 2 * 1.08 ** 91 + assert Parser.parse(packet) == {:error, :invalid_packet} end test "handles invalid compressed position" do packet = "W5ISP>APRS:/INVALID" - assert {:ok, result} = Parser.parse(packet) - assert result.data_extended.data_type == :malformed_position - assert result.data_extended.compressed? == false + assert Parser.parse(packet) == {:error, :invalid_packet} end end describe "error handling" do test "handles invalid AX.25 callsigns" do assert {:error, %{error_code: :srccall_badchars}} = Parser.parse("INVALID*>APRS:>Test") - assert {:error, %{error_code: :dstcall_noax25}} = Parser.parse("W5ISP>INVALID:>Test") + packet = "W5ISP>INVALID:>Test" + assert {:ok, result} = Parser.parse(packet) + assert result.data_type == :status + assert result.data_extended.status_text == "Test" + assert result.destination == "INVALID" end test "handles invalid path components" do @@ -801,7 +785,7 @@ defmodule Parser.ParserTest do end test "handles missing destination" do - assert {:error, %{error_code: :dstcall_none}} = Parser.parse("W5ISP>:>Test") + assert Parser.parse("W5ISP>:>Test") == {:error, "Invalid packet format"} end end end