ogn_client-ruby 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cac6cf6364fa78e20954308deb6258c8ae789661
4
- data.tar.gz: b5c802a8c11071a73549abaa50d7cf8e7cf03128
3
+ metadata.gz: cc7bfb92c9ee1a6a43a8fbe34b66a795c1a34551
4
+ data.tar.gz: 663f89af96ca723f2042fa46c943abf831c0dc9e
5
5
  SHA512:
6
- metadata.gz: e60aabf34f6e4967e9423b732d676149fda8fb1f3470d3e02b37f791b4804ddc637dfb09538dcac92ecc4687672eb4c2cf84f802d694a031f59734394ac448b1
7
- data.tar.gz: 1e6903681dcb6c26c5f3612f304914b867113b7598f7816f5d907c46cbade23d8392bc0a31fa43a4d61102fa08fe402e1a818bb0e9aaed06ac33c8c9d12c67df
6
+ metadata.gz: 47cd82bc99d6c9147ab1af0cbf29dbff876d536e50416f914a00a292b82dbb50b8f3e87a91faad2fe91ff52eb8024d57baa83541d504389895c6030a7852330e
7
+ data.tar.gz: 58a4744ec0cb1b4bcb9c35a3138b080d7bca6c301f953ceb08cb0204f0e8669ea6237aa04e5c0db68a8a88baeb8ba76332e4e97d577738a961627c506ff67618
data/.travis.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3.3
5
- - 2.2.6
6
- - 2.1.10
7
- before_install: gem install bundler -v 1.13.6
4
+ - 2.4.1
5
+ - 2.3.4
6
+ - 2.2.7
7
+ before_install: gem install bundler -v 1.14.6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.2
2
+
3
+ * add example executables
4
+ * ognlogd
5
+ * ogn2kml
6
+
1
7
  ## 0.2.0
2
8
 
3
9
  * support for receiver versions <= 0.2.6
data/README.md CHANGED
@@ -180,6 +180,20 @@ end
180
180
 
181
181
  :point_up: 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.
182
182
 
183
+ ## Executables
184
+
185
+ ### ognlogd
186
+
187
+ A simple daemon to log raw APRS messages to daily files.
188
+
189
+ ognlogd --help
190
+
191
+ ### ogn2kml
192
+
193
+ Convert raw APRS messages (e.g. from `ognlogd`) to KML.
194
+
195
+ ogn2kml --help
196
+
183
197
  ## Community Support
184
198
 
