This project comes from my first prototype of the thesis experiment- the water drop instrument.

I want to create a machine that can make cocktail when you speak to it.

The procedure will be really straightforward, but since now, it has consumed me a lot of days.

  1. Develop the voice control function (since now I’m using Alexa and Amazon web service)
  2. Use Alexa to control my Arduino and related pumps.
  3. Making bottles that can mix the liquid with pumps.
  4. Design the outlook for this machine.

For the first part, I spend 1 week on figuring out how the Alexa and AWS works. The logic will be like:

Alexa- AWS Alexa skill kit (recognize the command )- AWS Lambda (online server that can recognize what the command is asking for ) – AWS IOT (send processed command to my raspberry pi)

My Lambda code is here:

‘use strict’;

/* ———————– IoT Configuration ——————————– */

var config = {};

config.IOT_BROKER_ENDPOINT = “abo3i1ggjdy56.iot.us-east-1.amazonaws.com”.toLowerCase();

config.IOT_BROKER_REGION = “us-east-1”;

config.IOT_THING_NAME = “MyPi”;

// Load AWS SDK libraries
var AWS = require(‘aws-sdk’);

AWS.config.region = config.IOT_BROKER_REGION;

// Initialize client for IoT
var iotData = new AWS.IotData({endpoint: config.IOT_BROKER_ENDPOINT});

/* ——————– end: IoT Configuration —————————— */

 

/* ———— Helpers that build all of the responses ——————— */

function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {

return {
outputSpeech: {
type: ‘PlainText’,
text: output,
},
card: {
type: ‘Simple’,
title: `SessionSpeechlet – ${title}`,
content: `SessionSpeechlet – ${output}`,
},
reprompt: {
outputSpeech: {
type: ‘PlainText’,
text: repromptText,
},
},
shouldEndSession,
};

}

function buildResponse(sessionAttributes, speechletResponse) {

return {
version: ‘1.0’,
sessionAttributes,
response: speechletResponse,
};

}

/* ———- end: Helpers that build all of the responses —————— */

 

/* ———– Functions that control the skill’s behavior —————— */

function getWelcomeResponse(callback) {

// If we wanted to initialize the session to have some attributes we could add those here.
const sessionAttributes = {};
const cardTitle = ‘Welcome’;
const speechOutput = ‘Welcome,’ + ‘Please tell me what you want to drink’;
// If the user either does not reply to the welcome message or says something that is not understood, they will be prompted again with this text.
const repromptText = ‘Please tell me if you want anything to drink,’ + ‘like,’ + ‘I want a mojito’;
const shouldEndSession = false;

callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));

}

function handleSessionEndRequest(callback) {

const cardTitle = ‘Sold out’;
const speechOutput = ‘Do not get drunk. Have a nice day!’;
// Setting this to true ends the session and exits the skill.
const shouldEndSession = true;

callback({}, buildSpeechletResponse(cardTitle, speechOutput, null, shouldEndSession));

}

function createFavoriteRelayStatusAttributes(desiredDrink) {

return {desiredDrink,};

}

/**
* Sets the relay state in the session and prepares the speech to reply to the user.
*/
function getDrink(intent, session, callback) {

const cardTitle = intent.name;
const desiredDrinkSlot = intent.slots.Drinks;
var rum = 0;
var coke=0;
var gin=0;
var vodka=0;
var tonic=0;
var cointreau=0;
var pinappleJuice=0;
var coconutcream=0;
var lemonjuice=0;
var cranberryjuice=0;

let repromptText = ”;
let sessionAttributes = {};
const shouldEndSession = false;
let speechOutput = ”;

if (desiredDrinkSlot.value !== undefined) {

const desiredDrink = desiredDrinkSlot.value;
sessionAttributes = createFavoriteRelayStatusAttributes(desiredDrink);
speechOutput = “You have ordered ” + desiredDrink+ “. please stand by”;
repromptText = “The drink will be ready soon, move the bottle when the light turns red”;

/*
* Update AWS IoT
*/
// Determine relay postition within shadow
if (desiredDrink == ‘mojito’) {rum = 5, coke=0, vodka=0 ,tonic=5,cointreau=0,pinappleJuice=0,coconutcream=0,lemonjuice=0,cranberryjuice=0}
if (desiredDrink == ‘cubalibre’) {rum = 5, coke=5,vodka=0,tonic=0,cointreau=0,pinappleJuice=0,coconutcream=0,lemonjuice=0,cranberryjuice=0}
if (desiredDrink == ‘colada’) {rum = 1, coke=0,vodka=1,tonic=0,cointreau=0,pinappleJuice=3,coconutcream=1,lemonjuice=1,cranberryjuice=0}
if (desiredDrink == ‘longisland’) {rum = 1,coke=5,vodka=1,tonic=0,cointreau=0,pinappleJuice=0,coconutcream=0,lemonjuice=2,cranberryjuice=0}
if (desiredDrink == ‘cosmopolitan’) {rum =0,coke=0,vodka=0,tonic=0,cointreau=1,pinappleJuice=0,coconutcream=0,lemonjuice=1,cranberryjuice=2}
if (desiredDrink == ‘caprioska’) {rum = 5,coke=5,vodka=2, tonic=0,cointreau=0,pinappleJuice=0,coconutcream=0,lemonjuice=1,cranberryjuice=0}

var payloadObj={ “state”: { “desired”: { “rum”: rum, “coke”:coke,”vodka”:vodka,”tonic”:tonic,”cointreau”:cointreau,”pinappleJuice”:pinappleJuice,”coconutcream”:coconutcream,”lemonjuice”:lemonjuice,”cranberryjuice”:cranberryjuice} } };

//Prepare the parameters of the update call
var paramsUpdate = {

“thingName” : config.IOT_THING_NAME,
“payload” : JSON.stringify(payloadObj)

};

// Update IoT Device Shadow
iotData.updateThingShadow(paramsUpdate, function(err, data) {

if (err){
console.log(err); // Handle any errors
}
else {
console.log(data);
// if (desiredDrink == ‘Mojito’) {
// console.log(“notchange”);
// }
}

});

}
else {

speechOutput = “sorry I didn’t hear you clearly. can you say it again?”;
repromptText = “Maybe it’s too loud here, do you mind to come back later?”;

}

callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));

}

