0

I would like to access a Python package in Ruby using PyCall.

The non-blocking function in the Python code below activates a callback.

Could you help me implement the callback?

#!/usr/bin/env python
# start_reading.py
import time
import mercury

def found(tag):
    print(tag.epc.decode()) # Check check
    # print(tags[1].epc.decode())

reader = mercury.Reader("tmr:///dev/ttyUSB0")

reader.start_reading(found, on_time=250, off_time=0)
time.sleep(0.5)
reader.stop_reading()

Output start_reading.py:

b'001853000000000000000012'
b'34155CACB400000000000125'
b'34155CACB400000000000125'
b'34155CACB400000000000125'
b'001853000000000000000012'
b'34155CACB400000000000125'
b'001853000000000000000012'
b'34155CACB400000000000125'
b'34155CACB400000000000125'

This pertains an api for ThingMagic RFID readers, which is a Python wrapper for the original api written in C.

From the docs:

reader.start_reading(callback, on_time=250, off_time=0)

Starts asynchronous reading. It returns immediately and begins a sequence of reads or a continuous read. The results are passed to the callback. The reads are repeated until the reader.stop_reading() method is called

  • callback(TagReadData) will be invoked for every tag detected
  • on_time sets the duration, in milliseconds, for the reader to be actively querying
  • off_time duration, in milliseconds, for the reader to be quiet while querying

As follows the parts I got working using a single read function. First the Python code, then Ruby.

#!/usr/bin/env python
# read.py
import mercury
reader = mercury.Reader("tmr:///dev/ttyUSB0")

data = reader.read()
print(data)
print(f"type: {type(data)}")

Output read.py:

[EPC(b'34155CACB400000000000125'), EPC(b'001853000000000000000012')]
type: <class 'list'>
#!/usr/bin/env ruby
# read.rb
require 'pycall/import'
include PyCall::Import
pyimport :mercury

reader = mercury.Reader.new("tmr:///dev/ttyUSB0")

python_data = reader.read() 
puts "python_data: #{python_data}"
puts "python class: #{python_data.class}"
puts ""
ruby_data = python_data.to_ary
puts "ruby_data: #{ruby_data}"
puts "ruby class: #{ruby_data.class}"

Output read.rb:

python_data: [EPC(b'34155CACB400000000000125'), EPC(b'001853000000000000000012')]
python class: <class 'list'>

ruby_data: [EPC(b'34155CACB400000000000125'), EPC(b'001853000000000000000012')]
ruby class: Array

The above works, as you can see.

The solution for the callback should be an improvement upon the following code.

#!/usr/bin/env ruby
# start_reading.rb
require 'pycall/import'
include PyCall::Import
pyimport :mercury

def found(tag)
  puts tag.epc
end

reader = mercury.Reader.new("tmr:///dev/ttyUSB0")

reader.start_reading(found, on_time=250, off_time=0) # What should I do here?
sleep(0.5)
reader.stop_reading()

Current output start_reading.rb

start_reading.rb:7:in `found': wrong number of arguments (given 0, expected 1) (ArgumentError)
    from start_reading.rb:14:in `<main>'
4
  • The example there in the docs is reader.start_reading(lambda tag: print(tag.epc)) - have you tried the same thing? reader.start_reading(lambda tag: found(tag), on_time=250, off_time=0) Commented 2 days ago
  • if you need a lambda it should be: reader.start_reading(->(tag){ puts tag.epc }, 250, 0) or reader.start_reading(method(:found), 250, 0) Commented 2 days ago
  • Thank you for your responses. I tried both lambda's, which don't not work, both offer the following response: .../pycall/pytypeobject_wrapper.rb:24:in `call_object': <class 'TypeError'>: Resource temporarily unavailable (PyCall::PyError). I think whatever is passed to the reader.start_reading() function should be something Python understands. Hence, I think I need a way to transform the found function (or the lambda) from Ruby to Python using PyCall - the same is true for the other two variables (which are optional so I omitted them in my test). Commented yesterday
  • maybe asynchronous version is just not supported github.com/red-data-tools/… Commented yesterday

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.