@@ -28,6 +28,7 @@ void Ship::reset()
2828 path_ptr = -1 ;
2929
3030 mmsi = count = msg_type = shiptype = group_mask = 0 ;
31+ type_ttl = 0 ;
3132 flags.reset ();
3233
3334 heading = HEADING_UNDEFINED ;
@@ -68,6 +69,130 @@ void Ship::reset()
6869 msg.clear ();
6970}
7071
72+ // Which fields each message type can refresh, indexed by type; F_SIGNAL is in every
73+ // row as reception data comes with every message. A missing field here expires
74+ // early, a spurious one never expires.
75+ static const uint32_t TYPE_FIELDS [MAX_MSG_TYPE + 1 ] = {
76+ 0 , // 0 does not exist
77+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_HEADING | F_STATUS | F_MANEUVER | F_RECV_STATIONS , // 1 position report
78+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_HEADING | F_STATUS | F_MANEUVER | F_RECV_STATIONS , // 2 position report
79+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_HEADING | F_STATUS | F_MANEUVER | F_RECV_STATIONS , // 3 position report
80+ F_SIGNAL | F_LATLON | F_RECV_STATIONS , // 4 base station report
81+ F_SIGNAL | F_VOYAGE | F_STATIC , // 5 static and voyage
82+ F_SIGNAL | F_LATLON | F_OFF_POSITION | F_STATIC | F_VOYAGE , // 6 addressed binary, buoy/AtoN monitor payloads
83+ F_SIGNAL , // 7 binary acknowledge
84+ F_SIGNAL | F_STATIC | F_VOYAGE | F_OFF_POSITION , // 8 broadcast binary, inland static and AtoN monitor payloads
85+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_ALTITUDE , // 9 SAR aircraft
86+ F_SIGNAL , // 10 UTC inquiry
87+ F_SIGNAL | F_LATLON | F_RECV_STATIONS , // 11 UTC response
88+ F_SIGNAL , // 12 addressed safety
89+ F_SIGNAL , // 13 safety acknowledge
90+ F_SIGNAL , // 14 broadcast safety
91+ F_SIGNAL , // 15 interrogation
92+ F_SIGNAL , // 16 assignment
93+ F_SIGNAL , // 17 DGNSS broadcast
94+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_HEADING | F_COMM_CAP , // 18 class B position
95+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_HEADING | F_STATIC , // 19 class B extended
96+ F_SIGNAL , // 20 link management
97+ F_SIGNAL | F_LATLON | F_OFF_POSITION | F_STATIC , // 21 aid to navigation
98+ F_SIGNAL , // 22 channel management
99+ F_SIGNAL , // 23 group assignment
100+ F_SIGNAL | F_STATIC , // 24 class B static
101+ F_SIGNAL | F_LATLON | F_OFF_POSITION | F_STATIC | F_VOYAGE , // 25 single slot binary, same payloads as 6/8
102+ F_SIGNAL | F_LATLON | F_OFF_POSITION | F_STATIC | F_VOYAGE | F_RECV_STATIONS , // 26 multiple slot binary, same payloads as 6/8
103+ F_SIGNAL | F_LATLON | F_SPEED_COG | F_STATUS , // 27 long range
104+ F_SIGNAL | F_LATLON | F_STATIC , // 28 AtoN report
105+ };
106+
107+ void Ship::decayAndExpire ()
108+ {
109+ if (~type_ttl & msg_type)
110+ {
111+ uint32_t supported = 0 ;
112+ for (int t = 1 ; t <= MAX_MSG_TYPE ; t++)
113+ if (type_ttl & (1 << t))
114+ supported |= TYPE_FIELDS [t];
115+
116+ clearFields (~supported);
117+
118+ msg_type = type_ttl;
119+ setType ();
120+ }
121+
122+ type_ttl = 0 ;
123+ }
124+
125+ void Ship::clearFields (uint32_t doomed)
126+ {
127+ if (doomed & F_LATLON )
128+ {
129+ lat = LAT_UNDEFINED ;
130+ lon = LON_UNDEFINED ;
131+ distance = DISTANCE_UNDEFINED ;
132+ angle = ANGLE_UNDEFINED ;
133+ setApproximate (0 );
134+ setValidated (0 );
135+ setRAIM (0 );
136+ setAssigned (0 );
137+ }
138+ if (doomed & F_SPEED_COG )
139+ {
140+ speed = SPEED_UNDEFINED ;
141+ cog = COG_UNDEFINED ;
142+ }
143+ if (doomed & F_HEADING )
144+ heading = HEADING_UNDEFINED ;
145+ if (doomed & F_STATUS )
146+ status = STATUS_UNDEFINED ;
147+ if (doomed & F_MANEUVER )
148+ setManeuver (0 );
149+ if (doomed & F_ALTITUDE )
150+ altitude = ALT_UNDEFINED ;
151+ if (doomed & F_RECV_STATIONS )
152+ received_stations = RECEIVED_STATIONS_UNDEFINED ;
153+ if (doomed & F_OFF_POSITION )
154+ setOffPosition (0 );
155+ if (doomed & F_VOYAGE )
156+ {
157+ memset (destination, 0 , sizeof (destination));
158+ month = ETA_MONTH_UNDEFINED ;
159+ day = ETA_DAY_UNDEFINED ;
160+ hour = ETA_HOUR_UNDEFINED ;
161+ minute = ETA_MINUTE_UNDEFINED ;
162+ draught = DRAUGHT_UNDEFINED ;
163+ }
164+ if (doomed & F_STATIC )
165+ {
166+ memset (shipname, 0 , sizeof (shipname));
167+ memset (callsign, 0 , sizeof (callsign));
168+ memset (vendorid, 0 , sizeof (vendorid));
169+ memset (vin, 0 , sizeof (vin));
170+ unit_model = unit_serial = -1 ;
171+ IMO = IMO_UNDEFINED ;
172+ shiptype = 0 ;
173+ to_port = to_bow = to_starboard = to_stern = DIMENSION_UNDEFINED ;
174+ setDTE (0 );
175+ setVirtualAid (0 );
176+ }
177+ if (doomed & F_COMM_CAP )
178+ {
179+ setCSUnit (0 );
180+ setDisplay (0 );
181+ setDSC (0 );
182+ setBand (0 );
183+ setMsg22 (0 );
184+ }
185+ if (doomed & F_SIGNAL )
186+ {
187+ ppm = PPM_UNDEFINED ;
188+ level = LEVEL_UNDEFINED ;
189+ setRepeat (0 );
190+ memset (country_code, 0 , sizeof (country_code));
191+ clearOpChannels ();
192+ msg.clear ();
193+ }
194+ }
195+
71196std::string getSprite (const Ship *ship)
72197{
73198 std::string shipofs = (ship->speed != SPEED_UNDEFINED && ship->speed > 0.5 ) ? " <y>88</y><w>20</w><h>20</h>" : " <y>68</y><w>20</w><h>20</h>" ;
@@ -168,7 +293,16 @@ int Ship::getMMSItype()
168293 {
169294 return MMSI_SARTEPIRB ;
170295 }
171- if (msg_type & ATON_MASK || (mmsi >= 990000000 && mmsi <= 999999999 ))
296+ // the number outranks the message types: a bad decode must not reclassify a station
297+ if (mmsi >= 990000000 && mmsi <= 999999999 )
298+ {
299+ return MMSI_ATON ;
300+ }
301+ if (mmsi < 9000000 )
302+ {
303+ return MMSI_BASESTATION ;
304+ }
305+ if (msg_type & ATON_MASK )
172306 {
173307 return MMSI_ATON ;
174308 }
@@ -180,7 +314,7 @@ int Ship::getMMSItype()
180314 {
181315 return MMSI_CLASS_B ;
182316 }
183- if (msg_type & BASESTATION_MASK || (mmsi < 9000000 ) )
317+ if (msg_type & BASESTATION_MASK )
184318 {
185319 return MMSI_BASESTATION ;
186320 }
0 commit comments