Hackster is hosting Hackster Holidays, Ep. 4: Livestream & Giveaway Drawing. Start streaming on Wednesday!Stream Hackster Holidays, Ep. 4 on Wednesday!
Adam Siwy
Created December 26, 2019 © CC BY

Elvis Pacifier Bot - Ask Elvis, when you need a new pacifier

Young parents struggle against the continious pacifier disappearance. Elvis Bot assists you with ease, when the next pacifier is missing!

AdvancedFull instructions provided24 hours70

Things used in this project

Hardware components

Mindstorms EV3 Programming Brick / Kit
LEGO Mindstorms EV3 Programming Brick / Kit
×1
different pacifiers
different forms and shapes ;-)
×3
Echo Dot
Amazon Alexa Echo Dot
×1
AA Batteries
AA Batteries
6x rechargabel AA Batteries
×1
USB-A to Mini-USB Cable
USB-A to Mini-USB Cable
×1
MicroSD Module (Generic)
×1

Software apps and online services

Visual Studio Code Extension for Arduino
Microsoft Visual Studio Code Extension for Arduino
ev3dev
Alexa Voice Challange Setup

Story

Read more

Schematics

Large,Motor MediumMotor, TouchSensor and ColorSensor

Code

Release 1.0.1: Elvis Pacifier Bot

Python
Functional but still buggy at some points.
#!/usr/bin/env python3
from ev3dev2.motor import MediumMotor, LargeMotor, OUTPUT_A, OUTPUT_B, SpeedPercent, MoveTank
from ev3dev2.sensor import INPUT_4, INPUT_3
from ev3dev2.sensor.lego import ColorSensor, TouchSensor
from ev3dev2.led import Leds
from time import sleep
import os
import sys
import time
import logging
import threading
import json
from agt import AlexaGadget

# START ElvisSchnullerRoboter
# Version 1.0.1
# Adam A. Siwy for Alexa Voice Challenge 

DEBUGGERTIME = 1
GADGET_SPEED = 35

