Strip weather data, RNG, and negative altitudes from packet comments
Weather packets had raw data strings (e.g. 007/000g000t054...) stored as the comment instead of the trailing human-readable text. Now iteratively strips fixed-width APRS weather fields in any order, handling both position-included (XXX/XXX) and positionless (cXXXsXXX) formats. Also strips RNG data and fixes altitude regex to handle negative values. Empty comments after cleaning return nil.
This commit is contained in:
parent
2305635a30
commit
ddf26a99ce
2 changed files with 170 additions and 1 deletions
|
|
@ -750,15 +750,66 @@ defmodule Aprsme.Packet do
|
|||
|
||||
defp clean_comment(comment) when is_binary(comment) do
|
||||
comment
|
||||
|> strip_weather_data()
|
||||
# Remove altitude
|
||||
|> String.replace(~r/\s*\/A=\d{6}/, "")
|
||||
|> String.replace(~r/\s*\/A=-?\d{5,6}/, "")
|
||||
# Remove PHG
|
||||
|> String.replace(~r/PHG\d{4}\s*/, "")
|
||||
# Remove RNG
|
||||
|> String.replace(~r/RNG\d{4}\s*/, "")
|
||||
|> String.trim()
|
||||
|> case do
|
||||
"" -> nil
|
||||
cleaned -> cleaned
|
||||
end
|
||||
end
|
||||
|
||||
defp clean_comment(comment), do: comment
|
||||
|
||||
# APRS weather fields: each is a letter prefix + fixed number of digits/spaces
|
||||
@wx_field_patterns [
|
||||
~r/^g[\d .]{3}/,
|
||||
~r/^t[\d .-]{3}/,
|
||||
~r/^r[\d .]{3}/,
|
||||
~r/^p[\d .]{3}/,
|
||||
~r/^P[\d .]{3}/,
|
||||
~r/^h[\d .]{2}/,
|
||||
~r/^b[\d .]{5}/,
|
||||
~r/^s[\d .]{3}/,
|
||||
~r/^[Ll][\d .]{3}/
|
||||
]
|
||||
|
||||
# Matches position-included format (XXX/XXX) and positionless format (cXXXsXXX)
|
||||
@wx_preamble_pattern ~r/^_?(?:[\d .]{3}\/[\d .]{3}|c[\d .]{3}s[\d .]{3})/
|
||||
|
||||
defp strip_weather_data(comment) do
|
||||
case Regex.run(@wx_preamble_pattern, comment) do
|
||||
[match] ->
|
||||
comment
|
||||
|> String.slice(String.length(match)..-1//1)
|
||||
|> strip_wx_fields()
|
||||
|
||||
nil ->
|
||||
comment
|
||||
end
|
||||
end
|
||||
|
||||
defp strip_wx_fields(str) do
|
||||
case match_wx_field(str) do
|
||||
nil -> str
|
||||
match -> str |> String.slice(String.length(match)..-1//1) |> strip_wx_fields()
|
||||
end
|
||||
end
|
||||
|
||||
defp match_wx_field(str) do
|
||||
Enum.find_value(@wx_field_patterns, fn pat ->
|
||||
case Regex.run(pat, str) do
|
||||
[match] -> match
|
||||
nil -> nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
# Extract altitude from APRS comment field (e.g., "/A=000680" means 680 feet)
|
||||
defp extract_altitude_from_comment(nil), do: nil
|
||||
|
||||
|
|
|
|||
|
|
@ -91,4 +91,122 @@ defmodule Aprsme.PacketTest do
|
|||
assert get_in(result, [:data, "telemetry_bits"]) == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "comment cleaning" do
|
||||
test "strips weather data from weather packet comments" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "weather",
|
||||
data_extended: %{
|
||||
comment: "007/000g000t054r000p001P001b10052h90eMB61",
|
||||
data_type: :weather,
|
||||
wx: %{temperature: 54, humidity: 90, wind_speed: 0},
|
||||
latitude: 36.124,
|
||||
longitude: -75.723
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] == "eMB61"
|
||||
end
|
||||
|
||||
test "strips weather data with luminosity and preserves trailing comment" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "weather",
|
||||
data_extended: %{
|
||||
comment: "225/004g009t075r000p000h61b10206Plano, TX weather",
|
||||
data_type: :weather,
|
||||
wx: %{temperature: 75, humidity: 61, wind_speed: 4},
|
||||
latitude: 32.0,
|
||||
longitude: -96.0
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] == "Plano, TX weather"
|
||||
end
|
||||
|
||||
test "strips weather data with snow and luminosity fields" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "weather",
|
||||
data_extended: %{
|
||||
comment: "082/002g005t074r000p000P000b10099h58L708eMB63",
|
||||
data_type: :weather,
|
||||
wx: %{temperature: 74, humidity: 58, wind_speed: 2},
|
||||
latitude: 30.0,
|
||||
longitude: -90.0
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] == "eMB63"
|
||||
end
|
||||
|
||||
test "handles weather comment that is all weather data" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "weather",
|
||||
data_extended: %{
|
||||
comment: "_180/010g015t072r000p000h45b10132s005",
|
||||
data_type: :weather,
|
||||
wx: %{temperature: 72, humidity: 45, wind_speed: 10},
|
||||
latitude: 32.0,
|
||||
longitude: -96.0
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] in [nil, ""]
|
||||
end
|
||||
|
||||
test "strips positionless weather format (cXXXsXXX)" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "weather",
|
||||
data_extended: %{
|
||||
comment: "c011s000g000t077r000P000L000h95b10080GW2000C MaxGust:1.1mph",
|
||||
data_type: :weather,
|
||||
wx: %{temperature: 77, humidity: 95},
|
||||
latitude: 6.0,
|
||||
longitude: 79.0
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] == "GW2000C MaxGust:1.1mph"
|
||||
end
|
||||
|
||||
test "strips RNG data from comments" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "position",
|
||||
data_extended: %{
|
||||
comment: "RNG0050 2m Voice 145.57500MHz",
|
||||
latitude: 61.0,
|
||||
longitude: 14.0,
|
||||
radiorange: "0050"
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] == "2m Voice 145.57500MHz"
|
||||
end
|
||||
|
||||
test "does not modify non-weather, non-RNG comments" do
|
||||
attrs = %{
|
||||
sender: "TEST",
|
||||
data_type: "position",
|
||||
data_extended: %{
|
||||
comment: "70cm Voice (D-Star) 447.12500MHz -3.0000MHz",
|
||||
latitude: 46.0,
|
||||
longitude: -94.0
|
||||
}
|
||||
}
|
||||
|
||||
result = Packet.extract_additional_data(attrs, "test_packet")
|
||||
assert result[:comment] == "70cm Voice (D-Star) 447.12500MHz -3.0000MHz"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue