Skip to content

Commit 5e40de3

Browse files
committed
[Python] Implement asyncio variant of CallAsync
Call Matter SDK in a asyncio friendly way. During posting of the task onto the CHIP mainloop, it makes sure that the asyncio loop is not blocked.
1 parent 50500d2 commit 5e40de3

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

src/controller/python/chip/ChipStack.py

+44
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
from __future__ import absolute_import, print_function
2828

29+
import asyncio
2930
import builtins
3031
import logging
3132
import os
@@ -164,6 +165,31 @@ def Wait(self, timeoutMs: int = None):
164165
return self._res
165166

166167

168+
class AsyncSimpleCallableHandle:
169+
"""Class which handles Matter SDK Calls asyncio friendly"""
170+
171+
def __init__(self, callback, loop, future):
172+
self._callback = callback
173+
self._loop = loop
174+
self._future = future
175+
self._result = None
176+
self._exception = None
177+
178+
def _done(self):
179+
if self._exception:
180+
self._future.set_exception(self._exception)
181+
else:
182+
self._future.set_result(self._result)
183+
184+
def __call__(self):
185+
try:
186+
self._result = self._callback()
187+
except Exception as ex:
188+
self._exception = ex
189+
self._loop.call_soon_threadsafe(self._done)
190+
pythonapi.Py_DecRef(py_object(self))
191+
192+
167193
_CompleteFunct = CFUNCTYPE(None, c_void_p, c_void_p)
168194
_ErrorFunct = CFUNCTYPE(None, c_void_p, c_void_p,
169195
c_ulong, POINTER(DeviceStatusStruct))
@@ -367,6 +393,24 @@ def Call(self, callFunct, timeoutMs: int = None):
367393
return self.callbackRes
368394
return res
369395

396+
async def CallAsync(self, callFunct, timeoutMs: int = None):
397+
'''Run a Python function on CHIP stack, and wait for the response.
398+
This function will post a task on CHIP mainloop and waits for the call response in a asyncio friendly manner.
399+
'''
400+
loop = asyncio.get_event_loop()
401+
future = loop.create_future()
402+
callObj = AsyncSimpleCallableHandle(callFunct, loop, future)
403+
pythonapi.Py_IncRef(py_object(callObj))
404+
405+
res = self._ChipStackLib.pychip_DeviceController_PostTaskOnChipThread(
406+
self.cbHandleChipThreadRun, py_object(callObj))
407+
408+
if not res.is_success:
409+
pythonapi.Py_DecRef(py_object(callObj))
410+
raise res.to_exception()
411+
412+
return await asyncio.wait_for(future, timeoutMs / 1000 if timeoutMs else None)
413+
370414
def CallAsyncWithCallback(self, callFunct):
371415
'''Run a Python function on CHIP stack, and wait for the application specific response.
372416
This function is a wrapper of PostTaskOnChipThread, which includes some handling of application specific logics.

0 commit comments

Comments
 (0)