diff --git a/SimConnect/AsyncLoop.py b/SimConnect/AsyncLoop.py new file mode 100644 index 00000000..cb07d762 --- /dev/null +++ b/SimConnect/AsyncLoop.py @@ -0,0 +1,35 @@ +import asyncio +from threading import Thread, Condition +import logging + +logger = logging.getLogger(__name__) + +class AsyncLoop(Thread): + def __init__(self): + Thread.__init__(self) + self.async_loop = None + self._condition_var = Condition() + + def start(self): + with self._condition_var: + Thread.start(self) + self._condition_var.wait() + + def run(self): + self.async_loop = asyncio.new_event_loop() + logger.debug("AsyncLoop: %s", self.async_loop) + self.async_loop.call_soon_threadsafe(self._notify_start) + self.async_loop.run_forever() + + def _notify_start(self): + with self._condition_var: + self._condition_var.notify_all() + + def stop(self): + self.async_loop.call_soon_threadsafe(self.async_loop.stop) + self.join() + self.async_loop.close() + + def execute(self, routine): + future_runner = asyncio.run_coroutine_threadsafe(routine, loop=self.async_loop) + return future_runner.result() \ No newline at end of file diff --git a/SimConnect/RequestList.py b/SimConnect/RequestList.py index 0cd54a27..4f1c315b 100644 --- a/SimConnect/RequestList.py +++ b/SimConnect/RequestList.py @@ -6,17 +6,24 @@ class Request(object): def get(self): - return self.value + return self.sm.async_loop.execute(self.async_get()) + + async def async_get(self): + return await self.async_value def set(self, _value): self.value = _value @property def value(self): + return self.sm.async_loop.execute(self.async_value) + + @property + async def async_value(self): if self._deff_test(): # self.sm.run() if (self.LastData + self.time) < millis(): - if self.sm.get_data(self): + if await self.sm.async_get_data(self): self.LastData = millis() else: return None @@ -133,9 +140,12 @@ def __getattr__(self, _name): return None def get(self, _name): + return self.sm.async_loop.execute(self.async_get(_name)) + + async def async_get(self, _name): if getattr(self, _name) is None: return None - return getattr(self, _name).value + return await getattr(self, _name).async_value def set(self, _name, _value=0): temp = getattr(self, _name) @@ -175,10 +185,13 @@ def find(self, key): return None def get(self, key): + return self.sm.async_loop.execute(self.async_get(key)) + + async def async_get(self, key): request = self.find(key) if request is None: return None - return request.value + return await request.async_value def set(self, key, _value): request = self.find(key) diff --git a/SimConnect/SimConnect.py b/SimConnect/SimConnect.py index 613f5396..5c2afb56 100644 --- a/SimConnect/SimConnect.py +++ b/SimConnect/SimConnect.py @@ -1,3 +1,4 @@ +import ctypes from ctypes import * from ctypes.wintypes import * import logging @@ -7,6 +8,8 @@ from .Attributes import * import os import threading +import asyncio +from .AsyncLoop import * _library_path = os.path.splitext(os.path.abspath(__file__))[0] + '.dll' @@ -122,6 +125,8 @@ def __init__(self, auto_connect=True, library_path=_library_path): self.Requests = {} self.Facilities = [] + self.async_loop = AsyncLoop() + self.async_loop.start() self.dll = SimConnectDll(library_path) self.hSimConnect = HANDLE() self.quit = 0 @@ -178,6 +183,7 @@ def _run(self): def exit(self): self.quit = 1 + self.async_loop.stop() self.timerThread.join() self.dll.Close(self.hSimConnect) @@ -202,7 +208,7 @@ def add_to_notification_group(self, group, evnt, bMaskable=False): self.hSimConnect, group, evnt, bMaskable ) - def request_data(self, _Request): + async def request_data(self, _Request): _Request.outData = None self.dll.RequestDataOnSimObjectType( self.hSimConnect, @@ -243,16 +249,18 @@ def set_data(self, _Request): return False def get_data(self, _Request): - self.request_data(_Request) + return self.async_loop.execute(self.async_get_data(_Request)) + + async def async_get_data(self, _Request): + await self.request_data(_Request) # self.run() attemps = 0 while _Request.outData is None and attemps < _Request.attemps: # self.run() - time.sleep(.01) + await asyncio.sleep(.01) attemps += 1 if _Request.outData is None: return False - return True def send_event(self, evnt, data=DWORD(0)):