Gracias por tu visita. Esta página solo está disponible en inglés.

Discover Echo Buttons

The term Echo Button discovery refers to two different processes:

  • Bluetooth pairing – This is the process that users take to pair their Echo Buttons with their Amazon Echo device. For more information, see How Echo Buttons Work.
  • Roll call – This is the process by which a skill determines how many Echo Buttons, and the gadget IDs of the buttons, that the user wants to use with the skill. This is the subject of this topic.

In this topic, we first describe the goals of roll call, and then how to implement it.

Roll Call Goals

Because Echo Buttons enter sleep mode to preserve battery life, the Echo Buttons will likely be asleep when a user launches your skill. The user might also have a different number of buttons than your skill requires. For example, your skill might need three buttons, but the user has only paired two to this device, or has paired four. For these reasons, your skill should begin with a roll call.

A quiz game, for instance, might have a roll call phase asking each player to buzz in. An action game might ask the players to press all the Echo Buttons that they want to use, from left to right, to wake up the buttons and simultaneously learn about their spatial layout.

Your goals during roll call are as follows:

  • Wake up the Echo Buttons and make sure that they are connected.
  • Get the gadget ID for each Echo Button that you discover. Your skill will use these gadget IDs later to perform tasks like identify which player buzzed in, or to set the order in which you want the buttons to light up.
  • Produce a semantic mapping for your game. The timestamps of the raw button events within the event information will tell you the order that they were pressed in.

If you want to support drop in and drop out play, you should repeat this roll call procedure in response to a voice intent and update your internal gadget ID mapping. For example, if you have identified a player order among Echo Buttons during roll call and subsequently refer to your players by number, then you could add an intent to support the utterance "Alexa, drop Player 3 from the game."

Performing Roll Call

To begin roll call, respond to any prior request from Alexa (for example, your launch intent) with a response that includes verbal instructions to your players and an appropriate GameEngine.StartInputHandler directive.

Imagine that you want to refer to a group of three buttons as "first", "second" and "third" during your game. You could begin by using a GadgetController directive to set the LED animations for all three buttons to blue, and then have Alexa ask, "Great! Now, press these three blue buttons in order, from left to right."

To set this up, your GameEngine.StartInputHandler directive must include three recognizers, one for each button. The purpose is to detect if each button is pressed at least once. Set up the recognizers to recognize any down event, anywhere in the history. When all three recognizers are active, the complete event will fire and the Input Handler will stop. Otherwise, the Input Handler will time out and fire a failed event instead. In that case, the Input Handler will send all the raw button events that have occurred since the Input Handler started, so that you can determine if the player has pressed anything at all.

Example

Because Echo Buttons enter sleep mode to preserve battery life, when your skill is launched it is not likely that the Echo Buttons will actually be turned on and connected. There could also be fewer than or more than the number of buttons that your skill requires. For these reasons, your skill must begin with some form of a roll call.

The following example sets up roll call for a skill that requires three buttons. It therefore sets up an Input Handler to notify the skill when three buttons have been pressed, or if 30 seconds have passed without three buttons being pressed.

Copied to clipboard.

{
  "version": "1.0",
  "sessionAttributes": {},
  "response": {
  "outputSpeech": {
     "type": "SSML",
     "ssml": "<speak>Please press the buttons one at a time. When you press the third button, there will be an Input Handler event. If you do not press three buttons within 30 seconds, there will be an Input Handler event to signal that roll call failed. <audio src=\"https://s3.amazonaws.com/ask-soundlibrary/foley/amzn_sfx_rhythmic_ticking_30s_01.mp3\"/></speak>"
    },
  "shouldEndSession": false,
  "directives": [
      {
        "type": "GameEngine.StartInputHandler",
        "version": 1,
        "timeout": 30000,
        "proxies": ["first", "second", "third"],        
        "targetGadgets": [],
        "recognizers": {
           "allPressedRecognizer": {
              "type": "match",
              "fuzzy": true,
              "anchor": "end",
              "pattern": [
                {
                   "gadgetIds": ["first"],
                   "action": "down"
                },
                {
                   "gadgetIds": ["second"],
                   "action": "down"
                },
                {
                   "gadgetIds": ["third"],
                   "action": "down"
                }
             ]
           }
        },
        "events": {
           "rollCallCompleteEvent": {
              "meets": ["allPressedRecognizer"],
              "reports": "matches",
              "shouldEndInputHandler": true
           },
           "rollCallFailedEvent": {
              "meets": ["timed out"],
              "reports": "history",
              "shouldEndInputHandler": true
           }
         }
      }
   ]
 }
}

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Node.js (v2).

const StartInputIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'StartInputHandlerIntent';
  },
  handle(handlerInput) {

      // Set up an Input Handler to notify this skill when three buttons
      // have been pressed, or if 30 seconds have passed without three
      // buttons being pressed.
      const response = handlerInput.responseBuilder
          .speak("Please press the buttons one at a time. When you press the third button, "
                  + "there will be an Input Handler event. If you do not press three buttons "
                  + "within 30 seconds, there will be an Input Handler event to signal that "
                  + "roll call failed."
                  + "<audio src=\"https://s3.amazonaws.com/ask-soundlibrary/foley/amzn_sfx_rhythmic_ticking_30s_01.mp3\"/>")
          .withShouldEndSession(false)
          .addDirective({
            'type': 'GameEngine.StartInputHandler',
            'timeout': 30000,
            'proxies': [ 'first', 'second', 'third' ],
            'recognizers': {
               'allPressedRecognizer': {
                  'type': 'match',
                  'fuzzy': true,
                  'anchor': 'end',
                  'pattern': [
                      {
                         'gadgetIds': [ 'first' ],
                         'action': 'down'
                      },
                      {
                         'gadgetIds': [ 'second' ],
                         'action': 'down'
                      },
                      {
                         'gadgetIds': [ 'third' ],
                         'action': 'down'
                      }
                   ]
                }
            },
            'events': {
                'rollCallCompleteEvent': {
                    'meets': [
                       'allPressedRecognizer'
                    ],
                    'reports': 'matches',
                    'shouldEndInputHandler': true
                },

                'rollCallFailedEvent': {
                    'meets': [
                       'timed out'
                    ],
                    'reports': 'history',
                    'shouldEndInputHandler': true
                }
            }
         })
          .getResponse();

         console.log("===RESPONSE=== "+ JSON.stringify(response));
         return response;

   }
};

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Java.

package com.amazon.ask.buttonsamples.handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import static com.amazon.ask.request.Predicates.intentName;
import com.amazon.ask.model.services.gameEngine.*;
import com.amazon.ask.model.interfaces.gameEngine.*;
import java.util.Optional;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class StartInputIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput handlerInput) {
        return handlerInput.matches(intentName("StartInputHandlerIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {

      // We won't know the gadget IDs of the buttons in advance,
      // so define proxies that we can use in the recognizer definition.
      List<String> proxies = (List<String>)Arrays.asList("first","second","third");

      // Build a pattern that the recognizer will depend on.
      // This means that for the recognizer to be true, this
      // pattern (and any other patterns that the recognizer
      // depends on) must occur. We use a proxy ("first")
      // instead of a gadget ID because we won't know the
      // gadget ID in advance.
      Pattern firstButtonPressed = Pattern.builder()
        .withAction(InputEventActionType.DOWN)
        .withGadgetIds((List<String>)Arrays.asList("first"))
        .build();

      // Build a pattern for the second button pressed.
      Pattern secondButtonPressed = Pattern.builder()
        .withAction(InputEventActionType.DOWN)
        .withGadgetIds((List<String>)Arrays.asList("second"))
        .build();

      // Build a pattern for the third button pressed.
      Pattern thirdButtonPressed = Pattern.builder()
        .withAction(InputEventActionType.DOWN)
        .withGadgetIds((List<String>)Arrays.asList("third"))
        .build();

      // Build the recognizer that will be true when
      // three buttons are pressed.
      PatternRecognizer allPressedRecognizer = PatternRecognizer.builder()
        .withFuzzy(true)
        .withAnchor(PatternRecognizerAnchorType.END)
        .withPattern((List<Pattern>)Arrays.asList(
			firstButtonPressed,
			secondButtonPressed,
			thirdButtonPressed))
        .build();

      // Put the recognizer into a map so that we can give
      // it a name.
      HashMap<String, Recognizer> recognizerMap =
         new HashMap<String, Recognizer>();
      recognizerMap.put("allPressedRecognizer", allPressedRecognizer);

      // Define the event that will be triggered when three buttons
      // have been pressed.
      Event rollCallCompleteEvent = Event.builder()
        .withShouldEndInputHandler(true)
        .withReports(EventReportingType.MATCHES)
        .withMeets((List<String>)Arrays.asList("allPressedRecognizer"))
        .build();

      // Define the event that will be triggered by the Input Handler timing out.
      Event rollCallFailedEvent = Event.builder()
        .withShouldEndInputHandler(true)
        .withReports(EventReportingType.HISTORY)
        .withMeets((List<String>)Arrays.asList("timed out"))
        .build();

      // Put the events into a map.
      HashMap<String, Event> eventMap = new HashMap<String, Event>();
      eventMap.put("rollCallComplete", rollCallCompleteEvent);
      eventMap.put("rollCallFailed", rollCallFailedEvent);

      // Set up an Input Handler to notify this skill when three buttons
      // have been pressed, or if 30 seconds have passed without three
      // buttons being pressed.
      StartInputHandlerDirective directive = StartInputHandlerDirective.builder()
        .withTimeout((long)30000)
        .withProxies(proxies)
        .withRecognizers(recognizerMap)
        .withEvents(eventMap)
        .build();

      // Assemble the response.
      Optional<Response> response = handlerInput.getResponseBuilder()
        .withSpeech("Please press the buttons one at a time. When you press the "
                     + "third button, there will be an Input Handler event. If you "
                     + "do not press three buttons within 30 seconds, there will be "
                     + "an Input Handler event to signal that roll call failed. "
                     + "<audio src=\"https://s3.amazonaws.com/ask-soundlibrary/foley/amzn_sfx_rhythmic_ticking_30s_01.mp3\"/>")
        .withShouldEndSession(false)
        .addDirective(directive)
        .build();

      // Write the response to CloudWatch.
      String responseLog = response.toString();
      responseLog = responseLog.replace("\n", " ").replace("\r", " ");
      System.out.println("===RESPONSE=== " + responseLog);

      // Return the response.
      return response;

    }
}