【问题标题】:Decode UDP message with LUA使用 LUA 解码 UDP 消息
【发布时间】:2019-02-13 18:26:50
【问题描述】:

我对 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 个字节当然是 DATA*。接下来的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

我找到了使用 BitConverter.ToSingle() 进行解码的 C# 代码,但我还没有为 Lua 找到类似的代码。 有什么想法吗?

【问题讨论】:

  • 您能否举一个在使用string.byte()之前收到的完整消息的示例?
  • 这里是一个使用 print() 的例子。 DATA*{V???A?A??:?y?g(???%A???: 不是上面的,而是类似的。
  • 您是如何确定上述字节数组的值的(例如,0 0 128 63 = 1.0000
  • 游戏是X-Plane飞行模拟器,这些数值可以在游戏中显示。这是capture from the game。它们是飞机的位置(坐标、高度等)

标签: lua floating-point coronasdk floating-point-conversion lua-5.1


【解决方案1】:

是 IEEE-754 单精度二进制的 little-endian 字节序:

例如,0 0 128 63 是:

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

为什么等于1 要求您了解 IEEE-754 表示的基础知识,即它使用指数和尾数。请参阅here 开始。

有关如何在 Lua 5.3 中使用 string.unpack() 以及您可以在早期版本中使用的一种可能实现,请参阅上面的 @Egor 的回答。

【讨论】:

  • 非常感谢@Brian。正是我需要的,一个前进的方向。我知道我需要为此编写一些代码,但这很好。
【解决方案2】:

你有什么 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,你必须编写特殊函数(或从 François Perrad's 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

【讨论】:

  • 非常感谢@Egor!直接解包收到的消息,适用于 Lua 5.3。 Here is the output。但是,我打算将它用于使用 Corona SDK 的移动应用程序,该 SDK 使用 Lua 5.1.3。我会看看我能做什么。
  • 非常感谢@Egor!我欠你一杯啤酒!
  • 也谢谢@Egor - 我很高兴我在下面错了!它迫使我深入研究string.unpack 文档。我会在您的答案中添加对第一个参数的解释,即字符串格式,其中&lt; 会将字符串标记为小端,ff 是让您返回两个浮点数的原因。对于 here 涵盖的字符串格式,还有其他选项
猜你喜欢
  • 2018-08-11
  • 1970-01-01
  • 2018-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多