So i am trying to read data from a serial port with python.
I am planning on feeding this data to my asyncua server in the future. Comming from c# i always have the urge to make classes. However when i run the code i get the Exception that the loop is already running.
As far as i understood tasks will be put into the loop and then executed so i think i am missing something here.
From a best practice approach does it make sense to make classes in python like this or is there a "better" way? I appreciate all input.
I have made a Class which is supposed to handle the reading from the serial port and later should assign the value to the nodes on the opc server.
For the reading i used the examples made here pySerialDocumentation
import asyncio
import serial_asyncio
from async_serial_output import OutputProtocol,InputChunkProtocol
import logging
class EboxAndino():
"""
Class which manages the connection to the serial port
"""
ebox = None
timeout: int
counter1Opc = None
counter2Opc = None
input1Opc = None
input2Opc = None
Heartbeat = None
logger = None
debug = False
setup_dict = {}
counterValueDict = {}
hwPort = None
baud = None
timeout = None
debug = False
logger = logging.getLogger('foo')
hBeat = False
ser = None
rts = False
def __init__(self, ebox, hwPort, baud, timeout, debug, loggerName) -> None:
"""
@param ebox: opcObj
@param hwPort: string
@param baud: int
@param timeout: int
@param debug: bool
@param loggerName: string
"""
# self = EboxAndino('Ebox')
self.ebox = ebox
self.hwPort = hwPort
self.baud = baud
self.timeout = timeout
self.debug = debug
self.hBeat = False
self.ser = None
self.rts = False
print('created!')
async def initCounter(self):
self.hBeat = False
self.counterValueDict = {"Counter1": None,
"Counter2": None,
"Input1": None,
"Input2": None,
}
setup_list = [*self.counterValueDict]
print ('Counter is up!')
def get_values(self):
if self.counterValueDict:
return self.counterValueDict
else:
return None
async def line_reader(self,loop):
coro = await serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyAMA0', baudrate = 38400)
await asyncio.sleep(1)
transport, protocol = loop.run_until_complete(coro)
await asyncio.sleep(0.5)
loop.run_forever()
loop.close()
With my main beeing
async def main():
loop = asyncio.get_event_loop()
andino = EboxAndino('foo', '/dev/ttyAMA0', 38400, 1, True, 'foo')
await andino.initCounter()
await andino.line_reader(loop)
loop = asyncio.get_event_loop()
asyncio.sleep(2)
loop.run_until_complete(main())
Running this will give me the first line split into 4 recieved packages. After it it will get an exception that the loop is already running. Why?
As a follow up question where would be the best place to grab and store the values to the opc server?
Thank you everyone!
In asyncio you can only run one loop. The example you use is for an synchrnous context. But you are now in the async context already. So there is no need to call loop.run_until.
async def line_reader(self,loop):
transport, protocol = await serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyAMA0', baudrate = 38400)
await asyncio.sleep(1)
await asyncio.sleep(0.5)