class NMEAPlus::Message::AIS::VDMPayload::Payload
Basic tools for interpreting the armored (binary) payload encoding of AIS
. This class provides convenience functions for accessing the fields as the appropriate data type, as well as logic for AIS
bit-level formats
Attributes
@return [Integer] The number of padding characters required to bring the payload to a 6 bit boundary
@return [String] The raw “armored payload” in the original message
Public Class Methods
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 35 def self.payload_reader(name, start_bit, length, formatter, fmt_arg = nil, fmt_arg2 = nil, fmt_arg3 = nil) args = [start_bit, length] args << fmt_arg unless fmt_arg.nil? args << fmt_arg2 unless fmt_arg2.nil? args << fmt_arg3 unless fmt_arg3.nil? define_method(name) { self.send(formatter, *args) } end
Enable a shortcut syntax for AIS
payload attributes, in the style of ‘attr_accessor` metaprogramming. This is used to create a named field pointing to a specific bit range in the payload, applying a specific formatting function with up to 3 arguments as necessary @param name [String] What the accessor will be called @param start_bit [Integer] The index of first bit of this field in the payload @param length [Integer] The number of bits in this field @param formatter [Symbol] The symbol for the formatting function to apply to the field (optional) @param fmt_arg Any argument necessary for the formatting function @param fmt_arg2 Any other argument necessary for the formatting function @param fmt_arg3 Any other argument necessary for the formatting function @return [void] @macro [attach] payload_reader
@!attribute [r] $1 @return The field defined by the $3 bits starting at payload bit $2, formatted with the function {#$4}($5, $6, $7)
Public Instance Methods
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 223 def _2b_data_string(start, length) _access(start, length) end
Return a string representing binary digits. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @return [String] e.g. “0101010101011000”
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 56 def _6b_ascii(ord) '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !"#$%&\'()*+,-./0123456789:;<=>?'[ord] end
Convert 6-bit ascii to a character, according to catb.org/gpsd/AIVDM.html#_ais_payload_data_types @param ord [Integer] The 6-bit ascii code @return [String] the character for that code
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 205 def _6b_boolean(start, _) _access(start, 1) { |bits| bits.to_i == 1 } end
Get the value of a bit in the payload. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param _ [Integer] Doesn’t matter. Here so signatures match; we hard-code 1 because it’s 1 bit. @return [bool]
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 128 def _6b_integer(start, length, equiv_nil = nil) case @payload_bitstring[start] when "0" _6b_unsigned_integer(start, length, equiv_nil) when "1" # MSB is 1 for negative # two's complement: flip bits, then add 1 ret = _access(start, length) { |bits| (bits.tr("01", "10").to_i(2) + 1) * -1 } return nil if ret == equiv_nil ret end end
perform a twos complement operation on part of the payload. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @param equiv_nil [Integer] If applicable, the value for this field that would indicate nil @return [Integer] an integer value
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 149 def _6b_integer_scaled(start, length, denominator, equiv_nil = nil) ret = _6b_integer(start, length, equiv_nil) return nil if ret.nil? ret.to_f / denominator end
scale an integer by dividing it by a denominator. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @param denominator [Integer] The divisor to use in scaling down the result @param equiv_nil [Integer] If applicable, the value for this field that would indicate nil @return [Integer] an integer value
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 178 def _6b_integer_scaled_shifted(start, length, denominator, shift, equiv_nil = nil) ret = _6b_integer_scaled(start, length, denominator, equiv_nil) return nil if ret.nil? ret + shift end
scale an integer by dividing it by a denominator. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @param denominator [Integer] The divisor to use in scaling down the result @param shift [Float] the amount to shift (up) the result by @param equiv_nil [Integer] If applicable, the value for this field that would indicate nil @return [Integer] an integer value
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 214 def _6b_negated_boolean(start, _) !_6b_boolean(start, 1) end
Get the flipped value of a bit in the payload. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param _ [Integer] Doesn’t matter. Here so signatures match; we hard-code 1 because it’s 1 bit. @return [bool]
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 78 def _6b_string(start, length) _bit_slices(start, length, 6).to_a.map(&:join).map { |x| _6b_ascii(x.to_i(2)) }.join end
pull out 6b chunks from the payload, then convert those to their more familar characters This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @return [String]
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 105 def _6b_string_nullterminated(start, length) _6b_string(start, length).split("@", 2)[0] end
convert a 6b string but trim off the 0s (‘@’). This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @return [String]
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 115 def _6b_unsigned_integer(start, length, equiv_nil = nil) ret = _access(start, length) { |bits| bits.to_i(2) } return nil if ret == equiv_nil ret end
directly convert a string to a binary number as you’d read it. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @param equiv_nil [Integer] If applicable, the value for this field that would indicate nil @return [Integer] an unsigned integer value
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 163 def _6b_unsigned_integer_scaled(start, length, denominator, equiv_nil = nil) ret = _6b_unsigned_integer(start, length, equiv_nil) return nil if ret.nil? ret.to_f / denominator end
scale an unsigned integer by dividing it by a denominator. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @param denominator [Integer] The divisor to use in scaling down the result @param equiv_nil [Integer] If applicable, the value for this field that would indicate nil @return [Integer] an integer value
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 193 def _6b_unsigned_integer_scaled_shifted(start, length, denominator, shift, equiv_nil = nil) ret = _6b_unsigned_integer_scaled(start, length, denominator, equiv_nil) return nil if ret.nil? ret + shift end
scale an unsigned integer by dividing it by a denominator. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @param denominator [Integer] The divisor to use in scaling down the result @param shift [Float] the amount to shift (up) the result by @param equiv_nil [Integer] If applicable, the value for this field that would indicate nil @return [Integer] an integer value
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 87 def _8b_data_string(start, length) _bit_slices(start, length, 8).to_a.map(&:join).map { |x| x.to_i(2).chr }.join end
pull out 8b chunks from the payload, then convert those to their more familar characters. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @return [String]
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 66 def _access(start, length) part = @payload_bitstring[start, length] return nil if part.nil? || part.empty? block_given? ? (yield part) : part end
Access part of the payload. If there aren’t bytes, there, return nil. Else, execute a block @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @return Nil or whatever is yielded by the block @yield [String] A binary coded string (“010010101” etc)
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 96 def _bit_slices(start, length, chunk_size) _access(start, length) { |bits| bits.chars.each_slice(chunk_size) } end
Slice a part of the payload into binary chunks of a given size. This function is meant to be passed as a formatter to {payload_reader}. @param start [Integer] The index of the first bit in the payload field @param length [Integer] The number of bits in the payload field @return [Array<String>] Strings representing binary (“01010101” etc) for each slice
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 249 def _get_date_mdhm(month, day, hour, minute) now = Time.now month = now.month if month.nil? return nil if month.zero? return nil if day.zero? return nil if hour == 24 return nil if minute == 60 # try to be smart about picking a year rollover = 0 rollover = 1 if now.month > month rollover = -1 if now.month == 1 && month == 12 Time.new(now.year + rollover, month, day, hour, minute, 0, "+00:00") end
Get the date value of a month/day/hour/minute package This function is meant to be used for commonly-found date operations in which year, seconds, and timezone are not specified. @param month [Integer] the month number, 1-indexed, optional @param day [Integer] the day number, 1-indexed @param hour [Integer] the hour number, 0-indexed @param minute [Integer] the minute number, 0-indexed
Source
# File lib/nmea_plus/message/ais/vdm_payload/payload.rb, line 47 def _object_by_name(class_identifier) Object::const_get(class_identifier).new rescue ::NameError nil end
Return an object by its class name, or nil if it isn’t defined @param class_identifier [String] The ruby class identifier @return [Object] An object of the given class
use shorthand for data types as defined in catb.org/gpsd/AIVDM.html