View Source AprsUtils.AprsParser (AprsUtils v0.1.0)

Module for parsing APRS packets into components.

Philosopy

By its own admission, the APRS protocol is complex and shows definate signs of having a design which evolved and grew during it's development. This module is designed to abstract as much of this away as possible. It reveals only the actual information contained in the packet, and as little about the protocol as it can. For example, the module will not return any information about the type of packet, or if the positional information was compressed. Basically the structure that is returns contains the information the packet contains, and nil in the information fields that the packet does not contain.

See this set of documents for the APRS protocol:

Units

For historical reasons, APRS uses a variety of units. This module will convert all units to this set of SI units.

  • latitude, longitude: degrees (float)
  • distance: meters (float)
  • speed: meters per second (float)
  • temperature: degrees Celsius (float)
  • pressure: pascals (float)
  • humidity: relative percent (float)

Time handling

Some, but not all, APRS packet formats contain timestamps. However all of the formats give only partial time information. One of the most common formats, for example, provides the day, hour, and minutes of transmission. It is the receiver's responsibility to provide the year and month. This can introduce incorrect interpretation of the time, especially if the time between transmission and parsing of the data is long. This module does not attempt to interpret the time, but simply returns the time information that is in the packet. Note that most, but not all, timestamp formats are Zulu Time.

Caution on binary data

Many of the fields described below are returned as binaries taken directly from the APRS packet. These binaries are not necessarily valid UTF-8 strings. In fact, it is common for APRS packets to contain non-printable characters, and non-UTF-8. If you attempt to use these for in an iolist for example, make sure you are prepared to handle non-UTF-8 binaries that fail String.valid?/1.

Unsupported APRS Features

This is the set of Data Type Identifiers which are supported (others will return {:error, ...} tuples). ["!", "=", "@", "/", "'", "`", <<\x1c>>, <<\x1d>>, ">", ":", "T", ";", ")", "$", "_" ]

This module does not support the "!DAO!" construct in the Mic-E format.

This module does not recognize the software/device identifiers (APxxxx) in the TO field.

Summary

Functions

Parses an APRS string into components.

Functions

Parses an APRS string into components.

Args

  • aprs_packet - The APRS packet to parse. Note that this is a binary, but is not necessarily a valid String. APRS packets can, and regularly do, contain non-printable characters, and non-UTF-8 sequences.

Successful Returns

{:ok, %AprsUtils.AprsParser{}}

If an :ok is returned, the APRS packet has been successfully parsed into a struct. The struct contains the decoded components of the APRS packet. If the field of the struct is nil, then the packet did not contain that information.

Here is how to interpret each field of the struct:

FieldDescription
:rawThe same binary passed in to the parse function.
:toA binary containing callsign of the station from which the packet is sent.
:fromA binary often containing callsign of the station to which the packet is sent. Or, this can be used to encode other information found in the packet.
:pathA list of binaries containing the callsigns of the digipeaters or other gateways that the packet has passed through.
:timestampA map containting a set of the following fields: :month, :day, :hour, :minute, :second, and timezone. The fields are all integers, except for :timezone, which is either :zulu or :local_to_sender.
:symbolA two byte binary containing the symbol table and symbol represented in the packet. If you want to extract the bytes you can match <<symbol_table::binary-size(1), symbol::binary-size(1)>>
:positionA map, see the table below for the fields.
:courseA map, see the table below for the fields.
:antennaA map, see the table below for the fields.
:weatherA map, see the table below for the fields.
:telemetryA map containing :sequence_counter, :values, and :bits. :sequence_counter is an integer used to order telemetry reports. :values and :bits are lists. The former contains numeric values, and the later is a sequence of either 1 or 0.
:messageCertain APRS packets are meant to be messages to a specific destination. In this case a message map is returned with the following fields: :addressee, :message, :message_no (which may be missing). :message is a textual message. :message_no is an integer message sequencer.
:statusA binary which is the text from a packet containing a status report. Note, this is distinct from a message or a comment.
:deviceA binary containing the name of the sending device. This implementation is a bit weak in this area.
:objectA map which define's an object which has the fields :name and :state. :name is a binary identifier, and :state is either :killed or :alive.
:itemAn item is just like an object (above) except that semantically it represents an inanimate thing that are occasionally posted on a map (e.g. marathon checkpoints or first-aid posts).
:raw_gpsA binary. A packet can contain the raw GPS information in one of the popular GPS device formats, like an NMEA sentence.
:commentA binary comment on the packet.
Position
:latitudeA tuple in the form {degrees, precision} where degrees is a float, and precision is one of :hundredth_minute, :tenth_minute, :minute, :tenth_degree, or :degree giving the approximate precision.
:longitudeA tuple in the form {degrees, precision} where degrees is a float, and precision is one of :hundredth_minute, :tenth_minute, :minute, :tenth_degree, or :degree giving the approximate precision.
:maidenheadA string like IO91SX. This is given instead of latitude and longitude, but is considered obsolete.
:altitudeA floating point number in meters.
Course
:directionA float in degrees.
:speedA float in meters per second.
:bearingA float in degrees.
:rangeA float in meters.
:report_qualityAn integer from 0 to 8 with 8 being the best, or :manual.
:bearing_accuracyAn integer from 1 to 9 with 9 being the best, or :useless. See Chapter 7 of the APRS Spec. if you want to understand report quality and bearing accuracy better.
Antenna
:powerA float in watts.
:strengthAn integer in S-points from 0 to 9.
:heightA float in meters.
:directivityA float in degrees, or :omnidirectional.
Weather
:temperatureA float in degrees celsius.
:wind_speedA float in meters per second.
:wind_directionA float in degrees.
:gust_speedA float in meters per second.
:barometric_pressureA float in pascals.
:humidityA float in percent.
:rainfall_last_hourA float in meters.
:rainfall_last_24_hoursA float in meters.
:rainfall_since_midnightA float in meters.
:rain_countsA float in counts.
:luminosityA float in watts per square meter.
:snow_fallA float in meters.
:water_heightA float in meters.
:peak_wind_gustA float in meters per second.
:hurricane_winds_radiusA float in meters.
:tropical_storm_winds_radiusA float in meters.
:gale_force_winds_radiusA float in meters.
:software_typeA binary. Together with :wx_unit are meant to describe the weather device reporting. This isn't robustly handled.
:wx_unitA binary.

Error Returns

{:error, Map.t()}

Field
:rawThe same binary passed in to the parse function.
:errorA binary describing the error.
:near_character_positionAn integer indicating the position in the binary where the error was detected.

Note that for many type of errors :near_character_position will be nil.