class ElvisSchnullerbot(AlexaGadget):

    # 0
    # Funcs and Constants for Elvis Movements
    # Temporary 1,5 x for rotation count <- good enough for the moment! 26.12.2019 12:06
    tempfaktor = 1.5
    # Stores Names and Amount of Pacifiers 6, 4, 2
    gadget_schnullergrabber = ["WHITE", "YELLOW", "BLUE"]
    # Calculates real rotations
    tempanzahl = len(gadget_schnullergrabber)*tempfaktor
    # Calculates next rotations TODO variable Names for '3'
    tempnext = (tempanzahl/3)/3

    # 1
    # LED Status
    def elvisStatus(self, tocolor):
        print("Elivs LED Status Change")
        self.gadget_leds.set_color('LEFT', tocolor)
        self.gadget_leds.set_color('RIGHT', tocolor)

    # 2
    # COLORSENSOR Feedback 
    # (not used at this point)
    def elvisSchnullerColor(self):
        print("Elivs ColorSensor Status Started")
        # return self.gadget_sensor.value()
        
    # 3
    # MOTOR Feedback
    # PARAMS: rotatenumber - gives int for amount of EV Motor rotations
    def elvisSchnullerRotate(self, rotatenumber):
        print("Elivs Motor Started")
        self.gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), rotatenumber)

    # 5
    # Calibrates Colors - finds the ~white~ (COLOR_WHITE = 6) brick on wheel, stops and rotates 1/3 to the next position
    def elvisCalibrate(self, calibratecolor):
        self.gadget_rotate.on( SpeedPercent(GADGET_SPEED/3) )
        while self.gadget_sensor.value() != calibratecolor:
            sleep(0.01)
        self.gadget_rotate.stop()
        #  TODO Calibrated Positon Savepoint calibrateted_position = gadget_rotate.position.value()
        sleep(0.25)
        self.elvisStatus('GREEN')
        self.gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), 1/3)
        # TODO Custom event to ALEXA with calibration completed

    # 7
    # Reveals parciviers - activates Elvis' tongue to spit out latest pacifier
    def elvisSpit(self):
        self.gadget_spit.on_for_rotations( SpeedPercent(GADGET_SPEED),3 )

    #8
    # TouchSensor State
    def elvisTongue(self):
        pressed = bool( self.gadget_tongue.is_pressed )
        return pressed
        
    # 9
    # calibrates tongue
    def elvisCalibrateTounge(self):

        if self.elvisTongue() != True:
            self.gadget_spit.on( SpeedPercent(GADGET_SPEED/3))
            while self.elvisTongue() == False:
                sleep(0.01)
            self.gadget_spit.stop()
            
            elvisgadget.elvisStatus('GREEN')

    # 10
    # Now The Tricky Part. Connecting to Amazon Echo Dot as Bluetoot Gadget
    # https://developer.amazon.com/de-DE/docs/alexa/alexa-gadgets-toolkit/features.html
    def __init__(self):
        super().__init__()
        self.gadget_leds = Leds()
        self.gadget_sensor = ColorSensor()
        self.gadget_sensor.mode = 'COL-COLOR'
        self.gadget_rotate = MediumMotor(OUTPUT_A)
        self.gadget_spit = LargeMotor(OUTPUT_B)
        self.gadget_tongue = TouchSensor()
        self.gadget_tongue.mode = 'TOUCH'

    def on_connected(self, device_addr):
        self.elvisStatus('YELLOW')
        # FIRST Calibrate to right position
        self.elvisCalibrate(6)
        self.elvisStatus('GREEN')

    def on_disconnected(self, device_addr):
        self.elvisStatus('YELLOW')
        sleep(0.25)
        self.elvisStatus('RED')
        sleep(0.25)    

    def on_custom_elvis_schnullerbot_control(self, directive):
        # Rotate to Schnuller #1 #2 #3
        #self.elvisSchnullerRotate( self.tempnext * -1)

        try:
            payload = json.loads(directive.payload.decode("utf-8"))
            print("Control payload: {}".format(payload), file=sys.stderr)
            control_type = payload["type"]
            if control_type == "move":
                self._nextPacifier(0,1)
                self._release(1)

            if control_type == "calibrate":
                if payload["farbcode"] == 2:
                    self._calibrate(2)
                elif payload["farbcode"] == 4:
                    self._calibrate(4)
                else:
                    self._calibrate(6)

            if control_type == "release":
                self._release(payload["frabcode"])
            

        except KeyError:
            print("Fehlende Parameter: {}".format(directive), file=sys.stderr)

    def _calibrate(self, directive):
        self.elvisCalibrate(6)

    def _release(self, directive):
        self.elvisSpit()

    #def _count(self, directive):

    def _nextPacifier(self, directive, times):
        self.elvisSchnullerRotate( self.tempnext * -1 * times)

    def _lastPacifier(self, directive, times):
        self.elvisSchnullerRotate( self.tempnext * times)
        
if __name__ == "__main__":
    elvisgadget = ElvisSchnullerbot()

    elvisgadget.elvisStatus('RED')
    elvisgadget.elvisCalibrateTounge()
    elvisgadget.elvisSpit()

    elvisgadget.elvisCalibrate(2)

    # Spit out all 3 pacifiers (!)
    # sleep(3)
    # elvisgadget._nextPacifier(0,1)
    # elvisgadget.elvisSpit()

    # sleep(3)
    # elvisgadget._nextPacifier(0,1)
    # elvisgadget.elvisSpit()

    # sleep(3)
    # elvisgadget._nextPacifier(0,1)
    # elvisgadget.elvisSpit()

    # --> THIS main() does the magic
    elvisgadget.main()

Version 0.4 Elvis Pacifier Bot on Echo Dot with Spit out Feature

Python
Now Elvis can find 3 colored pacifiers and spit them out separatly. Touch Sensor Calibration included
#!/usr/bin/env python3
from ev3dev2.motor import MediumMotor, LargeMotor, OUTPUT_A, OUTPUT_B, SpeedPercent, MoveTank
from ev3dev2.sensor import INPUT_4, INPUT_3
from ev3dev2.sensor.lego import ColorSensor, TouchSensor
from ev3dev2.led import Leds
from time import sleep
import os
import sys
import time
import logging
import threading
import json
from agt import AlexaGadget

