-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
202 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<mxfile host="Electron" modified="2021-05-26T11:32:32.590Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="bnXJMvJ6PpK9BHE153Qq" version="14.1.8" type="device"><diagram id="8LHJcELrov1qkNwrF_JH" name="Seite-1">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</diagram></mxfile> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import logging, logging.handlers | ||
from simconnect_mobiflight import SimConnectMobiFlight | ||
from mobiflight_variable_requests import MobiFlightVariableRequests | ||
from time import sleep | ||
|
||
def setupLogging(logFileName): | ||
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s") | ||
rootLogger = logging.getLogger() | ||
rootLogger.setLevel(logging.DEBUG) | ||
fileHandler = logging.handlers.RotatingFileHandler(logFileName, maxBytes=500000, backupCount=7) | ||
fileHandler.setFormatter(logFormatter) | ||
rootLogger.addHandler(fileHandler) | ||
consoleHandler = logging.StreamHandler() | ||
consoleHandler.setFormatter(logFormatter) | ||
rootLogger.addHandler(consoleHandler) | ||
|
||
# MAIN | ||
setupLogging("SimConnectMobiFlight.log") | ||
sm = SimConnectMobiFlight() | ||
vr = MobiFlightVariableRequests(sm) | ||
vr.clear_sim_variables() | ||
|
||
while True: | ||
alt_ground = vr.get("(A:GROUND ALTITUDE,Meters)") | ||
alt_plane = vr.get("(A:PLANE ALTITUDE,Feet)") | ||
# FlyByWire A320 | ||
ap1 = vr.get("(L:A32NX_AUTOPILOT_1_ACTIVE)") | ||
hdg = vr.get("(L:A32NX_AUTOPILOT_HEADING_SELECTED)") | ||
mode = vr.get("(L:A32NX_FMA_LATERAL_MODE)") | ||
sleep(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import logging | ||
import struct | ||
from ctypes import sizeof | ||
from ctypes.wintypes import FLOAT | ||
from SimConnect.Enum import SIMCONNECT_CLIENT_DATA_PERIOD, SIMCONNECT_UNUSED | ||
|
||
|
||
class SimVariable: | ||
def __init__(self, id, name, float_value = 0): | ||
self.id = id | ||
self.name = name | ||
self.float_value = float_value | ||
def __str__(self): | ||
return f"Id={self.id}, value={self.float_value}, name={self.name}" | ||
|
||
|
||
class MobiFlightVariableRequests: | ||
|
||
def __init__(self, simConnect): | ||
logging.info("MobiFlightVariableRequests __init__") | ||
self.sm = simConnect | ||
self.sim_vars = {} | ||
self.sim_var_name_to_id = {} | ||
self.CLIENT_DATA_AREA_LVARS = 0 | ||
self.CLIENT_DATA_AREA_CMD = 1 | ||
self.CLIENT_DATA_AREA_RESPONSE = 2 | ||
self.FLAG_DEFAULT = 0 | ||
self.FLAG_CHANGED = 1 | ||
self.DATA_STRING_SIZE = 256 | ||
self.DATA_STRING_OFFSET = 0 | ||
self.DATA_STRING_DEFINITION_ID = 0 | ||
self.sm.register_client_data_handler(self.client_data_callback_handler) | ||
self.initialize_client_data_areas() | ||
|
||
|
||
def add_to_client_data_definition(self, definition_id, offset, size): | ||
logging.info("add_to_client_data_definition definition_id=%s, offset=%s, size=%s", definition_id, offset, size) | ||
self.sm.dll.AddToClientDataDefinition( | ||
self.sm.hSimConnect, | ||
definition_id, | ||
offset, | ||
size, | ||
0, # fEpsilon | ||
SIMCONNECT_UNUSED) # DatumId | ||
|
||
|
||
def subscribe_to_data_change(self, data_area_id, request_id, definition_id): | ||
logging.info("subscribe_to_data_change data_area_id=%s, request_id=%s, definition_id=%s", data_area_id, request_id, definition_id) | ||
self.sm.dll.RequestClientData( | ||
self.sm.hSimConnect, | ||
data_area_id, | ||
request_id, | ||
definition_id, | ||
SIMCONNECT_CLIENT_DATA_PERIOD.SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, | ||
self.FLAG_CHANGED, | ||
0, # origin | ||
0, # interval | ||
0) # limit | ||
|
||
|
||
def send_data(self, data_area_id, definition_id, size, dataBytes): | ||
logging.info("send_data data_area_id=%s, definition_id=%s, size=%s, dataBytes=%s", data_area_id, definition_id, size, dataBytes) | ||
self.sm.dll.SetClientData( | ||
self.sm.hSimConnect, | ||
data_area_id, | ||
definition_id, | ||
self.FLAG_DEFAULT, | ||
0, # dwReserved | ||
size, | ||
dataBytes) | ||
|
||
|
||
def send_command(self, command): | ||
logging.info("send_command command=%s", command) | ||
data_byte_array = bytearray(command, "ascii") | ||
data_byte_array.extend(bytearray(self.DATA_STRING_SIZE - len(data_byte_array))) # extend to fix DATA_STRING_SIZE | ||
self.send_data(self.CLIENT_DATA_AREA_CMD, self.DATA_STRING_DEFINITION_ID, self.DATA_STRING_SIZE, bytes(data_byte_array)) | ||
|
||
|
||
def initialize_client_data_areas(self): | ||
logging.info("initialize_client_data_areas") | ||
# register client data area for receiving simvars | ||
self.sm.dll.MapClientDataNameToID(self.sm.hSimConnect, "MobiFlight.LVars".encode("ascii"), self.CLIENT_DATA_AREA_LVARS) | ||
self.sm.dll.CreateClientData(self.sm.hSimConnect, self.CLIENT_DATA_AREA_LVARS, 4096, self.FLAG_DEFAULT) | ||
# register client data area for sending commands | ||
self.sm.dll.MapClientDataNameToID(self.sm.hSimConnect, "MobiFlight.Command".encode("ascii"), self.CLIENT_DATA_AREA_CMD) | ||
self.sm.dll.CreateClientData(self.sm.hSimConnect, self.CLIENT_DATA_AREA_CMD, self.DATA_STRING_SIZE, self.FLAG_DEFAULT) | ||
# register client data area for receiving responses | ||
self.sm.dll.MapClientDataNameToID(self.sm.hSimConnect, "MobiFlight.Response".encode("ascii"), self.CLIENT_DATA_AREA_RESPONSE) | ||
self.sm.dll.CreateClientData(self.sm.hSimConnect, self.CLIENT_DATA_AREA_RESPONSE, self.DATA_STRING_SIZE, self.FLAG_DEFAULT) | ||
# subscribe to WASM Module responses | ||
self.add_to_client_data_definition(self.DATA_STRING_DEFINITION_ID, self.DATA_STRING_OFFSET, self.DATA_STRING_SIZE) | ||
self.subscribe_to_data_change(self.CLIENT_DATA_AREA_RESPONSE, self.DATA_STRING_DEFINITION_ID, self.DATA_STRING_DEFINITION_ID) | ||
|
||
|
||
# simconnect library callback | ||
def client_data_callback_handler(self, client_data): | ||
if client_data.dwDefineID in self.sim_vars: | ||
data_bytes = struct.pack("i", client_data.dwData[0]) | ||
float_data = struct.unpack('<f', data_bytes)[0] # unpack delivers a tuple -> [0] | ||
self.sim_vars[client_data.dwDefineID].float_value = round(float_data, 5) | ||
logging.debug("client_data_callback_handler %s", self.sim_vars[client_data.dwDefineID]) | ||
else: | ||
logging.warning("client_data_callback_handler DefinitionID %s not found!", client_data.dwDefineID) | ||
|
||
|
||
def get(self, variableString): | ||
if variableString not in self.sim_var_name_to_id: | ||
# add new variable | ||
id = len(self.sim_vars) + 1 | ||
self.sim_vars[id] = SimVariable(id, variableString) | ||
self.sim_var_name_to_id[variableString] = id | ||
# subscribe to variable data change | ||
offset = (id-1)*sizeof(FLOAT) | ||
self.add_to_client_data_definition(id, offset, sizeof(FLOAT)) | ||
self.subscribe_to_data_change(self.CLIENT_DATA_AREA_LVARS, id, id) | ||
self.send_command("MF.SimVars.Add." + variableString) | ||
# determine id and return value | ||
variable_id = self.sim_var_name_to_id[variableString] | ||
float_value = self.sim_vars[variable_id].float_value | ||
logging.debug("get %s. Return=%s", variableString, float_value) | ||
return float_value | ||
|
||
|
||
def clear_sim_variables(self): | ||
logging.info("clear_sim_variables") | ||
self.sim_vars.clear() | ||
self.sim_var_name_to_id.clear() | ||
self.send_command("MF.SimVars.Clear") | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import logging, logging.handlers | ||
import ctypes | ||
from ctypes import wintypes | ||
from SimConnect import SimConnect | ||
from SimConnect.Enum import SIMCONNECT_CLIENT_DATA_ID, SIMCONNECT_RECV_ID, SIMCONNECT_RECV_CLIENT_DATA | ||
|
||
|
||
class SimConnectMobiFlight(SimConnect): | ||
|
||
def __init__(self, auto_connect=True, library_path=None): | ||
self.client_data_handlers = [] | ||
if library_path: | ||
super().__init__(auto_connect, library_path) | ||
else: | ||
super().__init__(auto_connect) | ||
# Fix missing types | ||
self.dll.MapClientDataNameToID.argtypes = [wintypes.HANDLE, ctypes.c_char_p, SIMCONNECT_CLIENT_DATA_ID] | ||
|
||
|
||
def register_client_data_handler(self, handler): | ||
if not handler in self.client_data_handlers: | ||
logging.info("Register new client data handler") | ||
self.client_data_handlers.append(handler) | ||
|
||
|
||
def unregister_client_data_handler(self, handler): | ||
if handler in self.client_data_handlers: | ||
logging.info("Unregister client data handler") | ||
self.client_data_handlers.remove(handler) | ||
|
||
|
||
def my_dispatch_proc(self, pData, cbData, pContext): | ||
dwID = pData.contents.dwID | ||
if dwID == SIMCONNECT_RECV_ID.SIMCONNECT_RECV_ID_CLIENT_DATA: | ||
client_data = ctypes.cast(pData, ctypes.POINTER(SIMCONNECT_RECV_CLIENT_DATA)).contents | ||
for handler in self.client_data_handlers: | ||
handler(client_data) | ||
else: | ||
super().my_dispatch_proc(pData, cbData, pContext) |