nmea_plus 1.0.8 → 1.0.9

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -9
  3. data/lib/nmea_plus/ais_message_factory.rb +3 -1
  4. data/lib/nmea_plus/generated_parser/tokenizer.rb +1 -1
  5. data/lib/nmea_plus/message/ais/base_ais.rb +9 -2
  6. data/lib/nmea_plus/message/ais/vdm.rb +8 -2
  7. data/lib/nmea_plus/message/ais/vdm_payload/payload.rb +59 -23
  8. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg.rb +444 -76
  9. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg1.rb +6 -5
  10. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg12.rb +5 -2
  11. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg14.rb +1 -1
  12. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg18.rb +5 -3
  13. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg20.rb +2 -1
  14. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg21.rb +2 -1
  15. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg24.rb +2 -1
  16. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg27.rb +2 -1
  17. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg4.rb +15 -2
  18. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg5.rb +3 -2
  19. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg6.rb +55 -0
  20. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg6d1022f61.rb +122 -0
  21. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg6d235f10.rb +54 -0
  22. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg7.rb +36 -0
  23. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg8.rb +2 -9
  24. data/lib/nmea_plus/message/ais/vdm_payload/vdm_msg9.rb +5 -5
  25. data/lib/nmea_plus/message/base.rb +27 -14
  26. data/lib/nmea_plus/message/nmea/base_nmea.rb +13 -7
  27. data/lib/nmea_plus/message/nmea/bwr.rb +2 -2
  28. data/lib/nmea_plus/message/nmea/dtm.rb +2 -2
  29. data/lib/nmea_plus/message/nmea/gga.rb +2 -2
  30. data/lib/nmea_plus/message/nmea/gll.rb +2 -2
  31. data/lib/nmea_plus/message/nmea/gns.rb +2 -2
  32. data/lib/nmea_plus/message/nmea/gxa.rb +2 -2
  33. data/lib/nmea_plus/message/nmea/hdg.rb +2 -2
  34. data/lib/nmea_plus/message/nmea/rma.rb +3 -3
  35. data/lib/nmea_plus/message/nmea/rmb.rb +2 -2
  36. data/lib/nmea_plus/message/nmea/rmc.rb +3 -3
  37. data/lib/nmea_plus/message/nmea/trf.rb +2 -2
  38. data/lib/nmea_plus/message/nmea/wpl.rb +2 -2
  39. data/lib/nmea_plus/nmea_message_factory.rb +3 -1
  40. data/lib/nmea_plus/version.rb +1 -1
  41. metadata +9 -5
@@ -19,9 +19,10 @@ module NMEAPlus
19
19
  # @!parse attr_reader :rate_of_turn
20
20
  # @return [Float]
21
21
  def rate_of_turn
22
- ret = _i(42, 8)
22
+ ret = _i(42, 8) # spec is wrong, we don't use I3
23
23
  return nil if ret == -128
24
- (_I(42, 8, 3) / 4.733)**2
24
+ negative = ret < 0
25
+ (ret / 4.733)**2 * (negative ? -1 : 1)
25
26
  end
26
27
 
27
28
  payload_reader :speed_over_ground, 50, 10, :_U, 10
@@ -64,13 +65,13 @@ module NMEAPlus
64
65
 
65
66
  end
66
67
 
67
- # Position report class A, which is really {VDMMsgCNB}
68
+ # AIS Type 1: Position report class A, which is really {VDMMsgCNB}
68
69
  class VDMMsg1 < VDMMsgCNB; end
69
70
 
70
- # Position report class A, which is really {VDMMsgCNB}
71
+ # AIS Type 2: Position report class A, which is really {VDMMsgCNB}
71
72
  class VDMMsg2 < VDMMsgCNB; end
72
73
 
73
- # Position report class A, which is really {VDMMsgCNB}
74
+ # AIS Type 3: Position report class A, which is really {VDMMsgCNB}
74
75
  class VDMMsg3 < VDMMsgCNB; end
75
76
  end
76
77
  end
@@ -4,15 +4,18 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 12: Addressed Safety-Related Message
7
+ # AIS Type 12: Addressed Safety-Related Message
8
8
  class VDMMsg12 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
