Author Topic: Radio frequency in DCS with Jester AI  (Read 2719 times)

abaco

  • Newbie
  • *
  • Posts: 2
Radio frequency in DCS with Jester AI
« on: April 14, 2025, 08:28:28 PM »
Hi,

I'm trying to setup VoiceAttack to speak radio frequencies in DCS and pass them to Jester in the F-14. A quick search didn't produce the results I'm looking for, so I'm asking here before I dig deeper into the documentation.

Basically:
- User speaks a radio frequency, e.g. "Jester tune radio to one-two-six-point-five-seven-five"
- VA produces the following outcome:
   - Start with initial sequence "Shift A > A > A > Ctrl 1 > Ctrl 4"
   - Then press "Ctrl 1 > Ctrl 2 > Ctrl 6 > Ctrl 5 > Ctrl 4" (the frequency numbers)

The keys to press are generally Ctrl + #, with some additional logic if digits fall in the 8-0 range (Ctrl 8 then Ctrl 6-8) or for the last two 00,25,50,75 kHz (Ctrl 1-4), or if user skips the trailing zeros.

I was thinking of doing a simple loop over the frequency array, but understand that VA doesn't support arrays. Has this been solved before?

Thank you!



SemlerPDX

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 332
  • Upstanding Lunatic
    • My AVCS Homepage
Re: Radio frequency in DCS with Jester AI
« Reply #1 on: April 15, 2025, 12:48:24 PM »
If you need to work with arrays in order to simplify your logic and flow, you can use inline function(s) written in VB.net or C#, which of course support arrays.  You can bring in or send out any information needed from VA, such as what was said in the command phrase, etc., and cast those as needed into arrays with minimal effort.

You could also use native VoiceAttack actions, such as dynamically named variables you could iterate over in a loop, or other such fancy footwork.

In the end, such a complex logical goal will require a bit of effort and a keen attention to detail, not to mention plenty of patience and testing - but what you propose is entirely possible using native VA tools or better still, inline functions.

Here are some posts that may help you get on the right track:
Control flow (If, Else, ElseIf, Loop, Jump) basics

Variables and tokens summed up

abaco

  • Newbie
  • *
  • Posts: 2
Re: Radio frequency in DCS with Jester AI
« Reply #2 on: April 17, 2025, 12:39:47 AM »
This is what I did, if someone finds it useful.

May not be the most elegant solution but it works pretty well.



Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #3 on: April 17, 2025, 01:53:07 AM »
Thanks for sharing your profile, I thought I would use this instead of opening a whole new topic but I am trying to play a sound file if frequency entrance is successful, and another if it failed. I want to do this in inline script since it gives the best result. The trouble is, so far I have been unable to do this. Here is the full script I am using

Code: [Select]
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Media;

public class VAInline
{
    public void main()
    {
        try
        {
            string inputRaw = VA.GetText("DestinationAirport")?.Trim().ToLower();

            if (string.IsNullOrEmpty(inputRaw))
            {
                VA.WriteToLog("No airport name or ID provided.", "red");
                return;
            }

            var airportFrequencies = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                { "a44", "121000" }, { "anapa", "121000" },
                { "a76", "131000" }, { "batumi", "131000" },
                { "b52", "136500" }, { "beslan", "136500" },
                { "f66", "125000" }, { "gelendzhik", "125000" },
                { "f95", "129000" }, { "gudauta", "129000" },
                { "g99", "133000" }, { "kobuleti", "133000" },
                { "k50", "127000" }, { "krasnodar center", "127000" },
                { "k80", "118500" }, { "krasnodar pashkovsky", "118500" },
                { "k71", "131500" }, { "krymsk", "131500" },
                { "k95", "134000" }, { "kutaisi", "134000" },
                { "k73", "126000" }, { "maykop", "126000" },
                { "l72", "130000" }, { "mineralnye vody", "130000" },
                { "m79", "127500" }, { "mozdok", "127500" },
                { "n11", "122500" }, { "nalchik", "122500" },
                { "q79", "130500" }, { "novorossiysk", "130500" },
                { "r10", "132000" }, { "senaki", "132000" },
                { "s96", "130000" }, { "soganlug", "130000" },
                { "s03", "121500" }, { "sochi", "121500" },
                { "ta1", "128000" }, { "sukhumi", "128000" },
                { "t71", "132000" }, { "tbilisi", "132000" },
            };

            if (!airportFrequencies.TryGetValue(inputRaw, out string frequency))
            {
                VA.WriteToLog("Unknown airport or ID: " + inputRaw, "red");
                return;
            }

            frequency = frequency.Replace(".", "").PadRight(6, '0');

            using (UdpClient client = new UdpClient())
            {
                client.Connect("127.0.0.1", 7778);

                SendCOMM1Selector(client);
                Thread.Sleep(500);
                SendUDPCommand(client, "UFC_CLR", 300);

                foreach (char digit in frequency)
                {
                    SendUDPCommand(client, $"UFC_{digit}", 150);
                }

                SendUDPCommand(client, "UFC_ENT", 500);
            }

            VA.WriteToLog($"Switched to {inputRaw.ToUpper()} → {frequency}", "green");

            // Play confirmation sound
            try
            {
                string soundPath = @"C:\DCS\VoiceSounds\success.wav";
                if (System.IO.File.Exists(soundPath))
                {
                    SoundPlayer player = new SoundPlayer(soundPath);
                    player.Play();
                }
                else
                {
                    VA.WriteToLog("Sound file not found: " + soundPath, "orange");
                }
            }
            catch (Exception se)
            {
                VA.WriteToLog("Sound error: " + se.Message, "orange");
            }
        }
        catch (Exception e)
        {
            VA.WriteToLog("Error: " + e.Message, "red");
        }
    }

    private void SendCOMM1Selector(UdpClient client)
    {
        client.Send(Encoding.ASCII.GetBytes("UFC_COMM1_PULL INC\n"), "UFC_COMM1_PULL INC\n".Length);
        Thread.Sleep(300);
        client.Send(Encoding.ASCII.GetBytes("UFC_COMM1_PULL DEC\n"), "UFC_COMM1_PULL DEC\n".Length);
        Thread.Sleep(300);
    }

    private void SendUDPCommand(UdpClient client, string command, int delayMs)
    {
        client.Send(Encoding.ASCII.GetBytes($"{command} INC\n"), $"{command} INC\n".Length);
        Thread.Sleep(75);
        client.Send(Encoding.ASCII.GetBytes($"{command} DEC\n"), $"{command} DEC\n".Length);
        Thread.Sleep(delayMs);
    }
}



