Python-SimConnect
Python-SimConnect copied to clipboard
Asyncio Testing
Not shure if this is the right direction or not thoughts?
I like the idea of asyncio in principal, but I haven't tested it as I'm away from home (and hence the Sim). Does it mean that the "time" and "attemp" parameters will no longer be necessary?
@danricho just thinking about removing attempts, not 100% on this so left in the pluming for now. values are set on thread https://github.com/odwdinc/Python-SimConnect/blob/152fa14bd71ed6a5b71b139f5b10c84ca9bc5db5/SimConnect/SimConnect.py#L163-L165
_run https://github.com/odwdinc/Python-SimConnect/blob/152fa14bd71ed6a5b71b139f5b10c84ca9bc5db5/SimConnect/SimConnect.py#L172-L175
Data is revived by https://github.com/odwdinc/Python-SimConnect/blob/152fa14bd71ed6a5b71b139f5b10c84ca9bc5db5/SimConnect/SimConnect.py#L243-L249
normally attempts are check in the while loop (Line 244) to escape if data is not received in a given time. I don't know if this is still needed or wanted with the new async bits.
With time, it is how long to return cashed data vs new data form the sim. https://github.com/odwdinc/Python-SimConnect/blob/152fa14bd71ed6a5b71b139f5b10c84ca9bc5db5/SimConnect/RequestList.py#L15-L24
Just tested this last version of the asyncio branch for a good 45 min reading altitude/long/lat/baro with another instance giving command and so far very stable and received no None value.
I haven't tested this PR, but I was just considering writing an async wrapper around my calls to Python-SimConnect so I hit fewer cases of needing to handle a None
, so I think aync support is a good direction.
I tested this change this morning and have found it flawless.
It enabled me to log flight parameters at a much higher frequency than the old method which essentially hangs until a value is received.
Only limitation I found is the returning of 'None's when I used get() on signals with an index (eg: 'x:1') or the wind direction/speed. But I used request in setup then .value() in the main loop to get around this. I didn't figure out why this happened.
so with such a big change how should we make handle the move? I have been holding off to see if I can think of some way..
new sample, added an a to the async vertions of functions to keep backwords code woking. https://github.com/odwdinc/Python-SimConnect/blob/c6da1c8d475e25d07f112f95993c462393e6d4e8/SimConnect/RequestList.py#L19 Sample:
from SimConnect import *
import logging
from SimConnect.Enum import *
from time import sleep
import asyncio
logging.basicConfig(level=logging.DEBUG)
LOGGER = logging.getLogger(__name__)
LOGGER.info("START")
# creat simconnection and pass used user classes
sm = SimConnect()
aq = AircraftRequests(sm, _time=10, _attemps=10)
Throttle = aq.find('GENERAL_ENG_THROTTLE_LEVER_POSITION:1')
# none async Function still works
print("Throttle:", Throttle.value)
print("Alt=%f Lat=%f Lon=%f Kohlsman=%.2f" % (
aq.PositionandSpeedData.get('PLANE_ALTITUDE'),
aq.PositionandSpeedData.get('PLANE_LATITUDE'),
aq.PositionandSpeedData.get('PLANE_LONGITUDE'),
aq.FlightInstrumentationData.get('KOHLSMAN_SETTING_HG')
))
# New async Function
async def PrintData():
# THROTTLE Request
print("Throttle:", await Throttle.avalue)
print("Lat=%f Lon=%f Alt=%f Kohlsman=%.2f" % tuple(
await asyncio.gather(
aq.PositionandSpeedData.aget('PLANE_LATITUDE'),
aq.PositionandSpeedData.aget('PLANE_LONGITUDE'),
aq.PositionandSpeedData.aget('PLANE_ALTITUDE'),
aq.FlightInstrumentationData.aget('KOHLSMAN_SETTING_HG')
)
))
asyncio.run(PrintData())
sm.exit()
quit()
My opinion: Follow semantic versioning. If this is a breaking change to old code, increment the major version number. It's on us as library users if we failed to pin the version correctly.
Unless there's a good reason to maintain both versions of the functions, don't.
I do agree that library users should be managing library versions and that we shouldn't keep both versions side by side due to maintenance burden; however I have a few thoughts that might help or at least ease the transition:
- could we call the non-async versions from within the async version so only the core functions nee to be maintained, or
- could we add a deprecated feedback message in the non-async version, with an end-of-support point defined?
I only suggest this as there seems to be quite a number of users now. Just my 2 cents!
I'd like to report the following bug I've noticed:
The asyncio version doesn't work when getting two SimVars with the same key but different index consecutively. Example:
ui_friendly_dictionary["NAV1_OBS_DEG"] = round(await aq.get("NAV_OBS:1"),0)
ui_friendly_dictionary["NAV2_OBS_DEG"] = round(await aq.get("NAV_OBS:2"),0)
NAV2_OBS_DEG will be getting the NAV_OBS:1 value.
The code works, however, when I introduce a different key inbetween. Like this:
ui_friendly_dictionary["NAV1_OBS_DEG"] = round(await aq.get("NAV_OBS:1"),0)
ui_friendly_dictionary["ADF_CARD_DEG"] = round(await aq.get("ADF_CARD"),0)
ui_friendly_dictionary["NAV2_OBS_DEG"] = round(await aq.get("NAV_OBS:2"),0)
This issue has been introduced with asyncio version and hasn't been a problem before. I'm not sure if it's a problem on my part or it's a bug in general. Unfortunately, my Python skills aren't up to the skills to propose a bug fix.
Thanks!
Hi @mracko, I'd suggest checking the thread in issue #67. I had a similar issue, albeit no with the Asyncio version.
It may or may not be useful, but I thought I'd share and I hope it's useful.
Cheers.
Thanks @danricho. This seems to explain the behavior and I understand the performance reasons. Hopefully, I'll be able to come up with a solution on how to efficiently get the NAV OBSs myself. Again, I'm not a Python pro. :)
If you post your code, I or someone else could help you adjust it to get this working. ;)
Hi guys,
let's go async ;-) See #98 for introducing asyncio, including a sync wrapper to stay compatible.
Please test. In a next step code can be ported to async, and async examples can be added.