@@ -576,6 +576,121 @@ void gnssReadTask(void *e)
576576 vTaskDelete (NULL );
577577}
578578
579+ // Force the NMEA Talker ID - if needed
580+ void forceTalkerId (const char *Id, char *msg, size_t maxLen)
581+ {
582+ if (msg[2 ] == *Id)
583+ return ; // Nothing to do
584+
585+ char oldTalker = msg[2 ];
586+ msg[2 ] = *Id; // Force the Talker ID
587+
588+ // Update the checksum: XOR chars between '$' and '*'
589+ size_t len = 1 ;
590+ uint8_t csum = 0 ;
591+ while ((len < maxLen) && (msg[len] != ' *' ))
592+ csum = csum ^ msg[len++];
593+
594+ if (len >= (maxLen - 3 ))
595+ {
596+ // Something went horribly wrong. Restore the Talker ID
597+ msg[2 ] = oldTalker;
598+ return ;
599+ }
600+
601+ len++; // Point at the checksum and update it
602+ sprintf (&msg[len], " %02X" , csum);
603+ }
604+
605+ // Force the RMC COG entry - if needed
606+ void forceRmcCog (char *msg, size_t maxLen)
607+ {
608+ const char *noCog = " 0.0" ;
609+
610+ if (strstr (msg, " RMC" ) == nullptr )
611+ return ; // Nothing to do
612+
613+ if (maxLen < (strlen (msg) + strlen (noCog)))
614+ return ; // No room for the COG!
615+
616+ // Find the start of COG ("Track made good") - after the 8th comma
617+ int numCommas = 0 ;
618+ size_t len = 0 ;
619+ while ((numCommas < 8 ) && (len < maxLen))
620+ {
621+ if (msg[len++] == ' ,' )
622+ numCommas++;
623+ }
624+
625+ if (len >= maxLen) // Something went horribly wrong
626+ return ;
627+
628+ // If the next char is not a ',' - there's nothing to do
629+ if (msg[len] != ' ,' )
630+ return ;
631+
632+ // If the next char is a ',' - add "0.0" manually
633+ // Start by creating space for the "0.0"
634+ for (size_t i = strlen (msg); i > len; i--) // Work backwards from the NULL
635+ msg[i + strlen (noCog)] = msg[i];
636+
637+ // Now insert the "0.0"
638+ memcpy (&msg[len], noCog, strlen (noCog));
639+
640+ // Update the checksum: XOR chars between '$' and '*'
641+ len = 1 ;
642+ uint8_t csum = 0 ;
643+ while ((len < maxLen) && (msg[len] != ' *' ))
644+ csum = csum ^ msg[len++];
645+ len++; // Point at the checksum and update it
646+ sprintf (&msg[len], " %02X" , csum);
647+ }
648+
649+ // Remove the RMC Navigational Status field - if needed
650+ void removeRmcNavStat (char *msg, size_t maxLen)
651+ {
652+ if (strstr (msg, " RMC" ) == nullptr )
653+ return ; // Nothing to do
654+
655+ // Find the start of Nav Stat - at the 13th comma
656+ int numCommas = 0 ;
657+ size_t len = 0 ;
658+ while ((numCommas < 13 ) && (msg[len] != ' *' ) && (len < maxLen))
659+ {
660+ if (msg[len++] == ' ,' )
661+ numCommas++;
662+ }
663+
664+ if (len >= (maxLen - 3 )) // Something went horribly wrong
665+ return ;
666+
667+ // If the next char is '*' - there's nothing to do
668+ if ((msg[len] == ' *' ) || (numCommas < 13 ))
669+ return ;
670+
671+ // Find the asterix. (NavStatus should be a single char)
672+ size_t asterix = len;
673+ len--;
674+
675+ while ((msg[asterix] != ' *' ) && (asterix < maxLen))
676+ asterix++;
677+
678+ if (msg[asterix] != ' *' ) // Something went horribly wrong
679+ return ;
680+
681+ // Delete the NavStat
682+ for (size_t i = 0 ; i < (strlen (msg) + 1 - asterix); i++) // Copy the * CSUM NULL
683+ msg[len + i] = msg[asterix + i];
684+
685+ // Update the checksum: XOR chars between '$' and '*'
686+ len = 1 ;
687+ uint8_t csum = 0 ;
688+ while ((len < maxLen) && (msg[len] != ' *' ))
689+ csum = csum ^ msg[len++];
690+ len++; // Point at the checksum and update it
691+ sprintf (&msg[len], " %02X" , csum);
692+ }
693+
579694// Call back from within parser, for end of message
580695// Process a complete message incoming from parser
581696// If we get a complete NMEA/UBX/RTCM message, pass on to SD/BT/TCP/UDP interfaces
@@ -642,6 +757,7 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type)
642757 latestGPGGA[parse->length ] = 0 ; // NULL terminate
643758 if ((strlen (latestGPGGA) > 10 ) && (latestGPGGA[strlen (latestGPGGA) - 2 ] == ' \r ' ))
644759 latestGPGGA[strlen (latestGPGGA) - 2 ] = 0 ; // Truncate the \r\n
760+ forceTalkerId (" P" ,latestGPGGA,latestNmeaMaxLen);
645761 }
646762 else
647763 systemPrintf (" Increase latestNmeaMaxLen to > %d\r\n " , parse->length );
@@ -654,6 +770,9 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type)
654770 latestGPRMC[parse->length ] = 0 ; // NULL terminate
655771 if ((strlen (latestGPRMC) > 10 ) && (latestGPRMC[strlen (latestGPRMC) - 2 ] == ' \r ' ))
656772 latestGPRMC[strlen (latestGPRMC) - 2 ] = 0 ; // Truncate the \r\n
773+ forceTalkerId (" P" ,latestGPRMC,latestNmeaMaxLen);
774+ forceRmcCog (latestGPRMC,latestNmeaMaxLen);
775+ removeRmcNavStat (latestGPRMC,latestNmeaMaxLen);
657776 }
658777 else
659778 systemPrintf (" Increase latestNmeaMaxLen to > %d\r\n " , parse->length );
@@ -666,6 +785,7 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type)
666785 latestGPGST[parse->length ] = 0 ; // NULL terminate
667786 if ((strlen (latestGPGST) > 10 ) && (latestGPGST[strlen (latestGPGST) - 2 ] == ' \r ' ))
668787 latestGPGST[strlen (latestGPGST) - 2 ] = 0 ; // Truncate the \r\n
788+ forceTalkerId (" P" ,latestGPGST,latestNmeaMaxLen);
669789 }
670790 else
671791 systemPrintf (" Increase latestNmeaMaxLen to > %d\r\n " , parse->length );
0 commit comments