nmea_plus 1.0.0

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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/gem/lib/nmea_plus.rb +63 -0
  3. data/gem/lib/nmea_plus/ais_message_factory.rb +17 -0
  4. data/gem/lib/nmea_plus/generated_parser/parser.rb +127 -0
  5. data/gem/lib/nmea_plus/generated_parser/tokenizer.rb +100 -0
  6. data/gem/lib/nmea_plus/message/ais/base_ais.rb +20 -0
  7. data/gem/lib/nmea_plus/message/ais/vdm.rb +100 -0
  8. data/gem/lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb +99 -0
  9. data/gem/lib/nmea_plus/message/ais/vdm_payload/vdm_msg1.rb +65 -0
  10. data/gem/lib/nmea_plus/message/ais/vdm_payload/vdm_msg5.rb +38 -0
  11. data/gem/lib/nmea_plus/message/ais/vdm_payload/vdm_msg8.rb +43 -0
  12. data/gem/lib/nmea_plus/message/base.rb +172 -0
  13. data/gem/lib/nmea_plus/message/nmea/aam.rb +17 -0
  14. data/gem/lib/nmea_plus/message/nmea/alm.rb +25 -0
  15. data/gem/lib/nmea_plus/message/nmea/apa.rb +20 -0
  16. data/gem/lib/nmea_plus/message/nmea/apb.rb +14 -0
  17. data/gem/lib/nmea_plus/message/nmea/base_nmea.rb +36 -0
  18. data/gem/lib/nmea_plus/message/nmea/bod.rb +14 -0
  19. data/gem/lib/nmea_plus/message/nmea/bwc.rb +12 -0
  20. data/gem/lib/nmea_plus/message/nmea/bwr.rb +25 -0
  21. data/gem/lib/nmea_plus/message/nmea/bww.rb +11 -0
  22. data/gem/lib/nmea_plus/message/nmea/dbk.rb +13 -0
  23. data/gem/lib/nmea_plus/message/nmea/dbs.rb +11 -0
  24. data/gem/lib/nmea_plus/message/nmea/dbt.rb +11 -0
  25. data/gem/lib/nmea_plus/message/nmea/dcn.rb +26 -0
  26. data/gem/lib/nmea_plus/message/nmea/dpt.rb +12 -0
  27. data/gem/lib/nmea_plus/message/nmea/dtm.rb +24 -0
  28. data/gem/lib/nmea_plus/message/nmea/fsi.rb +14 -0
  29. data/gem/lib/nmea_plus/message/nmea/gbs.rb +18 -0
  30. data/gem/lib/nmea_plus/message/nmea/gga.rb +32 -0
  31. data/gem/lib/nmea_plus/message/nmea/glc.rb +23 -0
  32. data/gem/lib/nmea_plus/message/nmea/gll.rb +21 -0
  33. data/gem/lib/nmea_plus/message/nmea/gns.rb +28 -0
  34. data/gem/lib/nmea_plus/message/nmea/grs.rb +24 -0
  35. data/gem/lib/nmea_plus/message/nmea/gsa.rb +27 -0
  36. data/gem/lib/nmea_plus/message/nmea/gst.rb +18 -0
  37. data/gem/lib/nmea_plus/message/nmea/gsv.rb +29 -0
  38. data/gem/lib/nmea_plus/message/nmea/gtd.rb +15 -0
  39. data/gem/lib/nmea_plus/message/nmea/gxa.rb +22 -0
  40. data/gem/lib/nmea_plus/message/nmea/hdg.rb +20 -0
  41. data/gem/lib/nmea_plus/message/nmea/hdm.rb +11 -0
  42. data/gem/lib/nmea_plus/message/nmea/hdt.rb +11 -0
  43. data/gem/lib/nmea_plus/message/nmea/hfb.rb +12 -0
  44. data/gem/lib/nmea_plus/message/nmea/hsc.rb +12 -0
  45. data/gem/lib/nmea_plus/message/nmea/its.rb +11 -0
  46. data/gem/lib/nmea_plus/message/nmea/lcd.rb +23 -0
  47. data/gem/lib/nmea_plus/message/nmea/msk.rb +15 -0
  48. data/gem/lib/nmea_plus/message/nmea/mss.rb +15 -0
  49. data/gem/lib/nmea_plus/message/nmea/mtw.rb +12 -0
  50. data/gem/lib/nmea_plus/message/nmea/mwv.rb +15 -0
  51. data/gem/lib/nmea_plus/message/nmea/oln.rb +22 -0
  52. data/gem/lib/nmea_plus/message/nmea/osd.rb +19 -0
  53. data/gem/lib/nmea_plus/message/nmea/pashr.rb +21 -0
  54. data/gem/lib/nmea_plus/message/nmea/r00.rb +11 -0
  55. data/gem/lib/nmea_plus/message/nmea/rma.rb +30 -0
  56. data/gem/lib/nmea_plus/message/nmea/rmb.rb +30 -0
  57. data/gem/lib/nmea_plus/message/nmea/rmc.rb +33 -0
  58. data/gem/lib/nmea_plus/message/nmea/rot.rb +12 -0
  59. data/gem/lib/nmea_plus/message/nmea/rpm.rb +15 -0
  60. data/gem/lib/nmea_plus/message/nmea/rsa.rb +17 -0
  61. data/gem/lib/nmea_plus/message/nmea/rsd.rb +14 -0
  62. data/gem/lib/nmea_plus/message/nmea/rte.rb +16 -0
  63. data/gem/lib/nmea_plus/message/nmea/sfi.rb +18 -0
  64. data/gem/lib/nmea_plus/message/nmea/stn.rb +11 -0
  65. data/gem/lib/nmea_plus/message/nmea/tds.rb +11 -0
  66. data/gem/lib/nmea_plus/message/nmea/tfi.rb +13 -0
  67. data/gem/lib/nmea_plus/message/nmea/tpc.rb +13 -0
  68. data/gem/lib/nmea_plus/message/nmea/tpr.rb +13 -0
  69. data/gem/lib/nmea_plus/message/nmea/tpt.rb +13 -0
  70. data/gem/lib/nmea_plus/message/nmea/trf.rb +28 -0
  71. data/gem/lib/nmea_plus/message/nmea/ttm.rb +22 -0
  72. data/gem/lib/nmea_plus/message/nmea/vbw.rb +16 -0
  73. data/gem/lib/nmea_plus/message/nmea/vdr.rb +13 -0
  74. data/gem/lib/nmea_plus/message/nmea/vhw.rb +14 -0
  75. data/gem/lib/nmea_plus/message/nmea/vlw.rb +12 -0
  76. data/gem/lib/nmea_plus/message/nmea/vpw.rb +12 -0
  77. data/gem/lib/nmea_plus/message/nmea/vtg.rb +41 -0
  78. data/gem/lib/nmea_plus/message/nmea/vwr.rb +15 -0
  79. data/gem/lib/nmea_plus/message/nmea/wcv.rb +12 -0
  80. data/gem/lib/nmea_plus/message/nmea/wnc.rb +14 -0
  81. data/gem/lib/nmea_plus/message/nmea/wpl.rb +19 -0
  82. data/gem/lib/nmea_plus/message/nmea/xdr.rb +14 -0
  83. data/gem/lib/nmea_plus/message/nmea/xte.rb +16 -0
  84. data/gem/lib/nmea_plus/message/nmea/xtr.rb +12 -0
  85. data/gem/lib/nmea_plus/message/nmea/zda.rb +23 -0
  86. data/gem/lib/nmea_plus/message/nmea/zfo.rb +13 -0
  87. data/gem/lib/nmea_plus/message/nmea/ztg.rb +13 -0
  88. data/gem/lib/nmea_plus/message_factory.rb +68 -0
  89. data/gem/lib/nmea_plus/nmea_message_factory.rb +110 -0
  90. data/gem/lib/nmea_plus/version.rb +3 -0
  91. metadata +285 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cb6a15ea1c4b8d040614ae117703221df082cf53
