4
$\begingroup$

I'm trying to read data fro ma serial port, usinc asyncio. General idea:

  • Create the Protocol and coroutine
  • Inside a timer(1ms) make the loop run one iteration at a time

But I get the following error whe callign run_forever() inside the loop:

RuntimeError: Event loop is closed

Working file(outside of blender):

import asyncio
import serial_asyncio
import time

continuar = True
class OutputProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport
        print('port opened', transport)
        transport.serial.rts = False  # You can manipulate Serial object via transport
        transport.write(b'Hello, World!\n')  # Write serial data via transport

    def data_received(self, data):
        global continuar
        #print('data received', repr(data))
        for caracter in data:
            if caracter == ord('+'):
                print("más")
            elif caracter == ord('-'):
                print("menos")
        if b'*' in data:
            self.transport.close()
             
            continuar = False

    def connection_lost(self, exc):
        print('port closed')
        self.transport.loop.stop()

    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')

loop = asyncio.get_event_loop()
coro = serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyACM0', baudrate=115200)
transport, protocol = loop.run_until_complete(coro)

while continuar:
    loop.stop()
    loop.run_forever()
    time.sleep(0.001)

loop.close()

Not working file(inside blender):

import asyncio
import serial_asyncio
import bpy

loop = None

class OutputProtocol(asyncio.Protocol):
    
    def connection_made(self, transport):
        self.transport = transport
        print('port opened', transport)
        transport.serial.rts = False  # You can manipulate Serial object via transport
        transport.write(b'Hello, World!\n')  # Write serial data via transport

    def data_received(self, data):
        #print('data received', repr(data))
        for caracter in data:
            if caracter == ord('+'):
                print("más")
            elif caracter == ord('-'):
                print("menos")
        if b'*' in data:
            self.transport.close()
            

    def connection_lost(self, exc):
        print('port closed')
        self.transport.loop.stop()

    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')



loop = asyncio.get_event_loop()

corutinaSerial = serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyACM0', baudrate=115200)
transport, protocol = loop.run_until_complete(corutinaSerial)

def cicloAsyncio():
    global loop
    loop.stop()
    loop.run_forever()
    return 0.001
    
bpy.app.timers.register(cicloAsyncio)
#loop.run_forever()
loop.close()

Help me blender coders, you are my only hope

$\endgroup$
1
  • $\begingroup$ Well I solved it. For anyone interested, here is the repo with the sample code: $\endgroup$ Jul 5, 2022 at 14:56

2 Answers 2

2
$\begingroup$

Here is the code. The problem in the first code is that I was calling close() just after creating the loop, so the timer couldn't made the loop iterate. It's very obvious now...

Here is the working code:

import asyncio
import serial_asyncio
import bpy
import random

loop = None
terminar = False

class OutputProtocol(asyncio.Protocol):
    
    def connection_made(self, transport):
        self.transport = transport
        print('port opened', transport)
        transport.serial.rts = False  # You can manipulate Serial object via transport
        transport.write(b'Hello, World!\n')  # Write serial data via transport

    def data_received(self, data):
        #print('data received', repr(data))
        for caracter in data:
            if caracter == ord('+'):
                print("más")
                bpy.ops.mesh.primitive_cube_add(
                    size=1, 
                    enter_editmode=False, 
                    align='WORLD', 
                    location=(-5+random.random()*10, -5+random.random()*10, -5+random.random()*10), 
                    scale=(1, 1, 1)
                )

            elif caracter == ord('-'):
                bpy.ops.mesh.primitive_monkey_add(
                    size=1, 
                    enter_editmode=False, 
                    align='WORLD', 
                    location=(-5+random.random()*10, -5+random.random()*10, -5+random.random()*10), 
                    scale=(1, 1, 1)
                )

                print("menos")
        if b'*' in data:
            self.transport.close()
            

    def connection_lost(self, exc):
        print('port closed')
        self.transport.loop.stop()

    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')


loop = asyncio.get_event_loop()


corutinaSerial = serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyACM0', baudrate=115200)
transport, protocol = loop.run_until_complete(corutinaSerial)

    
def cicloAsyncio():
    global loop
    #loop = asyncio.get_event_loop()
    loop.stop()
    loop.run_forever()
    #asyncio.run()
    return 0.001
    
bpy.app.timers.register(cicloAsyncio)
#loop.run_forever()
#loop.close()
$\endgroup$
1
$\begingroup$

Well I solved it. For anyone interested, here is the repo with the sample code: https://github.com/RaulHuertas/BlenderSerialAsync See you!

$\endgroup$
1
  • $\begingroup$ can u paste the whole code here instead of using links? and explain why it didnt work initially? that would be aweomse :) $\endgroup$ Jul 5, 2022 at 15:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .