nmea_plus 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
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