ogn_client-ruby 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e4b42ab724fb2c9046c419ab356990d476e4dcc
4
- data.tar.gz: 9c1617d22daa0fb63e936eb491acf2e6ff78a39e
3
+ metadata.gz: 02438399c35649b6367b7c29b764915182edc72b
4
+ data.tar.gz: c1d8d0cccae554f55cb74b9944dbcfe91a6a1ea0
5
5
  SHA512:
6
- metadata.gz: 68a2ca8b91f5ec145eb70ffa7cfc511b62ed324f97431a50232193e13b26bc90fb51b036030944b543935245a3900974c3d4b3fbeffac6a74d5bd9ffe34b12f3
7
- data.tar.gz: 6a522636b0cdf6eb93dbde9bb588607474a57a988a64f7f9480a8b3be2457e52f04ccc4afda6d2cecf17940145ada2ec8f3af2bc49183ad6fb3afa991113b4aa
6
+ metadata.gz: 102a7568799ecdbacb814fc7f5ab956a780ef237748f47e4bf4fcca6eedcf1bc11ea299b204a8a4d69da93e66d3f3e9ef4af0f6d55cb1937ca515e38ddc5e458
7
+ data.tar.gz: d9b989f3a32cc8b8c3316afa9a4d48391dee7de676326214a759eb76927f40c856e2008e792449a5df790c19cc605f6909a939631f450af22e404b7f0d3fb7fb
@@ -0,0 +1,14 @@
1
+ ---
2
+ languages:
3
+ Ruby: true
4
+ engines:
5
+ fixme:
6
+ enabled: true
7
+ rubocop:
8
+ enabled: true
9
+ ratings:
10
+ paths:
11
+ - "lib/**"
12
+ - "**.rb"
13
+ exclude_paths:
14
+ - "spec/**/*"
@@ -1,3 +1,4 @@
1
+ ---
1
2
  language: ruby
2
3
  rvm:
3
4
  - 2.2.3
@@ -1,5 +1,51 @@
1
+ ## 0.1.1
2
+
3
+ * remove debug support and raise errors instead
4
+ * convert raw messages to UTF-8 before parsing
5
+ * new sender and receiver attributes
6
+ * `Sender#flight_level
7
+ * `Sender#flarm_software_version`
8
+ * `Sender#flarm_hardware_version`
9
+ * `Sender#flarm_id`
10
+ * `Receiver#manual_correction`
11
+ * `Receiver#automatic_correction`
12
+ * renamed message attribute
13
+ * `Message#speed` -> `Message#ground_speed`
14
+ * verification of supported receiver version
15
+ * supported receiver versions <= 0.2.5
16
+
1
17
  ## 0.1.0
2
18
 
3
- ### initial release
4
19
  * OGN subscription
