Class: NMEAPlus::Message::Base Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/nmea_plus/message/base.rb

Overview

This class is abstract.

The base message type, from which all others inherit

Direct Known Subclasses

AIS::AISMessage, NMEA::NMEAMessage

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#checksumString



36
37
38
# File 'lib/nmea_plus/message/base.rb', line 36

def checksum
  @checksum
end

#data_typeObject (readonly)



44
# File 'lib/nmea_plus/message/base.rb', line 44

field_reader :data_type, 0, nil

#fieldsArray<String> (readonly)



33
34
35
# File 'lib/nmea_plus/message/base.rb', line 33

def fields
  @fields
end

#interpreted_data_typeString



39
40
41
# File 'lib/nmea_plus/message/base.rb', line 39

def interpreted_data_type
  @interpreted_data_type
end

#message_numberInteger (readonly)

This method is abstract.

Returns The ordinal number of this message in its sequence.

See Also:



87
88
89
# File 'lib/nmea_plus/message/base.rb', line 87

def message_number
  1
end

#next_partNMEAPlus::Message



42
43
44
# File 'lib/nmea_plus/message/base.rb', line 42

def next_part
  @next_part
end

#originalString (readonly)



48
49
50
# File 'lib/nmea_plus/message/base.rb', line 48

def original
  "#{prefix}#{payload}*#{checksum}"
end

#payloadString



30
31
32
# File 'lib/nmea_plus/message/base.rb', line 30

def payload
  @payload
end

#prefixString



27
28
29
# File 'lib/nmea_plus/message/base.rb', line 27

def prefix
  @prefix
end

#total_messagesInteger (readonly)

This method is abstract.

Returns The number of parts to this message.

See Also:



79
80
81
# File 'lib/nmea_plus/message/base.rb', line 79

def total_messages
  1
end

Class Method Details

.field_reader(name, field_num, formatter = nil) ⇒ Object

make our own shortcut syntax for message attribute accessors



18
19
20
21
22
23
24
# File 'lib/nmea_plus/message/base.rb', line 18

def self.field_reader(name, field_num, formatter = nil)
  if formatter.nil?
    self.class_eval("def #{name};@fields[#{field_num}];end")
  else
    self.class_eval("def #{name};#{formatter}(@fields[#{field_num}]);end")
  end
end

Instance Method Details

#_degrees_minutes_to_decimal(dm_string, sign_letter = "") ⇒ Float

Convert A string latitude or longitude as fields into a signed number



132
133
134
135
136
137
138
# File 'lib/nmea_plus/message/base.rb', line 132

def _degrees_minutes_to_decimal(dm_string, sign_letter = "")
  return nil if dm_string.nil? || dm_string.empty?
  r = /(\d+)(\d{2}\.\d+)/  # (some number of digits) (2 digits for minutes).(decimal minutes)
  m = r.match(dm_string)
  raw = m.values_at(1)[0].to_f + (m.values_at(2)[0].to_f / 60)
  _nsew_signed_float(raw, sign_letter)
end

#_float(field) ⇒ Float

float or nil



162
163
164
165
# File 'lib/nmea_plus/message/base.rb', line 162

def _float(field)
  return nil if field.nil? || field.empty?
  field.to_f
end

#_hex_to_integer(field) ⇒ Integer

hex to int or nil



178
179
180
181
# File 'lib/nmea_plus/message/base.rb', line 178

def _hex_to_integer(field)
  return nil if field.nil? || field.empty?
  field.hex
end

#_highest_contiguous_index(last_index) ⇒ Integer

Helper function to calculate the contiguous index



119
120
121
122
123
124
# File 'lib/nmea_plus/message/base.rb', line 119

def _highest_contiguous_index(last_index)
  mn = message_number # just in case this is expensive to compute
  return last_index if mn - last_index != 1      # indicating a skip or restart
  return mn if @next_part.nil?                   # indicating we're the last message
  @next_part._highest_contiguous_index(mn)       # recurse down
end

#_integer(field) ⇒ Integer

integer or nil



154
155
156
157
# File 'lib/nmea_plus/message/base.rb', line 154

def _integer(field)
  return nil if field.nil? || field.empty?
  field.to_i
