Декодировать UDP-сообщение с помощью LUA - PullRequest
0 голосов
/ 08 сентября 2018

Я относительно новичок в lua и программировании в целом (самоучка), поэтому, пожалуйста, будьте осторожны!

В любом случае, я написал скрипт lua для чтения UDP-сообщения из игры. Структура сообщения:

DATAxXXXXaaaaBBBBccccDDDDeeeeFFFFggggHHHH
DATAx = 4 letter ID and x = control character
XXXX = integer shows the group of the data (groups are known)
aaaa...HHHHH = 8 single-precision floating point numbers

Последние те цифры, которые мне нужно декодировать.

Если я распечатываю сообщение как полученное, оно выглядит примерно так:

DATA*{V???A?A?...etc.

Используя string.byte () , я получаю поток байтов, подобных этому (я «отформатировал» байты, чтобы отразить структуру выше.

68 65 84 65/42/20 0 0 0/237 222 28 66/189 59 182 65/107 42 41 65/33 173 79 63/0 0 128 63/146 41 41 65/0 0 30 66/0 0 184 65

Первые 5 байтов - это, конечно, ДАННЫЕ *. Следующие 4 являются 20-й группой данных. Следующие байты, которые мне нужно декодировать, равны этим значениям:

237 222 28 66 = 39.218
189 59 182 65 = 22.779
107 42 41 65 = 10.573
33 173 79 63 = 0.8114
0 0 128 63 = 1.0000
146 41 41 65 = 10.573
0 0 30 66 = 39.500
0 0 184 65 = 23.000

Я нашел код C #, который выполняет декодирование с помощью BitConverter.ToSingle () , но я не нашел ничего подобного для Lua. Есть идеи?

Ответы [ 2 ]

0 голосов
/ 09 сентября 2018

Какая у вас версия Lua?
Этот код работает в Lua 5.3

local str = "DATA*\20\0\0\0\237\222\28\66\189\59\182\65..."
-- Read two float values starting from position 10 in the string
print(string.unpack("<ff", str, 10))  -->  39.217700958252  22.779169082642 18
-- 18 (third returned value) is the next position in the string

Для Lua 5.1 вы должны написать специальную функцию (или украсть ее из git repo Франсуа Перрада )

local function binary_to_float(str, pos)
   local b1, b2, b3, b4 = str:byte(pos, pos+3)
   local sign = b4 > 0x7F and -1 or 1
   local expo = (b4 % 0x80) * 2 + math.floor(b3 / 0x80)
   local mant = ((b3 % 0x80) * 0x100 + b2) * 0x100 + b1
   local n
   if mant + expo == 0 then
      n = sign * 0.0
   elseif expo == 0xFF then
      n = (mant == 0 and sign or 0) / 0
   else
      n = sign * (1 + mant / 0x800000) * 2.0^(expo - 0x7F)
   end
   return n
end


local str = "DATA*\20\0\0\0\237\222\28\66\189\59\182\65..."
print(binary_to_float(str, 10))  --> 39.217700958252
print(binary_to_float(str, 14))  --> 22.779169082642
0 голосов
/ 08 сентября 2018

Порядковый порядок байтов в двоичном коде IEEE-754 с одинарной точностью:

Например, 0 0 128 63:

00111111 10000000 00000000 00000000 (63) (128) (0) (0)

Почему это равно 1 требует, чтобы вы понимали самые основы представления IEEE-754, а именно использование им показателя степени и мантиссы. См. здесь , чтобы начать.

См. Ответ @ Егора выше о том, как использовать string.unpack() в Lua 5.3 и одну возможную реализацию, которую вы могли использовать в более ранних версиях.

...