9
 
10
10
  payload_reader :sequence_number, 38, 2, :_u
11
11
  payload_reader :destination_mmsi, 40, 30, :_u
12
12
  payload_reader :retransmit?, 70, 1, :_b
13
13
 
14
- # Safety message
14
+ # Safety message as a null-terminated string
15
15
  payload_reader :text, 72, 936, :_t
16
+
17
+ # Safety message as data
18
+ payload_reader :data, 72, 936, :_tt
16
19
  end
17
20
  end
18
21
  end
@@ -4,7 +4,7 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 14: Safety-Related Broadcast Message
7
+ # AIS Type 14: Safety-Related Broadcast Message
8
8
  class VDMMsg14 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
9
 
10
10
  # Safety message
@@ -6,6 +6,8 @@ module NMEAPlus
6
6
  module VDMPayload
7
7
 
8
8
  # Base class for "Class B CS Position Report" messages (18 and 19)
9
+ # @see NMEAPlus::Message::AIS::VDMPayload::VDMMsg18
10
+ # @see NMEAPlus::Message::AIS::VDMPayload::VDMMsg19
9
11
  class VDMMsgClassBCSPosition < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
10
12
 
11
13
  payload_reader :speed_over_ground, 46, 10, :_U, 10
@@ -18,7 +20,7 @@ module NMEAPlus
18
20
 
19
21
  end
20
22
 
21
- # Type 18: Standard Class B CS Position Report
23
+ # AIS Type 18: Standard Class B CS Position Report
22
24
  class VDMMsg18 < VDMMsgClassBCSPosition
23
25
  payload_reader :cs_unit?, 141, 1, :_b
24
26
  payload_reader :display?, 142, 1, :_b
@@ -29,7 +31,7 @@ module NMEAPlus
29
31
  payload_reader :raim?, 147, 1, :_b
30
32
  end
31
33
 
32
- # Type 19: Extended Class B CS Position Report
34
+ # AIS Type 19: Extended Class B CS Position Report
33
35
  class VDMMsg19 < VDMMsgClassBCSPosition
34
36
  payload_reader :name, 143, 120, :_t
35
37
  payload_reader :ship_cargo_type, 263, 8, :_e
@@ -39,7 +41,7 @@ module NMEAPlus
39
41
  payload_reader :ship_dimension_to_starboard, 295, 6, :_u
40
42
  payload_reader :epfd_type, 301, 4, :_e
41
43
  payload_reader :raim?, 305, 1, :_b
42
- payload_reader :dte?, 306, 1, :_b
44
+ payload_reader :dte_ready?, 306, 1, :_nb
43
45
  payload_reader :assigned?, 307, 1, :_b
44
46
 
45
47
  # @!parse attr_reader :ship_cargo_type_description
@@ -4,7 +4,8 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 20 Data Link Management Message
7
+
8
+ # AIS Type 20 Data Link Management Message
8
9
  class VDMMsg20 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
10
  payload_reader :offset1, 40, 12, :_u
10
11
  payload_reader :reserved_slots1, 52, 4, :_u
@@ -4,7 +4,8 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 21: Aid-to-Navigation Report
7
+
8
+ # AIS Type 21: Aid-to-Navigation Report
8
9
  class VDMMsg21 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
10
 
10
11
  # TODO: Navaid type descriptions (there are 32 of them)
@@ -4,7 +4,8 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 24: Static Data Report
7
+
8
+ # AIS Type 24: Static Data Report
8
9
  class VDMMsg24 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
10
 
10
11
  payload_reader :part_number, 38, 2, :_u
@@ -4,7 +4,8 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 27: Long Range AIS Broadcast message
7
+
8
+ # AIS Type 27: Long Range AIS Broadcast message
8
9
  class VDMMsg27 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
10
 
10
11
  payload_reader :position_10m_accuracy?, 38, 1, :_b
@@ -4,8 +4,11 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 4: Base Station Report
8
- class VDMMsg4 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
7
+
8
+ # Base class for station reports
9
+ # @see VDMMsg4
10
+ # @see VDMMsg11
11
+ class VDMMsgStationReport < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
12
 