# START ElvisSchnullerRoboter
# Version 0.4
# Adam A. Siwy for Alexa Voice Challenge 

DEBUGGERTIME = 1
GADGET_SPEED = 35

class ElvisSchnullerbot(AlexaGadget):

    # 0
    # Funcs and Constants for Elvis Movements
    # Temporary 1,5 x for rotation count <- good enough for the moment! 26.12.2019 12:06
    tempfaktor = 1.5
    # Stores Names and Amount of Pacifiers 6, 4, 2
    gadget_schnullergrabber = ["WHITE", "YELLOW", "BLUE"]
    # Calculates real rotations
    tempanzahl = len(gadget_schnullergrabber)*tempfaktor
    # Calculates next rotations TODO variable Names for '3'
    tempnext = (tempanzahl/3)/3

    # 1
    # LED Status
    def elvisStatus(self, tocolor):
        print("Elivs LED Status Change")
        self.gadget_leds.set_color('LEFT', tocolor)
        self.gadget_leds.set_color('RIGHT', tocolor)

    # 2
    # COLORSENSOR Feedback 
    # (not used at this point)
    def elvisSchnullerColor(self):
        print("Elivs ColorSensor Status Started")
        # return self.gadget_sensor.value()
        
    # 3
    # MOTOR Feedback
    # PARAMS: rotatenumber - gives int for amount of EV Motor rotations
    def elvisSchnullerRotate(self, rotatenumber):
        print("Elivs Motor Started")
        self.gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), rotatenumber)

    # 5
    # Calibrates Colors - finds the ~white~ (COLOR_WHITE = 6) brick on wheel, stops and rotates 1/3 to the next position
    def elvisCalibrate(self, calibratecolor):
        self.gadget_rotate.on( SpeedPercent(GADGET_SPEED/3) )
        while self.gadget_sensor.value() != calibratecolor:
            sleep(0.01)
        self.gadget_rotate.stop()
        #  TODO Calibrated Positon Savepoint calibrateted_position = gadget_rotate.position.value()
        sleep(0.25)
        self.elvisStatus('GREEN')
        self.gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), 1/3)
        # TODO Custom event to ALEXA with calibration completed

    # 7
    # Reveals parciviers - activates Elvis' tongue to spit out latest pacifier
    def elvisSpit(self):
        self.gadget_spit.on_for_rotations( SpeedPercent(GADGET_SPEED),3 )

    #8
    # TouchSensor State
    def elvisTongue(self):
        pressed = bool( self.gadget_tongue.is_pressed )
        return pressed
        
    # 9
    # calibrates tongue
    def elvisCalibrateTounge(self):
        if self.elvisTongue() != True:
            self.gadget_spit.on( SpeedPercent(GADGET_SPEED/3))
            while self.elvisTongue() == False:
                sleep(0.01)
            self.gadget_spit.stop()
            
            elvisgadget.elvisStatus('GREEN')

    # 10
    # Now The Tricky Part. Connecting to Amazon Echo Dot as Bluetoot Gadget
    # https://developer.amazon.com/de-DE/docs/alexa/alexa-gadgets-toolkit/features.html
    def __init__(self):
        super().__init__()
        self.gadget_leds = Leds()
        self.gadget_sensor = ColorSensor()
        self.gadget_sensor.mode = 'COL-COLOR'
        self.gadget_rotate = MediumMotor(OUTPUT_A)
        self.gadget_spit = LargeMotor(OUTPUT_B)
        self.gadget_tongue = TouchSensor()
        self.gadget_tongue.mode = 'TOUCH'

    def on_connected(self, device_addr):
        self.elvisStatus('YELLOW')
        # FIRST Calibrate to right position
        self.elvisCalibrate(6)
        self.elvisStatus('GREEN')

    def on_disconnected(self, device_addr):
        self.elvisStatus('YELLOW')
        sleep(0.25)
        self.elvisStatus('RED')
        sleep(0.25)    

    def on_custom_elvis_schnullerbot_control(self, directive):
        # Rotate to Schnuller #1 #2 #3
        self.elvisSchnullerRotate( self.tempnext * -1)

        try:
            payload = json.loads(directive.payload.decode("utf-8"))
            print("Control payload: {}".format(payload), file=sys.stderr)
            control_type = payload["type"]
            if control_type == "move":
                self._nextPacifier()

            if control_type == "calibrate":
                self._calibrate()

        except KeyError:
            print("Fehlende Parameter: {}".format(directive), file=sys.stderr)

    def _calibrate(self, directive):
        self.elvisCalibrate(6)

    #def _release(self, directive):

    #def _count(self, directive):

    def _nextPacifier(self, directive, times):
        self.elvisSchnullerRotate( self.tempnext * -1 * times)

    def _lastPacifier(self, directive, times):
        self.elvisSchnullerRotate( self.tempnext * times)
        
