Estou aprendendo Python e Asyncio e, depois de ter sucesso com Asyncio para um cliente/servidor TCP, tentei pela primeira vez criar um cliente/servidor serial usando pyserial-asyncio em execução no bash em um Raspberry Pi 5 usando Python 3.8 (não posso alterar a versão).
Aqui está o servidor:
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())
e o cliente:
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))
Quero que o cliente me solicite algum texto que seja imediatamente enviado ao servidor e impresso lá. Posso fazer com que o cliente me solicite um texto, mas o servidor não exibe nada até que eu digite exit
no cliente para fechar a conexão e então ele imprime todo o texto que eu digitei no loop do cliente.
Entre muitas outras coisas, tentei adicionar writer.write_eof()
o cliente (veja a linha comentada no código do cliente abaixo) e isso fez com que o servidor exibisse imediatamente o texto anterior do cliente, mas o cliente nunca mais me solicitasse nenhuma entrada.
Se eu executar o servidor e executar apenas echo foo > /dev/ttyAMA1
o bash, o servidor imprime foo
imediatamente, então suspeito que o cliente seja o problema.
O que estou fazendo errado?