Create a Sample Alexa Built-in Disco Ball with Smart Home for AVS

Eric Fahsl Apr 17, 2020
Share:
Alexa Voice Service Smart Home Tutorial Alexa Built-in
Blog_Header_Post_Img

In December, Amazon released Smart Home for AVS—an update to the Alexa Voice Service (AVS) API that enables voice control of smart home functionality on Alexa Built-in products. With this release, device makers can now send smart home commands via AVS events and directives without needing to build a separate Smart Home skill, AWS Lambda function, or device cloud to communicate to the device. Today, we will walk you through the steps to enable a sample disco ball device and receive the new directives in the AVS Device SDK Sample App starting in v1.17. You can also watch a video version of the guide below.

Simplification of Using Smart Home Commands for Alexa Built-in Devices

comparison diagram

Smart Home for AVS provides a great simplification and optimization for Alexa Built-in device makers and provides new functionalities for device makers who do not have the ability to manage a third-party cloud. Additionally, this approach reduces development time, operational costs, simplifies debugging, and reduces latency. Today, we will review the details of what is available.

There are now four Smart Home interfaces available through AVS:

  • Alexa.PowerController – for use of turning devices or settings on or off.
  • Alexa.ToggleController – similar to power, a binary toggle that allows the customer to choose the name of the property
  • Alexa.RangeController – allows the customer to set a value of a customizable range, including increasing or decreasing, even defining values for “low,” “medium,” “high,” “min,” “max,” and more.
  • Alexa.ModeController – sets different customizable modes on the device. Combined with richer Smart Home features such as primitives and semantic annotations, this offers greater flexibility for device control.

Device makers can start taking advantage of this today by updating their client to use the Alexa.Discovery API instead of the Capabilities API. For developers using the AVS Device SDK, v1.17 adds new Capability Agents for each of the four supported Smart Home interfaces and the Sample App has been updated to create a new virtual device called Discoball.

Step by Step Guide to Creating a Disco Ball Using the AVS Device SDK Sample Application

Before we get started, note you will need to have the AVS Device SDK Sample App running on a device, whether it be your local developer machine or a Raspberry Pi. See our Getting Started section of the AVS Device SDK GitHub page if you have not yet completed this.

First, in order to understand the functionality, let’s take a look at what has changed. In the SampleApp/src/SampleApplication.cpp, you’ll notice the following lines:

Copied to clipboard
/// The friendly name of the Endpoint. This is used in utterance.
static const std::string SAMPLE_ENDPOINT_FRIENDLYNAME("Discoball");

This is where the application declares the “friendly name,” or the name of the device that your users will call it in their utterances to Alexa. You can rename this to something else if you like.

In the code below, we will enable all four capabilities, but let’s first inspect the PowerController as it is simpler and easy to follow. Further down in SampleApplication.cpp, we can see the code for defining and creating the PowerControllerHandler:

Copied to clipboard
#ifdef POWER_CONTROLLER
    auto discoballPowerHandler = PowerControllerHandler::create();
    if (!discoballPowerHandler) {
        ACSDK_CRITICAL(LX("Failed to create power controller handler!"));
        return false;
    }
    discoballEndpointBuilder->withPowerController(discoballPowerHandler, true, true);
#endif

This is where our Sample App declares we are using the PowerController and will use the PowerController capability agent to add to our Discovery call.

Next, let’s look at the SampleApp/src/PowerControllerHandler.cpp file in our Sample App folder:

Copied to clipboard
std::pair<AlexaResponseType, std::string> PowerControllerHandler::setPowerState(
    bool state,
    AlexaStateChangeCauseType cause) {
    std::lock_guard<std::mutex> lock{m_mutex};
    if (m_currentPowerState != state) {
        if (state) {
            ConsolePrinter::prettyPrint("POWER CONTROLLER : TURN-ON");
        } else {
            ConsolePrinter::prettyPrint("POWER CONTROLLER : TURN-OFF");
        }

        m_currentPowerState = state;

        auto powerState = PowerControllerInterface::PowerState{
            m_currentPowerState, avsCommon::utils::timing::TimePoint::now(), std::chrono::milliseconds(0)};
        m_executor.submit([this, powerState, cause]() { executeNotifyObservers(powerState, cause); });
    }
    return std::make_pair(AlexaResponseType::SUCCESS, "");
}

In the above code block, we can see the handlers for when the PowerController directive is received. You can see that the application prints out to the screen “TURN-ON” or “TURN-OFF” and also using the PowerControllerInterface to store the state of the PowerController.

Before we build, the one final piece we might be interested in is to inspect the Alexa.Discovery event that our application generates. You can add a logging statement of the Alexa.Discovery object so that you can see what is generated in case you want to create your own CapabilityAgents, and help better understand the Smart Home Discovery API.

In the CapabilitiesDelegate/src/PostConnectCapabilitiesPublisher.cpp file, within the MessageRequestObserverInterface::Status PostConnectCapabilitiesPublisher::sendDiscoveryEvent function, we added the following line in order to print out the Discovery JSON:

Copied to clipboard
m_postConnectRequest = std::make_shared<PostConnectMessageRequest>(eventString);
    lock.unlock();

    //ADDED THIS LINE TO PRINT OUT DISCOVERY EVENT OBJECT
    ACSDK_DEBUG1(LX(__func__).d("DISCOVERY EVENT OBJECT", eventString));

    postConnectSender->sendPostConnectMessage(m_postConnectRequest);
    auto status = m_postConnectRequest->waitForCompletion();
Update your CMake command

In order to use the new capability agents, you can update your CMake (link) with the following line to enable all four interfaces:

-DENABLE_ALL_ENDPOINT_CONTROLLERS=ON

Run your CMake and build your Sample App via the make command, as normal (if this is new to you, check our Getting Started guide for your system platform/OS).

Now when you launch your Sample App, you may receive a notification on your Alexa app or other Alexa device that a new device called “Discoball" has been discovered.

If you enabled logging of the Discovery object above (and ran in at least DEBUG1 or lower), you should see a line similar to the following:

Copied to clipboard
2020-03-02 21:19:45.203 [ 31] 1 PostConnectCapabilitiesPublisher:sendDiscoveryEvent:DISCOVERY EVENT OBJECT=
{"event"\:{"header"\:{"namespace"\:"Alexa.Discovery"\,"name"\:"AddOrUpdateReport"\,"messageId"\:"a959cbad-b082-43bc-bd05-a3fc5b969143"\,"eventCorrelationToken"\:"a959cbad-b082-43bc-bd05-a3fc5b969143"\,"payloadVersion"\:"3"}\,"payload"\:{"scope"\:{"type"\:"BearerToken"\,"token"\:"Atza|IwEzb...TRUNCATED"}\,
"endpoints"\:[{"endpointId"\:"amzn1.application-oa2-client.3af85c9d4e3a42a09cb497bf999999\:\:YOUR_DEVICE_NAME\:\:YOUR_DEVICE_DSN\:\
:Discoball"\,"friendlyName"\:"Discoball"\,"description"\:"Sample Disco ball Description 2"\,"manufacturerName"\:"Sample Manufacturer"\,"displayCategories"\:["OTHER"]\,"additionalAttributes"\:{"manufacturer"\:"Sample Manufacturer"\,"model"\:"Model1"\,"serialNumber"\:"123456789"\,"firmwareVersion"\:"1.0"\,"softwareVersion"\:"1.0"\,"customIdentifier"\:"SampleApp"}\,"capabilities"\:[
…
type"\:"AlexaInterface"\,"interface"\:"Alexa.PowerController"\,"version"\:"3"\,"properties"\:{"supported"\:[{"name"\:"powerState"}]\,"proactivelyReported"\:true\,"retrievable"\:true}}\,
{"type"\:"AlexaInterface"\,"interface"\:"Alexa.ToggleController"\,"version"\:"3"\,"instance"\:"Discoball.Light"\,"properties"\:{"supported"\:[{"name"\:"toggleState"}]\,"proactivelyReported"\:true\,"retrievable"\:true\,"nonControllable"\:false}\,"capabilityResources"\:{"friendlyNames"\:[{"@type"\:"text"\,"value"\:{"text"\:"Light"\,"locale"\:"en-US"}}]}}\,
{"type"\:"AlexaInterface"\,"interface"\:"Alexa"\,"version"\:"3"}]}]}}}

Try using it – from your Sample App, activate Alexa via tap-to-talk or use the wake word and say “turn on Discoball.” You should receive a directive to your Sample App and you should have output on your console output.

Copied to clipboard
2020-03-02 21:21:49.012 [  6] I DirectiveSequencer:onDirective:DIRECTIVE_HEADER=namespace\:Alexa.PowerController\,name\:TurnOn\,messageId\:0d117745-b426-4ad4-a674-c14d9aZZZZZZ\,dialogRequestId\:\,correlationToken\:AAAAAAAAAAD5wNcmk9SJy6b/jky4API26AEAAAAAAADeOzjWOm0wOlIZQxogmRjMqHrxELiUvc26K4e7RVe9LiFXInMwxFx2LPEPLuMInYXDetwE0DOkZhuNvXFK8FBAp7jXNiIkOncDU0I1E_TRUNCATED_j+BWpzg\=\=\,eventCorrelationToken\:\,payloadVersion\:3\,instance\:
...
##########################################
#       POWER CONTROLLER : TURN-ON       #
##########################################

Similarly, if you try saying “turn off Discoball” you should receive a corresponding event for turning off Discoball.

Copied to clipboard
2020-03-02 21:23:39.321 [  6] I DirectiveSequencer:onDirective:DIRECTIVE_HEADER=namespace\:Alexa.PowerController\,name\:TurnOff\,messageId\:cd075911-13f9-4490-bf97-7dad2ZZZZZZ\,dialogRequestId\:\,correlationToken\:AAAAAAAAAAD5wNcmk9SJy6b/jky4API26AEAAAAAAAAcc09O4t+MKtoQU+_TRUNCATED_um3wtgjqnjHfeWInJMreIqfduHY3BdgWwBkUvmFfU/msOjo88vW9gow+DULwKWIkTH0huA\=\=\,eventCorrelationToken\:\,payloadVersion\:3\,instance\:
…
###########################################
#       POWER CONTROLLER : TURN-OFF       #
###########################################

Try some other utterances:

  • “set Discoball to green”
  • “set the speed to 7”
  • “set color to red”
  • “switch on the light”
  • “what is the speed of Discoball?”

Notice how we don’t always have to say “Discoball” on every utterance? This is due to the friendly name of the different properties (note that if you have an existing device named one of these values it may conflict. You can manage this in the Alexa app).

Testing with the Alexa App

Since your Discoball sample device was discovered and is registered as a Smart Home device on your Alexa account, you can see the device within your Alexa app, get the current state, and change the values all through the app.

In the app, go to devices, all devices. Scroll down until you find the device “Discoball.” When you open it, you will see four attributes corresponding to the four interfaces you enabled: Power (PowerController), Speed (RangeController), Color (ModeController), and Light (ToggleController). Notice that when you open this screen on your Alexa app, your Sample App will start showing a number of “ReportState” directives coming in to your Sample App – these are requests from the Alexa app querying your device to understand the latest status. The SDK automatically responds with an Alexa.StateReport event containing the latest status. You can change the values via the Alexa app and your Sample App will receive the directives. Similarly, if you change one of the values via voice, the Alexa app will be updated shortly to reflect the updated status. You can also visit the Alexa Privacy Dashboard to learn about how customers can manage information related to their devices.

app
Certification

For this new capability, please note the updated certification guidelines for device controls. You can see the updated items on the AVS Certification checklist.

We are very excited about the new Smart Home for AVS capability and are looking forward to see how device makers are able to leverage it!

Get Started

You can watch our video version of this guide or review the documentation to get started.

Related Articles

Alexa Smart Home Controls Now Available via Alexa Voice Service API

Smart Home for AVS is an update to the Alexa Voice Service (AVS) API that enables voice control of smart home functionality on Alexa Built-in products. With this release, device makers can add support for Toggle, Mode, Range, and Power control APIs, previously enabled only for Smart Home Skill-based integrations.

Subscribe