我正在使用SerialPort Ruby gem来编写和读取一个串口,使用Ruby脚本“driver”。
我想从Windows和Linux Os运行该应用程序; 顺便说一句,下面的代码已在Windows 7上测试过。
具体来说,我必须在热敏打印机上打印ESC / POS文本数据, 连接到带有串行线(COM / USB端口)的主机。
我在打印机上写数据时没有任何问题(优质廉价的Epson TM-T20)!
但我必须管理错误/连接状态从设备读取数据,
通过示例查看打印机是否打开电源(在线)我会通过某些ESC / POS通讯向打印机设备询问打印机状态。
问题出现的原因是,即使我设置串口超时(我的意思是SerialPort类初始化程序的settimg超时参数),没有异常处理,这似乎没有宝石预见:-(,我无法理解是否打印机处于活动状态或已关闭电源。请参阅一大堆代码:
begin
printer = SerialPort.new PRINTER_SERIALPORT_NAME, BAUDRATE
# http://curiosity.roguepenguin.net/?p=35
# timeouts are in milliseconds
printer.read_timeout = 2000
printer.write_timeout = 2000
puts "Success for SerialPort: #{ printer.inspect }"
rescue => e
puts "Failed to open as SerialPort: #{ e.inspect }"
end
使用上面的代码,printer.read
实际上从2000毫秒退出..但我不知道是否因为我有少于预期的(0)字节返回..或因为设备断电。
所以,我尝试使用Ruby Timeout(http://ruby-doc.org/stdlib-2.0.0/libdoc/timeout/rdoc/Timeout.html),从Winows 7 shell运行脚本,但不幸的是下面的代码没有按预期运行(如果打印机关闭,printer.read
HANG ,我的意思是不要退出:-(,我没有预期的Timeout::Error
); stange不是吗?
begin
Timeout.timeout(2) do
puts printer.read
end
rescue Timeout::Error
puts "SerialPort timeout."
rescue => e
puts "Serialport ERROR: Failed to open: #{ e.inspect }"
end
有什么想法解决问题吗?
谢谢
乔治
答案 0 :(得分:0)
从我收集的文档中我指出,当指定read_timeout
时,读取操作将立即返回(非阻塞),因此永远不会像您期望的那样导致Timeout::Error
。
你能尝试设置0的超时,根据文档将阻塞,直到一个字节可用,看看Ruby是否会引发Timeout::Error
?
或者尝试根本不设置超时,看看是否有效。
或者你可以指定一个否定超时,它会立即返回任何可用的数据,并根据它做出决定。
答案 1 :(得分:0)
抱歉回答自己的问题,只是为了分享一些测试,也遵循rkhon的建议:
前提: 我现在正在使用带有USB连接的PC上的Epson TM-T20打印机在Windows 7上使用Ruby 2.0进行测试(以及串行端口 - USB Epson" matcher")
关于SerialPort(读取)超时测试:
如果我设置:
printer.read_timeout <= 0
serialport read hang(不返回控件)
如果我设置:
printer.read_timeout > 0
# read 1 byte
printer.read(1)
如果读缓冲区中没有AVAILABLE字节,则在read_timeout毫秒后返回,否则立即返回读取的字节。 好的!
BTW,似乎串口宝石超时运行优先级(WIN)与Ruby语言超时支持;这意味着,如果我设置printer.read_timeout = 2000
,之后我会
# 1000 msecs
Timeout.timeout(1) do
puts printer.read
end
然而,我在2000毫秒后得到了控制权......
管理错误/连接状态: 即使我不能使用异常超时,我也可以检查打印机的电源开启/连接状态,而且没有明确的超时异常...
我验证了如果我向打印机发送(写入)DLE EOT m(STATUS请求) 我回来了(读)没有数据(无)
希望报告有用......