nmea_gps 0.0.1
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 +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/Guardfile +18 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +7 -0
- data/lib/nmea_gps/config.rb +11 -0
- data/lib/nmea_gps/gps.rb +82 -0
- data/lib/nmea_gps/sentence_base.rb +37 -0
- data/lib/nmea_gps/sentences/gga.rb +70 -0
- data/lib/nmea_gps/sentences/gll.rb +34 -0
- data/lib/nmea_gps/sentences/gsa.rb +57 -0
- data/lib/nmea_gps/sentences/gsv.rb +34 -0
- data/lib/nmea_gps/sentences/rmc.rb +65 -0
- data/lib/nmea_gps/sentences/vtg.rb +27 -0
- data/lib/nmea_gps/sentences/zda.rb +31 -0
- data/lib/nmea_gps/version.rb +3 -0
- data/lib/nmea_gps.rb +40 -0
- data/nmea_gps.gemspec +29 -0
- data/spec/ddd_formatable_spec.rb +18 -0
- data/spec/lib/gps_spec.rb +97 -0
- data/spec/lib/nmea_gps/gps_spec.rb +138 -0
- data/spec/lib/nmea_gps/sentence_base_spec.rb +25 -0
- data/spec/lib/nmea_gps/sentences/gga_spec.rb +59 -0
- data/spec/lib/nmea_gps/sentences/gll_spec.rb +37 -0
- data/spec/lib/nmea_gps/sentences/gsa_spec.rb +44 -0
- data/spec/lib/nmea_gps/sentences/gsv_spec.rb +36 -0
- data/spec/lib/nmea_gps/sentences/rmc_spec.rb +62 -0
- data/spec/lib/nmea_gps/sentences/vtg_spec.rb +28 -0
- data/spec/lib/nmea_gps/sentences/zda_spec.rb +32 -0
- data/spec/nmea_gps_spec.rb +8 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/utc_timeable_spec.rb +32 -0
- metadata +205 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa3fef3d96dff44cb620276abc67d7e7eab832f0
|
4
|
+
data.tar.gz: c5ed23427e8805430ce9392035a149f8d1c74f3e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40adfabfbbfcf6167565709b84634dfb3c8d0cffcd82bbe9f9a00b3b557df3016aed4064639259deef1864dafd206a3ad6208d8cbee616fbff9c2ab52e9272df
|
7
|
+
data.tar.gz: 29ddd56de23382fd20364a607b234efa347ae430ab1e6b515411ec00cdffb869965d5ed6811110f7e308287197426c0333bc48d546b42772fb4b2780f24fd708
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
5
|
+
# rspec may be run, below are examples of the most common uses.
|
6
|
+
# * bundler: 'bundle exec rspec'
|
7
|
+
# * bundler binstubs: 'bin/rspec'
|
8
|
+
# * spring: 'bin/rsspec' (This will use spring if running and you have
|
9
|
+
# installed the spring binstubs per the docs)
|
10
|
+
# * zeus: 'zeus rspec' (requires the server to be started separetly)
|
11
|
+
# * 'just' rspec: 'rspec'
|
12
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
13
|
+
watch(%r{^spec/.+_spec\.rb$})
|
14
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec" }
|
16
|
+
|
17
|
+
end
|
18
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 ore
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
## Installation
|
2
|
+
|
3
|
+
Add this line to your application's Gemfile:
|
4
|
+
|
5
|
+
gem 'nmea_gps'
|
6
|
+
|
7
|
+
And then execute:
|
8
|
+
|
9
|
+
$ bundle
|
10
|
+
|
11
|
+
Or install it yourself as:
|
12
|
+
|
13
|
+
$ gem install nmea_gps
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
|
19
|
+
# create a serialport to your GPS receiver
|
20
|
+
# you should know how to open a connection between your GPS device
|
21
|
+
# mine runs on `9600 baudrate`, `8bit`, `1stop bit`, `none parity`
|
22
|
+
serialport = SerialPort.new("/dev/cu.your_whatever_device", 9600, 8, 1, SerialPort::NONE)
|
23
|
+
|
24
|
+
# you should know about your GPS receiver's update Hz(how often it will update logs 10Hz = 10 times per sec.)
|
25
|
+
# if you don't know leave it blank. It will at least update every sec.
|
26
|
+
gps = Nmea::Gps.new serialport update_hz: 10
|
27
|
+
|
28
|
+
# this will be called automatically!!
|
29
|
+
gps.rmc do |rmc|
|
30
|
+
p rmc.time
|
31
|
+
p rmc.latitude
|
32
|
+
p rmc.longitude
|
33
|
+
p rmc.heading
|
34
|
+
p rmc.date
|
35
|
+
end
|
36
|
+
|
37
|
+
# start the tracking
|
38
|
+
gps.track!
|
39
|
+
|
40
|
+
# you can also have
|
41
|
+
# gps.gga do |gga|
|
42
|
+
# ..
|
43
|
+
# end
|
44
|
+
# gps.gll do |gll|
|
45
|
+
# ..
|
46
|
+
# end
|
47
|
+
# gps.gsa do |gsa|
|
48
|
+
# ..
|
49
|
+
# end
|
50
|
+
# gps.vtg do |vtg|
|
51
|
+
# ..
|
52
|
+
# end
|
53
|
+
# gps.zda do |zda|
|
54
|
+
# ..
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# this one gets multiple Gsv objects
|
58
|
+
# gps.gsv do |gsvs|
|
59
|
+
# p gsvs.count
|
60
|
+
# ..
|
61
|
+
# end
|
62
|
+
|
63
|
+
# do your other works
|
64
|
+
# ..
|
65
|
+
# ..
|
66
|
+
# ..
|
67
|
+
|
68
|
+
# when you want to stop callbacks, you can call this
|
69
|
+
# gps.stop!
|
70
|
+
# then close the connection
|
71
|
+
# serialport.close
|
72
|
+
```
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
1. Fork it ( https://github.com/[my-github-username]/nmea_gps/fork )
|
77
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
78
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
79
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
80
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/nmea_gps/gps.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module Nmea
|
2
|
+
|
3
|
+
class Gps
|
4
|
+
TALKER_ID = "GP"
|
5
|
+
|
6
|
+
def initialize(serial_port, update_hz: 1)
|
7
|
+
self.callbacks = {}
|
8
|
+
self.gps_serial_port = serial_port
|
9
|
+
self.update_hz = 1.second.to_f / update_hz.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
Dir[Pathname(__FILE__).join("../sentences/*.rb")].collect do |path|
|
13
|
+
Pathname(path).basename(".rb").to_s
|
14
|
+
end.each do |sentence|
|
15
|
+
define_method(sentence) do |&block|
|
16
|
+
self.callbacks[__callee__] = block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def track!
|
21
|
+
self.track_thread = Thread.new do
|
22
|
+
loop do
|
23
|
+
callback!
|
24
|
+
frequency
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop!
|
30
|
+
self.track_thread.kill if self.track_thread.respond_to? :kill
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
attr_accessor :gps_serial_port, :update_hz, :callbacks, :track_thread
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def hz
|
39
|
+
self.update_hz
|
40
|
+
end
|
41
|
+
|
42
|
+
def frequency
|
43
|
+
sleep hz
|
44
|
+
end
|
45
|
+
|
46
|
+
def line_set
|
47
|
+
Hash.new{|hash, key| hash[key] = [] }.tap do |set|
|
48
|
+
loop do
|
49
|
+
line = self.gps_serial_port.gets("\r\n").strip
|
50
|
+
# %w[ GLL RMC VTG GGA GSA GSV ZDA].join.chars.uniq.sort.join
|
51
|
+
return unless match = line.match(/\A\$#{TALKER_ID}([ACDGLMRSTVZ]{3})/)
|
52
|
+
|
53
|
+
sentence = match[1].downcase.to_sym
|
54
|
+
set[sentence] << line
|
55
|
+
break if sentence == :gga
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def callback!
|
61
|
+
this_set = line_set
|
62
|
+
this_set.keys.each do |sentence|
|
63
|
+
this_callback = self.callbacks[sentence]
|
64
|
+
next unless this_callback
|
65
|
+
|
66
|
+
target_class = "Nmea::Gps::#{sentence.to_s.camelcase}".constantize
|
67
|
+
|
68
|
+
object = if sentence == :gsv
|
69
|
+
this_set[sentence].sort.collect do |line|
|
70
|
+
target_class.new line
|
71
|
+
end
|
72
|
+
else
|
73
|
+
target_class.new(this_set[sentence].first)
|
74
|
+
end
|
75
|
+
|
76
|
+
this_callback.call object
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class SentenceBase
|
5
|
+
|
6
|
+
STATUSES = {
|
7
|
+
"A" => :valid,
|
8
|
+
"V" => :invalid,
|
9
|
+
}
|
10
|
+
|
11
|
+
MODES = {
|
12
|
+
"A" => :autonomous,
|
13
|
+
"N" => :no_fix,
|
14
|
+
"D" => :dgps,
|
15
|
+
"E" => :dr,
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(line)
|
20
|
+
@line = line
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
raise "override this method"
|
25
|
+
end
|
26
|
+
|
27
|
+
def raw_data
|
28
|
+
_, *data = self.line.split("*").first.split(",")
|
29
|
+
data
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
attr_reader :line
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Gga < SentenceBase
|
5
|
+
include Nmea::UtcTimeable, Nmea::DddFormatable
|
6
|
+
|
7
|
+
QUALITIES = {
|
8
|
+
0 => :invalid,
|
9
|
+
1 => :gps_sps_fix,
|
10
|
+
2 => :dgps_fix,
|
11
|
+
3 => :gps_pps_fix,
|
12
|
+
}
|
13
|
+
|
14
|
+
def name
|
15
|
+
"Global positioning system fixed data"
|
16
|
+
end
|
17
|
+
|
18
|
+
def time
|
19
|
+
hhmmss_to_local_time raw_data[0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def latitude
|
23
|
+
dmm_to_ddd raw_data[1], raw_data[2]
|
24
|
+
end
|
25
|
+
|
26
|
+
def longitude
|
27
|
+
dmm_to_ddd raw_data[3], raw_data[4]
|
28
|
+
end
|
29
|
+
|
30
|
+
def quality
|
31
|
+
QUALITIES[raw_data[5].to_i]
|
32
|
+
end
|
33
|
+
|
34
|
+
def number_of_satellites
|
35
|
+
raw_data[6].to_i
|
36
|
+
end
|
37
|
+
alias :satellites :number_of_satellites
|
38
|
+
|
39
|
+
# http://en.wikipedia.org/wiki/Dilution_of_precision_%28GPS%29
|
40
|
+
def horizontal_dilution_of_precision
|
41
|
+
raw_data[7].to_f
|
42
|
+
end
|
43
|
+
alias :hdop :horizontal_dilution_of_precision
|
44
|
+
|
45
|
+
def altitude_in_meters
|
46
|
+
raw_data[8].to_f
|
47
|
+
end
|
48
|
+
alias :altitude :altitude_in_meters
|
49
|
+
|
50
|
+
def height_of_geoid_above_wgs84_ellipsoid
|
51
|
+
raw_data[10].to_f
|
52
|
+
end
|
53
|
+
alias :height_of_geoid :height_of_geoid_above_wgs84_ellipsoid
|
54
|
+
|
55
|
+
def time_in_seconds_since_last_dgps_update
|
56
|
+
raw_data[12].to_i
|
57
|
+
end
|
58
|
+
alias :last_dgps_update :time_in_seconds_since_last_dgps_update
|
59
|
+
|
60
|
+
def dgps_station_id
|
61
|
+
raw_data[13].to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
def checksum
|
65
|
+
raw_data[14].to_s
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Gll < SentenceBase
|
5
|
+
include Nmea::UtcTimeable, Nmea::DddFormatable
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Geographic position—latitude/longitude"
|
9
|
+
end
|
10
|
+
|
11
|
+
def latitude
|
12
|
+
dmm_to_ddd raw_data[0], raw_data[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
def longitude
|
16
|
+
dmm_to_ddd raw_data[2], raw_data[3]
|
17
|
+
end
|
18
|
+
|
19
|
+
def time
|
20
|
+
hhmmss_to_local_time raw_data[4]
|
21
|
+
end
|
22
|
+
|
23
|
+
def status
|
24
|
+
STATUSES[raw_data[5]]
|
25
|
+
end
|
26
|
+
|
27
|
+
def mode
|
28
|
+
MODES[raw_data[6]]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Gsa < SentenceBase
|
5
|
+
|
6
|
+
MODE_SELECTIONS = {
|
7
|
+
"M" => :manual,
|
8
|
+
"A" => :automatic,
|
9
|
+
}
|
10
|
+
|
11
|
+
MODES = {
|
12
|
+
"1" => :fix_not_available,
|
13
|
+
"2" => :fix_2D,
|
14
|
+
"3" => :fix_3D,
|
15
|
+
}
|
16
|
+
|
17
|
+
def name
|
18
|
+
"GNSS DOP and active satellites"
|
19
|
+
end
|
20
|
+
|
21
|
+
def mode_selection
|
22
|
+
MODE_SELECTIONS[raw_data[0]]
|
23
|
+
end
|
24
|
+
|
25
|
+
def mode
|
26
|
+
MODES[raw_data[1]]
|
27
|
+
end
|
28
|
+
|
29
|
+
def ids_of_svs_used_in_position_fix(at = :all)
|
30
|
+
ids = raw_data[2..13]
|
31
|
+
return ids if at == :all
|
32
|
+
|
33
|
+
id = ids[at.to_i - 1]
|
34
|
+
return nil if id.blank?
|
35
|
+
|
36
|
+
id.to_i
|
37
|
+
end
|
38
|
+
alias :svs_ids :ids_of_svs_used_in_position_fix
|
39
|
+
|
40
|
+
def position_dilution_of_precision
|
41
|
+
raw_data[14].to_f
|
42
|
+
end
|
43
|
+
alias :pdop :position_dilution_of_precision
|
44
|
+
|
45
|
+
def horizontal_dilution_of_precision
|
46
|
+
raw_data[15].to_f
|
47
|
+
end
|
48
|
+
alias :hdop :horizontal_dilution_of_precision
|
49
|
+
|
50
|
+
def vertical_dilution_of_precision
|
51
|
+
raw_data[16].to_f
|
52
|
+
end
|
53
|
+
alias :vdop :vertical_dilution_of_precision
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Gsv < SentenceBase
|
5
|
+
def name
|
6
|
+
"GNSS satellites in view"
|
7
|
+
end
|
8
|
+
|
9
|
+
def number_of_message
|
10
|
+
raw_data[0].to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def message_number
|
14
|
+
raw_data[1].to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def number_of_satellites_in_view
|
18
|
+
raw_data[2].to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def satellites
|
22
|
+
raw_data[3..-1].each_slice(4).collect do |slice|
|
23
|
+
OpenStruct.new.tap do |satellite|
|
24
|
+
satellite.id = slice.first.to_i
|
25
|
+
satellite.elevation = slice[1].to_i
|
26
|
+
satellite.azinmuth = slice[2].to_i
|
27
|
+
satellite.signal_to_noise_ratio = satellite.snr = slice.last.to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Rmc < SentenceBase
|
5
|
+
include Nmea::UtcTimeable, Nmea::DddFormatable
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Recommended minimum specific GNSS data"
|
9
|
+
end
|
10
|
+
|
11
|
+
def time
|
12
|
+
hhmmss_to_local_time raw_data[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def status
|
16
|
+
STATUSES[raw_data[1]]
|
17
|
+
end
|
18
|
+
|
19
|
+
def latitude
|
20
|
+
dmm_to_ddd raw_data[2], raw_data[3]
|
21
|
+
end
|
22
|
+
|
23
|
+
def longitude
|
24
|
+
dmm_to_ddd raw_data[4], raw_data[5]
|
25
|
+
end
|
26
|
+
|
27
|
+
def knot_per_hour
|
28
|
+
raw_data[6].to_f
|
29
|
+
end
|
30
|
+
|
31
|
+
def km_per_hour
|
32
|
+
knot_per_hour * 1.85200
|
33
|
+
end
|
34
|
+
|
35
|
+
def mile_per_hour
|
36
|
+
knot_per_hour * 1.15077945
|
37
|
+
end
|
38
|
+
|
39
|
+
def heading
|
40
|
+
raw_data[7].to_f
|
41
|
+
end
|
42
|
+
|
43
|
+
def date
|
44
|
+
_, day, month, year = raw_data[8].match(/(\d{2})(\d{2})(\d{2})/).to_a
|
45
|
+
Date.parse("#{year}/#{month}/#{day}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def magnetic_variation
|
49
|
+
return nil if raw_data[9].blank?
|
50
|
+
raw_data[9].to_f
|
51
|
+
end
|
52
|
+
|
53
|
+
def magnetic_variation_direction
|
54
|
+
return nil if raw_data[10].blank?
|
55
|
+
raw_data[10].to_f
|
56
|
+
end
|
57
|
+
|
58
|
+
def mode
|
59
|
+
MODES[raw_data[11]]
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Vtg < SentenceBase
|
5
|
+
def name
|
6
|
+
"Course over ground and ground speed"
|
7
|
+
end
|
8
|
+
|
9
|
+
def true_course
|
10
|
+
raw_data[0].to_f
|
11
|
+
end
|
12
|
+
|
13
|
+
def magnetic_course
|
14
|
+
return if raw_data[2].blank?
|
15
|
+
raw_data[2].to_f
|
16
|
+
end
|
17
|
+
|
18
|
+
def knot_per_hour
|
19
|
+
raw_data[4].to_f
|
20
|
+
end
|
21
|
+
|
22
|
+
def km_per_hour
|
23
|
+
raw_data[6].to_f
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Nmea
|
2
|
+
class Gps
|
3
|
+
|
4
|
+
class Zda < SentenceBase
|
5
|
+
include Nmea::UtcTimeable
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Date and Time"
|
9
|
+
end
|
10
|
+
|
11
|
+
def time
|
12
|
+
hhmmss_to_local_time raw_data[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def date
|
16
|
+
Date.parse("#{raw_data[3]}/#{raw_data[2]}/#{raw_data[1]}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def local_zone_hours
|
20
|
+
return if raw_data[4].blank?
|
21
|
+
raw_data[4].to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def local_zone_minutes
|
25
|
+
return if raw_data[5].blank?
|
26
|
+
raw_data[5].to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/nmea_gps.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "serialport"
|
3
|
+
require "ostruct"
|
4
|
+
|
5
|
+
require 'active_support'
|
6
|
+
require 'active_support/core_ext'
|
7
|
+
Time.zone = "UTC"
|
8
|
+
|
9
|
+
require "nmea_gps/version"
|
10
|
+
require "nmea_gps/config"
|
11
|
+
require "nmea_gps/gps"
|
12
|
+
|
13
|
+
require "nmea_gps/sentence_base"
|
14
|
+
Dir[Pathname(__FILE__).join("../sentences/*.rb")].each {|file| require file }
|
15
|
+
|
16
|
+
module Nmea
|
17
|
+
|
18
|
+
module UtcTimeable
|
19
|
+
protected
|
20
|
+
def hhmmss_to_local_time(text)
|
21
|
+
hh, mm, ss = text.chars.each_slice(2).collect{|chars| chars.join }
|
22
|
+
utc_today = Time.zone.today
|
23
|
+
Time.zone.local(utc_today.year, utc_today.month, utc_today.day, hh, mm, ss).
|
24
|
+
in_time_zone(Nmea::Config.time_zone)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module DddFormatable
|
29
|
+
protected
|
30
|
+
def dmm_to_ddd(dmm, direction)
|
31
|
+
dmm = dmm.to_f / 100
|
32
|
+
integer = dmm.to_i
|
33
|
+
decimal = dmm % 1
|
34
|
+
|
35
|
+
(integer + decimal / 60 * 100.0) * ("NE".include?(direction) ? 1 : -1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|