How to implement a callback using PyCall?

1 week ago 15
ARTICLE AD BOX

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>'
Read Entire Article