91 lines
2 KiB
Elixir
91 lines
2 KiB
Elixir
defmodule Parser.Types do
|
|
@moduledoc """
|
|
Core types and structs for APRS parser.
|
|
"""
|
|
|
|
alias Parser.Types.MicE
|
|
|
|
@type mice :: MicE.t()
|
|
|
|
defmodule Packet do
|
|
@moduledoc false
|
|
@type t :: %__MODULE__{}
|
|
defstruct [
|
|
:id,
|
|
:sender,
|
|
:path,
|
|
:destination,
|
|
:information_field,
|
|
:data_type,
|
|
:base_callsign,
|
|
:ssid,
|
|
:data_extended,
|
|
:received_at
|
|
]
|
|
end
|
|
|
|
defmodule Position do
|
|
@moduledoc false
|
|
@type t :: %__MODULE__{}
|
|
defstruct [
|
|
:latitude,
|
|
:longitude,
|
|
:timestamp,
|
|
:symbol_table_id,
|
|
:symbol_code,
|
|
:comment,
|
|
:aprs_messaging?,
|
|
:compressed?,
|
|
:position_ambiguity,
|
|
:dao
|
|
]
|
|
|
|
@doc """
|
|
Parse APRS lat/lon strings (e.g., "3339.13N", "11759.13W") into a map with latitude and longitude.
|
|
"""
|
|
def from_aprs(lat_str, lon_str) do
|
|
# Parse latitude: DDMM.MM format
|
|
lat =
|
|
case Regex.run(~r/^(\d{2})(\d{2}\.\d+)([NS])$/, lat_str) do
|
|
[_, degrees, minutes, direction] ->
|
|
lat_val = String.to_integer(degrees) + String.to_float(minutes) / 60
|
|
if direction == "S", do: -lat_val, else: lat_val
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
|
|
# Parse longitude: DDDMM.MM format
|
|
lon =
|
|
case Regex.run(~r/^(\d{3})(\d{2}\.\d+)([EW])$/, lon_str) do
|
|
[_, degrees, minutes, direction] ->
|
|
lon_val = String.to_integer(degrees) + String.to_float(minutes) / 60
|
|
if direction == "W", do: -lon_val, else: lon_val
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
|
|
%{latitude: lat, longitude: lon}
|
|
end
|
|
|
|
@doc """
|
|
Return a map with latitude and longitude from decimal values.
|
|
"""
|
|
def from_decimal(lat, lon) do
|
|
%{latitude: lat, longitude: lon}
|
|
end
|
|
end
|
|
|
|
defmodule ParseError do
|
|
@moduledoc false
|
|
@type t :: %__MODULE__{}
|
|
defstruct [
|
|
:error_code,
|
|
:error_message,
|
|
:raw_data
|
|
]
|
|
end
|
|
|
|
# Add more structs as needed for NMEA, PHG, etc.
|
|
end
|