fix weather
This commit is contained in:
parent
ac415368e8
commit
4348d34f62
7 changed files with 110 additions and 15 deletions
|
|
@ -93,7 +93,7 @@ defmodule Aprsme.CachedQueries do
|
|||
result
|
||||
|
||||
_ ->
|
||||
result = Packets.get_latest_weather_packet_optimized(callsign)
|
||||
result = Packets.get_latest_weather_packet(callsign)
|
||||
# Cache for 5 minutes since weather updates are less frequent
|
||||
Cachex.put(:query_cache, cache_key, result, ttl: @cache_ttl_short)
|
||||
result
|
||||
|
|
@ -118,7 +118,9 @@ defmodule Aprsme.CachedQueries do
|
|||
query =
|
||||
from p in Packet,
|
||||
where: p.sender == ^callsign,
|
||||
where: p.data_type == "weather" or (p.symbol_table_id == "/" and p.symbol_code == "_"),
|
||||
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),
|
||||
limit: 1,
|
||||
select: true
|
||||
|
||||
|
|
|
|||
|
|
@ -737,10 +737,10 @@ defmodule Aprsme.Packets do
|
|||
|
||||
@doc """
|
||||
Gets the most recent weather packet for a callsign.
|
||||
Optimized to check only recent data first before expanding the search window.
|
||||
Looks for any packet containing weather data fields.
|
||||
"""
|
||||
@spec get_latest_weather_packet_optimized(String.t()) :: struct() | nil
|
||||
def get_latest_weather_packet_optimized(callsign) when is_binary(callsign) do
|
||||
@spec get_latest_weather_packet(String.t()) :: struct() | nil
|
||||
def get_latest_weather_packet(callsign) when is_binary(callsign) do
|
||||
# First try last 24 hours
|
||||
one_day_ago = TimeUtils.one_day_ago()
|
||||
|
||||
|
|
@ -748,7 +748,9 @@ defmodule Aprsme.Packets do
|
|||
Repo.one(
|
||||
from(p in Packet,
|
||||
where: p.sender == ^callsign,
|
||||
where: p.data_type == "weather",
|
||||
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),
|
||||
where: p.received_at >= ^one_day_ago,
|
||||
order_by: [desc: p.received_at],
|
||||
limit: 1
|
||||
|
|
@ -763,7 +765,9 @@ defmodule Aprsme.Packets do
|
|||
Repo.one(
|
||||
from(p in Packet,
|
||||
where: p.sender == ^callsign,
|
||||
where: p.data_type == "weather",
|
||||
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),
|
||||
where: p.received_at >= ^one_week_ago,
|
||||
order_by: [desc: p.received_at],
|
||||
limit: 1
|
||||
|
|
|
|||
|
|
@ -76,7 +76,11 @@ defmodule Aprsme.Packets.QueryBuilder do
|
|||
@spec weather_only(Ecto.Query.t()) :: Ecto.Query.t()
|
||||
def weather_only(query) do
|
||||
from p in query,
|
||||
where: p.data_type == "weather" or (p.symbol_table_id == "/" and p.symbol_code == "_")
|
||||
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)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
|
|
|||
|
|
@ -1464,7 +1464,9 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
query =
|
||||
from p in Aprsme.Packet,
|
||||
where: fragment("UPPER(?)", p.sender) in ^normalized_callsigns,
|
||||
where: p.data_type == "weather" or (p.symbol_table_id == "/" and p.symbol_code == "_"),
|
||||
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),
|
||||
select: fragment("UPPER(?)", p.sender),
|
||||
distinct: true
|
||||
|
||||
|
|
|
|||
|
|
@ -76,10 +76,17 @@ defmodule AprsmeWeb.MapLive.PacketUtils do
|
|||
"""
|
||||
@spec weather_packet?(map()) :: boolean()
|
||||
def weather_packet?(packet) do
|
||||
data_type = get_packet_field(packet, :data_type, "")
|
||||
{symbol_table_id, symbol_code} = get_symbol_info(packet)
|
||||
|
||||
data_type == "weather" or (symbol_table_id == "/" and symbol_code == "_")
|
||||
# Check if packet contains any weather data fields
|
||||
not is_nil(get_packet_field(packet, :temperature, nil)) or
|
||||
not is_nil(get_packet_field(packet, :humidity, nil)) or
|
||||
not is_nil(get_packet_field(packet, :pressure, nil)) or
|
||||
not is_nil(get_packet_field(packet, :wind_speed, nil)) or
|
||||
not is_nil(get_packet_field(packet, :wind_direction, nil)) or
|
||||
not is_nil(get_packet_field(packet, :rain_1h, nil)) or
|
||||
not is_nil(get_packet_field(packet, :rain_24h, nil)) or
|
||||
not is_nil(get_packet_field(packet, :rain_since_midnight, nil)) or
|
||||
not is_nil(get_packet_field(packet, :snow, nil)) or
|
||||
not is_nil(get_packet_field(packet, :luminosity, nil))
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
|
|
|||
|
|
@ -74,8 +74,13 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
|
|||
|
||||
# Keep the old handler for backward compatibility
|
||||
def handle_info({:postgres_packet, packet}, socket) do
|
||||
# Only process if it's a weather packet for this callsign
|
||||
if packet.sender == socket.assigns.callsign && packet.data_type == "weather" do
|
||||
# Only process if it's a packet with weather data for this callsign
|
||||
has_weather_data =
|
||||
not is_nil(packet.temperature) or not is_nil(packet.humidity) or
|
||||
not is_nil(packet.pressure) or not is_nil(packet.wind_speed) or
|
||||
not is_nil(packet.wind_direction) or not is_nil(packet.rain_1h)
|
||||
|
||||
if packet.sender == socket.assigns.callsign && has_weather_data do
|
||||
handle_info({:weather_packet, packet}, socket)
|
||||
else
|
||||
{:noreply, socket}
|
||||
|
|
|
|||
71
test/aprsme/packet_weather_extraction_test.exs
Normal file
71
test/aprsme/packet_weather_extraction_test.exs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
defmodule Aprsme.PacketWeatherExtractionTest do
|
||||
use Aprsme.DataCase
|
||||
|
||||
alias Aprsme.Packet
|
||||
|
||||
describe "extract_additional_data/2 with weather data" do
|
||||
test "extracts weather data from parsed APRS weather packet" do
|
||||
# Simulate a real weather packet
|
||||
raw_packet = "AE5PL-13>API510,DSTAR*:!3240.46N/09657.49W_225/004g009t075r000p000h61b10206Plano, TX weather"
|
||||
|
||||
# Parse the packet using the real APRS parser
|
||||
{:ok, parsed_packet} = Aprs.parse(raw_packet)
|
||||
|
||||
# Create packet data as it would come from the parser
|
||||
attrs = %{
|
||||
base_callsign: "AE5PL",
|
||||
ssid: "13",
|
||||
sender: "AE5PL-13",
|
||||
destination: "API510",
|
||||
data_type: to_string(parsed_packet[:data_type]),
|
||||
path: "DSTAR*",
|
||||
information_field: "!3240.46N/09657.49W_225/004g009t075r000p000h61b10206Plano, TX weather",
|
||||
data_extended: parsed_packet
|
||||
}
|
||||
|
||||
# Extract additional data
|
||||
result = Packet.extract_additional_data(attrs, raw_packet)
|
||||
|
||||
# Verify weather data was extracted
|
||||
assert result.temperature == 75
|
||||
assert result.humidity == 61
|
||||
assert result.wind_direction == 225
|
||||
assert result.wind_speed == 4
|
||||
assert result.wind_gust == 9
|
||||
assert result.pressure == 1020.6
|
||||
assert result.rain_1h == 0
|
||||
end
|
||||
|
||||
test "extracts weather data from pure weather packet type" do
|
||||
# Simulate a pure weather packet (starts with _)
|
||||
raw_packet = "AE5PL-WX>APRS:_07121545c220s004g009t075r000p000h61b10206"
|
||||
|
||||
# Parse the packet using the real APRS parser
|
||||
{:ok, parsed_packet} = Aprs.parse(raw_packet)
|
||||
|
||||
# Create packet data as it would come from the parser
|
||||
attrs = %{
|
||||
base_callsign: "AE5PL",
|
||||
ssid: "WX",
|
||||
sender: "AE5PL-WX",
|
||||
destination: "APRS",
|
||||
data_type: to_string(parsed_packet[:data_type]),
|
||||
path: nil,
|
||||
information_field: "_07121545c220s004g009t075r000p000h61b10206",
|
||||
data_extended: parsed_packet
|
||||
}
|
||||
|
||||
# Extract additional data
|
||||
result = Packet.extract_additional_data(attrs, raw_packet)
|
||||
|
||||
# Verify weather data was extracted
|
||||
assert result.temperature == 75
|
||||
assert result.humidity == 61
|
||||
assert result.wind_direction == 220
|
||||
assert result.wind_speed == 4
|
||||
assert result.wind_gust == 9
|
||||
assert result.pressure == 1020.6
|
||||
assert result.rain_1h == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue