diff --git a/SimConnect/RequestList.py b/SimConnect/RequestList.py index 0cd54a27..8c6ca967 100644 --- a/SimConnect/RequestList.py +++ b/SimConnect/RequestList.py @@ -1,6 +1,7 @@ from SimConnect import * from .Enum import * from .Constants import * +import asyncio class Request(object): @@ -8,21 +9,33 @@ class Request(object): def get(self): return self.value + async def aget(self): + return await self.avalue + def set(self, _value): self.value = _value + @property + async def avalue(self): + if self._deff_test(): + # self.sm.run() + if (self.LastData + self.time) < millis(): + await self.sm.get_data(self) + self.LastData = millis() + return self.outData + else: + raise Exception(self.definitions[0][0]) + @property def value(self): if self._deff_test(): # self.sm.run() if (self.LastData + self.time) < millis(): - if self.sm.get_data(self): - self.LastData = millis() - else: - return None + asyncio.run(self.sm.get_data(self)) + self.LastData = millis() return self.outData else: - return None + raise Exception(self.definitions[0][0]) @value.setter def value(self, val): @@ -69,9 +82,9 @@ def redefine(self): ) self.defined = False # self.sm.run() - if self._deff_test(): - # self.sm.run() - self.sm.get_data(self) + # if self._deff_test(): + # # self.sm.run() + # self.sm.get_data(self) def _deff_test(self): if ':index' in str(self.definitions[0][0]): @@ -137,6 +150,11 @@ def get(self, _name): return None return getattr(self, _name).value + async def aget(self, _name): + if getattr(self, _name) is None: + return None + return await getattr(self, _name).avalue + def set(self, _name, _value=0): temp = getattr(self, _name) if temp is None: @@ -170,6 +188,8 @@ def find(self, key): if key in clas.list: rqest = getattr(clas, key) if index is not None: + if 'index' in index: + index = 0 rqest.setIndex(index) return rqest return None @@ -180,6 +200,12 @@ def get(self, key): return None return request.value + async def aget(self, key): + request = self.find(key) + if request is None: + return None + return await request.avalue + def set(self, key, _value): request = self.find(key) if request is None: diff --git a/SimConnect/SimConnect.py b/SimConnect/SimConnect.py index 2a129bb2..5cee0ff3 100644 --- a/SimConnect/SimConnect.py +++ b/SimConnect/SimConnect.py @@ -7,6 +7,7 @@ from .Attributes import * import os import threading +import asyncio _library_path = os.path.splitext(os.path.abspath(__file__))[0] + '.dll' @@ -239,18 +240,13 @@ def set_data(self, _Request): else: return False - def get_data(self, _Request): - self.request_data(_Request) - # self.run() - attemps = 0 - while _Request.outData is None and attemps < _Request.attemps: - # self.run() - time.sleep(.01) - attemps += 1 - if _Request.outData is None: - return False + async def get_return_data(self, _Request): + while _Request.outData is None: + await asyncio.sleep(0.01) - return True + async def get_data(self, _Request): + self.request_data(_Request) + await self.get_return_data(_Request) def send_event(self, evnt, data=DWORD(0)): err = self.dll.TransmitClientEvent( diff --git a/glass_server.py b/glass_server.py index 0fe4c6a2..aaa9c4c1 100644 --- a/glass_server.py +++ b/glass_server.py @@ -2,7 +2,7 @@ from SimConnect import * from time import sleep import random - +import asyncio app = Flask(__name__) @@ -11,7 +11,7 @@ # Create simconnection sm = SimConnect() ae = AircraftEvents(sm) -aq = AircraftRequests(sm, _time=10) +aq = AircraftRequests(sm) # Create request holders @@ -50,10 +50,10 @@ #] request_location = [ - 'ALTITUDE', - 'LATITUDE', - 'LONGITUDE', - 'KOHLSMAN', + 'PLANE_ALTITUDE', + 'PLANE_LATITUDE', + 'PLANE_LONGITUDE', + 'KOHLSMAN_SETTING_HG', ] request_airspeed = [ @@ -295,74 +295,75 @@ def get_dataset(data_type): return request_to_action - -@app.route('/ui') -def output_ui_variables(): - - # Initialise dictionaru - ui_friendly_dictionary = {} - ui_friendly_dictionary["STATUS"] = "success" - +async def ui_dictionary(ui_friendly_dictionary): # Fuel - fuel_percentage = (aq.get("FUEL_TOTAL_QUANTITY") / aq.get("FUEL_TOTAL_CAPACITY")) * 100 - ui_friendly_dictionary["FUEL_PERCENTAGE"] = round(fuel_percentage) - ui_friendly_dictionary["AIRSPEED_INDICATE"] = round(aq.get("AIRSPEED_INDICATED")) - ui_friendly_dictionary["ALTITUDE"] = thousandify(round(aq.get("PLANE_ALTITUDE"))) - + ui_friendly_dictionary["FUEL_PERCENTAGE"] = round((await aq.get("FUEL_TOTAL_QUANTITY") / await aq.get("FUEL_TOTAL_CAPACITY")) * 100) + ui_friendly_dictionary["AIRSPEED_INDICATE"] = round(await aq.get("AIRSPEED_INDICATED")) + ui_friendly_dictionary["ALTITUDE"] = thousandify(round(await aq.get("PLANE_ALTITUDE"))) # Control surfaces - if aq.get("GEAR_HANDLE_POSITION") == 1: + if await aq.get("GEAR_HANDLE_POSITION") == 1: ui_friendly_dictionary["GEAR_HANDLE_POSITION"] = "DOWN" else: ui_friendly_dictionary["GEAR_HANDLE_POSITION"] = "UP" - ui_friendly_dictionary["FLAPS_HANDLE_PERCENT"] = round(aq.get("FLAPS_HANDLE_PERCENT") * 100) + ui_friendly_dictionary["FLAPS_HANDLE_PERCENT"] = round(await aq.get("FLAPS_HANDLE_PERCENT") * 100) - ui_friendly_dictionary["ELEVATOR_TRIM_PCT"] = round(aq.get("ELEVATOR_TRIM_PCT") * 100) - ui_friendly_dictionary["RUDDER_TRIM_PCT"] = round(aq.get("RUDDER_TRIM_PCT") * 100) + ui_friendly_dictionary["ELEVATOR_TRIM_PCT"] = round(await aq.get("ELEVATOR_TRIM_PCT") * 100) + ui_friendly_dictionary["RUDDER_TRIM_PCT"] = round(await aq.get("RUDDER_TRIM_PCT") * 100) # Navigation - ui_friendly_dictionary["LATITUDE"] = aq.get("PLANE_LATITUDE") - ui_friendly_dictionary["LONGITUDE"] = aq.get("PLANE_LONGITUDE") - ui_friendly_dictionary["MAGNETIC_COMPASS"] = round(aq.get("MAGNETIC_COMPASS")) - ui_friendly_dictionary["MAGVAR"] = round(aq.get("MAGVAR")) - ui_friendly_dictionary["VERTICAL_SPEED"] = round(aq.get("VERTICAL_SPEED")) + ui_friendly_dictionary["LATITUDE"] = await aq.get("PLANE_LATITUDE") + ui_friendly_dictionary["LONGITUDE"] = await aq.get("PLANE_LONGITUDE") + ui_friendly_dictionary["MAGNETIC_COMPASS"] = round(await aq.get("MAGNETIC_COMPASS")) + ui_friendly_dictionary["MAGVAR"] = round(await aq.get("MAGVAR")) + ui_friendly_dictionary["VERTICAL_SPEED"] = round(await aq.get("VERTICAL_SPEED")) # Autopilot - ui_friendly_dictionary["AUTOPILOT_MASTER"] = aq.get("AUTOPILOT_MASTER") - ui_friendly_dictionary["AUTOPILOT_NAV_SELECTED"] = aq.get("AUTOPILOT_NAV_SELECTED") - ui_friendly_dictionary["AUTOPILOT_WING_LEVELER"] = aq.get("AUTOPILOT_WING_LEVELER") - ui_friendly_dictionary["AUTOPILOT_HEADING_LOCK"] = aq.get("AUTOPILOT_HEADING_LOCK") - ui_friendly_dictionary["AUTOPILOT_HEADING_LOCK_DIR"] = round(aq.get("AUTOPILOT_HEADING_LOCK_DIR")) - ui_friendly_dictionary["AUTOPILOT_ALTITUDE_LOCK"] = aq.get("AUTOPILOT_ALTITUDE_LOCK") - ui_friendly_dictionary["AUTOPILOT_ALTITUDE_LOCK_VAR"] = thousandify(round(aq.get("AUTOPILOT_ALTITUDE_LOCK_VAR"))) - ui_friendly_dictionary["AUTOPILOT_ATTITUDE_HOLD"] = aq.get("AUTOPILOT_ATTITUDE_HOLD") - ui_friendly_dictionary["AUTOPILOT_GLIDESLOPE_HOLD"] = aq.get("AUTOPILOT_GLIDESLOPE_HOLD") - ui_friendly_dictionary["AUTOPILOT_APPROACH_HOLD"] = aq.get("AUTOPILOT_APPROACH_HOLD") - ui_friendly_dictionary["AUTOPILOT_BACKCOURSE_HOLD"] = aq.get("AUTOPILOT_BACKCOURSE_HOLD") - ui_friendly_dictionary["AUTOPILOT_VERTICAL_HOLD"] = aq.get("AUTOPILOT_VERTICAL_HOLD") - ui_friendly_dictionary["AUTOPILOT_VERTICAL_HOLD_VAR"] = aq.get("AUTOPILOT_VERTICAL_HOLD_VAR") - ui_friendly_dictionary["AUTOPILOT_PITCH_HOLD"] = aq.get("AUTOPILOT_PITCH_HOLD") - ui_friendly_dictionary["AUTOPILOT_PITCH_HOLD_REF"] = aq.get("AUTOPILOT_PITCH_HOLD_REF") - ui_friendly_dictionary["AUTOPILOT_FLIGHT_DIRECTOR_ACTIVE"] = aq.get("AUTOPILOT_FLIGHT_DIRECTOR_ACTIVE") - ui_friendly_dictionary["AUTOPILOT_AIRSPEED_HOLD"] = aq.get("AUTOPILOT_AIRSPEED_HOLD") - ui_friendly_dictionary["AUTOPILOT_AIRSPEED_HOLD_VAR"] = round(aq.get("AUTOPILOT_AIRSPEED_HOLD_VAR")) + ui_friendly_dictionary["AUTOPILOT_MASTER"] = await aq.get("AUTOPILOT_MASTER") + ui_friendly_dictionary["AUTOPILOT_NAV_SELECTED"] = await aq.get("AUTOPILOT_NAV_SELECTED") + ui_friendly_dictionary["AUTOPILOT_WING_LEVELER"] = await aq.get("AUTOPILOT_WING_LEVELER") + ui_friendly_dictionary["AUTOPILOT_HEADING_LOCK"] = await aq.get("AUTOPILOT_HEADING_LOCK") + ui_friendly_dictionary["AUTOPILOT_HEADING_LOCK_DIR"] = round(await aq.get("AUTOPILOT_HEADING_LOCK_DIR")) + ui_friendly_dictionary["AUTOPILOT_ALTITUDE_LOCK"] = await aq.get("AUTOPILOT_ALTITUDE_LOCK") + ui_friendly_dictionary["AUTOPILOT_ALTITUDE_LOCK_VAR"] = thousandify(round(await aq.get("AUTOPILOT_ALTITUDE_LOCK_VAR"))) + ui_friendly_dictionary["AUTOPILOT_ATTITUDE_HOLD"] = await aq.get("AUTOPILOT_ATTITUDE_HOLD") + ui_friendly_dictionary["AUTOPILOT_GLIDESLOPE_HOLD"] = await aq.get("AUTOPILOT_GLIDESLOPE_HOLD") + ui_friendly_dictionary["AUTOPILOT_APPROACH_HOLD"] = await aq.get("AUTOPILOT_APPROACH_HOLD") + ui_friendly_dictionary["AUTOPILOT_BACKCOURSE_HOLD"] = await aq.get("AUTOPILOT_BACKCOURSE_HOLD") + ui_friendly_dictionary["AUTOPILOT_VERTICAL_HOLD"] = await aq.get("AUTOPILOT_VERTICAL_HOLD") + ui_friendly_dictionary["AUTOPILOT_VERTICAL_HOLD_VAR"] = await aq.get("AUTOPILOT_VERTICAL_HOLD_VAR") + ui_friendly_dictionary["AUTOPILOT_PITCH_HOLD"] = await aq.get("AUTOPILOT_PITCH_HOLD") + ui_friendly_dictionary["AUTOPILOT_PITCH_HOLD_REF"] = await aq.get("AUTOPILOT_PITCH_HOLD_REF") + ui_friendly_dictionary["AUTOPILOT_FLIGHT_DIRECTOR_ACTIVE"] = await aq.get("AUTOPILOT_FLIGHT_DIRECTOR_ACTIVE") + ui_friendly_dictionary["AUTOPILOT_AIRSPEED_HOLD"] = await aq.get("AUTOPILOT_AIRSPEED_HOLD") + ui_friendly_dictionary["AUTOPILOT_AIRSPEED_HOLD_VAR"] = round(await aq.get("AUTOPILOT_AIRSPEED_HOLD_VAR")) # Cabin - ui_friendly_dictionary["CABIN_SEATBELTS_ALERT_SWITCH"] = aq.get("CABIN_SEATBELTS_ALERT_SWITCH") - ui_friendly_dictionary["CABIN_NO_SMOKING_ALERT_SWITCH"] = aq.get("CABIN_NO_SMOKING_ALERT_SWITCH") + ui_friendly_dictionary["CABIN_SEATBELTS_ALERT_SWITCH"] = await aq.get("CABIN_SEATBELTS_ALERT_SWITCH") + ui_friendly_dictionary["CABIN_NO_SMOKING_ALERT_SWITCH"] = await aq.get("CABIN_NO_SMOKING_ALERT_SWITCH") +@app.route('/ui') +def output_ui_variables(): + # Initialise dictionaru + ui_friendly_dictionary = {} + ui_friendly_dictionary["STATUS"] = "success" + asyncio.run(ui_dictionary(ui_friendly_dictionary)) return jsonify(ui_friendly_dictionary) +async def _dictionary(data_dictionary): + dataset_map = {} # I have renamed map to dataset_map as map is used elsewhere + for datapoint_name in data_dictionary: + print(datapoint_name) + dataset_map[datapoint_name] = await aq.get(datapoint_name) + return jsonify(dataset_map) + @app.route('/dataset//', methods=["GET"]) def output_json_dataset(dataset_name): - dataset_map = {} #I have renamed map to dataset_map as map is used elsewhere data_dictionary = get_dataset(dataset_name) - for datapoint_name in data_dictionary: - dataset_map[datapoint_name] = aq.get(datapoint_name) - return jsonify(dataset_map) + return asyncio.run(_dictionary(data_dictionary)) -def get_datapoint(datapoint_name, index=None): +async def get_datapoint(datapoint_name, index=None): # This function actually does the work of getting the datapoint if index is not None and ':index' in datapoint_name: @@ -370,7 +371,7 @@ def get_datapoint(datapoint_name, index=None): if dp is not None: dp.setIndex(int(index)) - return aq.get(datapoint_name) + return await aq.get(datapoint_name) @app.route('/datapoint//get', methods=["GET"]) @@ -380,7 +381,7 @@ def get_datapoint_endpoint(datapoint_name): ds = request.get_json() if request.is_json else request.form index = ds.get('index') - output = get_datapoint(datapoint_name, index) + output = asyncio.run(get_datapoint(datapoint_name, index)) if isinstance(output, bytes): output = output.decode('ascii') @@ -413,17 +414,14 @@ def set_datapoint(datapoint_name, index=None, value_to_use=None): @app.route('/datapoint//set', methods=["POST"]) def set_datapoint_endpoint(datapoint_name): # This is the http endpoint wrapper for setting a datapoint - ds = request.get_json() if request.is_json else request.form index = ds.get('index') value_to_use = ds.get('value_to_use') - - status = set_datapoint (datapoint_name, index, value_to_use) - + status = set_datapoint(datapoint_name, index, value_to_use) return jsonify(status) -def trigger_event(event_name, value_to_use = None): +def trigger_event(event_name, value_to_use=None): # This function actually does the work of triggering the event EVENT_TO_TRIGGER = ae.find(event_name) @@ -452,6 +450,9 @@ def trigger_event_endpoint(event_name): return jsonify(status) +async def get_engen_ct(): + return await aq.get("NUMBER_OF_ENGINES") + @app.route('/custom_emergency/', methods=["GET", "POST"]) def custom_emergency(emergency_type): @@ -459,10 +460,11 @@ def custom_emergency(emergency_type): if emergency_type == "random_engine_fire": # Calculate number of engines - number_of_engines = aq.get("NUMBER_OF_ENGINES") + number_of_engines = asyncio.run(get_engen_ct()) - if number_of_engines < 0: return "error, no engines found - is sim running?" - engine_to_set_on_fire = random.randint(1,number_of_engines) + if number_of_engines < 0: + return "error, no engines found - is sim running?" + engine_to_set_on_fire = random.randint(1, number_of_engines) set_datapoint("ENG_ON_FIRE:index", engine_to_set_on_fire, 1) diff --git a/local_example.py b/local_example.py index 54a18496..4daa6c15 100644 --- a/local_example.py +++ b/local_example.py @@ -2,39 +2,18 @@ import logging from SimConnect.Enum import * from time import sleep - +import asyncio logging.basicConfig(level=logging.DEBUG) LOGGER = logging.getLogger(__name__) LOGGER.info("START") -# time holder for inline commands -ct_g = millis() + # creat simconnection and pass used user classes sm = SimConnect() -aq = AircraftRequests(sm) +aq = AircraftRequests(sm, _time=10, _attemps=10) ae = AircraftEvents(sm) - -mc = aq.find("MAGNETIC_COMPASS") -mv = aq.find("MAGVAR") -print(mc.get() + mv.get()) - -sm.exit() -quit() - -# Set pos arund space nedle in WA. -sm.set_pos( - _Altitude=1000.0, - _Latitude=47.614699, - _Longitude=-122.358473, - _Airspeed=130, - _Heading=70.0, - # _Pitch=0.0, - # _Bank=0.0, - # _OnGround=0 -) - # PARKING_BRAKES = Event(b'PARKING_BRAKES', sm) # long path PARKING_BRAKES = ae.Miscellaneous_Systems.PARKING_BRAKES @@ -59,36 +38,42 @@ # print the built in description # AP_MASTER Toggles AP on/off -print("AP_MASTER", AP_MASTER.description) +print("AP_MASTER", AP_MASTER.description) # Throttle Percent of max throttle position print("Throttle", Throttle.description) # THROTTLE1 Set throttle 1 exactly (0 to 16383) print("THROTTLE1", THROTTLE1.description) -while not sm.quit: - 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') - )) - sleep(2) - - # Send Event with value - # THROTTLE1(1500) - - # Send Event toggle AP_MASTER - # AP_MASTER() - - # PARKING_BRAKES() - - # send new data inine @ 5s - if ct_g + 5000 < millis(): - if Throttle.value < 100: - Throttle.value += 5 - print("THROTTLE SET") - ct_g = millis() - -sm.exit() +async def main(): + # time holder for inline commands + ct_g = millis() + while not sm.quit: + print("Throttle:", await Throttle.value) + print("Lat=%f Lon=%f Alt=%f Kohlsman=%.2f" % tuple( + await asyncio.gather( + aq.PositionandSpeedData.get('PLANE_LATITUDE'), + aq.PositionandSpeedData.get('PLANE_LONGITUDE'), + aq.PositionandSpeedData.get('PLANE_ALTITUDE'), + aq.FlightInstrumentationData.get('KOHLSMAN_SETTING_HG') + ) + )) + sleep(2) + + # Send Event with value + # THROTTLE1(1500) + + # Send Event toggle AP_MASTER + # AP_MASTER() + + # PARKING_BRAKES() + + # send new data inine @ 5s + # if ct_g + 5000 < millis(): + # if await Throttle.value < 100: + # Throttle.set(await Throttle.value + 5) + # print("THROTTLE SET") + # ct_g = millis() + sm.exit() + +asyncio.run(main())