10
13
  # @!parse attr_reader :current_time
11
14
  # @return [Time] current time
@@ -25,6 +28,16 @@ module NMEAPlus
25
28
  payload_reader :raim?, 148, 1, :_b
26
29
 
27
30
  end
31
+
32
+ # AIS Type 4: Base Station Report
33
+ # @see VDMMsgStationReport
34
+ class VDMMsg4 < VDMMsgStationReport; end
35
+
36
+ # AIS Type 11: UTC/Date Response
37
+ # According to the unoffical spec: "Identical to message 4, with the semantics of a response to inquiry."
38
+ # @see VDMMsgStationReport
39
+ class VDMMsg11 < VDMMsgStationReport; end
40
+
28
41
  end
29
42
  end
30
43
  end
@@ -4,7 +4,8 @@ module NMEAPlus
4
4
  module Message
5
5
  module AIS
6
6
  module VDMPayload
7
- # Type 5: Static and Voyage Related Data
7
+
8
+ # AIS Type 5: Static and Voyage Related Data
8
9
  class VDMMsg5 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
9
10
 
10
11
  payload_reader :ais_version, 38, 2, :_u
@@ -32,7 +33,7 @@ module NMEAPlus
32
33
 
33
34
  payload_reader :static_draught, 294, 8, :_U, 10
34
35
  payload_reader :destination, 302, 120, :_t
35
- payload_reader :dte?, 422, 1, :_b
36
+ payload_reader :dte_ready?, 422, 1, :_nb
36
37
 
37
38
  # @!parse attr_reader :ship_cargo_type_description
38
39
  # @return [String] Cargo type description
