Class: NMEAPlus::Message::AIS::VDMPayload::VDMMsg

Inherits:
Object
  • Object
show all
Defined in:
lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb

Overview

The base class for the AIS payload (of NMEAPlus::Message::AIS::VDM), which uses its own encoding for its own subtypes

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#fill_bitsInteger

Returns The number of padding characters required to bring the payload to a 6 bit boundary.

Returns:

  • (Integer)

    The number of padding characters required to bring the payload to a 6 bit boundary



15
16
17
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 15

def fill_bits
  @fill_bits
end

#message_typeObject (readonly)

Returns The field defined by 6 bits starting at bit 0 of the payload, formatted with the function #_u().

Returns:

  • The field defined by 6 bits starting at bit 0 of the payload, formatted with the function #_u()



34
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 34

payload_reader :message_type, 0, 6, :_u

#payload_bitstringString

Returns The raw “armored payload” in the original message.

Returns:

  • (String)

    The raw “armored payload” in the original message



12
13
14
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 12

def payload_bitstring
  @payload_bitstring
end

#repeat_indicatorObject (readonly)

Returns The field defined by 2 bits starting at bit 6 of the payload, formatted with the function #_u().

Returns:

  • The field defined by 2 bits starting at bit 6 of the payload, formatted with the function #_u()



35
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 35

payload_reader :repeat_indicator, 6, 2, :_u

#source_mmsiObject (readonly)

Returns The field defined by 30 bits starting at bit 8 of the payload, formatted with the function #_u().

Returns:

  • The field defined by 30 bits starting at bit 8 of the payload, formatted with the function #_u()



36
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 36

payload_reader :source_mmsi, 8, 30, :_u

Class Method Details

.payload_reader(name, start_bit, length, formatter, formatter_arg = nil) ⇒ Object

make our own shortcut syntax for payload attributes

Parameters:

  • name (String)

    What the accessor will be called

  • start_bit (Integer)

    The index of first bit of this field in the payload

  • length (Integer)

    The number of bits in this field

  • formatter (Symbol)

    The symbol for the formatting function to apply to the field (optional)

  • formatter_arg (defaults to: nil)

    Any argument necessary for the formatting function



26
27
28
29
30
31
32
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 26

def self.payload_reader(name, start_bit, length, formatter, formatter_arg = nil)
  if formatter_arg.nil?
    self.class_eval("def #{name};#{formatter}(#{start_bit}, #{length});end")
  else
    self.class_eval("def #{name};#{formatter}(#{start_bit}, #{length}, #{formatter_arg});end")
  end
end

Instance Method Details

#_2b_data_string(start, length) ⇒ String Also known as: _d

Return a string representing binary

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (String)

    e.g. “0101010101011000”



145
146
147
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 145

def _2b_data_string(start, length)
  _access(start, length)
end

#_6b_ascii(ord) ⇒ String

Convert 6-bit ascii to a character, according to catb.org/gpsd/AIVDM.html#_ais_payload_data_types

Parameters:

  • ord (Integer)

    The 6-bit ascii code

Returns:

  • (String)

    the character for that code



41
42
43
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 41

def _6b_ascii(ord)
  '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !"#$%&\'()*+,-./0123456789:;<=>?'[ord]
end

#_6b_boolean(start, _) ⇒ bool Also known as: _b

Get the value of a bit in the payload

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • _ (Integer)

    Doesn’t matter. Here so signatures match; we hard-code 1 because it’s 1 bit.

Returns:

  • (bool)


137
138
139
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 137

def _6b_boolean(start, _)
  _access(start, 1) { |bits| bits.to_i == 1 }
end

#_6b_integer(start, length) ⇒ Integer Also known as: _i

Returns an integer value.

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (Integer)

    an integer value



109
110
111
112
113
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 109

def _6b_integer(start, length)
  # MSB is 1 for negative
  twoc = _6b_twoscomplement(start, length)
  twoc && twoc * (@payload_bitstring[start] == 0 ? 1 : -1)
end

#_6b_integer_scaled(start, length, decimal_places) ⇒ Integer Also known as: _I

scale an integer by dividing it by 10^decimal_places

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

  • decimal_places (Integer)

    The power of ten to use in scaling down the result

Returns:

  • (Integer)

    an integer value



120
121
122
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 120

def _6b_integer_scaled(start, length, decimal_places)
  _6b_integer(start, length).to_f / (10 ** decimal_places)
end

#_6b_string(start, length) ⇒ String

pull out 6b chunks from the payload, then convert those to their more familar characters

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (String)


61
62
63
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 61

def _6b_string(start, length)
  _bit_slices(start, length, 6).to_a.map(&:join).map { |x| _6b_ascii(x.to_i(2)) }.join
end

#_6b_string_nullterminated(start, length) ⇒ String Also known as: _t

convert a 6b string but trim off the 0s (‘@’)

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (String)


85
86
87
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 85

def _6b_string_nullterminated(start, length)
  _6b_string(start, length).split("@", 2)[0]
end

#_6b_twoscomplement(start, length) ⇒ Integer

perform a twos complement operation on part of the payload

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (Integer)

    an integer value



101
102
103
104
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 101

def _6b_twoscomplement(start, length)
  # two's complement: flip bits, then add 1
  _access(start, length) { |bits| bits.tr("01", "10").to_i(2) + 1 }
