add PHG parsing

This commit is contained in:
Graham McIntire 2025-07-12 10:22:43 -05:00
parent 68f0e77f37
commit c09f9175f4
No known key found for this signature in database
6 changed files with 170 additions and 1 deletions

View file

@ -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

View file

@ -139,6 +139,45 @@
</dd>
</div>
<% end %>
<%= if @packet.phg_power || @packet.phg_height || @packet.phg_gain do %>
<div class="col-span-2 border-t pt-3 mt-3">
<dt class="text-xs font-medium opacity-70 mb-2">
{gettext("PHG (Power-Height-Gain)")}
</dt>
<dd class="grid grid-cols-2 gap-2 text-sm">
<%= if @packet.phg_power do %>
<div>
<span class="opacity-70">{gettext("Power:")}</span>
<span class="font-semibold">{@packet.phg_power} W</span>
</div>
<% end %>
<%= if @packet.phg_height do %>
<div>
<span class="opacity-70">{gettext("HAAT:")}</span>
<span class="font-semibold">{@packet.phg_height} ft</span>
</div>
<% end %>
<%= if @packet.phg_gain do %>
<div>
<span class="opacity-70">{gettext("Gain:")}</span>
<span class="font-semibold">{@packet.phg_gain} dBi</span>
</div>
<% end %>
<%= if @packet.phg_directivity do %>
<div>
<span class="opacity-70">{gettext("Dir:")}</span>
<span class="font-semibold">
<%= if @packet.phg_directivity == 0 or @packet.phg_directivity == 360 do %>
{gettext("Omni")}
<% else %>
{@packet.phg_directivity}°
<% end %>
</span>
</div>
<% end %>
</dd>
</div>
<% end %>
</dl>
</div>
</div>

View file

@ -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

View file

@ -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

View file

@ -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

2
vendor/aprs vendored

@ -1 +1 @@
Subproject commit cbe4cf0fcf3577c0b6a3dcf4f34db6d5361db340
Subproject commit b964e1da6e159900d01416c178a2cd20a721447e