Remove dead PostGIS code, deduplicate utilities, and simplify module hierarchy

- Delete ~170 lines of commented-out PostGIS spatial query functions
- Consolidate coordinate validation into CoordinateUtils
- Replace private normalize_data_type with EncodingUtils delegation
- Inline to_float/to_decimal wrappers at call sites
- Fix has_weather_data? missing wind_gust field
- Remove BoundsManager passthrough delegation module
- Simplify MapLive.PacketUtils by removing pure-passthrough delegations
This commit is contained in:
Graham McIntire 2026-02-20 13:38:47 -06:00
parent bb494bce65
commit 50544c8354
No known key found for this signature in database
13 changed files with 64 additions and 334 deletions

View file

@ -6,6 +6,7 @@ defmodule Aprsme.Packet do
alias Aprs.Types.MicE
alias Aprsme.DataExtended
alias AprsmeWeb.Live.Shared.CoordinateUtils
schema "packets" do
field(:base_callsign, :string)
@ -217,37 +218,14 @@ defmodule Aprsme.Packet do
end
defp valid_coordinates?(lat, lon) do
lat = normalize_coordinate(lat)
lon = normalize_coordinate(lon)
is_number(lat) && is_number(lon) &&
lat >= -90 && lat <= 90 &&
lon >= -180 && lon <= 180
CoordinateUtils.valid_coordinates_any_type?(lat, lon)
end
defp normalize_coordinate(%Decimal{} = decimal), do: Decimal.to_float(decimal)
defp normalize_coordinate(coord), do: coord
# Convert atom data_type to string for storage
defp normalize_data_type(%{data_type: data_type} = attrs) when is_atom(data_type) do
%{attrs | data_type: to_string(data_type)}
defp normalize_coordinate(coord) do
CoordinateUtils.normalize_coordinate(coord)
end
defp normalize_data_type(%{"data_type" => data_type} = attrs) when is_atom(data_type) do
%{attrs | "data_type" => to_string(data_type)}
end
defp normalize_data_type(attrs) when is_map(attrs) do
case {Map.has_key?(attrs, :data_type), Map.get(attrs, :data_type)} do
{true, data_type} when is_atom(data_type) ->
%{attrs | data_type: to_string(data_type)}
_ ->
attrs
end
end
defp normalize_data_type(attrs), do: attrs
defp normalize_data_type(attrs), do: Aprsme.EncodingUtils.normalize_data_type(attrs)
@doc """
Extracts additional data from the raw packet and data_extended structure
@ -613,88 +591,6 @@ defmodule Aprsme.Packet do
defp maybe_put(map, _key, ""), do: map
defp maybe_put(map, key, value), do: Map.put(map, key, value)
# @doc """
# Spatial query functions for efficient location-based searches
# """
# Temporarily commented out until PostGIS is properly configured
# @doc """
# Find packets within a given radius (in meters) of a point.
# """
# def within_radius(query \\ __MODULE__, lat, lon, radius_meters) do
# point = %Geo.Point{coordinates: {lon, lat}, srid: 4326}
# from p in query,
# where: st_dwithin_in_meters(p.location, ^point, ^radius_meters),
# where: not is_nil(p.location)
# end
# @doc """
# Find packets within a bounding box defined by southwest and northeast corners.
# """
# def within_bbox(query \\ __MODULE__, sw_lat, sw_lon, ne_lat, ne_lon) do
# # Create a polygon representing the bounding box
# bbox = %Geo.Polygon{
# coordinates: [[
# {sw_lon, sw_lat},
# {ne_lon, sw_lat},
# {ne_lon, ne_lat},
# {sw_lon, ne_lat},
# {sw_lon, sw_lat}
# ]],
# srid: 4326
# }
# from p in query,
# where: st_within(p.location, ^bbox),
# where: not is_nil(p.location)
# end
# @doc """
# Find packets ordered by distance from a given point.
# """
# def nearest_to(query \\ __MODULE__, lat, lon, limit \\ 100) do
# point = %Geo.Point{coordinates: {lon, lat}, srid: 4326}
# from p in query,
# where: not is_nil(p.location),
# order_by: st_distance(p.location, ^point),
# limit: ^limit,
# select: %{p | distance: st_distance_in_meters(p.location, ^point)}
# end
# @doc """
# Find recent packets with location data within the last N hours.
# """
# def recent_with_location(query \\ __MODULE__, hours_back \\ 24) do
# cutoff_time = DateTime.utc_now() |> DateTime.add(-hours_back, :hour)
# from p in query,
# where: p.has_position == true,
# where: not is_nil(p.location),
# where: p.received_at > ^cutoff_time,
# order_by: [desc: p.received_at]
# end
# @doc """
# Get statistics for packets in a geographic area.
# """
# def location_stats(query \\ __MODULE__, lat, lon, radius_meters) do
# point = %Geo.Point{coordinates: {lon, lat}, srid: 4326}
# from p in query,
# where: st_dwithin_in_meters(p.location, ^point, ^radius_meters),
# where: not is_nil(p.location),
# group_by: p.base_callsign,
# select: %{
# callsign: p.base_callsign,
# packet_count: count(p.id),
# latest_position: max(p.received_at),
# avg_lat: avg(fragment("ST_Y(?)", p.location)),
# avg_lon: avg(fragment("ST_X(?)", p.location))
# }
# end
@doc """
Create a geometry point from lat/lon coordinates.
"""
@ -732,19 +628,6 @@ defmodule Aprsme.Packet do
def lon(%__MODULE__{location: %Geo.Point{coordinates: {lon, _lat}}}), do: lon
def lon(_), do: nil
# @doc """
# Calculate distance between two packets in meters.
# """
# def distance_between(%__MODULE__{location: %Geo.Point{} = p1}, %__MODULE__{location: %Geo.Point{} = p2}) do
# Repo.one(
# from p in "packets",
# select: fragment("ST_Distance_Sphere(?, ?)", ^p1, ^p2),
# limit: 1
# )
# end
# def distance_between(_, _), do: nil
# Clean comment by removing altitude and PHG data
defp clean_comment(nil), do: nil

