I'm playing for the first time with asyncio in python and trying to combine it with ZMQ.
Basically my issue is that I have a REP/REQ system, in an async def
with a function I need to await. how the value is not updated. Here's a snippet of the code to illustrate that:
#Declaring the zmq contextcontext = zmq_asyncio.Context()REP_server_django = context.socket(zmq.REP)REP_server_django.bind("tcp://*:5558")
I send this object to a class and get it back in this function
async def readsonar(self, trigger_pin, REP_server_django): i= 0 while True: ping_from_view = await REP_server_django.recv() # line.1 value = await self.board.sonar_read(trigger_pin) # line.2 print(value) # line.3 json_data = json.dumps(value) # line.4 #json_data = json.dumps(i) # line.4bis REP_server_django.send(json_data.encode()) # line.5 i+=1 # line.6 await asyncio.sleep(1/1000) # line.7
the sonar_read
, is using pymata_express to read an ultrasonic sensor. If I comment line.2
and line.4
I get the right value for i
. If I comment line.1
and line.5
the print(value)
prints the correct value from sonar_read
. However, when I run it as shown here, the value
is not updated.
Am I missing something?
EDIT :
Edited a type regarding the line comments. What I meant is that if I only read the sonar and print the value. It works fine. If I only .recv()
and .send(json.dumps(i).encode())
, it works. But if I try to send the value from the sonar. It locks to a given value
which is not updated
EDIT2 : (answer to Alan Yorinks): here is the MWE, it considers what you sent regarding the declaration of zmq
in the class. It is taken from the pymata_express
example concurrent_tasks.py
To reproduce the error, run these two scripts in two different terminals. You will need an arduino board with Frimata_express installed. If all runs well, PART A.
should only spit out the same value on the mve_req.py
end. You may edit the diffrent blocks (PARTS A, B or C) to see the behaviour.
mve_rep.py
#ADAPTED FROM PYMATA EXPRESS EXAMPLE CONCURRENTTAKS#https://github.com/MrYsLab/pymata-express/blob/master/examples/concurrent_tasks.pyimport asyncioimport zmqimport jsonimport zmq.asyncio as zmq_asynciofrom pymata_express.pymata_express import PymataExpressclass ConcurrentTasks: def __init__(self, board): self.loop = board.get_event_loop() self.board = board self.ctxsync = zmq.Context() self.context = zmq.asyncio.Context() self.rep = self.context.socket(zmq.REP) self.rep.bind("tcp://*:5558") self.trigger_pin = 53 self.echo_pin = 51 loop.run_until_complete(self.async_init_and_run()) async def readsonar(self): i = 0 while True: #PART. A. WHAT I HOPE COULD WORK rep_recv = await self.rep.recv() # line.1 value = await self.board.sonar_read(self.trigger_pin) # line.2 print(value) # line.3 json_data = json.dumps(value) # line.4 # json_data = json.dumps(i) # line.4bis await self.rep.send(json_data.encode()) # line.5 i += 1 # line.6 await asyncio.sleep(1 / 1000) # line.7''' #PART. B. WORKS FINE IN UPDATING THE SONAR_RAED VALUE AND PRINTING IT value = await self.board.sonar_read(self.trigger_pin) # line.2 print(value) # line.3 json_data = json.dumps(value) # line.4 i += 1 # line.6 await asyncio.sleep(1 / 1000) # line.7'''''' #PART. C. WORKS FINE IN SENDING THE i VALUE OVER ZMQ rep_recv = await self.rep.recv() # line.1 json_data = json.dumps(i) # line.4bis await self.rep.send(json_data.encode()) # line.5 i += 1 # line.6 await asyncio.sleep(1 / 1000) # line.7''' async def async_init_and_run(self): await self.board.set_pin_mode_sonar(self.trigger_pin, self.echo_pin) readsonar = asyncio.create_task(self.readsonar()) await readsonar # OTHER CREATED_TASK GO HERE, (removed them in the MVE, but they work fine)if __name__ == "__main__": loop = asyncio.get_event_loop() my_board = PymataExpress() try: ConcurrentTasks(my_board) except (KeyboardInterrupt, RuntimeError): loop.run_until_complete(my_board.shutdown()) print('goodbye') finally: loop.close()
mve_req.py
import zmqimport timeimport jsondef start_zmq(): context = zmq.Context() REQ_django = context.socket(zmq.REQ) REQ_django.connect("tcp://localhost:5558") return REQ_django, contextdef get_sonar(REQ_django): REQ_django.send(b"server_django") ping_from_server_django = REQ_django.recv() return ping_from_server_django.decode()if __name__ == '__main__': data = {"sensors":{}} REQ_django, context = start_zmq() while REQ_django: data['sensors']['sonar'] = get_sonar(REQ_django) json_data = json.dumps(data) print(data) #DO OTHER WORK time.sleep(1) REQ_django.close() context.term()