前提・実現したいこと
pyserial_asyncioを使った通信プログラムを作っています。TCP socketとのゲートウェイを作る為、ノンブロッキングIO処理を行っています。
今回問題となっているのは、そのシリアル通信側。
相手機器とは幾つかのメッセージシーケンスを持っていて、それぞれに受信時の相手側が送りつける終了文字が異なります。その受信シーケンスを終了させる条件を定義する関数を用意しました。
受信バッファ読み出し部は共通のため、それをreceive関数としてシーケンス関数にデコレートしました。
python
1import asyncio 2import serial_asyncio 3import functools 4 5class MachineCommunication(): 6 7 def __init__(self,port,baudrate): 8 self.__reader = None 9 self.__writer = None 10 self.__port = port 11 self.__baudrate = baudrate 12 13 async def connect(self): 14 self.__reader, self.__writer = await serial_asyncio.open_serial_connection(url=self.__port, 15 baudrate=int(self.__baudrate)) 16 async def send(self, msg): 17 self.__writer.write((msg + '\r').encode()) 18 19 def receive(Function): 20 @functools.wraps(Function) 21 async listener(self): 22 msg = '' 23 while Function(msg) 24 msg = await self.__reader.readuntil(b'\r') # pyserial_asyncioのストリームリーダ 25 msg = msg.rstrip().decode() 26 return listener 27 28 @receive 29 def sequence_A(self,msg): 30 if msg == '受信を終了する文字': 31 return False 32 else: 33 メッセージをさばく処理 34 return True 35 36 @receive 37 def sequence_B(self,msg): 38 if msg == '受信を終了する文字': 39 return True 40 else: 41 メッセージをさばく処理 42 return False
発生している問題・エラーメッセージ
問題は、どうやって上記のsequence_A, sequence_B を呼び出す時にrecieveをawaitさせるか?という事です。
これらの関数を呼び出す時はコルーチンではないため、
await sequence_A
などとは定義できません。しかし、awaitさせないと、
- sendを使ってメッセージ送信
- seqence_Aを使って受信待ち
- sendを使って次のメッセージ送信
- seqence_Bを使って受信待ち
- 終了
のそれぞれ2,4 を待ってくれません。
試したこと
デコレータを使わず、recieve関数をコルーチンにして呼び出す形にすればうまくいきました。
しかし、すっきり書きたいので、デコレータでうまく行く方法を探しています。
補足情報(FW/ツールのバージョンなど)
Python3.7を使っています。
回答2件
あなたの回答
tips
プレビュー