OpenCPN Partial API docs
Loading...
Searching...
No Matches
ais_target_data.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 *
5 ***************************************************************************
6 * Copyright (C) 2010 by David S. Register *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22 ***************************************************************************
23 */
24#include <unordered_map>
25
26#include <wx/datetime.h>
27#include <wx/intl.h>
28#include <wx/string.h>
29
31#include "model/ais_target_data.h"
32#include "model/config_vars.h"
33#include "model/navutil_base.h"
34#include "model/own_ship.h"
35
36static std::unordered_map<int, wxString> s_ERI_hash;
37
38void make_hash_ERI(int key, const wxString &description) {
39 s_ERI_hash[key] = description;
40}
41
42void clear_hash_ERI() { s_ERI_hash.clear(); }
43
44static wxString FormatTimeAdaptive(int seconds) {
45 int m = seconds / 60;
46 if (seconds < 100)
47 return wxString::Format(_T("%3ds"), seconds);
48 else if (seconds < 3600) {
49 int m = seconds / 60;
50 int s = seconds % 60;
51 return wxString::Format(_T("%2dmin %02ds"), m, s);
52 }
53 int h = seconds / 3600;
54 m -= h * 60;
55 return wxString::Format(_T("%2dh %02dmin"), h, m);
56}
57
58static wxString html_escape(const wxString &src) {
59 // Escape &, <, > as well as single and double quotes for HTML.
60 wxString ret = src;
61
62 ret.Replace(_T("<"), _T("&lt;"));
63 ret.Replace(_T(">"), _T("&gt;"));
64
65 // only < and > in 6 bits AIS ascii
66 // ret.Replace(_T("\""), _T("&quot;"));
67 // ret.Replace(_T("&"), _T("&amp;"));
68 // ret.Replace(_T("'"), _T("&#39;"));
69
70 // Do we care about multiple spaces?
71 // ret.Replace(_T(" "), _T("&nbsp;"));
72 return ret;
73}
74
75wxString trimAISField(char *data) {
76 // Clip any unused characters (@) from data
77
78 wxString field = wxString::From8BitData(data);
79 while (field.Right(1) == '@' || field.Right(1) == ' ') field.RemoveLast();
80
81 // And remove any leading spaces to properly sort and display
82 field.Trim(false);
83
84 return field;
85}
86
87wxString ais_get_status(int index) {
88 static const wxString ais_status[] = {
89 _("Underway using Engine"),
90 _("At Anchor"),
91 _("Not Under Command"),
92 _("Restricted Manoeuvrability"),
93 _("Constrained by draught"),
94 _("Moored"),
95 _("Aground"),
96 _("Engaged in Fishing"),
97 _("Underway Sailing"),
98 _("High Speed Craft"),
99 _("Wing In Ground Effect"),
100 _("Power-driven vessel towing astern (regional use)"),
101 _("Power-driven vessel pushing ahead or towing alongside (regional use)"),
102 _("Reserved 13"),
103 _("Reserved 14"),
104 _("Undefined"),
105 _("AtoN Virtual"),
106 _("AtoN Virtual (On Position)"),
107 _("AtoN Virtual (Off Position)"),
108 _("AtoN Real"),
109 _("AtoN Real (On Position)"),
110 _("AtoN Real(Off Position)")};
111
112 return ais_status[index];
113}
114
115wxString ais_meteo_get_trend(int tend) {
116 wxString trend = wxEmptyString;
117 if (tend < 3) {
118 if (tend == 0)
119 trend = _("steady");
120 else if (tend == 1)
121 trend = _("decreasing");
122 else if (tend == 2)
123 trend = _("increasing");
124 }
125 return trend;
126}
127
128wxString aisMeteoPrecipType(int precip) {
129 wxString prec = wxEmptyString;
130 switch (precip) {
131 case 0:
132 prec = "Reserved";
133 break;
134 case 1:
135 prec = "Rain";
136 break;
137 case 2:
138 prec = "Thunderstorm";
139 break;
140 case 3:
141 prec = "Freezing rain";
142 break;
143 case 4:
144 prec = "Mixed / ice";
145 break;
146 case 5:
147 prec = "Snow";
148 break;
149 default:
150 prec = "not available";
151 // 6 = reserved 7 = not available = default
152 }
153 return prec;
154}
155
156wxString aisMeteoWaterLevelRef(int refID) {
157 wxString ref = wxEmptyString;
158 switch (refID) {
159 case 0:
160 ref = "MLLW";
161 break;
162 case 1:
163 ref = "IGLD-85";
164 break;
165 case 2:
166 ref = "Local river";
167 break;
168 case 3:
169 ref = "STND";
170 break;
171 case 4:
172 ref = "MHHW";
173 break;
174 case 5:
175 ref = "MHW";
176 break;
177 case 6:
178 ref = "MSL";
179 break;
180 case 7:
181 ref = "MLW";
182 break;
183 case 8:
184 ref = "NGVD-29";
185 break;
186 case 9:
187 ref = "NAVD-88";
188 break;
189 case 10:
190 ref = "WGS-84";
191 break;
192 case 11:
193 ref = "LAT";
194 break;
195 case 12:
196 ref = "Pool";
197 break;
198 case 13:
199 ref = "Gauge";
200 break;
201 }
202 return ref;
203}
204
205AisTargetData::AisTargetData(AisTargetCallbacks cb) : m_callbacks(cb) {
206 strncpy(ShipName, "Unknown ", SHIP_NAME_LEN);
207 strncpy(CallSign, " ", 8);
208 strncpy(Destination, " ", DESTINATION_LEN);
209 ShipNameExtension[0] = 0;
210 b_show_AIS_CPA = false;
211
212 SOG = 555.;
213 COG = 666.;
214 HDG = 511.;
215 ROTAIS = -128;
216 Lat = 0.;
217 Lon = 0.;
218
219 wxDateTime now = wxDateTime::Now();
220 now.MakeGMT();
221 PositionReportTicks = now.GetTicks(); // Default is my idea of NOW
222 StaticReportTicks = now.GetTicks();
223 b_lost = false;
224 b_removed = false;
225
226 IMO = 0;
227 MID = 555;
228 MMSI = 666;
229 NavStatus = UNDEFINED;
230 SyncState = 888;
231 SlotTO = 999;
232 ShipType = 19; // "Unknown"
233 b_isDSCtarget = false;
234 m_dscNature = 99;
235 m_dscTXmmsi = 666;
236
237 CPA = 100; // Large values avoid false alarms
238 TCPA = 100;
239
240 Range_NM = -1.;
241 Brg = -1.;
242
243 DimA = DimB = DimC = DimD = 0;
244 ;
245
246 ETA_Mo = 0;
247 ETA_Day = 0;
248 ETA_Hr = 24;
249 ETA_Min = 60;
250
251 Draft = 0.;
252
253 RecentPeriod = 0;
254
255 m_utc_hour = 0;
256 m_utc_min = 0;
257 m_utc_sec = 0;
258
259 Class = AIS_CLASS_A; // default
260 n_alert_state = AIS_NO_ALERT;
261 b_suppress_audio = false;
262 b_positionDoubtful = false;
263 b_positionOnceValid = false;
264 b_nameValid = false;
265
266 Euro_Length = 0; // Extensions for European Inland AIS
267 Euro_Beam = 0;
268 Euro_Draft = 0;
269 strncpy(Euro_VIN, " ", 8);
270 UN_shiptype = 0;
271
272 b_isEuroInland = false;
273 b_blue_paddle = false;
274
275 b_NoTrack = false;
276 b_OwnShip = false;
277 b_PersistTrack = false;
278 b_mPropPersistTrack = false;
279 b_in_ack_timeout = false;
280
281 b_active = false;
282 blue_paddle = 0;
283 bCPA_Valid = false;
284 b_isFollower = false;
285 ROTIND = 0;
286 b_show_track = g_bAISShowTracks;
287 b_SarAircraftPosnReport = false;
288 altitude = 0;
289 b_nameFromCache = false;
290 importance = 0.0;
291 for (unsigned int i = 0; i < AIS_TARGETDATA_MAX_CANVAS; i++)
292 last_scale[i] = 50;
293 met_data.original_mmsi = 0;
294 met_data.stationID = 0;
295 met_data.month = 0;
296 met_data.day = 0;
297 met_data.hour = 24;
298 met_data.minute = 60;
299 met_data.pos_acc = 1;
300 met_data.wind_kn = 122;
301 met_data.wind_gust_kn = 127;
302 met_data.wind_dir = 360;
303 met_data.wind_gust_dir = 360;
304 met_data.air_temp = -102.4;
305 met_data.rel_humid = 101;
306 met_data.dew_point = 50.1;
307 met_data.airpress = 1310;
308 met_data.airpress_tend = 3;
309 met_data.hor_vis = 12.7;
310 met_data.hor_vis_GT = false;
311 met_data.water_lev_dev = 4001 / 100 - 10;
312 met_data.water_level = -32;
313 met_data.water_lev_trend = 3;
314 met_data.current = 25.5;
315 met_data.curr_dir = 360;
316 met_data.wave_height = 25.5;
317 met_data.wave_period = 63;
318 met_data.wave_dir = 360;
319 met_data.swell_height = 25.5;
320 met_data.swell_per = 63;
321 met_data.swell_dir = 360;
322 met_data.seastate = 13;
323 met_data.water_temp = 501;
324 met_data.precipitation = 7;
325 met_data.salinity = 51.;
326 met_data.ice = 3;
327 met_data.vertical_ref = 14;
328}
329
330void AisTargetData::CloneFrom(AisTargetData *q) {
331 strncpy(ShipName, q->ShipName, SHIP_NAME_LEN);
332 strncpy(CallSign, q->CallSign, 8);
333 strncpy(Destination, q->Destination, DESTINATION_LEN);
334 ShipNameExtension[0] = 0;
335 b_show_AIS_CPA = q->b_show_AIS_CPA;
336 ;
337
338 SOG = q->SOG;
339 COG = q->COG;
340 HDG = q->HDG;
341 ROTAIS = q->ROTAIS;
342 Lat = q->Lat;
343 Lon = q->Lon;
344
345 PositionReportTicks = q->PositionReportTicks;
346 StaticReportTicks = q->StaticReportTicks;
347 b_lost = q->b_lost;
348 b_removed = q->b_removed;
349
350 IMO = q->IMO;
351 MID = q->MID;
352 MMSI = q->MMSI;
353 NavStatus = q->NavStatus;
354 SyncState = q->SyncState;
355 SlotTO = q->SlotTO;
356 ShipType = q->ShipType;
357 b_isDSCtarget = q->b_isDSCtarget;
358 m_dscNature = q->m_dscNature;
359 m_dscTXmmsi = q->m_dscTXmmsi;
360
361 CPA = q->CPA;
362 TCPA = q->TCPA;
363
364 Range_NM = q->Range_NM;
365 Brg = q->Brg;
366
367 DimA = q->DimA;
368 DimB = q->DimB;
369 DimC = q->DimC;
370 DimD = q->DimD;
371
372 ETA_Mo = q->ETA_Mo;
373 ETA_Day = q->ETA_Day;
374 ETA_Hr = q->ETA_Hr;
375 ETA_Min = q->ETA_Min;
376
377 Draft = q->Draft;
378
379 RecentPeriod = q->RecentPeriod;
380
381 m_utc_hour = q->m_utc_hour;
382 m_utc_min = q->m_utc_min;
383 m_utc_sec = q->m_utc_sec;
384
385 Class = q->Class;
386 n_alert_state = q->n_alert_state;
387 b_suppress_audio = q->b_suppress_audio;
388 b_positionDoubtful = q->b_positionDoubtful;
389 b_positionOnceValid = q->b_positionOnceValid;
390 b_nameValid = q->b_nameValid;
391
392 Euro_Length = q->Euro_Length; // Extensions for European Inland AIS
393 Euro_Beam = q->Euro_Beam;
394 Euro_Draft = q->Euro_Draft;
395 memcpy(Euro_VIN, q->Euro_VIN, EURO_VIN_LEN);
396 UN_shiptype = q->UN_shiptype;
397
398 b_isEuroInland = q->b_isEuroInland;
399 b_blue_paddle = q->b_blue_paddle;
400
401 b_OwnShip = q->b_OwnShip;
402 b_in_ack_timeout = q->b_in_ack_timeout;
403
404 m_ptrack = q->m_ptrack;
405
406 b_active = q->b_active;
407 blue_paddle = q->blue_paddle;
408 bCPA_Valid = q->bCPA_Valid;
409 ROTIND = q->ROTIND;
410 b_show_track = q->b_show_track;
411 b_SarAircraftPosnReport = q->b_SarAircraftPosnReport;
412 altitude = q->altitude;
413}
414
415AisTargetData::~AisTargetData() { m_ptrack.clear(); }
416// AisTargetData::~AisTargetData() { m_pMetPoint.clear(); } //TODO Needed?
417
418wxString AisTargetData::GetFullName(void) {
419 wxString retName;
420 if (b_nameValid) {
421 wxString shipName = trimAISField(ShipName);
422 if (shipName == _T("Unknown"))
423 retName = wxGetTranslation(shipName);
424 else
425 retName = shipName;
426
427 if (strlen(ShipNameExtension)) {
428 wxString shipNameExt = trimAISField(ShipNameExtension);
429 retName += shipNameExt;
430 }
431 }
432
433 return retName;
434}
435
436wxString AisTargetData::BuildQueryResult(void) {
437 wxString html;
438 wxDateTime now = wxDateTime::Now();
439
440 wxString tableStart = _T("\n<table border=0 cellpadding=1 cellspacing=0>\n");
441 wxString tableEnd = _T("</table>\n\n");
442 wxString rowStart = _T("<tr><td><font size=-2>");
443 wxString rowStartH = _T("<tr><td nowrap>");
444 wxString rowSeparator = _T("</font></td><td></td><td><b>");
445 wxString rowSeparatorH = _T("</td><td></td><td>");
446 wxString colSeparator = _T("<td></td>");
447 wxString rowEnd = _T("</b></td></tr>\n");
448 wxString vertSpacer =
449 _T("<tr><td></td></tr><tr><td></td></tr><tr><td></td></tr>\n\n");
450
451 wxString IMOstr, MMSIstr, ClassStr;
452
453 html << tableStart << _T("<tr><td nowrap colspan=2>");
454 if (b_nameValid) {
455 html << _T("<font size=+2><i><b>") << GetFullName();
456 html << _T("</b></i></font>&nbsp;&nbsp;<b>");
457 }
458
459 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_GPSG_BUDDY) &&
460 (Class != AIS_SART) && (Class != AIS_METEO)) {
461 html << trimAISField(CallSign) << _T("</b>") << rowEnd;
462
463 if (Class != AIS_CLASS_B) {
464 if (IMO > 0) IMOstr = wxString::Format(_T("%08d"), abs(IMO));
465 }
466 } else
467 html << _T("</b>") << rowEnd;
468
469 html << vertSpacer;
470
471 if (Class != AIS_GPSG_BUDDY) {
472 MMSIstr = wxString::Format(_T("%09d"), abs(MMSI));
473 }
474 ClassStr = wxGetTranslation(Get_class_string(false));
475
476 if (Class == AIS_ATON) {
477 wxString cls(_T("AtoN: "));
478 cls += Get_vessel_type_string(false);
479 ClassStr = wxGetTranslation(cls);
480 }
481
482 if (b_SarAircraftPosnReport) {
483 int airtype = (MMSI % 1000) / 100;
484 ClassStr = airtype == 5 ? _("SAR Helicopter") : _("SAR Aircraft");
485 }
486
487 if (IMOstr.Length())
488 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
489 _T("cellspacing=0>")
490 << rowStart << _("MMSI")
491 << _T("</font></td><td>&nbsp;</td><td><font size=-2>") << _("Class")
492 << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
493 << _("IMO") << _T("</font></td></tr>") << rowStartH << _T("<b>")
494 << MMSIstr << _T("</b></td><td>&nbsp;</td><td><b>") << ClassStr
495 << _T("</b></td><td>&nbsp;</td><td align=right><b>") << IMOstr
496 << rowEnd << _T("</table></td></tr>");
497
498 else if (Class == AIS_METEO) {
499 MMSIstr = wxString::Format(_T("%09d"), abs(met_data.original_mmsi));
500 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
501 _T("cellspacing=0>")
502 << rowStart << _("MMSI")
503 << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
504 << _("Class") << _T("</font></td></tr>") << rowStartH << _T("<b>")
505 << MMSIstr << _T("</b></td><td>&nbsp;</td><td align=right><b>")
506 << _T("<font size=-1>") << ClassStr << rowEnd << rowStart
507 << _T("<b>ID: ") << MMSI;
508 if (met_data.stationID) { // Facilitate to find a Meteo target on SignalK
509 wxString SK_ID =
510 wxString::Format(_T("%06d"), (met_data.stationID - 1000000));
511 html << "<td>&nbsp;</td><td align=right>"
512 << "SK-ID: " << SK_ID;
513 }
514 html << rowEnd << _T("</b></table></td></tr>");
515 } else
516 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
517 _T("cellspacing=0>")
518 << rowStart << _("MMSI")
519 << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
520 << _("Class") << _T("</font></td></tr>") << rowStartH << _T("<b>")
521 << MMSIstr << _T("</b></td><td>&nbsp;</td><td align=right><b>")
522 << ClassStr << rowEnd << _T("</table></td></tr>");
523
524 if ((Class != AIS_SART)) //&& (Class != AIS_DSC))
525 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
526 _T("cellspacing=0>")
527 << rowStart
528 << ((Class == AIS_BASE || Class == AIS_ATON || Class == AIS_METEO)
529 ? _("Nation")
530 : _("Flag"))
531 << rowEnd << _T("</font></td></tr>") << rowStartH
532 << _T("<font size=-1><b>") << GetCountryCode(true);
533 if (Class == AIS_CLASS_B && MMSIstr.StartsWith("8")) {
534 html << "<td align=right>" << _("Handheld");
535 }
536 html << rowEnd << _T("</font></table></td></tr>");
537
538 wxString navStatStr;
539 if ((Class != AIS_BASE) && (Class != AIS_CLASS_B) && (Class != AIS_SART) &&
540 (Class != AIS_METEO)) {
541 html << vertSpacer;
542 if ((NavStatus <= 21) && (NavStatus >= 0))
543 navStatStr = wxGetTranslation(ais_get_status(NavStatus));
544 } else if (Class == AIS_SART) {
545 if (NavStatus == RESERVED_14)
546 navStatStr = _("Active");
547 else if (NavStatus == UNDEFINED)
548 navStatStr = _("Testing");
549 }
550
551 wxString sart_sub_type;
552 if (Class == AIS_SART) {
553 int mmsi_start = MMSI / 1000000;
554 switch (mmsi_start) {
555 case 970:
556 // sart_sub_type = _T("SART");
557 break;
558 case 972:
559 sart_sub_type = _T("MOB");
560 break;
561 case 974:
562 sart_sub_type = _T("EPIRB");
563 break;
564 default:
565 sart_sub_type = _("Unknown");
566 break;
567 }
568 }
569
570 wxString AISTypeStr, UNTypeStr, sizeString;
571 if ((Class != AIS_BASE) && (Class != AIS_SART) && (Class != AIS_DSC) &&
572 (Class != AIS_METEO)) {
573 // Ship type
574 AISTypeStr = wxGetTranslation(Get_vessel_type_string());
575
576 if (b_isEuroInland && UN_shiptype) {
577 auto it = s_ERI_hash.find(UN_shiptype);
578 wxString type;
579 if (it == s_ERI_hash.end())
580 type = _("Undefined");
581 else
582 type = it->second;
583
584 UNTypeStr = wxGetTranslation(type);
585 }
586
587 if (b_SarAircraftPosnReport) {
588 AISTypeStr.Clear();
589 UNTypeStr.Clear();
590 navStatStr.Clear();
591 }
592
593 if (Class == AIS_SART) {
594 if (MSG_14_text.Len()) {
595 html << rowStart << _("Safety Broadcast Message") << rowEnd << rowStartH
596 << _T("<b>") << MSG_14_text << rowEnd;
597 }
598 }
599
600 // Dimensions
601
602 if (NavStatus != ATON_VIRTUAL && Class != AIS_ARPA && Class != AIS_APRS &&
603 Class != AIS_BUOY) {
604 if ((Class == AIS_CLASS_B) || (Class == AIS_ATON)) {
605 sizeString =
606 wxString::Format(_T("%dm x %dm"), (DimA + DimB), (DimC + DimD));
607 } else if (!b_SarAircraftPosnReport) {
608 if ((DimA + DimB + DimC + DimD) == 0) {
609 if (b_isEuroInland) {
610 if (Euro_Length == 0.0) {
611 if (Euro_Draft > 0.01) {
612 sizeString << wxString::Format(_T("---m x ---m x %4.1fm"),
613 Euro_Draft);
614 } else {
615 sizeString << _T("---m x ---m x ---m");
616 }
617 } else {
618 if (Euro_Draft > 0.01) {
619 sizeString << wxString::Format(_T("%5.1fm x %4.1fm x %4.1fm"),
620 Euro_Length, Euro_Beam,
621 Euro_Draft);
622 } else {
623 sizeString << wxString::Format(_T("%5.1fm x %4.1fm x ---m\n\n"),
624 Euro_Length, Euro_Beam);
625 }
626 }
627 } else {
628 if (Draft > 0.01) {
629 sizeString << wxString::Format(_T("---m x ---m x %4.1fm"), Draft);
630 } else {
631 sizeString << _T("---m x ---m x ---m");
632 }
633 }
634 } else if (Draft < 0.01) {
635 sizeString << wxString::Format(_T("%dm x %dm x ---m"), (DimA + DimB),
636 (DimC + DimD));
637 } else {
638 sizeString << wxString::Format(_T("%dm x %dm x %4.1fm"),
639 (DimA + DimB), (DimC + DimD), Draft);
640 }
641 }
642 }
643 }
644
645 if (Class == AIS_SART) {
646 html << _T("<tr><td colspan=2>")
647 << _T("<b>") << AISTypeStr;
648 if (sart_sub_type.Length()) html << _T(" (") << sart_sub_type << _T("), ");
649 html << navStatStr;
650 html << rowEnd << _T("<tr><td colspan=2>")
651 << _T("<b>") << sizeString << rowEnd;
652 }
653
654 else if (Class == AIS_ATON) {
655 html << _T("<tr><td colspan=2>")
656 << _T("<b>") << navStatStr;
657 html << rowEnd << _T("<tr><td colspan=2>")
658 << _T("<b>") << sizeString << rowEnd;
659 } else if (Class == AIS_DSC && (ShipType == 12 || ShipType == 16)) {
660 if (ShipType == 16) { // Distress relay
661 html << _T("<tr><td colspan=2>")
662 << _T("<b>") << _("Distress relay");
663 if (m_dscTXmmsi > 2000000) {
664 wxString mmsirelay = wxString::Format(_T(" %09d"), abs(m_dscTXmmsi));
665 html << _T(" ") << _("by:") << mmsirelay;
666 }
667 html << _T("<b>") << sizeString << rowEnd;
668 }
669 html << _T("<tr><td colspan=2>") << _("Nature of distress: ") << rowEnd
670 << _T("<tr><td colspan=2>");
671 if (m_dscNature < 13) {
672 html << _T("<tr><td colspan=2>")
673 << _T("<b>") << GetNatureofDistress(m_dscNature) << _T("<b>")
674 << sizeString << rowEnd << _T("<tr><td colspan=2>");
675 }
676 } else if ((Class != AIS_BASE) && (Class != AIS_DSC)) {
677 html << _T("<tr><td colspan=2>")
678 << _T("<b>") << AISTypeStr;
679 if (navStatStr.Length()) html << _T(", ") << navStatStr;
680 if (UNTypeStr.Length()) html << _T(" (UN Type ") << UNTypeStr << _T(")");
681 html << rowEnd << _T("<tr><td colspan=2>")
682 << _T("<b>") << sizeString << rowEnd;
683 }
684
685 if (b_positionOnceValid) {
686 wxString posTypeStr;
687 if (b_positionDoubtful) posTypeStr << _(" (Last Known)");
688
689 now.MakeGMT();
690 int target_age = now.GetTicks() - PositionReportTicks;
691 // wxLogMessage(wxString::Format(_T("** PositionReportTicks %ld %ld %d"),
692 // now.GetTicks(), PositionReportTicks,
693 // target_age));
694
695 html << vertSpacer << rowStart << _("Position") << posTypeStr
696 << _T("</font></td><td align=right><font size=-2>") << _("Report Age")
697 << _T("</font></td></tr>")
698
699 << rowStartH << _T("<b>") << toSDMM(1, Lat)
700 << _T("</b></td><td align=right><b>") << FormatTimeAdaptive(target_age)
701 << rowEnd << rowStartH << _T("<b>") << toSDMM(2, Lon);
702 if (Class != AIS_METEO)
703 html << rowEnd;
704 else {
705 wxString meteoTime =
706 wxString::Format(" %02d:%02d", met_data.hour, met_data.minute);
707 html << " </td><td align=right></b></font><font size=-3>"
708 << _("Issued (UTC)") << "</font><font size=-1><b>" << meteoTime
709 << "</font>" << rowEnd;
710 }
711 }
712
713 wxString courseStr, sogStr, hdgStr, rotStr, rngStr, brgStr, destStr, etaStr;
714
715 if (Class == AIS_GPSG_BUDDY) {
716 long month, year, day;
717 m_date_string.Mid(0, 2).ToLong(&day);
718 m_date_string.Mid(2, 2).ToLong(&month);
719 m_date_string.Mid(4, 2).ToLong(&year);
720 wxDateTime date;
721 date.SetDay(day);
722 date.SetMonth((wxDateTime::Month)(month - 1));
723 date.SetYear(year + 2000);
724
725 wxString f_date = date.FormatISODate();
726
727 html << vertSpacer << rowStart << _("Report as of") << rowEnd << rowStartH
728 << _T("<b>") << f_date + _T("</b> at <b>")
729 << wxString::Format(_T("%d:%d UTC "), m_utc_hour, m_utc_min) << rowEnd;
730 } else {
731 if (Class == AIS_CLASS_A && !b_SarAircraftPosnReport) {
732 html << vertSpacer << rowStart << _("Destination")
733 << _T("</font></td><td align=right><font size=-2>") << _("ETA (UTC)")
734 << _T("</font></td></tr>\n") << rowStartH << _T("<b>");
735 wxString dest = trimAISField(Destination);
736 if (dest.Length())
737 html << html_escape(dest);
738 else
739 html << _T("---");
740 html << _T("</b></td><td nowrap align=right><b>");
741
742 if ((ETA_Mo) && (ETA_Hr < 24)) {
743 int yearOffset = 0;
744 if (now.GetMonth() > (ETA_Mo - 1)) yearOffset = 1;
745 wxDateTime eta(ETA_Day, wxDateTime::Month(ETA_Mo - 1),
746 now.GetYear() + yearOffset, ETA_Hr, ETA_Min);
747 html << eta.Format(_T("%b %d %H:%M"));
748 } else
749 html << _T("---");
750 html << rowEnd;
751 }
752
753 if (Class == AIS_CLASS_A || Class == AIS_CLASS_B || Class == AIS_ARPA ||
754 Class == AIS_APRS || Class == AIS_SART || Class == AIS_BUOY) {
755 int crs = wxRound(COG);
756 if (crs < 360) {
757 wxString magString, trueString;
758 if (g_bShowMag)
759 magString << wxString::Format(
760 wxString("%03d%c(M)"), static_cast<int>(m_callbacks.get_mag(COG)),
761 0x00B0);
762 if (g_bShowTrue)
763 trueString << wxString::Format(wxString("%03d%c "), (int)crs, 0x00B0);
764
765 courseStr << trueString << magString;
766 } else if (COG == 360.0)
767 courseStr = _T("---");
768 else if (crs == 360)
769 courseStr = _T("0&deg;");
770
771 double speed_show = toUsrSpeed(SOG);
772
773 if ((SOG <= 102.2) || b_SarAircraftPosnReport) {
774 if (speed_show < 10.0)
775 sogStr =
776 wxString::Format(_T("%.2f "), speed_show) + getUsrSpeedUnit();
777 else if (speed_show < 100.0)
778 sogStr =
779 wxString::Format(_T("%.1f "), speed_show) + getUsrSpeedUnit();
780 else
781 sogStr =
782 wxString::Format(_T("%.0f "), speed_show) + getUsrSpeedUnit();
783 }
784 // sogStr = wxString::Format( _T("%5.2f ") +
785 // getUsrSpeedUnit(), toUsrSpeed( SOG ) );
786 else
787 sogStr = _T("---");
788
789 if ((int)HDG != 511)
790 hdgStr = wxString::Format(_T("%03d&deg;"), (int)HDG);
791 else
792 hdgStr = _T("---");
793
794 if (ROTAIS != -128) {
795 if (ROTAIS == 127)
796 rotStr << _T("> 5&deg;/30s ") << _("Right");
797 else if (ROTAIS == -127)
798 rotStr << _T("> 5&deg;/30s ") << _("Left");
799 else {
800 if (ROTIND > 0)
801 rotStr << wxString::Format(_T("%3d&deg;/Min "), ROTIND)
802 << _("Right");
803 else if (ROTIND < 0)
804 rotStr << wxString::Format(_T("%3d&deg;/Min "), -ROTIND)
805 << _("Left");
806 else
807 rotStr = _T("0");
808 }
809 } else if (!b_SarAircraftPosnReport)
810 rotStr = _T("---");
811 }
812 }
813
814 if (b_positionOnceValid && bGPSValid && (Range_NM >= 0.))
815 rngStr = FormatDistanceAdaptive(Range_NM);
816 else
817 rngStr = _T("---");
818
819 int brg = (int)wxRound(Brg);
820 if (Brg > 359.5) brg = 0;
821 if (b_positionOnceValid && bGPSValid && (Brg >= 0.) && (Range_NM > 0.) &&
822 (fabs(Lat) < 85.)) {
823 wxString magString, trueString;
824 if (g_bShowMag)
825 magString << wxString::Format(wxString("%03d%c(M)"),
826 static_cast<int>(m_callbacks.get_mag(Brg)),
827 0x00B0);
828 if (g_bShowTrue)
829 trueString << wxString::Format(wxString("%03d%c "), (int)Brg, 0x00B0);
830
831 brgStr << trueString << magString;
832 } else
833 brgStr = _T("---");
834
835 wxString turnRateHdr; // Blank if ATON or BASE or Special Position Report (9)
836 if ((Class != AIS_ATON) && (Class != AIS_BASE) && (Class != AIS_DSC) &&
837 (Class != AIS_METEO)) {
838 html << vertSpacer
839 << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
840 _T("cellspacing=0>")
841 << rowStart << _("Speed")
842 << _T("</font></td><td>&nbsp;</td><td><font size=-2>") << _("Course")
843 << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>");
844 if (!b_SarAircraftPosnReport) html << _("Heading");
845
846 html << _T("</font></td></tr>") << rowStartH << _T("<b>") << sogStr
847 << _T("</b></td><td>&nbsp;</td><td><b>") << courseStr
848 << _T("</b></td><td>&nbsp;</td><td align=right><b>");
849 if (!b_SarAircraftPosnReport) html << hdgStr;
850 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
851
852 if (!b_SarAircraftPosnReport) turnRateHdr = _("Turn Rate");
853 }
854 if (Class != AIS_METEO) {
855 html << _T("<tr><td colspan=2><table width=100% border=0 cellpadding=0 ")
856 _T("cellspacing=0>")
857 << rowStart << _("Range")
858 << _T("</font></td><td>&nbsp;</td><td><font size=-2>") << _("Bearing")
859 << _T("</font></td><td>&nbsp;</td><td align=right><font size=-2>")
860 << turnRateHdr << _T("</font></td></tr>") << rowStartH << _T("<b>")
861 << rngStr << _T("</b></td><td>&nbsp;</td><td><b>") << brgStr
862 << _T("</b></td><td>&nbsp;</td><td align=right><b>");
863 if (!b_SarAircraftPosnReport) html << rotStr;
864 html << rowEnd << _T("</table></td></tr>") << vertSpacer;
865 }
866
867 if (bCPA_Valid && Class != AIS_METEO) {
868 wxString tcpaStr;
869 tcpaStr << _T("</b> ") << _("in ") << _T("</td><td align=right><b>")
870 << FormatTimeAdaptive((int)(TCPA * 60.));
871
872 html << /*vertSpacer << */ rowStart << _T("<font size=-2>") << _("CPA")
873 << _T("</font>") << rowEnd << rowStartH << _T("<b>")
874 << FormatDistanceAdaptive(CPA) << tcpaStr << rowEnd;
875 }
876
877 if (Class != AIS_BASE && Class != AIS_METEO) {
878 if (blue_paddle == 1) {
879 html << rowStart << _("Inland Blue Flag") << rowEnd << rowStartH
880 << _T("<b>") << _("Clear") << rowEnd;
881 } else if (blue_paddle == 2) {
882 html << rowStart << _("Inland Blue Flag") << rowEnd << rowStartH
883 << _T("<b>") << _("Set") << rowEnd;
884 }
885 }
886
887 if (b_SarAircraftPosnReport) {
888 wxString altStr;
889 if (altitude != 4095)
890 altStr.Printf(_T("%4d m"), altitude);
891 else
892 altStr = _("Unknown");
893
894 html << rowStart << _("Altitude")
895 << _T("</font></td><td>&nbsp;</td><td><font size=-0>") << rowStartH
896 << _T("<b>") << altStr << _T("</b></td><td>&nbsp;</td><td><b>")
897 << rowEnd << _T("</table></td></tr>") << vertSpacer;
898 }
899
900 if (Class == AIS_METEO) {
901 if (met_data.wind_kn < 122) {
902 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
903 wxString wspeed =
904 wxString::Format("%0.1f %s %d%c", userwindspeed,
905 getUsrWindSpeedUnit(), met_data.wind_dir, 0x00B0);
906
907 double userwindgustspeed = toUsrWindSpeed(met_data.wind_gust_kn);
908 wxString wspeedGust = wxString::Format("%.0f %s %d%c", userwindgustspeed,
909 getUsrWindSpeedUnit(),
910 met_data.wind_gust_dir, 0x00B0);
911 if (met_data.wind_gust_kn >= 126) wspeedGust = wxEmptyString;
912
913 html << vertSpacer << rowStart << _("Wind speed")
914 << _T("</font></td><td align=right><font size=-2>") << _("Wind gust")
915 << _T("</font></td></tr>") << rowStartH << _T("<b>") << wspeed
916 << _T("</b></td><td align=right><b>") << wspeedGust << rowEnd;
917 }
918
919 if (met_data.water_lev_dev < 30. || met_data.water_level > -32. ||
920 met_data.current < 25.5) {
921 wxString wlevel_txt = _("Water level deviation");
922 wxString wlevel;
923 if (met_data.water_lev_dev < 30.) {
924 double userlevel = toUsrDepth(met_data.water_lev_dev);
925 wlevel =
926 wxString::Format("%.1f %s %s", userlevel, getUsrDepthUnit(),
927 ais_meteo_get_trend(met_data.water_lev_trend));
928 if (met_data.vertical_ref < 14) {
929 wlevel_txt = _("Water level dev. Ref: ");
930 wlevel_txt << aisMeteoWaterLevelRef(met_data.vertical_ref);
931 }
932
933 if (met_data.water_lev_dev >= 30.) wlevel = wxEmptyString;
934
935 } else if (met_data.water_level > -32.) {
936 double userlevel = toUsrDepth(met_data.water_level);
937 wlevel =
938 wxString::Format("%.1f %s %s", userlevel, getUsrDepthUnit(),
939 ais_meteo_get_trend(met_data.water_lev_trend));
940 wlevel_txt = _("Water level");
941 if (met_data.water_level <= -32.) wlevel = wxEmptyString;
942 }
943
944 wxString current = wxString::Format("%.1f kts %d%c", met_data.current,
945 met_data.curr_dir, 0x00B0);
946 if (met_data.current >= 25.5) current = wxEmptyString;
947
948 html << vertSpacer << rowStart << wlevel_txt
949 << _T("</font></td><td align=right><font size=-2>")
950 << _("Surface current ") << _T("</font></td></tr>") << rowStartH
951 << _T("<b>") << wlevel << _T("</b></td><td align=right><b>")
952 << current << rowEnd;
953 }
954
955 if (met_data.wave_height < 24.6 || met_data.swell_height < 24.6) {
956 double userwave = toUsrDepth(met_data.wave_height);
957 wxString wave = wxString::Format("%.1f %s %d%c %d %s ", userwave,
958 getUsrDepthUnit(), met_data.wave_dir,
959 0x00B0, met_data.wave_period, _("s"));
960 if (met_data.wave_height >= 24.6) wave = wxEmptyString;
961
962 double userswell = toUsrDepth(met_data.swell_height);
963 wxString swell = wxString::Format("%.1f %s %d%c %d %s", userswell,
964 getUsrDepthUnit(), met_data.swell_dir,
965 0x00B0, met_data.swell_per, _("s"));
966 if (met_data.swell_height >= 25.) swell = wxEmptyString;
967
968 html << vertSpacer << rowStart << _("Waves height & period")
969 << _T("</font></td><td align=right><font size=-2>")
970 << _("Swell height & period ") << _T("</font></td></tr>")
971 << rowStartH << _T("<b>") << wave
972 << _T("</b></td><td align=right><b>") << swell << rowEnd;
973 }
974
975 if (met_data.air_temp != -102.4 || met_data.airpress < 1310) {
976 double usertemp = toUsrTemp(met_data.air_temp);
977 wxString airtemp =
978 wxString::Format("%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
979 if (met_data.air_temp == -102.4) airtemp = wxEmptyString;
980
981 wxString airpress =
982 wxString::Format("%d hPa %s", met_data.airpress,
983 ais_meteo_get_trend(met_data.airpress_tend));
984 const int ap = met_data.airpress;
985 if (ap < 800 || ap >= 1310) airpress = wxEmptyString;
986
987 html << vertSpacer << rowStart << _("Air Temperatur")
988 << _T("</font></td><td align=right><font size=-2>")
989 << _("Air pressure") << _T("</font></td></tr>") << rowStartH
990 << _T("<b>") << airtemp << _T("</b></td><td align=right><b>")
991 << airpress << rowEnd;
992 }
993
994 if (met_data.rel_humid < 101 || met_data.dew_point < 50.) {
995 wxString humid = wxString::Format("%d%c", met_data.rel_humid, '%');
996 if (met_data.rel_humid >= 101) humid = wxEmptyString;
997
998 double usertempDew = toUsrTemp(met_data.dew_point);
999 wxString dewpoint =
1000 wxString::Format("%.1f%c%s", usertempDew, 0x00B0, getUsrTempUnit());
1001 if (met_data.dew_point >= 50.) dewpoint = wxEmptyString;
1002
1003 html << vertSpacer << rowStart << _("Relative Humidity")
1004 << _T("</font></td><td align=right><font size=-2>")
1005 << _("Dew Point ") << _T("</font></td></tr>") << rowStartH
1006 << _T("<b>") << humid << _T("</b></td><td align=right><b>")
1007 << dewpoint << rowEnd;
1008 }
1009
1010 if (met_data.water_temp < 50.1 || met_data.seastate < 13) {
1011 double usertemp = toUsrTemp(met_data.water_temp);
1012 wxString watertemp =
1013 wxString::Format("%.1f%c%s", usertemp, 0x00B0, getUsrTempUnit());
1014 if (met_data.water_temp >= 50.1) watertemp = wxEmptyString;
1015
1016 wxString seastate = wxString::Format("%d Bf ", met_data.seastate);
1017 if (met_data.seastate == 13) seastate = wxEmptyString;
1018
1019 html << vertSpacer << rowStart << _("Water Temperatur")
1020 << _T("</font></td><td align=right><font size=-2>") << _("Sea state")
1021 << _T("</font></td></tr>") << rowStartH << _T("<b>") << watertemp
1022 << _T("</b></td><td align=right><b>") << seastate << rowEnd;
1023 }
1024
1025 if (met_data.precipitation < 7 || met_data.hor_vis < 12.7) {
1026 wxString precip =
1027 wxString::Format("%s", aisMeteoPrecipType(met_data.precipitation));
1028 if (met_data.precipitation >= 6) precip = wxEmptyString;
1029
1030 double userVisDist = toUsrDistance(met_data.hor_vis);
1031 wxString horVis =
1032 wxString::Format("%s%.1f %s", (met_data.hor_vis_GT ? ">" : ""),
1033 userVisDist, getUsrDistanceUnit());
1034 if (met_data.hor_vis >= 12.7) horVis = wxEmptyString;
1035 html << vertSpacer << rowStart << _("Precipitation")
1036 << _T("</font></td><td align=right><font size=-2>")
1037 << _("Horizontal Visibility") << _T("</font></td></tr>") << rowStartH
1038 << _T("<b>") << precip << _T("</b></td><td align=right><b>")
1039 << horVis << rowEnd;
1040 }
1041
1042 if (met_data.salinity < 50. || met_data.ice < 2) {
1043 wxString sal = wxString::Format("%.1f%c", met_data.salinity, 0x2030);
1044 if (met_data.salinity >= 50.) sal = wxEmptyString;
1045
1046 wxString icestatus = _("No");
1047 if (met_data.ice == 1) icestatus = _("Yes");
1048 if (met_data.ice >= 2) icestatus = wxEmptyString;
1049
1050 html << vertSpacer << rowStart << _("Sea salinity")
1051 << _T("</font></td><td align=right><font size=-2>")
1052 << _("Ice status") << _T("</font></td></tr>") << rowStartH
1053 << _T("<b>") << sal << _T("</b></td><td align=right><b>")
1054 << icestatus << rowEnd;
1055 }
1056 }
1057 html << _T("</table>");
1058 return html;
1059}
1060
1061wxString AisTargetData::GetRolloverString(void) {
1062 wxString result;
1063 wxString t;
1064 if (b_nameValid) {
1065 result.Append(_T("\""));
1066 result.Append(GetFullName());
1067 result.Append(_T("\" "));
1068 }
1069 if (Class != AIS_GPSG_BUDDY) {
1070 t.Printf(_T("%09d"), abs(MMSI));
1071 result.Append(t);
1072 result.Append(_T(" "));
1073 result.Append(GetCountryCode(false));
1074 }
1075 t = trimAISField(CallSign);
1076 if (t.Len()) {
1077 result.Append(_T(" ("));
1078 result.Append(t);
1079 result.Append(_T(")"));
1080 }
1081 if (g_bAISRolloverShowClass || (Class == AIS_SART)) {
1082 if (result.Len()) result.Append(_T("\n"));
1083 result.Append(_T("["));
1084 if (Class == AIS_ATON) {
1085 result.Append(wxGetTranslation(Get_class_string(true)));
1086 result.Append(_T(": "));
1087 result.Append(wxGetTranslation(Get_vessel_type_string(false)));
1088 } else if (b_SarAircraftPosnReport) {
1089 int airtype = (MMSI % 1000) / 100;
1090 result.Append(airtype == 5 ? _("SAR Helicopter") : _("SAR Aircraft"));
1091 } else
1092 result.Append(wxGetTranslation(Get_class_string(false)));
1093
1094 result.Append(_T("] "));
1095 if ((Class != AIS_ATON) && (Class != AIS_BASE)) {
1096 if (Class == AIS_SART) {
1097 int mmsi_start = MMSI / 1000000;
1098 switch (mmsi_start) {
1099 case 970:
1100 break;
1101 case 972:
1102 result += _T("MOB");
1103 break;
1104 case 974:
1105 result += _T("EPIRB");
1106 break;
1107 default:
1108 result += _("Unknown");
1109 break;
1110 }
1111 }
1112
1113 if (Class != AIS_SART && Class != AIS_METEO) {
1114 if (!b_SarAircraftPosnReport)
1115 result.Append(wxGetTranslation(Get_vessel_type_string(false)));
1116 }
1117
1118 if ((Class != AIS_CLASS_B) && (Class != AIS_SART) && Class != AIS_DSC &&
1119 Class != AIS_METEO && !b_SarAircraftPosnReport) {
1120 if ((NavStatus <= 15) && (NavStatus >= 0)) {
1121 result.Append(_T(" ("));
1122 result.Append(wxGetTranslation(ais_get_status(NavStatus)));
1123 result.Append(_T(")"));
1124 }
1125 } else if (Class == AIS_SART) {
1126 result.Append(_T(" ("));
1127 if (NavStatus == RESERVED_14)
1128 result.Append(_("Active"));
1129 else if (NavStatus == UNDEFINED)
1130 result.Append(_("Testing"));
1131 result.Append(_T(")"));
1132 } else if (Class == AIS_DSC) {
1133 result.Append(_T(" ("));
1134 result.Append(GetNatureofDistress(m_dscNature));
1135 result.Append(_T(")"));
1136 }
1137 }
1138 }
1139
1140 if (g_bAISRolloverShowCOG && ((SOG <= 102.2) || b_SarAircraftPosnReport) &&
1141 !((Class == AIS_ATON) || (Class == AIS_BASE) || (Class == AIS_METEO))) {
1142 if (result.Len()) result << _T("\n");
1143
1144 double speed_show = toUsrSpeed(SOG);
1145 if (speed_show < 10.0)
1146 result << wxString::Format(_T("SOG %.2f "), speed_show)
1147 << getUsrSpeedUnit() << _T(" ");
1148 else if (speed_show < 100.0)
1149 result << wxString::Format(_T("SOG %.1f "), speed_show)
1150 << getUsrSpeedUnit() << _T(" ");
1151 else
1152 result << wxString::Format(_T("SOG %.0f "), speed_show)
1153 << getUsrSpeedUnit() << _T(" ");
1154
1155 int crs = wxRound(COG);
1156 if (b_positionOnceValid) {
1157 if (crs < 360) {
1158 wxString magString, trueString;
1159 if (g_bShowMag)
1160 magString << wxString::Format(
1161 wxString("%03d%c(M) "),
1162 static_cast<int>(m_callbacks.get_mag(COG)), 0x00B0);
1163 if (g_bShowTrue)
1164 trueString << wxString::Format(wxString("%03d%c "), (int)crs, 0x00B0);
1165
1166 result << trueString << magString;
1167 }
1168
1169 else if (COG == 360.0)
1170 result << _(" COG Unavailable");
1171 else if (crs == 360)
1172 result << wxString(" COG 000\u00B0");
1173 } else
1174 result << _(" COG Unavailable");
1175 }
1176
1177 if (g_bAISRolloverShowCPA && bCPA_Valid && Class != AIS_METEO) {
1178 if (result.Len()) result << _T("\n");
1179 result << _("CPA") << _T(" ") << FormatDistanceAdaptive(CPA) << _T(" ")
1180 << _("in") << _T(" ") << wxString::Format(_T("%.0f"), TCPA)
1181 << _T(" ") << _("min");
1182 }
1183 if (Class == AIS_METEO) {
1184 if (met_data.wind_kn < 122) {
1185 if (result.Len()) result << "\n";
1186 double userwindspeed = toUsrWindSpeed(met_data.wind_kn);
1187 result << _("Wind speed");
1188 result << wxString::Format(": %0.1f %s", userwindspeed,
1189 getUsrWindSpeedUnit())
1190 << wxString::Format(" %d%c ", met_data.wind_dir, 0x00B0);
1191 }
1192
1193 if (met_data.water_lev_dev < 30.) {
1194 if (result.Len()) result << "\n";
1195 result << _("Water level deviation");
1196 double userdepth;
1197 userdepth = toUsrDepth(met_data.water_lev_dev);
1198 result << wxString::Format(": %.1f %s", userdepth, getUsrDepthUnit());
1199
1200 } else if (met_data.water_level > -32.) {
1201 if (result.Len()) result << "\n";
1202 result << _("Water level");
1203 double userdepth;
1204 userdepth = toUsrDepth(met_data.water_level);
1205 result << wxString::Format(": %.1f %s", userdepth, getUsrDepthUnit());
1206 }
1207
1208 if (met_data.current < 25.) {
1209 if (result.Len()) result << "\n";
1210 result << _("Current");
1211 result << wxString::Format(": %.1f ", met_data.current) << _("kts")
1212 << wxString::Format(" %d%c ", met_data.curr_dir, 0x00B0);
1213 }
1214
1215 if (met_data.wave_height < 24.6) {
1216 if (result.Len()) result << "\n";
1217 double userwh = toUsrDepth(met_data.wave_height);
1218 result << _("Wave height")
1219 << wxString::Format(": %.1f %s", userwh, getUsrDepthUnit())
1220 << " / " << met_data.wave_period << " " << _("s");
1221 }
1222
1223 if (met_data.water_temp < 50.) {
1224 if (result.Len()) result << "\n";
1225 double usertemp = toUsrTemp(met_data.water_temp);
1226 result << _("Water temp");
1227 result << wxString::Format(": %.1f%c", usertemp, 0x00B0)
1228 << getUsrTempUnit();
1229 }
1230
1231 if (met_data.air_temp != -102.4) {
1232 if (result.Len()) result << "\n";
1233 double usertemp = toUsrTemp(met_data.air_temp);
1234 result << _("Air temp");
1235 result << wxString::Format(": %.1f%c", usertemp, 0x00B0)
1236 << getUsrTempUnit() << " ";
1237 }
1238
1239 if (met_data.airpress > 799 && met_data.airpress < 1310) {
1240 if (met_data.air_temp == -102.4 && result.Len()) result << "\n";
1241 result << _("Air press");
1242 result << wxString::Format(": %d hPa", met_data.airpress);
1243 }
1244
1245 if (met_data.hor_vis < 12.) {
1246 if (result.Len()) result << "\n";
1247 double userVisDist = toUsrDistance(met_data.hor_vis);
1248 wxString horVis =
1249 wxString::Format(": %s%.1f %s", (met_data.hor_vis_GT ? ">" : ""),
1250 userVisDist, getUsrDistanceUnit());
1251 result << _("Visibility") << horVis;
1252 }
1253 }
1254 return result;
1255}
1256
1257wxString AisTargetData::Get_vessel_type_string(bool b_short) {
1258 int i = 19;
1259 if (Class == AIS_ATON) {
1260 i = ShipType + 20;
1261 } else
1262 switch (ShipType) {
1263 case 30:
1264 i = 0;
1265 break;
1266 case 31:
1267 i = 1;
1268 break;
1269 case 32:
1270 i = 2;
1271 break;
1272 case 33:
1273 i = 3;
1274 break;
1275 case 34:
1276 i = 4;
1277 break;
1278 case 35:
1279 i = 5;
1280 break;
1281 case 36:
1282 i = 6;
1283 break;
1284 case 37:
1285 i = 7;
1286 break;
1287 case 50:
1288 i = 9;
1289 break;
1290 case 51:
1291 i = 10;
1292 break;
1293 case 52:
1294 i = 11;
1295 break;
1296 case 53:
1297 i = 12;
1298 break;
1299 case 54:
1300 i = 13;
1301 break;
1302 case 55:
1303 i = 14;
1304 break;
1305 case 58:
1306 i = 15;
1307 break;
1308 default:
1309 i = 19;
1310 break;
1311 }
1312
1313 if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A)) {
1314 if ((ShipType >= 40) && (ShipType < 50)) i = 8;
1315
1316 if ((ShipType >= 60) && (ShipType < 70)) i = 16;
1317
1318 if ((ShipType >= 70) && (ShipType < 80)) i = 17;
1319
1320 if ((ShipType >= 80) && (ShipType < 90)) i = 18;
1321 } else if (Class == AIS_GPSG_BUDDY)
1322 i = 52;
1323 else if (Class == AIS_ARPA)
1324 i = 55;
1325 else if (Class == AIS_APRS)
1326 i = 56;
1327 else if (Class == AIS_BUOY)
1328 i = 57;
1329 else if (Class == AIS_DSC)
1330 i = (ShipType == 12 || ShipType == 16) ? 54 : 53; // 12 & 16 is distress
1331
1332 if (!b_short)
1333 return ais_get_type(i);
1334 else
1335 return ais_get_short_type(i);
1336}
1337
1338wxString AisTargetData::Get_class_string(bool b_short) {
1339 switch (Class) {
1340 case AIS_CLASS_A:
1341 return _("A");
1342 case AIS_CLASS_B:
1343 return _("B");
1344 case AIS_ATON:
1345 return b_short ? _("AtoN") : _("Aid to Navigation");
1346 case AIS_BASE:
1347 return b_short ? _("Base") : _("Base Station");
1348 case AIS_GPSG_BUDDY:
1349 return b_short ? _("Buddy") : _("GPSGate Buddy");
1350 case AIS_DSC:
1351 if (ShipType == 12 || (ShipType == 16 && m_dscNature < 13))
1352 return b_short ? _("DSC") : _("DSC Distress");
1353 else
1354 return b_short ? _("DSC") : _("DSC Position Report");
1355 case AIS_SART:
1356 return b_short ? _("SART") : _("SART");
1357 case AIS_ARPA:
1358 return b_short ? _("ARPA") : _("ARPA");
1359 case AIS_BUOY:
1360 return b_short ? _("Buoy") : _("BUOY");
1361 case AIS_APRS:
1362 return b_short ? _("APRS") : _("APRS Position Report");
1363 case AIS_METEO:
1364 return b_short ? _("Meteo") : _("Meteorologic");
1365
1366 default:
1367 return b_short ? _("Unk") : _("Unknown");
1368 }
1369}
1370
1371wxString AisTargetData::GetNatureofDistress(int dscnature) {
1372 // Natures of distress from: Rec. ITU-R M.493-10.
1373 wxString dscDistressType[] = {_("Fire, explosion"),
1374 _("Flooding"),
1375 _("Collision"),
1376 _("Grounding"),
1377 _("Listing, in danger of capsizing"),
1378 _("Sinking"),
1379 _("Disabled and adrift"),
1380 _("Undesignated distress"),
1381 _("Abandoning ship"),
1382 _("Piracy/armed robbery attack"),
1383 _("Man overboard"),
1384 _T("-"),
1385 _("EPIRB emission")};
1386 if (dscnature >= 0 && dscnature < 13) return dscDistressType[dscnature];
1387
1388 return wxEmptyString;
1389}
1390
1391void AisTargetData::Toggle_AIS_CPA(void) {
1392 b_show_AIS_CPA = !b_show_AIS_CPA ? true : false;
1393}
1394
1395void AisTargetData::ToggleShowTrack(void) {
1396 b_show_track = !b_show_track ? true : false;
1397}
1398
1399bool AisTargetData::IsValidMID(int mid) {
1400 if (mid >= 201 && mid <= 775) return true;
1401 return false;
1402}
1403
1404// Get country name and code according to ITU 2023-02
1405// (http://www.itu.int/en/ITU-R/terrestrial/fmd/Pages/mid.aspx)
1406wxString AisTargetData::GetCountryCode(bool b_CntryLongStr) {
1407 if (Class == AIS_BUOY) return wxEmptyString;
1408 /***** Check for a valid MID *****/
1409 // Meteo adaption
1410 int tmpMmsi = met_data.original_mmsi ? met_data.original_mmsi : MMSI;
1411 // First check the most common case
1412 int nMID = tmpMmsi / 1000000;
1413 if (!IsValidMID(nMID) || Class == AIS_ATON) {
1414 // SART, MOB, EPIRB starts with 97 and don't use MID (ITU-R M.1371-5)
1415 // or healthy check
1416 if (tmpMmsi < 1000 || 97 == tmpMmsi / 10000000) return wxEmptyString;
1417
1418 // Find MID when not in first position like e.g. SAR/ATON
1419 wxString s_mmsi;
1420 s_mmsi << tmpMmsi;
1421 bool foundMID = false;
1422 size_t i;
1423 i = nMID > 900 ? 2 : 0; // AIS_ATON or others where MMSI starts with 9x
1424 for (i; i < s_mmsi.length() - 3; i++) {
1425 nMID = wxAtoi(s_mmsi.Mid(i, 3));
1426 if (IsValidMID(nMID)) {
1427 foundMID = true;
1428 break;
1429 }
1430 }
1431 if (!foundMID) return wxEmptyString;
1432 }
1433
1434#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1435
1436 switch (nMID) {
1437 case 201:
1438 return b_CntryLongStr ? _("Albania") : _T("AL");
1439 case 202:
1440 return b_CntryLongStr ? _("Andorra") : _T("AD");
1441 case 203:
1442 return b_CntryLongStr ? _("Austria") : _T("AT");
1443 case 204:
1444 return b_CntryLongStr ? _("Azores") : _T("AZ");
1445 case 205:
1446 return b_CntryLongStr ? _("Belgium") : _T("BE");
1447 case 206:
1448 return b_CntryLongStr ? _("Belarus") : _T("BY");
1449 case 207:
1450 return b_CntryLongStr ? _("Bulgaria") : _T("BG");
1451 case 208:
1452 return b_CntryLongStr ? _("Vatican City State") : _T("VA");
1453 case 209:
1454 case 210:
1455 return b_CntryLongStr ? _("Cyprus") : _T("CY");
1456 case 211:
1457 return b_CntryLongStr ? _("Germany") : _T("DE");
1458 case 212:
1459 return b_CntryLongStr ? _("Cyprus") : _T("CY");
1460 case 213:
1461 return b_CntryLongStr ? _("Georgia") : _T("GE");
1462 case 214:
1463 return b_CntryLongStr ? _("Moldova") : _T("MD");
1464 case 215:
1465 return b_CntryLongStr ? _("Malta") : _T("MT");
1466 case 216:
1467 return b_CntryLongStr ? _("Armenia") : _T("AM");
1468 case 218:
1469 return b_CntryLongStr ? _("Germany") : _T("DE");
1470 case 219:
1471 case 220:
1472 return b_CntryLongStr ? _("Denmark") : _T("DK");
1473 case 224:
1474 return b_CntryLongStr ? _("Spain") : _T("ES");
1475 case 225:
1476 return b_CntryLongStr ? _("Spain") : _T("ES");
1477 case 226:
1478 case 227:
1479 case 228:
1480 return b_CntryLongStr ? _("France") : _T("FR");
1481 case 229:
1482 return b_CntryLongStr ? _("Malta") : _T("MT");
1483 case 230:
1484 return b_CntryLongStr ? _("Finland") : _T("FI");
1485 case 231:
1486 return b_CntryLongStr ? _("Faroe Islands") : _T("FO");
1487 case 232:
1488 case 233:
1489 case 234:
1490 case 235:
1491 return b_CntryLongStr ? _("Great Britain") : _T("GB");
1492 case 236:
1493 return b_CntryLongStr ? _("Gibraltar") : _T("GI");
1494 case 237:
1495 return b_CntryLongStr ? _("Greece") : _T("GR");
1496 case 238:
1497 return b_CntryLongStr ? _("Croatia") : _T("HR");
1498 case 239:
1499 case 240:
1500 case 241:
1501 return b_CntryLongStr ? _("Greece") : _T("GR");
1502 case 242:
1503 return b_CntryLongStr ? _("Morocco") : _T("MA");
1504 case 243:
1505 return b_CntryLongStr ? _("Hungary") : _T("HU");
1506 case 244:
1507 case 245:
1508 case 246:
1509 return b_CntryLongStr ? _("Netherlands") : _T("NL");
1510 case 247:
1511 return b_CntryLongStr ? _("Italy") : _T("IT");
1512 case 248:
1513 case 249:
1514 return b_CntryLongStr ? _("Malta") : _T("MT");
1515 case 250:
1516 return b_CntryLongStr ? _("Ireland") : _T("IE");
1517 case 251:
1518 return b_CntryLongStr ? _("Iceland") : _T("IS");
1519 case 252:
1520 return b_CntryLongStr ? _("Liechtenstein") : _T("LI");
1521 case 253:
1522 return b_CntryLongStr ? _("Luxembourg") : _T("LU");
1523 case 254:
1524 return b_CntryLongStr ? _("Monaco") : _T("MC");
1525 case 255:
1526 return b_CntryLongStr ? _("Madeira") : _T("PT");
1527 case 256:
1528 return b_CntryLongStr ? _("Malta") : _T("MT");
1529 case 257:
1530 case 258:
1531 case 259:
1532 return b_CntryLongStr ? _("Norway") : _T("NO");
1533 case 261:
1534 return b_CntryLongStr ? _("Poland") : _T("PL");
1535 case 262:
1536 return b_CntryLongStr ? _("Montenegro") : _T("ME");
1537 case 263:
1538 return b_CntryLongStr ? _("Portugal") : _T("PT");
1539 case 264:
1540 return b_CntryLongStr ? _("Romania") : _T("RO");
1541 case 265:
1542 case 266:
1543 return b_CntryLongStr ? _("Sweden") : _T("SE");
1544 case 267:
1545 return b_CntryLongStr ? _("Slovak Republic") : _T("SK");
1546 case 268:
1547 return b_CntryLongStr ? _("San Marino") : _T("SM");
1548 case 269:
1549 return b_CntryLongStr ? _("Switzerland") : _T("CH");
1550 case 270:
1551 return b_CntryLongStr ? _("Czech Republic") : _T("CZ");
1552 case 271:
1553 return b_CntryLongStr ? _("Turkey") : _T("TR");
1554 case 272:
1555 return b_CntryLongStr ? _("Ukraine") : _T("UA");
1556 case 273:
1557 return b_CntryLongStr ? _("Russian") : _T("RU");
1558 case 274:
1559 return b_CntryLongStr ? _("Macedonia") : _T("MK");
1560 case 275:
1561 return b_CntryLongStr ? _("Latvia") : _T("LV");
1562 case 276:
1563 return b_CntryLongStr ? _("Estonia") : _T("EE");
1564 case 277:
1565 return b_CntryLongStr ? _("Lithuania") : _T("LT");
1566 case 278:
1567 return b_CntryLongStr ? _("Slovenia") : _T("SI");
1568 case 279:
1569 return b_CntryLongStr ? _("Serbia") : _T("RS");
1570 case 301:
1571 return b_CntryLongStr ? _("Anguilla") : _T("AI");
1572 case 303:
1573 return b_CntryLongStr ? _("Alaska") : _T("AK");
1574 case 304:
1575 case 305:
1576 return b_CntryLongStr ? _("Antigua and Barbuda") : _T("AG");
1577 case 306:
1578 return b_CntryLongStr ? _("Antilles") : _T("AN");
1579 case 307:
1580 return b_CntryLongStr ? _("Aruba") : _T("AW");
1581 case 308:
1582 case 309:
1583 return b_CntryLongStr ? _("Bahamas") : _T("BS");
1584 case 310:
1585 return b_CntryLongStr ? _("Bermuda") : _T("BM");
1586 case 311:
1587 return b_CntryLongStr ? _("Bahamas") : _T("BS");
1588 case 312:
1589 return b_CntryLongStr ? _("Belize") : _T("BZ");
1590 case 314:
1591 return b_CntryLongStr ? _("Barbados") : _T("BB");
1592 case 316:
1593 return b_CntryLongStr ? _("Canada") : _T("CA");
1594 case 319:
1595 return b_CntryLongStr ? _("Cayman Islands") : _T("KY");
1596 case 321:
1597 return b_CntryLongStr ? _("Costa Rica") : _T("CR");
1598 case 323:
1599 return b_CntryLongStr ? _("Cuba") : _T("CU");
1600 case 325:
1601 return b_CntryLongStr ? _("Dominica") : _T("DM");
1602 case 327:
1603 return b_CntryLongStr ? _("Dominican Republic") : _T("DM");
1604 case 329:
1605 return b_CntryLongStr ? _("Guadeloupe") : _T("GP");
1606 case 330:
1607 return b_CntryLongStr ? _("Grenada") : _T("GD");
1608 case 331:
1609 return b_CntryLongStr ? _("Greenland") : _T("GL");
1610 case 332:
1611 return b_CntryLongStr ? _("Guatemala") : _T("GT");
1612 case 334:
1613 return b_CntryLongStr ? _("Honduras") : _T("HN");
1614 case 336:
1615 return b_CntryLongStr ? _("Haiti") : _T("HT");
1616 case 338:
1617 return b_CntryLongStr ? _("United States of America") : _T("US");
1618 case 339:
1619 return b_CntryLongStr ? _("Jamaica") : _T("JM");
1620 case 341:
1621 return b_CntryLongStr ? _("Saint Kitts and Nevis") : _T("KN");
1622 case 343:
1623 return b_CntryLongStr ? _("Saint Lucia") : _T("LC");
1624 case 345:
1625 return b_CntryLongStr ? _("Mexico") : _T("MX");
1626 case 347:
1627 return b_CntryLongStr ? _("Martinique") : _T("MQ");
1628 case 348:
1629 return b_CntryLongStr ? _("Montserrat") : _T("MS");
1630 case 350:
1631 return b_CntryLongStr ? _("Nicaragua") : _T("NI");
1632 case 351:
1633 case 352:
1634 case 353:
1635 case 354:
1636 case 355:
1637 case 356:
1638 case 357:
1639 return b_CntryLongStr ? _("Panama") : _T("PA");
1640 case 358:
1641 return b_CntryLongStr ? _("Puerto Rico") : _T("PR");
1642 case 359:
1643 return b_CntryLongStr ? _("El Salvador") : _T("SV");
1644 case 361:
1645 return b_CntryLongStr ? _("Saint Pierre and Miquelon") : _T("PM");
1646 case 362:
1647 return b_CntryLongStr ? _("Trinidad and Tobago") : _T("TT");
1648 case 364:
1649 return b_CntryLongStr ? _("Turks and Caicos Islands") : _T("TC");
1650 case 366:
1651 case 367:
1652 case 368:
1653 case 369:
1654 return b_CntryLongStr ? _("United States of America") : _T("US");
1655 case 370:
1656 case 371:
1657 case 372:
1658 case 373:
1659 case 374:
1660 return b_CntryLongStr ? _("Panama") : _T("PA");
1661 case 375:
1662 case 376:
1663 case 377:
1664 return b_CntryLongStr ? _("Saint Vincent and the Grenadines") : _T("VC");
1665 case 378:
1666 return b_CntryLongStr ? _("British Virgin Islands") : _T("VG");
1667 case 379:
1668 return b_CntryLongStr ? _("United States Virgin Islands") : _T("AE");
1669 case 401:
1670 return b_CntryLongStr ? _("Afghanistan") : _T("AF");
1671 case 403:
1672 return b_CntryLongStr ? _("Saudi Arabia") : _T("SA");
1673 case 405:
1674 return b_CntryLongStr ? _("Bangladesh") : _T("BD");
1675 case 408:
1676 return b_CntryLongStr ? _("Bahrain") : _T("BH");
1677 case 410:
1678 return b_CntryLongStr ? _("Bhutan") : _T("BT");
1679 case 412:
1680 case 413:
1681 case 414:
1682 return b_CntryLongStr ? _("China") : _T("CN");
1683 case 416:
1684 return b_CntryLongStr ? _("Taiwan") : _T("TW");
1685 case 417:
1686 return b_CntryLongStr ? _("Sri Lanka") : _T("LK");
1687 case 419:
1688 return b_CntryLongStr ? _("India") : _T("IN");
1689 case 422:
1690 return b_CntryLongStr ? _("Iran") : _T("IR");
1691 case 423:
1692 return b_CntryLongStr ? _("Azerbaijani Republic") : _T("AZ");
1693 case 425:
1694 return b_CntryLongStr ? _("Iraq") : _T("IQ");
1695 case 428:
1696 return b_CntryLongStr ? _("Israel") : _T("IL");
1697 case 431:
1698 return b_CntryLongStr ? _("Japan") : _T("JP");
1699 case 432:
1700 return b_CntryLongStr ? _("Japan") : _T("JP");
1701 case 434:
1702 return b_CntryLongStr ? _("Turkmenistan") : _T("TM");
1703 case 436:
1704 return b_CntryLongStr ? _("Kazakhstan") : _T("KZ");
1705 case 437:
1706 return b_CntryLongStr ? _("Uzbekistan") : _T("UZ");
1707 case 438:
1708 return b_CntryLongStr ? _("Jordan") : _T("JO");
1709 case 440:
1710 case 441:
1711 return b_CntryLongStr ? _("Korea") : _T("KR");
1712 case 443:
1713 return b_CntryLongStr ? _("Palestine") : _T("PS");
1714 case 445:
1715 return b_CntryLongStr ? _("People's Rep. of Korea") : _T("KP");
1716 case 447:
1717 return b_CntryLongStr ? _("Kuwait") : _T("KW");
1718 case 450:
1719 return b_CntryLongStr ? _("Lebanon") : _T("LB");
1720 case 451:
1721 return b_CntryLongStr ? _("Kyrgyz Republic") : _T("KG");
1722 case 453:
1723 return b_CntryLongStr ? _("Macao") : _T("MO");
1724 case 455:
1725 return b_CntryLongStr ? _("Maldives") : _T("MV");
1726 case 457:
1727 return b_CntryLongStr ? _("Mongolia") : _T("MN");
1728 case 459:
1729 return b_CntryLongStr ? _("Nepal") : _T("NP");
1730 case 461:
1731 return b_CntryLongStr ? _("Oman") : _T("OM");
1732 case 463:
1733 return b_CntryLongStr ? _("Pakistan") : _T("PK");
1734 case 466:
1735 return b_CntryLongStr ? _("Qatar") : _T("QA");
1736 case 468:
1737 return b_CntryLongStr ? _("Syrian Arab Republic") : _T("SY");
1738 case 470:
1739 case 471:
1740 return b_CntryLongStr ? _("United Arab Emirates") : _T("AE");
1741 case 472:
1742 return b_CntryLongStr ? _("Tajikistan") : _T("TJ");
1743 case 473:
1744 case 475:
1745 return b_CntryLongStr ? _("Yemen") : _T("YE");
1746 case 477:
1747 return b_CntryLongStr ? _("Hong Kong") : _T("HK");
1748 case 478:
1749 return b_CntryLongStr ? _("Bosnia and Herzegovina") : _T("BA");
1750 case 501:
1751 return b_CntryLongStr ? _("Adelie Land") : _T("TF");
1752 case 503:
1753 return b_CntryLongStr ? _("Australia") : _T("AU");
1754 case 506:
1755 return b_CntryLongStr ? _("Myanmar") : _T("MM");
1756 case 508:
1757 return b_CntryLongStr ? _("Brunei Darussalam") : _T("BN");
1758 case 510:
1759 return b_CntryLongStr ? _("Micronesia") : _T("FM");
1760 case 511:
1761 return b_CntryLongStr ? _("Palau") : _T("PW");
1762 case 512:
1763 return b_CntryLongStr ? _("New Zealand") : _T("NZ");
1764 case 514:
1765 case 515:
1766 return b_CntryLongStr ? _("Cambodia") : _T("KH");
1767 case 516:
1768 return b_CntryLongStr ? _("Christmas Island") : _T("CX");
1769 case 518:
1770 return b_CntryLongStr ? _("Cook Islands") : _T("CK");
1771 case 520:
1772 return b_CntryLongStr ? _("Fiji") : _T("FJ");
1773 case 523:
1774 return b_CntryLongStr ? _("Cocos (Keeling) Islands") : _T("CC");
1775 case 525:
1776 return b_CntryLongStr ? _("Indonesia") : _T("ID");
1777 case 529:
1778 return b_CntryLongStr ? _("Kiribati") : _T("KI");
1779 case 531:
1780 return b_CntryLongStr ? _("Lao People's Dem. Rep.") : _T("LA");
1781 case 533:
1782 return b_CntryLongStr ? _("Malaysia") : _T("MY");
1783 case 536:
1784 return b_CntryLongStr ? _("Northern Mariana Islands") : _T("MP");
1785 case 538:
1786 return b_CntryLongStr ? _("Marshall Islands") : _T("MH");
1787 case 540:
1788 return b_CntryLongStr ? _("New Caledonia") : _T("NC");
1789 case 542:
1790 return b_CntryLongStr ? _("Niue") : _T("NU");
1791 case 544:
1792 return b_CntryLongStr ? _("Nauru") : _T("NR");
1793 case 546:
1794 return b_CntryLongStr ? _("French Polynesia") : _T("PF");
1795 case 548:
1796 return b_CntryLongStr ? _("Philippines") : _T("PH");
1797 case 550:
1798 return b_CntryLongStr ? _("East Timor") : _T("TL");
1799 case 553:
1800 return b_CntryLongStr ? _("Papua New Guinea") : _T("PG");
1801 case 555:
1802 return b_CntryLongStr ? _("Pitcairn Island") : _T("PN");
1803 case 557:
1804 return b_CntryLongStr ? _("Solomon Islands") : _T("SB");
1805 case 559:
1806 return b_CntryLongStr ? _("American Samoa") : _T("AS");
1807 case 561:
1808 return b_CntryLongStr ? _("Samoa") : _T("WS");
1809 case 563:
1810 case 564:
1811 case 565:
1812 case 566:
1813 return b_CntryLongStr ? _("Singapore") : _T("SG");
1814 case 567:
1815 return b_CntryLongStr ? _("Thailand") : _T("TH");
1816 case 570:
1817 return b_CntryLongStr ? _("Tonga") : _T("TO");
1818 case 572:
1819 return b_CntryLongStr ? _("Tuvalu") : _T("TV");
1820 case 574:
1821 return b_CntryLongStr ? _("Viet Nam") : _T("VN");
1822 case 576:
1823 case 577:
1824 return b_CntryLongStr ? _("Vanuatu") : _T("VU");
1825 case 578:
1826 return b_CntryLongStr ? _("Wallis and Futuna Islands") : _T("WF");
1827 case 601:
1828 return b_CntryLongStr ? _("South Africa") : _T("ZA");
1829 case 603:
1830 return b_CntryLongStr ? _("Angola") : _T("AO");
1831 case 605:
1832 return b_CntryLongStr ? _("Algeria") : _T("DZ");
1833 case 607:
1834 return b_CntryLongStr ? _("Saint Paul") : _T("TF");
1835 case 608:
1836 return b_CntryLongStr ? _("Ascension Island") : _T("SH");
1837 case 609:
1838 return b_CntryLongStr ? _("Burundi") : _T("BI");
1839 case 610:
1840 return b_CntryLongStr ? _("Benin") : _T("BJ");
1841 case 611:
1842 return b_CntryLongStr ? _("Botswana") : _T("BW");
1843 case 612:
1844 return b_CntryLongStr ? _("Central African Republic") : _T("CF");
1845 case 613:
1846 return b_CntryLongStr ? _("Cameroon") : _T("CM");
1847 case 615:
1848 return b_CntryLongStr ? _("Congo") : _T("CD");
1849 case 616:
1850 return b_CntryLongStr ? _("Comoros") : _T("KM");
1851 case 617:
1852 return b_CntryLongStr ? _("Capo Verde") : _T("CV");
1853 case 618:
1854 return b_CntryLongStr ? _("Crozet Archipelago") : _T("TF");
1855 case 619:
1856 return b_CntryLongStr ? _("Ivory Coast") : _T("CI");
1857 case 620:
1858 return b_CntryLongStr ? _("Comoros (Union of the)") : _T("KM");
1859 case 621:
1860 return b_CntryLongStr ? _("Djibouti") : _T("DJ");
1861 case 622:
1862 return b_CntryLongStr ? _("Egypt") : _T("EG");
1863 case 624:
1864 return b_CntryLongStr ? _("Ethiopia") : _T("ET");
1865 case 625:
1866 return b_CntryLongStr ? _("Eritrea") : _T("ER");
1867 case 626:
1868 return b_CntryLongStr ? _("Gabonese Republic") : _T("GA");
1869 case 627:
1870 return b_CntryLongStr ? _("Ghana") : _T("GH");
1871 case 629:
1872 return b_CntryLongStr ? _("Gambia") : _T("GM");
1873 case 630:
1874 return b_CntryLongStr ? _("Guinea-Bissau") : _T("GW");
1875 case 631:
1876 return b_CntryLongStr ? _("Equatorial Guinea") : _T("GQ");
1877 case 632:
1878 return b_CntryLongStr ? _("Guinea") : _T("GN");
1879 case 633:
1880 return b_CntryLongStr ? _("Burkina Faso") : _T("BF");
1881 case 634:
1882 return b_CntryLongStr ? _("Kenya") : _T("KE");
1883 case 635:
1884 return b_CntryLongStr ? _("Kerguelen Islands") : _T("TF");
1885 case 636:
1886 case 637:
1887 return b_CntryLongStr ? _("Liberia") : _T("LR");
1888 case 638:
1889 return b_CntryLongStr ? _("South Sudan (Republic of)") : _T("SS");
1890 case 642:
1891 return b_CntryLongStr ? _("Libya") : _T("LY");
1892 case 644:
1893 return b_CntryLongStr ? _("Lesotho") : _T("LS");
1894 case 645:
1895 return b_CntryLongStr ? _("Mauritius") : _T("MU");
1896 case 647:
1897 return b_CntryLongStr ? _("Madagascar") : _T("MG");
1898 case 649:
1899 return b_CntryLongStr ? _("Mali") : _T("ML");
1900 case 650:
1901 return b_CntryLongStr ? _("Mozambique") : _T("MZ");
1902 case 654:
1903 return b_CntryLongStr ? _("Mauritania") : _T("MR");
1904 case 655:
1905 return b_CntryLongStr ? _("Malawi") : _T("MW");
1906 case 656:
1907 return b_CntryLongStr ? _("Niger") : _T("NE");
1908 case 657:
1909 return b_CntryLongStr ? _("Nigeria") : _T("NG");
1910 case 659:
1911 return b_CntryLongStr ? _("Namibia") : _T("NA");
1912 case 660:
1913 return b_CntryLongStr ? _("Reunion") : _T("RE");
1914 case 661:
1915 return b_CntryLongStr ? _("Rwanda") : _T("RW");
1916 case 662:
1917 return b_CntryLongStr ? _("Sudan") : _T("SD");
1918 case 663:
1919 return b_CntryLongStr ? _("Senegal") : _T("SN");
1920 case 664:
1921 return b_CntryLongStr ? _("Seychelles") : _T("SC");
1922 case 665:
1923 return b_CntryLongStr ? _("Saint Helena") : _T("SH");
1924 case 666:
1925 return b_CntryLongStr ? _("Somalia") : _T("SO");
1926 case 667:
1927 return b_CntryLongStr ? _("Sierra Leone") : _T("SL");
1928 case 668:
1929 return b_CntryLongStr ? _("Sao Tome and Principe") : _T("ST");
1930 case 669:
1931 return b_CntryLongStr ? _("Eswatini") : _T("SZ");
1932 case 670:
1933 return b_CntryLongStr ? _("Chad") : _T("TD");
1934 case 671:
1935 return b_CntryLongStr ? _("Togolese Republic") : _T("TG");
1936 case 672:
1937 return b_CntryLongStr ? _("Tunisia") : _T("TN");
1938 case 674:
1939 return b_CntryLongStr ? _("Tanzania") : _T("TZ");
1940 case 675:
1941 return b_CntryLongStr ? _("Uganda") : _T("UG");
1942 case 676:
1943 return b_CntryLongStr ? _("Dem Rep.of the Congo") : _T("CD");
1944 case 677:
1945 return b_CntryLongStr ? _("Tanzania") : _T("TZ");
1946 case 678:
1947 return b_CntryLongStr ? _("Zambia") : _T("ZM");
1948 case 679:
1949 return b_CntryLongStr ? _("Zimbabwe") : _T("ZW");
1950 case 701:
1951 return b_CntryLongStr ? _("Argentine Republic") : _T("AR");
1952 case 710:
1953 return b_CntryLongStr ? _("Brazil") : _T("BR");
1954 case 720:
1955 return b_CntryLongStr ? _("Bolivia") : _T("BO");
1956 case 725:
1957 return b_CntryLongStr ? _("Chile") : _T("CL");
1958 case 730:
1959 return b_CntryLongStr ? _("Colombia") : _T("CO");
1960 case 735:
1961 return b_CntryLongStr ? _("Ecuador") : _T("EC");
1962 case 740:
1963 return b_CntryLongStr ? _("Falkland Islands") : _T("FK");
1964 case 745:
1965 return b_CntryLongStr ? _("France - Guiana") : _T("GY");
1966 case 750:
1967 return b_CntryLongStr ? _("Guyana") : _T("GY");
1968 case 755:
1969 return b_CntryLongStr ? _("Paraguay") : _T("PY");
1970 case 760:
1971 return b_CntryLongStr ? _("Peru") : _T("PE");
1972 case 765:
1973 return b_CntryLongStr ? _("Suriname") : _T("SR");
1974 case 770:
1975 return b_CntryLongStr ? _("Uruguay") : _T("UY");
1976 case 775:
1977 return b_CntryLongStr ? _("Venezuela") : _T("VE");
1978
1979 default:
1980 return wxEmptyString;
1981 }
1982#else
1983 return wxEmptyString;
1984#endif
1985}
1986
1987wxString ais_get_type(int index) {
1988 static const wxString ais_type[] = {
1989 _("Fishing Vessel"), // 30 0
1990 _("Towing Vessel"), // 31 1
1991 _("Towing Vessel, Long"), // 32 2
1992 _("Dredger"), // 33 3
1993 _("Diving Ops Vessel"), // 34 4
1994 _("Military Vessel"), // 35 5
1995 _("Sailing Vessel"), // 36 6
1996 _("Pleasure craft"), // 37 7
1997 _("High Speed Craft"), // 4x 8
1998 _("Pilot Vessel"), // 50 9
1999 _("Search and Rescue Vessel"), // 51 10
2000 _("Tug"), // 52 11
2001 _("Port Tender"), // 53 12
2002 _("Pollution Control Vessel"), // 54 13
2003 _("Law Enforcement Vessel"), // 55 14
2004 _("Medical Transport"), // 58 15
2005 _("Passenger Ship"), // 6x 16
2006 _("Cargo Ship"), // 7x 17
2007 _("Tanker"), // 8x 18
2008 _("Unknown"), // 19
2009 _("Unspecified"), // 00 20
2010 _("Reference Point"), // 01 21
2011 _("RACON"), // 02 22
2012 _("Fixed Structure"), // 03 23
2013 _("Spare"), // 04 24
2014 _("Light"), // 05 25
2015 _("Light w/Sectors"), // 06 26
2016 _("Leading Light Front"), // 07 27
2017 _("Leading Light Rear"), // 08 28
2018 _("Cardinal N Beacon"), // 09 29
2019 _("Cardinal E Beacon"), // 10 30
2020 _("Cardinal S Beacon"), // 11 31
2021 _("Cardinal W Beacon"), // 12 32
2022 _("Beacon, Port Hand"), // 13 33
2023 _("Beacon, Starboard Hand"), // 14 34
2024 _("Beacon, Preferred Channel Port Hand"), // 15 35
2025 _("Beacon, Preferred Channel Starboard Hand"), // 16 36
2026 _("Beacon, Isolated Danger"), // 17 37
2027 _("Beacon, Safe Water"), // 18 38
2028 _("Beacon, Special Mark"), // 19 39
2029 _("Cardinal Mark N"), // 20 40
2030 _("Cardinal Mark E"), // 21 41
2031 _("Cardinal Mark S"), // 22 42
2032 _("Cardinal Mark W"), // 23 43
2033 _("Port Hand Mark"), // 24 44
2034 _("Starboard Hand Mark"), // 25 45
2035 _("Preferred Channel Port Hand"), // 26 46
2036 _("Preferred Channel Starboard Hand"), // 27 47
2037 _("Isolated Danger"), // 28 48
2038 _("Safe Water"), // 29 49
2039 _("Special Mark"), // 30 50
2040 _("Light Vessel/Rig"), // 31 51
2041 _("GpsGate Buddy"), // xx 52
2042 _("Position Report"), // xx 53
2043 _("Distress"), // xx 54
2044 _("ARPA radar target"), // xx 55
2045 _("APRS Position Report"), // xx 56
2046 _("Buoy or similar") // xx 57
2047 };
2048
2049 return ais_type[index];
2050}
2051
2052wxString ais_get_short_type(int index) {
2053 static const wxString short_ais_type[] = {
2054 _("F/V"), // 30 0
2055 _("Tow"), // 31 1
2056 _("Long Tow"), // 32 2
2057 _("Dredge"), // 33 3
2058 _("D/V"), // 34 4
2059 _("Mil/V"), // 35 5
2060 _("S/V"), // 36 6
2061 _("Yat"), // 37 7
2062 _("HSC"), // 4x 8
2063 _("P/V"), // 50 9
2064 _("SAR/V"), // 51 10
2065 _("Tug"), // 52 11
2066 _("Tender"), // 53 12
2067 _("PC/V"), // 54 13
2068 _("LE/V"), // 55 14
2069 _("Med/V"), // 58 15
2070 _("Pass/V"), // 6x 16
2071 _("M/V"), // 7x 17
2072 _("M/T"), // 8x 18
2073 _("?"), // 19
2074
2075 _("AtoN"), // 00 20
2076 _("Ref. Pt"), // 01 21
2077 _("RACON"), // 02 22
2078 _("Fix.Struct."), // 03 23
2079 _("?"), // 04 24
2080 _("Lt"), // 05 25
2081 _("Lt sect."), // 06 26
2082 _("Ldg Lt Front"), // 07 27
2083 _("Ldg Lt Rear"), // 08 28
2084 _("Card. N"), // 09 29
2085 _("Card. E"), // 10 30
2086 _("Card. S"), // 11 31
2087 _("Card. W"), // 12 32
2088 _("Port"), // 13 33
2089 _("Stbd"), // 14 34
2090 _("Pref. Chnl"), // 15 35
2091 _("Pref. Chnl"), // 16 36
2092 _("Isol. Dngr"), // 17 37
2093 _("Safe Water"), // 18 38
2094 _("Special"), // 19 39
2095 _("Card. N"), // 20 40
2096 _("Card. E"), // 21 41
2097 _("Card. S"), // 22 42
2098 _("Card. W"), // 23 43
2099 _("Port Hand"), // 24 44
2100 _("Stbd Hand"), // 25 45
2101 _("Pref. Chnl"), // 26 46
2102 _("Pref. Chnl"), // 27 47
2103 _("Isol. Dngr"), // 28 48
2104 _("Safe Water"), // 29 49
2105 _("Special"), // 30 50
2106 _("LtV/Rig"), // 31 51
2107 _("Buddy"), // xx 52
2108 _("DSC"), // xx 53
2109 _("Distress"), // xx 54
2110 _("ARPA"), // xx 55
2111 _("APRS"), // xx 56
2112 _("Buoy or similar") // xx 57
2113 };
2114 return short_ais_type[index];
2115}
Global state for AIS decoder.