ruby-gps 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/gps.rb +2 -0
- data/lib/gps/device.rb +163 -0
- data/lib/gps/nmea.rb +12 -0
- data/lib/gps/nmea/gga.rb +34 -0
- data/lib/gps/nmea/gll.rb +22 -0
- data/lib/gps/nmea/gsa.rb +27 -0
- data/lib/gps/nmea/gsv.rb +26 -0
- data/lib/gps/nmea/has_datetime.rb +15 -0
- data/lib/gps/nmea/rmc.rb +36 -0
- data/lib/gps/nmea/sentence.rb +111 -0
- data/lib/gps/nmea/vtg.rb +22 -0
- data/lib/gps/nmea/zda.rb +28 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 16bbfb313f9945b300c9fd352de126e1ffe869d98ad3ae7aec7f2e196ec72e28
|
4
|
+
data.tar.gz: 8701cb221f89141aee9beea05f6c9d04860e628e97f35a314f1cd08731f71f1f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 786fd55095f2b19cc5aef507ae50de65022b6f9b70a475564702d25be4f67767cdbc1ed4a2fa40945b7b353d4a7705c27662a0bb268e32fc4d6a6a31ca86d200
|
7
|
+
data.tar.gz: 3ce9fc1152771455ff1f4531e949c23c7e1fa1ad03a08958ef652f69909e5917743f1ae0ce22be17663d4dfc551fc5c6612836513133fb28229288b9e99873da
|
data/lib/gps.rb
ADDED
data/lib/gps/device.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
module Gps
|
2
|
+
class Device
|
3
|
+
attr_accessor :last_datetime # Updates any time a sentence has a datetime
|
4
|
+
|
5
|
+
def initialize(filename, track_datetime=true)
|
6
|
+
@callbacks = {}
|
7
|
+
@track_datetime = track_datetime
|
8
|
+
@filename = filename
|
9
|
+
@file = File.open(filename, 'rb')
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.open(filename, &block)
|
13
|
+
device = Device.new filename
|
14
|
+
block.call device
|
15
|
+
device.close
|
16
|
+
end
|
17
|
+
|
18
|
+
def close
|
19
|
+
@file.close if @file
|
20
|
+
end
|
21
|
+
|
22
|
+
def each_line(&block)
|
23
|
+
@file.each_line do |line|
|
24
|
+
line.strip!
|
25
|
+
next if line.empty?
|
26
|
+
block.call line
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each_sentence(&block)
|
31
|
+
each_line do |line|
|
32
|
+
s = Nmea::Sentence.parse line
|
33
|
+
next if s.nil?
|
34
|
+
update_datetime s if @track_datetime
|
35
|
+
block.call s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def each_coordinates(&block)
|
40
|
+
each_sentence do |sentence|
|
41
|
+
block.call sentence.lat_long_dec if sentence.has_coordinates?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Rewind file if not a character device
|
46
|
+
def rewind
|
47
|
+
@file.rewind unless File.chardev?(@file.path)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Begin fetch process with callbacks
|
51
|
+
def start
|
52
|
+
@stopped = false
|
53
|
+
each_sentence do |sentence|
|
54
|
+
break if @stopped
|
55
|
+
|
56
|
+
if @callbacks[:coordinates] && sentence.has_coordinates?
|
57
|
+
@callbacks[:coordinates].each do |block|
|
58
|
+
block.call sentence.lat_long_dec
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
if @callbacks[:datetime] && sentence.has_datetime?
|
64
|
+
@callbacks[:datetime].each do |block|
|
65
|
+
block.call sentence.datetime
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if @callbacks[:speed_knots] && sentence.respond_to?(:speed_knots)
|
70
|
+
@callbacks[:speed_knots].each do |block|
|
71
|
+
block.call sentence.speed_knots if sentence.speed_knots
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if @callbacks[:speed_kmh] && sentence.respond_to?(:speed_kmh)
|
76
|
+
@callbacks[:speed_kmh].each do |block|
|
77
|
+
block.call sentence.speed_kmh if sentence.speed_kmh
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
if @callbacks[:altitude] && sentence.respond_to?(:altitude)
|
82
|
+
@callbacks[:altitude].each do |block|
|
83
|
+
block.call sentence.altitude if sentence.altitude
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
if @callbacks[:true_track] && sentence.respond_to?(:true_track)
|
88
|
+
@callbacks[:true_track].each do |block|
|
89
|
+
block.call sentence.true_track if sentence.true_track
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if @callbacks[:magnetic_track] && sentence.respond_to?(:magnetic_track)
|
94
|
+
@callbacks[:magnetic_track].each do |block|
|
95
|
+
block.call sentence.magnetic_track if sentence.magnetic_track
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
if @callbacks[:complete]
|
101
|
+
@callbacks[:complete].each(&:call)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def start_async
|
106
|
+
Thread.new(&method(:start))
|
107
|
+
end
|
108
|
+
|
109
|
+
def stop
|
110
|
+
@stopped = true
|
111
|
+
end
|
112
|
+
|
113
|
+
def on_coordinates(&block)
|
114
|
+
callbacks[:coordinates] ||= []
|
115
|
+
callbacks[:coordinates] << block
|
116
|
+
end
|
117
|
+
|
118
|
+
def on_datetime(&block)
|
119
|
+
callbacks[:datetime] ||= []
|
120
|
+
callbacks[:datetime] << block
|
121
|
+
end
|
122
|
+
|
123
|
+
def on_speed_knots(&block)
|
124
|
+
callbacks[:speed_knots] ||= []
|
125
|
+
callbacks[:speed_knots] << block
|
126
|
+
end
|
127
|
+
|
128
|
+
def on_speed_kmh(&block)
|
129
|
+
callbacks[:speed_kmh] ||= []
|
130
|
+
callbacks[:speed_kmh] << block
|
131
|
+
end
|
132
|
+
|
133
|
+
def on_altitude(&block)
|
134
|
+
callbacks[:altitude] ||= []
|
135
|
+
callbacks[:altitude] << block
|
136
|
+
end
|
137
|
+
|
138
|
+
def on_complete(&block)
|
139
|
+
callbacks[:complete] ||= []
|
140
|
+
callbacks[:complete] << block
|
141
|
+
end
|
142
|
+
|
143
|
+
def on_true_track(&block)
|
144
|
+
callbacks[:true_track] ||= []
|
145
|
+
callbacks[:true_track] << block
|
146
|
+
end
|
147
|
+
|
148
|
+
def on_magnetic_track(&block)
|
149
|
+
callbacks[:magnetic_track] ||= []
|
150
|
+
callbacks[:magnetic_track] << block
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
attr_reader :callbacks
|
156
|
+
|
157
|
+
def update_datetime(sentence)
|
158
|
+
if sentence.respond_to? :datetime
|
159
|
+
@last_datetime = sentence.datetime
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/lib/gps/nmea.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
require_relative 'nmea/sentence'
|
4
|
+
require_relative 'nmea/gga'
|
5
|
+
require_relative 'nmea/gll'
|
6
|
+
require_relative 'nmea/gsv'
|
7
|
+
require_relative 'nmea/gsa'
|
8
|
+
require_relative 'nmea/vtg'
|
9
|
+
require_relative 'nmea/rmc'
|
10
|
+
require_relative 'nmea/zda'
|
11
|
+
end
|
12
|
+
end
|
data/lib/gps/nmea/gga.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Gps
|
4
|
+
module Nmea
|
5
|
+
class Gga < Sentence
|
6
|
+
attr_accessor :time, :time_str, :latitude, :latitude_direction, :longitude,
|
7
|
+
:longitude_direction, :fix_quality, :num_satellites, :hdop,
|
8
|
+
:altitude, :altitude_unit, :age_of_diff
|
9
|
+
|
10
|
+
def initialize(line)
|
11
|
+
@line = line
|
12
|
+
fill_parts
|
13
|
+
fill_data
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def fill_data
|
19
|
+
@time_str = Sentence.time_part_to_str @parts[0]
|
20
|
+
@time = Time.parse time_str
|
21
|
+
@latitude = @parts[1].to_f
|
22
|
+
@latitude_direction = @parts[2]
|
23
|
+
@longitude = @parts[3].to_f
|
24
|
+
@longitude_direction = @parts[4]
|
25
|
+
@fix_quality = @parts[5].to_i
|
26
|
+
@num_satellites = @parts[6].to_i
|
27
|
+
@hdop = @parts[7].to_f
|
28
|
+
@altitude = @parts[8].to_f
|
29
|
+
@altitude_unit = @parts[9]
|
30
|
+
@age_of_diff = @parts[10].to_f
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/gps/nmea/gll.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
class Gll < Sentence
|
4
|
+
attr_accessor :latitude, :latitude_direction, :longitude, :longitude_direction
|
5
|
+
|
6
|
+
def initialize(line)
|
7
|
+
@line = line
|
8
|
+
fill_parts
|
9
|
+
fill_data
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def fill_data
|
15
|
+
@latitude = @parts[0].to_f
|
16
|
+
@latitude_direction = @parts[1]
|
17
|
+
@longitude = @parts[2].to_f
|
18
|
+
@longitude_direction = @parts[3]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/gps/nmea/gsa.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
class Gsa < Sentence
|
4
|
+
attr_accessor :forced, :mode, :sv_id, :pdop, :hdop, :vdop
|
5
|
+
|
6
|
+
def initialize(line)
|
7
|
+
@line = line
|
8
|
+
fill_parts
|
9
|
+
fill_data
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def fill_data
|
15
|
+
@forced = @parts[0] == 'M'
|
16
|
+
@mode = @parts[1].to_i
|
17
|
+
@sv_id = 0
|
18
|
+
(2..13).each do |i|
|
19
|
+
@sv_id += ((12 - i) * 100) * @parts[i].to_i
|
20
|
+
end
|
21
|
+
@pdop = @parts[14].to_f
|
22
|
+
@hdop = @parts[15].to_f
|
23
|
+
@vdop = @parts[16].to_f
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/gps/nmea/gsv.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
class Gsv < Sentence
|
4
|
+
attr_accessor :num_messages, :message_num, :total_svs, :sv_prn,
|
5
|
+
:elevation, :azimuth, :snr
|
6
|
+
|
7
|
+
def initialize(line)
|
8
|
+
@line = line
|
9
|
+
fill_parts
|
10
|
+
fill_data
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def fill_data
|
16
|
+
@num_messages = @parts[0].to_i
|
17
|
+
@message_num = @parts[1].to_i
|
18
|
+
@total_svs = @parts[2].to_i
|
19
|
+
@sv_prn = @parts[3].to_i
|
20
|
+
@elevation = @parts[4].to_i
|
21
|
+
@azimuth = @parts[5].to_i
|
22
|
+
@snr = @parts[6].to_i
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Gps
|
4
|
+
module Nmea
|
5
|
+
module HasDatetime
|
6
|
+
attr_accessor :date_str, :time_str, :datetime
|
7
|
+
|
8
|
+
def update_datetime
|
9
|
+
if @date_str && @time_str
|
10
|
+
@datetime = DateTime.iso8601 "#{@date_str}T#{@time_str}Z"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/gps/nmea/rmc.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'has_datetime'
|
2
|
+
|
3
|
+
module Gps
|
4
|
+
module Nmea
|
5
|
+
class Rmc < Sentence
|
6
|
+
include HasDatetime
|
7
|
+
|
8
|
+
attr_accessor :data_status, :latitude, :latitude_direction,
|
9
|
+
:longitude, :longitude_direction, :speed_knots, :true_track,
|
10
|
+
:variation, :variation_direction
|
11
|
+
|
12
|
+
def initialize(line)
|
13
|
+
@line = line
|
14
|
+
fill_parts
|
15
|
+
fill_data
|
16
|
+
update_datetime
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def fill_data
|
22
|
+
@time_str = Sentence.time_part_to_str @parts[0]
|
23
|
+
@data_status = @parts[1]
|
24
|
+
@latitude = @parts[2]
|
25
|
+
@latitude_direction = @parts[3]
|
26
|
+
@longitude = @parts[4]
|
27
|
+
@longitude_direction = @parts[5]
|
28
|
+
@speed_knots = @parts[6]
|
29
|
+
@true_track = @parts[7]
|
30
|
+
@date_str = Sentence.date_part_to_str @parts[8]
|
31
|
+
@variation = @parts[9]
|
32
|
+
@variation_direction = @parts[10]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
class Sentence
|
4
|
+
attr_accessor :line
|
5
|
+
|
6
|
+
def self.parse(line)
|
7
|
+
case
|
8
|
+
when line.start_with?('$GPGGA')
|
9
|
+
Gga.new line
|
10
|
+
when line.start_with?('$GPGLL')
|
11
|
+
Gll.new line
|
12
|
+
when line.start_with?('$GPGSV')
|
13
|
+
Gsv.new line
|
14
|
+
when line.start_with?('$GPGSA')
|
15
|
+
Gsa.new line
|
16
|
+
when line.start_with?('$GPVTG')
|
17
|
+
Vtg.new line
|
18
|
+
when line.start_with?('$GPRMC')
|
19
|
+
Rmc.new line
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.time_part_to_str(time_part)
|
26
|
+
"#{time_part[0..1]}:#{time_part[2..3]}:#{time_part[4..5]}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.date_part_to_str(date_part)
|
30
|
+
century = date_part[4..5].to_i > 70 ? 1900 : 2000
|
31
|
+
"#{century + date_part[4..5].to_i}-#{date_part[2..3]}-#{date_part[0..1]}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def checksum_valid?
|
35
|
+
get_checksum == generate_checksum
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_checksum
|
39
|
+
line.split(',')[-1].split('*')[1].to_i 16
|
40
|
+
end
|
41
|
+
|
42
|
+
def generate_checksum
|
43
|
+
data = line.gsub('$', '').split('*')[0]
|
44
|
+
res = 0
|
45
|
+
data.split('').each do |c|
|
46
|
+
res ^= c.ord
|
47
|
+
end
|
48
|
+
res
|
49
|
+
end
|
50
|
+
|
51
|
+
def lat_dec
|
52
|
+
return nil if @latitude.nil?
|
53
|
+
return nil if @latitude_direction.nil?
|
54
|
+
|
55
|
+
lat, lat_dec = @latitude.to_s.split '.'
|
56
|
+
lat = lat.rjust 4, '0'
|
57
|
+
res = lat[0..1].to_i + ("#{lat[2..3]}.#{lat_dec}".to_f / 60.0)
|
58
|
+
res *= -1 if @latitude_direction == 'S'
|
59
|
+
res
|
60
|
+
end
|
61
|
+
|
62
|
+
def long_dec
|
63
|
+
return nil if @longitude.nil?
|
64
|
+
return nil if @longitude_direction.nil?
|
65
|
+
|
66
|
+
long, long_dec = @longitude.to_s.split '.'
|
67
|
+
long = long.rjust 5, '0'
|
68
|
+
res = long[0..2].to_i + ("#{long[3..4]}.#{long_dec}".to_f / 60.0)
|
69
|
+
res *= -1 if @longitude_direction == 'W'
|
70
|
+
res
|
71
|
+
end
|
72
|
+
|
73
|
+
def lat_long_dec
|
74
|
+
return nil unless has_coordinates?
|
75
|
+
"#{lat_dec} #{long_dec}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_h
|
79
|
+
self.class.instance_methods(false)
|
80
|
+
.reject { |a| a.to_s.end_with? '=' }
|
81
|
+
.map { |a| [a.to_s, self.send(a)] }
|
82
|
+
.to_h.merge({ type: self.class.to_s.split('::').last.upcase })
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_json(pretty=false)
|
86
|
+
require 'json'
|
87
|
+
if pretty
|
88
|
+
JSON.pretty_generate to_h
|
89
|
+
else
|
90
|
+
to_h.to_json
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def has_coordinates?
|
95
|
+
!(@latitude.nil? || @longitude.nil? ||
|
96
|
+
@latitude_direction.nil? || @longitude_direction.nil?)
|
97
|
+
end
|
98
|
+
|
99
|
+
def has_datetime?
|
100
|
+
respond_to? :datetime
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def fill_parts
|
106
|
+
@parts = @line.split(',')[1..]
|
107
|
+
@parts[-1].gsub! /\*.+$/, ''
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/gps/nmea/vtg.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
class Vtg < Sentence
|
4
|
+
attr_accessor :true_track, :magnetic_track, :speed_knots, :speed_kmh
|
5
|
+
|
6
|
+
def initialize(line)
|
7
|
+
@line = line
|
8
|
+
fill_parts
|
9
|
+
fill_data
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def fill_data
|
15
|
+
@true_track = @parts[0].to_f
|
16
|
+
@magnetic_track = @parts[2].to_f
|
17
|
+
@speed_knots = @parts[4].to_f
|
18
|
+
@speed_kmh = @parts[6].to_f
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/gps/nmea/zda.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Gps
|
2
|
+
module Nmea
|
3
|
+
class Zda < Sentence
|
4
|
+
attr_accessor :hour, :minute, :second, :day, :month, :year,
|
5
|
+
:local_zone_desc, :local_zone_minutes
|
6
|
+
|
7
|
+
def initialize(line)
|
8
|
+
@line = line
|
9
|
+
fill_parts
|
10
|
+
fill_data
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def fill_data
|
16
|
+
hms = @parts[0]
|
17
|
+
@hour = hms[0..1].to_i
|
18
|
+
@minute = hms[2..3].to_i
|
19
|
+
@second = hms[4..5].to_i
|
20
|
+
@day = @parts[1].to_i
|
21
|
+
@month = @parts[2].to_i
|
22
|
+
@year = @parts[3].to_i
|
23
|
+
@local_zone_desc = @parts[4].to_i
|
24
|
+
@local_zone_minutes = @parts[5].to_i
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-gps
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nikola Miljkovic
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-16 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: nikomil@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/gps.rb
|
20
|
+
- lib/gps/device.rb
|
21
|
+
- lib/gps/nmea.rb
|
22
|
+
- lib/gps/nmea/gga.rb
|
23
|
+
- lib/gps/nmea/gll.rb
|
24
|
+
- lib/gps/nmea/gsa.rb
|
25
|
+
- lib/gps/nmea/gsv.rb
|
26
|
+
- lib/gps/nmea/has_datetime.rb
|
27
|
+
- lib/gps/nmea/rmc.rb
|
28
|
+
- lib/gps/nmea/sentence.rb
|
29
|
+
- lib/gps/nmea/vtg.rb
|
30
|
+
- lib/gps/nmea/zda.rb
|
31
|
+
homepage:
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.0.1
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: GPS utilities for Ruby
|
54
|
+
test_files: []
|