用Ruby创建数据包

3

我正在尝试使用ruby-serialport创建一个要通过串口发送的数据包。这似乎应该很简单,当我只写一个字符串时它可以正常工作:

packet = "\xFF\x03\x10\x01\x01\xFE"
sp.write(packet)
=>hardware does what it's supposed to, opens the door represented by the 4th hex value

但我显然需要以编程方式完成这个任务,但我无法找到正确的方法。这里只是我尝试过的一些方法:

door = 1    
packet = "\xFF\x03\x10" + door.to_s(16) + "\x01\xFE"
sp.write(packet)
=> can't convert fixnum into string

并且

door = 1
packet = "\xFF\x03\x10" + door.to_a.pack('H*') + "\x01\xFE"
sp.write(packet)
=> to_a will be obsolete
can't convert fixnum into string

并且

door = 1
sp.write("\xFF\x03\x10")
sp.write(door)
sp.write("\x01\xFE")
=>no response from hardware

有人能帮我正确地将数字转换为串口所需的十六进制表示法,并与其他十六进制字符串连接吗?提前感谢!

2个回答

4

如果您坚持使用字符串来表示二进制数据,那么您真的会遇到麻烦。您真正需要的是pack函数:

packet = [ 0xFF, 0x30, 0x10, door, 0x01, 0xFE ].pack('C*')

这使得构建和拆解任意二进制数据变得非常容易。该方法不仅支持无符号字符,还支持许多其他常用类型。
你甚至可以构建自己的方法来读写这些数据:
def write_packet(*bytes)
  sp.write(bytes.flatten.pack('C*'))
end

1
没错,这非常有道理,这就是我在接收端要做的事情,我想我只是在编写端变得懒惰了(并且非常缺乏在这个低级别工作方面的经验),因为我正在使用的东西有两个需要一个变量的命令。但最好还是正确地做,非常感谢您的建议。 - jack_was_taken
1
请注意,在 Ruby 1.9 中使用 chr 可能会与 UTF-8 或默认字符集发生冲突。确保您的文件句柄以 BINARY 模式打开,否则您可能会发现字符被转换,数据流将被破坏。Ruby 1.8 生活在字符编码的“无知是福”的世界中。当使用 chr 时,对于 door 值 > 127,我会收到 Encoding::CompatibilityError 错误。pack 是处理这个问题的唯一明智的方法。 - tadman

3

试试这个:

door = 1    
packet = "\xFF\x03\x10" + door.chr + "\x01\xFE"

哦,太棒了,谢谢!我感觉自己很傻,没有仔细查看整数方法。非常感激。 - jack_was_taken
在 Ruby 1.9 版本中,当 door 的值超过 127 时,使用 UTF-8 编码将无法正常工作。 - tadman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接