if __name__ == "__main__":
    elvisgadget = ElvisSchnullerbot()
    elvisgadget.elvisStatus('RED')
    elvisgadget.elvisCalibrateTounge()
    elvisgadget.elvisSpit()
    elvisgadget.elvisCalibrate(4)
    sleep(3)
    elvisgadget._nextPacifier(0,1)
    elvisgadget.elvisSpit()
    sleep(3)
    elvisgadget._nextPacifier(0,1)
    elvisgadget.elvisSpit()
    sleep(3)
    elvisgadget._nextPacifier(0,1)
    elvisgadget.elvisSpit()
    # --> THIS main() does the magic
    elvisgadget.main()

Version 0.3 Elvis Pacifier Bot connected to Echo Dot

Python
Functional Minimal Version of Elvis Pacifier Bot connecting to Echo Dot via ini
#!/usr/bin/env python3
from ev3dev2.motor import MediumMotor, OUTPUT_A, OUTPUT_B, SpeedPercent, MoveTank
from ev3dev2.sensor import INPUT_4
from ev3dev2.sensor.lego import ColorSensor
from ev3dev2.led import Leds
from time import sleep
import os
import sys
import time
import logging
import threading
import json
from agt import AlexaGadget

# START ElvisSchnullerRoboter
# Version 0.3
# Adam A. Siwy for Alexa Voice Challenge 

DEBUGGERTIME = 1
GADGET_SPEED = 35

