Hello.
I have written an NTRIP client that connects to a network and then receives data until the connection is closed. The issue I am having is that occasionally client:receive() will hang and not return at all. I have set the timeout to be 5 seconds but when this error occurs the timeout does not kick in and the function does not receive nil as it should on a timeout.
Has anyone seen this issue before?
Here are the three chunks of code that are relevant to this issue:
Thank you very much!
Chunk 1 is the GETNTRIPMessage function which calls NTRIP.GetNewByte()
function GetNTRIPMessage()
-- this function will get data byte by byte from the NTRIP connection and parse through it to find NCT or RTCM messages.
-- It will return the Buffer, Buffer Length, and Message Number when found
local NTRIPBuffer = {}
local NTRIPBufferIndex = 0
local NTRIPBufferLength = -1
local NTRIPMessageType = "NONE"
local Received = false
local NTRIPByte = 0
if(NTRIP.Connected) then
while true do
if(NTRIPBufferIndex > NTRIPBufferLength and NTRIPBufferLength ~= -1) then
return false -- if we have a buffer larger then we expected there was an error in reading message length so return false and try again
end
if(NTRIPBufferIndex == NTRIPBufferLength) then
-- we have the expected message lengthm so return true along with the message, length, and type
return true, NTRIPBuffer, NTRIPBufferLength, NTRIPMessageType
else
print("main.Line204 - Calling NTRIP.GetNewByte")
Received, NTRIPByte = NTRIP.GetNewByte(1)
print("main.Line206 - NTRIPByte - " .. NTRIPByte)
if(Received) then -- check to ensure we actually received a byte, if we did continue
if(NTRIPBufferIndex == 0) then -- if we are at the start of the buffer with no other bytes loaded
NTRIPBuffer[0] = NTRIPByte --NTRIP.GetNewByte() -- load a byte from the NTRIP connection into the buffer
if(NTRIPBuffer[0] == 0xD3 or NTRIPBuffer[0] == 0x02) then -- if the byte is an 0x02 or a 0xD3 then we may have an NCT or a RTCM message
NTRIPBufferIndex = NTRIPBufferIndex + 1 -- increment so we can start loading
end
elseif(NTRIPBufferIndex > 0 and NTRIPBufferIndex < 6) then -- we need 6 bytes to determing the length and message type so load that many in
NTRIPBuffer[NTRIPBufferIndex] = NTRIPByte
NTRIPBufferIndex = NTRIPBufferIndex + 1
elseif(NTRIPBufferIndex == 6 ) then -- if we have 6 bytes loaded we can check the length and message type
NTRIPBuffer[NTRIPBufferIndex] = NTRIPByte
if(NTRIPBuffer[0] == 0xD3) then -- we have an RTCM Message, so get the length and message type
NTRIPBufferLength = bit32.lshift(bit32.band(NTRIPBuffer[1], 0x03), 8) + NTRIPBuffer[2] + 6
NTRIPMessageType = bit32.lshift(NTRIPBuffer[3], 4) + bit32.rshift(NTRIPBuffer[4], 4)
local Valid, MessageRemainder = NTRIP.GetNewByte(NTRIPBufferLength-7) -- now receive the remainder of the message
if(Valid) then -- if it was succesful in receiving, copy to buffer.
local ReceivedIndex = 1
for i = NTRIPBufferIndex+1, NTRIPBufferLength-1, 1 do
NTRIPBuffer[i] = string.byte(MessageRemainder,ReceivedIndex)
ReceivedIndex = ReceivedIndex +1
end
NTRIPBufferIndex = NTRIPBufferLength
else
return false -- we did not receive all of the message
end
elseif(NTRIPBuffer[0] == 0x02) then -- we have an NCT message, so get the length and message type
NTRIPBufferLength = bit32.bor(NTRIPBuffer[4], bit32.lshift(NTRIPBuffer[5], 8)) + 4
NTRIPMessageType = NTRIPBuffer[3]
local Valid, MessageRemainder = NTRIP.GetNewByte(NTRIPBufferLength-7) -- now receive the remainder of the message
if(Valid) then
local ReceivedIndex = 1
for i = NTRIPBufferIndex+1, NTRIPBufferLength-1, 1 do
NTRIPBuffer[i] = string.byte(MessageRemainder,ReceivedIndex)
ReceivedIndex = ReceivedIndex +1
end
NTRIPBufferIndex = NTRIPBufferLength
else
return false -- we did not receive all of the message
end
end -- ends the RTCM or NCT Statement
end -- end the 6 byte statement
else
return false -- if we did not receive a byte return false
end
end -- end of the main if statement to check for a full message or continue looping if not full.
end -- end of the while loop for receiving
else -- we are not connected
return false
end
end
Here is the NTRIP.GetNewByte() function
function NTRIP.GetNewByte(bytes)
print("NTRIP.Line93 - Beginning of function")
if(NTRIP.NTRIPConnection ~= nil) then
print("NTRIP.Line95 - NTRIP.NTRIPConnection is not nil, begin receive " .. bytes .. " bytes")
local received = assert(NTRIP.NTRIPConnection:receive(bytes))
print("NTRIP.Line97 - NTRIP.NTRIPConnection receive finished")
if(received == nil) then
print("NTRIP.Line78 - Received nil")
return false, "0"
elseif (bytes == 1) then
print("NTRIP.Line81 - NTRIP Receive not nil, returning true + byte")
return true, str.byte(received)
else
return true, received
end
else
print("NTRIP.Line85 - NTRIP.NTRIPConnection is nil, returning false and 0")
return false, "0"
end
end
Finally here is where the NTRIP connection is initiated and the timeouts set
function NTRIP.Connect()
print("NTRIP.Line17 - NTRIP.Connect Entered")
if(NTRIP.NTRIPConnection ~= nil) then -- If we are trying to connect we had a data issue so delete and start over
print("NTRIP.Line19 - NTRIP.NTRIPConnection is not nil")
NTRIP.NTRIPConnection = nil
NTRIP.Connected = false
NTRIP.Status = "X"
end
print("NTRIP.Line24 - NTRIP.NTRIPConnection should now be nil, creating connection.")
print("NTRIP.Line25 - IP - \"" .. DataAsset.tree.downlink.NTRIP_IP .. "\" port - \"" .. DataAsset.tree.downlink.NTRIP_Port .. "\"")
NTRIP.NTRIPConnection = socket.connect(DataAsset.tree.downlink.NTRIP_IP, DataAsset.tree.downlink.NTRIP_Port) -- attempt connection
if(NTRIP.NTRIPConnection ~= nil) then -- if connection failes it will return nil, so only continue if not nil
print("NTRIP.Line28 - NTRIP connection is not nil, sending login")
NTRIP.NTRIPConnection:settimeout(5, 't') -- set timeout and then send login info
NTRIP.NTRIPConnection:settimeout(5, 'b')
-- build NTRIP login and send it
NTRIP.NTRIPConnection:send(NTRIP.BuildLogin(DataAsset.tree.downlink.NTRIP_Mount_Point, DataAsset.tree.downlink.NTRIP_Username, DataAsset.tree.downlink.NTRIP_Password))
print("NTRIP.Line33 - NTRIP Login sent, proceed to NTRIP")
NTRIP.Status = "C" -- this indicates we have a cell connectio
NTRIP.CheckConnection() -- now check the NTRIP connection response/
else -- if we fail reset
NTRIP.NTRIPConnection = nil
NTRIP.Status = "X"
NTRIP.Connected = false
end
end