end

#_6b_unsigned_integer(start, length) ⇒ Integer Also known as: _u, _e

directly convert a string to a binary number as you’d read it

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (Integer)

    an unsigned integer value



93
94
95
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 93

def _6b_unsigned_integer(start, length)
  _access(start, length) { |bits| bits.to_i(2) }
end

#_6b_unsigned_integer_scaled(start, length, decimal_places) ⇒ Integer Also known as: _U

scale an unsigned integer by dividing it by 10^decimal_places

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

  • decimal_places (Integer)

    The power of ten to use in scaling the result

Returns:

  • (Integer)

    an integer value



129
130
131
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 129

def _6b_unsigned_integer_scaled(start, length, decimal_places)
  _6b_unsigned_integer(start, length).to_f / (10.0 ** decimal_places)
end

#_8b_data_string(start, length) ⇒ String

pull out 8b chunks from the payload, then convert those to their more familar characters

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (String)


69
70
71
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 69

def _8b_data_string(start, length)
  _bit_slices(start, length, 8).to_a.map(&:join).map { |x| x.to_i(2).chr }.join
end

#_access(start, length) {|String| ... } ⇒ Object

Access part of the payload. If there aren’t bytes, there, return nil else execute a block

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Yields:

  • (String)

    A binary coded string (“010010101” etc)

Returns:

  • Nil or whatever is yielded by the block



51
52
53
54
55
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 51

def _access(start, length)
  part = @payload_bitstring[start, length]
  return nil if part.nil? || part.empty?
  yield part
end

#_bit_slices(start, length, chunk_size) ⇒ Array<String>

Slice a part of the payload into binary chunks of a given size

Parameters:

  • start (Integer)

    The index of the first bit in the payload field

  • length (Integer)

    The number of bits in the payload field

Returns:

  • (Array<String>)

    Strings representing binary (“01010101” etc) for each slice



77
78
79
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 77

def _bit_slices(start, length, chunk_size)
  _access(start, length) { |bits| bits.chars.each_slice(chunk_size) }
end

#get_ship_cargo_type_description(code) ⇒ String

The ship cargo type description lookup table

Parameters:

  • code (Integer)

    The cargo type id

Returns:

  • (String)

    Cargo type description



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb', line 162

def get_ship_cargo_type_description(code)
  case code
  when 0 then return nil
  when 1...19 then return "(future use)"
  when 20 then return "WIG (any)"
  when 21 then return "WIG Hazardous category A"
  when 22 then return "WIG Hazardous category B"
  when 23 then return "WIG Hazardous category C"
  when 24 then return "WIG Hazardous category D"
  when 25...29 then return "WIG (future use)"
  when 30 then return "Fishing"
  when 31 then return "Towing"
  when 32 then return "Towing (large)"
  when 33 then return "Dredging/underwater ops"
  when 34 then return "Diving ops"
  when 35 then return "Military ops"
  when 36 then return "Sailing"
  when 37 then return "Pleasure craft"
  when 38, 39 then return "Reserved"
  when 40 then return "High Speed Craft"
  when 41 then return "HSC Hazardous category A"
  when 42 then return "HSC Hazardous category B"
  when 43 then return "HSC Hazardous category C"
  when 44 then return "HSC Hazardous category D"
  when 45...48 then return "HSC (reserved)"
  when 49 then return "HSC (no additional information)"
  when 50 then return "Pilot Vessel"
  when 51 then return "Search and Rescue Vessel"
  when 52 then return "Tug"
  when 53 then return "Port Tender"
  when 54 then return "Anti-pollution equipment"
  when 55 then return "Law Enforcement"
  when 56, 57 then return "Spare - Local Vessel"
  when 58 then return "Medical Transport"
  when 59 then return "Noncombatant ship according to RR Resolution No. 18"
  when 60 then return "Passenger"
  when 61 then return "Passenger, Hazardous category A"
  when 62 then return "Passenger, Hazardous category B"
  when 63 then return "Passenger, Hazardous category C"
  when 64 then return "Passenger, Hazardous category D"
  when 65..68 then return "Passenger, Reserved for future use"
  when 69 then return "Passenger, No additional information"
  when 70 then return "Cargo"
  when 71 then return "Cargo, Hazardous category A"
  when 72 then return "Cargo, Hazardous category B"
  when 73 then return "Cargo, Hazardous category C"
  when 74 then return "Cargo, Hazardous category D"
  when 75..78 then return "Cargo, Reserved for future use"
  when 79 then return "Cargo, No additional information"
  when 80 then return "Tanker"
  when 81 then return "Tanker, Hazardous category A"
  when 82 then return "Tanker, Hazardous category B"
  when 83 then return "Tanker, Hazardous category C"
  when 84 then return "Tanker, Hazardous category D"
  when 85.88 then return "Tanker, Reserved for future use"
  when 89 then return "Tanker, No additional information"
  when 90 then return "Other Type"
  when 91 then return "Other Type, Hazardous category A"
  when 92 then return "Other Type, Hazardous category B"
  when 93 then return "Other Type, Hazardous category C"
  when 94 then return "Other Type, Hazardous category D"
  when 95..98 then return "Other Type, Reserved for future use"
  when 99 then return "Other Type, no additional information"
  end
end