Strange code behavior - udp:receivefrom() always receiving the same data

Dear All,

I’m currently trying to read UDP messages from a flight simulator called X-Plane. 

All data are sent as bytes:
 

  • There are 41 bytes per sentence
  • The first 5 bytes are the message header, or “prologue”
  • First 4 of the 5 prologue bytes are the message type, like “DATA”
  • Fifth byte of prologue is an “internal-use” byte
  • The next 36 bytes are the message
  • First 4 bytes of message indicates the index number of a data element, as shown in the Data Output screen in X-Plane. For example, 18 is the speed of your aircraft.
  • Last 32 bytes is the data, up to 8 single-precision floating point numbers

Here is a raw data string sent from X-Plane:

68 65 84 65 60 18 0 0 0 171 103 81 191 187 243 46 190 103 246 45 67 156 246 26 67 47 231 26 67 0 192 121 196 0 192 121 196 85 254 151 193

I wrote a small C# console application to test the behavior of the server and I receive the correct heading of the plane without any problem.

Here is the working C# code:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace XPlaneReader { class Program { static void Main(string[] args) { byte[] data = new byte[1024]; IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 49003); UdpClient newsock = new UdpClient(ipep); Console.WriteLine("Waiting for a client..."); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); while (!Console.KeyAvailable) { data = newsock.Receive(ref sender); int numDatasets = (data.Length - 5) / 36; string buffer = string.Empty; for (int i = 0; i \< numDatasets; i++) { string msg = processMessage(data, (i \* 36) + 5); if (msg.Length \> 0) { buffer += msg; } } Console.WriteLine(buffer); } newsock.Close(); Console.ReadKey(); } private static string processMessage(byte[] data, int startIndex) { string retValue = string.Empty; // this is an index number that correspond to a specifix dataset in x-plane int datasetIndex = Convert.ToInt32(data[startIndex]); if (datasetIndex == 3) { // speed // these 32 bytes make up the 8 single-precision floating point numbers // sent in the message byte[] tmp = { data[startIndex + 4], data[startIndex + 5], data[startIndex + 6], data[startIndex + 7] }; float ias = BitConverter.ToSingle(tmp, 0); retValue = string.Format("{0,3:##0}", ias) + "KIAS "; } if (datasetIndex == 18) { // magnetic heading byte[] tmp = { data[startIndex + 16], data[startIndex + 17], data[startIndex + 18], data[startIndex + 19] }; float hdg = BitConverter.ToSingle(tmp, 0); retValue = string.Format("{0,3:##0}", hdg) + "DEG "; } if (datasetIndex == 20) { // altitude byte[] tmp = { data[startIndex + 24], data[startIndex + 25], data[startIndex + 26], data[startIndex + 27] }; float alt = BitConverter.ToSingle(tmp, 0); retValue = string.Format("{0,5:####0}", alt) + "FT "; } if (datasetIndex == 4) { // vvi byte[] tmp = { data[startIndex + 12], data[startIndex + 13], data[startIndex + 14], data[startIndex + 15] }; float vvi = BitConverter.ToSingle(tmp, 0); retValue = string.Format("{0,5:#####}", vvi) + "FPM "; } return retValue; } } }

Then, I tried to adapt the code in LUA. I had to use a function to convert the bytes received to floating numbers. But the logic of the code is basically the same.

But the behavior is totally different. For a mysterious reason, I’m always receiving the same data. I still continue to receive data from udp:receivefrom() even if the flight simulator is closed!

Here is my code (I’m must confess that I’m a beginner in Corona/LUA development)

 --socket test SERVER local socket = require "socket" local udp = socket.udp() udp:settimeout(0) udp:setsockname('\*', 49003) local data, msg\_or\_ip, port\_or\_nil function hex2float(c) if c == 0 then return 0.0 end local c = string.gsub(string.format("%X", c),"(..)",function (x) return string.char(tonumber(x, 16)) end) local b1,b2,b3,b4 = string.byte(c, 1, 4) local sign = b1 \> 0x7F local expo = (b1 % 0x80) \* 0x2 + math.floor(b2 / 0x80) local mant = ((b2 % 0x80) \* 0x100 + b3) \* 0x100 + b4 if sign then sign = -1 else sign = 1 end local n if mant == 0 and expo == 0 then n = sign \* 0.0 elseif expo == 0xFF then if mant == 0 then n = sign \* math.huge else n = 0.0/0.0 end else n = sign \* math.ldexp(1.0 + mant / 0x800000, expo - 0x7F) end return n end function processMessage(data2, startIndex) if (data~=nil) then datasetIndex = tonumber(string.byte(data2,startIndex+1)) if datasetIndex==18 then -- Speed print ("magnetic heading") single = "0x" .. string.format ("%0X",tonumber(string.byte(data2,startIndex+20))) .. string.format ("%0X",tonumber(string.byte(data2,startIndex+19))) .. string.format ("%0X",tonumber(string.byte(data2,startIndex+18))) .. string.format ("%0X",tonumber(string.byte(data2,startIndex+17))) print(string.format("Heading: %3d°",hex2float(single))) end end end local function revieveUdpMsg(event) print("Ready to recieve...") local running = true while running do data, msg\_or\_ip, port\_or\_nil = udp:receivefrom() if data ~= nil then print("Recieved: " .. data) numDataSets = (#data-5)/36 for i=0, numDataSets-1 do processMessage(data, (i\*36)+5) print(msg\_or\_ip) end running = false print("Server paused ") timer.performWithDelay( 3000, revieveUdpMsg ) elseif msg\_or\_ip ~= 'timeout' then error("Unknown network error: "..tostring(msg\_or\_ip)) end socket.sleep(0.01) end end timer.performWithDelay( 3000, revieveUdpMsg )

Any idea? 

Any suggestion will be highly appreciated!

Thanks in advance