5
- * parser for senders (aircraft), receivers and comments
20
+ * parser for senders, receivers and comments with attributes
21
+ * `Message#raw`
22
+ * `Message#callsign`
23
+ * `Message#receiver`
24
+ * `Message#time`
25
+ * `Message#longitude`
26
+ * `Message#latitude`
27
+ * `Message#altitude`
28
+ * `Message#heading`
29
+ * `Message#speed`
30
+ * `Sender#stealth_mode`
31
+ * `Sender#no_tracking`
32
+ * `Sender#sender_type`
33
+ * `Sender#address_type`
34
+ * `Sender#id`
35
+ * `Sender#climb_rate`
36
+ * `Sender#turn_rate`
37
+ * `Sender#signal`
38
+ * `Sender#errors`
39
+ * `Sender#frequency_offset`
40
+ * `Sender#gps_accuracy`
41
+ * `Sender#proximity`
42
+ * `Receiver#version`
43
+ * `Receiver#platform`
44
+ * `Receiver#cpu_load`
45
+ * `Receiver#cpu_temperature`
46
+ * `Receiver#ram_free`
47
+ * `Receiver#ram_total`
48
+ * `Receiver#ntp_offset`
49
+ * `Receiver#ntp_correction`
50
+ * `Receiver#signal`
51
+ * `Comment#comment`
data/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ [![Version](https://img.shields.io/gem/v/ogn_client-ruby.svg?style=flat)](https://rubygems.org/gems/ogn_client-ruby)
2
+ [![Continuous Integration](https://img.shields.io/travis/svoop/ogn_client-ruby/master.svg?style=flat)](https://travis-ci.org/svoop/ogn_client-ruby)
3
+ [![Code Climate](https://img.shields.io/codeclimate/github/svoop/ogn_client-ruby.svg?style=flat)](https://codeclimate.com/github/svoop/ogn_client-ruby)
4
+ [![Gitter](https://img.shields.io/gitter/room/svoop/ogn_client-ruby.svg?style=flat)](https://gitter.im/svoop/ogn_client-ruby)
5
+
1
6
  # ogn_client-ruby
2
7
 
3
8
  [OGN](http://glidernet.org) broadcasts aircraft positions as [APRS](http://www.aprs.org)/[APRS-IS](http://www.aprs-is.net) messages. This gem hooks into this stream of data and provides the necessary classes to parse the raw message strings into meaningful objects.
@@ -31,37 +36,39 @@ Choose a [valid callsign](http://www.aprs-is.net/Connecting.aspx#loginrules) and
31
36
 
32
37
  ```ruby
33
38
  OGNClient::APRS.start(callsign: 'ROCT', filter: 'r/33/-97/200') do |aprs|
34
- puts aprs.gets until aprs.eof?
39
+ loop { puts aprs.gets }
35
40
  end
36
41
  ```
37
42
 
38
43
  ### Parse Raw Message Strings
39
44
 
45
+ :point_up: Refer to the wiki for an introduction to [OGN flavoured APRS](https://github.com/svoop/ogn_client-ruby/wiki) messages.
46
+
40
47
  In the above example, each `aprs.gets` returns a raw message string. To decode this string, just pass it to the message parser:
41
48
 
42
49
  ```ruby
43
50
  OGNClient::Message.parse(aprs.gets)
44
51
  ```
45
52
 
46
- This factory method will return an instance of one of the following four classes.
53
+ :point_up: 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".
47
54
 
48
- :point_up: Refer to the wiki for an introduction to [OGN flavoured APRS](https://github.com/svoop/ogn_client-ruby/wiki) messages.
55
+ The factory method `OGNClient::Message.parse` will return one an instance of `OGNClient::Sender`, `OGNClient::Receiver`, `OGNClient::comment` or [raise an error](#errors). When this happens, either the message is crippled, the [OGN](http://glidernet.org) specifications have changed or you have found a bug in the parser code. You may want to store such messages, [file a bug](#community-support) and replay them once the bug has been fixed.
49
56
 
50
57
  #### OGNClient::Sender
51
58
 
52
59
  Senders are usually aircraft equipped with [FLARM](https://flarm.com) (anti-collision warning system) or similar devices which broadcast position data as RF beacons.
53
60
 
54
- The data is converted into the metric system since [OGN](http://glidernet.org) is primarily made for gliders which mostly use the metric system for speed, climb rate and so forth.
61
+ The data is converted into the metric system since [OGN](http://glidernet.org) is primarily made for gliders which mostly use the metric system for ground speed, climb rate and so forth.
55
62
 
56
63
  Attributes:
57
64
  * **callsign** - origin callsign
58
65
  * **receiver** - receiver callsign
59
- * **time** - UTZ/zulu time with date
60
- * **longitude** - degrees from -180 (W) to 180 (E)
61
- * **latitude** - degrees from -90 (S) to 90 (N)
62
- * **altitude** - meters
66
+ * **time** - zulu/UTC time with date
67
+ * **longitude** - WGS84 degrees from -180 (W) to 180 (E)
68
+ * **latitude** - WGS84 degrees from -90 (S) to 90 (N)
69
+ * **altitude** - WGS84 meters above mean see level QNH
63
70
  * **heading** - degrees from 1 to 360
64
- * **speed** - kilometers per hour
71
+ * **ground_speed** - kilometers per hour
65
72
  * **stealth_mode** - boolean (should always be false)
66
73
  * **no_tracking** - boolean
67
74
  * **sender_type** - see [SENDER_TYPES](https://github.com/svoop/ogn_client-ruby/blob/master/lib/ogn_client/messages/sender.rb)
@@ -69,11 +76,15 @@ Attributes:
69
76
  * **id** - device ID
70
77
  * **climb_rate** - meters per second
71
78
  * **turn_rate** - revolutions per minute
79
+ * **flight_level** - 100 feet QNE
72
80
  * **signal** - signal to noise ratio in decibel
73
81
  * **errors** - number of CRC errors
74
82
  * **frequency_offset** - kilohertz
75
83
  * **gps_accuracy** - array [vertical meters, horizontal meters]
76
- * **proximity** - array of callsign tails
84
+ * **flarm_software_version** - version as #<Gem::Version "major.minor">
85
+ * **flarm_hardware_version** - version as #<Gem::Version "major">
86
+ * **flarm_id** - FLARM device ID
87
+ * **proximity** - array of FLARM device ID tails
77
88
 
78
89
  #### OGNClient::Receiver
79
90
 
@@ -82,13 +93,13 @@ Receivers are little RF boxes which pick up the RF beacons from aircraft and rel
82
93
  Attributes:
83
94
  * **callsign** - origin callsign
84
95
  * **receiver** - receiver callsign
85
- * **time** - UTZ/zulu time with date
86
- * **longitude** - degrees from -180 (W) to 180 (E)
87
- * **latitude** - degrees from -90 (S) to 90 (N)
88
- * **altitude** - meters
96
+ * **time** - zulu/UTC time with date
97
+ * **longitude** - WG84 degrees from -180 (W) to 180 (E)
98
+ * **latitude** - WG84 degrees from -90 (S) to 90 (N)
99
+ * **altitude** - WG84 meters above mean sea level QNH
89
100
  * **heading** - degrees from 1 to 360
90
- * **speed** - kilometers per hour
91
- * **version** - software version "major.minor.patch"
101
+ * **ground_speed** - kilometers per hour
102
+ * **version** - software version as #<Gem::Version "major.minor.patch">
92
103
  * **platform** - e.g. :arm
93
104
  * **cpu_load** - as reported by "uptime"
94
105
  * **cpu_temperature** - in degrees celsius
@@ -105,23 +116,42 @@ Comments are sent on a regular basis to keep the connection alive.
105
116
  Attribute:
106
117
  * **comment** - raw message with the comment marker stripped
107
118
 
108
- #### OGNClient::Message
119
+ ## Errors
109
120
 
110
- Generic message objects are only used as a fallback in case the raw message string could not be parsed into one of the above three [OGN](http://glidernet.org) object types. If this happens, either the [OGN](http://glidernet.org) specifications have changed, the message is invalid or you have found a bug in the parser code. You can choose to ignore such messages or to store them for debugging and replaying once the bug is fixed.
121
+ The following domain specific errors may be raised:
111
122
 
112
- ## Debugging
123
+ * OGNClient::MessageError - errors during the parsing of a message
124
+ * OGNClient::ReceiverError - errors during the parsing of a receiver message
113
125
 
114
- To get additional debug messages, either invoke Ruby with the `-d` flag or set the global debug variable explicitly:
126
+ They all inherit from `OGNClient::Error`. An fault-tolerant subscription could therefore look as follows:
115
127
 
116
128
  ```ruby
117
- $DEBUG = true
129
+ logger = Logger.new('/tmp/ogn_client.log')
130
+ OGNClient::APRS.start(callsign: 'ROCT', filter: 'r/33/-97/200') do |aprs|
131
+ loop do
132
+ begin
133
+ message = OGNClient::Message.parse aprs.gets
134
+ rescue OGNClient::Error => error
135
+ logger.error error.message
136
+ end
137
+ puts message.raw
138
+ end
139
+ end
118
140
  ```
119
141
 
142
+ ## Community Support
143
+
144
+ * Look for developers and users on [Gitter](https://gitter.im/svoop/ogn_client-ruby).
145
+ * Ask your questions on [Stackoverflow](https://stackoverflow.com/questions/ask?tags=ogn_client-ruby,ruby,gem).
146
+ * Bug reports and pull requests are welcome on [GitHub](https://github.com/svoop/ogn_client-ruby).
147
+
120
148
  ## Development
121
149
 
122
150
  Check out the repository, install the dependencies and run the test suite:
123
151
 
124
152
  $ git clone git@github.com:svoop/ogn_client-ruby.git
153
+ $ cd ogn_client-ruby
154
+ $ gem install bundler
125
155
  $ bin/setup
126
156
  $ rake
127
157
 
@@ -137,12 +167,9 @@ And to install this gem onto your local machine:
137
167
 
138
168
  $ bundle exec rake install
139
169
 
140
- ## Contributing
141
-
142
- Bug reports and pull requests are welcome on GitHub at https://github.com/svoop/ogn_client-ruby
143
-
144
170
  ## Feature Brainstorming
145
171
 
172
+ * registration lookups
146
173
  * configuration option to switch between metric and aeronautical units
147
174
  * more data sources such as ADS-B
148
175
 
data/Rakefile CHANGED
@@ -9,3 +9,5 @@ Rake::TestTask.new do |t|
9
9
  end
10
10
 
11
11
  task :default => :test
12
+
13
+ Dir.glob('tasks/*.rake').each { |task| load task }
@@ -1,7 +1,7 @@
1
1
  require 'socket'
2
2
 
3
3
  require_relative 'ogn_client/version'
4
- require_relative 'ogn_client/debug'
4
+ require_relative 'ogn_client/errors'
5
5
  require_relative 'ogn_client/aprs'
6
6
  require_relative 'ogn_client/message'
7
7
  require_relative 'ogn_client/messages/comment'
@@ -0,0 +1,8 @@
1
+ module OGNClient
2
+
3
+ class Error < StandardError; end
4
+
5
+ class MessageError < Error; end
6
+ class ReceiverError < Error; end
7
+
8
+ end
@@ -27,49 +27,50 @@ module OGNClient
27
27
  (?<time>\d{6})h
28
28
  (?<latitude>\d{4}\.\d{2}[NS]).
29
29
  (?<longitude>\d{5}\.\d{2}[EW]).
30
- (?:(?<heading>\d{3})/(?<speed>\d{3}))?.*?
30
+ (?:(?<heading>\d{3})/(?<ground_speed>\d{3}))?.*?
31
31
  /A=(?<altitude>\d{6})\s
32
32
  (?:!W((?<latitude_enhancement>\d)(?<longitude_enhancement>\d))!)?
33
33
  )x
34
34
 
35
35
  attr_reader :raw
36
- attr_reader :callsign # origin callsign
37
- attr_reader :receiver # receiver callsign
38
- attr_reader :time # zulu time with date
39
- attr_reader :longitude # degrees from -180 (W) to 180 (E)
40
- attr_reader :latitude # degrees from -90 (S) to 90 (N)
41
- attr_reader :altitude # meters
42
- attr_reader :heading # degrees from 1 to 360
43
- attr_reader :speed # kilometers per hour
36
+ attr_reader :callsign # origin callsign
37
+ attr_reader :receiver # receiver callsign
38
+ attr_reader :time # zulu/UTC time with date
39
+ attr_reader :longitude # WGS84 degrees from -180 (W) to 180 (E)
40
+ attr_reader :latitude # WGS84 degrees from -90 (S) to 90 (N)
41
+ attr_reader :altitude # WGS84 meters above mean sea level QNH
42
+ attr_reader :heading # degrees from 1 to 360
43
+ attr_reader :ground_speed # kilometers per hour
44
44
 
45
45
  def self.parse(raw)
46
- OGNClient::Sender.new.parse(raw) ||
47
- OGNClient::Receiver.new.parse(raw) ||
48
- OGNClient::Comment.new.parse(raw) ||
49
- new.parse(raw)
46
+ fail(OGNClient::MessageError, "raw message must be String but is #{raw.class}") unless raw.is_a? String
47
+ raw = raw.chomp.force_encoding('ASCII-8BIT').encode('UTF-8')
48
+ OGNClient::Sender.new.send(:parse, raw) ||
49
+ OGNClient::Receiver.new.send(:parse, raw) ||
50
+ OGNClient::Comment.new.send(:parse, raw)
50
51
  end
51
52
 
53
+ def to_s
54
+ @raw
55
+ end
56
+
57
+ private
58
+
52
59
  def parse(raw)
53
60
  @raw = raw
54
- raw.match(POSITION_PATTERN) do |match|
61
+ @raw.match(POSITION_PATTERN) do |match|
55
62
  %i(callsign receiver time altitude).each do |attr|
56
63
  send "#{attr}=", match[attr]
57
64
  end
58
65
  self.heading = match[:heading] if match[:heading] && match[:heading] != '000'
59
- self.speed = match[:speed] if match[:speed] && match[:heading] != '000'
66
+ self.ground_speed = match[:ground_speed] if match[:ground_speed] && match[:heading] != '000'
60
67
  self.longitude = [match[:longitude], match[:longitude_enhancement]]
61
68
  self.latitude = [match[:latitude], match[:latitude_enhancement]]
62
69
  self
63
- end || OGNClient.debug("invalid message: `#{@raw}'")
70
+ end || fail(OGNClient::MessageError, "message parsing failed: `#{@raw}'")
64
71
  self
65
72
  end
66
73
 
67
- def to_s
68
- @raw
69
- end
70
-
71
- private
72
-
73
74
  def callsign=(raw)
74
75
  @callsign = raw
75
76
  end
@@ -103,8 +104,8 @@ module OGNClient
103
104
  @heading = raw.to_i
104
105
  end
105
106
 
106
- def speed=(raw)
107
- @speed = (raw.to_i * 1.852).round
107
+ def ground_speed=(raw)
108
+ @ground_speed = (raw.to_i * 1.852).round
108
109
  end
109
110
 
110
111
  end
@@ -8,16 +8,16 @@ module OGNClient
8
8
 
9
9
  attr_reader :comment # free form text comment
10
10
 
11
+ private
12
+
11
13
  def parse(raw)
12
14
  @raw = raw
13
- raw.match COMMENT_PATTERN do |match|
15
+ @raw.match COMMENT_PATTERN do |match|
14
16
  self.comment = match[:comment]
15
17
  self
16
18
  end
17
19
  end
18
20
 
19
- private
20
-
21
21
  def comment=(raw)
22
22
  @comment = raw
23
23
  end
@@ -3,38 +3,54 @@ module OGNClient
3
3
  class Receiver < Message
4
4
 
5
5
  RECEIVER_PATTERN = %r(
6
- v(?<version>\d+\.\d+\.\d+)\.(?<platform>.+?)\s
6
+ (?:
7
+ v(?<version>\d+\.\d+\.\d+)
8
+ (?:\.(?<platform>.+?))?
9
+ \s)?
7
10
  CPU:(?<cpu_load>[\d.]+)\s
8
11
  RAM:(?<ram_free>[\d.]+)/(?<ram_total>[\d.]+)MB\s
9
- NTP:(?<ntp_offset>[\d.]+)ms/(?<ntp_correction>[+-][\d.]+)ppm\s
10
- (?:(?<cpu_temperature>[+-][\d.]+)C\s)?
11
- RF:(?<signal>[+-][\d.]+)dB
12
+ NTP:(?<ntp_offset>[\d.]+)ms/(?<ntp_correction>[+-][\d.]+)ppm\s?
13
+ (?:(?<cpu_temperature>[+-][\d.]+)C\s*)?
14
+ (?:RF:
15
+ (?:
16
+ (?<manual_correction>[+-][\d]+)
17
+ (?<automatic_correction>[+-][\d.]+)ppm/
18
+ )?
19
+ (?<signal>[+-][\d.]+)dB
20
+ )?
12
21
  $)x
13
22
 
14
- attr_reader :version # software version "major.minor.patch"
15
- attr_reader :platform # e.g. "ARM"
16
- attr_reader :cpu_load # as reported by "uptime"
17
- attr_reader :cpu_temperature # degrees celsius
18
- attr_reader :ram_free # megabytes
19
- attr_reader :ram_total # megabytes
20
- attr_reader :ntp_offset # milliseconds
21
- attr_reader :ntp_correction # parts-per-million
22
- attr_reader :signal # signal-to-noise ratio in decibel
23
+ SUPPORTED_RECEIVER_VERSION = Gem::Version.new('0.2.5')
24
+
25
+ attr_reader :version # software version as #<Gem::Version "major.minor.patch">
26
+ attr_reader :platform # e.g. "ARM"
27
+ attr_reader :cpu_load # as reported by "uptime"
28
+ attr_reader :cpu_temperature # degrees celsius
29
+ attr_reader :ram_free # megabytes
30
+ attr_reader :ram_total # megabytes
31
+ attr_reader :ntp_offset # milliseconds
32
+ attr_reader :ntp_correction # parts-per-million
33
+ attr_reader :manual_correction # as per configuration
34
+ attr_reader :automatic_correction # based on GSM
35
+ attr_reader :signal # signal-to-noise ratio in decibel
36
+
37
+ private
23
38
 
24
39
  def parse(raw)
25
- raw.match RECEIVER_PATTERN do |match|
40
+ @raw = raw
41
+ @raw.match RECEIVER_PATTERN do |match|
26
42
  return unless super
27
- %i(version platform cpu_load cpu_temperature ram_free ram_total ntp_offset ntp_correction signal).each do |attr|
43
+ %i(version platform cpu_load cpu_temperature ram_free ram_total ntp_offset ntp_correction manual_correction automatic_correction signal).each do |attr|
28
44
  send("#{attr}=", match[attr]) if match[attr]
29
45
  end
30
46
  self
31
47
  end
32
48
  end
33
49
 
34
- private
35
-
36
50
  def version=(raw)
37
- @version = raw
51
+ @version = Gem::Version.new(raw)
52
+ fail(OGNClient::ReceiverError, "unsupported receiver version: `#{@raw}'") if @version > SUPPORTED_RECEIVER_VERSION
53
+ @version
38
54
  end
39
55
 
40
56
  def platform=(raw)
@@ -65,6 +81,14 @@ module OGNClient
65
81
  @ntp_correction = raw.to_f.round(2)
66
82
  end
67
83
 
84
+ def manual_correction=(raw)
85
+ @manual_correction = raw.to_i
86
+ end
87
+
88
+ def automatic_correction=(raw)
89
+ @automatic_correction = raw.to_f.round(1)
90
+ end
91
+
68
92
  def signal=(raw)
69
93
  @signal = raw.to_f.round(3)
70
94
  end
@@ -6,10 +6,14 @@ module OGNClient
6
6
  id(?<details>\w{2})(?<id>\w+?)\s
7
7
  (?<climb_rate>[+-]\d+?)fpm\s
8
8
  (?<turn_rate>[+-][\d.]+?)rot\s
9
+ (?:FL(?<flight_level>[\d.]+)\s)?
9
10
  (?<signal>[\d.]+?)dB\s
10
11
  (?<errors>\d+)e\s
11
12
  (?<frequency_offset>[+-][\d.]+?)kHz\s?
12
13
  (?:gps(?<gps_accuracy>\d+x\d+)\s?)?
14
+ (?:s(?<flarm_software_version>[\d.]+)\s?)?
15
+ (?:h(?<flarm_hardware_version>[\dA-F]{2})\s?)?
16
+ (?:r(?<flarm_id>[\dA-F]+)\s?)?
13
17
  (?:hear(?<proximity>.+))?
14
18
  $)x
15
19
 
@@ -37,31 +41,39 @@ module OGNClient
37
41
  3 => :ogn
38
42
  }
39
43
 
40
- attr_reader :stealth_mode # boolean
41
- attr_reader :no_tracking # boolean
42
- attr_reader :sender_type # see SENDER_TYPES
43
- attr_reader :address_type # see ADDRESS_TYPES
44
- attr_reader :id # device ID
45
- attr_reader :climb_rate # meters per second
46
- attr_reader :turn_rate # revolutions per minute
47
- attr_reader :signal # signal to noise ratio in decibel
48
- attr_reader :errors # number of CRC errors
49
- attr_reader :frequency_offset # kilohertz
50
- attr_reader :gps_accuracy # array [vertical meters, horizontal meters]
51
- attr_reader :proximity # array of callsign tails
44
+ attr_reader :stealth_mode # boolean
45
+ attr_reader :no_tracking # boolean
46
+ attr_reader :sender_type # see SENDER_TYPES
47
+ attr_reader :address_type # see ADDRESS_TYPES
48
+ attr_reader :id # device ID
49
+ attr_reader :climb_rate # meters per second
50
+ attr_reader :turn_rate # revolutions per minute
51
+ attr_reader :flight_level # 100 feet QNE
52
+ attr_reader :signal # signal to noise ratio in decibel
53
+ attr_reader :errors # number of CRC errors
54
+ attr_reader :frequency_offset # kilohertz
55
+ attr_reader :gps_accuracy # array [vertical meters, horizontal meters]
56
+ attr_reader :flarm_software_version # version as #<Gem::Version "major.minor">
57
+ attr_reader :flarm_hardware_version # version as #<Gem::Version "major">
58
+ attr_reader :flarm_id # FLARM device ID
59
+ attr_reader :proximity # array of FLARM device ID tails
60
+
61
+ private
52
62
 
53
63
  def parse(raw)
54
- raw.match SENDER_PATTERN do |match|
64
+ @raw = raw
65
+ @raw.match SENDER_PATTERN do |match|
55
66
  return unless super
56
- %i(details id climb_rate turn_rate signal errors frequency_offset gps_accuracy proximity).each do |attr|
67
+ %i(details id climb_rate turn_rate flight_level signal errors frequency_offset gps_accuracy flarm_software_version flarm_hardware_version flarm_id proximity).each do |attr|
57
68
  send("#{attr}=", match[attr]) if match[attr]
58
69
  end
70
+ # NOTE: [@svoop] [ruby21] workaround necessary until support for ruby21 is removed
71
+ # self.flarm_id ||= id if address_type == :icao || address_type == :flarm
72
+ self.flarm_id = id if !flarm_id && (address_type == :icao || address_type == :flarm)
59
73
  self
60
74
  end
61
75
  end
62
76
 
63
- private
64
-
65
77
  def details=(raw)
66
78
  byte = raw.to_i(16)
67
79
  @stealth_mode = !(byte & 0b10000000).zero?
@@ -82,6 +94,10 @@ module OGNClient
82
94
  @turn_rate = (raw.to_i / 4.0).round(1)
83
95
  end
84
96
 
97
+ def flight_level=(raw)
98
+ @flight_level = raw.to_f.round(2)
99
+ end
100
+
85
101
  def signal=(raw)
86
102
  @signal = raw.to_f.round(1)
87
103
  end
@@ -98,6 +114,18 @@ module OGNClient
98
114
  @gps_accuracy = raw.split('x').map(&:to_i)
99
115
  end
100
116
 
117
+ def flarm_software_version=(raw)
118
+ @flarm_software_version = Gem::Version.new raw
119
+ end
120
+
121
+ def flarm_hardware_version=(raw)
122
+ @flarm_hardware_version = Gem::Version.new raw.to_i(16)
123
+ end
124
+
125
+ def flarm_id=(raw)
126
+ @flarm_id = raw
127
+ end
128
+
101
129
  def proximity=(raw)
102
130
  @proximity = raw.split(/\shear/)
103
131
  end
@@ -1,3 +1,3 @@
1
1
  module OGNClient
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1".freeze
3
3
  end
@@ -0,0 +1,21 @@
1
+
2
+ namespace :test do
3
+
4
+ desc "Parse real-time APRS messages and test the parser"
5
+ task :parser do
6
+ require 'ogn_client'
7
+ OGNClient::APRS.start(callsign: 'ROCT') do |aprs|
8
+ loop do
9
+ print '.'
10
+ raw = aprs.gets
11
+ begin
12
+ OGNClient::Message.parse raw
13
+ rescue OGNClient::Error => error
14
+ puts
15
+ warn "WARNING: #{error.message}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ogn_client-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-05 00:00:00.000000000 Z
11
+ date: 2015-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -103,6 +103,7 @@ executables: []
103
103
  extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
+ - ".code_climate.yml"
106
107
  - ".editorconfig"
107
108
  - ".gitignore"
108
109
  - ".ruby-version"
@@ -117,13 +118,14 @@ files:
117
118
  - bin/setup
118
119
  - lib/ogn_client.rb
119
120
  - lib/ogn_client/aprs.rb
120
- - lib/ogn_client/debug.rb
121
+ - lib/ogn_client/errors.rb
121
122
  - lib/ogn_client/message.rb
122
123
  - lib/ogn_client/messages/comment.rb
123
124
  - lib/ogn_client/messages/receiver.rb
124
125
  - lib/ogn_client/messages/sender.rb
125
126
  - lib/ogn_client/version.rb
126
127
  - ogn_client-ruby.gemspec
128
+ - tasks/test.rake
127
129
  homepage: https://github.com/svoop/ogn_client-ruby
128
130
  licenses:
129
131
  - MIT
@@ -1,9 +0,0 @@
1
- module OGNClient
2
- class << self
3
-
4
- def debug(message)
5
- puts "DEBUG: #{message}" if $DEBUG
6
- end
7
-
8
- end
9
- end