【问题标题】:packet creation in rubyruby 中的数据包创建
【发布时间】:2011-08-12 18:29:55
【问题描述】:

我正在尝试创建一个数据包以使用 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

任何人都可以帮助我了解如何将数字正确转换为串行端口的正确十六进制表示法并加入其他十六进制字符串吗?提前致谢!

【问题讨论】:

    标签: ruby hex serial-port


    【解决方案1】:

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

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

    这使得构造和解构任意二进制数据变得非常容易。该方法不仅支持无符号字符,还支持各种常用的其他类型。

    您甚至可能想要构建自己的方法来读写:

    def write_packet(*bytes)
      sp.write(bytes.flatten.pack('C*'))
    end
    

    【讨论】:

    • 对,这很有意义,这就是我在接收端所做的,我想我只是在写作端偷懒(而且在这个低级别的工作非常缺乏经验)因为我正在与之交互的东西有两个命令,每个命令都需要一个变量。不过最好还是做对吧,非常感谢您的建议。
    • 请记住,在 Ruby 1.9 下使用 chr 您可能会遇到与 UTF-8 或默认字符集的冲突。确保您的文件句柄在BINARY 模式下打开,否则您可能会发现字符在您身上被转换并且数据流将被破坏。 Ruby 1.8 生活在“无知就是幸福”的字符编码世界中。使用 chr 时,door 值 > 127 时出现 Encoding::CompatibilityError 错误。 pack 是处理这个问题的唯一明智的方法。
    【解决方案2】:

    试试这个:

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

    【讨论】:

    • 哦,太棒了,谢谢!我为不仔细研究整数方法而感到愚蠢。真的很感激。
    • 这在使用 UTF-8 编码的 Ruby 1.9 中对于超过 127 的 door 值不起作用。
    猜你喜欢
    • 2012-09-23
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多