Have ideas to improve npm?Join in the discussion! »

    @litexa/gadgets

    0.7.2 • Public • Published

    Litexa Input Handler Support

    This module adds support for both the Game Engine Interface, and Gadget Controller Interface, which make up the Alexa Gadgets Skill API. See Alexa Gadgets for more information.

    The module @litexa/gadgets supports easily sending and validating Input Handler and GadgetController.SetLight directives, and handling GameEngine.InputHandlerEvents. It adds new syntax for Input Handlers. Please find the information on how to install and use this module below.

    NOTE: When installed, the @litexa/gadgets will validate any Input Handler and GadgetController.SetLight directives added to a response, even if the directive wasn't built using the module's new statements.

    Installation

    The module can be installed globally, which makes it available to any of your Litexa projects:

    npm install -g @litexa/gadgets

    If you alternatively prefer installing the extension locally inside your Litexa project for the sake of tracking the dependency, just run the following inside of your Litexa project directory root:

    npm install --save @litexa/gadgets

    This should result in the following directory structure:

    project_dir
    ├── litexa
    └── node_modules
        └── @litexa
            └── gadgets
    

    Game Engine Interface

    New Statements

    When installed, the module adds a few new statements to Litexa's syntax.

    The startInputHandler statement adds support for declaring an Input Handler, and expects an inline function call that returns a single directive as an argument.

        startInputHandler createHandler()

    The createHandler function might look something like:

    createHandler = function() {
      var inputHandler = {
        type: "GameEngine.StartInputHandler",
        timeout: 60000,
        ...
      };
      return inputHandler;
    };

    Litexa will automatically save the originatingRequestId attached to this Input Handler, which is a requirement for validating that your skill handles only the events it asked for.

    The stopInputHandler statement creates the appropriate directive and automatically inserts the saved originatingRequestId of the last Input Handler started by the skill. It takes no arguments.

        stopInputHandler

    It is okay to put a stopInputHandler anywhere you might need to, even if there is not a specific Input Handler it might apply to. This is useful in handlers suited for global use (e.g. AMAZON.StartOverIntent to start over at any point in a game - you don't want the Input Handler's timeout event to interrupt her speech) and other cases where multiple interaction flows might go to a common state.

    If there is no active Input Handler, Litexa will ignore the stopInputHandler directive and instead simply log a warning.

    Event routing support is added for the GameEngine.InputHandlerEvent request directly, with the $request variable containing the full request object.

    Events are automatically filtered by the last valid originatingRequestId, with expired events (those generated for any prior startInputHandler) being discarded silently.

    Event handler syntax and behavior follow those of intent handlers. There are two forms of event handlers, listed below.

    General Handler

    You can write an event handler as below, which will cause Litexa to route all Input Handler events to it while in that state:

        when GameEngine.InputHandlerEvent
          local result = processInputEvents($request.events)

    Each request may include multiple events, so you can loop over the events key to catch them all:

        when GameEngine.InputHandlerEvent
          for event in $request.events
            local result = processEvent(event)

    Alternatively, you could switch over the names and react to event names directly:

        when GameEngine.InputHandlerEvent
          for event in $request.events
            switch event.name
              == "red" then
                say "red was pressed!"
              == "blue" then
                say "blue was pressed!"
              else
                say "I didn't recognize event {event.name}"
            local result = processEvent(event)

    Filtered Handler

    An alternate form of the intent handler that filters for event names is also available. In this case, the code will be executed repeatedly, if multiple of the same event are received. Inside these named intent handlers, the $event slot variable will contain the current Input Handler event. The following example's behavior is identical to the switch statement example above.

        when GameEngine.InputHandlerEvent "red"
          say "red was pressed"
          local result = processEvent($event)
    
        when GameEngine.InputHandlerEvent "blue"
          say "blue was pressed"
          local result = processEvent($event)

    In cases where both forms are used in the same state, the general handler will be invoked first, followed by the filtered version.

    Testing Support

    To test incoming Input Handler events, you can use the new inputHandlerEvent statement to generate an event matching the name of an event you've programmed into your startInputHandler directives.

        TEST "pressing buttons"
          launch
          inputHandlerEvent "button 1 pressed"

    If you need more information in your test, e.g. a sequence of simulated button events in the history, then you can write a JSON file with just the contents of the events key in the skill request, and refer to that in the test instead.

        TEST "pressing buttons"
          launch
          inputHandlerEvent quickPress.json

    The quickPress.json file contents might look like:

        [
          {
            "name": "button pressed",
            "inputEvents": [
              {
                "gadgetId": "agadget",
                "timestamp": "2017-08-18T01:32:40.027Z",
                "action": "down",
                "color": "FF0000"
              },
              {
                "gadgetId": "agadget",
                "timestamp": "2017-08-18T01:32:41.050Z",
                "action": "up",
                "color": "FF0000"
              }
            ]
          }
        ]

    Gadget Controller Interface

    Usage

    There are no new statements for the Gadget Controller Interface. However, use of the GadgetController.SetLight directive often pairs with Input Handler directives. For example, you may want the Echo Buttons to light up in a sequence for the user to memorize as part of a game.

    To add a GadgetController.SetLight directive in a response, use the directive keyword:

    gameStart
      say "Press the buttons when they are blue."
      directive animateButtonsForGame()

    and animateButtonsForGame() would look something like this:

    animateButtonsForGame() {
      return [
        {
          type: "GadgetController.SetLight",
          parameters: {...},
          ...
        }
      ]
    }

    Testing Support

    In your Litexa tests, the directives will show up as seen below, as part of the simulation output:

    84.COUNT_BUTTONS   $count=5 @ 3:02:10 PM
         ◖----------------"<!ouch,> I can't deal with more than four buttons right now. Before we start: Trickster, how many buttons do you want to use?" ... "Tell me Trickster, how many buttons should I look for?"
                              [DIRECTIVE 54] GadgetController.SetLight

    As for the actual content, you can write tests in your code files, and look at the directive JSON in the skill response in .test/output.json.

    Skill Manifest Addition

    If you use the Gadget Controller interface, you will need to include GADGET_CONTROLLER in your skill.* file, to officially tell Alexa that your skill is using it.

    {
      "manifest": {
        "apis": {
          "custom": {
            "interfaces": [
              {
                "type": "GADGET_CONTROLLER"
              }
              ... // other interfaces
            ]
      ...
    }

    Intent Handling Requirements

    When using either interface of the Gadgets Skill API, the AMAZON.HelpIntent and AMAZON.StopIntent must be handled by the skill (i.e. included in at least one when listener). Not doing so will result in an error during deployment.

    This can be done via state-specific handlers, or a global handler:

    waitForAnswer
      when AMAZON.HelpIntent
        say "Please answer the question. You can say, I don't know, to pass."
    
    global
      when AMAZON.StopIntent
        say "Goodbye for now."

    Install

    npm i @litexa/gadgets

    DownloadsWeekly Downloads

    214

    Version

    0.7.2

    License

    Apache-2.0

    Unpacked Size

    129 kB

    Total Files

    28

    Homepage

    litexa.com

    Last publish

    Collaborators

    • avatar
    • avatar