{{announcement.body}}
{{announcement.title}}

Alexa and Raspberry Pi Demo

DZone 's Guide to

Alexa and Raspberry Pi Demo

I'm going to create one skill on my Alexa devices that is executed on my Raspberry Pi! This a tutorial for a skill that you can recreate.

· IoT Zone ·
Free Resource

amazon echo dot

Combine your two favorite gadgets!

We're keeping on playing with Alexa. This time I want to create one skill that uses a compatible device (for example one Raspberry Pi 3). Here you can see the documentation and examples that the people of Alexa provides us. Basically we need to create a new Product/Alexa gadget in the console. It gives us one amazonId and alexaGadgetSecret.

You may also like: Smart Home Tutorial: ESP8266, Alexa, and Amazon Echo

Then we need to install the SDK in our Raspberry Pi (it install several python libraries). Then we can create our gadget script running on our Raspberry Pi, using the AmazonId and alexaGadgetSecret. We can listen to several Alexa events. For example: When we say the wakeword, with a timer, an alarm and also we can create our custom events.

I'm going to create one skill that allows me to say something like: "Alexa, use device demo and set color to green" or "Alexa, use device demo and set color to red" and I'll put this color in the led matrix that I've got (one Raspberry Pi Sense Hat)

This is the python script:

Python




x
52


 
1
import logging
2
import sys
3
import json
4
from agt import AlexaGadget
5
from sense_hat import SenseHat
6
 
           
7
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
8
logger = logging.getLogger(__name__)
9
 
           
10
sense = SenseHat()
11
sense.clear()
12
 
           
13
RED = [255, 0, 0]
14
GREEN = [0, 255, 0]
15
BLUE = [0, 0, 255]
16
YELLOW = [255, 255, 0]
17
BLACK = [0, 0, 0]
18
 
           
19
class Gadget(AlexaGadget):
20
    def on_alexa_gadget_statelistener_stateupdate(self, directive):
21
        for state in directive.payload.states:
22
            if state.name == 'wakeword':
23
                sense.clear()
24
                if state.value == 'active':
25
                    sense.show_message("Alexa", text_colour=BLUE)
26
 
           
27
    def set_color_to(self, color):
28
        sense.set_pixels(([color] * 64))
29
 
           
30
    def on_custom_gonzalo123_setcolor(self, directive):
31
        payload = json.loads(directive.payload.decode("utf-8"))
32
        color = payload['color']
33
 
           
34
        if color == 'red':
35
            logger.info('turn on RED display')
36
            self.set_color_to(RED)
37
 
           
38
        if color == 'green':
39
            logger.info('turn on GREEN display')
40
            self.set_color_to(GREEN)
41
 
           
42
        if color == 'yellow':
43
            logger.info('turn on YELLOW display')
44
            self.set_color_to(YELLOW)
45
 
           
46
        if color == 'black':
47
            logger.info('turn on YELLOW display')
48
            self.set_color_to(BLACK)
49
 
           
50
 
           
51
if __name__ == '__main__':
52
    Gadget().main()



Here the ini file of our gadget:

Python




xxxxxxxxxx
1


 
1
[GadgetSettings]
2
amazonId = my_amazonId
3
alexaGadgetSecret = my_alexaGadgetSecret
4
 
           
5
[GadgetCapabilities]
6
Alexa.Gadget.StateListener = 1.0 - wakeword
7
Custom.gonzalo123 = 1.0



Whit this ini file I'm saying that my gadget will trigger a function when wakeword has been said and with my custom event "Custom.gonzalo123".

That's the skill:

Python




