nmea_plus 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +116 -0
  3. data/{gem/lib → lib}/nmea_plus.rb +19 -3
  4. data/lib/nmea_plus/ais_message_factory.rb +23 -0
  5. data/{gem/lib → lib}/nmea_plus/generated_parser/parser.rb +0 -0
  6. data/{gem/lib → lib}/nmea_plus/generated_parser/tokenizer.rb +1 -1
  7. data/{gem/lib → lib}/nmea_plus/message/ais/base_ais.rb +0 -0
  8. data/{gem/lib → lib}/nmea_plus/message/ais/vdm.rb +5 -4
  9. data/{gem/lib → lib}/nmea_plus/message/ais/vdm_payload/vdm_msg.rb +0 -0
  10. data/{gem/lib → lib}/nmea_plus/message/ais/vdm_payload/vdm_msg1.rb +0 -0
  11. data/{gem/lib → lib}/nmea_plus/message/ais/vdm_payload/vdm_msg5.rb +0 -0
  12. data/{gem/lib → lib}/nmea_plus/message/ais/vdm_payload/vdm_msg8.rb +0 -0
  13. data/lib/nmea_plus/message/base.rb +235 -0
  14. data/{gem/lib → lib}/nmea_plus/message/nmea/aam.rb +0 -0
  15. data/{gem/lib → lib}/nmea_plus/message/nmea/alm.rb +0 -0
  16. data/{gem/lib → lib}/nmea_plus/message/nmea/apa.rb +0 -0
  17. data/{gem/lib → lib}/nmea_plus/message/nmea/apb.rb +0 -0
  18. data/{gem/lib → lib}/nmea_plus/message/nmea/base_nmea.rb +0 -0
  19. data/{gem/lib → lib}/nmea_plus/message/nmea/bod.rb +0 -0
  20. data/{gem/lib → lib}/nmea_plus/message/nmea/bwc.rb +0 -0
  21. data/{gem/lib → lib}/nmea_plus/message/nmea/bwr.rb +0 -0
  22. data/{gem/lib → lib}/nmea_plus/message/nmea/bww.rb +0 -0
  23. data/{gem/lib → lib}/nmea_plus/message/nmea/dbk.rb +0 -0
  24. data/{gem/lib → lib}/nmea_plus/message/nmea/dbs.rb +0 -0
  25. data/{gem/lib → lib}/nmea_plus/message/nmea/dbt.rb +0 -0
  26. data/{gem/lib → lib}/nmea_plus/message/nmea/dcn.rb +0 -0
  27. data/{gem/lib → lib}/nmea_plus/message/nmea/dpt.rb +0 -0
  28. data/{gem/lib → lib}/nmea_plus/message/nmea/dtm.rb +0 -0
  29. data/{gem/lib → lib}/nmea_plus/message/nmea/fsi.rb +0 -0
  30. data/{gem/lib → lib}/nmea_plus/message/nmea/gbs.rb +0 -0
  31. data/{gem/lib → lib}/nmea_plus/message/nmea/gga.rb +0 -0
  32. data/{gem/lib → lib}/nmea_plus/message/nmea/glc.rb +0 -0
  33. data/{gem/lib → lib}/nmea_plus/message/nmea/gll.rb +0 -0
  34. data/{gem/lib → lib}/nmea_plus/message/nmea/gns.rb +0 -0
  35. data/{gem/lib → lib}/nmea_plus/message/nmea/grs.rb +0 -0
  36. data/{gem/lib → lib}/nmea_plus/message/nmea/gsa.rb +0 -0
  37. data/{gem/lib → lib}/nmea_plus/message/nmea/gst.rb +0 -0
  38. data/{gem/lib → lib}/nmea_plus/message/nmea/gsv.rb +0 -0
  39. data/{gem/lib → lib}/nmea_plus/message/nmea/gtd.rb +0 -0
  40. data/{gem/lib → lib}/nmea_plus/message/nmea/gxa.rb +0 -0
  41. data/{gem/lib → lib}/nmea_plus/message/nmea/hdg.rb +0 -0
  42. data/{gem/lib → lib}/nmea_plus/message/nmea/hdm.rb +0 -0
  43. data/{gem/lib → lib}/nmea_plus/message/nmea/hdt.rb +0 -0
  44. data/{gem/lib → lib}/nmea_plus/message/nmea/hfb.rb +0 -0
  45. data/{gem/lib → lib}/nmea_plus/message/nmea/hsc.rb +0 -0
  46. data/{gem/lib → lib}/nmea_plus/message/nmea/its.rb +0 -0
  47. data/{gem/lib → lib}/nmea_plus/message/nmea/lcd.rb +0 -0
  48. data/{gem/lib → lib}/nmea_plus/message/nmea/msk.rb +0 -0
  49. data/{gem/lib → lib}/nmea_plus/message/nmea/mss.rb +0 -0
  50. data/{gem/lib → lib}/nmea_plus/message/nmea/mtw.rb +0 -0
  51. data/{gem/lib → lib}/nmea_plus/message/nmea/mwv.rb +0 -0
  52. data/{gem/lib → lib}/nmea_plus/message/nmea/oln.rb +0 -0
  53. data/{gem/lib → lib}/nmea_plus/message/nmea/osd.rb +0 -0
  54. data/{gem/lib → lib}/nmea_plus/message/nmea/pashr.rb +0 -0
  55. data/{gem/lib → lib}/nmea_plus/message/nmea/r00.rb +0 -0
  56. data/{gem/lib → lib}/nmea_plus/message/nmea/rma.rb +0 -0
  57. data/{gem/lib → lib}/nmea_plus/message/nmea/rmb.rb +0 -0
  58. data/{gem/lib → lib}/nmea_plus/message/nmea/rmc.rb +0 -0
  59. data/{gem/lib → lib}/nmea_plus/message/nmea/rot.rb +0 -0
  60. data/{gem/lib → lib}/nmea_plus/message/nmea/rpm.rb +0 -0
  61. data/{gem/lib → lib}/nmea_plus/message/nmea/rsa.rb +0 -0
  62. data/{gem/lib → lib}/nmea_plus/message/nmea/rsd.rb +0 -0
  63. data/{gem/lib → lib}/nmea_plus/message/nmea/rte.rb +0 -0
  64. data/{gem/lib → lib}/nmea_plus/message/nmea/sfi.rb +0 -0
  65. data/{gem/lib → lib}/nmea_plus/message/nmea/stn.rb +0 -0
  66. data/{gem/lib → lib}/nmea_plus/message/nmea/tds.rb +0 -0
  67. data/{gem/lib → lib}/nmea_plus/message/nmea/tfi.rb +0 -0
  68. data/{gem/lib → lib}/nmea_plus/message/nmea/tpc.rb +0 -0
  69. data/{gem/lib → lib}/nmea_plus/message/nmea/tpr.rb +0 -0
  70. data/{gem/lib → lib}/nmea_plus/message/nmea/tpt.rb +0 -0
  71. data/{gem/lib → lib}/nmea_plus/message/nmea/trf.rb +0 -0
  72. data/{gem/lib → lib}/nmea_plus/message/nmea/ttm.rb +0 -0
  73. data/{gem/lib → lib}/nmea_plus/message/nmea/vbw.rb +0 -0
  74. data/{gem/lib → lib}/nmea_plus/message/nmea/vdr.rb +0 -0
  75. data/{gem/lib → lib}/nmea_plus/message/nmea/vhw.rb +0 -0
  76. data/{gem/lib → lib}/nmea_plus/message/nmea/vlw.rb +0 -0
  77. data/{gem/lib → lib}/nmea_plus/message/nmea/vpw.rb +0 -0
  78. data/{gem/lib → lib}/nmea_plus/message/nmea/vtg.rb +0 -0
  79. data/{gem/lib → lib}/nmea_plus/message/nmea/vwr.rb +0 -0
  80. data/{gem/lib → lib}/nmea_plus/message/nmea/wcv.rb +0 -0
  81. data/{gem/lib → lib}/nmea_plus/message/nmea/wnc.rb +0 -0
  82. data/{gem/lib → lib}/nmea_plus/message/nmea/wpl.rb +0 -0
  83. data/{gem/lib → lib}/nmea_plus/message/nmea/xdr.rb +0 -0
  84. data/{gem/lib → lib}/nmea_plus/message/nmea/xte.rb +0 -0
  85. data/{gem/lib → lib}/nmea_plus/message/nmea/xtr.rb +0 -0
  86. data/{gem/lib → lib}/nmea_plus/message/nmea/zda.rb +0 -0
  87. data/{gem/lib → lib}/nmea_plus/message/nmea/zfo.rb +0 -0
  88. data/{gem/lib → lib}/nmea_plus/message/nmea/ztg.rb +0 -0
  89. data/lib/nmea_plus/message_factory.rb +92 -0
  90. data/{gem/lib → lib}/nmea_plus/nmea_message_factory.rb +5 -0
  91. data/{gem/lib → lib}/nmea_plus/version.rb +1 -1
  92. metadata +117 -96
  93. data/gem/lib/nmea_plus/ais_message_factory.rb +0 -17
  94. data/gem/lib/nmea_plus/message/base.rb +0 -172
  95. data/gem/lib/nmea_plus/message_factory.rb +0 -68
