26 #include <wx/wxprec.h>
34 #include <wx/string.h>
36 #include "rapidjson/document.h"
38 #include "model/comm_decoder.h"
39 #include "model/comm_util.h"
40 #include "model/comm_vars.h"
41 #include "model/geodesic.h"
42 #include "model/own_ship.h"
45 bool CommDecoder::ParsePosition(
const LATLONG&
Position,
double& lat,
48 double llt =
Position.Latitude.Latitude;
50 if (!std::isnan(llt)) {
51 int lat_deg_int = (int)(llt / 100);
52 double lat_deg = lat_deg_int;
53 double lat_min = llt - (lat_deg * 100);
55 lat = lat_deg + (lat_min / 60.);
56 if (
Position.Latitude.Northing == South) lat = -lat;
60 double lln =
Position.Longitude.Longitude;
61 if (!std::isnan(lln)) {
62 int lon_deg_int = (int)(lln / 100);
63 double lon_deg = lon_deg_int;
64 double lon_min = lln - (lon_deg * 100);
66 lon = lon_deg + (lon_min / 60.);
67 if (
Position.Longitude.Easting == West) lon = -lon;
74 bool CommDecoder::DecodeRMC(std::string s,
NavData& temp_data) {
75 wxString sentence(s.c_str());
76 wxString sentence3 = ProcessNMEA4Tags(sentence);
77 m_NMEA0183 << sentence3;
79 if (!m_NMEA0183.PreParse())
return false;
80 if (!m_NMEA0183.Parse())
return false;
82 if (m_NMEA0183.Rmc.IsDataValid == NTrue) {
84 if (ParsePosition(m_NMEA0183.Rmc.Position, tlat, tlon)) {
85 temp_data.gLat = tlat;
86 temp_data.gLon = tlon;
92 if (!std::isnan(m_NMEA0183.Rmc.SpeedOverGroundKnots)) {
93 temp_data.gSog = m_NMEA0183.Rmc.SpeedOverGroundKnots;
95 if (!std::isnan(temp_data.gSog) && (temp_data.gSog > 0.05)) {
96 temp_data.gCog = m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue;
104 if ((!std::isnan(m_NMEA0183.Rmc.MagneticVariation)) &&
105 0.0 != m_NMEA0183.Rmc.MagneticVariation) {
106 if (m_NMEA0183.Rmc.MagneticVariationDirection == East)
107 temp_data.gVar = m_NMEA0183.Rmc.MagneticVariation;
108 else if (m_NMEA0183.Rmc.MagneticVariationDirection == West)
109 temp_data.gVar = -m_NMEA0183.Rmc.MagneticVariation;
114 gRmcTime = m_NMEA0183.Rmc.UTCTime;
115 gRmcDate = m_NMEA0183.Rmc.Date;
122 bool CommDecoder::DecodeHDM(std::string s,
NavData& temp_data) {
123 wxString sentence(s.c_str());
124 wxString sentence3 = ProcessNMEA4Tags(sentence);
125 m_NMEA0183 << sentence3;
127 if (!m_NMEA0183.PreParse())
return false;
128 if (!m_NMEA0183.Parse())
return false;
130 temp_data.gHdm = m_NMEA0183.Hdm.DegreesMagnetic;
135 bool CommDecoder::DecodeHDT(std::string s,
NavData& temp_data) {
136 wxString sentence(s.c_str());
137 wxString sentence3 = ProcessNMEA4Tags(sentence);
138 m_NMEA0183 << sentence3;
140 if (!m_NMEA0183.PreParse())
return false;
141 if (!m_NMEA0183.Parse())
return false;
143 temp_data.gHdt = m_NMEA0183.Hdt.DegreesTrue;
148 bool CommDecoder::DecodeHDG(std::string s,
NavData& temp_data) {
149 wxString sentence(s.c_str());
150 wxString sentence3 = ProcessNMEA4Tags(sentence);
151 m_NMEA0183 << sentence3;
153 if (!m_NMEA0183.PreParse())
return false;
154 if (!m_NMEA0183.Parse())
return false;
156 temp_data.gHdm = m_NMEA0183.Hdg.MagneticSensorHeadingDegrees;
161 if ((!std::isnan(m_NMEA0183.Hdg.MagneticVariationDegrees)) &&
162 0.0 != m_NMEA0183.Hdg.MagneticVariationDegrees) {
163 if (m_NMEA0183.Hdg.MagneticVariationDirection == East)
164 temp_data.gVar = m_NMEA0183.Hdg.MagneticVariationDegrees;
165 else if (m_NMEA0183.Hdg.MagneticVariationDirection == West)
166 temp_data.gVar = -m_NMEA0183.Hdg.MagneticVariationDegrees;
174 bool CommDecoder::DecodeVTG(std::string s,
NavData& temp_data) {
175 wxString sentence(s.c_str());
176 wxString sentence3 = ProcessNMEA4Tags(sentence);
177 m_NMEA0183 << sentence3;
179 if (!m_NMEA0183.PreParse())
return false;
180 if (!m_NMEA0183.Parse())
return false;
184 if (!std::isnan(m_NMEA0183.Vtg.SpeedKnots)) temp_data.gSog = m_NMEA0183.Vtg.SpeedKnots;
186 if (!std::isnan(m_NMEA0183.Vtg.SpeedKnots) &&
187 !std::isnan(m_NMEA0183.Vtg.TrackDegreesTrue)) {
188 temp_data.gCog = m_NMEA0183.Vtg.TrackDegreesTrue;
194 bool CommDecoder::DecodeGLL(std::string s,
NavData& temp_data) {
195 wxString sentence(s.c_str());
196 wxString sentence3 = ProcessNMEA4Tags(sentence);
197 m_NMEA0183 << sentence3;
199 if (!m_NMEA0183.PreParse())
return false;
200 if (!m_NMEA0183.Parse())
return false;
202 if (m_NMEA0183.Gll.IsDataValid == NTrue) {
204 if (ParsePosition(m_NMEA0183.Gll.Position, tlat, tlon)) {
205 temp_data.gLat = tlat;
206 temp_data.gLon = tlon;
215 bool CommDecoder::DecodeGSV(std::string s,
NavData& temp_data) {
216 wxString sentence(s.c_str());
217 wxString sentence3 = ProcessNMEA4Tags(sentence);
218 m_NMEA0183 << sentence3;
220 if (!m_NMEA0183.PreParse())
return false;
221 if (!m_NMEA0183.Parse())
return false;
223 if (m_NMEA0183.Gsv.MessageNumber == 1)
224 temp_data.n_satellites = m_NMEA0183.Gsv.SatsInView;
229 bool CommDecoder::DecodeGGA(std::string s,
NavData& temp_data) {
230 wxString sentence(s.c_str());
231 wxString sentence3 = ProcessNMEA4Tags(sentence);
232 m_NMEA0183 << sentence3;
234 if (!m_NMEA0183.PreParse())
return false;
235 if (!m_NMEA0183.Parse())
return false;
237 if (m_NMEA0183.Gga.GPSQuality > 0) {
239 if (ParsePosition(m_NMEA0183.Gga.Position, tlat, tlon)) {
240 temp_data.gLat = tlat;
241 temp_data.gLon = tlon;
245 temp_data.n_satellites = m_NMEA0183.Gga.NumberOfSatellitesInUse;
258 bool CommDecoder::DecodePGN129026(std::vector<unsigned char> v,
NavData& temp_data) {
261 tN2kHeadingReference ref;
264 if (ParseN2kPGN129026(v, SID, ref, COG, SOG)) {
265 temp_data.gCog = COG;
266 temp_data.gSog = SOG;
274 bool CommDecoder::DecodePGN129029(std::vector<unsigned char> v,
NavData& temp_data) {
276 uint16_t DaysSince1970;
277 double SecondsSinceMidnight;
278 double Latitude, Longitude, Altitude;
279 tN2kGNSStype GNSStype;
280 tN2kGNSSmethod GNSSmethod;
281 unsigned char nSatellites;
282 double HDOP, PDOP, GeoidalSeparation;
283 unsigned char nReferenceStations;
284 tN2kGNSStype ReferenceStationType;
285 uint16_t ReferenceSationID;
286 double AgeOfCorrection;
288 if (ParseN2kPGN129029(v, SID, DaysSince1970, SecondsSinceMidnight,
289 Latitude, Longitude, Altitude,
290 GNSStype, GNSSmethod,
291 nSatellites, HDOP, PDOP, GeoidalSeparation,
292 nReferenceStations, ReferenceStationType, ReferenceSationID,
295 temp_data.gLat = Latitude;
296 temp_data.gLon = Longitude;
303 if ( (GNSSmethod == N2kGNSSm_GNSSfix) ||
304 (GNSSmethod == N2kGNSSm_DGNSS) ||
305 (GNSSmethod == N2kGNSSm_PreciseGNSS)){
307 temp_data.n_satellites = nSatellites;
316 bool CommDecoder::DecodePGN127250(std::vector<unsigned char> v,
NavData& temp_data) {
319 double Heading, Deviation, Variation;
320 tN2kHeadingReference ref;
322 if (ParseN2kPGN127250(v, SID, Heading, Deviation, Variation, ref)){
323 temp_data.gHdt = N2kDoubleNA;
324 temp_data.gHdm = N2kDoubleNA;
325 if (ref == tN2kHeadingReference::N2khr_true)
326 temp_data.gHdt = Heading;
327 else if (ref == tN2kHeadingReference::N2khr_magnetic)
328 temp_data.gHdm = Heading;
330 temp_data.gVar = Variation;
338 bool CommDecoder::DecodePGN129025(std::vector<unsigned char> v,
NavData& temp_data) {
340 double Latitude, Longitude;
342 if (ParseN2kPGN129025(v, Latitude, Longitude)){
344 temp_data.gLat = Latitude;
345 temp_data.gLon = Longitude;
352 bool CommDecoder::DecodePGN129540(std::vector<unsigned char> v,
NavData& temp_data) {
355 uint8_t NumberOfSVs;;
356 tN2kRangeResidualMode Mode;
358 if (ParseN2kPGN129540(v, SID, Mode, NumberOfSVs)) {
359 temp_data.n_satellites = NumberOfSVs;
367 bool CommDecoder::DecodeSignalK(std::string s,
NavData& temp_data){
368 rapidjson::Document root;
371 if (root.HasParseError())
374 if (root.HasMember(
"updates") && root[
"updates"].IsArray()) {
375 for (rapidjson::Value::ConstValueIterator itr = root[
"updates"].Begin(); itr != root[
"updates"].End(); ++itr) {
376 handleUpdate(*itr, temp_data);
383 void CommDecoder::handleUpdate(
const rapidjson::Value &update,
NavData& temp_data) {
384 wxString sfixtime =
"";
386 if (update.HasMember(
"timestamp")) {
387 sfixtime = update[
"timestamp"].GetString();
389 if (update.HasMember(
"source") && update[
"source"].HasMember(
"src")) {
390 src_string = update[
"source"][
"src"].GetString();
393 if (update.HasMember(
"values") && update[
"values"].IsArray()) {
394 for (rapidjson::Value::ConstValueIterator itr = update[
"values"].Begin(); itr != update[
"values"].End(); ++itr) {
395 updateItem(*itr, sfixtime, temp_data);
400 void CommDecoder::updateItem(
const rapidjson::Value &item,
401 wxString &sfixtime,
NavData& temp_data) {
402 bool bposValid =
false;
403 if (item.HasMember(
"path") && item.HasMember(
"value")) {
404 const wxString &update_path = item[
"path"].GetString();
406 if (update_path == _T(
"navigation.gnss.methodQuality")) {
408 if (src_string.size()) {
409 if (item[
"value"] ==
"no GPS") {
410 GNSS_quality_map[src_string] = 0;
412 GNSS_quality_map[src_string] = 1;
417 if (update_path == _T(
"navigation.position") && !item[
"value"].IsNull()) {
418 bposValid = updateNavigationPosition(item[
"value"], sfixtime, temp_data);
422 if (GNSS_quality_map.find(src_string) != GNSS_quality_map.end()) {
423 if (GNSS_quality_map[src_string] == 0) {
424 temp_data.gLat = NAN;
428 }
else if (update_path == _T(
"navigation.speedOverGround") &&
429 !item[
"value"].IsNull()) {
430 updateNavigationSpeedOverGround(item[
"value"], sfixtime, temp_data);
434 if (GNSS_quality_map.find(src_string) != GNSS_quality_map.end()) {
435 if (GNSS_quality_map[src_string] == 0) {
440 }
else if (update_path == _T(
"navigation.courseOverGroundTrue") &&
441 !item[
"value"].IsNull()) {
442 updateNavigationCourseOverGround(item[
"value"], sfixtime, temp_data);
443 }
else if (update_path == _T(
"navigation.courseOverGroundMagnetic")) {
445 else if (update_path ==
446 _T(
"navigation.gnss.satellites"))
448 updateGnssSatellites(item[
"value"], sfixtime, temp_data);
449 }
else if (update_path ==
450 _T(
"navigation.gnss.satellitesInView"))
452 updateGnssSatellites(item[
"value"], sfixtime, temp_data);
453 }
else if (update_path == _T(
"navigation.headingTrue")) {
454 if(!item[
"value"].IsNull())
455 updateHeadingTrue(item[
"value"], sfixtime, temp_data);
456 }
else if (update_path == _T(
"navigation.headingMagnetic")) {
457 if(!item[
"value"].IsNull())
458 updateHeadingMagnetic(item[
"value"], sfixtime, temp_data);
459 }
else if (update_path == _T(
"navigation.magneticVariation")) {
460 if(!item[
"value"].IsNull())
461 updateMagneticVariance(item[
"value"], sfixtime, temp_data);
469 bool CommDecoder::updateNavigationPosition(
470 const rapidjson::Value &value,
const wxString &sfixtime,
NavData& temp_data) {
471 if ((value.HasMember(
"latitude") && value[
"latitude"].IsDouble()) &&
472 (value.HasMember(
"longitude") && value[
"longitude"].IsDouble())) {
474 temp_data.gLat = value[
"latitude"].GetDouble();
475 temp_data.gLon = value[
"longitude"].GetDouble();
483 void CommDecoder::updateNavigationSpeedOverGround(
484 const rapidjson::Value &value,
const wxString &sfixtime,
NavData& temp_data){
485 double sog_ms = value.GetDouble();
486 double sog_knot = sog_ms * 1.9438444924406;
488 temp_data.gSog = sog_knot;
491 void CommDecoder::updateNavigationCourseOverGround(
492 const rapidjson::Value &value,
const wxString &sfixtime,
NavData& temp_data) {
493 double cog_rad = value.GetDouble();
494 double cog_deg = GEODESIC_RAD2DEG(cog_rad);
496 temp_data.gCog = cog_deg;
499 void CommDecoder::updateGnssSatellites(
const rapidjson::Value &value,
500 const wxString &sfixtime,
504 if (value.GetInt() > 0) {
505 temp_data.n_satellites = value.GetInt();
507 }
else if ((value.HasMember(
"count") && value[
"count"].IsInt())) {
508 temp_data.n_satellites = value[
"count"].GetInt();
511 if (GNSS_quality_map.find(src_string) != GNSS_quality_map.end()) {
512 if (GNSS_quality_map[src_string] == 0) {
513 temp_data.n_satellites = 0;
518 void CommDecoder::updateHeadingTrue(
const rapidjson::Value &value,
519 const wxString &sfixtime,
521 temp_data.gHdt = GEODESIC_RAD2DEG(value.GetDouble());
524 void CommDecoder::updateHeadingMagnetic(
525 const rapidjson::Value &value,
const wxString &sfixtime,
527 temp_data.gHdm = GEODESIC_RAD2DEG(value.GetDouble());
530 void CommDecoder::updateMagneticVariance(
531 const rapidjson::Value &value,
const wxString &sfixtime,
533 temp_data.gVar = GEODESIC_RAD2DEG(value.GetDouble());