end

#_interval_hms(field) ⇒ Time

time interval or nil (HHMMSS or HHMMSS.SS)



201
202
203
204
205
206
207
208
209
210
# File 'lib/nmea_plus/message/base.rb', line 201

def _interval_hms(field)
  return nil if field.nil? || field.empty?
  re_format = /(\d{2})(\d{2})(\d{2}(\.\d+)?)/
  begin
    hms = re_format.match(field)
    Time.new(0, 0, 0, hms[1].to_i, hms[2].to_i, hms[3].to_f)
  rescue
    nil
  end
end

#_nsew_signed_float(mixed_val, sign_letter = "") ⇒ Float

Use cardinal directions to assign positive or negative to mixed_val. Of possible directions NSEW (sign_letter) treat N/E as + and S/W as -



145
146
147
148
149
# File 'lib/nmea_plus/message/base.rb', line 145

def _nsew_signed_float(mixed_val, sign_letter = "")
  value = mixed_val.to_f
  value *= -1 if !sign_letter.empty? && "SW".include?(sign_letter.upcase)
  value
end

#_string(field) ⇒ String

string or nil



170
171
172
173
# File 'lib/nmea_plus/message/base.rb', line 170

def _string(field)
  return nil if field.nil? || field.empty?
  field
end

#_utc_date_time(d_field, t_field) ⇒ Time



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/nmea_plus/message/base.rb', line 215

def _utc_date_time(d_field, t_field)
  return nil if t_field.nil? || t_field.empty?
  return nil if d_field.nil? || d_field.empty?

  # get formats and time
  time_format = /(\d{2})(\d{2})(\d{2}(\.\d+)?)/
  date_format = /(\d{2})(\d{2})(\d{2})/

  # crunch numbers
  begin
    dmy = date_format.match(d_field)
    hms = time_format.match(t_field)
    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)
  rescue
    nil
  end
end

#_utctime_hms(field) ⇒ Time

utc time or nil (HHMMSS or HHMMSS.SS)



186
187
188
189
190
191
192
193
194
195
196
# File 'lib/nmea_plus/message/base.rb', line 186

def _utctime_hms(field)
  return nil if field.nil? || field.empty?
  re_format = /(\d{2})(\d{2})(\d{2}(\.\d+)?)/
  now = Time.now
  begin
    hms = re_format.match(field)
    Time.new(now.year, now.month, now.day, hms[1].to_i, hms[2].to_i, hms[3].to_f)
  rescue
    nil
  end
end

#add_message_part(msg) ⇒ void

This method returns an undefined value.

Create a linked list of messages by appending a new message to the end of the chain that starts with this message. (O(n) implementation; message parts assumed to be < 10)



95
96
97
98
99
100
101
# File 'lib/nmea_plus/message/base.rb', line 95

def add_message_part(msg)
  if @next_part.nil?
    @next_part = msg
  else
    @next_part.add_message_part(msg)
  end
end

#all_checksums_ok?Boolean

return [bool] Whether the checksums for all available message parts are OK



64
65
66
67
68
# File 'lib/nmea_plus/message/base.rb', line 64

def all_checksums_ok?
  return false unless checksum_ok?
  return true if @next_part.nil?
  @next_part.all_checksums_ok?
end

#all_messages_received?bool



104
105
106
# File 'lib/nmea_plus/message/base.rb', line 104

def all_messages_received?
  total_messages == highest_contiguous_index
end

#calculated_checksumObject

return [String] The calculated checksum for this payload as a two-character string



71
72
73
# File 'lib/nmea_plus/message/base.rb', line 71

def calculated_checksum
  "%02x" % @payload.each_byte.map(&:ord).reduce(:^)
end

#checksum_ok?bool



59
60
61
# File 'lib/nmea_plus/message/base.rb', line 59

def checksum_ok?
  calculated_checksum.upcase == checksum.upcase
end

#highest_contiguous_indexInteger

Returns The highest contiguous sequence number of linked message parts.



111
112
113
# File 'lib/nmea_plus/message/base.rb', line 111

def highest_contiguous_index
  _highest_contiguous_index(0)
end