class ElvisSchnullerbot(AlexaGadget):

    # 0
    # Funcs and Constants for Elvis Movements
    # Temporary 1,5 x for rotation count <- good enough for the moment! 26.12.2019 12:06
    tempfaktor = 1.5
    # Stores Names and Amount of Pacifiers
    gadget_schnullergrabber = ["Silikon", "Gelb", "Blau"]
    # Calculates real rotations
    tempanzahl = len(gadget_schnullergrabber)*tempfaktor
    # Calculates next rotations TODO variable Names for '3'
    tempnext = (tempanzahl/3)/3

    # 1
    # LED Status
    def elvisStatus(self, tocolor):
        print("Elivs LED Status Change")
        self.gadget_leds.set_color('LEFT', tocolor)
        self.gadget_leds.set_color('RIGHT', tocolor)

    # 2
    # COLORSENSOR Feedback 
    # (not used at this point)
    def elvisSchnullerColor(self):
        print("Elivs ColorSensor Status Started")
        # return self.gadget_sensor.value()
        
    # 3
    # MOTOR Feedback
    # PARAMS: rotatenumber - gives int for amount of EV Motor rotations
    def elvisSchnullerRotate(self, rotatenumber):
        print("Elivs Motor Started")
        self.gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), rotatenumber)

    # 5
    # Calibrates Colors - finds the ~white~ (COLOR_WHITE = 6) brick on wheel, stops and rotates 1/3 to the next position
    def elvisCalibrate(self):
        self.gadget_rotate.on( SpeedPercent(GADGET_SPEED/3) )
        while self.gadget_sensor.value() != 6:
            sleep(0.01)
        self.gadget_rotate.stop()
        #  TODO Calibrated Positon Savepoint calibrateted_position = gadget_rotate.position.value()
        sleep(0.25)
        self.elvisStatus('GREEN')
        self.gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), 1/3)
        # TODO Custom event to ALEXA with calibration completed

    # 6
    # Now The Tricky Part. Connecting to Amazon Echo Dot as Bluetoot Gadget
    # https://developer.amazon.com/de-DE/docs/alexa/alexa-gadgets-toolkit/features.html

    def __init__(self):
        super().__init__()
        self.gadget_leds = Leds()
        self.gadget_sensor = ColorSensor()
        self.gadget_sensor.mode = 'COL-COLOR'
        self.gadget_rotate = MediumMotor(OUTPUT_A)

    def on_connected(self, device_addr):
        self.elvisStatus('YELLOW')
        # FIRST Calibrate to right position
        self.elvisCalibrate()
        self.elvisStatus('GREEN')

    def on_disconnected(self, device_addr):
        self.elvisStatus('YELLOW')
        sleep(0.25)
        self.elvisStatus('RED')
        sleep(0.25)    

    def on_custom_elvis_schnullerbot_control(self, directive):
        # Rotate to Schnuller #1 #2 #3
        self.elvisSchnullerRotate( self.tempnext * -1)

        try:
            payload = json.loads(directive.payload.decode("utf-8"))
            print("Control payload: {}".format(payload), file=sys.stderr)
            control_type = payload["type"]
            if control_type == "move":
                self._nextPacifier()

            if control_type == "calibrate":
                self._calibrate()

        except KeyError:
            print("Fehlende Parameter: {}".format(directive), file=sys.stderr)

    def _calibrate(self, directive):
        self.elvisCalibrate()

    #def _release(self, directive):

    #def _count(self, directive):

    def _nextPacifier(self, directive):
        self.elvisSchnullerRotate( self.tempnext )

    def _lastPacifier(self, directive):
        self.elvisSchnullerRotate( self.tempnext * -1 )
        
if __name__ == "__main__":
    elvisgadget = ElvisSchnullerbot()
    elvisgadget.elvisStatus('RED')
    # --> THIS main() does the magic
    elvisgadget.main()

Version 0.2 Stand Alone ElvisBot on EV3

Python
This early part shows the stand-alone interaktion of Elvis PYTHON Code.
#!/usr/bin/env python3
from ev3dev2.motor import MediumMotor, OUTPUT_A, OUTPUT_B, SpeedPercent, MoveTank
from ev3dev2.sensor import INPUT_4
from ev3dev2.sensor.lego import ColorSensor
from ev3dev2.led import Leds
from time import sleep
import sys
import logging
from agt import AlexaGadget

# START ElvisSchnullerRoboter
# Version 0.2
# Adam A. Siwy for Alexa Voice Challenge 

DEBUGGERTIME = 1
GADGET_SPEED = 35

# 0
# Logging and Configuration Part

    # logging.basicConfig(level=logging.INFO, stream=sys.stdout, format='%(message)s')
    # logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))

# 1
# LED Status
gadget_leds = Leds()
def elvisStatus(tocolor):
    print("Elivs LED Status Change")
    gadget_leds.set_color('LEFT', tocolor)
    gadget_leds.set_color('RIGHT', tocolor)
    # sleep(debbugertime)

# 2
# COLORSENSOR Feedback
gadget_sensor = ColorSensor()
gadget_sensor.mode = 'COL-COLOR'
def elvisSchnullerColor():
    print("Elivs ColorSensor Status Started")
    # print(gadget_sensor.value())
    # sleep(debbugertime)

# 3
# MOTOR Feedback
# PARAMS: rotatenumber - gives int for amount of EV Motor rotations
gadget_rotate = MediumMotor(OUTPUT_A)
def elvisSchnullerRotate(rotatenumber):
    print("Elivs Motor Started")
    gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), rotatenumber)
    # sleep(debbugertime)

