aprs.me/lib/parser/types.ex

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
import Decimal, only: [new: 1, add: 2, negate: 1]
lat =
case Regex.run(~r/^(\d{2})(\d{2}\.\d+)([NS])$/, lat_str) do
[_, degrees, minutes, direction] ->
lat_val = add(new(degrees), Decimal.div(new(minutes), new("60")))
if direction == "S", do: negate(lat_val), else: lat_val
_ ->
nil
end
lon =
case Regex.run(~r/^(\d{3})(\d{2}\.\d+)([EW])$/, lon_str) do
[_, degrees, minutes, direction] ->
lon_val = add(new(degrees), Decimal.div(new(minutes), new("60")))
if direction == "W", do: negate(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: Decimal.new(to_string(lat)), longitude: Decimal.new(to_string(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