2022-07-23 19:23:32 +00:00
using Microsoft.FlightSimulator.SimConnect ;
using MSFSPopoutPanelManager.Shared ;
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
2023-07-12 22:41:31 +00:00
using System.Reflection ;
2022-08-13 06:14:49 +00:00
using System.Threading.Tasks ;
2022-07-23 19:23:32 +00:00
using System.Timers ;
2023-07-30 21:30:47 +00:00
using static MSFSPopoutPanelManager . SimConnectAgent . SimDataDefinitions ;
2022-07-23 19:23:32 +00:00
namespace MSFSPopoutPanelManager.SimConnectAgent
{
public class SimConnector
{
private const int MSFS_CONNECTION_RETRY_TIMEOUT = 2000 ;
2023-07-12 22:41:31 +00:00
private const uint WM_USER_SIMCONNECT = 0x0402 ;
2022-07-23 19:23:32 +00:00
private SimConnect _simConnect ;
private Timer _connectionTimer ;
2022-08-13 06:14:49 +00:00
private bool _isDisabledReconnect ;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
private readonly List < SimConnectDataDefinition > _simConnectRequiredDataDefinitions = SimDataDefinitions . GetRequiredDefinitions ( ) ;
2024-03-14 22:50:32 +00:00
private readonly List < SimConnectDataDefinition > _simConnectDynamicLodDataDefinitions = SimDataDefinitions . GetDynamicLodDefinitions ( ) ;
2023-07-12 22:41:31 +00:00
private List < SimConnectDataDefinition > _simConnectHudBarDataDefinitions ;
2024-02-28 02:44:21 +00:00
private readonly FieldInfo [ ] _simConnectStructFields = typeof ( SimConnectStruct ) . GetFields ( BindingFlags . Public | BindingFlags . Instance ) ;
2023-07-12 22:41:31 +00:00
2022-07-23 19:23:32 +00:00
public event EventHandler < string > OnException ;
2023-07-12 22:41:31 +00:00
public event EventHandler < List < SimDataItem > > OnReceivedRequiredData ;
public event EventHandler < List < SimDataItem > > OnReceivedHudBarData ;
2024-03-14 22:50:32 +00:00
public event EventHandler < List < SimDataItem > > OnReceivedDynamicLodData ;
2022-07-23 19:23:32 +00:00
public event EventHandler OnConnected ;
public event EventHandler OnDisconnected ;
2023-07-12 22:41:31 +00:00
public event EventHandler < SimConnectEvent > OnReceiveSystemEvent ;
2024-03-14 22:50:32 +00:00
public event EventHandler < int > OnReceivedEventFrameData ;
2023-07-12 22:41:31 +00:00
public event EventHandler < string > OnActiveAircraftChanged ;
2022-07-23 19:23:32 +00:00
public bool Connected { get ; set ; }
public void Start ( )
{
2024-02-28 02:44:21 +00:00
_connectionTimer = new ( )
{
Interval = MSFS_CONNECTION_RETRY_TIMEOUT ,
Enabled = true
} ;
_connectionTimer . Elapsed + = ( _ , _ ) = >
2022-07-23 19:23:32 +00:00
{
try
{
2023-07-12 22:41:31 +00:00
Debug . WriteLine ( "Connecting to MSFS..." ) ;
2022-07-23 19:23:32 +00:00
InitializeSimConnect ( ) ;
}
catch
{
// handle SimConnect instantiation error when MSFS is not connected
}
} ;
}
public void Restart ( )
{
_connectionTimer . Enabled = true ;
}
2023-07-12 22:41:31 +00:00
public void SetSimConnectHudBarDataDefinition ( SimDataDefinitionType definitionType )
{
_simConnectHudBarDataDefinitions = SimDataDefinitions . GetHudBarDefinitions ( definitionType ) ;
AddHudBarDataDefinitions ( ) ;
}
2024-03-14 22:50:32 +00:00
public void SetSimConnectDynamicLodDataDefinition ( )
{
AddDynamicLodDataDefinitions ( ) ;
}
2022-07-23 19:23:32 +00:00
private void HandleOnRecvOpen ( SimConnect sender , SIMCONNECT_RECV_OPEN data )
{
ReceiveMessage ( ) ;
}
public void StopAndReconnect ( )
{
2024-02-28 02:44:21 +00:00
if ( _isDisabledReconnect )
return ;
Stop ( ) ;
InitializeSimConnect ( ) ;
2022-07-23 19:23:32 +00:00
}
public void Stop ( )
{
2024-02-28 02:44:21 +00:00
_simConnect = null ;
2022-07-23 19:23:32 +00:00
Connected = false ;
}
2023-07-12 22:41:31 +00:00
public void RequestRequiredData ( )
2022-07-23 19:23:32 +00:00
{
if ( _simConnect = = null | | ! Connected )
return ;
2023-07-12 22:41:31 +00:00
try
{
2024-02-28 02:44:21 +00:00
_simConnect . RequestDataOnSimObjectType ( DataRequest . REQUIRED_REQUEST , DataDefinition . REQUIRED_DEFINITION , 0 , SIMCONNECT_SIMOBJECT_TYPE . USER ) ;
2023-07-12 22:41:31 +00:00
}
catch
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
if ( ! _isDisabledReconnect )
_isDisabledReconnect = true ;
OnException ? . Invoke ( this , null ) ;
}
}
public void RequestHudBarData ( )
{
if ( _simConnect = = null | | ! Connected )
return ;
try
{
if ( _simConnectHudBarDataDefinitions ! = null )
2024-02-28 02:44:21 +00:00
_simConnect . RequestDataOnSimObjectType ( DataRequest . HUDBAR_REQUEST , DataDefinition . HUDBAR_DEFINITION , 0 , SIMCONNECT_SIMOBJECT_TYPE . USER ) ;
2023-07-12 22:41:31 +00:00
}
catch
{
if ( ! _isDisabledReconnect )
_isDisabledReconnect = true ;
OnException ? . Invoke ( this , null ) ;
2022-07-23 19:23:32 +00:00
}
}
2024-03-14 22:50:32 +00:00
public void RequestDynamicLodData ( )
{
if ( _simConnect = = null | | ! Connected )
return ;
try
{
if ( _simConnectDynamicLodDataDefinitions ! = null )
_simConnect . RequestDataOnSimObjectType ( DataRequest . DYNAMICLOD_REQUEST , DataDefinition . DYNAMICLOD_DEFINITION , 0 , SIMCONNECT_SIMOBJECT_TYPE . USER ) ;
}
catch
{
if ( ! _isDisabledReconnect )
_isDisabledReconnect = true ;
OnException ? . Invoke ( this , null ) ;
}
}
2022-07-23 19:23:32 +00:00
public void ReceiveMessage ( )
{
if ( _simConnect = = null )
return ;
try
{
2022-08-13 06:14:49 +00:00
if ( ! _isDisabledReconnect )
_simConnect . ReceiveMessage ( ) ;
2022-07-23 19:23:32 +00:00
}
catch ( Exception ex )
{
if ( ex . Message ! = "0xC00000B0" )
{
FileLogger . WriteLog ( $"SimConnector: SimConnect receive message exception - {ex.Message}" , StatusMessageType . Error ) ;
2022-08-13 06:14:49 +00:00
}
2022-07-23 19:23:32 +00:00
2022-08-13 06:14:49 +00:00
if ( ! _isDisabledReconnect )
{
// Prevent multiple reconnects from running
_isDisabledReconnect = true ;
2023-07-12 22:41:31 +00:00
OnException ? . Invoke ( this , null ) ;
2022-07-23 19:23:32 +00:00
}
}
}
2024-02-28 02:44:21 +00:00
public void TransmitActionEvent ( ActionEvent eventId , uint data )
2022-07-23 19:23:32 +00:00
{
if ( _simConnect ! = null )
{
try
{
2024-02-28 02:44:21 +00:00
_simConnect . TransmitClientEvent ( 0 U , eventId , data , NotificationGroup . GROUP0 , SIMCONNECT_EVENT_FLAG . GROUPID_IS_PRIORITY ) ;
2023-07-12 22:41:31 +00:00
System . Threading . Thread . Sleep ( 200 ) ;
2022-07-23 19:23:32 +00:00
}
catch ( Exception ex )
{
2024-02-28 02:44:21 +00:00
var eventName = eventId . ToString ( ) [ 4. . ] ; // trim out KEY_ prefix
2022-07-23 19:23:32 +00:00
FileLogger . WriteLog ( $"SimConnector: SimConnect transmit event exception - EventName: {eventName} - {ex.Message}" , StatusMessageType . Error ) ;
}
}
}
2024-02-28 02:44:21 +00:00
public void SetDataObject ( WritableVariableName propName , object dValue )
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
try
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
if ( _simConnect = = null )
return ;
var dataStruct = new WritableDataStruct
{
Prop0 = ( double ) dValue
} ;
2023-07-12 22:41:31 +00:00
2023-07-30 21:30:47 +00:00
switch ( propName )
{
2024-02-28 02:44:21 +00:00
case WritableVariableName . TrackIREnable :
_simConnect . SetDataOnSimObject ( DataDefinition . WRITABLE_TRACK_IR_DEFINITION , SimConnect . SIMCONNECT_OBJECT_ID_USER , SIMCONNECT_DATA_SET_FLAG . DEFAULT , dataStruct ) ;
break ;
case WritableVariableName . CockpitCameraZoom :
_simConnect . SetDataOnSimObject ( DataDefinition . WRITABLE_COCKPIT_CAMERA_ZOOM_DEFINITION , SimConnect . SIMCONNECT_OBJECT_ID_USER , SIMCONNECT_DATA_SET_FLAG . DEFAULT , dataStruct ) ;
2023-07-30 21:30:47 +00:00
break ;
2024-02-29 00:54:25 +00:00
case WritableVariableName . CameraState :
_simConnect . SetDataOnSimObject ( DataDefinition . WRITABLE_COCKPIT_CAMERA_STATE_DEFINITION , SimConnect . SIMCONNECT_OBJECT_ID_USER , SIMCONNECT_DATA_SET_FLAG . DEFAULT , dataStruct ) ;
break ;
2024-02-28 02:44:21 +00:00
case WritableVariableName . CameraRequestAction :
_simConnect . SetDataOnSimObject ( DataDefinition . WRITABLE_CAMERA_REQUEST_ACTION_DEFINITION , SimConnect . SIMCONNECT_OBJECT_ID_USER , SIMCONNECT_DATA_SET_FLAG . DEFAULT , dataStruct ) ;
2023-07-30 21:30:47 +00:00
break ;
2024-02-28 02:44:21 +00:00
case WritableVariableName . CameraViewTypeAndIndex0 :
_simConnect . SetDataOnSimObject ( DataDefinition . WRITABLE_CAMERA_VIEW_TYPE_INDEX_0_DEFINITION , SimConnect . SIMCONNECT_OBJECT_ID_USER , SIMCONNECT_DATA_SET_FLAG . DEFAULT , dataStruct ) ;
break ;
case WritableVariableName . CameraViewTypeAndIndex1 :
_simConnect . SetDataOnSimObject ( DataDefinition . WRITABLE_CAMERA_VIEW_TYPE_INDEX_1_DEFINITION , SimConnect . SIMCONNECT_OBJECT_ID_USER , SIMCONNECT_DATA_SET_FLAG . DEFAULT , dataStruct ) ;
2023-08-16 03:41:14 +00:00
break ;
2023-07-30 21:30:47 +00:00
}
2023-07-12 22:41:31 +00:00
}
catch ( Exception ex )
{
FileLogger . WriteLog ( $"SimConnector: Unable to set SimConnect variable - {ex.Message}" , StatusMessageType . Error ) ;
2022-07-23 19:23:32 +00:00
}
}
2024-03-14 22:50:32 +00:00
public void StartReceiveFrameData ( )
{
if ( _simConnect = = null )
return ;
_simConnect . OnRecvEventFrame - = HandleOnRecvEventFrame ;
_simConnect . OnRecvEventFrame + = HandleOnRecvEventFrame ;
_simConnect . UnsubscribeFromSystemEvent ( SimConnectEvent . FRAME ) ;
_simConnect . SubscribeToSystemEvent ( SimConnectEvent . FRAME , "Frame" ) ;
}
public void StopReceiveFrameData ( )
{
_simConnect . OnRecvEventFrame - = HandleOnRecvEventFrame ;
_simConnect . UnsubscribeFromSystemEvent ( SimConnectEvent . FRAME ) ;
}
2022-07-23 19:23:32 +00:00
private void InitializeSimConnect ( )
{
2023-07-12 22:41:31 +00:00
Debug . WriteLine ( "Trying to start simConnect" ) ;
2022-07-23 19:23:32 +00:00
_simConnect = new SimConnect ( "MSFS Pop Out Panel Manager" , Process . GetCurrentProcess ( ) . MainWindowHandle , WM_USER_SIMCONNECT , null , 0 ) ;
2023-07-12 22:41:31 +00:00
Debug . WriteLine ( "SimConnect started" ) ;
2022-07-23 19:23:32 +00:00
_connectionTimer . Enabled = false ;
2024-02-28 02:44:21 +00:00
// Listen to connect and quit messages
2022-07-23 19:23:32 +00:00
_simConnect . OnRecvOpen + = HandleOnRecvOpen ;
_simConnect . OnRecvQuit + = HandleOnRecvQuit ;
_simConnect . OnRecvException + = HandleOnRecvException ;
_simConnect . OnRecvEvent + = HandleOnReceiveSystemEvent ;
2024-02-28 02:44:21 +00:00
_simConnect . OnRecvSimobjectDataBytype + = HandleOnRecvSimObjectDataByType ;
2022-08-01 23:21:42 +00:00
_simConnect . OnRecvEventFilename + = HandleOnRecvEventFilename ;
2022-08-02 15:51:28 +00:00
_simConnect . OnRecvSystemState + = HandleOnRecvSystemState ;
2022-07-23 19:23:32 +00:00
// Register simConnect system events
2024-02-28 02:44:21 +00:00
_simConnect . UnsubscribeFromSystemEvent ( SimConnectEvent . SIM_START ) ;
_simConnect . SubscribeToSystemEvent ( SimConnectEvent . SIM_START , "SimStart" ) ;
_simConnect . UnsubscribeFromSystemEvent ( SimConnectEvent . SIM_STOP ) ;
_simConnect . SubscribeToSystemEvent ( SimConnectEvent . SIM_STOP , "SimStop" ) ;
2023-07-12 22:41:31 +00:00
_simConnect . UnsubscribeFromSystemEvent ( SimConnectEvent . VIEW ) ;
_simConnect . SubscribeToSystemEvent ( SimConnectEvent . VIEW , "View" ) ;
2024-02-28 02:44:21 +00:00
_simConnect . UnsubscribeFromSystemEvent ( SimConnectEvent . AIRCRAFT_LOADED ) ;
_simConnect . SubscribeToSystemEvent ( SimConnectEvent . AIRCRAFT_LOADED , "AircraftLoaded" ) ;
2024-03-14 22:50:32 +00:00
2023-07-12 22:41:31 +00:00
AddRequiredDataDefinitions ( ) ;
SetupActionEvents ( ) ;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
_simConnect . RequestSystemState ( SystemStateRequestId . AIRCRAFT_PATH , "AircraftLoaded" ) ;
2022-08-02 15:51:28 +00:00
2022-08-13 06:14:49 +00:00
_isDisabledReconnect = false ;
Task . Run ( ( ) = >
{
for ( var i = 0 ; i < 5 ; i + + )
{
System . Threading . Thread . Sleep ( 1000 ) ;
ReceiveMessage ( ) ;
}
} ) ;
2024-02-28 02:44:21 +00:00
OnConnected ? . Invoke ( this , EventArgs . Empty ) ;
2022-08-13 06:14:49 +00:00
Connected = true ;
2022-07-23 19:23:32 +00:00
}
2024-03-14 22:50:32 +00:00
private void HandleOnRecvEventFrame ( SimConnect sender , SIMCONNECT_RECV_EVENT_FRAME data )
{
if ( data = = null )
return ;
OnReceivedEventFrameData ? . Invoke ( this , Convert . ToInt32 ( data . fFrameRate ) ) ;
}
2022-08-02 15:51:28 +00:00
private void HandleOnRecvSystemState ( SimConnect sender , SIMCONNECT_RECV_SYSTEM_STATE data )
{
switch ( ( SystemStateRequestId ) Enum . Parse ( typeof ( SystemStateRequestId ) , data . dwRequestID . ToString ( ) ) )
{
2024-02-28 02:44:21 +00:00
case SystemStateRequestId . AIRCRAFT_PATH :
2022-08-02 15:51:28 +00:00
SetActiveAircraftTitle ( data . szString ) ;
break ;
}
}
2022-08-01 23:21:42 +00:00
private void HandleOnRecvEventFilename ( SimConnect sender , SIMCONNECT_RECV_EVENT_FILENAME data )
{
switch ( data . uEventID )
{
2024-02-28 02:44:21 +00:00
case ( uint ) SimConnectEvent . AIRCRAFT_LOADED :
2022-08-02 15:51:28 +00:00
SetActiveAircraftTitle ( data . szFileName ) ;
2022-08-01 23:21:42 +00:00
break ;
}
}
2023-07-12 22:41:31 +00:00
private void SetupActionEvents ( )
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
foreach ( ActionEvent item in Enum . GetValues ( typeof ( ActionEvent ) ) )
{
_simConnect . MapClientEventToSimEvent ( item , item . ToString ( ) ) ;
}
}
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
private void AddRequiredDataDefinitions ( )
{
if ( _simConnect = = null | | _simConnectRequiredDataDefinitions = = null )
return ;
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
foreach ( var definition in _simConnectRequiredDataDefinitions )
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
if ( definition . DefinitionId ! = DataDefinition . REQUIRED_DEFINITION | |
definition . DataDefinitionType ! = DataDefinitionType . SimConnect ) continue ;
2022-08-01 23:21:42 +00:00
2024-02-28 02:44:21 +00:00
SIMCONNECT_DATATYPE simConnectDataType ;
switch ( definition . DataType )
{
case DataType . String :
simConnectDataType = SIMCONNECT_DATATYPE . STRING256 ;
break ;
case DataType . Float64 :
simConnectDataType = SIMCONNECT_DATATYPE . FLOAT64 ;
break ;
default :
simConnectDataType = SIMCONNECT_DATATYPE . FLOAT64 ;
break ;
2023-07-12 22:41:31 +00:00
}
2022-08-01 23:21:42 +00:00
2024-02-28 02:44:21 +00:00
_simConnect . AddToDataDefinition ( definition . DefinitionId , definition . VariableName , definition . SimConnectUnit , simConnectDataType , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
}
2022-08-01 23:21:42 +00:00
2024-02-28 02:44:21 +00:00
_simConnect . AddToDataDefinition ( DataDefinition . WRITABLE_TRACK_IR_DEFINITION , "TRACK IR ENABLE" , "bool" , SIMCONNECT_DATATYPE . FLOAT64 , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
2024-02-29 00:54:25 +00:00
_simConnect . AddToDataDefinition ( DataDefinition . WRITABLE_COCKPIT_CAMERA_STATE_DEFINITION , "CAMERA STATE" , "enum" , SIMCONNECT_DATATYPE . FLOAT64 , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
2024-02-28 02:44:21 +00:00
_simConnect . AddToDataDefinition ( DataDefinition . WRITABLE_COCKPIT_CAMERA_ZOOM_DEFINITION , "COCKPIT CAMERA ZOOM" , "percentage" , SIMCONNECT_DATATYPE . FLOAT64 , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
_simConnect . AddToDataDefinition ( DataDefinition . WRITABLE_CAMERA_REQUEST_ACTION_DEFINITION , "CAMERA REQUEST ACTION" , "enum" , SIMCONNECT_DATATYPE . FLOAT64 , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
_simConnect . AddToDataDefinition ( DataDefinition . WRITABLE_CAMERA_VIEW_TYPE_INDEX_0_DEFINITION , "CAMERA VIEW TYPE AND INDEX:0" , "number" , SIMCONNECT_DATATYPE . FLOAT64 , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
_simConnect . AddToDataDefinition ( DataDefinition . WRITABLE_CAMERA_VIEW_TYPE_INDEX_1_DEFINITION , "CAMERA VIEW TYPE AND INDEX:1" , "number" , SIMCONNECT_DATATYPE . FLOAT64 , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . REQUIRED_DEFINITION ) ;
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . WRITABLE_TRACK_IR_DEFINITION ) ;
2024-02-29 00:54:25 +00:00
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . WRITABLE_COCKPIT_CAMERA_STATE_DEFINITION ) ;
2024-02-28 02:44:21 +00:00
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . WRITABLE_COCKPIT_CAMERA_ZOOM_DEFINITION ) ;
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . WRITABLE_CAMERA_VIEW_TYPE_INDEX_0_DEFINITION ) ;
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . WRITABLE_CAMERA_VIEW_TYPE_INDEX_1_DEFINITION ) ;
2023-07-12 22:41:31 +00:00
}
2022-08-01 23:21:42 +00:00
2023-07-12 22:41:31 +00:00
private void AddHudBarDataDefinitions ( )
{
if ( _simConnect = = null )
return ;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
_simConnect . ClearDataDefinition ( DataDefinition . HUDBAR_DEFINITION ) ;
2023-07-12 22:41:31 +00:00
if ( _simConnectHudBarDataDefinitions = = null )
return ;
foreach ( var definition in _simConnectHudBarDataDefinitions )
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
if ( definition . DefinitionId ! = DataDefinition . HUDBAR_DEFINITION | |
definition . DataDefinitionType ! = DataDefinitionType . SimConnect ) continue ;
2023-07-12 22:41:31 +00:00
2024-02-28 02:44:21 +00:00
SIMCONNECT_DATATYPE simConnectDataType ;
switch ( definition . DataType )
{
case DataType . String :
simConnectDataType = SIMCONNECT_DATATYPE . STRING256 ;
break ;
case DataType . Float64 :
simConnectDataType = SIMCONNECT_DATATYPE . FLOAT64 ;
break ;
default :
simConnectDataType = SIMCONNECT_DATATYPE . FLOAT64 ;
break ;
2023-07-12 22:41:31 +00:00
}
2024-02-28 02:44:21 +00:00
_simConnect . AddToDataDefinition ( definition . DefinitionId , definition . VariableName , definition . SimConnectUnit , simConnectDataType , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
2022-07-23 19:23:32 +00:00
}
2023-07-12 22:41:31 +00:00
2024-02-28 02:44:21 +00:00
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . HUDBAR_DEFINITION ) ;
2022-07-23 19:23:32 +00:00
}
2024-03-14 22:50:32 +00:00
private void AddDynamicLodDataDefinitions ( )
{
if ( _simConnect = = null )
return ;
_simConnect . ClearDataDefinition ( DataDefinition . DYNAMICLOD_DEFINITION ) ;
if ( _simConnectDynamicLodDataDefinitions = = null )
return ;
foreach ( var definition in _simConnectDynamicLodDataDefinitions )
{
if ( definition . DefinitionId ! = DataDefinition . DYNAMICLOD_DEFINITION | |
definition . DataDefinitionType ! = DataDefinitionType . SimConnect ) continue ;
SIMCONNECT_DATATYPE simConnectDataType ;
switch ( definition . DataType )
{
case DataType . String :
simConnectDataType = SIMCONNECT_DATATYPE . STRING256 ;
break ;
case DataType . Float64 :
simConnectDataType = SIMCONNECT_DATATYPE . FLOAT64 ;
break ;
default :
simConnectDataType = SIMCONNECT_DATATYPE . FLOAT64 ;
break ;
}
_simConnect . AddToDataDefinition ( definition . DefinitionId , definition . VariableName , definition . SimConnectUnit , simConnectDataType , 0.0f , SimConnect . SIMCONNECT_UNUSED ) ;
}
_simConnect . RegisterDataDefineStruct < SimConnectStruct > ( DataDefinition . DYNAMICLOD_DEFINITION ) ;
}
2022-07-23 19:23:32 +00:00
private void HandleOnRecvQuit ( SimConnect sender , SIMCONNECT_RECV data )
{
Stop ( ) ;
2024-02-28 02:44:21 +00:00
OnDisconnected ? . Invoke ( this , EventArgs . Empty ) ;
2022-07-23 19:23:32 +00:00
}
private void HandleOnRecvException ( SimConnect sender , SIMCONNECT_RECV_EXCEPTION data )
{
2024-02-28 02:44:21 +00:00
var e = ( SIMCONNECT_EXCEPTION ) data . dwException ;
2022-07-23 19:23:32 +00:00
switch ( e )
{
case SIMCONNECT_EXCEPTION . DATA_ERROR :
case SIMCONNECT_EXCEPTION . NAME_UNRECOGNIZED :
case SIMCONNECT_EXCEPTION . ALREADY_CREATED :
case SIMCONNECT_EXCEPTION . UNRECOGNIZED_ID :
case SIMCONNECT_EXCEPTION . EVENT_ID_DUPLICATE :
break ;
default :
2024-02-28 02:44:21 +00:00
OnException ? . Invoke ( this , $"SimConnector: SimConnect on receive exception - {e}" ) ;
2022-07-23 19:23:32 +00:00
break ;
}
}
2023-07-12 22:41:31 +00:00
private void HandleOnReceiveSystemEvent ( SimConnect sender , SIMCONNECT_RECV_EVENT data )
{
var systemEvent = ( ( SimConnectEvent ) data . uEventID ) ;
OnReceiveSystemEvent ? . Invoke ( this , systemEvent ) ;
}
2024-02-28 02:44:21 +00:00
private void HandleOnRecvSimObjectDataByType ( SimConnect sender , SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data )
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
if ( _simConnect = = null | | ! Connected )
return ;
2024-02-28 02:44:21 +00:00
switch ( data . dwRequestID )
{
case ( int ) DataRequest . REQUIRED_REQUEST :
ParseRequiredReceivedSimData ( data ) ;
break ;
case ( int ) DataRequest . HUDBAR_REQUEST :
ParseHudBarReceivedSimData ( data ) ;
break ;
2024-03-14 22:50:32 +00:00
case ( int ) DataRequest . DYNAMICLOD_REQUEST :
ParseDynamicLodReceivedSimData ( data ) ;
break ;
2024-02-28 02:44:21 +00:00
}
2023-07-12 22:41:31 +00:00
}
private void ParseRequiredReceivedSimData ( SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data )
{
if ( _simConnectRequiredDataDefinitions = = null )
2022-07-23 19:23:32 +00:00
return ;
try
{
2023-07-12 22:41:31 +00:00
var simData = new List < SimDataItem > ( ) ;
var simDataStruct = ( SimConnectStruct ) data . dwData [ 0 ] ;
2024-02-28 02:44:21 +00:00
var i = 0 ;
2023-07-12 22:41:31 +00:00
foreach ( var definition in _simConnectRequiredDataDefinitions )
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
if ( definition . DataDefinitionType ! = DataDefinitionType . SimConnect )
continue ;
var dataValue = _simConnectStructFields [ i ] . GetValue ( simDataStruct ) ;
var simDataItem = new SimDataItem
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
PropertyName = definition . PropName ,
Value = dataValue = = null ? 0 : ( double ) dataValue
} ;
simData . Add ( simDataItem ) ;
i + + ;
2022-07-23 19:23:32 +00:00
}
2023-07-12 22:41:31 +00:00
OnReceivedRequiredData ? . Invoke ( this , simData ) ;
2022-07-23 19:23:32 +00:00
}
catch ( Exception ex )
{
2023-07-12 22:41:31 +00:00
FileLogger . WriteException ( $"SimConnector: SimConnect received required data exception - {ex.Message}" , ex ) ;
2022-07-23 19:23:32 +00:00
}
}
2023-07-12 22:41:31 +00:00
private void ParseHudBarReceivedSimData ( SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data )
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
try
{
if ( _simConnectHudBarDataDefinitions = = null )
return ;
var simData = new List < SimDataItem > ( ) ;
var simDataStruct = ( SimConnectStruct ) data . dwData [ 0 ] ;
2024-02-28 02:44:21 +00:00
var i = 0 ;
2023-07-12 22:41:31 +00:00
lock ( _simConnectHudBarDataDefinitions )
{
foreach ( var definition in _simConnectHudBarDataDefinitions )
{
2024-02-28 02:44:21 +00:00
if ( definition . DataDefinitionType ! = DataDefinitionType . SimConnect )
continue ;
var dataValue = _simConnectStructFields [ i ] . GetValue ( simDataStruct ) ;
var simDataItem = new SimDataItem
2023-07-12 22:41:31 +00:00
{
2024-02-28 02:44:21 +00:00
PropertyName = definition . PropName ,
Value = dataValue = = null ? 0 : ( double ) dataValue
} ;
simData . Add ( simDataItem ) ;
i + + ;
2023-07-12 22:41:31 +00:00
}
}
OnReceivedHudBarData ? . Invoke ( this , simData ) ;
}
catch ( Exception ex )
{
FileLogger . WriteException ( $"SimConnector: SimConnect received hud bar data exception - {ex.Message}" , ex ) ;
StopAndReconnect ( ) ;
}
2022-07-23 19:23:32 +00:00
}
2022-08-02 15:51:28 +00:00
2024-03-14 22:50:32 +00:00
private void ParseDynamicLodReceivedSimData ( SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data )
{
try
{
if ( _simConnectDynamicLodDataDefinitions = = null )
return ;
var simData = new List < SimDataItem > ( ) ;
var simDataStruct = ( SimConnectStruct ) data . dwData [ 0 ] ;
var i = 0 ;
lock ( _simConnectDynamicLodDataDefinitions )
{
foreach ( var definition in _simConnectDynamicLodDataDefinitions )
{
if ( definition . DataDefinitionType ! = DataDefinitionType . SimConnect )
continue ;
var dataValue = _simConnectStructFields [ i ] . GetValue ( simDataStruct ) ;
var simDataItem = new SimDataItem
{
PropertyName = definition . PropName ,
Value = dataValue = = null ? 0 : ( double ) dataValue
} ;
simData . Add ( simDataItem ) ;
i + + ;
}
}
OnReceivedDynamicLodData ? . Invoke ( this , simData ) ;
}
catch ( Exception ex )
{
FileLogger . WriteException ( $"SimConnector: SimConnect received dynamic lod data exception - {ex.Message}" , ex ) ;
StopAndReconnect ( ) ;
}
}
2022-08-02 15:51:28 +00:00
private void SetActiveAircraftTitle ( string aircraftFilePath )
{
var filePathToken = aircraftFilePath . Split ( @"\" ) ;
2022-08-13 06:14:49 +00:00
if ( filePathToken . Length > 1 )
{
2024-02-28 02:44:21 +00:00
var aircraftName = filePathToken [ ^ 2 ] ;
2022-08-13 06:14:49 +00:00
aircraftName = aircraftName . Replace ( "_" , " " ) . ToUpper ( ) ;
2023-07-12 22:41:31 +00:00
OnActiveAircraftChanged ? . Invoke ( this , aircraftName ) ;
2022-08-13 06:14:49 +00:00
}
2022-08-02 15:51:28 +00:00
}
2022-07-23 19:23:32 +00:00
}
}