Author Topic: Command queue possible?  (Read 281 times)

Sircheeze89

  • Newbie
  • *
  • Posts: 4
Command queue possible?
« on: July 05, 2018, 05:46:42 am »
I've been working on a profile I use at work. I'm an automotive technician. I am required to do an inspection on any vehicle I perform repairs on, and found it annoying to be checking all the boxes and walking from the car to my computer constantly. Now I just say a command (like "inspection front brakes") and VA will reply to me that it is adding brakes to the inspection and click all the boxes. Way quicker, way easier. It does take around 15 to 20 seconds for it to do this action. I would like to find a way to "queue" my commands so that I can just ramble off what the vehicle needs and for it to detect and wait on previous commands to run. I've tried a few ideas, but they are never consistent in working properly. I've made each command add 1 to the "RUNNING COMMANDS" INT token when it starts and subtract 1 when it stops. I used loop commands to "lock" each command in  a spot of this start command, but can't figure out how to cycle them without stuff jumping incorrectly and breaking. Any simple way to make a command queue for this?

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1544
  • RTFM
Re: Command queue possible?
« Reply #1 on: July 05, 2018, 05:35:15 pm »
I believe I have a working solution for you:

Command 1
Code: [Select]
\/\/\/ Cue Manager Header \/\/\/
// If the command is requested by the user(instead of the cue manager)
Begin Text Compare : [{CMDACTION}] Equals 'Spoken'
    // Check both the variable that indicates a command is running, and the cue in case a command has just finished, to try and prevent a race condition
    Begin Condition : [commandRunning] Equals True OR [commandQue] Does Not Equal ''
        // Make sure commandQue exists, to prevent "Not Set" being the first entry in the cue
        Begin Text Compare : [commandCue] Has Not Been Set
            Set Text [commandCue] to ''
        End Condition
        Begin Text Compare : [commandCue] Does Not Equal ''
            // Add the requested command to the end of the cue
            Set Text [commandCue] to '{TXT:commandCue}{CMD};'
        Else
            // Add the requested command to the start of the que
            Set Text [commandCue] to '{TXT:commandCue}{CMD};'
            // If the command cue was empty, start the cue manager so it can run the next command(s) once the currently executing command finishes
            Execute command, 'Cue Manager' (by name)
        End Condition
        Write [Purple] 'Cue Manager: "{CMD}" added to que' to log
    End Condition - Exit when condition met
End Condition
Set Boolean [commandRunning] to True
/\/\/\ End of Cue Manager Header /\/\/\

Write [Pink] 'Doing things in {CMD}...' to log
Pause 5 seconds
Write [Black] 'Done doing things in {CMD}.' to log

\/\/\/ Cue Manager Footer \/\/\/
Set Boolean [commandRunning] to False
/\/\/\ End of Cue Manager Footer /\/\/\

Cue Manager  (voice disabled)
Code: [Select]
// If a command is running, wait for it to finished before starting the next one. This needs to happen here when the command that starts the manager is still running
Start Loop While : [commandRunning] Equals True
End Loop
// Keep running until all commands in the cue have been executed and the que is empty
Start Loop While : [commandCue] Does Not Equal ''
    // Get the next command from the beginning of the cue
    Set Text [~~nextCommand] to '{TXTSUBSTR:commandCue:0:{TXTPOS:";":commandCue:0}}'
    Write [Blue] 'Cue Manager: Starting command "{TXT:~~nextCommand}"' to log
    Execute command, '{TXT:~~nextCommand}' (by name)
    // Remove the executed command from the cue
    Set Text [commandCue] to '{TXTSUBSTR:commandCue:{EXP: {TXTPOS:";":commandCue:0} + 1}:}'
    // Wait to make sure the command has started and has set commandRunning to true. Depending on your system this may need to be longer or shorter
    Pause 0,1 seconds
    // If a command is running, wait for it to finished before starting the next one
    Start Loop While : [commandRunning] Equals True
    End Loop
End Loop
// Pause so the end message doesn't appear before the command actually finishes(race condition)
Pause 0,1 seconds
Write [Blue] 'All cued commands executed' to log


This allows you to speak any command wrapped in the header and the footer, and the cue manager will execute them in the sequence you've spoken them in.

The commands are attached as a .vap to this post, so you can import them.



Notes:

In the header, you'll noticed the section
Code: [Select]
        Begin Text Compare : [commandCue] Does Not Equal ''
            // Add the requested command to the end of the cue
            Set Text [commandCue] to '{TXT:commandCue}{CMD};'
        Else
            // Add the requested command to the start of the que
            Set Text [commandCue] to '{TXT:commandCue}{CMD};'
            // If the command cue was empty, start the cue manager so it can run the next command(s) once the currently executing command finishes
            Execute command, 'Cue Manager' (by name)
        End Condition

It's set up this way because determining if the cue is empty(which decides if the cue manager should be started) must happen before adding something to the cue(otherwise the cue manager will never start, as the cue would contain what was just added to it).
This necessitates repeating the "Set a Text Value" action, as it must still run in either case.



The use of "commandRunning" combined with waiting loops seems a little clumsy, but because the first command is not started by the que manager command, the "Wait until this command completes before continuing" option of the "Execute Another Command" action can't be used, so it's necessary.