xxxxxxxxxx
1
40


 
1
const Alexa = require('ask-sdk')
2
 
           
3
const RequestInterceptor = require('./interceptors/RequestInterceptor')
4
const ResponseInterceptor = require('./interceptors/ResponseInterceptor')
5
const LocalizationInterceptor = require('./interceptors/LocalizationInterceptor')
6
const GadgetInterceptor = require('./interceptors/GadgetInterceptor')
7
 
           
8
const LaunchRequestHandler = require('./handlers/LaunchRequestHandler')
9
const ColorHandler = require('./handlers/ColorHandler')
10
const HelpIntentHandler = require('./handlers/HelpIntentHandler')
11
const CancelAndStopIntentHandler = require('./handlers/CancelAndStopIntentHandler')
12
const SessionEndedRequestHandler = require('./handlers/SessionEndedRequestHandler')
13
const FallbackHandler = require('./handlers/FallbackHandler')
14
const ErrorHandler = require('./handlers/ErrorHandler')
15
 
           
16
let skill
17
 
           
18
module.exports.handler = async (event, context) => {
19
  if (!skill) {
20
    skill = Alexa.SkillBuilders.custom().
21
      addRequestInterceptors(
22
        RequestInterceptor,
23
        ResponseInterceptor,
24
        LocalizationInterceptor,
25
        GadgetInterceptor
26
      ).
27
      addRequestHandlers(
28
        LaunchRequestHandler,
29
        ColorHandler,
30
        HelpIntentHandler,
31
        CancelAndStopIntentHandler,
32
        SessionEndedRequestHandler,
33
        FallbackHandler).
34
      addErrorHandlers(
35
        ErrorHandler).
36
      create()
37
  }
38
 
           
39
  return await skill.invoke(event, context)
40
}



One important thing here is the GadgetInterceptor. This interceptor finds the endpointId from the request and appends it to the session. This endpoint exists because we've created our Product/Alexa gadget and also the python script is running on the device. If the endpoint isn't present maybe our skill must say to the user something like "No gadgets found. Please try again after connecting your gadget.".

Python
x
12
 
1
const utils = require('../lib/utils')
2
 
           
3
const GadgetInterceptor = {
4
  async process (handlerInput) {
5
    const endpointId = await utils.getEndpointIdFromConnectedEndpoints(handlerInput)
6
    if (endpointId) {
7
      utils.appendToSession(handlerInput, 'endpointId', endpointId)
8
    }
9
  }
10
}
11
 
           
12
module.exports = GadgetInterceptor


Finally, the handlers to trigger the custom event:

Python
xxxxxxxxxx
1
49
 
1
const log = require('../lib/log')
2
const utils = require('../lib/utils')
3
 
           
4
const buildLEDDirective = (endpointId, color) => {
5
  return {
6
    type: 'CustomInterfaceController.SendDirective',
7
    header: {
8
      name: 'setColor',
9
      namespace: 'Custom.gonzalo123'
10
    },
11
    endpoint: {
12
      endpointId: endpointId
13
    },
14
    payload: {
15
      color: color
16
    }
17
  }
18
}
19
 
           
20
const ColorHandler = {
21
  canHandle (handlerInput) {
22
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
23
      && handlerInput.requestEnvelope.request.intent.name === 'ColorIntent'
24
  },
25
  handle (handlerInput) {
26
    const requestAttributes = handlerInput.attributesManager.getRequestAttributes()
27
    const cardTitle = requestAttributes.t('SKILL_NAME')
28
 
           
29
    const endpointId = utils.getEndpointIdFromSession(handlerInput)
30
    if (!endpointId) {
31
      log.error('endpoint', error)
32
      return handlerInput.responseBuilder.
33
        speak(error).
34
        getResponse()
35
    }
36
 
           
37
    const color = handlerInput.requestEnvelope.request.intent.slots['color'].value
38
    log.info('color', color)
39
    log.info('endpointId', endpointId)
40
 
           
41
    return handlerInput.responseBuilder.
42
      speak(`Ok. The selected color is ${color}`).
43
      withSimpleCard(cardTitle, color).
44
      addDirective(buildLEDDirective(endpointId, color)).
45
      getResponse()
46
  }
47
}
48
 
           
49
module.exports = ColorHandler


Here one video with the working example:

Source code in my GitHub.


Further Reading

Developing Alexa Skills With Spring Boot REST Services in Mind

Eavesdropping With Amazon Alexa

Developing Location-Aware Alexa Skills

Topics:
iot ,tutorial ,alexa ,amazon ,raspberry pi ,demoboard

Published at DZone with permission of Gonzalo Ayuso , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}