and these are the errors I am getting


Code: [Select]
78: CS1069: The type name 'SoundPlayer' could not be found in the namespace 'System.Media'. This type has been forwarded to assembly 'System.Windows.Extensions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly.
Code: [Select]
78: CS1069: The type name 'SoundPlayer' could not be found in the namespace 'System.Media'. This type has been forwarded to assembly 'System.Windows.Extensions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly.


Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4881
  • RTFM
Re: Radio frequency in DCS with Jester AI
« Reply #4 on: April 17, 2025, 04:43:44 AM »
As the compiler states: you need to add a reference to System.Windows.Extensions

Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #5 on: April 18, 2025, 01:17:35 AM »
Thanks for the response, one error that I come across very often is
Code: [Select]
5: CS0103: The name 'main' does not exist in the current context, so far I have not been able to solve this.

simple test script like this would result the error

Code: [Select]
public class VAInline
{
    public void Main() // ← Must be "Main" (capital M)
    {
        VA.WriteToLog("Test succeeded!", "Green");
    }
}




Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4881
  • RTFM
Re: Radio frequency in DCS with Jester AI
« Reply #6 on: April 18, 2025, 04:43:51 AM »
C# is case-sensitive, I.E. "Main" or "mAin" or "MAIN" are not the same thing as "main"

This is a basic property of the programming language, not specific to VoiceAttack.


I will note that inline functions are intended for users that are already familiar with .NET, and C#/VB.NET

Learning how to program in this framework/these languages is commendable, but beyond the scope of VoiceAttack support.

Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #7 on: April 28, 2025, 05:48:27 AM »
I have another question. How do you send key inputs to the game using inline C#
I am using this simple script to test if input "A" will be received but so far no luck. here is the code

Code: [Select]
using System;
using System.Threading;

public class VAInline
{
    public void main()
    {
        try
        {
           
            VA.Command.Execute("Window.Activate: DCS");
            Thread.Sleep(1000); // Wait 1 second for focus

            // 2) Send the 'A' key
            VA.Command.Execute("Keys.Press: A");
            VA.WriteToLog("Sent: A", "green");
        }
        catch (Exception ex)
        {
            VA.WriteToLog($"Error: {ex.Message}", "red");
        }
    }
}

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4881
  • RTFM
Re: Radio frequency in DCS with Jester AI
« Reply #8 on: April 28, 2025, 06:21:51 AM »
What does the command with the phrase "Keys.Press: A" look like? Does said command work if you trigger using a method other than an inline function?

Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #9 on: April 28, 2025, 01:38:14 PM »
It is saying
Code: [Select]
2:36:39.633 UNABLE TO EXECUTE EXTERNALLY INITIALIZED COMMAND. COMMAND NOT AVAILABLE (Keys.Press: A)


It is supposed to be bring up the Jester Menu and yes I can do it in other methods but for my project which is to tune manual frequency entering of jester radio, this would be the best approach

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4881
  • RTFM
Re: Radio frequency in DCS with Jester AI
« Reply #10 on: April 28, 2025, 01:39:55 PM »
...and does one of the loaded profiles contain a command corresponding to the phrase "Keys.Press: A"?

Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #11 on: April 28, 2025, 01:41:23 PM »
Yeah Jester Menu is by default A and I made sure

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4881
  • RTFM
Re: Radio frequency in DCS with Jester AI
« Reply #12 on: April 28, 2025, 01:48:03 PM »
That does not answer the question.


I'll put it another way: what is "Keys.Press: A" referring to? Did you literally just make it up and expect it to do something?

Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #13 on: April 28, 2025, 02:06:42 PM »
I thought that was a command in VA, no?

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4881
  • RTFM
Re: Radio frequency in DCS with Jester AI
« Reply #14 on: April 28, 2025, 02:12:11 PM »
Do you see a command with that phrase in either the active profile, or an included or global profile?

If not, there is no such command. VoiceAttack has no "built-in" commands. They all exist in profiles.

Killerwhale

  • Newbie
  • *
  • Posts: 10
Re: Radio frequency in DCS with Jester AI
« Reply #15 on: May 03, 2025, 02:57:00 AM »
I am not sure if Voice Attack is sometimes broken but here is my problem, my command scan [1..500] doesn't seem to work every number in between 1-500

For example, it won't work on numbers 1 -10 reliably
Here is a screen shot of what I am saying.
For this particular problem I am using {CMD} token but would like to use {CMDSEGMENT} instead but not quite sure how to do. if you can help me with this would be great, thanks.