View file

@ -9,6 +9,7 @@ defmodule Aprsme.PacketConsumer do
alias Aprsme.Cluster.PacketDistributor
alias Aprsme.LogSanitizer
alias Aprsme.Repo
alias AprsmeWeb.Live.Shared.CoordinateUtils
require Logger
@ -449,16 +450,12 @@ defmodule Aprsme.PacketConsumer do
# Helper functions for coordinate validation and point creation
defp valid_coordinates?(lat, lon) do
lat = normalize_coordinate(lat)
lon = normalize_coordinate(lon)
is_number(lat) && is_number(lon) &&
lat >= -90 && lat <= 90 &&
lon >= -180 && lon <= 180
CoordinateUtils.valid_coordinates_any_type?(lat, lon)
end
defp normalize_coordinate(%Decimal{} = decimal), do: Decimal.to_float(decimal)
defp normalize_coordinate(coord), do: coord
defp normalize_coordinate(coord) do
CoordinateUtils.normalize_coordinate(coord)
end
defp create_point(lat, lon)
when (is_number(lat) or is_struct(lat, Decimal)) and (is_number(lon) or is_struct(lon, Decimal)) do
@ -615,7 +612,7 @@ defmodule Aprsme.PacketConsumer do
defp extract_position(packet_data) do
if not is_nil(packet_data[:lat]) and not is_nil(packet_data[:lon]) do
{to_float(packet_data.lat), to_float(packet_data.lon)}
{Aprsme.EncodingUtils.to_float(packet_data.lat), Aprsme.EncodingUtils.to_float(packet_data.lon)}
else
extract_position_from_data_extended(packet_data[:data_extended])
end
@ -640,7 +637,7 @@ defmodule Aprsme.PacketConsumer do
defp has_standard_position?(_), do: false
defp extract_standard_position(data_extended) when is_map(data_extended) and not is_struct(data_extended) do
{to_float(data_extended[:latitude]), to_float(data_extended[:longitude])}
{Aprsme.EncodingUtils.to_float(data_extended[:latitude]), Aprsme.EncodingUtils.to_float(data_extended[:longitude])}
end
defp extract_standard_position(_), do: {nil, nil}
@ -648,7 +645,7 @@ defmodule Aprsme.PacketConsumer do
defp extract_position_from_data_extended_case(data_extended) do
lat = extract_lat_from_ext_map(data_extended)
lon = extract_lon_from_ext_map(data_extended)
{to_float(lat), to_float(lon)}
{Aprsme.EncodingUtils.to_float(lat), Aprsme.EncodingUtils.to_float(lon)}
end
defp extract_lat_from_ext_map(ext_map) do
@ -691,8 +688,6 @@ defmodule Aprsme.PacketConsumer do
defp sanitize_packet_strings(value), do: Aprsme.EncodingUtils.sanitize_packet_strings(value)
defp to_float(value), do: Aprsme.EncodingUtils.to_float(value)
defp normalize_data_type(attrs), do: Aprsme.EncodingUtils.normalize_data_type(attrs)
defp struct_to_map(%{__struct__: ParseError} = error) do

