Windows 10 - programming Cortana
Asked Answered
R

4

7

I am trying to programm a litte application for Cortana.

My idea is, that i say: (I enabled the "Hey Cortana" feature)

Hey Cortana, Convert 45 degrees to farenheit

and I get (in the moment) a log in my Output window (Visual Studio). I tried to say exact this sentence and Cortana understood me perfectly, but Cortana opened the browser and entered it into Bing.

Why? What did I do wrong? I don't get any Syntax Error.

This is my Code:

// commands.xml

<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
  <CommandSet xml:lang="en-us" Name="MyCommands_en-us">
    <CommandPrefix> Convert, </CommandPrefix>
    <Example> Convert 45 degrees to farenheit </Example>

    <Command Name ="farenheitToDegrees">
      <Example> 73 farenheit to degrees</Example>
      <ListenFor> {farenheit} farenheit to degrees </ListenFor>
      <Feedback> {farenheit} are ... in degrees </Feedback>
      <Navigate/>
    </Command>

    <Command Name="degreesToFarenheit">
      <Example> 45 degrees to farenheit </Example>
      <ListenFor> {degrees} degrees to farenheit </ListenFor>
      <Feedback> {degrees} degrees are ... in fareneheit </Feedback>
      <Navigate/>
    </Command>

    <PhraseTopic Label="degrees" Scenario="Dictation">
      <Subject>Temperature</Subject>
    </PhraseTopic>

    <PhraseTopic Label="farenheit" Scenario="Dictation">
      <Subject>Temperature</Subject>
    </PhraseTopic>
  </CommandSet>
</VoiceCommands>

// App.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using Windows.ApplicationModel.VoiceCommands;
using Windows.Storage;
using Windows.Media.SpeechRecognition;

namespace HelloWorld
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default  Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
            Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
            Microsoft.ApplicationInsights.WindowsCollectors.Session);
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected async override void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();


            var storageFile =
              await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///commands.xml"));
            await
                Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(storageFile);
        }

        protected override void OnActivated(IActivatedEventArgs e)
        {
            // Was the app activated by a voice command?
            if (e.Kind != Windows.ApplicationModel.Activation.ActivationKind.VoiceCommand)
            {
                return;
            }

            var commandArgs = e as Windows.ApplicationModel.Activation.VoiceCommandActivatedEventArgs;

        SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;

        // Get the name of the voice command and the text spoken
        string voiceCommandName = speechRecognitionResult.RulePath[0];
        string textSpoken = speechRecognitionResult.Text;

        switch (voiceCommandName)
        {
            case "farenheitToDegrees":
                string farenheit = speechRecognitionResult.SemanticInterpretation.Properties["farenheit"][0];
                System.Diagnostics.Debug.WriteLine((Convert.ToInt32(farenheit) - 32) / 1.8);
                break;

            case "degreesToFarenheit":
                string degrees = speechRecognitionResult.SemanticInterpretation.Properties["degrees"][0];
                System.Diagnostics.Debug.WriteLine(Convert.ToInt32(degrees) * 1.8 + 32);
                break;

            default:
                System.Diagnostics.Debug.WriteLine("None of my bussiness");
                break;
        }
    }


    /// <summary>
    /// Invoked when Navigation to a certain page fails
    /// </summary>
    /// <param name="sender">The Frame which failed navigation</param>
    /// <param name="e">Details about the navigation failure</param>
    void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
    }

    /// <summary>
    /// Invoked when application execution is being suspended.  Application state is saved
    /// without knowing whether the application will be terminated or resumed with the contents
    /// of memory still intact.
    /// </summary>
    /// <param name="sender">The source of the suspend request.</param>
    /// <param name="e">Details about the suspend request.</param>
    private void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        //TODO: Save application state and stop any background activity
        deferral.Complete();
    }
}

}

can somebody help me?

Reflection answered 15/8, 2015 at 11:3 Comment(3)
For the command prefix have a , after convert is this on purpose? I'm not sure Cortana will recognise the , when it is spoken…Hoover
Also I think you are using the wrong version of the voice command definition file. Try the following schemas.microsoft.com/voicecommands/1.2Hoover
@Hoover the link is outdatedJustifiable
D
2

The VCD definition file you've listed above doesn't have either a PhraseTopic or PhraseList to define the parts you've got in curly braces:

 <ListenFor> {farenheit} farenheit to degrees </ListenFor>

I'm guessing you probably wanted a PhraseTopic because that allows for an unconstrained dictation suitable for a wide range of numbers, something like this:

<PhraseTopic Label="farenheit" Scenario="Dictation">
   <Subject>Temperature</Subject>
</PhraseTopic>

See the spec for VCD's here on msdn, you might want to play with tweaking the Scenario value. This does mean you'll need to handle the text you get as the farenheit term yourself, of course, but typically dictated text for numbers comes through in textual '1234' form (but not in 100% of cases).

