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