aprs.me/test/aprsme/packet_test.exs
Graham McIntire 179e2e407d
fix: Convert telemetry_seq string values to integers
The APRS parser returns telemetry sequence numbers as strings (e.g., "094"),
but the database schema expects integers. This was causing Ecto.ChangeError
in production when processing telemetry packets.

Changes:
- Updated put_telemetry_fields/2 to convert string seq values to integers
- Added comprehensive tests for telemetry_seq type conversion
- Handles nil, string, integer, and invalid seq values gracefully

Production deployment notes:
1. Check if migration 20250801215236 has run in production
2. If not, run pending migrations before deploying this fix

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 17:12:47 -05:00

176 lines
5.3 KiB
Elixir

defmodule Aprsme.PacketTest do
use Aprsme.DataCase, async: true
alias Aprsme.Packet
describe "extract_additional_data/2" do
test "position packet with course/speed should not be classified as weather" do
# This is the problematic packet from KG5GKC-12
raw_packet =
"KG5GKC-12>APAT51,WIDE1-1,WIDE2-2,qAO,NI2C-10:!3310.04N/09640.40Wk038/023/A=000623AT-MOBILE KG5GKC@YAHOO.COM"
# Simulate the parsed data from APRS parser
attrs = %{
sender: "KG5GKC-12",
destination: "APAT51",
path: "WIDE1-1,WIDE2-2,qAO,NI2C-10",
information_field: "!3310.04N/09640.40Wk038/023/A=000623AT-MOBILE KG5GKC@YAHOO.COM",
data_type: :position,
base_callsign: "KG5GKC",
ssid: "12",
data_extended: %{
latitude: Decimal.new("33.167333"),
longitude: Decimal.new("-96.673333"),
symbol_table_id: "/",
symbol_code: "k",
comment: "038/023/A=000623AT-MOBILE KG5GKC@YAHOO.COM",
course: 38,
speed: 23.0,
data_type: :position,
has_position: true
}
}
result = Packet.extract_additional_data(attrs, raw_packet)
# The data_type should be "position" (normalized to string)
assert result[:data_type] == "position" or result[:data_type] == :position
assert result[:symbol_code] == "k"
assert result[:symbol_table_id] == "/"
assert result[:course] == 38
assert result[:speed] == 23.0
assert result[:raw_packet] == raw_packet
end
test "actual weather packet should be classified as weather" do
raw_packet = "KC0ABC>APRS:_10090556c220s004g005t077P000h50b09900"
attrs = %{
sender: "KC0ABC",
destination: "APRS",
path: "",
information_field: "_10090556c220s004g005t077P000h50b09900",
data_type: :weather,
base_callsign: "KC0ABC",
ssid: nil,
data_extended: %{
timestamp: "10090556",
wind_direction: 220,
wind_speed: 4.0,
wind_gust: 5.0,
temperature: 77.0,
rain_since_midnight: 0.0,
humidity: 50.0,
pressure: 990.0,
data_type: :weather
}
}
result = Packet.extract_additional_data(attrs, raw_packet)
# Weather packet should remain as weather (normalized to string)
assert result[:data_type] == "weather" or result[:data_type] == :weather
assert result[:temperature] == 77.0
assert result[:humidity] == 50.0
assert result[:pressure] == 990.0
end
test "position packet with weather symbol should use parser's determination" do
raw_packet = "KC0ABC>APRS:=3310.04N/09640.40W_PHG5130"
attrs = %{
sender: "KC0ABC",
destination: "APRS",
path: "",
information_field: "=3310.04N/09640.40W_PHG5130",
# Parser determined this is position despite weather symbol
data_type: :position,
base_callsign: "KC0ABC",
ssid: nil,
data_extended: %{
latitude: Decimal.new("33.167333"),
longitude: Decimal.new("-96.673333"),
symbol_table_id: "/",
symbol_code: "_",
comment: "PHG5130",
data_type: :position,
has_position: true
}
}
result = Packet.extract_additional_data(attrs, raw_packet)
# Should trust parser's determination (normalized to string)
assert result[:data_type] == "position" or result[:data_type] == :position
assert result[:symbol_code] == "_"
end
test "telemetry packet with string seq value should convert to integer" do
raw_packet = "KC0ABC>APRS:T#094,199,000,255,073,123,00000000"
attrs = %{
sender: "KC0ABC",
destination: "APRS",
path: "",
information_field: "T#094,199,000,255,073,123,00000000",
data_type: :telemetry,
base_callsign: "KC0ABC",
ssid: nil,
data_extended: %{
telemetry: %{
seq: "094",
vals: [199, 0, 255, 73, 123],
bits: "00000000"
},
data_type: :telemetry
}
}
result = Packet.extract_additional_data(attrs, raw_packet)
# telemetry_seq should be converted to integer
assert result[:telemetry_seq] == 94
assert result[:telemetry_vals] == [199, 0, 255, 73, 123]
assert result[:telemetry_bits] == "00000000"
end
test "telemetry packet with integer seq value should remain integer" do
attrs = %{
sender: "KC0ABC",
data_type: :telemetry,
data_extended: %{
telemetry: %{
seq: 42,
vals: [100, 200],
bits: "11110000"
}
}
}
result = Packet.extract_additional_data(attrs, "")
assert result[:telemetry_seq] == 42
assert result[:telemetry_vals] == [100, 200]
assert result[:telemetry_bits] == "11110000"
end
test "telemetry packet with invalid seq value should be nil" do
attrs = %{
sender: "KC0ABC",
data_type: :telemetry,
data_extended: %{
telemetry: %{
seq: "invalid",
vals: [100],
bits: "00000000"
}
}
}
result = Packet.extract_additional_data(attrs, "")
assert result[:telemetry_seq] == nil
assert result[:telemetry_vals] == [100]
end
end
end