@@ -721,7 +721,7 @@ void ntripClientUpdate()
721721 {
722722 // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA
723723 theGNSS.setVal8 (UBLOX_CFG_NMEA_MAINTALKERID, 1 );
724- theGNSS.setNMEAGPGGAcallbackPtr (&pushGPGGA ); // Set up the callback for GPGGA
724+ theGNSS.setNMEAGPGGAcallbackPtr (&newGPGGA ); // Set up the callback for GPGGA
725725
726726 float measurementFrequency = (1000.0 / settings.measurementRate ) / settings.navigationRate ;
727727 if (measurementFrequency < 0.2 )
@@ -850,6 +850,9 @@ void ntripClientUpdate()
850850 }
851851 }
852852 }
853+
854+ // Now that the ntripClient->read is complete, write GPGGA if needed and available. See RTK Everywhere issue #695
855+ pushGPGGA (nullptr );
853856 }
854857 break ;
855858 }
@@ -869,24 +872,60 @@ void ntripClientValidateTables()
869872 reportFatalError (" Fix ntripClientStateNameEntries to match NTRIPClientState" );
870873}
871874
872- void pushGPGGA (NMEA_GGA_data_t *nmeaData)
875+ void newGPGGA (NMEA_GGA_data_t *nmeaData)
876+ {
877+ // New GPGGA data received from GNSS. Store it. ntripClientUpdate will push it.
878+ pushGPGGA ((char *)nmeaData->nmea );
879+ }
880+
881+ // Periodically push GGA sentence over NTRIP Client, to Caster, if enabled
882+ // We must not push to the Caster while we are reading data from the Caster
883+ // See RTK Everywhere Issue #695
884+ // pushGPGGA is called by processUart1Message from gnssReadTask
885+ // ntripClient->read is called by ntripClientUpdate and ntripClientResponse from networkUpdate from loop
886+ // We need to make sure processUart1Message doesn't gatecrash
887+ // If ggaData is provided, store it. If ggaData is nullptr, try to push it
888+ static void pushGPGGA (char *ggaData)
873889{
874- // Provide the caster with our current position as needed
875- if (ntripClient->connected () && settings.ntripClient_TransmitGGA == true )
890+ static char storedGPGGA[100 ];
891+
892+ static SemaphoreHandle_t reentrant = xSemaphoreCreateMutex (); // Create the mutex
893+
894+ if (xSemaphoreTake (reentrant, 10 / portTICK_PERIOD_MS) == pdPASS)
876895 {
877- if (millis () - lastGGAPush > NTRIPCLIENT_MS_BETWEEN_GGA )
896+ if (ggaData )
878897 {
879- lastGGAPush = millis ();
898+ snprintf (storedGPGGA, sizeof (storedGPGGA), " %s" , ggaData);
899+ xSemaphoreGive (reentrant);
900+ return ;
901+ }
880902
881- if (settings.debugNtripClientRtcm || PERIODIC_DISPLAY (PD_NTRIP_CLIENT_GGA))
903+ #ifdef COMPILE_NETWORK
904+ // Wait until the client has been created
905+ if (ntripClient != nullptr )
906+ {
907+ // Provide the caster with our current position as needed
908+ if (ntripClient->connected () && settings.ntripClient_TransmitGGA == true )
882909 {
883- PERIODIC_CLEAR (PD_NTRIP_CLIENT_GGA);
884- systemPrintf (" NTRIP Client pushing GGA to server: %s" , (const char *)nmeaData->nmea );
885- }
910+ if (millis () - lastGGAPush > NTRIPCLIENT_MS_BETWEEN_GGA)
911+ {
912+ lastGGAPush = millis ();
913+
914+ if ((settings.debugNtripClientRtcm || PERIODIC_DISPLAY (PD_NTRIP_CLIENT_GGA)) && !inMainMenu)
915+ {
916+ PERIODIC_CLEAR (PD_NTRIP_CLIENT_GGA);
917+ systemPrintf (" NTRIP Client pushing GGA to server: %s" , (const char *)storedGPGGA);
918+ }
886919
887- // Push our current GGA sentence to caster
888- ntripClient->print ((const char *)nmeaData->nmea );
920+ // Push our current GGA sentence to caster
921+ if (strlen (storedGPGGA) > 0 )
922+ ntripClient->write ((const uint8_t *)storedGPGGA, strlen (storedGPGGA));
923+ }
924+ }
889925 }
926+ #endif // COMPILE_NETWORK
927+
928+ xSemaphoreGive (reentrant);
890929 }
891930}
892931
0 commit comments