Darrin answered 15/8, 2015 at 14:29 Comment(9)
Seems to be just a part of the problem. Cortana still does nothing. Maybe I am doing something wrong? To install the features to Cortana I just have to Press the "Local Maschine" button right?Reflection
Paul, can you update your question with an updated VCD file? I can drop it into a project here and poke at it.Darrin
Hm, so I'm able to get this to work in my test environment here without any modifications. If you open Cortana, type 'help' into the search box, and use the "Get Help" option that should appear at the top, does your app show at the bottom of the list of things that Cortana can do (you'll probably need to scroll it down)Darrin
no, my app does not display under "help". But i can find it under the installed applications. What did i wrong?Reflection
@PaulScharnofske okay, if it's not showing up under help, then the VCD isn't getting installed for some reason, odd. Is your system set for US English? Or are you in another region?Darrin
Including your location? Did you install an en-US version of windows, but set your location to Germany? It's possible Cortana is looking for en-DE (which we don't support to my knowledge), and not falling back to en-US. Is there a particular reason you haven't tried building a de-DE VCD set?Darrin
No. everything englisch. I am pretty sure. The only thing which is german are my keybindings.Reflection
Okay, and when you used cortana for the first time, it walked you through the whole "What should I call you?" process? I'm not sure what "Local machine" button you're referring to above, BTW. Can you give me a quick rundown of how you set up your system specifically?Darrin
Also, are you 100% sure that your call to InstallCommandDefinitionsFromStorageFileAsync is actually completing? When you first started this question, your VCD file should have been causing that to throw an exception. I'm wondering if it's just never returning instead.Darrin
E
0

check the properties of your VCD file, values shoud be: Buil Action = Content, Copy to Output Directory = Copy always. Anyway, I hope that you registered the vcd file:

VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri("ms-appx:///VCD.xml"));

Check this MVA video about Cortana: https://www.microsoftvirtualacademy.com/en-US/training-courses/universal-windows-app-development-with-cortana-and-the-speech-sdk-8487

Epaminondas answered 17/8, 2015 at 6:4 Comment(7)
I'm using it in Windows Phone 8.1 Silverlight app. using Windows.Phone.Speech.VoiceCommands;Gizela
Another source from microsoft: msdn.microsoft.com/en-us/library/windows/apps/…Gizela
OH! I tried to write this code for Windows 10 (PC) not for the phone. What do i have to change?Reflection
Sory, you are right, here is the namespace for Windows 10: msdn.microsoft.com/en-us/library/windows/apps/xaml/…Gizela
This is it: msdn.microsoft.com/en-us/library/windows/apps/xaml/…Gizela
so that means, this: var storageFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///commands.xml")); await Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(storageFile); should work?Reflection
Let me know if it work. I think If you have done all related steps, then it should work.Gizela
B
0

Well... Seems that you have understood all the steps but still something is missing...

Here's an example that I have made regarding Cortana's foreground functionality:

Here's the VCD...

    <?xml version="1.0" encoding="utf-8" ?>
    <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
      <CommandSet xml:lang="en-us" Name="HomeControlCommandSet_en-us">
        <CommandPrefix>HomeControl</CommandPrefix>
        <Example>Control alarm, temperature, light and others</Example>

        <Command Name="Activate_Alarm">
          <Example>Activate alarm</Example>
          <ListenFor>[Would] [you] [please] activate [the] alarm [please]</ListenFor>
          <ListenFor RequireAppName="BeforeOrAfterPhrase">Activate alarm</ListenFor>
          <ListenFor RequireAppName="ExplicitlySpecified">Activate {builtin:AppName} alarm</ListenFor>
          <Feedback>Activating alarm</Feedback>
          <Navigate />
        </Command>

After create this definitions, you need to registry it at App Startup:

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    {
        ...
        // Install the VCD
        try
        {
            StorageFile vcdStorageFile = await Package.Current.InstalledLocation.GetFileAsync(@"HomeControlCommands.xml");
            await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdStorageFile);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("There was an error registering the Voice Command Definitions", ex);
        }
    }

An then override App.OnActivated method to handle when the events are triggered:

    protected override void OnActivated(IActivatedEventArgs e)
    {
        // Handle when app is launched by Cortana
        if (e.Kind == ActivationKind.VoiceCommand)
        {
            VoiceCommandActivatedEventArgs commandArgs = e as VoiceCommandActivatedEventArgs;
            SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;

            string voiceCommandName = speechRecognitionResult.RulePath[0];
            string textSpoken = speechRecognitionResult.Text;
            IReadOnlyList<string> recognizedVoiceCommandPhrases;

            System.Diagnostics.Debug.WriteLine("voiceCommandName: " + voiceCommandName);
            System.Diagnostics.Debug.WriteLine("textSpoken: " + textSpoken);

            switch (voiceCommandName)
            {
                case "Activate_Alarm":
                    System.Diagnostics.Debug.WriteLine("Activate_Alarm command");
                    break;

To see the complete tutorial, please visit this link and a working project is here. Also, if you interested in respond to the user through Cortana window, check this post regarding Cortana in background

Blowtorch answered 18/8, 2015 at 2:29 Comment(0)
O
0

I think you are missing a part of the command.

You're asking for Cortana to convert degrees to Fahrenheit, and the program is confused because you're not being specific enough.

If you want Cortana to covert from degrees Celsius to degrees Fahrenheit, you have to tell it specifically Celsius to Fahrenheit.

Oversew answered 21/6, 2016 at 18:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.