1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-10-16 14:10:45 +00:00
msfs-popout-panel-manager/SimconnectAgent/SimConnectProvider.cs

392 lines
13 KiB
C#
Raw Normal View History

2023-07-12 22:41:31 +00:00
using MSFSPopoutPanelManager.DomainModel.Profile;
using System;
2022-07-23 19:23:32 +00:00
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
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 SimConnectProvider
{
private const int MSFS_DATA_REFRESH_TIMEOUT = 500;
2023-08-06 21:43:26 +00:00
private const int MSFS_HUDBAR_DATA_REFRESH_TIMEOUT = 200;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
private readonly SimConnector _simConnector;
2022-07-23 19:23:32 +00:00
private bool _isHandlingCriticalError;
2024-02-28 02:44:21 +00:00
private List<SimDataItem> _requiredSimData;
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
private System.Timers.Timer _requiredRequestDataTimer;
private System.Timers.Timer _hudBarRequestDataTimer;
2022-07-23 19:23:32 +00:00
private bool _isPowerOnForPopOut;
private bool _isAvionicsOnForPopOut;
private bool _isTrackIRManaged;
2023-07-12 22:41:31 +00:00
private bool _isHudBarDataActive;
private HudBarType _activeHudBarType;
2022-07-23 19:23:32 +00:00
public event EventHandler OnConnected;
public event EventHandler OnDisconnected;
2022-08-19 16:03:12 +00:00
public event EventHandler<bool> OnIsInCockpitChanged;
2022-07-23 19:23:32 +00:00
public event EventHandler OnFlightStarted;
public event EventHandler OnFlightStopped;
2023-08-05 03:40:29 +00:00
public event EventHandler OnException;
2023-07-12 22:41:31 +00:00
public event EventHandler<List<SimDataItem>> OnSimConnectDataRequiredRefreshed;
public event EventHandler<List<SimDataItem>> OnSimConnectDataHudBarRefreshed;
public event EventHandler<string> OnActiveAircraftChanged;
2022-07-23 19:23:32 +00:00
public SimConnectProvider()
{
_simConnector = new SimConnector();
_simConnector.OnConnected += HandleSimConnected;
2024-02-28 02:44:21 +00:00
_simConnector.OnDisconnected += HandleSimDisconnected;
2022-07-23 19:23:32 +00:00
_simConnector.OnException += HandleSimException;
_simConnector.OnReceiveSystemEvent += HandleReceiveSystemEvent;
2023-07-12 22:41:31 +00:00
_simConnector.OnReceivedRequiredData += HandleRequiredDataReceived;
_simConnector.OnReceivedHudBarData += HandleHudBarDataReceived;
2024-02-28 02:44:21 +00:00
_simConnector.OnActiveAircraftChanged += (_, e) => OnActiveAircraftChanged?.Invoke(this, e);
2022-07-23 19:23:32 +00:00
_isHandlingCriticalError = false;
2023-07-12 22:41:31 +00:00
_isHudBarDataActive = false;
_activeHudBarType = HudBarType.None;
2022-07-23 19:23:32 +00:00
}
public void Start()
{
2023-07-12 22:41:31 +00:00
_simConnector.Stop();
Thread.Sleep(2000); // wait for everything to stop
2022-07-23 19:23:32 +00:00
_simConnector.Start();
}
public void Stop(bool appExit)
{
_simConnector.Stop();
if (!appExit)
2024-02-28 02:44:21 +00:00
OnDisconnected?.Invoke(this, EventArgs.Empty);
2022-07-23 19:23:32 +00:00
}
public void StopAndReconnect()
{
_simConnector.Stop();
Thread.Sleep(2000); // wait for everything to stop
_simConnector.Restart();
}
2023-07-12 22:41:31 +00:00
public void SetHudBarConfig(HudBarType hudBarType)
{
if (_hudBarRequestDataTimer.Enabled && _activeHudBarType == hudBarType)
return;
_activeHudBarType = hudBarType;
_isHudBarDataActive = true;
// shut down data request and wait for the last request to be completed
_hudBarRequestDataTimer.Stop();
Thread.Sleep(MSFS_HUDBAR_DATA_REFRESH_TIMEOUT);
switch (hudBarType)
{
case HudBarType.Generic_Aircraft:
_simConnector.SetSimConnectHudBarDataDefinition(SimDataDefinitionType.GenericHudBar);
_hudBarRequestDataTimer.Start();
break;
case HudBarType.PMDG_737:
2024-02-28 02:44:21 +00:00
_simConnector.SetSimConnectHudBarDataDefinition(SimDataDefinitionType.Pmdg737HudBar);
2023-07-12 22:41:31 +00:00
_hudBarRequestDataTimer.Start();
break;
default:
_simConnector.SetSimConnectHudBarDataDefinition(SimDataDefinitionType.NoHudBar);
_hudBarRequestDataTimer.Stop();
break;
}
}
public void StopHudBar()
{
_hudBarRequestDataTimer.Stop();
}
2022-07-23 19:23:32 +00:00
public void TurnOnPower(bool isRequiredForColdStart)
{
2024-02-28 02:44:21 +00:00
if (!isRequiredForColdStart || _requiredSimData == null)
2022-07-23 19:23:32 +00:00
return;
// Wait for _simData.AtcOnParkingSpot to refresh
Thread.Sleep(MSFS_DATA_REFRESH_TIMEOUT + 500);
2024-02-28 02:44:21 +00:00
var planeInParkingSpot = Convert.ToBoolean(_requiredSimData.Find(d => d.PropertyName == PropName.PlaneInParkingSpot).Value);
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
if (!planeInParkingSpot)
return;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
Debug.WriteLine("Turn On Battery Power...");
_isPowerOnForPopOut = true;
_simConnector.TransmitActionEvent(ActionEvent.MASTER_BATTERY_SET, 1);
2022-07-23 19:23:32 +00:00
}
2023-07-12 22:41:31 +00:00
public void TurnOffPower(bool isRequiredForColdStart)
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
if (!isRequiredForColdStart || _requiredSimData == null)
2022-07-23 19:23:32 +00:00
return;
2024-02-28 02:44:21 +00:00
if (!_isPowerOnForPopOut)
return;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
Debug.WriteLine("Turn Off Battery Power...");
_simConnector.TransmitActionEvent(ActionEvent.MASTER_BATTERY_SET, 0);
_isPowerOnForPopOut = false;
2022-07-23 19:23:32 +00:00
}
public void TurnOnAvionics(bool isRequiredForColdStart)
{
2024-02-28 02:44:21 +00:00
if (!isRequiredForColdStart || _requiredSimData == null)
2022-07-23 19:23:32 +00:00
return;
2024-02-28 02:44:21 +00:00
var planeInParkingSpot = Convert.ToBoolean(_requiredSimData.Find(d => d.PropertyName == PropName.PlaneInParkingSpot).Value);
if (!planeInParkingSpot)
return;
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
Debug.WriteLine("Turn On Avionics...");
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
_isAvionicsOnForPopOut = true;
_simConnector.TransmitActionEvent(ActionEvent.AVIONICS_MASTER_SET, 1);
2022-07-23 19:23:32 +00:00
}
public void TurnOffAvionics(bool isRequiredForColdStart)
{
2024-02-28 02:44:21 +00:00
if (!isRequiredForColdStart || _requiredSimData == null)
2022-07-23 19:23:32 +00:00
return;
2024-02-28 02:44:21 +00:00
if (!_isAvionicsOnForPopOut)
return;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
Debug.WriteLine("Turn Off Avionics...");
_simConnector.TransmitActionEvent(ActionEvent.AVIONICS_MASTER_SET, 0);
_isAvionicsOnForPopOut = false;
2022-07-23 19:23:32 +00:00
}
2023-07-12 22:41:31 +00:00
public void TurnOnTrackIR()
{
2024-02-28 02:44:21 +00:00
if (_requiredSimData == null)
return;
2023-07-12 22:41:31 +00:00
2024-02-28 02:44:21 +00:00
if (!_isTrackIRManaged)
return;
Debug.WriteLine("Turn On TrackIR...");
SetTrackIREnable(true);
_isTrackIRManaged = false;
2023-07-12 22:41:31 +00:00
}
2022-07-23 19:23:32 +00:00
public void TurnOffTrackIR()
{
2024-02-28 02:44:21 +00:00
if (_requiredSimData == null)
return;
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
var trackIREnable = Convert.ToBoolean(_requiredSimData.Find(d => d.PropertyName == PropName.TrackIREnable).Value);
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
if (!trackIREnable)
return;
Debug.WriteLine("Turn Off TrackIR...");
2022-07-23 19:23:32 +00:00
2024-02-28 02:44:21 +00:00
SetTrackIREnable(false);
_isTrackIRManaged = true;
2022-07-23 19:23:32 +00:00
Thread.Sleep(200);
}
2023-07-12 22:41:31 +00:00
public void TurnOnActivePause()
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
Debug.WriteLine("Active Pause On...");
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
_simConnector.TransmitActionEvent(ActionEvent.PAUSE_SET, 1);
}
public void TurnOffActivePause()
{
2024-02-28 02:44:21 +00:00
Debug.WriteLine("Active Pause Off...");
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
_simConnector.TransmitActionEvent(ActionEvent.PAUSE_SET, 0);
}
public void IncreaseSimRate()
{
_simConnector.TransmitActionEvent(ActionEvent.SIM_RATE_INCR, 1);
Thread.Sleep(200);
}
public void DecreaseSimRate()
{
_simConnector.TransmitActionEvent(ActionEvent.SIM_RATE_DECR, 1);
2022-07-23 19:23:32 +00:00
Thread.Sleep(200);
}
2024-02-29 00:54:25 +00:00
public void SetCameraState(CameraState cameraState)
{
_simConnector.SetDataObject(WritableVariableName.CameraState, Convert.ToDouble(cameraState));
}
2023-07-30 21:30:47 +00:00
public void SetCockpitCameraZoomLevel(int zoomLevel)
{
2024-02-28 02:44:21 +00:00
_simConnector.SetDataObject(WritableVariableName.CockpitCameraZoom, Convert.ToDouble(zoomLevel));
2023-07-30 21:30:47 +00:00
}
2023-08-16 03:41:14 +00:00
public void SetCameraRequestAction(int actionEnum)
{
2024-02-28 02:44:21 +00:00
_simConnector.SetDataObject(WritableVariableName.CameraRequestAction, Convert.ToDouble(actionEnum));
}
public void SetCameraViewTypeAndIndex0(int actionEnum)
{
_simConnector.SetDataObject(WritableVariableName.CameraViewTypeAndIndex0, Convert.ToDouble(actionEnum));
}
public void SetCameraViewTypeAndIndex1(int actionEnum)
{
_simConnector.SetDataObject(WritableVariableName.CameraViewTypeAndIndex1, Convert.ToDouble(actionEnum));
2023-08-16 03:41:14 +00:00
}
2024-02-28 02:44:21 +00:00
2022-07-23 19:23:32 +00:00
private void SetTrackIREnable(bool enable)
{
2024-02-28 02:44:21 +00:00
_simConnector.SetDataObject(WritableVariableName.TrackIREnable, enable ? Convert.ToDouble(1) : Convert.ToDouble(0));
2022-07-23 19:23:32 +00:00
}
private void HandleSimConnected(object source, EventArgs e)
{
2023-07-12 22:41:31 +00:00
// Setup required data request timer
2024-02-28 02:44:21 +00:00
_requiredRequestDataTimer = new()
{
Interval = MSFS_DATA_REFRESH_TIMEOUT
};
2023-07-12 22:41:31 +00:00
_requiredRequestDataTimer.Start();
2024-02-28 02:44:21 +00:00
_requiredRequestDataTimer.Elapsed += (_, _) =>
{
try
{
_simConnector.RequestRequiredData();
_simConnector.ReceiveMessage();
}
catch
{
// ignored
}
};
2023-07-12 22:41:31 +00:00
// Setup hudbar data request timer
2024-02-28 02:44:21 +00:00
_hudBarRequestDataTimer = new()
{
Interval = MSFS_HUDBAR_DATA_REFRESH_TIMEOUT,
};
2023-07-12 22:41:31 +00:00
_hudBarRequestDataTimer.Stop();
2024-02-28 02:44:21 +00:00
_hudBarRequestDataTimer.Elapsed += (_, _) =>
{
try
{
_simConnector.RequestHudBarData();
}
catch
{
// ignored
}
};
2023-07-12 22:41:31 +00:00
if (_isHudBarDataActive)
SetHudBarConfig(_activeHudBarType);
2022-08-13 06:14:49 +00:00
2024-02-28 02:44:21 +00:00
OnConnected?.Invoke(this, EventArgs.Empty);
2022-07-23 19:23:32 +00:00
}
2024-02-28 02:44:21 +00:00
private void HandleSimDisconnected(object source, EventArgs e)
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
_requiredRequestDataTimer.Stop();
_hudBarRequestDataTimer.Stop();
2024-02-28 02:44:21 +00:00
OnDisconnected?.Invoke(this, EventArgs.Empty);
2022-07-23 19:23:32 +00:00
StopAndReconnect();
}
private void HandleSimException(object source, string e)
{
2024-02-28 02:44:21 +00:00
OnException?.Invoke(this, EventArgs.Empty);
2023-08-05 03:40:29 +00:00
2023-07-12 22:41:31 +00:00
_requiredRequestDataTimer.Stop();
_hudBarRequestDataTimer.Stop();
2022-07-23 19:23:32 +00:00
if (!_isHandlingCriticalError)
{
_isHandlingCriticalError = true; // Prevent restarting to occur in parallel
StopAndReconnect();
_isHandlingCriticalError = false;
}
}
2023-07-12 22:41:31 +00:00
private void HandleRequiredDataReceived(object sender, List<SimDataItem> e)
2022-07-23 19:23:32 +00:00
{
2024-02-28 02:44:21 +00:00
_requiredSimData = e;
2023-07-12 22:41:31 +00:00
DetectFlightStartedOrStopped(e);
OnSimConnectDataRequiredRefreshed?.Invoke(this, e);
2022-07-23 19:23:32 +00:00
}
2023-07-12 22:41:31 +00:00
private void HandleHudBarDataReceived(object sender, List<SimDataItem> e)
2022-07-23 19:23:32 +00:00
{
2023-07-12 22:41:31 +00:00
OnSimConnectDataHudBarRefreshed?.Invoke(this, e);
2022-07-23 19:23:32 +00:00
}
2024-02-29 00:54:25 +00:00
private CameraState _currentCameraState = CameraState.Unknown;
2022-07-23 19:23:32 +00:00
2023-07-12 22:41:31 +00:00
private void DetectFlightStartedOrStopped(List<SimDataItem> simData)
2022-07-23 19:23:32 +00:00
{
// Determine is flight started or ended
2024-02-29 00:54:25 +00:00
var cameraStateInt = Convert.ToInt32(simData.Find(d => d.PropertyName == PropName.CameraState).Value);
var success = Enum.TryParse<CameraState>(cameraStateInt.ToString(), out var cameraState);
if(!success)
cameraState = CameraState.Unknown;
2022-07-23 19:23:32 +00:00
if (_currentCameraState == cameraState)
return;
2024-02-29 00:54:25 +00:00
if (cameraState == CameraState.Cockpit)
2022-08-19 16:03:12 +00:00
OnIsInCockpitChanged?.Invoke(this, true);
2024-02-29 00:54:25 +00:00
2022-07-23 20:04:06 +00:00
switch (_currentCameraState)
2022-07-23 19:23:32 +00:00
{
2024-02-29 00:54:25 +00:00
case CameraState.HomeScreen:
case CameraState.LoadScreen:
if (cameraState == CameraState.Cockpit)
2022-07-23 20:04:06 +00:00
{
_currentCameraState = cameraState;
2024-02-28 02:44:21 +00:00
OnFlightStarted?.Invoke(this, EventArgs.Empty);
2022-07-23 20:04:06 +00:00
}
break;
2024-02-29 00:54:25 +00:00
case CameraState.Cockpit:
if (cameraState == CameraState.LoadScreen || cameraState == CameraState.HomeScreen)
2022-07-23 20:04:06 +00:00
{
_currentCameraState = cameraState;
2024-02-28 02:44:21 +00:00
OnFlightStopped?.Invoke(this, EventArgs.Empty);
2022-08-19 16:03:12 +00:00
OnIsInCockpitChanged?.Invoke(this, false);
2023-07-12 22:41:31 +00:00
_isHudBarDataActive = false;
_hudBarRequestDataTimer.Stop();
2022-07-23 20:04:06 +00:00
}
break;
2022-07-23 19:23:32 +00:00
}
2022-07-23 20:04:06 +00:00
2024-02-29 00:54:25 +00:00
if (cameraState is CameraState.Cockpit or CameraState.HomeScreen or CameraState.LoadScreen)
2022-07-23 20:04:06 +00:00
_currentCameraState = cameraState;
2022-07-23 19:23:32 +00:00
}
2023-07-12 22:41:31 +00:00
private void HandleReceiveSystemEvent(object sender, SimConnectEvent e)
2022-07-23 19:23:32 +00:00
{
// TBD
}
}
}