我正在使用http://ruby-serialport.rubyforge.org/ 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
有什么想法解决这个问题吗?
谢谢
乔治
2 回答
从我收集的文档中我指出,当指定
read_timeout
时,读操作将立即返回(非阻塞),因此永远不会像您期望的那样导致Timeout::Error
.您可以尝试设置超时为0,根据文档将阻塞直到一个字节可用并查看Ruby是否会引发
Timeout::Error
?或者尝试根本不设置超时,看看是否有效 .
或者,您可以指定一个否定超时,它会立即返回任何可用的数据,并根据该超时做出决定 .
很抱歉回答自己的问题,只是为了分享一些测试,也遵循rkhon的建议:
前提:我现在正在使用带有USB连接的PC上的Epson TM-T20打印机(以及串行端口 - USB Epson“matcher”)在Windows 7上使用Ruby 2.0进行测试
关于SerialPort(读取)超时测试:
如果我设置:
printer.read_timeout <= 0
serialport读挂(不返回控件)
如果我设置:
printer.read_timeout > 0
如果读缓冲区中没有AVAILABLE字节,则在read_timeout毫秒后返回,否则立即返回读取的字节 . 没关系!
顺便说一句,看起来串口宝石超时运行优先级(WIN)对Ruby语言超时支持;这意味着,如果我设置
printer.read_timeout = 2000
,然后我做不过我在2000毫秒后得到了控制权......
管理错误/连接状态:即使我不能使用异常超时,我也可以检查打印机的电源开启/连接状态,也没有明确的超时异常...
我验证了如果我向打印机发送(写入)DLE EOT m(STATUS请求),我会回来(读取)NO DATA(nil)
希望报告有用......