@@ -1,17 +0,0 @@
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
@@ -1,172 +0,0 @@
1
-
2
- class Class
3
- # make our own shortcut syntax for message attributes
4
- def field_reader(name, field_num, formatter = nil)
5
- if formatter.nil?
6
- self.class_eval("def #{name};@fields[#{field_num}];end")
7
- else
8
- self.class_eval("def #{name};#{formatter}(@fields[#{field_num}]);end")
9
- end
10
- end
11
- end
12
-
13
- module NMEAPlus
14
- module Message
15
- class Base
16
- attr_accessor :prefix
17
- attr_reader :payload
18
- attr_reader :fields
19
- attr_accessor :checksum
20
- attr_accessor :interpreted_data_type
21
- attr_accessor :next_part
22
-
23
- field_reader :data_type, 0, nil
24
-
25
- def original
26
- "#{prefix}#{payload}*#{checksum}"
27
- end
28
-
29
- def payload=(val)
30
- @payload = val
31
- @fields = val.split(',', -1)
32
- end
33
-
34
- def checksum_ok?
35
- calculated_checksum.upcase == checksum.upcase
36
- end
37
-
38
- def all_checksums_ok?
39
- return false unless checksum_ok?
40
- return true if @next_part.nil?
41
- @next_part.all_checksums_ok?
42
- end
43
-
44
- def calculated_checksum
45
- "%02x" % @payload.each_byte.map(&:ord).reduce(:^)
46
- end
47
-
48
- # many messages override these fields
49
- def total_messages
50
- 1
51
- end
52
-
53
- # sequence number
54
- def message_number
55
- 1
56
- end
57
-
58
- # create a linked list (O(n) implementation; message parts assumed to be < 10) of message parts
59
- def add_message_part(msg)
60
- if @next_part.nil?
61
- @next_part = msg
62
- else
63
- @next_part.add_message_part(msg)
64
- end
65
- end
66
-
67
- def all_messages_received?
68
- total_messages == highest_contiguous_index
69
- end
70
-
71
- def highest_contiguous_index
72
- _highest_contiguous_index(0)
73
- end
74
-
75
- def _highest_contiguous_index(last_index)
76
- mn = message_number # just in case this is expensive to compute
77
- return last_index if mn - last_index != 1 # indicating a skip or restart
78
- return mn if @next_part.nil? # indicating we're the last message
79
- @next_part._highest_contiguous_index(mn) # recurse down
80
- end
81
-
82
- ######################### Conversion functions
83
-
84
- # convert DDMM.MMM to single decimal value.
85
- # sign_letter can be N,S,E,W
86
- def _degrees_minutes_to_decimal(dm_string, sign_letter = "")
87
- return nil if dm_string.nil? || dm_string.empty?
88
- r = /(\d+)(\d{2}\.\d+)/ # (some number of digits) (2 digits for minutes).(decimal minutes)
89
- m = r.match(dm_string)
90
- raw = m.values_at(1)[0].to_f + (m.values_at(2)[0].to_f / 60)
91
- _nsew_signed_float(raw, sign_letter)
92
- end
93
-
94
- # Use cardinal directions to assign positive or negative to mixed_val
95
- # mixed_val can be string or float
96
- # Of possible directions NSEW (sign_letter) treat N/E as + and S/W as -
97
- def _nsew_signed_float(mixed_val, sign_letter = "")
98
- value = mixed_val.to_f
99
- value *= -1 if !sign_letter.empty? && "SW".include?(sign_letter.upcase)
100
- value
101
- end
102
-
103
- # integer or nil
104
- def _integer(field)
105
- return nil if field.nil? || field.empty?
106
- field.to_i
107
- end
108
-
109
- # float or nil
110
- def _float(field)
111
- return nil if field.nil? || field.empty?
112
- field.to_f
113
- end
114
-
115
- # string or nil
116
- def _string(field)
117
- return nil if field.nil? || field.empty?
118
- field
119
- end
120
-
121
- # hex to int or nil
122
- def _hex_to_integer(field)
123
- return nil if field.nil? || field.empty?
124
- field.hex
125
- end
126
-
127
- # utc time or nil (HHMMSS or HHMMSS.SS)
128
- def _utctime_hms(field)
129
- return nil if field.nil? || field.empty?
130
- re_format = /(\d{2})(\d{2})(\d{2}(\.\d+)?)/
131
- now = Time.now
132
- begin
133
- hms = re_format.match(field)
134
- Time.new(now.year, now.month, now.day, hms[1].to_i, hms[2].to_i, hms[3].to_f)
135
- rescue
136
- nil
137
- end
138
- end
139
-
140
- # time interval or nil (HHMMSS or HHMMSS.SS)
141
- def _interval_hms(field)
142
- return nil if field.nil? || field.empty?
143
- re_format = /(\d{2})(\d{2})(\d{2}(\.\d+)?)/
144
- begin
145
- hms = re_format.match(field)
146
- Time.new(0, 0, 0, hms[1].to_i, hms[2].to_i, hms[3].to_f)
147
- rescue
148
- nil
149
- end
150
- end
151
-
152
- def _utc_date_time(d_field, t_field)
153
- return nil if t_field.nil? || t_field.empty?
154
- return nil if d_field.nil? || d_field.empty?
155
-
156
- # get formats and time
157
- time_format = /(\d{2})(\d{2})(\d{2}(\.\d+)?)/
158
- date_format = /(\d{2})(\d{2})(\d{2})/
159
-
160
- # crunch numbers
161
- begin
162
- dmy = date_format.match(d_field)
163
- hms = time_format.match(t_field)
164
- Time.new(2000 + dmy[3].to_i, dmy[2].to_i, dmy[1].to_i, hms[1].to_i, hms[2].to_i, hms[3].to_f)
165
- rescue
166
- nil
167
- end
168
- end
169
-
170
- end
171
- end
172
- end
@@ -1,68 +0,0 @@
1
-
2
- module NMEAPlus
3
-
4
- # meant to be extended. Creates message classes with a common prefix and variable suffix
5
- class MessageFactory
6
-
7
- # factory class must be extended
8
- def self.parent_module
9
- "FIXME_parent_module"
10
- end
11
-
12
- # a way to override the data_type (e.g. __AAM) with GPAAM to get a match
13
- # whatever factory extends this class should override this method
14
- def self.alternate_data_type(data_type)
15
- data_type # in basic implementation, there is no alternative.
16
- end
17
-
18
- # check whether a given object exists. this will work for all consts but shhhhhhhhh
19
- def self.message_class_exists?(class_identifier)
20
- Object::const_get(class_identifier)
21
- return true
22
- rescue ::NameError
23
- return false
24
- end
25
-
26
- # shortcut for the full name to a message class
27
- def self.message_class_name(data_type)
28
- "NMEAPlus::Message::#{self.parent_module}::#{data_type}"
29
- end
30
-
31
- # use the actual type if we have it, else try an alternate (and let it fail there)
32
- def self.best_match_for_data_type(data_type)
33
- return data_type if self.message_class_exists?(self.message_class_name(data_type))
34
- self.alternate_data_type(data_type)
35
- end
36
-
37
- # get a message class through reflection
38
- def self.dynamically_get_message_object(class_identifier)
39
- Object::const_get(class_identifier).new
40
- rescue ::NameError => e
41
- raise ::NameError, "Couldn't instantiate a #{class_identifier} object: #{e}"
42
- end
43
-
44
- # Choose what class to create, and create it based on the first of the (unsplitted) fields
45
- #
46
- def self.create(message_prefix, fields, checksum)
47
- # get the data type and adjust it if necessary (e.g. support for NMEA standard sentences like __AAM)
48
- data_type = fields.split(',', 2)[0].upcase # assumed to be 'GPGGA', etc
49
- interpreted_type = self.best_match_for_data_type(data_type)
50
- class_name = self.message_class_name(interpreted_type)
51
-
52
- # create message and make sure it's the right type
53
- message = self.dynamically_get_message_object(class_name)
54
- unless message.is_a? NMEAPlus::Message::Base
55
- fail ArgumentError, "Undefined message type #{data_type} (classname #{class_name})"
56
- end
57
-
58
- # assign its data and return it
59
- message.checksum = checksum
60
- message.payload = fields
61
- message.prefix = message_prefix
62
- message.interpreted_data_type = interpreted_type
63
- message
64
- end
65
-
66
- end
67
-
68
- end