OGN broadcasts aircraft positions as APRS/APRS-IS messages. This gem hooks into this stream of data and provides the necessary classes to parse the raw message strings into meaningful objects.
- Homepage: https://github.com/svoop/ogn_client-ruby
- Author: Sven Schwyn
Thank you for supporting free and open-source software by sponsoring on GitHub or on Donorbox. Any gesture is appreciated, from a single Euro for a βοΈ cup of coffee to πΉ early retirement.
This gem is cryptographically signed in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:
gem cert --add <(curl -Ls https://raw.github.com/svoop/ogn_client-ruby/master/certs/svoop.pem)
Add the following to the Gemfile or gems.rb of your Bundler powered Ruby project:
gem 'ogn_client-ruby', require: 'ogn_client'
And then install the bundle:
bundle install --trust-policy MediumSecurity
If you're only going to use the executables:
gem install ogn_client-ruby --trust-policy MediumSecurity
Choose a valid callsign and appropriate filters, then start listening to the broadcasted raw messages:
require 'ogn_client'
OGNClient::APRS.start(callsign: "ROCT#{rand(1000)}", filter: 'r/47/2/500') do |aprs|
while raw = aprs.gets
puts raw # do more interesting stuff here
end
end
βοΈ Refer to the wiki for an introduction to OGN flavoured APRS messages.
In the above example, each aprs.gets
returns a raw message string. To decode this string, just pass it to the message parser:
OGNClient::Message.parse(aprs.gets)
βοΈ Raw APRS messages as returned by aprs.gets
are "ASCII-8BIT" encoded and may contain tailing whitespace. The parser removes this whitespace and converts the string to "UTF-8".
The factory method OGNClient::Message.parse
will return one an instance of OGNClient::Sender
, OGNClient::Receiver
, OGNClient::Comment
or raise an error. When this happens, either the message is crippled, the OGN specifications have changed or you have found a bug in the parser code.
In production, you may want to rescue from these errors and ignore the message. You should, however, log the offending messages messages, file a bug and replay them once the bug has been fixed.
βοΈ Raw APRS messages do not contain the date, but assume the current day. This may cause trouble around midnight, however, the parser deals with such edge cases gracefully. Things are a little different when parsing raw APRS messages recorded in the past e.g. with ognlogd
. Since the parser has no means to detect the date the APRS messages have been sent, you have to pass it as an option:
raw_aprs = File.open('2017-06-24.log', &:gets)
OGNClient::Message.parse(raw_aprs, date: '2017-06-24')
Sender beacons are usually coming from aircraft equipped with FLARM (anti-collision warning system) or similar devices which broadcast position data as RF beacons.
The data is converted into the metric system since OGN is primarily made for gliders which mostly use the metric system for ground speed, climb rate and so forth.
Attributes:
- callsign - origin callsign
- receiver - receiver callsign
- time - zulu/UTC time with date
- longitude - WGS84 degrees from -180 (W) to 180 (E)
- latitude - WGS84 degrees from -90 (S) to 90 (N)
- altitude - WGS84 meters above mean see level QNH
- heading - degrees from 1 to 360
- ground_speed - kilometers per hour
- sender_type - see SENDER_TYPES
- address_type - see ADDRESS_TYPES
- id - device ID
- stealth_mode - boolean (should always be false)
- no_tracking - boolean
- flight_level - 100 feet QNE
- climb_rate - meters per second
- turn_rate - revolutions per minute
- signal_power - power ratio in dBm
- signal_quality - signal to noise ratio in decibel
- errors - number of CRC errors
- frequency_offset - kilohertz
- gps_accuracy - array [vertical meters, horizontal meters]
- flarm_software_version - version as "major.minor"
- flarm_hardware_version - version as integer
- flarm_id - FLARM device ID
- proximity - array of FLARM device ID tails
Receivers are little RF boxes which pick up the RF beacons from aircraft and relay them to the OGN servers as messages. They send their own beacons on a regular basis.
Attributes:
- callsign - origin callsign
- receiver - receiver callsign
- time - zulu/UTC time with date
- longitude - WG84 degrees from -180 (W) to 180 (E)
- latitude - WG84 degrees from -90 (S) to 90 (N)
- altitude - WG84 meters above mean sea level QNH
- heading - degrees from 1 to 360
- ground_speed - kilometers per hour
Please note: These receiver beacons contained status information up until version 0.2.5.
Receivers of version 0.2.6 and higher send status messages on a regular basis:
Attributes:
- callsign - origin callsign
- receiver - receiver callsign
- time - zulu/UTC time with date
- version - software version as "major.minor.patch"
- platform - e.g. :arm
- cpu_load - as reported by "uptime"
- cpu_temperature - in degrees celsius
- ram_free - megabytes
- ram_total - megabytes
- ntp_offset - milliseconds
- ntp_correction - parts-per-million
- voltage - board voltage in V
- amperage - board amperage in A
- rf_correction_manual - manual frequency correction as per configuration
- rf_correction_automatic - automatic frequency correction based on GSM
- senders - number of senders received within the last hour
- visible_senders - number of visible senders withint the last hour
- invisible_senders - number of invisible senders ("no-track" on device or "invisible" in database)
- signal_quality - signal-to-noise ratio in decibel
- senders_signal_quality - average signal-to-noise ratio across all senders
- senders_messages - number of messages analyzed to calculate the above
- good_senders_signal_quality - average signal-to-noise ratio in decibel of good senders (transmitting properly) within the last 24 hours
- good_and_bad_senders - number of good and bad senders within the last 24 hours
- good_senders - number of good senders (transmitting properly) within the last 24 hours
- bad_senders - number of bad senders (not transmitting properly) within the last 24 hours
Comments are sent on a regular basis to keep the connection alive.
Attribute:
- comment - raw message with the comment marker stripped
The following domain specific errors may be raised:
- OGNClient::MessageError - errors during the parsing of a message
- OGNClient::ReceiverError - errors during the parsing of a receiver message
They all inherit from OGNClient::Error
. An fault-tolerant subscription could therefore look as follows:
require 'ogn_client'
require 'logger'
logger = Logger.new('/tmp/ogn_client.log')
options = { callsign: "ROCT#{rand(1000)}", filter: 'r/47/2/500' }
loop do
OGNClient::APRS.start(options) do |aprs|
while raw = aprs.gets
begin
message = OGNClient::Message.parse aprs.gets
rescue OGNClient::Error => error
logger.error error.message
next
end
puts message.raw # do more interesting stuff here
end
end
end
βοΈ Receiver versions ("major.minor.patch") are will only raise an error when the offending version has a higher major or minor version digit. Patch level differences will only trigger a warning.
A simple daemon to log raw APRS messages to daily files.
ognlogd --help
Convert raw APRS messages (e.g. from ognlogd
) to KML or GeoJSON.
ogn2kml --help
ogn2geojson --help
- Look for developers and users on Gitter.
- Ask your questions on Stackoverflow.
- Annotated source code on omniref
- Bug reports, feature and pull requests are welcome on GitHub.
- Donations are welcome as welll. If you prefer to sponsor a feature, please create an issue on GitHub first and state your intentions.
To install the development dependencies and then run the test suite:
bundle install bundle exec rake # run tests once bundle exec guard # run tests whenever files are modified
The test suite may run against live OGN data if you set the SPEC_SCOPE
environment variable, by default, these tests are skipped.
export SPEC_SCOPE=all
Please submit issues on:
https://github.com/svoop/ogn_client-ruby/issues
To contribute code, fork the project on Github, add your code and submit a pull request:
https://help.github.com/articles/fork-a-repo
- registration lookups
- configuration option to switch between metric and aeronautical units
- more data sources such as ADS-B
The gem is available as open source under the terms of the MIT License.