I chose this option because this allows you to add the header and footer to any command to make it a que-able command, while still allowing non-quing commands to run simultaneously(E.G. media player control by multimedia keys, which shouldn't interfere with your checklist system).

Sircheeze89

  • Newbie
  • *
  • Posts: 4
Re: Command queue possible?
« Reply #2 on: July 06, 2018, 06:33:32 am »
Awesome!

I added it to my commands but I have an issue, which hopefully is a quick fix. I have a command at the start and end of each voice command so I can edit the start and end of each command easily. I put the header in the start command and the footer in the end command. The issue is the {CMD} token doesn't like this I guess, so its breaking it. Neither does the {CMDACTION} command. I also have my computer read things back to me after I say a command, but had it set to say something else if the command is added to the que. 

I would say a command, and it would say "adding (what is said) to que", then when it actually did that action, it would say what is in the command when it started that command.

I have over 130 voice commands, so adding the header to each command would take a bit of time, but if that's what needs to happen I can do it. Same with footer.

Thank you so much for your help. I appreciate it very much!

Exergist

  • Sr. Member
  • ****
  • Posts: 330
  • Can you dig it?
Re: Command queue possible?
« Reply #3 on: July 06, 2018, 09:14:40 am »
Very clever :)

@Pfeil - I think a native cue manager would be a nice feature request. I'm guessing command execution is quick enough that most folks won't need a cue manager, but I bet there are a fair number of use cases where this would be useful to have.

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1544
  • RTFM
Re: Command queue possible?
« Reply #4 on: July 06, 2018, 12:32:16 pm »
Awesome!

I added it to my commands but I have an issue, which hopefully is a quick fix. I have a command at the start and end of each voice command so I can edit the start and end of each command easily. I put the header in the start command and the footer in the end command. The issue is the {CMD} token doesn't like this I guess, so its breaking it. Neither does the {CMDACTION} command. I also have my computer read things back to me after I say a command, but had it set to say something else if the command is added to the que. 
You could pass the value of "{CMD}" and "{CMDACTION}" from the original command to your start command(the footer only serves to signal the end of command execution and shouldn't require modification).

Add
Code: [Select]
Set Text [~~CMD] to '{CMD}'
Set Text [~~CMDACTION] to '{CMDACTION}'
to the top of your command(before calling your start command)

Then modify the header like this:
Code: [Select]
\/\/\/ Cue Manager Header \/\/\/
// If the command is requested by the user(instead of the cue manager)
Begin Text Compare : [~~CMDACTION] Equals 'Spoken'
    // Check both the variable that indicates a command is running, and the cue in case a command has just finished, to try and prevent a race condition
    Begin Condition : [commandRunning] Equals True OR [commandQue] Does Not Equal ''
        // Make sure commandQue exists, to prevent "Not Set" being the first entry in the cue
        Begin Text Compare : [commandCue] Has Not Been Set
            Set Text [commandCue] to ''
        End Condition
        Begin Text Compare : [commandCue] Does Not Equal ''
            // Add the requested command to the end of the cue
            Set Text [commandCue] to '{TXT:commandCue}{TXT:~~CMD};'
        Else
            // Add the requested command to the start of the que
            Set Text [commandCue] to '{TXT:commandCue}{TXT:~~CMD};'
            // If the command cue was empty, start the cue manager so it can run the next command(s) once the currently executing command finishes
            Execute command, 'Cue Manager' (by name)
        End Condition
        Write [Purple] 'Cue Manager: "{TXT:~~CMD}" added to que' to log
    End Condition - Exit when condition met
End Condition
Set Boolean [commandRunning] to True
/\/\/\ End of Cue Manager Header /\/\/\


@Pfeil - I think a native cue manager would be a nice feature request. I'm guessing command execution is quick enough that most folks won't need a cue manager, but I bet there are a fair number of use cases where this would be useful to have.
Perhaps. Feel free to post the suggestion, if you wish.

Sircheeze89

  • Newbie
  • *
  • Posts: 4
Re: Command queue possible?
« Reply #5 on: July 06, 2018, 12:53:48 pm »
Great!

Thank you so much for making this. I'll have to get this implemented and start testing it. I'm no pro at this, so I really appreciate the help! :) :D ;D

Sircheeze89

  • Newbie
  • *
  • Posts: 4
Re: Command queue possible?
« Reply #6 on: July 09, 2018, 07:51:52 pm »
Just an update on using this.

I've had a few times that when adding 3 or so commands to the queue, it would run the 3rd command twice side by side. It turns out I was getting 2 instances of the "Cue Manager" command running at the same time. 

I added a check before it launches the "Cue Manager" command to make sure it wasn't running already.

If {BOOL:CueRunning} = False
Execute command "Cue Manager"
End Condition

I set {BOOL:CueRunning} to true at the start of the "Cue Manager" command and set it to false if it finishes the loop on the "Cue Manager" command.

Now, It's smooth as butter! using the test command "command [1..3]" I went through each and got the queue to around 6 or 7 commands deep. I also added to that test command a TTS sound of it reading the 1 2 or 3, just to verify that it stayed in order and ran everything. Very, very glad to have this working. Thank you so much again for your help in this! ;D

I attached the profile with those added in.

« Last Edit: July 09, 2018, 09:55:24 pm by Sircheeze89 »

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1544
  • RTFM
Re: Command queue possible?
« Reply #7 on: July 10, 2018, 02:01:44 pm »
Hmm...as long as the cue isn't empty, the manager shouldn't be started again. This shouldn't happen unless the third command runs before the second has set up the cue.

Either way, you've managed to make it run reliably, so it's no longer an issue.