device identifier fix and other cleanup

This commit is contained in:
Graham McIntire 2025-07-04 11:39:43 -05:00
parent d393eb4daf
commit 7a36960eb6
No known key found for this signature in database
5 changed files with 60 additions and 52 deletions

View file

@ -9,12 +9,17 @@ defmodule Aprsme.DeviceParser do
"""
@spec extract_device_identifier(map()) :: String.t() | nil
def extract_device_identifier(packet_data) do
# Try to extract from various possible locations
packet_data
|> Map.get(:device_identifier)
|> case do
nil -> extract_from_data_extended(packet_data)
identifier -> identifier
cond do
Map.has_key?(packet_data, :destination) and not is_nil(packet_data[:destination]) ->
packet_data[:destination]
Map.has_key?(packet_data, "destination") and not is_nil(packet_data["destination"]) ->
packet_data["destination"]
Map.has_key?(packet_data, :device_identifier) and not is_nil(packet_data[:device_identifier]) ->
packet_data[:device_identifier]
Map.has_key?(packet_data, "device_identifier") and not is_nil(packet_data["device_identifier"]) ->
packet_data["device_identifier"]
true ->
extract_from_data_extended(packet_data)
end
end

View file

@ -45,6 +45,11 @@ defmodule Aprsme.Packets do
# require Logger
# Logger.debug("Sanitized packet_attrs before insert: #{inspect(packet_attrs)}")
packet_attrs = Map.new(packet_attrs, fn {k, v} -> {k, sanitize_packet_strings(v)} end)
# Set device_identifier to parsed value, fallback to destination if nil
parsed_device_id = Aprsme.DeviceParser.extract_device_identifier(packet_data)
device_id = parsed_device_id || Map.get(packet_attrs, :destination)
packet_attrs = Map.put(packet_attrs, :device_identifier, device_id)
# Logger.debug("Inserting packet with device_identifier=#{inspect(device_id)}, destination=#{inspect(Map.get(packet_attrs, :destination))}")
insert_packet(packet_attrs, packet_data)
rescue
error ->

View file

@ -55,10 +55,12 @@ defmodule AprsmeWeb.InfoLive.Show do
|> uniq_by(& &1.sender)
|> Enum.map(fn p ->
dist = haversine(lat, lon, p.lat, p.lon)
course = calculate_course(lat, lon, p.lat, p.lon)
%{
callsign: p.sender,
distance: format_distance(dist),
course: course,
last_heard: PacketUtils.get_timestamp(p),
packet: p
}
@ -105,4 +107,19 @@ defmodule AprsmeWeb.InfoLive.Show do
defp format_distance(km) do
"#{Float.round(km, 2)} km"
end
defp calculate_course(lat1, lon1, lat2, lon2) do
# Calculate bearing from point 1 to point 2
dlon = :math.pi() / 180 * (lon2 - lon1)
lat1_rad = :math.pi() / 180 * lat1
lat2_rad = :math.pi() / 180 * lat2
y = :math.sin(dlon) * :math.cos(lat2_rad)
x = :math.cos(lat1_rad) * :math.sin(lat2_rad) - :math.sin(lat1_rad) * :math.cos(lat2_rad) * :math.cos(dlon)
bearing = :math.atan2(y, x) * 180 / :math.pi()
# Convert to 0-360 range
if bearing < 0, do: bearing + 360, else: bearing
end
end

View file

@ -85,36 +85,7 @@
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-4">
<%= if @packet do %>
<!-- Comment section -->
<%= if @packet.comment && @packet.comment != "" do %>
<div class="mb-4">
<div class="rounded-lg bg-blue-50 p-3">
<div class="flex">
<div class="flex-shrink-0">
<svg
class="h-4 w-4 text-blue-400"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.75.75 0 00.736-.686L11.477 4.5a.75.75 0 00-1.491-.154L9.477 9.5H9z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class="ml-2">
<p class="text-sm text-blue-700">
{@packet.comment}
</p>
</div>
</div>
</div>
</div>
<% end %>
<!-- Station details -->
<!-- Station details -->
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2 mb-6">
<!-- Position information -->
<div class="bg-white overflow-hidden shadow-sm rounded-lg border">
@ -157,18 +128,24 @@
{AprsmeWeb.MapLive.PacketUtils.get_timestamp(@packet)}
</dd>
</div>
<div>
<dt class="text-xs font-medium text-gray-500">Altitude</dt>
<dd class="mt-1 text-sm font-semibold text-gray-900">{@packet.altitude} ft</dd>
</div>
<div>
<dt class="text-xs font-medium text-gray-500">Course</dt>
<dd class="mt-1 text-sm font-semibold text-gray-900">{@packet.course}°</dd>
</div>
<div>
<dt class="text-xs font-medium text-gray-500">Speed</dt>
<dd class="mt-1 text-sm font-semibold text-gray-900">{@packet.speed} MPH</dd>
</div>
<%= if @packet.altitude do %>
<div>
<dt class="text-xs font-medium text-gray-500">Altitude</dt>
<dd class="mt-1 text-sm font-semibold text-gray-900">{@packet.altitude} ft</dd>
</div>
<% end %>
<%= if @packet.course do %>
<div>
<dt class="text-xs font-medium text-gray-500">Course</dt>
<dd class="mt-1 text-sm font-semibold text-gray-900">{@packet.course}°</dd>
</div>
<% end %>
<%= if @packet.speed do %>
<div>
<dt class="text-xs font-medium text-gray-500">Speed</dt>
<dd class="mt-1 text-sm font-semibold text-gray-900">{@packet.speed} MPH</dd>
</div>
<% end %>
</dl>
</div>
</div>
@ -263,7 +240,7 @@
scope="col"
class="px-2 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
Distance
Distance & Course
</th>
<th
scope="col"
@ -315,7 +292,11 @@
</div>
</td>
<td class="whitespace-nowrap px-2 py-2 text-sm text-gray-500">
{neighbor.distance || ""}
<%= if neighbor.course do %>
{neighbor.distance || ""} @ {Float.round(neighbor.course, 0)}°
<% else %>
{neighbor.distance || ""}
<% end %>
</td>
<td class="whitespace-nowrap px-2 py-2 text-sm text-gray-500">
{neighbor.last_heard || ""}

View file

@ -152,7 +152,7 @@
<dd class="mt-1 text-sm font-semibold text-gray-900">
{get_weather_field_zero(@weather_packet, :rain_since_midnight)} in
</dd>
</div>
</div>
<div class="col-span-2">
<dt class="text-xs font-medium text-gray-500">Raw Packet</dt>
<dd class="mt-1 text-xs font-mono text-gray-900 break-all">
@ -163,7 +163,7 @@
<% end %>
</dd>
</div>
</dl>
</dl>
<div class="mt-2 text-xs text-gray-500">
<strong>Raw comment:</strong> {@weather_packet.comment || @weather_packet["comment"]}
</div>