4
+ data.tar.gz: 3d738a04a524c69e02c371befc3d1edd9f913a96
5
+ SHA512:
6
+ metadata.gz: f026b1f759c56c97952ea97b3b7a6190c0930e4cb02486a715cf704eefe5fa8c4f012c19b6b8778dd32be709be95cc671c23f267096635ddcd55d3f2e1d1074c
7
+ data.tar.gz: 9002792450538ed8f492db5f54707f1631bc44f27acede7a44868b82900755177da03974922565249ebde61b175fd56023aa5cf23878d0141b606dbad891ceb8
@@ -0,0 +1,63 @@
1
+ require 'nmea_plus/version'
2
+
3
+ require 'nmea_plus/generated_parser/parser'
4
+ require 'nmea_plus/generated_parser/tokenizer'
5
+
6
+ module NMEAPlus
7
+ class SourceDecoder
8
+ attr_accessor :throw_on_parse_fail
9
+ attr_accessor :throw_on_unrecognized_type # typically for development
10
+
11
+ def initialize(line_reader)
12
+ unless line_reader.respond_to? :each_line
13
+ fail ArgumentError, "line_reader must inherit from type IO (or implement each_line)"
14
+ end
15
+ @throw_on_parse_fail = false
16
+ @source = line_reader
17
+ @decoder = NMEAPlus::Decoder.new
18
+ end
19
+
20
+ # return each parsed message
21
+ def each_message
22
+ @source.each_line do |line|
23
+ if @throw_on_parse_fail
24
+ yield @decoder.parse(line)
25
+ else
26
+ begin
27
+ y = @decoder.parse(line)
28
+ yield y
29
+ rescue
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # return messages grouped into multipart chains as required
36
+ def each_complete_message
37
+ partials = {}
38
+ each_message do |msg|
39
+ slot = msg.data_type
40
+
41
+ if partials[slot].nil?
42
+ partials[slot] = msg
43
+ else
44
+ # the message was already in there
45
+ if 1 != (msg.message_number - partials[slot].message_number)
46
+ # error! just overwrite what was there
47
+ partials[slot] = msg
48
+ else
49
+ partials[slot].add_message_part(msg)
50
+ end
51
+ end
52
+
53
+ # take action if we've completed the chain
54
+ maybe_full = partials[slot]
55
+ if maybe_full.all_messages_received?
56
+ partials[slot] = nil
57
+ yield maybe_full
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,17 @@
1
+
2
+ require_relative 'message_factory'
3
+
4
+ require_relative 'message/ais/vdm'
5
+
6
+ module NMEAPlus
7
+ class AISMessageFactory < MessageFactory
8
+ def self.parent_module
9
+ "AIS"
10
+ end
11
+
12
+ def self.alternate_data_type(data_type)
13
+ # match last 3 digits (get rid of talker)
14
+ data_type[2..4]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,127 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.13
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+
10
+ require_relative "../nmea_message_factory"
11
+ require_relative "../ais_message_factory"
12
+
13
+ module NMEAPlus
14
+ class Parser < Racc::Parser
15
+
16
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 19)
17
+
18
+ # override racc's on_error so we can have context in our error messages
19
+ def on_error(t, val, vstack)
20
+ errcontext = (@ss.pre_match[-10..-1] || @ss.pre_match) +
21
+ @ss.matched + @ss.post_match[0..9]
22
+ line_number = @ss.pre_match.lines.count
23
+ raise ParseError, sprintf("parse error on value %s (%s) " +
24
+ "on line %s around \"%s\"",
25
+ val.inspect, token_to_str(t) || '?',
26
+ line_number, errcontext)
27
+ end
28
+ ...end parser.y/module_eval...
29
+ ##### State transition tables begin ###
30
+
31
+ racc_action_table = [
32
+ 2, 3, 6, 5, 4, 7, 8, 9 ]
33
+
34
+ racc_action_check = [
35
+ 0, 0, 3, 2, 1, 4, 5, 6 ]
36
+
37
+ racc_action_pointer = [
38
+ -3, 4, -2, -3, 5, 4, 5, nil, nil, nil ]
39
+
40
+ racc_action_default = [
41
+ -3, -3, -3, -3, -3, -3, -3, 10, -1, -2 ]
42
+
43
+ racc_goto_table = [
44
+ 1 ]
45
+
46
+ racc_goto_check = [
47
+ 1 ]
48
+
49
+ racc_goto_pointer = [
50
+ nil, 0 ]
51
+
52
+ racc_goto_default = [
53
+ nil, nil ]
54
+
55
+ racc_reduce_table = [
56
+ 0, 0, :racc_error,
57
+ 3, 7, :_reduce_1,
58
+ 3, 7, :_reduce_2 ]
59
+
60
+ racc_reduce_n = 3
61
+
62
+ racc_shift_n = 10
63
+
64
+ racc_token_table = {
65
+ false => 0,
66
+ :error => 1,
67
+ :CSUM => 2,
68
+ :CASH => 3,
69
+ :BANG => 4,
70
+ :DATA => 5 }
71
+
72
+ racc_nt_base = 6
73
+
74
+ racc_use_result_var = true
75
+
76
+ Racc_arg = [
77
+ racc_action_table,
78
+ racc_action_check,
79
+ racc_action_default,
80
+ racc_action_pointer,
81
+ racc_goto_table,
82
+ racc_goto_check,
83
+ racc_goto_default,
84
+ racc_goto_pointer,
85
+ racc_nt_base,
86
+ racc_reduce_table,
87
+ racc_token_table,
88
+ racc_shift_n,
89
+ racc_reduce_n,
90
+ racc_use_result_var ]
91
+
92
+ Racc_token_to_s_table = [
93
+ "$end",
94
+ "error",
95
+ "CSUM",
96
+ "CASH",
97
+ "BANG",
98
+ "DATA",
99
+ "$start",
100
+ "start" ]
101
+
102
+ Racc_debug_parser = false
103
+
104
+ ##### State transition tables end #####
105
+
106
+ # reduce 0 omitted
107
+
108
+ module_eval(<<'.,.,', 'parser.y', 8)
109
+ def _reduce_1(val, _values, result)
110
+ result = NMEAPlus::NMEAMessageFactory.create(val[0], val[1], val[2])
111
+ result
112
+ end
113
+ .,.,
114
+
115
+ module_eval(<<'.,.,', 'parser.y', 9)
116
+ def _reduce_2(val, _values, result)
117
+ result = NMEAPlus::AISMessageFactory.create(val[0], val[1], val[2])
118
+ result
119
+ end
120
+ .,.,
121
+
122
+ def _reduce_none(val, _values, result)
123
+ val[0]
124
+ end
125
+
126
+ end # class Parser
127
+ end # module NMEAPlus
@@ -0,0 +1,100 @@
1
+ #--
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by rex 1.0.5
4
+ # from lexical definition file "/Users/iakatz/Code Base/nmea_plus/parser/tokenizer.rex".
5
+ #++
6
+
7
+
8
+ module NMEAPlus
9
+ class Decoder < Parser # not indented due to constraints of .rex format
10
+ require 'strscan'
11
+
12
+ class ScanError < StandardError ; end
13
+
14
+ attr_reader :lineno
15
+ attr_reader :filename
16
+ attr_accessor :state
17
+
18
+ def scan_setup(str)
19
+ @ss = StringScanner.new(str)
20
+ @lineno = 1
21
+ @state = nil
22
+ end
23
+
24
+ def action
25
+ yield
26
+ end
27
+
28
+ def scan_str(str)
29
+ scan_setup(str)
30
+ do_parse
31
+ end
32
+ alias :scan :scan_str
33
+
34
+ def load_file( filename )
35
+ @filename = filename
36
+ open(filename, "r") do |f|
37
+ scan_setup(f.read)
38
+ end
39
+ end
40
+
41
+ def scan_file( filename )
42
+ load_file(filename)
43
+ do_parse
44
+ end
45
+
46
+
47
+ def next_token
48
+ return if @ss.eos?
49
+
50
+ # skips empty actions
51
+ until token = _next_token or @ss.eos?; end
52
+ token
53
+ end
54
+
55
+ def _next_token
56
+ text = @ss.peek(1)
57
+ @lineno += 1 if text == "\n"
58
+ token = case @state
59
+ when nil
60
+ case
61
+ when (text = @ss.scan(/\*[0-9A-F]{2}[\w\n\r]*/i))
62
+ action { [:CSUM, text[1..2]] }
63
+
64
+ when (text = @ss.scan(/\$/i))
65
+ action { [:CASH, text] }
66
+
67
+ when (text = @ss.scan(/!/i))
68
+ action { [:BANG, text] }
69
+
70
+ when (text = @ss.scan(/[^\*]+/i))
71
+ action { [:DATA, text] }
72
+
73
+ else
74
+ text = @ss.string[@ss.pos .. -1]
75
+ raise ScanError, "can not match: '" + text + "'"
76
+ end # if
77
+
78
+ else
79
+ raise ScanError, "undefined state: '" + state.to_s + "'"
80
+ end # case state
81
+ token
82
+ end # def _next_token
83
+
84
+ def parse(input)
85
+ @yydebug = true if ENV['DEBUG_RACC']
86
+ scan_str(input)
87
+ end
88
+ def tokenize(input)
89
+ scan_setup(input)
90
+ ret = []
91
+ last_token = nil
92
+ loop do
93
+ last_token = next_token
94
+ break if last_token.nil?
95
+ ret << last_token
96
+ end
97
+ ret
98
+ end
99
+ end # class
100
+ end # class
@@ -0,0 +1,20 @@
1
+
2
+ require_relative "../base"
3
+
4
+ module NMEAPlus
5
+ module Message
6
+ module AIS
7
+
8
+ class AISMessage < NMEAPlus::Message::Base
9
+ def talker
10
+ data_type[0..1]
11
+ end
12
+
13
+ def message_type
14
+ data_type[2..-1]
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,100 @@
1
+ require_relative "base_ais"
2
+
3
+ require_relative "vdm_payload/vdm_msg1"
4
+ require_relative "vdm_payload/vdm_msg5"
5
+ require_relative "vdm_payload/vdm_msg8"
6
+
7
+ =begin boilerplate for vdm payload objects
8
+ require_relative 'vdm_msg'
9
+
10
+ module NMEAPlus
11
+ module Message
12
+ module AIS
13
+ module VDMPayload
14
+ class VDMMsg5 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ =end
23
+
24
+ module NMEAPlus
25
+ module Message
26
+ module AIS
27
+ class VDM < NMEAPlus::Message::AIS::AISMessage
28
+ field_reader :total_messages, 1, :_integer
29
+ field_reader :message_number, 2, :_integer
30
+ field_reader :message_id, 3, :_string
31
+ field_reader :channel_code, 4, :_string
32
+ field_reader :raw_ais_payload, 5, :_string
33
+ field_reader :ais_payload_fill_bits, 6, :_integer
34
+
35
+ def ais
36
+ # factory method: find the appropriate message type class and instantiate it
37
+ p = full_dearmored_ais_payload
38
+ ret = _payload_container(p[0, 6].to_i(2))
39
+ ret.payload_bitstring = p
40
+ ret.fill_bits = last_ais_fill_bits
41
+ ret
42
+ end
43
+
44
+ # the full encoded payload as it was received
45
+ def full_armored_ais_payload
46
+ # get the full message and fill bits for the last one
47
+ ptr = self
48
+ ret = ""
49
+ loop do
50
+ ret << ptr.raw_ais_payload
51
+ break if ptr.next_part.nil?
52
+ ptr = ptr.next_part
53
+ end
54
+ ret
55
+ end
56
+
57
+ # a binary string ("0010101110110") representing the dearmored payload
58
+ def full_dearmored_ais_payload
59
+ data = full_armored_ais_payload
60
+ out = ""
61
+ # dearmor all but the last byte, then apply the fill bits to the last byte
62
+ data[0..-2].each_char { |c| out << _dearmor6b(c) }
63
+ out << _dearmor6b(data[-1], 6 - last_ais_fill_bits)
64
+ out
65
+ end
66
+
67
+ def last_ais_fill_bits
68
+ # get the fill bits for the last message in the sequence
69
+ ptr = self
70
+ fill_bits = nil
71
+ loop do
72
+ fill_bits = ptr.ais_payload_fill_bits
73
+ break if ptr.next_part.nil?
74
+ ptr = ptr.next_part
75
+ end
76
+ fill_bits.to_i
77
+ end
78
+
79
+ # perform the 6-bit to 8-bit conversion defined in the spec
80
+ def _dearmor6b(c, len = 6)
81
+ val = c.ord
82
+ if val >= 96
83
+ ret = val - 56
84
+ else
85
+ ret = val - 48
86
+ end
87
+ ret.to_s(2).rjust(6, "0")[0..(len - 1)]
88
+ end
89
+
90
+ def _payload_container(message_type_id)
91
+ class_identifier = "NMEAPlus::Message::AIS::VDMPayload::VDMMsg#{message_type_id}"
92
+ Object::const_get(class_identifier).new
93
+ rescue ::NameError
94
+ class_identifier = "NMEAPlus::Message::AIS::VDMPayload::VDMMsgUndefined" # generic
95
+ Object::const_get(class_identifier).new
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,99 @@
1
+ class Class
2
+ # make our own shortcut syntax for payload attributes
3
+ def payload_reader(name, start_bit, length, formatter, formatter_arg = nil)
4
+ if formatter_arg.nil?
5
+ self.class_eval("def #{name};#{formatter}(#{start_bit}, #{length});end")
6
+ else
7
+ self.class_eval("def #{name};#{formatter}(#{start_bit}, #{length}, #{formatter_arg});end")
8
+ end
9
+ end
10
+ end
11
+
12
+ module NMEAPlus
13
+ module Message
14
+ module AIS
15
+ module VDMPayload
16
+ class VDMMsg
17
+ attr_accessor :payload_bitstring
18
+ attr_accessor :fill_bits
19
+
20
+ payload_reader :message_type, 0, 6, :_u
21
+ payload_reader :repeat_indicator, 6, 2, :_u
22
+ payload_reader :source_mmsi, 8, 30, :_u
23
+
24
+ # lookup table for 6-bit ascii
25
+ def _6b_ascii(ord)
26
+ '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !"#$%&\'()*+,-./0123456789:;<=>?'[ord]
27
+ end
28
+
29
+ # convert an entire string from the payload
30
+ def _6b_string(start, length)
31
+ # pull out 6b chunks from the string, use their value as a lookup into the ascii array
32
+ _bit_slices(start, length, 6).to_a.map(&:join).map { |x| _6b_ascii(x.to_i(2)) }.join
33
+ end
34
+
35
+ def _8b_data_string(start, length)
36
+ _bit_slices(start, length, 8).to_a.map(&:join).map { |x| x.to_i(2).chr }.join
37
+ end
38
+
39
+ def _bit_slices(start, length, chunk_size)
40
+ @payload_bitstring[start, length].chars.each_slice(chunk_size)
41
+ end
42
+
43
+ # convert a string but trim off the 0s ('@')
44
+ def _6b_string_nullterminated(start, length)
45
+ _6b_string(start, length).split("@", 2)[0]
46
+ end
47
+
48
+ # directly convert a string to a binary number as you'd read it
49
+ def _6b_unsigned_integer(start, length)
50
+ @payload_bitstring[start, length].to_i(2)
51
+ end
52
+
53
+ # perform a twos complement operation on part of the payload
54
+ def _6b_twoscomplement(start, length)
55
+ # two's complement: flip bits, then add 1
56
+ @payload_bitstring[start, length].tr("01", "10").to_i(2) + 1
57
+ end
58
+
59
+ def _6b_integer(start, length)
60
+ # MSB is 1 for negative
61
+ _6b_twoscomplement(start, length) * (@payload_bitstring[start] == 0 ? 1 : -1)
62
+ end
63
+
64
+ # scale an integer by dividing it by 10^decimal_places
65
+ def _6b_integer_scaled(start, length, decimal_places)
66
+ _6b_integer(start, length).to_f / (10 ** decimal_places)
67
+ end
68
+
69
+ # scale an unsigned integer by dividing it by 10^decimal_places
70
+ def _6b_unsigned_integer_scaled(start, length, decimal_places)
71
+ _6b_unsigned_integer(start, length).to_f / (10.0 ** decimal_places)
72
+ end
73
+
74
+ def _6b_boolean(start, _)
75
+ @payload_bitstring[start].to_i == 1
76
+ end
77
+
78
+ def _2b_data_string(start, length)
79
+ @payload_bitstring[start, length]
80
+ end
81
+
82
+ # use shorthand for data types as defined in http://catb.org/gpsd/AIVDM.html
83
+ alias_method :_u, :_6b_unsigned_integer
84
+ alias_method :_U, :_6b_unsigned_integer_scaled
85
+ alias_method :_i, :_6b_integer
86
+ alias_method :_I, :_6b_integer_scaled
87
+ alias_method :_b, :_6b_boolean
88
+ alias_method :_e, :_6b_unsigned_integer
89
+ alias_method :_t, :_6b_string_nullterminated
90
+ alias_method :_d, :_2b_data_string
91
+
92
+ end
93
+
94
+ class VDMMsgUndefined < VDMMsg; end
95
+
96
+ end
97
+ end
98
+ end
99
+ end