diff --git a/Firmware/RTK_Surveyor/NtripClient.ino b/Firmware/RTK_Surveyor/NtripClient.ino index 7c72e736a..5c9d60f34 100644 --- a/Firmware/RTK_Surveyor/NtripClient.ino +++ b/Firmware/RTK_Surveyor/NtripClient.ino @@ -145,6 +145,9 @@ static const int SERVER_BUFFER_SIZE = CREDENTIALS_BUFFER_SIZE + 3; static const int NTRIPCLIENT_MS_BETWEEN_GGA = 5000; // 5s between transmission of GGA messages, if enabled +// NTRIP client connection delay before resetting the connect accempt counter +static const int NTRIP_CLIENT_CONNECTION_TIME = 5 * 60 * 1000; + // Define the NTRIP client states enum NTRIPClientState { @@ -305,10 +308,12 @@ bool ntripClientConnectLimitReached() bool limitReached = (ntripClientConnectionAttempts >= MAX_NTRIP_CLIENT_CONNECTION_ATTEMPTS); // Restart the NTRIP client - ntripClientStop(limitReached); + ntripClientStop(limitReached || (!settings.enableNtripClient)); ntripClientConnectionAttempts++; ntripClientConnectionAttemptsTotal++; + if (settings.debugNtripClientState) + ntripClientPrintStatus(); if (limitReached == false) { @@ -316,7 +321,7 @@ bool ntripClientConnectLimitReached() ntripClientConnectionAttempts * 15 * 1000L; // Wait 15, 30, 45, etc seconds between attempts // Display the delay before starting the NTRIP client - if (ntripClientConnectionAttemptTimeout) + if (settings.debugNtripClientState && ntripClientConnectionAttemptTimeout) { seconds = ntripClientConnectionAttemptTimeout / 1000; if (seconds < 120) @@ -454,7 +459,7 @@ void ntripClientRestart() // Save the previous uptime value if (ntripClientState == NTRIP_CLIENT_CONNECTED) ntripClientStartTime = ntripClientTimer - ntripClientStartTime; - ntripClientStop(!settings.enableNtripClient); + ntripClientConnectLimitReached(); } // Update the state of the NTRIP client state machine @@ -619,7 +624,7 @@ void ntripClientUpdate() { // Socket opened to NTRIP system if (settings.debugNtripClientState) - systemPrintf("NTRIP client waiting for response from %s:%d\r\n", + systemPrintf("NTRIP Client waiting for response from %s:%d\r\n", settings.ntripClient_CasterHost, settings.ntripClient_CasterPort); ntripClientSetState(NTRIP_CLIENT_WAIT_RESPONSE); @@ -656,9 +661,27 @@ void ntripClientUpdate() // Look for various responses if (strstr(response, "200") != nullptr) //'200' found { - systemPrintf("NTRIP Client connected to %s:%d\r\n", - settings.ntripClient_CasterHost, - settings.ntripClient_CasterPort); + // Timeout receiving NTRIP data, retry the NTRIP client connection + if (online.rtc && online.gnss) + { + int hours; + int minutes; + int seconds; + + seconds = rtc.getLocalEpoch() % SECONDS_IN_A_DAY; + hours = seconds / SECONDS_IN_AN_HOUR; + seconds -= hours * SECONDS_IN_AN_HOUR; + minutes = seconds / SECONDS_IN_A_MINUTE; + seconds -= minutes * SECONDS_IN_A_MINUTE; + systemPrintf("NTRIP Client connected to %s:%d at %d:%02d:%02d\r\n", + settings.ntripClient_CasterHost, + settings.ntripClient_CasterPort, + hours, minutes, seconds); + } + else + systemPrintf("NTRIP Client connected to %s:%d\r\n", + settings.ntripClient_CasterHost, + settings.ntripClient_CasterPort); // Connection is now open, start the NTRIP receive data timer ntripClientTimer = millis(); @@ -683,8 +706,6 @@ void ntripClientUpdate() // We don't use a task because we use I2C hardware (and don't have a semphore). online.ntripClient = true; ntripClientStartTime = millis(); - ntripClientConnectionAttempts = 0; - ntripClientConnectionAttemptTimeout = 0; ntripClientSetState(NTRIP_CLIENT_CONNECTED); } else if (strstr(response, "401") != nullptr) @@ -741,13 +762,45 @@ void ntripClientUpdate() } else { + // Handle other types of NTRIP connection failures to prevent + // hammering the NTRIP caster with rapid connection attempts. + // A fast reconnect is reasonable after a long NTRIP caster + // connection. However increasing backoff delays should be + // added when the NTRIP caster fails after a short connection + // interval. + if (((millis() - ntripClientStartTime) > NTRIP_CLIENT_CONNECTION_TIME) + && (ntripClientConnectionAttempts || ntripClientConnectionAttemptTimeout)) + { + // After a long connection period, reset the attempt counter + ntripClientConnectionAttempts = 0; + ntripClientConnectionAttemptTimeout = 0; + if (settings.debugNtripClientState) + systemPrintln("NTRIP Client resetting connection attempt counter and timeout"); + } + // Check for timeout receiving NTRIP data if (ntripClientReceiveDataAvailable() == 0) { + // Don't fail during retransmission attempts if ((millis() - ntripClientTimer) > NTRIP_CLIENT_RECEIVE_DATA_TIMEOUT) { // Timeout receiving NTRIP data, retry the NTRIP client connection - systemPrintln("NTRIP Client timeout receiving data"); + if (online.rtc && online.gnss) + { + int hours; + int minutes; + int seconds; + + seconds = rtc.getLocalEpoch() % SECONDS_IN_A_DAY; + hours = seconds / SECONDS_IN_AN_HOUR; + seconds -= hours * SECONDS_IN_AN_HOUR; + minutes = seconds / SECONDS_IN_A_MINUTE; + seconds -= minutes * SECONDS_IN_A_MINUTE; + systemPrintf("NTRIP Client timeout receiving data at %d:%02d:%02d\r\n", + hours, minutes, seconds); + } + else + systemPrintln("NTRIP Client timeout receiving data"); ntripClientRestart(); } } @@ -758,25 +811,25 @@ void ntripClientUpdate() size_t rtcmCount = 0; // Collect any available RTCM data - while (ntripClientReceiveDataAvailable() > 0) - { - rtcmData[rtcmCount++] = ntripClient->read(); - if (rtcmCount == sizeof(rtcmData)) - break; - } - - // Restart the NTRIP receive data timer - ntripClientTimer = millis(); - - // Push RTCM to GNSS module over I2C / SPI - theGNSS.pushRawData(rtcmData, rtcmCount); - netIncomingRTCM = true; - - if ((settings.debugNtripClientRtcm || PERIODIC_DISPLAY(PD_NTRIP_CLIENT_DATA)) - && (!inMainMenu)) + if (ntripClientReceiveDataAvailable() > 0) { - PERIODIC_CLEAR(PD_NTRIP_CLIENT_DATA); - systemPrintf("NTRIP Client received %d RTCM bytes, pushed to ZED\r\n", rtcmCount); + rtcmCount = ntripClient->read(rtcmData, sizeof(rtcmData)); + if (rtcmCount) + { + // Restart the NTRIP receive data timer + ntripClientTimer = millis(); + + // Push RTCM to GNSS module over I2C / SPI + theGNSS.pushRawData(rtcmData, rtcmCount); + netIncomingRTCM = true; + + if ((settings.debugNtripClientRtcm || PERIODIC_DISPLAY(PD_NTRIP_CLIENT_DATA)) + && (!inMainMenu)) + { + PERIODIC_CLEAR(PD_NTRIP_CLIENT_DATA); + systemPrintf("NTRIP Client received %d RTCM bytes, pushed to ZED\r\n", rtcmCount); + } + } } } } diff --git a/Firmware/RTK_Surveyor/NtripServer.ino b/Firmware/RTK_Surveyor/NtripServer.ino index 87b983ca7..221c9cbdb 100644 --- a/Firmware/RTK_Surveyor/NtripServer.ino +++ b/Firmware/RTK_Surveyor/NtripServer.ino @@ -138,6 +138,9 @@ NtripServer.ino // 5 minutes. The NTRIP server stops retrying after 25 hours and 18 minutes static const int MAX_NTRIP_SERVER_CONNECTION_ATTEMPTS = 28; +// NTRIP client connection delay before resetting the connect accempt counter +static const int NTRIP_SERVER_CONNECTION_TIME = 5 * 60 * 1000; + // Define the NTRIP server states enum NTRIPServerState { @@ -259,10 +262,12 @@ bool ntripServerConnectLimitReached() bool limitReached = (ntripServerConnectionAttempts >= MAX_NTRIP_SERVER_CONNECTION_ATTEMPTS); // Shutdown the NTRIP server - ntripServerStop(limitReached); + ntripServerStop(limitReached || (!settings.enableNtripServer)); ntripServerConnectionAttempts++; ntripServerConnectionAttemptsTotal++; + if (settings.debugNtripServerState) + ntripServerPrintStatus(); if (limitReached == false) { @@ -279,7 +284,7 @@ bool ntripServerConnectLimitReached() (ntripServerConnectionAttempts - 4) * 5 * 60 * 1000L; // Wait 5, 10, 15, etc minutes between attempts // Display the delay before starting the NTRIP server - if (ntripServerConnectionAttemptTimeout) + if (settings.debugNtripServerState && ntripServerConnectionAttemptTimeout) { seconds = ntripServerConnectionAttemptTimeout / 1000; if (seconds < 120) @@ -448,7 +453,7 @@ void ntripServerRestart() // Save the previous uptime value if (ntripServerState == NTRIP_SERVER_CASTING) ntripServerStartTime = ntripServerTimer - ntripServerStartTime; - ntripServerStop(!settings.enableNtripServer); + ntripServerConnectLimitReached(); } // Update the state of the NTRIP server state machine @@ -687,8 +692,7 @@ void ntripServerUpdate() // We don't use a task because we use I2C hardware (and don't have a semphore). online.ntripServer = true; - ntripServerConnectionAttempts = 0; - ntripClientConnectionAttemptTimeout = 0; + ntripServerStartTime = millis(); ntripServerSetState(NTRIP_SERVER_CASTING); } @@ -746,6 +750,22 @@ void ntripServerUpdate() } else { + // Handle other types of NTRIP connection failures to prevent + // hammering the NTRIP caster with rapid connection attempts. + // A fast reconnect is reasonable after a long NTRIP caster + // connection. However increasing backoff delays should be + // added when the NTRIP caster fails after a short connection + // interval. + if (((millis() - ntripServerStartTime) > NTRIP_SERVER_CONNECTION_TIME) + && (ntripServerConnectionAttempts || ntripServerConnectionAttemptTimeout)) + { + // After a long connection period, reset the attempt counter + ntripServerConnectionAttempts = 0; + ntripServerConnectionAttemptTimeout = 0; + if (settings.debugNtripServerState) + systemPrintln("NTRIP Server resetting connection attempt counter and timeout"); + } + // All is well cyclePositionLEDs(); }