Home > Blockchain >  How to pass serial_asyncio between async tasks
How to pass serial_asyncio between async tasks

Time:02-02

I need to pass reader and writer from serial_asyncio between 2 asynchronous tasks, first task is reading user keyboard input, when user press x, function send information to Arduino, second task reading response from Arduino and for specyfic response do stuff

Code:

import warnings
import serial
import serial.tools.list_ports
import requests
import json
import asyncio
import keyboard
import time
from serial_asyncio import open_serial_connection

with open("config.json") as config:
    cfg = json.load(config)
    config.close()

headers = {'Accept': 'application/json'}

url = f"""https://{cfg["web"]}/login?username={cfg["user"]}&password={cfg["password"]}""" 

get_token = requests.post(url, headers=headers)
token = get_token.json()
my_token = token["token"]

arduino_ports = [
    p.device
    for p in serial.tools.list_ports.comports()
    if p.manufacturer and 'Arduino' in p.manufacturer
]
if not arduino_ports:
    raise IOError("No Arduino found")
if len(arduino_ports) > 1:
    warnings.warn("Multiple arduinos, select first")


async def arduino_listen(cfg, headers, reader):
    print('arduino_listen task created')
    while True:
        await asyncio.sleep(0.1)
        info = await reader.readline()
        print('arduino respond:', info)
        if "good" in str(info):
            print('good from arduino')
        if "bad" in str(info):
            print('bad from arduino')


async def arduino_writer(cfg, headers, writer):
    print('arduino_writer task created')
    keypress = False
    key = 'x'
    while True:
        if keypress and not keyboard.is_pressed(key):
            print('x pressed on keyboard, send 5')
            writer.write(b'5')
            await asyncio.sleep(0.3)
            keypress = False
        elif keyboard.is_pressed(key) and not keypress:
            keypress = True


async def serial():
    print(f'serial task created, arduino port {arduino_ports[0]} selected')
    reader, writer = await open_serial_connection(url=arduino_ports[0], baudrate=115200)

#reader, writer = await open_serial_connection(url=arduino_ports[0], baudrate=115200)

loop = asyncio.get_event_loop()
loop.create_task(serial())
loop.create_task(arduino_listen(cfg, headers, reader))
loop.create_task(arduino_writer(cfg, headers, writer))
loop.run_forever()

My question is, how to pass connection from serial function task to arduino_listen and arduino_writer tasks, I have try to add reader, writer = await open_serial_connection(url=arduino_ports[0], baudrate=115200) before loop.create_task but error unexpected ident appear

CodePudding user response:

Avoid giving functions name that conflict with your module names, it's about serial in your case. Let's call it say start_serial.
As start_serial is the initial function that starts a serial connection arduino_listen and arduino_writer should be run in parallel right after it.
Change the final part of your code to the following:

async def start_serial():
    print(f'serial task created, arduino port {arduino_ports[0]} selected')
    reader, writer = await open_serial_connection(url=arduino_ports[0], baudrate=115200)
    return reader, writer

async def main():
    reader, writer = await start_serial()
    await asyncio.gather(
        arduino_listen(cfg, headers, reader),
        arduino_writer(cfg, headers, writer))


asyncio.run(main())
  • Related