From c09f9175f4c80ed8f45cd9e6886c0faeb1e092f2 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 12 Jul 2025 10:22:43 -0500 Subject: [PATCH] add PHG parsing --- lib/aprsme/packet.ex | 25 ++++++ lib/aprsme_web/live/info_live/show.html.heex | 39 ++++++++++ ...250712150402_add_phg_fields_to_packets.exs | 16 ++++ ...712150759_change_phg_fields_to_integer.exs | 11 +++ test/aprsme/packet_parsing_test.exs | 78 +++++++++++++++++++ vendor/aprs | 2 +- 6 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 priv/repo/migrations/20250712150402_add_phg_fields_to_packets.exs create mode 100644 priv/repo/migrations/20250712150759_change_phg_fields_to_integer.exs create mode 100644 test/aprsme/packet_parsing_test.exs diff --git a/lib/aprsme/packet.ex b/lib/aprsme/packet.ex index c80f029..bac1dd4 100644 --- a/lib/aprsme/packet.ex +++ b/lib/aprsme/packet.ex @@ -52,6 +52,12 @@ defmodule Aprsme.Packet do field(:speed, :float) field(:altitude, :float) + # PHG (Power-Height-Gain) fields + field(:phg_power, :integer) + field(:phg_height, :integer) + field(:phg_gain, :integer) + field(:phg_directivity, :integer) + # Message-specific fields field(:addressee, :string) field(:message_text, :string) @@ -109,6 +115,10 @@ defmodule Aprsme.Packet do :course, :speed, :altitude, + :phg_power, + :phg_height, + :phg_gain, + :phg_directivity, :addressee, :message_text, :message_number, @@ -352,6 +362,21 @@ defmodule Aprsme.Packet do |> maybe_put(:course, data_extended[:course] || data_extended["course"]) |> maybe_put(:speed, data_extended[:speed] || data_extended["speed"]) |> maybe_put(:altitude, data_extended[:altitude] || data_extended["altitude"]) + |> put_phg_fields(data_extended) + end + + defp put_phg_fields(map, data_extended) do + phg = data_extended[:phg] || data_extended["phg"] + + if phg && is_map(phg) do + map + |> maybe_put(:phg_power, phg[:power] || phg["power"]) + |> maybe_put(:phg_height, phg[:height] || phg["height"]) + |> maybe_put(:phg_gain, phg[:gain] || phg["gain"]) + |> maybe_put(:phg_directivity, phg[:directivity] || phg["directivity"]) + else + map + end end defp put_message_fields(map, data_extended) do diff --git a/lib/aprsme_web/live/info_live/show.html.heex b/lib/aprsme_web/live/info_live/show.html.heex index 261a966..eb83cf0 100644 --- a/lib/aprsme_web/live/info_live/show.html.heex +++ b/lib/aprsme_web/live/info_live/show.html.heex @@ -139,6 +139,45 @@ <% end %> + <%= if @packet.phg_power || @packet.phg_height || @packet.phg_gain do %> +
+
+ {gettext("PHG (Power-Height-Gain)")} +
+
+ <%= if @packet.phg_power do %> +
+ {gettext("Power:")} + {@packet.phg_power} W +
+ <% end %> + <%= if @packet.phg_height do %> +
+ {gettext("HAAT:")} + {@packet.phg_height} ft +
+ <% end %> + <%= if @packet.phg_gain do %> +
+ {gettext("Gain:")} + {@packet.phg_gain} dBi +
+ <% end %> + <%= if @packet.phg_directivity do %> +
+ {gettext("Dir:")} + + <%= if @packet.phg_directivity == 0 or @packet.phg_directivity == 360 do %> + {gettext("Omni")} + <% else %> + {@packet.phg_directivity}° + <% end %> + +
+ <% end %> +
+
+ <% end %> diff --git a/priv/repo/migrations/20250712150402_add_phg_fields_to_packets.exs b/priv/repo/migrations/20250712150402_add_phg_fields_to_packets.exs new file mode 100644 index 0000000..d9b3445 --- /dev/null +++ b/priv/repo/migrations/20250712150402_add_phg_fields_to_packets.exs @@ -0,0 +1,16 @@ +defmodule Aprsme.Repo.Migrations.AddPhgFieldsToPackets do + use Ecto.Migration + + def change do + alter table(:packets) do + add :phg_power, :float + add :phg_height, :float + add :phg_gain, :float + add :phg_directivity, :integer + end + + # Create indexes for PHG fields to support queries by power/height/etc + create index(:packets, [:phg_power]) + create index(:packets, [:phg_height]) + end +end diff --git a/priv/repo/migrations/20250712150759_change_phg_fields_to_integer.exs b/priv/repo/migrations/20250712150759_change_phg_fields_to_integer.exs new file mode 100644 index 0000000..b94b53e --- /dev/null +++ b/priv/repo/migrations/20250712150759_change_phg_fields_to_integer.exs @@ -0,0 +1,11 @@ +defmodule Aprsme.Repo.Migrations.ChangePhgFieldsToInteger do + use Ecto.Migration + + def change do + alter table(:packets) do + modify :phg_power, :integer, from: :float + modify :phg_height, :integer, from: :float + modify :phg_gain, :integer, from: :float + end + end +end diff --git a/test/aprsme/packet_parsing_test.exs b/test/aprsme/packet_parsing_test.exs new file mode 100644 index 0000000..d960e77 --- /dev/null +++ b/test/aprsme/packet_parsing_test.exs @@ -0,0 +1,78 @@ +defmodule Aprsme.PacketParsingTest do + use Aprsme.DataCase + + alias Aprsme.Packet + + describe "packet parsing for altitude and PHG" do + test "extracts altitude and PHG data from packet" do + raw_packet = "W5MRC-15>APN391,qAO,KG5JPL-1:!3317.02NN09634.37W#PHG5530 Collin Cty Wide Digi /A=000680" + + # Parse the packet + {:ok, parsed} = Aprs.parse(raw_packet) + + # Get the position data from data_extended + position_data = parsed[:data_extended] + + # Verify altitude was extracted + assert position_data[:altitude] == 680.0 + + # Verify PHG data was extracted + assert is_map(position_data[:phg]) + # PHG5 = 36W + assert position_data[:phg][:power] == 36 + # PHG x5x = 320 ft + assert position_data[:phg][:height] == 320 + # PHG xx3 = 3 dBi + assert position_data[:phg][:gain] == 3 + # PHG xxx0 = omni (360°) + assert position_data[:phg][:directivity] == 360 + + # Verify comment is cleaned + assert position_data[:comment] == "Collin Cty Wide Digi" + end + + test "packet changeset includes altitude and PHG fields" do + attrs = %{ + sender: "W5MRC-15", + base_callsign: "W5MRC", + ssid: "15", + data_type: "position", + destination: "APN391", + information_field: "!3317.02NN09634.37W#PHG5530 Collin Cty Wide Digi /A=000680", + path: "qAO,KG5JPL-1", + lat: Decimal.new("33.2837"), + lon: Decimal.new("-96.5728"), + location: %Geo.Point{coordinates: {-96.5728, 33.2837}}, + has_position: true, + received_at: DateTime.truncate(DateTime.utc_now(), :second), + data_extended: %{ + altitude: 680.0, + phg: %{ + power: 25, + height: 320, + gain: 3, + directivity: 0 + }, + comment: "Collin Cty Wide Digi" + } + } + + # Extract additional data + attrs_with_data = Packet.extract_additional_data(attrs, attrs.information_field) + + # Create changeset + changeset = Packet.changeset(%Packet{}, attrs_with_data) + + assert changeset.valid? + + # Check that fields were properly set + changes = changeset.changes + assert changes.altitude == 680.0 + assert changes.phg_power == 25 + assert changes.phg_height == 320 + assert changes.phg_gain == 3 + assert changes.phg_directivity == 0 + assert changes.comment == "Collin Cty Wide Digi" + end + end +end diff --git a/vendor/aprs b/vendor/aprs index cbe4cf0..b964e1d 160000 --- a/vendor/aprs +++ b/vendor/aprs @@ -1 +1 @@ -Subproject commit cbe4cf0fcf3577c0b6a3dcf4f34db6d5361db340 +Subproject commit b964e1da6e159900d01416c178a2cd20a721447e