From 3e3d20df055225e8e87bf914cf40ffc1144b8e0b Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 13 Sep 2023 15:02:56 -1000 Subject: [PATCH 1/6] NTRIP Client: Receive up to a buffer at once from the network --- Firmware/RTK_Surveyor/NtripClient.ino | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Firmware/RTK_Surveyor/NtripClient.ino b/Firmware/RTK_Surveyor/NtripClient.ino index 7c72e736a..fe3310076 100644 --- a/Firmware/RTK_Surveyor/NtripClient.ino +++ b/Firmware/RTK_Surveyor/NtripClient.ino @@ -758,25 +758,25 @@ void ntripClientUpdate() size_t rtcmCount = 0; // Collect any available RTCM data - while (ntripClientReceiveDataAvailable() > 0) + if (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)) - { - 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); + } + } } } } From 683803a589b23a30dabdede5040118acf9ef5b4c Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 13 Sep 2023 15:11:16 -1000 Subject: [PATCH 2/6] NTRIP Client: Reset attempt count & timeout after long connection --- Firmware/RTK_Surveyor/NtripClient.ino | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Surveyor/NtripClient.ino b/Firmware/RTK_Surveyor/NtripClient.ino index fe3310076..eba0fa320 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 { @@ -683,8 +686,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,6 +742,22 @@ 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) { From 1bc049e24ecf21660889f164a41b57f03fd9c636 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 13 Sep 2023 15:06:54 -1000 Subject: [PATCH 3/6] NTRIP Client: Force backoff when the client retries --- Firmware/RTK_Surveyor/NtripClient.ino | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Surveyor/NtripClient.ino b/Firmware/RTK_Surveyor/NtripClient.ino index eba0fa320..ab97f4cc8 100644 --- a/Firmware/RTK_Surveyor/NtripClient.ino +++ b/Firmware/RTK_Surveyor/NtripClient.ino @@ -308,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) { @@ -319,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) @@ -457,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 @@ -622,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); From 29a5eb89d80b4eeb964a1b19d7ae69767832c0b5 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 13 Sep 2023 15:13:34 -1000 Subject: [PATCH 4/6] NTRIP Client: Print NTRIP client connection and timeout times --- Firmware/RTK_Surveyor/NtripClient.ino | 42 ++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Surveyor/NtripClient.ino b/Firmware/RTK_Surveyor/NtripClient.ino index ab97f4cc8..5c9d60f34 100644 --- a/Firmware/RTK_Surveyor/NtripClient.ino +++ b/Firmware/RTK_Surveyor/NtripClient.ino @@ -661,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(); @@ -763,10 +781,26 @@ void ntripClientUpdate() // 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(); } } From 0fbdaf81956f5e9ab6802c6350028ae3b9f59fd7 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 13 Sep 2023 15:47:48 -1000 Subject: [PATCH 5/6] NTRIP Server: Reset attempt count & timeout after long connection --- Firmware/RTK_Surveyor/NtripServer.ino | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Surveyor/NtripServer.ino b/Firmware/RTK_Surveyor/NtripServer.ino index 87b983ca7..9aefa4fc3 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 { @@ -687,8 +690,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 +748,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(); } From ffa047c1334c3b765d5e568d87399185d3a47e33 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 13 Sep 2023 15:28:04 -1000 Subject: [PATCH 6/6] NTRIP Server: Force backoff when the caster link breaks --- Firmware/RTK_Surveyor/NtripServer.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Surveyor/NtripServer.ino b/Firmware/RTK_Surveyor/NtripServer.ino index 9aefa4fc3..221c9cbdb 100644 --- a/Firmware/RTK_Surveyor/NtripServer.ino +++ b/Firmware/RTK_Surveyor/NtripServer.ino @@ -262,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) { @@ -282,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) @@ -451,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