diff --git a/README.md b/README.md index 07b2c3b..42a8585 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,25 @@ Latest build: [![Build status](https://ci.appveyor.com/api/projects/status/ejvcv * Vertical speed set * set __vertical speed__ to negative V thousand /& X hundred [fifty] [fpm / feet per minute / feet] * __eg: set vertical speed to six thousand five hundred fifty; set vertical speed to six hundred; set vertical speed fifty__ - +* Altitude set + * set __altitude__ to XX thousand XX hundred feet + * set __altitude__ to __FL XXX__ +* Vertical speed button + * __[select] / [de-select / toggle] vertical speed__ mode +* Approach button + * __[select] / [de-select / toggle] approach__ mode +* Altitude hold + * __[select] / [de-select] / toggle] altitude hold__ mode +* Localizer + * __[select] / [de-select] / toggle] localizer__ mode +* N1 + * __[select] / [de-select] / toggle] n1__ mode +* Speed + * __[select] / [de-select] / toggle] speed__ mode +* Level change + * __[select] / [de-select] / toggle] level change__ +* Heading select + * __[select / egnage / turn on / de-select / disengage / turn off / toggle] heading select__ __Cheat sheet:__ * __Bold text is Mandatory__ @@ -92,7 +110,7 @@ __Cheat sheet:__ * __T => [zero / one / two / three / four / fiver / six / seven]__ * __V => [zero / one / two / three / four / five / six]__ -## Hard time speaking - train Windows to understand you better? +## Hard time speaking - train Windows to understand you better! * Open Speech Recognition by clicking the Start button, clicking Control Panel, clicking Ease of Access, and then clicking Speech Recognition. * Click “Train your computer to better understand you.” * Follow the instructions on the screen. diff --git a/X-Plane Voice Control/Commands/AltitudeHoldControl.cs b/X-Plane Voice Control/Commands/AltitudeHoldControl.cs new file mode 100644 index 0000000..df365c1 --- /dev/null +++ b/X-Plane Voice Control/Commands/AltitudeHoldControl.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class AltitudeHoldControl : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public AltitudeHoldControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("altitude hold"); + lnavGrammar.Append("mode", 0, 1); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/alt_hld_status"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("altitude hold toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/alt_hld_status").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("altitude hold engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("altitude hold disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/alt_hld_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/alt_hld_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Commands/AltitudeMcpControl.cs b/X-Plane Voice Control/Commands/AltitudeMcpControl.cs new file mode 100644 index 0000000..65124c5 --- /dev/null +++ b/X-Plane Voice Control/Commands/AltitudeMcpControl.cs @@ -0,0 +1,109 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; + +namespace X_Plane_Voice_Control.Commands +{ + class AltitudeMcpControl : ControlTemplate + { + + public AltitudeMcpControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var mainAltitudeGrammar = new GrammarBuilder(); + + var thousandGrammar = new GrammarBuilder(); + thousandGrammar.Append(Constants.AltitudeNumberChoices); + thousandGrammar.Append("thousand"); + + var hundredGrammar = new GrammarBuilder(); + hundredGrammar.Append(Constants.ClassicNumberChoices); + hundredGrammar.Append("hundred"); + + var flGrammar = new GrammarBuilder(); + flGrammar.Append("flight level"); + flGrammar.Append(Constants.ClassicNumberChoices, 1, 3); + + + + var altitudeGrammar = new GrammarBuilder(); + altitudeGrammar.Append(thousandGrammar, 0, 1); + altitudeGrammar.Append(hundredGrammar, 0, 1); + altitudeGrammar.Append("feet", 0, 1); + mainAltitudeGrammar.Append("please", 0, 1); + mainAltitudeGrammar.Append("set", 0, 1); + mainAltitudeGrammar.Append("altitude"); + mainAltitudeGrammar.Append("to", 0, 1); + mainAltitudeGrammar.Append(new Choices(altitudeGrammar, flGrammar)); + mainAltitudeGrammar.Append("please", 0, 1); + Grammar = new Grammar(mainAltitudeGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(mainAltitudeGrammar.DebugShowPhrases); + } + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("sim/cockpit/autopilot/altitude"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + var currentAltitude = (int)XPlaneInterface.GetDataRef("sim/cockpit/autopilot/altitude").Value; + var altitudeToSet = 0; + if (phrase.Contains("flight level")) + { + var flString = phrase.Split(new[] + { + "flight level " + }, StringSplitOptions.RemoveEmptyEntries)[1]; + + altitudeToSet = int.Parse(Constants.StringNumbersToDigits(flString).Replace(" ", "")) * 100; + } + var strinAltitude = Constants.StringNumbersToDigits(phrase); + try + { + var startingIndexNumber = Constants.NumbersInDigits40.First(strinAltitude.Contains); + var startingIndex = strinAltitude.IndexOf(startingIndexNumber, StringComparison.Ordinal); + strinAltitude = strinAltitude.Substring(startingIndex, strinAltitude.Length - startingIndex); + } + catch + { + // ignored + } + + var splittedString = strinAltitude.Split(' '); + for (var i = 0; i < splittedString.Length; i += 2) + { + var nextIndex = i + 1; + if (nextIndex > splittedString.Length - 1) + break; + if (splittedString[i + 1] == "thousand") + { + altitudeToSet += int.Parse(splittedString[i]) * 1000; + } + if (splittedString[i + 1] == "hundred") + { + altitudeToSet += int.Parse(splittedString[i]) * 100; + } + } + + var buttonCommand = currentAltitude > altitudeToSet ? "laminar/B738/autopilot/altitude_dn" : "laminar/B738/autopilot/altitude_up"; + var rotation = currentAltitude > altitudeToSet ? -100 : 100; + Task.Run(() => + { + while (currentAltitude != altitudeToSet) + { + currentAltitude += rotation; + XPlaneInterface.SetExecutingCommand(buttonCommand); + Thread.Sleep(20); + } + }); + SpeechSynthesizer.SpeakAsync($"Setting altitude to {altitudeToSet} feet"); + } + + } +} diff --git a/X-Plane Voice Control/Commands/ApproachControl.cs b/X-Plane Voice Control/Commands/ApproachControl.cs new file mode 100644 index 0000000..03c32de --- /dev/null +++ b/X-Plane Voice Control/Commands/ApproachControl.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class ApproachControl : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public ApproachControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("approach"); + lnavGrammar.Append("mode", 0, 1); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/app_status"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("approach toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/app_status").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("approach engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("approach disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/app_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/app_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Commands/LocalizerControl.cs b/X-Plane Voice Control/Commands/LocalizerControl.cs new file mode 100644 index 0000000..c3dcb82 --- /dev/null +++ b/X-Plane Voice Control/Commands/LocalizerControl.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class LocalizerControl : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public LocalizerControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("localizer"); + lnavGrammar.Append("mode", 0, 1); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/vorloc_status"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("localizer toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/vorloc_status").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("localizer engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("localizer disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/vorloc_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/vorloc_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Commands/LvlChange.cs b/X-Plane Voice Control/Commands/LvlChange.cs new file mode 100644 index 0000000..f9db5a7 --- /dev/null +++ b/X-Plane Voice Control/Commands/LvlChange.cs @@ -0,0 +1,70 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class LvlChange : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public LvlChange(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("level change"); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/lvl_chg_status"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("level change toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/lvl_chg_status").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("level change engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("level change disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/lvl_chg_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/lvl_chg_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Commands/N1Control.cs b/X-Plane Voice Control/Commands/N1Control.cs new file mode 100644 index 0000000..42aff7e --- /dev/null +++ b/X-Plane Voice Control/Commands/N1Control.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class N1Control : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public N1Control(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("n-1"); + lnavGrammar.Append("mode", 0, 1); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/n1_status"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("n1 toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/n1_status").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("n1 engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("n1 disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/n1_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/n1_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Commands/SpeedControl.cs b/X-Plane Voice Control/Commands/SpeedControl.cs new file mode 100644 index 0000000..50333ee --- /dev/null +++ b/X-Plane Voice Control/Commands/SpeedControl.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class SpeedControl : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public SpeedControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("speed"); + lnavGrammar.Append("mode", 0, 1); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/speed_status1"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("speed mode toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/speed_status1").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("speed mode engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("speed mode disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/speed_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/speed_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Commands/VerticalSpeedMCPControl.cs b/X-Plane Voice Control/Commands/VerticalSpeedMCPControl.cs index 02f8585..32b1289 100644 --- a/X-Plane Voice Control/Commands/VerticalSpeedMCPControl.cs +++ b/X-Plane Voice Control/Commands/VerticalSpeedMCPControl.cs @@ -2,16 +2,14 @@ using System.Linq; using System.Speech.Recognition; using System.Speech.Synthesis; -using System.Threading; -using System.Threading.Tasks; using ExtPlaneNet; namespace X_Plane_Voice_Control.Commands { - class VerticalSpeedMCPControl : ControlTemplate + class VerticalSpeedMcpControl : ControlTemplate { - public VerticalSpeedMCPControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + public VerticalSpeedMcpControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) { var headingGrammar = new GrammarBuilder(); @@ -55,7 +53,10 @@ public override void OnTrigger(RecognitionResult rResult, string phrase) var startingIndex = stringHeading.IndexOf(startingIndexNumber, StringComparison.Ordinal); stringHeading = stringHeading.Substring(startingIndex, stringHeading.Length - startingIndex); } - catch { } + catch + { + // ignored + } var splittedString = stringHeading.Split(' '); float verticalSpeedToSet = 0; diff --git a/X-Plane Voice Control/Commands/VertticalSpeedControl.cs b/X-Plane Voice Control/Commands/VertticalSpeedControl.cs new file mode 100644 index 0000000..c53467c --- /dev/null +++ b/X-Plane Voice Control/Commands/VertticalSpeedControl.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Speech.Recognition; +using System.Speech.Synthesis; +using System.Threading; +using System.Threading.Tasks; +using ExtPlaneNet; +using ExtPlaneNet.Commands; + +namespace X_Plane_Voice_Control.Commands +{ + class VertticalSpeedControl : ControlTemplate + { + private readonly string[] _lnavOnStrings = { "select" }; + private readonly string[] _lnavOffStrings = { "de-select" }; + public VertticalSpeedControl(ExtPlaneInterface interface_, SpeechSynthesizer synthesizer) : base(interface_, synthesizer) + { + var lnavGrammar = new GrammarBuilder(); + var lnavGrammarOn = new GrammarBuilder(); + lnavGrammarOn.Append(new Choices(_lnavOnStrings)); + var lnavGrammarOff = new GrammarBuilder(); + lnavGrammarOff.Append(new Choices(_lnavOffStrings)); + lnavGrammar.Append(new Choices(lnavGrammarOn, lnavGrammarOff, "toggle")); + lnavGrammar.Append("vertical speed"); + lnavGrammar.Append("mode", 0, 1); + Grammar = new Grammar(lnavGrammar); + RecognitionPattern = Constants.DeserializeRecognitionPattern(lnavGrammar.DebugShowPhrases); + } + + public sealed override Grammar Grammar { get; } + public override string RecognitionPattern { get; } + + public override void DataRefSubscribe() + { + XPlaneInterface.Subscribe("laminar/B738/autopilot/vs_status"); + } + + public override void OnTrigger(RecognitionResult rResult, string phrase) + { + if (phrase.Contains("toggle")) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("vertical speed toggled"); + return; + } + + var turnOn = !_lnavOffStrings.Any(phrase.Contains); + var lnavStatus = (int)XPlaneInterface.GetDataRef("laminar/B738/autopilot/vs_status").Value; + if (turnOn && lnavStatus == 0) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("vertical speed engaged"); + } + else if (!turnOn && lnavStatus == 1) + { + PressButton(); + SpeechSynthesizer.SpeakAsync("vertical speed disengaged"); + } + } + + private void PressButton() + { + Task.Run(() => + { + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/vs_press", Command.CommandType.Begin); + Thread.Sleep(Constants.PushButtonReleaseDelay); + XPlaneInterface.SetExecutingCommand("laminar/B738/autopilot/vs_press", Command.CommandType.End); + }); + } + } +} diff --git a/X-Plane Voice Control/Constants.cs b/X-Plane Voice Control/Constants.cs index 977ed65..e851a0d 100644 --- a/X-Plane Voice Control/Constants.cs +++ b/X-Plane Voice Control/Constants.cs @@ -14,6 +14,12 @@ internal static class Constants public static readonly string[] NumbersInDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + public static readonly string[] NumbersInDigits40 = + { + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", + "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42" + }; + public static readonly Choices NumberChoices = new Choices(Numbers); public static readonly Choices ClassicNumberChoices = new Choices(ClassicNumbers); @@ -22,6 +28,8 @@ internal static class Constants public static readonly Choices VerticalSpeedNumberChoices = new Choices(VerticalSpeedNumbers); + public static readonly Choices AltitudeNumberChoices = new Choices(NumbersInDigits40); + public const int ButtonReleaseDelay = 700; public const int PushButtonReleaseDelay = 300; diff --git a/X-Plane Voice Control/Properties/AssemblyInfo.cs b/X-Plane Voice Control/Properties/AssemblyInfo.cs index 4582b41..9218c6d 100644 --- a/X-Plane Voice Control/Properties/AssemblyInfo.cs +++ b/X-Plane Voice Control/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.8.0.0")] -[assembly: AssemblyFileVersion("0.8.0.0")] +[assembly: AssemblyVersion("0.9.0.0")] +[assembly: AssemblyFileVersion("0.9.0.0")] diff --git a/X-Plane Voice Control/X-Plane Voice Control.csproj b/X-Plane Voice Control/X-Plane Voice Control.csproj index 421a995..32dddef 100644 --- a/X-Plane Voice Control/X-Plane Voice Control.csproj +++ b/X-Plane Voice Control/X-Plane Voice Control.csproj @@ -52,8 +52,16 @@ + + + + + + + +