View file

@ -151,7 +151,7 @@ defmodule Aprsme.Packets do
defp to_decimal_safe(nil), do: {:error, :nil_value}
defp to_decimal_safe(value) do
case to_decimal(value) do
case Aprsme.EncodingUtils.to_decimal(value) do
nil -> {:error, :conversion_failed}
decimal -> {:ok, decimal}
end
@ -329,7 +329,7 @@ defmodule Aprsme.Packets do
defp extract_position(packet_data) do
# Check for lat/lon at top level
if not is_nil(packet_data[:lat]) and not is_nil(packet_data[:lon]) do
{to_float(packet_data.lat), to_float(packet_data.lon)}
{Aprsme.EncodingUtils.to_float(packet_data.lat), Aprsme.EncodingUtils.to_float(packet_data.lon)}
else
extract_position_from_data_extended(packet_data[:data_extended])
end
@ -354,7 +354,7 @@ defmodule Aprsme.Packets do
defp has_standard_position?(_), do: false
defp extract_standard_position(data_extended) when is_map(data_extended) and not is_struct(data_extended) do
{to_float(data_extended[:latitude]), to_float(data_extended[:longitude])}
{Aprsme.EncodingUtils.to_float(data_extended[:latitude]), Aprsme.EncodingUtils.to_float(data_extended[:longitude])}
end
defp extract_standard_position(_), do: {nil, nil}
@ -761,12 +761,6 @@ defmodule Aprsme.Packets do
{:ok, deleted_count}
end
# Helper to convert various types to float
defp to_float(value), do: Aprsme.EncodingUtils.to_float(value)
# Helper to convert various types to Decimal
defp to_decimal(value), do: Aprsme.EncodingUtils.to_decimal(value)
# Get packets from last hour only - used to initialize the map
@spec get_last_hour_packets() :: [struct()]
def get_last_hour_packets do
@ -780,82 +774,6 @@ defmodule Aprsme.Packets do
[]
end
# @doc """
# Spatial query functions for efficient location-based searches using PostGIS
# """
# Temporarily commented out PostGIS functions until PostGIS is properly configured
# @doc """
# Find packets within a given radius (in meters) of a point.
# Uses PostGIS spatial indexes for efficient querying.
# """
# def find_packets_within_radius(lat, lon, radius_meters, opts \\ %{}) do
# point = %Geo.Point{coordinates: {lon, lat}, srid: 4326}
# base_query =
# Packet
# |> where([p], not is_nil(p.location))
# |> where([p], st_dwithin_in_meters(p.location, ^point, ^radius_meters))
# |> order_by([p], st_distance(p.location, ^point))
# base_query
# |> apply_common_filters(opts)
# |> maybe_limit(opts)
# |> Repo.all()
# end
# Additional PostGIS functions commented out for now...
# Helper functions for spatial queries - commented out for now
# defp apply_common_filters(query, opts) do
# query
# |> filter_by_time_range(opts)
# |> filter_by_callsign(opts)
# |> filter_by_data_type(opts)
# end
# defp filter_by_time_range(query, %{start_time: start_time, end_time: end_time}) do
# from p in query,
# where: p.received_at >= ^start_time and p.received_at <= ^end_time
# end
# defp filter_by_time_range(query, %{start_time: start_time}) do
# from p in query, where: p.received_at >= ^start_time
# end
# defp filter_by_time_range(query, %{end_time: end_time}) do
# from p in query, where: p.received_at <= ^end_time
# end
# defp filter_by_time_range(query, %{hours_back: hours}) do
# cutoff_time = DateTime.utc_now() |> DateTime.add(-hours, :hour)
# from p in query, where: p.received_at >= ^cutoff_time
# end
# defp filter_by_time_range(query, _), do: query
# defp filter_by_data_type(query, %{data_type: data_type}) do
# from p in query, where: p.data_type == ^data_type
# end
# defp filter_by_data_type(query, _), do: query
# defp maybe_limit(query, %{limit: limit}) when is_integer(limit) and limit > 0 do
# from p in query, limit: ^limit
# end
# defp maybe_limit(query, _), do: query
# Calculate clustering distance based on zoom level
# Higher zoom levels need smaller clustering distances
# defp calculate_cluster_distance(zoom_level) when zoom_level >= 15, do: 100 # 100m
# defp calculate_cluster_distance(zoom_level) when zoom_level >= 12, do: 500 # 500m
# defp calculate_cluster_distance(zoom_level) when zoom_level >= 9, do: 2000 # 2km
# defp calculate_cluster_distance(zoom_level) when zoom_level >= 6, do: 10000 # 10km
# defp calculate_cluster_distance(_), do: 50000 # 50km
@doc """
Gets the most recent packet for a callsign regardless of type or age.
This is used for API endpoints that need the latest packet from a source.

View file

@ -2,7 +2,7 @@ defmodule AprsmeWeb.InfoController do
use AprsmeWeb, :controller
alias Aprsme.Packets
alias AprsmeWeb.MapLive.PacketUtils
alias AprsmeWeb.Live.Shared.PacketUtils
@neighbor_radius_km 10
@neighbor_limit 10

View file

@ -143,10 +143,10 @@ defmodule AprsmeWeb.InfoLive.Show do
defp position_changed?(current_packet, new_packet) do
# Compare lat/lon to see if position actually changed
current_lat = to_float_safe(current_packet.lat)
current_lon = to_float_safe(current_packet.lon)
new_lat = to_float_safe(new_packet.lat)
new_lon = to_float_safe(new_packet.lon)
current_lat = EncodingUtils.to_float(current_packet.lat)
current_lon = EncodingUtils.to_float(current_packet.lon)
new_lat = EncodingUtils.to_float(new_packet.lat)
new_lon = EncodingUtils.to_float(new_packet.lon)
# If any coordinate is invalid, consider it a change
case {current_lat, current_lon, new_lat, new_lon} do
@ -274,10 +274,6 @@ defmodule AprsmeWeb.InfoLive.Show do
r * c
end
# Safe float conversion that preserves nil for invalid coordinates
defp to_float_safe(value), do: EncodingUtils.to_float(value)
# Legacy float conversion that defaults to 0.0 for backward compatibility
defp to_float(value), do: EncodingUtils.to_float(value) || 0.0
defp format_timestamp_for_display(packet) do

View file

@ -1,25 +0,0 @@
defmodule AprsmeWeb.MapLive.BoundsManager do
@moduledoc """
Handles map bounds calculations, validation, and filtering operations.
"""
alias AprsmeWeb.Live.Shared.BoundsUtils
alias AprsmeWeb.Live.Shared.PacketUtils
# Delegate to shared utilities
defdelegate calculate_bounds_from_center_and_zoom(center, zoom), to: BoundsUtils
defdelegate valid_bounds?(map_bounds), to: BoundsUtils
defdelegate compare_bounds(b1, b2), to: BoundsUtils
defdelegate within_bounds?(packet, bounds), to: BoundsUtils
defdelegate filter_packets_by_bounds(packets, bounds), to: BoundsUtils
defdelegate reject_packets_by_bounds(packets_map, bounds), to: BoundsUtils
@doc """
Filter packets by both time threshold and bounds.
"""
@spec filter_packets_by_time_and_bounds(map(), map(), DateTime.t()) :: map()
def filter_packets_by_time_and_bounds(packets, bounds, time_threshold) do
# Use shared packet utils for this functionality
PacketUtils.filter_packets_by_time_and_bounds(packets, bounds, time_threshold)
end
end

View file

@ -4,7 +4,7 @@ defmodule AprsmeWeb.MapLive.DisplayManager do
"""
alias Aprsme.Packets.Clustering
alias AprsmeWeb.MapLive.BoundsManager
alias AprsmeWeb.Live.Shared.BoundsUtils
alias AprsmeWeb.MapLive.DataBuilder
alias Phoenix.LiveView
alias Phoenix.LiveView.Socket
@ -50,7 +50,7 @@ defmodule AprsmeWeb.MapLive.DisplayManager do
# Filter by bounds
filtered_packets =
all_packets
|> BoundsManager.filter_packets_by_bounds(socket.assigns.map_bounds)
|> BoundsUtils.filter_packets_by_bounds(socket.assigns.map_bounds)
|> Enum.uniq_by(fn packet ->
Map.get(packet, :id) || Map.get(packet, "id")
end)