185
199
  * Look for developers and users on [Gitter](https://gitter.im/svoop/ogn_client-ruby).
data/exe/ogn2kml ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/inline'
4
+ require 'optparse'
5
+
6
+ gemfile do
7
+ source 'https://rubygems.org'
8
+ ruby '>= 2.4'
9
+ gem 'progressbar', '~> 1.8'
10
+ gem 'libxml-ruby', '~> 3.0', require: 'xml'
11
+ gem 'ogn_client-ruby', '~> 0.2', require: 'ogn_client'
12
+ end
13
+
14
+ class Converter
15
+ def initialize
16
+ OptionParser.new do |o|
17
+ o.banner = <<~END
18
+ Convert raw OGN APRS to KML tracks.
19
+ Usage: ogn2kml [options] infile
20
+ END
21
+ o.on('-a', '--about', 'author and license information') { puts 'Written by Sven Schwyn (bitcetera.com) and distributed under MIT license.'; exit }
22
+ o.on('-c', '--callsign STRING', String, 'aircraft callsign (e.g. FLRAABBCC)') { |v| @callsign = v }
23
+ o.on('-o', '--outfile FILE', String, 'generated KML file (default: INFILE.kml)') { |v| @outfile = v.sub(/\.kml$/, '') + '.kml' }
24
+ end.parse!
25
+ @infile = ARGV.pop
26
+ fail 'infile not found' unless @infile && File.exists?(@infile)
27
+ @outfile ||= @infile.sub(/\.\w+$/, '') + '.kml'
28
+ end
29
+
30
+ def style_nodes
31
+ fragment = <<~END
32
+ <Fragment>
33
+ <Style id="track_normal">
34
+ <IconStyle>
35
+ <Icon>
36
+ <href>http://earth.google.com/images/kml-icons/track-directional/track-0.png</href>
37
+ </Icon>
38
+ </IconStyle>
39
+ <LineStyle>
40
+ <color>99ffac59</color>
41
+ <width>6</width>
42
+ </LineStyle>
43
+ </Style>
44
+ <Style id="track_highlight">
45
+ <IconStyle>
46
+ <scale>1.2</scale>
47
+ <Icon>
48
+ <href>http://earth.google.com/images/kml-icons/track-directional/track-0.png</href>
49
+ </Icon>
50
+ </IconStyle>
51
+ <LineStyle>
52
+ <color>99ffac59</color>
53
+ <width>8</width>
54
+ </LineStyle>
55
+ </Style>
56
+ <StyleMap id="track">
57
+ <Pair>
58
+ <key>normal</key>
59
+ <styleUrl>#track_normal</styleUrl>
60
+ </Pair>
61
+ <Pair>
62
+ <key>highlight</key>
63
+ <styleUrl>#track_highlight</styleUrl>
64
+ </Pair>
65
+ </StyleMap>
66
+ </Fragment>
67
+ END
68
+ XML::Parser.string(fragment).parse.root.each_child { |c| yield c }
69
+ end
70
+
71
+ def convert!
72
+ lines = File.readlines(@infile)
73
+ progressbar = ProgressBar.create(format: '%e |%b>%i| %p%% %t', total: lines.count)
74
+ xml = XML::Document.new
75
+ root = xml.root = XML::Node.new(:kml)
76
+ root['xmlns'] = 'http://www.opengis.net/kml/2.2'
77
+ root['xmlns:gx'] = 'http://www.google.com/kml/ext/2.2'
78
+ root << (document = XML::Node.new(:Document))
79
+ document << XML::Node.new(:name, 'OGN')
80
+ style_nodes { |n| document << xml.import(n) }
81
+ document << (folder = XML::Node.new(:Folder))
82
+ folder << XML::Node.new(:name, 'Tracks')
83
+ folder << (placemark = XML::Node.new(:Placemark))
84
+ placemark << XML::Node.new(:name, @callsign || 'all')
85
+ placemark << XML::Node.new(:styleUrl, '#track')
86
+ placemark << (track = XML::Node.new(:'gx:Track'))
87
+ track << XML::Node.new(:altitudeMode, 'absolute')
88
+ time = XML::Node.new(:'gx:SimpleArrayData')
89
+ time['name'] = 'Time'
90
+ ground_speed = XML::Node.new(:'gx:SimpleArrayData')
91
+ ground_speed['name'] = 'Ground Speed'
92
+ climb_rate = XML::Node.new(:'gx:SimpleArrayData')
93
+ climb_rate['name'] = 'Climb Rate'
94
+ turn_rate = XML::Node.new(:'gx:SimpleArrayData')
95
+ turn_rate['name'] = 'Turn Rate'
96
+ lines.each do |line|
97
+ if (sender = OGNClient::Message.parse(line)).is_a? OGNClient::SenderBeacon
98
+ if !@callsign || sender.callsign == @callsign
99
+ track << XML::Node.new(:when, sender.time.xmlschema)
100
+ track << XML::Node.new(:'gx:coord', "#{sender.longitude} #{sender.latitude} #{sender.altitude}")
101
+ track << XML::Node.new(:'gx:angles', "#{sender.heading} 0 0")
102
+ time << XML::Node.new(:'gx:value', sender.time.getlocal.strftime('%H:%M:%S'))
103
+ ground_speed << XML::Node.new(:'gx:value', sender.ground_speed.to_i.to_s)
104
+ climb_rate << XML::Node.new(:'gx:value', sender.climb_rate.to_i.to_s)
105
+ turn_rate << XML::Node.new(:'gx:value', sender.turn_rate.to_i.to_s)
106
+ end
107
+ end
108
+ progressbar.increment
109
+ end
110
+ track << (extended_data = XML::Node.new(:ExtendedData))
111
+ extended_data << (schema_data = XML::Node.new(:SchemaData))
112
+ schema_data['schemaUrl'] = '#schema'
113
+ schema_data << time
114
+ schema_data << ground_speed
115
+ schema_data << climb_rate
116
+ schema_data << turn_rate
117
+ xml.save(@outfile, encoding: XML::Encoding::UTF_8)
118
+ end
119
+ end
120
+
121
+ begin
122
+ Converter.new.convert!
123
+ rescue => exception
124
+ puts "#{File.basename($0)}: #{exception.message}"
125
+ exit 1
126
+ end
data/exe/ognlogd ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/inline'
4
+ require 'optparse'
5
+ require 'time'
6
+
7
+ gemfile do
8
+ source 'https://rubygems.org'
9
+ ruby '>= 2.4'
10
+ gem 'ogn_client-ruby', '~> 0.2', require: 'ogn_client'
11
+ gem 'daemons', '~> 1.2'
12
+ end
13
+
14
+ class Daemon
15
+ attr_reader :name, :command, :rundir, :monitor
16
+
17
+ def initialize
18
+ @name = File.basename($0)
19
+ @callsign = "ROCD#{rand(1000)}"
20
+ @filter = "r/44/4/20"
21
+ @outdir = "/tmp"
22
+ @rundir = '/var/run'
23
+ @gzip = true
24
+ @monitor = false
25
+ OptionParser.new do |o|
26
+ o.banner = <<~END
27
+ Log raw OGN APRS messages to daily files.
28
+ Usage: #{@name} [options] {start|stop|restart|run|status|zap}
29
+ END
30
+ o.on('-a', '--about', 'author and license information') { puts 'Written by Sven Schwyn (bitcetera.com) and distributed under MIT license.'; exit }
31
+ o.on('-c', '--callsign STRING', String, 'daemon callsign (default: ROCDnnnn)') { |v| @callsign = v }
32
+ o.on('-f', '--filter STRING', String, "APRS filter (default: #{@filter})") { |v| @filter = v }
33
+ o.on('-g', '--[no-]gzip', "gzip log files at midnight (default: #{@gzip})") { |v| @gzip = v }
34
+ o.on('-m', '--[no-]monitor', "automatically restart daemon after crash (default: #{@monitor})") { |v| @monitor = v }
35
+ o.on('-o', '--outdir DIR', String, "directory to write the files (default: #{@outdir})") { |v| @outdir = v }
36
+ o.on('-r', '--rundir DIR', String, "directory to write the PID file (default: #{@rundir})") { |v| @rundir = v }
37
+ end.parse!
38
+ @command = ARGV.pop&.to_sym
39
+ fail "command not recognized" unless %i(start stop restart run status zap).include? @command
40
+ end
41
+
42
+ def capture!
43
+ loop do
44
+ catch :cut do
45
+ `gzip "#{logfile}"` if @gzip && defined?(logfile)
46
+ logfile = "#{@outdir}/ogn.log-#{Time.now.strftime('%Y%m%d')}"
47
+ end_of_day = Time.parse("24:00").to_i
48
+ File.open(logfile, 'a') do |file|
49
+ file.sync = true
50
+ loop do
51
+ OGNClient::APRS.start(callsign: @callsign, filter: @filter) do |aprs|
52
+ while raw = aprs.gets
53
+ file.puts raw
54
+ throw :cut if end_of_day < Process.clock_gettime(Process::CLOCK_REALTIME, :second)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ begin
65
+ daemon = Daemon.new
66
+ Daemons.run_proc(
67
+ daemon.name,
68
+ multiple: false,
69
+ ARGV: [daemon.command.to_s],
70
+ dir_mode: :normal,
71
+ dir: daemon.rundir,
72
+ monitor: daemon.monitor,
73
+ monitor_interval: 60
74
+ ) do
75
+ daemon.capture!
76
+ end
77
+ rescue => exception
78
+ puts "#{File.basename($0)}: #{exception.message}"
79
+ exit 1
80
+ end
@@ -1,3 +1,3 @@
1
1
  module OGNClient
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.2.2".freeze
3
3
  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.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-19 00:00:00.000000000 Z
11
+ date: 2017-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -99,7 +99,9 @@ description: OGN (glidernet.org) broadcasts aircraft positions as APRS/APRS-IS m
99
99
  the raw message strings into meaningful objects.
100
100
  email:
101
101
  - ruby@bitcetera.com
102
- executables: []
102
+ executables:
103
+ - ogn2kml
104
+ - ognlogd
103
105
  extensions: []
104
106
  extra_rdoc_files: []
105
107
  files:
@@ -116,6 +118,8 @@ files:
116
118
  - Rakefile
117
119
  - bin/console
118
120
  - bin/setup
121
+ - exe/ogn2kml
122
+ - exe/ognlogd
119
123
  - lib/ogn_client.rb
120
124
  - lib/ogn_client/aprs.rb
121
125
  - lib/ogn_client/errors.rb