Support Capability Interfaces with the ACK Device SDK

This page provides an overview of how to support smart home capability interfaces in your host microcontroller unit (HMCU) application logic by using the Alexa Connect Kit (ACK) Device SDK. This page doesn't provide step-by-step instructions about implementing specific interfaces, but instead provides general information about the process.

For details about downloading and using the SDK, see ACK Device SDK. After you download the SDK, you can view the sample apps to see full examples of the concepts covered on this page.

Support smart home properties on your device

To support the smart home interfaces that you defined for your virtual product, you need to list the same interfaces in your ACK Device SDK ack_user_config.h file and then implement the corresponding callbacks in your application code.

For example, if your device supports PowerController, BrightnessController and two instances of ModeControllers (with instance ids 1 and 2), your application code must report the states of these four interfaces to the ACK Device SDK. Your code also must maintain and report the state for each defined interface using the application defined properties.

For example:

First, declare the support for the power, brightness and mode controllers in your ack_user_config.h file.

#define ACK_POWER_CONTROLLER
#define ACK_BRIGHTNESS_CONTROLLER
#define ACK_MODE_CONTROLLER

Then, in your application code, define the ordinals for the reported properties. Your application uses these ordinals with the ACK Device SDK APIs to indicate which properties are modified and need to be reported back to Alexa.

// Application-specific property ordinals
#define PROPERTY_POWER_STATE 0 // Power controller ordinal
#define PROPERTY_BRIGHTNESS 1 // Brightness controller ordinal
#define PROPERTY_TIMER_MODE 2 // Timer (mode) controller ordinal
#define PROPERTY_SPEED_MODE 3 // Blinking (mode) controller ordinal

Report smart home property values to Alexa

For each on-device property, your application must also define a callback method that reports the property values to Alexa.

ACKPropertyTableEntry_t ACKUser_PropertyTable[] = {
  {
    PROPERTY_POWER_STATE,
    AddPowerProperty
  },
  {
    PROPERTY_BRIGHTNESS,
    AddLightBrightnessProperty
  },
  {
    PROPERTY_TIMER_MODE,
    AddLightTimerProperty
  },
  {
    PROPERTY_SPEED_MODE,
    AddLightBlinkingProperty
  },
  {
    0,
    NULL
  }
};

Your property callback must report the value of the associated property to Alexa with the relevant ACK Device SDK API. For example, the following PowerController callback function uses the ACK_AddPowerControllerProperty API to report the Boolean value of the current power on/off state.

bool g_power = false; // Light power
bool AddPowerProperty(uint32_t propertyOrdinal, unsigned propertyFlags) {
  // Populate metadata about the property.
  // Leave the time-of-sample-field 0 to cause the current time to be sent.
  // Set the error margin to 10 milliseconds for illustrative purposes.
  ACKStateCommon_t common = {
    0,
    10,
    propertyFlags
  };
  ACKError_t error;
  error = ACK_AddPowerControllerProperty( & common, g_power);
  if (ACK_NO_ERROR != error) {
    ACK_DEBUG_PRINT_E("Error %u adding power property to event", error);
    return false;
  }
  return true;
}

Respond to smart home directives

Each smart home interface also requires that you implement a callback when your device receives relevant smart home directives.

For example, when an ACK-based device receives a PowerController directive from the Alexa service, the ACK Device SDK invokes the ACKUser_OnPowerControllerDirective() callback method. This callback needs to process reported changes and respond to the directive.

  • For a successful response, use the ACK_CompleteDirectiveWithSuccess() APIs.
  • For errors, use one of the relevant ACK_CompleteDirectiveWithXXXError() APIs. Errors might include out-of-range values or returning an incorrect device state.

The following code provides a sample implementation of the ACKUser_OnPowerControllerDirective() callback.

This example uses the POWER_STATE_PROPERTY ordinal to indicate which properties to include in the response to the PowerController directive and in the follow-up change report to Alexa services. If your application doesn't detect any changes, it can use a changed properties bitmask value of 0, which skips sending the change report.

bool g_power = false;

...

// Handler callback for incoming Alexa.PowerController directives.
// ACK_Process dispatches to this routine if such an incoming event is available from the
// ACK connectivity module when ACK_Process is called.
void ACKUser_OnPowerControllerDirective(int32_t correlationId, bool powerOn)
{
    bool powerStateChanged;

    // bitmasks of the properties that need to be included in the directive response and follow-up change report
    ACKPropertiesBits_t responsePropertiesBits = ACK_PROPERTY_BIT(POWER_STATE_PROPERTY);
    ACKPropertiesBits_t changedPropertiesBits = 0;

    ACK_DEBUG_PRINT_I("Received power controller directive; power %u.", powerOn);

    // Track whether the power state is actually changing. If so, we want to indicate this when completing
    // the directive, so an Alexa change report will be sent automatically.
    if(powerOn != g_power) {
        // need to indicate that power state has changed
       changedPropertiesBits = ACK_PROPERTY_BIT(POWER_STATE_PROPERTY);

        // change the internal state
        g_power = powerOn;
    }

   // Communicate with device power and change its state
    Hardware_SetPowerState(powerOn);

    // Complete directive and indicate changed properties
    ACK_CompleteDirectiveWithSuccess(
        correlationId,
        responsePropertiesBits,
        changedPropertiesBits);
}

Report smart home state changes to Alexa

In certain situations, your application code might also need to indicate that an incoming Alexa directive changed the state of the other Alexa control interfaces on the device.

For example, if a device that's powered off receives a Alexa.BrightnessController SetBrightness directive, it might have to power on before changing the brightness level. In this example, your application needs to indicate both the brightness level change and the power state change when responding to the directive.

The following code shows how you handle this example.

ACK_CompleteDirectiveWithSuccess(
  correlationId,
  ACK_PROPERTY_BIT(PROPERTY_BRIGHTNESS_STATE),
  ACK_PROPERTY_BIT(PROPERTY_BRIGHTNESS_STATE) | ACK_PROPERTY_BIT(PROPERTY_POWER_STATE));

Respond to smart home ReportState directives

Alexa sends a ReportState directive to your device to retrieve the current state of supported Alexa interfaces on your device. For example, a user might check their Alexa app to determine the on/off status of a light on a different floor of their house. In this case, when a user opens the app, Alexa sends a ReportState directive to your devices to retrieve the status. After Alexa determines the status, it displays it to the user.

You handle ReportState directives with the ACKUser_OnReportStateDirective() callback. When you do so, you should continuously return all device properties in your application.

// State-report callback
void ACKUser_OnReportStateDirective(int32_t correlationId)
{
    // This sends all properties demonstrated in this application.
    ACK_CompleteStateReportWithSuccess(correlationId);
}

Support smart home proactive state updates

If your device properties change their state due to a user interaction or additional logic that you programmed, you must report the change to Alexa services. This is called a proactive state update. If you don't report these changes, your device might not pass Works with Alexa (WWA) certification.

To report these changes, use the ACK_SendChangeReport() API. For example, you could use the following code to report when a user turns on a fan using the physical ON button affixed to a device.

ACK_SendChangeReport(
 ack_alexa_change_report_cause_type_physical_interaction,
 ACK_PROPERTY_BIT(PROPERTY_POWER_STATE),
 ACK_PROPERTY_BIT(PROPERTY_POWER_STATE));