The Alexa Auto SDK Alexa API provides interfaces for standard Alexa features. The Engine handles some extra setup and steps to sequence events and directive handling. The platform developer can focus on just using the provided API to interact with Alexa. This is done by registering platform interfaces via the Engine object.
You can read more about how the Alexa Auto SDK flow works by checking out some sequence diagrams.
If you want to enable wake word support for your Alexa Auto integration, you need to make a request with your Alexa Auto Solution Architect (SA).
There are 3 steps to this process:
- Let your SA know you want to enable wake word support.
- Your SA processes your request with the appropriate Alexa teams.
- You'll receive a single zip file containing the necessary packages, instructions, and scripts.
All that's left for you to do is create an "extras" directory under your "aac-sdk" directory for the packages and follow the instructions in the README file included in the package.
The Alexa Auto SDK manages internal state information for Alexa and provides an interface for developers to handle state changes in their platform. To implement a custom handler for Alexa state changes, the aace::alexa::AlexaClient
class should be extended:
#include <AACE/Alexa/AlexaClient.h>
class MyAlexaClient : public aace::alexa::AlexaClient {
public:
void dialogStateChanged( DialogState state ) override {
// handle dialog state change!
}
void authStateChanged( AuthState state, AuthError error ) override {
// handle auth state change!
}
void connectionStatusChanged( ConnectionStatus status, ConnectionChangedReason reason ) override {
// handle connection status change!
}
};
...
// Configure the Engine
engine->registerPlatformInterface( std::make_shared<MyAlexaClient>() );
It is the responsibility of the platform implementation to supply audio data to the Engine so that Alexa can process voice input. Since the Engine does not know how audio is managed on a specific platform, the specific audio capture implementation is up to the platform developer. The default platform implementation provides methods for writing raw PCM data to the Engine's audio input processor, which includes handling wakeword recognition and end-of-speech detection.
To implement a custom handler for speech input, the aace::alexa::SpeechRecognizer
class should be extended:
#include <AACE/Alexa/SpeechRecognizer.h>
class MySpeechRecognizer : public aace::alexa::SpeechRecognizer {
public:
// possible platform implementation that has an audio input callback
void startAudioInput(){
MyAudioInput->start(); //start platform-specific audio input
...
}
...
void MyAudioInputOnWriteCallback( const int16_t* data, const size_t size ) {
// call inherited write() method to provide audio samples
// to the Engine for input processing
write( data, size );
...
}
};
...
// Configure the Engine
engine->registerPlatformInterface( std::make_shared<MySpeechRecognizer>() );
The speech synthesizer is responsible for handling Alexa's speech. The SpeechSynthesizer
class extends the abstract aace::alexa::AudioChannel
class. This is to separate each audio-capable class on the platform while allowing the nEgine to control their interactive behaviors. The platform implementation provides a reference to an instance of a media player and a speaker. (The term "speaker" is used here in the sense of an "output device") Read more about handling media and volume here.
To implement a custom handler for speech output the aace::alexa::SpeechSynthesizer
class should be extended:
#include <AACE/Alexa/SpeechSynthesizer.h>
class MySpeechSynthesizer : public aace::alexa::SpeechSynthesizer {
public:
MySpeechSynthesizer(std::shared_ptr<MyMediaPlayer> myMediaPlayer, std::shared_ptr<MySpeaker> mySpeaker);
...
}
...
MySpeechSynthesizer::MySpeechSynthesizer(std::shared_ptr<MyMediaPlayer> mediaPlayer, std::shared_ptr<MySpeaker> mySpeaker) : aace::alexa::SpeechSynthesizer(mediaPlayer, mySpeaker) { }
...
// Configure the Engine
auto mySpeechSynthesizerMediaPlayer = std::make_shared<MyMediaPlayer>(...);
auto mySpeechSynthesizerSpeaker = std::make_shared<MySpeaker>(...);
auto mySpeechSynthesizer = std::make_shared<MySpeechSynthesizer>( mySpeechSynthesizerMediaPlayer, mySpeechSynthesizerSpeaker);
engine->registerPlatformInterface( mySpeechSynthesizer );
When an audio media stream is received from Alexa it is the responsibility of the platform implementation to play the stream in a platform-specific media player and to notify the Engine when the audio starts and stops playing.
The class is similar to the SpeechSynthesizer class. However, you may want to handle your media player or speaker differently. Read more about handling media and volume here.
To implement a custom handler for audio player output the aace::alexa::AudioPlayer
class should be extended:
#include <AACE/Alexa/AudioPlayer.h>
class MyAudioPlayer : public aace::alexa::AudioPlayer {
public:
MyAudioPlayer(std::shared_ptr<MyMediaPlayer> myMediaPlayer, std::shared_ptr<MySpeaker> mySpeaker);
...
MyAudioPlayer::MyAudioPlayer(std::shared_ptr<MyMediaPlayer> mediaPlayer, std::shared_ptr<MySpeaker> mySpeaker) : aace::alexa::AudioPlayer(mediaPlayer, mySpeaker) { }
...
// Configure the Engine
auto myAudioPlayerMediaPlayer = std::make_shared<MyMediaPlayer>(...);
auto myAudioPlayerSpeaker = std::make_shared<MySpeaker>(...);
auto myAudioPlayer = std::make_shared<MyAudioPlayer>(myAudioPlayerMediaPlayer, myAudioPlayerSpeaker);
engine->registerPlatformInterface( myAudioPlayer );
It is the responsibility of the platform implementation to provide a visual and audio indication to the user when notifications (package shipment notifications, notifications from skills, etc.) are available from Alexa. Read more about Notifications here.
To implement a custom handler for Notifications the aace::alexa::Notifications
class should be extended:
#include <AACE/Alexa/Notifications.h>
using IndicatorState = aace::alexa::Notifications::IndicatorState;
class MyNotificationsHandler : public aace::alexa::Notifications {
MyNotificationsHandler(std::shared_ptr<aace::alexa::MediaPlayer> player, std::shared_ptr<aace::alexa::Speaker> speaker)
public:
void setIndicator( IndicatorState state ) override {
// set your notifcations indicator!
}
};
...
// Configure the Engine
auto notificationsMediaPlayer = std::make_shared<MyMediaPlayer>(...);
auto notificationsSpeaker = std::make_shared<MySpeaker>(...);
auto m_notificationsHandler = std::make_shared<MyNotificationsHandler>(notificationsMediaPlayer, notificationsSpeaker);
engine->registerPlatformInterface(m_notificationsHandler);
When an alert is received from Alexa, it is the responsibility of the platform implementation to play the alert sounds in a platform-specific media player and notify the Engine when the audio starts and stops playing. The state of the alert is also made available for the platform to react to. The class is similar to the SpeechSynthesizer
class. However, you may want to handle your media player or speaker differently. Read more about handling media and volume here.
To implement a custom handler for alerts, the aace::alexa::Alerts
class should be extended:
#include <AACE/Alexa/Alerts.h>
class MyAlerts : public aace::alexa::Alerts {
public:
MyAlerts(std::shared_ptr<MyMediaPlayer> myMediaPlayer, std::shared_ptr<MySpeaker> mySpeaker)
...
MyAlerts::MyAlerts(std::shared_ptr<MyMediaPlayer> mediaPlayer, std::shared_ptr<MySpeaker> mySpeaker) : aace::alexa::Alerts(mediaPlayer, mySpeaker) { }
void MyAlerts::alertStateChanged( const std::string& alertToken, AlertState state, const std::string& reason ) override {
//handle the alert state change
}
...
// Configure the Engine
auto myAlertsMediaPlayer = std::make_shared<MyMediaPlayer>(...);
auto myAlertsSpeaker = std::make_shared<MySpeaker>(...);
auto myAlerts = std::make_shared<MyAlerts>(myAudioPlayerMediaPlayer, myAudioPlayerSpeaker);
engine->registerPlatformInterface( myAlerts );
When audio data is received from Alexa it is the responsibility of the platform implementation to read the data from the Engine and play it using a platform-specific media player and speaker. It is also the responsibility of the platform implementation to notify the Engine when the speech audio actually begins playing in the media player and when it is finished. Alexa will notify the Engine that the platform should play/stop/pause/resume playing the speech or other audio in which case the platform implementation must play/stop/pause/resume the media player playback. The platform should extend both MediaPlayer
and Speaker
and implement the platform-specific functionality. These classes will then be instantiated by other platform interfaces (Alerts
, SpeechSynthesizer
, AudioPlayer
) as separate audio channels.
To implement a custom handler for MediaPlayer the aace::alexa::MediaPlayer
class should be extended:
#include <AACE/Alexa/MediaPlayer.h>
class MyMediaPlayer : public aace::alexa::MediaPlayer{
public:
bool prepare() override {
...
while(read(data, size) > 0)
//write readable data to media location
...
if(successful) return true;
else playbackError(type, error);// if platform mediaplayer fails, notify the engine with type and description
}
bool prepare(std::string url) override {
MyMediaPlayerReference->MySetMediaUrl(url)// set platform media when url is given
...
return true; //if successful
}
bool play() override {
...
MyMediaPlayerReference->MyPlay(); //play platform mediaplayer
...
return true; //if successful
}
...
PlatformMediaPlayer* MyMediaPlayerReference = ...//platform-specific
}
The platform implementation's Speaker class will likely need a reference to the media player class.
To implement a custom handler for Speaker, the aace::alexa::Speaker
class should be extended:
#include <AACE/Alexa/Speaker.h>
class MySpeaker : public aace::alexa::Speaker{
public:
MySpeaker(std::shared_ptr<MyMediaPlayer> mediaPlayer){
m_mediaPlayer = mediaPlayer;
}; //One way to get the media player reference
...
bool setVolume( int8_t volume ) override {
m_mediaPlayer->MySetVolume(volume);//platform-specific.
m_myPlatformVolume = volume;
return true;
...
int8_t getVolume() override {
return m_myPlatformVolume;//using a member variable
}
...
}
When template info is received from Alexa, it is the responsibility of the platform implementation to handle the rendering of any UI with the info that is received from Alexa. There are two template types: Templates and PlayerInfo.
In the case of lists, it is the responsibility of the platform to handle pagination. Alexa sends down the entire list as a JSON response and starts reading out the first five elements of the list. At the end of reading the first five elements it will prompt the user to see if they want to read the remaining elements from the list. If the user chooses to proceed with the remaining elements, Alexa sends down the entire list as a JSON response but starts reading from the sixth element onwards.
To implement a custom handler for GUI templates, the aace::alexa::TemplateRuntime
class should be extended:
#include <AACE/Alexa/TemplateRuntime.h>
class MyTemplateRuntime : public aace::alexa::TemplateRuntime {
public:
void doRenderTemplate( const std::string& payload ) override {
// handle rendering the template data specified in payload
}
void doRenderPlayerInfo( const std::string& payload ) override {
// handle rendering the player info data specified in payload
}
};
...
// Configure the Engine
engine->registerPlatformInterface( std::make_shared<MyTemplateRuntime>() );
The Engine provides methods for notifying it of playback controller events. If the platform has playback control features, it must inform the Engine.
To implement a custom handler for the playback controller, the aace::alexa::PlaybackController
class should be extended:
#include <AACE/Alexa/PlaybackController.h>
class MyPlaybackController : public aace::alexa::PlaybackController {
...
void platformPlayButtonPressed(){ //called by some platform event
playButtonPressed();
...
};
...
// Configure the Engine
engine->registerPlatformInterface( std::make_shared<MyPlaybackController>() );