Skip to content

Commit f36bf83

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 f36bf83

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

src/controller/python/chip/ChipStack.py

+43
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,30 @@ 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+
def __init__(self, callback, loop, future):
171+
self._callback = callback
172+
self._loop = loop
173+
self._future = future
174+
self._result = None
175+
self._exception = None
176+
177+
def _done(self):
178+
if self._exception:
179+
self._future.set_exception(self._exception)
180+
else:
181+
self._future.set_result(self._result)
182+
183+
def __call__(self):
184+
try:
185+
self._result = self._callback()
186+
except Exception as ex:
187+
self._exception = ex
188+
self._loop.call_soon_threadsafe(self._done)
189+
pythonapi.Py_DecRef(py_object(self))
190+
191+
167192
_CompleteFunct = CFUNCTYPE(None, c_void_p, c_void_p)
168193
_ErrorFunct = CFUNCTYPE(None, c_void_p, c_void_p,
169194
c_ulong, POINTER(DeviceStatusStruct))
@@ -367,6 +392,24 @@ def Call(self, callFunct, timeoutMs: int = None):
367392
return self.callbackRes
368393
return res
369394

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

0 commit comments

Comments
 (0)