diff --git a/README.md b/README.md
index 06f2c0c..1776443 100644
--- a/README.md
+++ b/README.md
@@ -378,6 +378,19 @@ worldManager.SetTime(new DateTime(year, month, day, hour, minute, 0));
```
+### Radio Manager
+
+The radio manager currently supports setting and getting COM1 and COM2 standby and active frequencies.
+
+```csharp
+
+FsConnect fsConnect = new FsConnect();
+fsConnect.Connect("RadioManagerTest", 0);
+RadioManager radioManager = new RadioManager(_fsConnect);
+radioManager.SetCom1ActiveFrequency(freq);
+
+```
+
## Community
* Have you find a bug? Do you have an idea for a new feature? ... [open an issue on GitHub](https://github.com/c-true/FsConnect/issues)
@@ -387,6 +400,10 @@ worldManager.SetTime(new DateTime(year, month, day, hour, minute, 0));
## Change log
+## 1.3.2
+
+* Added RadioManager, with support for setting and getting COM1 and COM2 standby and active frequencies.
+
## 1.3.1
* [Breaking] SimProperty renamed to SimVar, minor other renames.
diff --git a/src/CTrue.FsConnect.ExampleConsole/Program.cs b/src/CTrue.FsConnect.ExampleConsole/Program.cs
index 78d363c..6a698d8 100644
--- a/src/CTrue.FsConnect.ExampleConsole/Program.cs
+++ b/src/CTrue.FsConnect.ExampleConsole/Program.cs
@@ -66,7 +66,7 @@ public static void Main(string[] args)
do
{
- fsConnect.RequestData(Requests.PlaneInfoRequest, planeInfoDefinitionId);
+ fsConnect.RequestData((int)Requests.PlaneInfoRequest, planeInfoDefinitionId);
cki = Console.ReadKey();
} while (cki.Key != ConsoleKey.Escape);
diff --git a/src/CTrue.FsConnect.Managers.Test/AircraftManagersIntegrationTests.cs b/src/CTrue.FsConnect.Managers.Test/AircraftManagersIntegrationTests.cs
new file mode 100644
index 0000000..d2ca8b4
--- /dev/null
+++ b/src/CTrue.FsConnect.Managers.Test/AircraftManagersIntegrationTests.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using NUnit.Framework;
+
+namespace CTrue.FsConnect.Managers.Test
+{
+ ///
+ /// World manager integration tests.
+ ///
+ ///
+ /// Load MSFS and an aircraft before running.
+ /// Observe that the time changes in the simulator.
+ ///
+ [TestFixture(Explicit = true)]
+ public class AircraftManagersIntegrationTests
+ {
+ [Test]
+ public void GetAircraftData()
+ {
+ // Arrange
+ AutoResetEvent resetEvent = new AutoResetEvent(false);
+ int errorCount = 0;
+
+ FsConnect fsConnect = new FsConnect();
+ fsConnect.ConnectionChanged += (sender, b) =>
+ {
+ if (b) resetEvent.Set();
+ };
+ fsConnect.FsError += (sender, args) =>
+ {
+ errorCount++;
+ Console.WriteLine($"Error: {args.ExceptionDescription}");
+ };
+
+ fsConnect.Connect("AircraftManagersIntegrationTests", 0);
+
+ bool res = resetEvent.WaitOne(2000);
+ if(!res) Assert.Fail("Not connected to MSFS within timeout");
+
+ var defId = fsConnect.RegisterDataDefinition();
+
+ AircraftManager aircraftManager = new AircraftManager(fsConnect, defId);
+
+ // Act
+ var info = aircraftManager.Get();
+
+ // Assert
+ Assert.That(errorCount, Is.Zero);
+ Assert.That(info.Title, Is.Not.Empty);
+ Assert.That(info.Latitude, Is.Not.EqualTo(0));
+ Assert.That(info.Longitude, Is.Not.EqualTo(0));
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
+ public struct AircraftInfo
+ {
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public String Title;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public String Category;
+ [SimVar(NameId = FsSimVar.PlaneLatitude, UnitId = FsUnit.Radian)]
+ public double Latitude;
+ [SimVar(NameId = FsSimVar.PlaneLongitude, UnitId = FsUnit.Radian)]
+ public double Longitude;
+ [SimVar(NameId = FsSimVar.PlaneAltitudeAboveGround, UnitId = FsUnit.Feet)]
+ public double AltitudeAboveGround;
+ [SimVar(NameId = FsSimVar.PlaneAltitude, UnitId = FsUnit.Feet)]
+ public double Altitude;
+ [SimVar(NameId = FsSimVar.PlaneHeadingDegreesTrue, UnitId = FsUnit.Degree)]
+ public double Heading;
+ [SimVar(NameId = FsSimVar.AirspeedTrue, UnitId = FsUnit.Knot)]
+ public double Speed;
+ };
+}
diff --git a/src/CTrue.FsConnect.Managers.Test/RadioManagerTests.cs b/src/CTrue.FsConnect.Managers.Test/RadioManagerTests.cs
new file mode 100644
index 0000000..cfd6850
--- /dev/null
+++ b/src/CTrue.FsConnect.Managers.Test/RadioManagerTests.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Threading;
+using NUnit.Framework;
+
+namespace CTrue.FsConnect.Managers.Test
+{
+ ///
+ /// Radio manager integration tests.
+ ///
+ ///
+ /// Load MSFS and an aircraft before running.
+ ///
+ [TestFixture(Explicit = true)]
+ public class RadioManagerTests
+ {
+ private FsConnect _fsConnect;
+ private RadioManager _manager;
+
+ [SetUp]
+ public void SetUp()
+ {
+ AutoResetEvent resetEvent = new AutoResetEvent(false);
+
+ _fsConnect = new FsConnect();
+ _fsConnect.ConnectionChanged += (sender, b) =>
+ {
+ if (b) resetEvent.Set();
+ };
+ _fsConnect.FsError += (sender, args) =>
+ {
+ Assert.Fail($"MSFS Error: {args.ExceptionDescription}");
+ };
+
+ _fsConnect.Connect("RadioManagerIntegrationTest", 0);
+
+ bool res = resetEvent.WaitOne(2000);
+ if (!res) Assert.Fail("Not connected to MSFS within timeout");
+
+ _manager = new RadioManager(_fsConnect);
+ }
+
+ [Test]
+ public void SetCom1StandbyFrequency()
+ {
+ // Arrange
+ double freq = 124.774d;
+
+ // Act
+ _manager.SetCom1StandbyFrequency(freq);
+
+ // Assert
+ _manager.Update();
+ Assert.That(_manager.Com1StandbyFrequency, Is.EqualTo(freq));
+ }
+
+ [Test]
+ public void SetCom1ActiveFrequency()
+ {
+ // Arrange
+ double freq = 124.774d;
+
+ // Act
+ _manager.SetCom1ActiveFrequency(freq);
+
+ // Assert
+ _manager.Update();
+ Assert.That(_manager.Com1ActiveFrequency, Is.EqualTo(freq));
+ }
+
+ [Test]
+ public void SetCom2StandbyFrequency()
+ {
+ // Arrange
+ double freq = 124.774d;
+
+ // Act
+ _manager.SetCom2StandbyFrequency(freq);
+
+ // Assert
+ _manager.Update();
+ Assert.That(_manager.Com2StandbyFrequency, Is.EqualTo(freq));
+ }
+
+ [Test]
+ public void SetCom2ActiveFrequency()
+ {
+ // Arrange
+ double freq = 124.773d;
+
+ // Act
+ _manager.SetCom2ActiveFrequency(freq);
+
+ // Assert
+ _manager.Update();
+ Assert.That(_manager.Com2ActiveFrequency, Is.EqualTo(freq));
+ }
+
+ [Test]
+ public void SwapCom1()
+ {
+ // Arrange
+ double freq = 124.773d;
+ _manager.SetCom1StandbyFrequency(freq);
+ _manager.SetCom1ActiveFrequency(125.000d);
+
+ // Act
+ _manager.Com1Swap();
+
+ // Assert
+ _manager.Update();
+ Assert.That(_manager.Com1ActiveFrequency, Is.EqualTo(freq));
+ }
+
+ [Test]
+ public void SwapCom2()
+ {
+ // Arrange
+ double freq = 124.773d;
+ _manager.SetCom2StandbyFrequency(freq);
+ _manager.SetCom2ActiveFrequency(125.000d);
+
+ // Act
+ _manager.Com2Swap();
+
+ // Assert
+ _manager.Update();
+ Assert.That(_manager.Com2ActiveFrequency, Is.EqualTo(freq));
+ }
+ }
+}
diff --git a/src/CTrue.FsConnect.Managers.Test/FsConnectManagersIntegrationTests.cs b/src/CTrue.FsConnect.Managers.Test/WorldManagerIntegrationTests.cs
similarity index 93%
rename from src/CTrue.FsConnect.Managers.Test/FsConnectManagersIntegrationTests.cs
rename to src/CTrue.FsConnect.Managers.Test/WorldManagerIntegrationTests.cs
index 1ecf109..831fe22 100644
--- a/src/CTrue.FsConnect.Managers.Test/FsConnectManagersIntegrationTests.cs
+++ b/src/CTrue.FsConnect.Managers.Test/WorldManagerIntegrationTests.cs
@@ -12,7 +12,7 @@ namespace CTrue.FsConnect.Managers.Test
/// Observe that the time changes in the simulator.
///
[TestFixture(Explicit = true)]
- public class FsConnectManagersIntegrationTests
+ public class WorldManagerIntegrationTests
{
[Test]
public void SetTime_SetsTimeInMSFS()
@@ -32,7 +32,7 @@ public void SetTime_SetsTimeInMSFS()
Console.WriteLine($"Error: {args.ExceptionDescription}");
};
- fsConnect.Connect("FsConnectManagersIntegrationTest", 0);
+ fsConnect.Connect("WorldManagerIntegrationTests", 0);
bool res = resetEvent.WaitOne(2000);
if(!res) Assert.Fail("Not connected to MSFS within timeout");
diff --git a/src/CTrue.FsConnect.Managers/AircraftManager.cs b/src/CTrue.FsConnect.Managers/AircraftManager.cs
index cfa0109..221a608 100644
--- a/src/CTrue.FsConnect.Managers/AircraftManager.cs
+++ b/src/CTrue.FsConnect.Managers/AircraftManager.cs
@@ -73,6 +73,26 @@ public RequestMethod RequestMethod
}
}
+ ///
+ /// Creates an instance of the class.
+ ///
+ ///
+ public AircraftManager(IFsConnect fsConnect, int defineId)
+ : this(fsConnect, defineId, fsConnect.GetNextId())
+ {
+ }
+
+ ///
+ /// Creates an instance of the class.
+ ///
+ ///
+ /// The definition used when registering the aircraft information structure.
+ /// The request Id to use when requesting data using the manager.
+ public AircraftManager(IFsConnect fsConnect, int defineId, int requestId)
+ : this(fsConnect, (FsConnectEnum)defineId, (FsConnectEnum)requestId)
+ {
+ }
+
///
/// Creates an instance of the class.
///
diff --git a/src/CTrue.FsConnect.Managers/CTrue.FsConnect.Managers.csproj b/src/CTrue.FsConnect.Managers/CTrue.FsConnect.Managers.csproj
index fd34e45..18abcf0 100644
--- a/src/CTrue.FsConnect.Managers/CTrue.FsConnect.Managers.csproj
+++ b/src/CTrue.FsConnect.Managers/CTrue.FsConnect.Managers.csproj
@@ -11,6 +11,7 @@
- Aircraft information
- Retrieving sim objects
- Setting world time
+ - Controlling COM radios
C-True
true
@@ -18,11 +19,11 @@
true
https://github.com/c-true/FsConnect
msfs flight-simulator simconnect
- 1.3.1
+ 1.3.2
true
-
- 1.3.1.0
- 1.3.1.0
+ Added RadioManager for controlling COM radios.
+ 1.3.2.0
+ 1.3.2.0
diff --git a/src/CTrue.FsConnect.Managers/RadioManager.cs b/src/CTrue.FsConnect.Managers/RadioManager.cs
new file mode 100644
index 0000000..30dc2df
--- /dev/null
+++ b/src/CTrue.FsConnect.Managers/RadioManager.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace CTrue.FsConnect.Managers
+{
+ ///
+ /// The controls the navigation and communication radios in the current aircraft.
+ ///
+ ///
+ /// Note: Currently only 2 decimal frequencies, e.g. 120.25 are supported, not 3 decimal frequencies such as 128.725
+ ///
+ public interface IRadioManager
+ {
+ ///
+ /// Gets the COM1 Active frequency as returned from the last call with .
+ ///
+ ///
+ /// The active frequency is changed by setting the COM1 standby frequency and calling
+ ///
+ double Com1ActiveFrequency { get; }
+
+ ///
+ /// Gets the COM1 Standby frequency as returned from the last call with .
+ ///
+ double Com1StandbyFrequency { get; }
+
+ ///
+ /// Gets the COM2 Active frequency as returned from the last call with .
+ ///
+ ///
+ /// The active frequency is changed by setting the COM2 standby frequency and calling
+ ///
+ double Com2ActiveFrequency { get; }
+
+ ///
+ /// Gets the COM2 Standby frequency as returned from the last call with .
+ ///
+ double Com2StandbyFrequency { get; }
+
+ ///
+ /// Sets the COM1 standby frequency.
+ ///
+ /// The frequency, in MHz, e.g. 124.100
+ ///
+ /// Range: 118.000 to 135.975Mhz
+ ///
+ void SetCom1StandbyFrequency(double frequency);
+
+ ///
+ /// Sets the COM1 active frequency.
+ ///
+ /// The frequency, in MHz, e.g. 124.100
+ ///
+ /// Range: 118.000 to 135.975Mhz
+ ///
+ void SetCom1ActiveFrequency(double frequency);
+
+ ///
+ /// Sets the COM2 standby frequency.
+ ///
+ /// The frequency, in MHz, e.g. 124.100
+ ///
+ /// Range: 118.000 to 135.975Mhz
+ ///
+ void SetCom2StandbyFrequency(double frequency);
+
+ ///
+ /// Sets the COM2 active frequency.
+ ///
+ /// The frequency, in MHz, e.g. 124.10
+ ///
+ /// Range: 118.000 to 135.975Mhz
+ ///
+ void SetCom2ActiveFrequency(double frequency);
+
+ ///
+ /// Swaps COMS1 active and standby frequency.
+ ///
+ void Com1Swap();
+
+ ///
+ /// Swaps COMS2 active and standby frequency.
+ ///
+ void Com2Swap();
+
+ ///
+ /// Request new radio data from MSFS.
+ ///
+ ///
+ /// The call is blocked until an update is returned.
+ ///
+ void Update();
+ }
+
+ ///
+ public class RadioManager : IRadioManager
+ {
+ private readonly IFsConnect _fsConnect;
+ private AutoResetEvent _resetEvent = new AutoResetEvent(false);
+ private int _groupId;
+
+ private int _com1StbyRadioSetHzEventId;
+ private int _com1ActiveRadioSetHzEventId;
+ private int _com1StbySwapEventId;
+
+ private int _com2StbyRadioSetHzEventId;
+ private int _com2ActiveRadioSetHzEventId;
+ private int _com2StbySwapEventId;
+
+ private RadioManagerSimVars _radioManagerSimVars = new RadioManagerSimVars();
+ private int _radioManagerSimVarsReqId;
+ private int _radioManagerSimVarsDefId;
+
+ ///
+ public double Com1StandbyFrequency { get; private set; }
+
+ ///
+ public double Com1ActiveFrequency { get; private set; }
+
+ ///
+ public double Com2StandbyFrequency { get; private set; }
+
+ ///
+ public double Com2ActiveFrequency { get; private set; }
+
+ ///
+ /// Creates a new instance.
+ ///
+ ///
+ public RadioManager(IFsConnect fsConnect)
+ {
+ _fsConnect = fsConnect;
+
+ RegisterEvents();
+ }
+
+ ///
+ public void Com1Swap()
+ {
+ _fsConnect.TransmitClientEvent(_com1StbySwapEventId, 0, _groupId);
+ }
+
+ ///
+ public void Com2Swap()
+ {
+ _fsConnect.TransmitClientEvent(_com2StbySwapEventId, 0, _groupId);
+ }
+
+ private void RegisterEvents()
+ {
+ _fsConnect.FsDataReceived += OnFsDataReceived;
+ _groupId = _fsConnect.GetNextId();
+
+ _com1StbyRadioSetHzEventId = _fsConnect.GetNextId();
+ _fsConnect.MapClientEventToSimEvent(_groupId, _com1StbyRadioSetHzEventId, FsEventNameId.ComStbyRadioSetHz);
+
+ _com1ActiveRadioSetHzEventId = _fsConnect.GetNextId();
+ _fsConnect.MapClientEventToSimEvent(_groupId, _com1ActiveRadioSetHzEventId, FsEventNameId.ComRadioSetHz);
+
+ _com1StbySwapEventId = _fsConnect.GetNextId();
+ _fsConnect.MapClientEventToSimEvent(_groupId, _com1StbySwapEventId, FsEventNameId.ComStbyRadioSwitchTo);
+
+ _com2StbyRadioSetHzEventId = _fsConnect.GetNextId();
+ _fsConnect.MapClientEventToSimEvent(_groupId, _com2StbyRadioSetHzEventId, FsEventNameId.Com2StbyRadioSetHz);
+
+ _com2ActiveRadioSetHzEventId = _fsConnect.GetNextId();
+ _fsConnect.MapClientEventToSimEvent(_groupId, _com2ActiveRadioSetHzEventId, FsEventNameId.Com2RadioSetHz);
+
+ _com2StbySwapEventId = _fsConnect.GetNextId();
+ _fsConnect.MapClientEventToSimEvent(_groupId, _com2StbySwapEventId, FsEventNameId.Com2RadioSwap);
+
+ _fsConnect.SetNotificationGroupPriority(_groupId);
+
+ _radioManagerSimVarsReqId = _fsConnect.GetNextId();
+ _radioManagerSimVarsDefId = _fsConnect.RegisterDataDefinition();
+ }
+
+ private void OnFsDataReceived(object sender, FsDataReceivedEventArgs e)
+ {
+ if (e.Data.Count == 0) return;
+ if (!(e.Data[0] is RadioManagerSimVars)) return;
+
+ _radioManagerSimVars = (RadioManagerSimVars) e.Data[0];
+ _resetEvent.Set();
+ }
+
+ ///
+ public void Update()
+ {
+ _fsConnect.RequestData(_radioManagerSimVarsReqId, _radioManagerSimVarsDefId);
+ bool resetRes =_resetEvent.WaitOne(10000);
+
+ if(!resetRes)
+ throw new TimeoutException("Radio Manager data was not returned from MSFS within timeout");
+
+ Com1StandbyFrequency = new FrequencyBcd(_radioManagerSimVars.Com1StandbyFrequency).Value;
+ Com1ActiveFrequency = new FrequencyBcd(_radioManagerSimVars.Com1ActiveFrequency).Value;
+ Com2ActiveFrequency = new FrequencyBcd(_radioManagerSimVars.Com2ActiveFrequency).Value;
+ Com2StandbyFrequency = new FrequencyBcd(_radioManagerSimVars.Com2StandbyFrequency).Value;
+ }
+
+ ///
+ public void SetCom1StandbyFrequency(double frequency)
+ {
+ FrequencyBcd freqBcd = new FrequencyBcd(frequency);
+ _fsConnect.TransmitClientEvent(_com1StbyRadioSetHzEventId, freqBcd.Bcd32Value, _groupId);
+ }
+
+ ///
+ public void SetCom1ActiveFrequency(double frequency)
+ {
+ FrequencyBcd freqBcd = new FrequencyBcd(frequency);
+ _fsConnect.TransmitClientEvent(_com1ActiveRadioSetHzEventId, freqBcd.Bcd32Value, _groupId);
+ }
+
+ ///
+ public void SetCom2StandbyFrequency(double frequency)
+ {
+ FrequencyBcd freqBcd = new FrequencyBcd(frequency);
+ _fsConnect.TransmitClientEvent(_com2StbyRadioSetHzEventId, freqBcd.Bcd32Value, _groupId);
+ }
+
+ ///
+ public void SetCom2ActiveFrequency(double frequency)
+ {
+ FrequencyBcd freqBcd = new FrequencyBcd(frequency);
+ _fsConnect.TransmitClientEvent(_com2ActiveRadioSetHzEventId, freqBcd.Bcd32Value, _groupId);
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
+ public struct RadioManagerSimVars
+ {
+ [SimVar(NameId = FsSimVar.ComActiveFrequency, UnitId = FsUnit.FrequencyBcd32, Instance = 1)]
+ public uint Com1ActiveFrequency;
+
+ [SimVar(NameId = FsSimVar.ComStandbyFrequency, UnitId = FsUnit.FrequencyBcd32, Instance = 1)]
+ public uint Com1StandbyFrequency;
+
+ [SimVar(NameId = FsSimVar.ComActiveFrequency, UnitId = FsUnit.FrequencyBcd32, Instance = 2)]
+ public uint Com2ActiveFrequency;
+
+ [SimVar(NameId = FsSimVar.ComStandbyFrequency, UnitId = FsUnit.FrequencyBcd32, Instance = 2)]
+ public uint Com2StandbyFrequency;
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CTrue.FsConnect.Test/BcdTests.cs b/src/CTrue.FsConnect.Test/BcdTests.cs
new file mode 100644
index 0000000..54e3545
--- /dev/null
+++ b/src/CTrue.FsConnect.Test/BcdTests.cs
@@ -0,0 +1,46 @@
+using System;
+using NUnit.Framework;
+
+namespace CTrue.FsConnect.Test
+{
+ [TestFixture]
+ public class BcdTests
+ {
+ [Test]
+ public void Test()
+ {
+ /*
+ def to_radio_bcd16(val):
+ encodable = int(val * 100)
+ remainder = ((val * 100) - encodable) / 100.0
+ return int(str(encodable), 16), round(remainder,3), val
+ */
+ double freq = 128.775;
+ uint freq1 = (uint)(freq * 100);
+ double remainder = ((freq * 100) - freq1) / 100.0;
+ var bcd = Bcd.Dec2Bcd(freq1);
+ var freq2 = Bcd.Bcd2Dec(bcd);
+
+
+ Assert.That(freq2, Is.EqualTo(freq1));
+
+ //Assert.That(ToRadioBcd(128.775), Is.EqualTo(75895));
+
+ }
+
+ [Test]
+ public void Test2()
+ {
+ double freq = 128.775;
+
+ // Act
+ var bcd = Bcd.Dec2Bcd(freq);
+
+ // Assert
+ var freqOutUint = Bcd.Bcd2Dec(bcd);
+ var freqOutDouble = (double)freqOutUint / 100;
+
+ Assert.That(freqOutDouble, Is.EqualTo(freq));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CTrue.FsConnect.Test/FrequencyBcdTest.cs b/src/CTrue.FsConnect.Test/FrequencyBcdTest.cs
new file mode 100644
index 0000000..4032d5d
--- /dev/null
+++ b/src/CTrue.FsConnect.Test/FrequencyBcdTest.cs
@@ -0,0 +1,31 @@
+using NUnit.Framework;
+
+namespace CTrue.FsConnect.Test
+{
+ [TestFixture]
+ public class FrequencyBcdTest
+ {
+ [Test]
+ public void Test()
+ {
+ FrequencyBcd freq = new FrequencyBcd(128.775);
+
+ Assert.That(freq.Bcd16Value, Is.EqualTo(75895));
+
+ FrequencyBcd freq2 = new FrequencyBcd(freq.Bcd16Value);
+
+ Assert.That(freq2.Value, Is.EqualTo(128.75));
+ }
+
+ [Test]
+ public void Test2([Values(124.00, 127.90)] double frequency)
+ {
+ // Act
+ FrequencyBcd freq = new FrequencyBcd(frequency);
+ FrequencyBcd freq2 = new FrequencyBcd(freq.Bcd16Value);
+
+ // Assert
+ Assert.That(freq2.Value, Is.EqualTo(frequency));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CTrue.FsConnect.Test/FsConnectIntegrationTest.cs b/src/CTrue.FsConnect.Test/FsConnectIntegrationTest.cs
new file mode 100644
index 0000000..cbdc48d
--- /dev/null
+++ b/src/CTrue.FsConnect.Test/FsConnectIntegrationTest.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Microsoft.FlightSimulator.SimConnect;
+using NUnit.Framework;
+namespace CTrue.FsConnect.Test
+{
+ [TestFixture, Explicit]
+ public class FsConnectIntegrationTest
+ {
+ enum TestEnums
+ {
+ GroupId = 1234,
+ EventId = 1235,
+ RequestId
+ }
+
+ [Test]
+ public void TransmitClientEvent_HeadingBugDirectionSet_SetsHeadingBugDirection()
+ {
+ // Arrange
+ AutoResetEvent resetEvent = new AutoResetEvent(false);
+ int errorCount = 0;
+
+ FsConnect fsConnect = new FsConnect();
+ fsConnect.ConnectionChanged += (sender, b) =>
+ {
+ if (b) resetEvent.Set();
+ };
+
+ fsConnect.FsError += (sender, args) =>
+ {
+ errorCount++;
+ Console.WriteLine($"Error: {args.ExceptionDescription}");
+ };
+
+ fsConnect.Connect("FsConnectIntegrationTest", 0);
+ bool res = resetEvent.WaitOne(2000);
+ if (!res) Assert.Fail("Not connected to MSFS within timeout");
+
+ var hbDef = fsConnect.RegisterDataDefinition();
+ HeadingBugTest headingBugData = default;
+
+ // Act
+ fsConnect.MapClientEventToSimEvent(TestEnums.GroupId, TestEnums.EventId, FsEventNameId.HeadingBugSet);
+ fsConnect.SetNotificationGroupPriority(TestEnums.GroupId);
+ uint headingValue = (uint)DateTime.Now.Second * 6;
+ fsConnect.TransmitClientEvent(TestEnums.EventId, (uint)headingValue, TestEnums.GroupId);
+
+ // Assert
+ Assert.That(errorCount, Is.Zero, "MSFS returned errors. Check console output.");
+
+ fsConnect.FsDataReceived += (sender, args) =>
+ {
+ var data = args.Data.FirstOrDefault();
+
+ headingBugData = data is HeadingBugTest ? (HeadingBugTest) data : default;
+
+ resetEvent.Set();
+ };
+
+ fsConnect.RequestData((int)TestEnums.RequestId, hbDef);
+ res = resetEvent.WaitOne(2000);
+ if (!res) Assert.Fail("Data not returned from MSFS within timeout");
+
+ Assert.That(headingBugData, Is.Not.Null);
+ Assert.That(headingBugData.HeadingBug, Is.EqualTo(headingValue));
+
+ // Teardown
+ fsConnect?.Disconnect();
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
+ public struct HeadingBugTest
+ {
+ [SimVar(NameId = FsSimVar.AutopilotHeadingLockDir, UnitId = FsUnit.Degree)]
+ public double HeadingBug;
+ }
+}
\ No newline at end of file
diff --git a/src/CTrue.FsConnect/Bcd.cs b/src/CTrue.FsConnect/Bcd.cs
new file mode 100644
index 0000000..c7f1a04
--- /dev/null
+++ b/src/CTrue.FsConnect/Bcd.cs
@@ -0,0 +1,45 @@
+namespace CTrue.FsConnect
+{
+ ///
+ /// Handles the BCD format
+ ///
+ public static class Bcd
+ {
+ ///
+ /// Converts from binary coded decimal to integer
+ ///
+ ///
+ ///
+ public static uint Bcd2Dec(uint num)
+ {
+ return HornerScheme(num, 0x10, 10);
+ }
+
+ ///
+ /// Converts from integer to binary coded decimal
+ ///
+ ///
+ ///
+ public static uint Dec2Bcd(uint num)
+ {
+ return HornerScheme(num, 10, 0x10);
+ }
+
+ public static uint Dec2Bcd(double num)
+ {
+ return Dec2Bcd((uint) (num * 100));
+ }
+
+ private static uint HornerScheme(uint Num, uint Divider, uint Factor)
+ {
+ uint Remainder = 0, Quotient = 0, Result = 0;
+ Remainder = Num % Divider;
+ Quotient = Num / Divider;
+
+ if (!(Quotient == 0 && Remainder == 0))
+ Result += HornerScheme(Quotient, Divider, Factor) * Factor + Remainder;
+
+ return Result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CTrue.FsConnect/CTrue.FsConnect.csproj b/src/CTrue.FsConnect/CTrue.FsConnect.csproj
index 3e1ec47..9c6f291 100644
--- a/src/CTrue.FsConnect/CTrue.FsConnect.csproj
+++ b/src/CTrue.FsConnect/CTrue.FsConnect.csproj
@@ -13,11 +13,11 @@ Contains SimConnect binaries, as distributed by the Flight Simulator 20202 SDK 0
true
https://github.com/c-true/FsConnect
msfs flight-simulator simconnect
- 1.3.1
+ 1.3.2
true
- Support for SimVar reflection, client event enum
- 1.3.1.0
- 1.3.1.0
+ Added and updated some method signatures. * Added event ids for setting COM and NAV frequencies.
+ 1.3.2.0
+ 1.3.2.0
diff --git a/src/CTrue.FsConnect/FrequencyBcd.cs b/src/CTrue.FsConnect/FrequencyBcd.cs
new file mode 100644
index 0000000..5b4816b
--- /dev/null
+++ b/src/CTrue.FsConnect/FrequencyBcd.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace CTrue.FsConnect
+{
+ public class FrequencyBcd
+ {
+ private double _value = 0;
+ private uint _bcd16Value = 0;
+ private uint _bcd32Value = 0;
+
+ public double Value => _value;
+
+ ///
+ /// Gets the BCD encoded as 32 bit.
+ ///
+ public uint Bcd32Value => _bcd32Value;
+
+ ///
+ /// Gets the BCD encoded as 16 bit.
+ ///
+ public uint Bcd16Value => _bcd16Value;
+
+ public FrequencyBcd(double freqValue)
+ {
+ _value = freqValue;
+
+ uint encodable = (uint)((_value - 100) * 100);
+ double remainder = ((_value * 100) - encodable) / 100.0;
+
+ _bcd16Value = Bcd.Dec2Bcd(encodable);
+
+ Byte[] bytes = BitConverter.GetBytes(Convert.ToInt32(freqValue * 1000000));
+ _bcd32Value = BitConverter.ToUInt32(bytes, 0);
+ }
+
+ public FrequencyBcd(uint bcd32Value)
+ {
+ _bcd32Value = bcd32Value;
+ var freqOutUint = Bcd.Bcd2Dec(_bcd32Value);
+ _value = (double)freqOutUint / 10000;
+ }
+
+ public FrequencyBcd(ushort bcd16Value)
+ {
+ _bcd16Value = bcd16Value;
+ var freqOutUint = Bcd.Bcd2Dec(_bcd16Value);
+ var tmp = freqOutUint + 10000;
+ _value = (double)tmp / 100;
+ //_value = Math.Round(_value * 4, MidpointRounding.ToEven) / 4;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CTrue.FsConnect/FsConnect.cs b/src/CTrue.FsConnect/FsConnect.cs
index 2543ade..9425aa0 100644
--- a/src/CTrue.FsConnect/FsConnect.cs
+++ b/src/CTrue.FsConnect/FsConnect.cs
@@ -268,9 +268,9 @@ public void RequestData(Enum requestId, Enum defineId, uint radius = 0, FsConnec
}
///
- public void RequestData(Enum requestId, int defineId, uint radius = 0, FsConnectSimobjectType type = FsConnectSimobjectType.User)
+ public void RequestData(int requestId, int defineId, uint radius = 0, FsConnectSimobjectType type = FsConnectSimobjectType.User)
{
- _simConnect?.RequestDataOnSimObjectType(requestId, (FsConnectEnum)defineId, radius, (SIMCONNECT_SIMOBJECT_TYPE)type);
+ _simConnect?.RequestDataOnSimObjectType((FsConnectEnum)requestId, (FsConnectEnum)defineId, radius, (SIMCONNECT_SIMOBJECT_TYPE)type);
}
#endregion
@@ -341,6 +341,12 @@ public void TransmitClientEvent(Enum eventId, uint dwData, Enum groupId)
_simConnect.TransmitClientEvent((uint)SIMCONNECT_SIMOBJECT_TYPE.USER, eventId, dwData, groupId, SIMCONNECT_EVENT_FLAG.DEFAULT);
}
+ ///
+ public void TransmitClientEvent(int eventId, uint dwData, int groupId)
+ {
+ _simConnect.TransmitClientEvent((uint)SIMCONNECT_SIMOBJECT_TYPE.USER, (FsConnectEnum)eventId, dwData, (FsConnectEnum)groupId, SIMCONNECT_EVENT_FLAG.DEFAULT);
+ }
+
///
public void SetText(string text, int duration)
{
diff --git a/src/CTrue.FsConnect/FsEventNameId.cs b/src/CTrue.FsConnect/FsEventNameId.cs
index 3f2821a..9f67a07 100644
--- a/src/CTrue.FsConnect/FsEventNameId.cs
+++ b/src/CTrue.FsConnect/FsEventNameId.cs
@@ -3957,6 +3957,38 @@ public enum FsEventNameId
/// Show or hide multi-player race results.
///
ToggleRaceresultsWindow,
+ ///
+ /// Set COM1 Standby frequency.
+ ///
+ ComRadioSetHz,
+ ///
+ /// Set COM2 Standby frequency.
+ ///
+ Com2RadioSetHz,
+ ///
+ /// Set NAV1 Standby frequency.
+ ///
+ Nav1RadioSetHz,
+ ///
+ /// Set NAV2 Standby frequency.
+ ///
+ Nav2RadioSetHz,
+ ///
+ /// Set COM1 Standby frequency.
+ ///
+ ComStbyRadioSetHz,
+ ///
+ /// Set COM2 Standby frequency.
+ ///
+ Com2StbyRadioSetHz,
+ ///
+ /// Set NAV1 Standby frequency.
+ ///
+ Nav1StbyRadioSetHz,
+ ///
+ /// Set NAV2 Standby frequency.
+ ///
+ Nav2StbyRadioSetHz,
};
///
@@ -4484,7 +4516,7 @@ internal static class FsEventNameLookup
"AVIONICS_MASTER_SET",
"TOGGLE_AVIONICS_MASTER",
"COM_STBY_RADIO_SET",
- "COM_STBY_RADIO_SWITCH_TO",
+ "COM_STBY_RADIO_SWAP",
"COM_RADIO_FRACT_DEC_CARRY",
"COM_RADIO_FRACT_INC_CARRY",
"COM2_RADIO_WHOLE_DEC",
@@ -4952,6 +4984,14 @@ internal static class FsEventNameLookup
"MULTIPLAYER_VOICE_CAPTURE_STOP",
"MULTIPLAYER_BROADCAST_VOICE_",
"TOGGLE_RACERESULTS_WINDOW",
+ "COM_RADIO_SET_HZ",
+ "COM2_RADIO_SET_HZ",
+ "NAV1_RADIO_SET_HZ",
+ "NAV2_RADIO_SET_HZ",
+ "COM_STBY_RADIO_SET_HZ",
+ "COM2_STBY_RADIO_SET_HZ",
+ "NAV1_STBY_RADIO_SET_HZ",
+ "NAV2_STBY_RADIO_SET_HZ"
};
///
diff --git a/src/CTrue.FsConnect/FsSimVar.cs b/src/CTrue.FsConnect/FsSimVar.cs
index c03f3fc..458f5ef 100644
--- a/src/CTrue.FsConnect/FsSimVar.cs
+++ b/src/CTrue.FsConnect/FsSimVar.cs
@@ -298,7 +298,13 @@ public enum FsSimVar
AutopilotMaster,
AutopilotWingLeveler,
AutopilotNav1Lock,
+ ///
+ /// Heading mode active
+ ///
AutopilotHeadingLock,
+ ///
+ /// Selected heading
+ ///
AutopilotHeadingLockDir,
AutopilotAltitudeLock,
AutopilotAltitudeLockVar,
diff --git a/src/CTrue.FsConnect/IFsConnect.cs b/src/CTrue.FsConnect/IFsConnect.cs
index 13a0e0b..854964b 100644
--- a/src/CTrue.FsConnect/IFsConnect.cs
+++ b/src/CTrue.FsConnect/IFsConnect.cs
@@ -236,7 +236,7 @@ public interface IFsConnect : IDisposable
/// The definition id to associated with the data definition.
/// Radius in meters. Should be less that 2000000 (200km).
///
- void RequestData(Enum requestId, int defineId, uint radius = 0, FsConnectSimobjectType type = FsConnectSimobjectType.User);
+ void RequestData(int requestId, int defineId, uint radius = 0, FsConnectSimobjectType type = FsConnectSimobjectType.User);
///
/// Updates a sim object in the flight simulator.
@@ -276,6 +276,14 @@ public interface IFsConnect : IDisposable
///
void TransmitClientEvent(Enum eventId, uint dwData, Enum groupId);
+ ///
+ /// Sends a client event to flight simulator.
+ ///
+ ///
+ ///
+ ///
+ void TransmitClientEvent(int eventId, uint dwData, int groupId);
+
///
/// Maps a client event to a sim event.
///
diff --git a/src/CTrue.FsConnect/SimVarReflector.cs b/src/CTrue.FsConnect/SimVarReflector.cs
index 8ace400..651f0da 100644
--- a/src/CTrue.FsConnect/SimVarReflector.cs
+++ b/src/CTrue.FsConnect/SimVarReflector.cs
@@ -110,6 +110,7 @@ private string GetUnit(FieldInfo fieldInfo, SimVarAttribute attr)
private SIMCONNECT_DATATYPE GetDataType(FieldInfo field, SimVarAttribute attr)
{
+ // Always return the specified data type if provided
if (attr != null && attr.DataType != SIMCONNECT_DATATYPE.INVALID)
{
return attr.DataType;
@@ -148,6 +149,12 @@ private SIMCONNECT_DATATYPE GetDataType(FieldInfo field, SimVarAttribute attr)
if (field.FieldType == typeof(bool))
return SIMCONNECT_DATATYPE.INT32;
+ if (field.FieldType == typeof(uint) || field.FieldType == typeof(int))
+ return SIMCONNECT_DATATYPE.INT32;
+
+ if (field.FieldType == typeof(ulong) || field.FieldType == typeof(long))
+ return SIMCONNECT_DATATYPE.INT64;
+
// Default data type
return SIMCONNECT_DATATYPE.FLOAT64;
}