# 4
# Funcs for Elvis Movements
# TODO Calculate real rotation on list's Places 
# Temporary 1,5 x for rotation count <- good enough for the moment! 26.12.2019 12:06
tempfaktor = 1.5

# 5
# Calibrates Colors - finds the ~white~ (COLOR_WHITE = 6) brick on wheel, stops and rotates 1/3 to the next position
def elvisCalibrate():
    gadget_rotate.on( SpeedPercent(GADGET_SPEED/3) )
    while gadget_sensor.value() != 6:
        sleep(0.01)
    gadget_rotate.stop()
    #  TODO Calibrated Positon Savepoint calibrateted_position = gadget_rotate.position.value()
    sleep(0.25)
    elvisStatus('YELLOW')
    gadget_rotate.on_for_rotations(SpeedPercent(GADGET_SPEED), 1/3)
    # TODO Custom event to ALEXA with calibration completed

# Stores Names and Amount of Passifiers
gadget_schnullergrabber = ["Silikon", "Gelb", "Blau"]
# Calculates real rotations
tempanzahl = len(gadget_schnullergrabber)*tempfaktor
# Calculates next rotations TODO variable Names for '3'
tempnext = (tempanzahl/3)/3

elvisStatus('RED')
elvisCalibrate()
# elvisSchnullerColor()
elvisSchnullerRotate(tempnext*2)
# elvisSchnullerRotate(tempnext)
elvisStatus('GREEN')

# 6
# Now The Tricky Part. Connecting to Amazon Echo Dot as Bluetoot Gadget
# https://developer.amazon.com/de-DE/docs/alexa/alexa-gadgets-toolkit/features.html
class ElvisSchnullerbot(AlexaGadget):
    def __init__(self):
        super().__init__()
        # INIT

    def on_connected(self, device_addr):
        elvisStatus('GREEN')
        sleep(0.25)
        elvisStatus('YELLOW')
        sleep(0.25)

    def on_disconnected(self, device_addr):
        elvisStatus('RED')
        sleep(0.25)
        elvisStatus('YELLOW')
        sleep(0.25)    

    # TODO Directive to ALEXA SKILL CODE
    def on_custom_elvis_schnullerbot_control(self, directive):
        #

        # Calibrate

        # Rotate to Schnuller #1 #2 #3

        # TODO Whatever mir noch so einfällt

if __name__ == '__main__':
    gadget = ElvisSchnullerbot()
    gadget.main()   

# END Target Lines of code < 100! 99 26.12 12:23 ~ 96 26.12 21:29 ~ 84 26.12 21:40 ~ 106 26.12 22:12 (mit AGT)

SKILL JS: 0.2 index.js

JavaScript
Basic functionality with directive hacks
/*
 * Copyright 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * You may not use this file except in compliance with the terms and conditions 
 * set forth in the accompanying LICENSE.TXT file.
 *
 * THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY DISCLAIMS, WITH 
 * RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
*/

// This sample demonstrates sending directives to an Echo connected gadget from an Alexa skill
// using the Alexa Skills Kit SDK (v2). Please visit https://alexa.design/cookbook for additional
// examples on implementing slots, dialog management, session persistence, api calls, and more.

const Alexa = require('ask-sdk-core');
const Util = require('./util');
const Common = require('./common');

// The namespace of the custom directive to be sent by this skill
const NAMESPACE = 'Custom.Elvis.Schnullerbot';