function getlist(intent, session, callback) {

const desiredDrinkSlot = intent.slots.list;

const repromptText = null;
const sessionAttributes = {};
let shouldEndSession = false;
let speechOutput = ”;

if (desiredDrinkSlot) {
speechOutput = “I don’t know many recipies, but here is what I know: ” + “mojito;”+”cubalibre;”+”colada;”+”longisland;”+”cosmopolitan;”+”caprioska;”;

}

else {
speechOutput = “I don’t know your question, you can ask” + “how many recipes do you know”;
}

// Setting repromptText to null signifies that we do not want to reprompt the user.
// If the user does not respond or says something that is not understood, the session
// will end.
callback(sessionAttributes, buildSpeechletResponse(intent.name, speechOutput, repromptText, shouldEndSession));

}

/* ——— end: Functions that control the skill’s behavior ————— */

 

/* —————————– Events ————————————- */

/**
* Called when the session starts.
*/
function onSessionStarted(sessionStartedRequest, session) {
console.log(`onSessionStarted requestId=${sessionStartedRequest.requestId}, sessionId=${session.sessionId}`);
}

/**
* Called when the user launches the skill without specifying what they want.
*/
function onLaunch(launchRequest, session, callback) {

console.log(`onLaunch requestId=${launchRequest.requestId}, sessionId=${session.sessionId}`);

// Dispatch to your skill’s launch.
getWelcomeResponse(callback);

}

/**
* Called when the user specifies an intent for this skill.
*/
function onIntent(intentRequest, session, callback) {

console.log(`onIntent requestId=${intentRequest.requestId}, sessionId=${session.sessionId}`);

const intent = intentRequest.intent;
const intentName = intentRequest.intent.name;

// Dispatch to your skill’s intent handlers
if (intentName === ‘Order’) {getDrink(intent, session, callback);}
else if (intentName === ‘Ask’) {getlist(intent, session, callback);}
else if (intentName === ‘AMAZON.HelpIntent’) {getWelcomeResponse(callback);}
else if (intentName === ‘AMAZON.StopIntent’ || intentName === ‘AMAZON.CancelIntent’) {handleSessionEndRequest(callback);}
else {throw new Error(‘Invalid intent’);}

}

/**
* Called when the user ends the session.
* Is not called when the skill returns shouldEndSession=true.
*/
function onSessionEnded(sessionEndedRequest, session) {

console.log(`onSessionEnded requestId=${sessionEndedRequest.requestId}, sessionId=${session.sessionId}`);
// Add cleanup logic here

}

/* ————————— end: Events ———————————- */

 

/* ————————– Main handler ———————————- */

// Route the incoming request based on type (LaunchRequest, IntentRequest, etc.) The JSON body of the request is provided in the event parameter.
exports.handler = (event, context, callback) => {

try {

console.log(`event.session.application.applicationId=${event.session.application.applicationId}`);

/**
* Uncomment this if statement and populate with your skill’s application ID to
* prevent someone else from configuring a skill that sends requests to this function.
*/
/*
if (event.session.application.applicationId !== ‘amzn1.echo-sdk-ams.app.[unique-value-here]’) {
callback(‘Invalid Application ID’);l
}
*/

if (event.session.new) {
onSessionStarted({ requestId: event.request.requestId }, event.session);
}

if (event.request.type === ‘LaunchRequest’) {
onLaunch(event.request,
event.session,
(sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
}
else if (event.request.type === ‘IntentRequest’) {
onIntent(event.request,
event.session,
(sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
}
else if (event.request.type === ‘SessionEndedRequest’) {
onSessionEnded(event.request, event.session);
callback();
}

}
catch (err) {callback(err);}

};

For the IOT part, I’m using IOT Shadow to make a place to receive the message from Lambda then send to my raspberry pi.

To be continue/