diff --git a/lib/aprsme/packet.ex b/lib/aprsme/packet.ex index ffcd6ee..b07388d 100644 --- a/lib/aprsme/packet.ex +++ b/lib/aprsme/packet.ex @@ -455,13 +455,13 @@ defmodule Aprsme.Packet do defp put_equipment_fields(map, data_extended) do # Extract altitude from comment if not already in data_extended altitude = - data_extended[:altitude] || data_extended["altitude"] || - extract_altitude_from_comment(data_extended[:comment] || data_extended["comment"]) + get_field_value(data_extended, :altitude) || + extract_altitude_from_comment(get_field_value(data_extended, :comment)) # Extract PHG from comment if not already in data_extended phg = - data_extended[:phg] || data_extended["phg"] || - extract_phg_from_comment(data_extended[:comment] || data_extended["comment"]) + get_field_value(data_extended, :phg) || + extract_phg_from_comment(get_field_value(data_extended, :comment)) # Update data_extended with extracted values data_extended = @@ -470,28 +470,25 @@ defmodule Aprsme.Packet do |> Map.put(:phg, phg) map - |> maybe_put(:manufacturer, data_extended[:manufacturer] || data_extended["manufacturer"]) - |> maybe_put( - :equipment_type, - data_extended[:equipment_type] || data_extended["equipment_type"] - ) - |> maybe_put(:course, data_extended[:course] || data_extended["course"]) - |> maybe_put(:speed, data_extended[:speed] || data_extended["speed"]) + |> maybe_put(:manufacturer, get_field_value(data_extended, :manufacturer)) + |> maybe_put(:equipment_type, get_field_value(data_extended, :equipment_type)) + |> maybe_put(:course, get_field_value(data_extended, :course)) + |> maybe_put(:speed, get_field_value(data_extended, :speed)) |> maybe_put(:altitude, altitude) # Don't add :phg to the map - it will be split into individual fields by put_phg_fields |> put_phg_fields(data_extended) end defp put_phg_fields(map, data_extended) do - phg = data_extended[:phg] || data_extended["phg"] + phg = get_field_value(data_extended, :phg) cond do phg && is_map(phg) -> 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"]) + |> maybe_put(:phg_power, get_field_value(phg, :power)) + |> maybe_put(:phg_height, get_field_value(phg, :height)) + |> maybe_put(:phg_gain, get_field_value(phg, :gain)) + |> maybe_put(:phg_directivity, get_field_value(phg, :directivity)) phg && is_binary(phg) && String.length(phg) == 4 -> # Handle new string format from improved parser (e.g., "1060") @@ -867,20 +864,27 @@ defmodule Aprsme.Packet do # Extract standard parser compatibility fields defp put_standard_parser_fields(map, data) do map - |> maybe_put(:srccallsign, data[:srccallsign] || data["srccallsign"]) - |> maybe_put(:dstcallsign, data[:dstcallsign] || data["dstcallsign"]) - |> maybe_put(:body, data[:body] || data["body"]) - |> maybe_put(:origpacket, data[:origpacket] || data["origpacket"]) - |> maybe_put(:header, data[:header] || data["header"]) - |> maybe_put(:alive, data[:alive] || data["alive"]) - |> maybe_put(:posambiguity, data[:posambiguity] || data["posambiguity"]) - |> maybe_put(:symboltable, data[:symboltable] || data["symboltable"]) - |> maybe_put(:symbolcode, data[:symbolcode] || data["symbolcode"]) - |> maybe_put(:messaging, data[:messaging] || data["messaging"]) + |> maybe_put(:srccallsign, get_field_value(data, :srccallsign)) + |> maybe_put(:dstcallsign, get_field_value(data, :dstcallsign)) + |> maybe_put(:body, get_field_value(data, :body)) + |> maybe_put(:origpacket, get_field_value(data, :origpacket)) + |> maybe_put(:header, get_field_value(data, :header)) + |> maybe_put(:alive, get_field_value(data, :alive)) + |> maybe_put(:posambiguity, get_field_value(data, :posambiguity)) + |> maybe_put(:symboltable, get_field_value(data, :symboltable)) + |> maybe_put(:symbolcode, get_field_value(data, :symbolcode)) + |> maybe_put(:messaging, get_field_value(data, :messaging)) end # Extract radio range field defp put_radio_range_field(map, data) do - maybe_put(map, :radiorange, data[:radiorange] || data["radiorange"]) + maybe_put(map, :radiorange, get_field_value(data, :radiorange)) end + + # Helper to get field value from either atom or string key + defp get_field_value(data, field) when is_map(data) do + data[field] || data[to_string(field)] + end + + defp get_field_value(_, _), do: nil end diff --git a/lib/aprsme/packets/query_builder.ex b/lib/aprsme/packets/query_builder.ex index 25e17ea..77c9fcf 100644 --- a/lib/aprsme/packets/query_builder.ex +++ b/lib/aprsme/packets/query_builder.ex @@ -72,15 +72,25 @@ defmodule Aprsme.Packets.QueryBuilder do @doc """ Filters query to only weather packets. + Uses SQL to check if any weather field is not null. """ @spec weather_only(Ecto.Query.t()) :: Ecto.Query.t() def weather_only(query) do from p in query, where: - not is_nil(p.temperature) or not is_nil(p.humidity) or not is_nil(p.pressure) or - not is_nil(p.wind_speed) or not is_nil(p.wind_direction) or not is_nil(p.rain_1h) or - not is_nil(p.rain_24h) or not is_nil(p.rain_since_midnight) or not is_nil(p.snow) or - not is_nil(p.luminosity) + fragment( + "? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL", + p.temperature, + p.humidity, + p.pressure, + p.wind_speed, + p.wind_direction, + p.rain_1h, + p.rain_24h, + p.rain_since_midnight, + p.snow, + p.luminosity + ) end @doc """ diff --git a/lib/aprsme_web/live/map_live/packet_utils.ex b/lib/aprsme_web/live/map_live/packet_utils.ex index acfac52..5a51e8d 100644 --- a/lib/aprsme_web/live/map_live/packet_utils.ex +++ b/lib/aprsme_web/live/map_live/packet_utils.ex @@ -118,10 +118,20 @@ defmodule AprsmeWeb.MapLive.PacketUtils do from p in Aprsme.Packet, where: p.sender == ^callsign, where: - not is_nil(p.temperature) or not is_nil(p.humidity) or not is_nil(p.pressure) or - not is_nil(p.wind_direction) or not is_nil(p.wind_speed) or not is_nil(p.wind_gust) or - not is_nil(p.rain_1h) or not is_nil(p.rain_24h) or not is_nil(p.rain_midnight) or - not is_nil(p.luminosity) or not is_nil(p.snow_24h), + fragment( + "? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL OR ? IS NOT NULL", + p.temperature, + p.humidity, + p.pressure, + p.wind_direction, + p.wind_speed, + p.wind_gust, + p.rain_1h, + p.rain_24h, + p.rain_midnight, + p.luminosity, + p.snow_24h + ), select: fragment("1"), limit: 1 end