// The name of the custom directive to be sent this skill
const NAME_CONTROL = 'control';

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle: async function(handlerInput) {

        let request = handlerInput.requestEnvelope;
        let { apiEndpoint, apiAccessToken } = request.context.System;
        let apiResponse = await Util.getConnectedEndpoints(apiEndpoint, apiAccessToken);
        if ((apiResponse.endpoints || []).length === 0) {
            return handlerInput.responseBuilder
            .speak(`<voice name="Hans"><prosody pitch="low">ELVIS ist gerade unterwegs oder ausgeschaltet.</prosody> Starte den Elvis Schnullerroboter und aktiviere Bluetooth.</voice>`)
            .getResponse();
        }

        // Store the gadget endpointId to be used in this skill session
        let endpointId = apiResponse.endpoints[0].endpointId || [];
        Util.putSessionAttribute(handlerInput, 'endpointId', endpointId);

        const speakOutput = `<voice name="Hans"><prosody pitch="low">Oh je, alle Schnuller sind verschwunden.</prosody> Ich bin ELVIS und helfe dir bei der Schnullersuche. Lass uns alle Schnuller finden! Ich kann Schnuller für dich aufbewahren und wieder ausspucken?</voice>`;
    
        
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(`<voice name="Hans">Ich kann Schnuller aufbewahren oder den Schnuller deiner Lieblingsfarbe ausspucken. Was möchtest du?</voice>`)
            .getResponse();
    }
};

// Add the speed value to the session attribute.
// This allows other intent handler to use the specified speed value
// without asking the user for input.
const SetSpeedIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'SetSpeedIntent';
    },
    handle: function (handlerInput) {

        // Bound speed to (1-100)
        let speed = Alexa.getSlotValue(handlerInput.requestEnvelope, 'Speed');
        speed = Math.max(1, Math.min(100, parseInt(speed)));
        Util.putSessionAttribute(handlerInput, 'speed', speed);

        const attributesManager = handlerInput.attributesManager;
        let endpointId = attributesManager.getSessionAttributes().endpointId || [];
        let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
            {
                type: 'release',
                farbcode: 6,
                duration: 'all',
                speed: 'normal'
            });

        return handlerInput.responseBuilder
            .speak(`<voice name="Hans">Ich kann Schnuller mit der Farbnummer ${speed} ausspucken.</voice>`)
            .reprompt(`<voice name="Hans">Möchtest du diesen Schnuller haben?</voice>`)
            .addDirective(directive)
            .getResponse();
    }
};

const CalibrateIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'CalibrateIntent';
    },
    handle: function (handlerInput) {
        
        const attributesManager = handlerInput.attributesManager;
        let endpointId = attributesManager.getSessionAttributes().endpointId || [];
        
        let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
            {
                type: 'calibrate',
                farbcode: 2,
                duration: 'all',
                speed: 'normal'
            });

        return handlerInput.responseBuilder
            .speak(`<voice name="Hans">Es macht Sinn das Schnullerrad gelegentlich zu kalibrieren. Auf geht's!</voice>`)
            .reprompt(`<voice name="Hans">Soll ich nochmal Kalibrieren?</voice>`)
            .addDirective(directive)
            .getResponse();
    }
};

// Construct and send a custom directive to the connected gadget with
// data from the MoveIntent request.
const MoveIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'MoveIntent';
    },
    handle: function (handlerInput) {
        const request = handlerInput.requestEnvelope;
        const direction = Alexa.getSlotValue(request, 'Direction');

        // Duration is optional, use default if not available
        const duration = Alexa.getSlotValue(request, 'Duration') || "2";

        // Get data from session attribute
        const attributesManager = handlerInput.attributesManager;
        const speed = attributesManager.getSessionAttributes().speed || "50";
        let endpointId = attributesManager.getSessionAttributes().endpointId || [];

        // Construct the directive with the payload containing the move parameters
        let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
            {
                type: 'move',
                direction: direction,
                duration: duration,
                speed: speed
            });

        const speechOutput = (direction === "brake")
            ?  "Applying brake"
            : `<voice name="Hans">${direction} ${duration} seconds at ${speed} percent speed</voice>`;

        return handlerInput.responseBuilder
            .speak(`<voice name="Hans">Schnuller wird ausgespuckt.</voice>`)
            .reprompt(`<voice name="Hans">Was kann ich noch für dich tun?</voice>`)
            .addDirective(directive)
            .getResponse();
    }
};