View file

@ -18,7 +18,6 @@ defmodule AprsmeWeb.MapLive.Index do
alias AprsmeWeb.Live.Shared.CoordinateUtils
alias AprsmeWeb.Live.Shared.PacketUtils, as: SharedPacketUtils
alias AprsmeWeb.Live.Shared.ParamUtils
alias AprsmeWeb.MapLive.BoundsManager
alias AprsmeWeb.MapLive.DataBuilder
alias AprsmeWeb.MapLive.DisplayManager
alias AprsmeWeb.MapLive.HistoricalLoader
@ -83,7 +82,7 @@ defmodule AprsmeWeb.MapLive.Index do
)
# Calculate initial bounds
initial_bounds = BoundsManager.calculate_bounds_from_center_and_zoom(final_map_center, final_map_zoom)
initial_bounds = BoundsUtils.calculate_bounds_from_center_and_zoom(final_map_center, final_map_zoom)
# Final socket assignment
{:ok,

View file

@ -1,66 +1,22 @@
defmodule AprsmeWeb.MapLive.PacketUtils do
@moduledoc """
Shared utilities for extracting and processing packet data in map views.
Map-specific packet utilities. Provides weather-check queries against the
database and a convenience wrapper for weather field display.
For general packet field access, symbol info, timestamps, callsign
generation, and weather-packet detection, use
`AprsmeWeb.Live.Shared.PacketUtils` directly.
For building marker/popup data, use `AprsmeWeb.MapLive.DataBuilder` directly.
"""
alias AprsmeWeb.Live.Shared.PacketUtils, as: SharedPacketUtils
alias AprsmeWeb.Live.Shared.ParamUtils
alias AprsmeWeb.MapLive.DataBuilder
@doc """
Safely extracts a value from a packet or data_extended map with fallback support.
Checks both atom and string keys, and provides a default value.
"""
@spec get_packet_field(map(), atom() | String.t(), any()) :: any()
def get_packet_field(packet, field, default \\ nil) do
SharedPacketUtils.get_packet_field(packet, field, default)
end
@doc """
Extracts symbol information from a packet with fallbacks.
"""
@spec get_symbol_info(map()) :: {String.t(), String.t()}
def get_symbol_info(packet) do
SharedPacketUtils.get_symbol_info(packet)
end
@doc """
Extracts timestamp from a packet in ISO8601 format.
"""
@spec get_timestamp(map()) :: String.t()
def get_timestamp(packet) do
SharedPacketUtils.get_timestamp(packet)
end
@doc """
Converts various numeric types to float for consistent display.
"""
@spec to_float(any()) :: float()
def to_float(value) do
ParamUtils.to_float(value)
end
@doc """
Generates a callsign string with SSID if present.
"""
@spec generate_callsign(map()) :: String.t()
def generate_callsign(packet) do
SharedPacketUtils.generate_callsign(packet)
end
@doc """
Determines if a packet is a weather packet.
"""
@spec weather_packet?(map()) :: boolean()
def weather_packet?(packet) do
SharedPacketUtils.weather_packet?(packet)
end
@doc """
Checks if a station has sent weather packets by looking at recent packets.
"""
@spec has_weather_packets?(String.t()) :: boolean()
# Get recent packets for this callsign and check if any are weather packets
def has_weather_packets?(callsign) when is_binary(callsign) do
query = build_weather_check_query(callsign)
Aprsme.Repo.exists?(query)
@ -95,7 +51,7 @@ defmodule AprsmeWeb.MapLive.PacketUtils do
def convert_tuples_to_strings(other), do: other
@doc """
Extracts weather field data with fallback support.
Extracts weather field data with "N/A" fallback for display.
"""
@spec get_weather_field(map(), atom()) :: String.t()
def get_weather_field(packet, key) do
@ -105,13 +61,11 @@ defmodule AprsmeWeb.MapLive.PacketUtils do
end
end
# These functions have been moved to AprsmeWeb.MapLive.DataBuilder
# Keep build_packet_data delegations for backward compatibility with tests
defdelegate build_packet_data(packet, is_most_recent_for_callsign, locale), to: DataBuilder
defdelegate build_packet_data(packet, is_most_recent_for_callsign), to: DataBuilder
defdelegate build_packet_data(packet), to: DataBuilder
# All packet data building functions have been moved to AprsmeWeb.MapLive.DataBuilder
defp build_weather_check_query(callsign) do
import Ecto.Query

View file

@ -65,6 +65,27 @@ defmodule AprsmeWeb.Live.Shared.CoordinateUtils do
def valid_coordinates?(_, _), do: false
@doc """
Validate coordinates that may be Decimals, floats, or integers.
Normalizes Decimals to floats before checking range.
"""
@spec valid_coordinates_any_type?(any(), any()) :: boolean()
def valid_coordinates_any_type?(lat, lon) do
lat = normalize_coordinate(lat)
lon = normalize_coordinate(lon)
is_number(lat) && is_number(lon) &&
lat >= -90 && lat <= 90 &&
lon >= -180 && lon <= 180
end
@doc """
Normalize a coordinate value, converting Decimals to floats.
"""
@spec normalize_coordinate(any()) :: number() | any()
def normalize_coordinate(%Decimal{} = decimal), do: Decimal.to_float(decimal)
def normalize_coordinate(coord), do: coord
@doc """
Calculate distance between two lat/lon points in meters using Haversine formula.
"""

View file

@ -94,19 +94,7 @@ defmodule AprsmeWeb.Live.Shared.PacketUtils do
"""
@spec has_weather_data?(map()) :: boolean()
def has_weather_data?(packet) do
weather_fields = [
:temperature,
:humidity,
:pressure,
:wind_speed,
:wind_direction,
:rain_1h,
:rain_24h,
:rain_since_midnight,
:snow
]
Enum.any?(weather_fields, fn field ->
Enum.any?(Aprsme.EncodingUtils.weather_fields(), fn field ->
value = get_packet_field(packet, field, nil)
not is_nil(value)
end)

View file

@ -12,7 +12,7 @@
{@callsign}
</span>
<% {symbol_table_id, symbol_code} =
AprsmeWeb.MapLive.PacketUtils.get_symbol_info(@weather_packet) %>
AprsmeWeb.Live.Shared.PacketUtils.get_symbol_info(@weather_packet) %>
<% symbol_table =
if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %>
<% symbol_code = (symbol_code || ">") |> to_string() %>

View file

@ -1,6 +1,7 @@
defmodule AprsmeWeb.MapLive.PacketUtilsTest do
use ExUnit.Case, async: true
alias AprsmeWeb.Live.Shared.PacketUtils, as: SharedPacketUtils
alias AprsmeWeb.MapLive.PacketUtils
describe "weather popup generation" do
@ -282,7 +283,7 @@ defmodule AprsmeWeb.MapLive.PacketUtilsTest do
temperature: 75
}
assert PacketUtils.weather_packet?(weather_packet)
assert SharedPacketUtils.weather_packet?(weather_packet)
end
test "identifies weather packets with humidity" do
@ -293,7 +294,7 @@ defmodule AprsmeWeb.MapLive.PacketUtilsTest do
humidity: 80
}
assert PacketUtils.weather_packet?(weather_packet)
assert SharedPacketUtils.weather_packet?(weather_packet)
end
test "does not identify non-weather packets" do
@ -303,7 +304,7 @@ defmodule AprsmeWeb.MapLive.PacketUtilsTest do
symbol_code: ">"
}
refute PacketUtils.weather_packet?(regular_packet)
refute SharedPacketUtils.weather_packet?(regular_packet)
end
test "has_weather_packets? returns false for non-existent callsign" do
@ -383,7 +384,7 @@ defmodule AprsmeWeb.MapLive.PacketUtilsTest do
ssid: "1"
}
assert PacketUtils.generate_callsign(packet) == "TEST-1"
assert SharedPacketUtils.generate_callsign(packet) == "TEST-1"
end
test "generates callsign without SSID" do
@ -392,7 +393,7 @@ defmodule AprsmeWeb.MapLive.PacketUtilsTest do
ssid: nil
}
assert PacketUtils.generate_callsign(packet) == "TEST"
assert SharedPacketUtils.generate_callsign(packet) == "TEST"
end
test "generates callsign with empty SSID" do
@ -401,7 +402,7 @@ defmodule AprsmeWeb.MapLive.PacketUtilsTest do
ssid: ""
}
assert PacketUtils.generate_callsign(packet) == "TEST"
assert SharedPacketUtils.generate_callsign(packet) == "TEST"
end
end
end