[Python] pyserial-asyncio client/server in Python 3.8 not communicating immediately

Discussão em 'Python' iniciado por Stack, Março 4, 2025.

  1. Stack

    Stack Membro Participativo

    I'm learning python and asyncio and after having success with asyncio for a TCP client/server I took my first stab at creating a serial client/server using pyserial-asyncio running in bash on a Raspberry Pi 5 using Python 3.8 (I cannot change version).

    Here is the server:

    import asyncio
    import serial_asyncio

    class UARTProtocol(asyncio.Protocol):
    def __init__(self):
    self.transport = None

    def connection_made(self, transport):
    self.transport = transport
    print('Port opened', transport)

    def data_received(self, data):
    print('Data received:', data.decode())
    # Echo received data back (example)
    self.transport.write(data)
    # Close the connection if 'exit' is received
    if data == b"exit\r":
    self.transport.close()

    def connection_lost(self, exc):
    print('Port closed')
    self.transport = None

    def pause_writing(self):
    print('pause writing')
    print(self.transport.get_write_buffer_size())

    def resume_writing(self):
    print(self.transport.get_write_buffer_size())
    print('resume writing')

    async def run_uart_server():
    loop = asyncio.get_running_loop()
    try:
    transport, protocol = await serial_asyncio.create_serial_connection(loop, UARTProtocol, '/dev/ttyAMA2', baudrate=9600)
    print("UART server started.")
    await asyncio.Future() # Run forever
    except serial.serialutil.SerialException as e:
    print(f"Error: Could not open serial port: {e}")
    finally:
    if transport:
    transport.close()

    if __name__ == "__main__":
    asyncio.run(run_uart_server())


    and the client:

    import asyncio
    import serial_asyncio

    async def uart_client(port, baudrate):
    try:
    reader, writer = await serial_asyncio.open_serial_connection(url=port, baudrate=baudrate)
    print(f"Connected to {port} at {baudrate} bps")

    async def receive_data():
    while True:
    try:
    data = await reader.readline()
    if data:
    print(f"Received: {data.decode().strip()}")
    except Exception as e:
    print(f"Error reading data: {e}")
    break

    async def send_data():
    while True:
    message = input("Enter message to send (or 'exit' to quit): ")
    if message.lower() == 'exit':
    break
    writer.write((message + '\n').encode())
    # writer.write_eof()
    await writer.drain()
    print(f"Sent: {message}")

    await asyncio.gather(receive_data(), send_data())

    except serial.SerialException as e:
    print(f"Error opening serial port: {e}")
    finally:
    if 'writer' in locals():
    writer.close()
    await writer.wait_closed()
    print("Connection closed.")

    if __name__ == "__main__":
    asyncio.run(uart_client('/dev/ttyAMA1', 9600))


    I want the client to prompt me for some text which is immediately sent to the server and printed there. I can get the client to prompt me for text, but the server doesn't display any of it until after I type exit in the client to close the connection and then it prints all of the text I typed in the client loop.

    Among many other things, I've tried adding writer.write_eof() in the client (see commented out line in the client code below) and that succeeds in the server immediately displaying the preceding text from the client but then the client never prompts me for input again.

    If I run the server and just do echo foo > /dev/ttyAMA1 from bash the server prints foo immediately so I suspect the client is the problem.

    What am I doing wrong?

    Continue reading...

Compartilhe esta Página