// Construct and send a custom directive to the connected gadget with data from
// the SetCommandIntent request.
const SetCommandIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'SetCommandIntent';
    },
    handle: function (handlerInput) {

        let command = Alexa.getSlotValue(handlerInput.requestEnvelope, 'Command');
        if (!command) {
            return handlerInput.responseBuilder
                .speak(`<voice name="Hans">Kannst du das bitte noch mal wiederholen?</voice>`)
                .reprompt(`<voice name="Hans">Was möchtest du tun?</voice>`).getResponse();
        }

        const attributesManager = handlerInput.attributesManager;
        let endpointId = attributesManager.getSessionAttributes().endpointId || [];
        let speed = attributesManager.getSessionAttributes().speed || "50";

        // Construct the directive with the payload containing the move parameters
        let directive = Util.build(endpointId, NAMESPACE, NAME_CONTROL,
            {
                type: 'command',
                command: command,
                speed: speed
            });

        return handlerInput.responseBuilder
            .speak(`<voice name="Hans"> Befehl ${command} aktivier</voice>`)
            .reprompt(`<voice name="Hans">awaiting command</voice>`)
            .addDirective(directive)
            .getResponse();
    }
};

// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(
        LaunchRequestHandler,
        SetSpeedIntentHandler,
        SetCommandIntentHandler,
        MoveIntentHandler,
        CalibrateIntentHandler,
        Common.HelpIntentHandler,
        Common.CancelAndStopIntentHandler,
        Common.SessionEndedRequestHandler,
        Common.IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
    )
    .addRequestInterceptors(Common.RequestInterceptor)
    .addErrorHandlers(
        Common.ErrorHandler,
    )
    .lambda();

SKILL JS: 0.1 index_elvisspeekaout.js

JavaScript
German conversation flow
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speakOutput = 'Oh je, alle Schnuller sind verschwunden. Ich bin ELVIS und helfe dir bei der Schnullersuche. Lass uns alle Schnuller finden! Möchtest du Schnuller suchen oder aufbewahren?';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt('Möchtest du Schnuller suchen oder aufbewahren?')
            .reprompt('Ich kann Schnuller aufbewahren oder mit deiner Hilfe auch finden. Was möchtest du?')
            .getResponse();
    }
};
const HelloWorldIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'Hello World!';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
            .getResponse();
    }
};

const SucheIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'SucheIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'Auf gehts. Wo sind alle Schnuller geblieben?';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt('Du musst mich bei der Suche unterstützen... ')
            .reprompt('Moment ich schaue mal, wie viele Schnuller aufbewahrt wurden.')
            .getResponse();
    }
};
const HelpIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'Ich kann Schnuller aufbewahren, Schnuller finden und sie dir ausspucken. Sage zum Beispiel Schnuller aufbewahren, wenn du neue Schnuller einlegen möchtest.';

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};
const CancelAndStopIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
                || Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
    },
    handle(handlerInput) {
        const speakOutput = 'Tschö mit Ö!';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .getResponse();
    }
};
const SessionEndedRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
    },
    handle(handlerInput) {
        // Any cleanup logic goes here.
        return handlerInput.responseBuilder.getResponse();
    }
};

// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
    },
    handle(handlerInput) {
        const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
        const speakOutput = `You just triggered ${intentName}`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
            .getResponse();
    }
};

// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
    canHandle() {
        return true;
    },
    handle(handlerInput, error) {
        console.log(`~~~~ Error handled: ${error.stack}`);
        const speakOutput = `Sorry, I had trouble doing what you asked. Please try again.`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};

// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(
        LaunchRequestHandler,
        HelloWorldIntentHandler,
        SucheIntentHandler,
     //   SortierenIntentHandler,
     //   AuswerfenIntentHandler,
        HelpIntentHandler,
        CancelAndStopIntentHandler,
        SessionEndedRequestHandler,
        IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
    )
    .addErrorHandlers(
        ErrorHandler,
    )
    .lambda();

Credits

Adam Siwy

Adam Siwy

1 project • 0 followers
Thanks to Marvin (our son), Christel (my girl), Oskar, and Grandparents.

Comments