@@ -0,0 +1,55 @@
1
+ require_relative 'vdm_msg'
2
+ require_relative 'vdm_msg6d235f10'
3
+ require_relative 'vdm_msg6d1022f61'
4
+
5
+ module NMEAPlus
6
+ module Message
7
+ module AIS
8
+ module VDMPayload
9
+
10
+ # AIS Type 6: Binary Addressed Message
11
+ class VDMMsg6 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
12
+
13
+ payload_reader :sequence_number, 38, 2, :_u
14
+ payload_reader :destination_mmsi, 40, 30, :_u
15
+ payload_reader :retransmitted?, 70, 1, :_b
16
+ payload_reader :designated_area_code, 72, 10, :_u
17
+ payload_reader :functional_id, 82, 6, :_u
18
+
19
+ # Dynamic Payload containing fields for the appropriate message 6 subtype.
20
+ # This is a factory method for the container class
21
+ # @!parse attr_reader :dp
22
+ # @return [VDMPayload::VDMMsg::VDMMsg8DynamicPayload]
23
+ def dp
24
+ ret = _dynamic_payload_container
25
+ ret.payload_bitstring = payload_bitstring
26
+ ret.fill_bits = fill_bits
27
+ ret
28
+ end
29
+
30
+ # Dynamically calculate what message subtype to use
31
+ # which depends on the designated_area_code and functional_id
32
+ def _dynamic_payload_container
33
+ class_identifier = "NMEAPlus::Message::AIS::VDMPayload::VDMMsg6d#{designated_area_code}f#{functional_id}"
34
+ ret = _object_by_name(class_identifier)
35
+ return ret unless ret.nil?
36
+
37
+ _object_by_name("NMEAPlus::Message::AIS::VDMPayload::VDMMsg8Undefined") # generic
38
+ end
39
+
40
+ end
41
+
42
+ # Base class for dynamic payloads (subtypes) of AIS VDM message 6
43
+ class VDMMsg6DynamicPayload < NMEAPlus::Message::AIS::VDMPayload::Payload; end
44
+
45
+ # Placeholder for undefined message 8 payload subtypes
46
+ class VDMMsg6Undefined < NMEAPlus::Message::AIS::VDMPayload::VDMMsg6DynamicPayload
47
+ payload_reader :application_data_2b, 56, 952, :_d
48
+ payload_reader :application_data_6b, 56, 952, :_6b_string
49
+ payload_reader :application_data_8b, 56, 952, :_8b_data_string
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,122 @@
1
+ require_relative 'vdm_msg'
2
+
3
+ module NMEAPlus
4
+ module Message
5
+ module AIS
6
+ module VDMPayload
7
+
8
+ # Type 6: Binary Addressed Message Subtype: Sealite SL125 Lantern or 155 Apollo Lantern
9
+ # This message has an ascii CSV payload wrapped in an armored AIS payload, wrapped in the NMEA CSV payload.
10
+ class VDMMsg6d1022f61 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
11
+
12
+ def initialize
13
+ super
14
+ @fields = []
15
+ end
16
+
17
+ # The raw payload: comma separated ascii fields
18
+ # @return [String]
19
+ payload_reader :application_data, 88, 384, :_T # not actually sure if 384 is enough length
20
+
21
+ # Override default bitstring setting to automatically load up a fields array for easier access
22
+ def payload_bitstring=(val)
23
+ super
24
+ @fields = application_data.split(",")
25
+ end
26
+
27
+ # Return a bit from the 8 bits in field 0
28
+ # @param position [Integer] the bit position: 0=MSB, 7=LSB
29
+ # @return [bool]
30
+ def _field0_bit(position)
31
+ return nil if @fields[1].nil?
32
+ mask = 1 << (7 - position)
33
+ @fields[0].hex & mask == mask
34
+ end
35
+
36
+ # Enable a shortcut syntax for bit field attributes, in the style of `attr_accessor` metaprogramming.
37
+ # This is used to create a named field pointing to a specific bit in the first field of the payload
38
+ # @param name [String] What the accessor will be called
39
+ # @param position [Integer] The bit position in this field
40
+ # @return [void]
41
+ # @macro [attach] bit_reader
42
+ # @!attribute [r] $1
43
+ # @return [bool] The value in bit $2 of the status field
44
+ def self.bit_reader(name, position)
45
+ self.class_eval("def #{name};_field0_bit(#{position});end")
46
+ end
47
+
48
+ bit_reader :supply_fail?, 0
49
+ bit_reader :gps_off_station?, 1
50
+ bit_reader :light_sensor_dark?, 2
51
+ bit_reader :gps_sync_valid?, 3
52
+ bit_reader :gps_valid?, 4
53
+ bit_reader :temperature_sensor_hot?, 5
54
+ bit_reader :battery_flat?, 6
55
+ bit_reader :battery_low?, 7
56
+
57
+ # @!parse attr_reader :operation_mode
58
+ # @return [Integer]
59
+ def operation_mode
60
+ return nil if @fields[1].nil?
61
+ @fields[1].hex >> 6
62
+ end
63
+
64
+ # A human-readable description of the operation mode
65
+ # @!parse attr_reader :operation_mode_description
66
+ # @return [String]
67
+ def operation_mode_description
68
+ case operation_mode
69
+ when 1 then "Standby"
70
+ when 2 then "Always on"
71
+ else
72
+ "description n/a" # TODO
73
+ end
74
+ end
75
+
76
+ # This field seems to be a 0-100% value encoded as 6-bit.
77
+ # The test cases seem to indicate that it is offset by +1.5625, which may mean that "3F" is a special case.
78
+ # But I have no data on that.
79
+ # @!parse attr_reader :intensity_percent
80
+ # @return [Float]
81
+ def intensity_percent
82
+ return nil if @fields[1].nil?
83
+ (1 + (@fields[1].hex & "3F".hex)) * (100.0 / 2**6)
84
+ end
85
+
86
+ # A vendor-specific code
87
+ # @!parse attr_reader :flash_code
88
+ # @return [String]
89
+ def flash_code
90
+ @fields[2].nil? ? nil : @fields[2].hex
91
+ end
92
+
93
+ # The battery voltage in volts
94
+ # @!parse attr_reader :battery_voltage
95
+ # @return [Float]
96
+ def battery_voltage
97
+ @fields[3].nil? ? nil : @fields[3].to_f
98
+ end
99
+
100
+ # Latitude
101
+ # @!parse attr_reader :latitude
102
+ # @return [Float]
103
+ def latitude
104
+ parts = @fields[4]
105
+ return nil if parts.nil?
106
+ NMEAPlus::Message::Base.degrees_minutes_to_decimal(parts[0..-1], parts[-1])
107
+ end
108
+
109
+ # Longitude
110
+ # @!parse attr_reader :longitude
111
+ # @return [Float]
112
+ def longitude
113
+ parts = @fields[5]
114
+ return nil if parts.nil?
115
+ NMEAPlus::Message::Base.degrees_minutes_to_decimal(parts[0..-1], parts[-1])
116
+ end
117
+
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'vdm_msg'
2
+
3
+ module NMEAPlus
4
+ module Message
5
+ module AIS
6
+ module VDMPayload
7
+
8
+ # Type 6: Binary Addressed Message Subtype: GLA Aid to Navigation Monitoring Data
9
+ class VDMMsg6d235f10 < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
10
+
11
+ payload_reader :analog_internal, 88, 10, :_U, 20, 0
12
+ payload_reader :analog_external1, 98, 10, :_U, 20, 0
13
+ payload_reader :analog_external2, 108, 10, :_U, 20, 0
14
+ payload_reader :racon_status, 118, 2, :_u
15
+
16
+ # RACON status description
17
+ # @!parse attr_reader :racon_status_description
18
+ # @return [String] RACON status description
19
+ def racon_status_description
20
+ case racon_status
21
+ when 0 then "no RACON installed"
22
+ when 1 then "RACON not monitored"
23
+ when 2 then "RACON operational"
24
+ when 3 then "RACON ERROR"
25
+ end
26
+ end
27
+
28
+ payload_reader :racon_light_status, 120, 2, :_u
29
+
30
+ # @!parse attr_reader :racon_light_status_description
31
+ # @return [String] RACON light status description
32
+ def racon_light_status_description
33
+ case racon_light_status
34
+ when 0 then "no light or monitoring"
35
+ when 1 then "ON"
36
+ when 2 then "OFF"
37
+ when 3 then "ERROR"
38
+ end
39
+ end
40
+
41
+ payload_reader :racon_alarm?, 122, 1, :_b
42
+ payload_reader :digital_input7?, 123, 1, :_b
43
+ payload_reader :digital_input6?, 124, 1, :_b
44
+ payload_reader :digital_input5?, 125, 1, :_b
45
+ payload_reader :digital_input4?, 126, 1, :_b
46
+ payload_reader :digital_input3?, 127, 1, :_b
47
+ payload_reader :digital_input2?, 128, 1, :_b
48
+ payload_reader :digital_input1?, 129, 1, :_b
49
+ payload_reader :digital_input0?, 130, 1, :_b
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'vdm_msg'
2
+
3
+ module NMEAPlus
4
+ module Message
5
+ module AIS
6
+ module VDMPayload
7
+
8
+ # Base class for binary acknowledgement messages
9
+ # @see VDMMsg7
10
+ # @see VDMMsg13
11
+ class VDMMsgBinaryAcknowledgement < NMEAPlus::Message::AIS::VDMPayload::VDMMsg
12
+
13
+ payload_reader :ack1_mmsi, 40, 30, :_u
14
+ payload_reader :ack1_sequence_number, 70, 2, :_u
15
+ payload_reader :ack2_mmsi, 72, 30, :_u
16
+ payload_reader :ack2_sequence_number, 102, 2, :_u
17
+ payload_reader :ack3_mmsi, 104, 30, :_u
18
+ payload_reader :ack3_sequence_number, 134, 2, :_u
19
+ payload_reader :ack4_mmsi, 136, 30, :_u
20
+ payload_reader :ack4_sequence_number, 166, 2, :_u
21
+
22
+ end
23
+
24
+ # AIS Type 7: Binary Acknowledge
25
+ # @see VDMMsgBinaryAcknowledgement
26
+ class VDMMsg7 < VDMMsgBinaryAcknowledgement; end
27
+
28
+ # AIS Type 13: Safety-Related Acknowledgement
29
+ # According to the unoffical spec: "The message layout is identical to a type 7 Binary Acknowledge."
30
+ # @see VDMMsgBinaryAcknowledgement
31
+ class VDMMsg13 < VDMMsgBinaryAcknowledgement; end
32
+
33
+ end
34
+ end
35
+ end
36
+ end