pr2gpx 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -4
- data/lib/pr2gpx.rb +13 -6
- data/lib/pr2gpx/options.rb +6 -6
- data/lib/pr2gpx/parser.rb +31 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -1,18 +1,22 @@
|
|
1
1
|
pr2gpx
|
2
2
|
======
|
3
3
|
|
4
|
-
Converts Winlink position reports
|
4
|
+
Converts Winlink position reports into GPX tracks or waypoints.
|
5
5
|
|
6
|
-
|
6
|
+
pr2gpx understands position report data downloaded as RSS documents from the [Winlink 2000](http://www.winlink.org/) website using this Url:
|
7
|
+
|
8
|
+
http://www.winlink.org/dotnet/maps/RSSPositionReports.aspx?callsign=[callsign]
|
9
|
+
|
10
|
+
It also understands the information contained in messages sent or received with the [AirMail](http://siriuscyber.net/airmail/) client program:
|
7
11
|
- sent position reports (Window->Winlink-2000->Position Report)
|
8
12
|
- reports requested for specific stations (Window->Winlink-2000->Position Request)
|
9
13
|
- lists of nearby stations (Window->Catalogs->WL2K->Global->WL2K_USERS->WL2K_NEARBY)
|
10
14
|
|
11
|
-
pr2gpx
|
15
|
+
pr2gpx can either be given one file to parse, or it can scan all files in a directory. It can filter the data to include only stations with a given callsign, and limit the results to the last N reports per station.
|
12
16
|
|
13
17
|
The output is either one track for each station, a list of waypoints for every position report, or both.
|
14
18
|
|
15
|
-
|
19
|
+
The results can either be saved into a single file containing everything, or it can be split into one file for each station.
|
16
20
|
|
17
21
|
|
18
22
|
Installing
|
data/lib/pr2gpx.rb
CHANGED
@@ -9,9 +9,11 @@ def enumerate_files search_path
|
|
9
9
|
Dir
|
10
10
|
.glob(search_path)
|
11
11
|
.each do |filename|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
if File.file?(filename)
|
13
|
+
$stderr.puts "Reading #{filename}" if $verbose
|
14
|
+
File.open filename do |file|
|
15
|
+
e.yield file.read()
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -77,11 +79,16 @@ end
|
|
77
79
|
options[:input].gsub!('\\', '/')
|
78
80
|
options[:output].gsub!('\\', '/') if options[:output]
|
79
81
|
|
80
|
-
search_path = "#{options[:input]}/#{options[:recurse] ? '**/' : ''}*.*"
|
81
|
-
$stderr.puts "Searching #{search_path}" if $verbose
|
82
|
-
|
83
82
|
filter = ReportFilter.new options[:callsign]
|
84
83
|
|
84
|
+
search_path = if File.directory?(options[:input])
|
85
|
+
"#{options[:input]}/#{options[:recurse] ? '**/' : ''}*.*"
|
86
|
+
else
|
87
|
+
options[:input]
|
88
|
+
end
|
89
|
+
|
90
|
+
$stderr.puts "Searching #{search_path}" if $verbose
|
91
|
+
|
85
92
|
stations = load_data(enumerate_files(search_path), filter)
|
86
93
|
filter_data! stations, options[:last]
|
87
94
|
|
data/lib/pr2gpx/options.rb
CHANGED
@@ -104,8 +104,6 @@ def validate_options options
|
|
104
104
|
|
105
105
|
if not File.exists?(options[:input])
|
106
106
|
errors << 'Path specified in --input does not exist.'
|
107
|
-
elsif not File.directory?(options[:input])
|
108
|
-
errors << 'Path specified in --input is not a directory.'
|
109
107
|
end
|
110
108
|
|
111
109
|
if options[:split]
|
@@ -115,10 +113,12 @@ def validate_options options
|
|
115
113
|
errors << 'Path specified in --output is not a directory.'
|
116
114
|
end
|
117
115
|
else
|
118
|
-
if
|
119
|
-
|
120
|
-
|
121
|
-
|
116
|
+
if options[:output]
|
117
|
+
if not File.exists?(File.dirname(options[:output]))
|
118
|
+
errors << 'Path specified in --output does not exist.'
|
119
|
+
elsif File.directory?(options[:output])
|
120
|
+
errors << 'Path specified in --output is a directory.'
|
121
|
+
end
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
data/lib/pr2gpx/parser.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'date'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'nokogiri/xml'
|
2
4
|
|
3
5
|
PositionReport = Struct.new "PositionReport", :callsign, :date, :position, :comment
|
4
6
|
|
@@ -24,7 +26,7 @@ end
|
|
24
26
|
|
25
27
|
class ReportParser
|
26
28
|
def initialize
|
27
|
-
@parsers = [NearbyStationsParser.new, ReportsListParser.new, OutboundReportParser.new]
|
29
|
+
@parsers = [NearbyStationsParser.new, ReportsListParser.new, OutboundReportParser.new, RSSParser.new]
|
28
30
|
end
|
29
31
|
|
30
32
|
def parse input
|
@@ -108,6 +110,34 @@ class NearbyStationsParser
|
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
113
|
+
class RSSParser
|
114
|
+
def can_parse? input
|
115
|
+
/<rss version="2\.0">/ =~ input
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse input
|
119
|
+
Enumerator.new do |e|
|
120
|
+
xml = Nokogiri::XML(input)
|
121
|
+
xml.xpath('//item').each do |item|
|
122
|
+
%r{^
|
123
|
+
Position[ ]report[ ]for[ ]
|
124
|
+
(?<callsign>[^ ]*)
|
125
|
+
[ ]is[ ]
|
126
|
+
(?<latitude>[^ ]*)
|
127
|
+
[ ]/[ ]
|
128
|
+
(?<longitude>[^ ]*)
|
129
|
+
}x =~ item.xpath('title').first.content
|
130
|
+
comment = item.xpath('description').first.content
|
131
|
+
date = DateTime.parse(item.xpath('pubDate').first.content)
|
132
|
+
e.yield PositionReport.new callsign,
|
133
|
+
date,
|
134
|
+
Position.new(latitude, longitude),
|
135
|
+
comment
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
111
141
|
class ReportFilter
|
112
142
|
def initialize callsigns
|
113
143
|
@callsigns = callsigns
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pr2gpx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|