Search code examples
python-asynciopython-multithreadingpyserial

Serial Async Acquisition


I'ven't understood well the asyncio functionaly and I need a clarification. I've checked that this code works:

from asyncio import get_event_loop
from serial_asyncio import open_serial_connection

async def main():
    reader, writer = await open_serial_connection(url='COM10', baudrate=115200)
    while True:
        line = await reader.readline()
        print(str(line, 'utf-8'))


asyncio.run(main())

basically the connection is established and I see messages coming from the serial port but it is not what I was expecting. I'd like to start the acquisition from the serial and at the same time I'd like to go ahead doing other stuffs in my code.

Basically something like this one in scapy:

            t = AsyncSniffer()
            t.start()
            print("Acquisition started")
            wait (10)
            t.stop()

I've also tried using the Thread option like this:

import serial
import threading
global stop_threads
import time
stop_threads=False
def thread_function_1():
    ser = serial.Serial('COM1',115200)
  
            
    while   thread_function_1():
        line=ser.readline()
        if line:
            string=line.decode()
            print(string)
        
        if stop_threads==true:
            ser.close()
            break


print ('print_1')
x= threading.Thread(name = "thread_function_1", target = thread_function_1)
x.start()
time.sleep(100)
stop_threads = True
print ('print_2')
x.join()

I'm getting this error which I cannot solve:

Traceback (most recent call last):
  File "C:\Users\SIM\AppData\Local\Programs\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\SIM\AppData\Local\Programs\Python\Python38\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:\python\connessione_seriale.py", line 31, in thread_function_1
    while   thread_function_1():
  File "C:\python\connessione_seriale.py", line 14, in thread_function_1
    ser = serial.Serial('COM1',115200)
  File "C:\Users\SIM\AppData\Local\Programs\Python\Python38\lib\site-packages\serial\serialwin32.py", line 33, in __init__
    super(Serial, self).__init__(*args, **kwargs)
  File "C:\Users\SIM\AppData\Local\Programs\Python\Python38\lib\site-packages\serial\serialutil.py", line 244, in __init__
    self.open()
  File "C:\Users\SIM\AppData\Local\Programs\Python\Python38\lib\site-packages\serial\serialwin32.py", line 64, in open
    raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))
serial.serialutil.SerialException: could not open port 'COM1': PermissionError(13, 'Access is denied.', None, 5)

the COM1 is available.I've tried to open it via putty and it works.


Solution

  • this is the solution I've found. I've used a thread inside a class in order to start/stop the serial acquisition when I need it.

    class ThreadTest:
        def seriale(self, n):
            ser = serial.Serial('COM9', 115200, timeout=1)
            time.sleep(2)
            with open('C:/python/test.txt', 'w') as output:
                if self._running==False:
                    ser.close()
                while self._running and n > 0:
                    line = ser.readline() 
                    #print (line)
                    n -= 1
                    if line:
                        # Converting Byte Strings into unicode strings
                        string = line.decode() 
                        #print (string)
                        output.write(string)
        def terminate(self):
            self._running = False
        
        def __init__(self):
            self._running = True
    c = ThreadTest()
    t1 = Thread(target=c.seriale, args=(10,)) #10 are the seconds of the acquisition via serial and can be replaced
    
    t1.start() # start of the serial acquisition
    
    time.sleep(10)# here the sleep can be replaced with code
    c.terminate()