Reputation: 13
I have a function do_serial()
that reads from the serial port and adds the data to a queue. I want to process that queue on main()
.
I have read the serial_asyncio docs and have a basic echo type proof that reads serial data and echoes it back from a single async function. What I cannot get to work is updating the queue and reading the queue from main()
.
Once I have this working I also want to update another queue on main() and have that get written to the serial port. This way do_serial()
can run async and process the serial port and main()
interacts with the queues.
Here is my code:
import queue
import asyncio
import serial_asyncio
incoming_serial_queue = queue.Queue()
async def do_serial():
reader, writer = await serial_asyncio.open_serial_connection(url='/dev/ttyS0', baudrate=9600)
while True:
# read serial port
data = await reader.readline()
# echo back to serial port for verification
writer.write(incoming_serial_queue.get)
# add data to queue
incoming_serial_queue.put(data)
async def main():
while True:
# read queued data from serial port
await print(incoming_serial_queue.get())
asyncio.run(do_serial())
asyncio.run(main())
Upvotes: 1
Views: 3035
Reputation: 142859
I'm not specialist for asyncio
but I created some working code - so don't ask why something doesn't work :)
I can't run serial_asyncio
so I used datetime
to generate some data for queue
You can't use run()
to start two processes at the same time. run()
starts one process and waits for its end - so run(do_serial())
starts function do_serial
and waits for its end - and this way it never runs main
. If you change order then run(main())
will wait for end of main
and it will never run do_serial
So I used run()
to start one function which use create_task() for do_serial()
and main()
. I had to first create task and later use them with await because in other way it didn't start main
and I don't know why.
Other problem with asyncio
: await
can't work with every function - it will not work with standard print()
. You would have to create special print()
for it. Or maybe you have special print()
from serial_asyncio
- I don't know.
In both functions I used asyncio.sleep()
to have some function with await
Problem with queue
: when there is no data in queue then get()
may block code and it is better to check first if it is not empty()
import queue
import asyncio
import datetime
incoming_serial_queue = queue.Queue()
async def do_serial():
print("do serial")
while True:
data = str(datetime.datetime.now())
print('put:', data)
# add data to queue
incoming_serial_queue.put(data)
await asyncio.sleep(2)
async def main():
print("main")
while True:
# read queued data from serial port
if not incoming_serial_queue.empty():
data = incoming_serial_queue.get()
print('get:', data)
await asyncio.sleep(1)
async def start():
print("start")
#await do_serial() # doesn't work
#await main() # doesn't work
# I had to create all tasks before running
task1 = asyncio.create_task(do_serial())
task2 = asyncio.create_task(main())
# running task
await task1
await task2
asyncio.run(start())
EDIT:
I could run two functions using asyncio.gather()
async def start():
print("start")
await asyncio.gather(
do_serial(),
main(),
)
Rest is the same as in my previous code
import queue
import asyncio
import datetime
incoming_serial_queue = queue.Queue()
async def do_serial():
print("do serial")
while True:
data = str(datetime.datetime.now())
print('put:', data)
# add data to queue
incoming_serial_queue.put(data)
await asyncio.sleep(2)
async def main():
print("main")
while True:
# read queued data from serial port
if not incoming_serial_queue.empty():
data = incoming_serial_queue.get()
print('get:', data)
await asyncio.sleep(1)
async def start():
print("start")
await asyncio.gather(
do_serial(),
main(),
)
asyncio.run(start())
Upvotes: 1