commit e5ade7a70cfdf1b9ce7ae9e7f134ccaadaad2cca Author: Karl Date: Mon Nov 28 22:09:45 2016 +0000 First commit diff --git a/AlexaSkill b/AlexaSkill new file mode 100644 index 0000000..f9804e4 --- /dev/null +++ b/AlexaSkill @@ -0,0 +1,175 @@ +// Alexa SDK for JavaScript v1.0.00 +// Copyright (c) 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. Use is subject to license terms. +'use strict'; +function AlexaSkill(appId) { + this._appId = appId; +} + +AlexaSkill.prototype.requestHandlers = { + LaunchRequest: function (event, context, response) { + this.eventHandlers.onLaunch.call(this, event.request, event.session, response); + }, + + IntentRequest: function (event, context, response) { + this.eventHandlers.onIntent.call(this, event.request, event.session, response); + }, + + SessionEndedRequest: function (event, context) { + this.eventHandlers.onSessionEnded(event.request, event.session); + context.succeed(); + } +}; + +/** + * Override any of the eventHandlers as needed + */ +AlexaSkill.prototype.eventHandlers = { + /** + * Called when the session starts. + * Subclasses could have overriden this function to open any necessary resources. + */ + onSessionStarted: function (sessionStartedRequest, session) { + }, + + /** + * Called when the user launches the skill without specifying what they want. + * The subclass must override this function and provide feedback to the user. + */ + onLaunch: function (launchRequest, session, response) { + throw "onLaunch should be overriden by subclass"; + }, + + /** + * Called when the user specifies an intent. + */ + onIntent: function (intentRequest, session, response) { + var intent = intentRequest.intent, + intentName = intentRequest.intent.name, + intentHandler = this.intentHandlers[intentName]; + if (intentHandler) { + console.log('dispatch intent = ' + intentName); + intentHandler.call(this, intent, session, response); + } else { + throw 'Unsupported intent = ' + intentName; + } + }, + + /** + * Called when the user ends the session. + * Subclasses could have overriden this function to close any open resources. + */ + onSessionEnded: function (sessionEndedRequest, session) { + } +}; + +/** + * Subclasses should override the intentHandlers with the functions to handle specific intents. + */ +AlexaSkill.prototype.intentHandlers = {}; + +AlexaSkill.prototype.execute = function (event, context) { + try { + console.log("session applicationId: " + event.session.application.applicationId); + + // Validate that this request originated from authorized source. + if (this._appId && event.session.application.applicationId !== this._appId) { + console.log("The applicationIds don't match : " + event.session.application.applicationId + " and " + + this._appId); + throw "Invalid applicationId"; + } + + if (!event.session.attributes) { + event.session.attributes = {}; + } + + if (event.session.new) { + this.eventHandlers.onSessionStarted(event.request, event.session); + } + + // Route the request to the proper handler which may have been overriden. + var requestHandler = this.requestHandlers[event.request.type]; + requestHandler.call(this, event, context, new Response(context, event.session)); + } catch (e) { + console.log("Unexpected exception " + e); + context.fail(e); + } +}; + +var Response = function (context, session) { + this._context = context; + this._session = session; +}; + +Response.prototype = (function () { + var buildSpeechletResponse = function (options) { + var alexaResponse = { + outputSpeech: { + type: 'PlainText', + text: options.output + }, + shouldEndSession: options.shouldEndSession + }; + if (options.reprompt) { + alexaResponse.reprompt = { + outputSpeech: { + type: 'PlainText', + text: options.reprompt + } + }; + } + if (options.cardTitle && options.cardContent) { + alexaResponse.card = { + type: "Simple", + title: options.cardTitle, + content: options.cardContent + }; + } + var returnResult = { + version: '1.0', + response: alexaResponse + }; + if (options.session && options.session.attributes) { + returnResult.sessionAttributes = options.session.attributes; + } + return returnResult; + }; + + return { + tell: function (speechOutput) { + this._context.succeed(buildSpeechletResponse({ + session: this._session, + output: speechOutput, + shouldEndSession: true + })); + }, + tellWithCard: function (speechOutput, cardTitle, cardContent) { + this._context.succeed(buildSpeechletResponse({ + session: this._session, + output: speechOutput, + cardTitle: cardTitle, + cardContent: cardContent, + shouldEndSession: true + })); + }, + ask: function (speechOutput, repromptSpeech) { + this._context.succeed(buildSpeechletResponse({ + session: this._session, + output: speechOutput, + reprompt: repromptSpeech, + shouldEndSession: false + })); + }, + askWithCard: function (speechOutput, repromptSpeech, cardTitle, cardContent) { + this._context.succeed(buildSpeechletResponse({ + session: this._session, + output: speechOutput, + reprompt: repromptSpeech, + cardTitle: cardTitle, + cardContent: cardContent, + shouldEndSession: false + })); + } + }; +})(); + +module.exports = AlexaSkill; diff --git a/IntentSchema b/IntentSchema new file mode 100644 index 0000000..98876fb --- /dev/null +++ b/IntentSchema @@ -0,0 +1,13 @@ +{ + "intents": [ + { + "intent": "desk", + "slots": [ + { + "name": "Control", + "type": "Control_List" + } + ] + } + ] +} \ No newline at end of file diff --git a/SampleUtterances b/SampleUtterances new file mode 100644 index 0000000..ce1f62c --- /dev/null +++ b/SampleUtterances @@ -0,0 +1,6 @@ +desk to turn {Control} +desk can you turn {Control} +desk to turn {Control} please +desk {Control} +desk to turn the {Control} +desk to {Control} \ No newline at end of file diff --git a/index b/index new file mode 100644 index 0000000..1c44cf8 --- /dev/null +++ b/index @@ -0,0 +1,90 @@ +var http = require('http'); // if going through a proxy that uses SSL change to "require('https');" + +// Your external IP. Alexa can only access publically-accessible IPs. No LAN access unfortunately. +// In my case I had to move receiver to DMZ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +var local_ip = 'home.k-world.me.uk'; +var local_port = '8088'; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * App ID for the skill + */ + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +var APP_ID = "amzn1.ask.skill.8f9502ec-5452-4c18-a8e5-6f2aed86d676"; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** +* The AlexaSkill prototype and helper functions + */ +var AlexaSkill = require('./AlexaSkill'); + +var DTVControl = function () { + AlexaSkill.call(this, APP_ID); +}; + + +// Extend AlexaSkill +DTVControl.prototype = Object.create(AlexaSkill.prototype); +DTVControl.prototype.constructor = DTVControl; + +//Ignore Certificate errors if using HTTPS communication +process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + +DTVControl.prototype.intentHandlers = { + desk: function (intent, session, response) { + + //No matter what she wants to tell you her opinion. + + function satisfyAlexa() { + response.tell("Desk Updated"); + }; + + // Obtain User Intent + switch(intent.slots.Control.value) { + + // List of triggers and URL to goto + case "red": + path = '/DeskControl/red.php'; + break; + + case "blue": + path = '/DeskControl/blue.php'; + break; + + case "green": + path = '/DeskControl/green.php'; + break; + + case "off": + path = '/DeskControl/off.php'; + break; + + + + default: + + response.tell("Sorry, I didnt understand that desk request."); + break; + + + } + var options = { + host: local_ip, + port: local_port, // default port for webserver + path: '' + path, // Modify if path is prefixed + method: 'POST' //, //(remove first comment slashes if using the "auth" option below) + // auth: 'username:password' // this is used if going through authenticated proxy (this is BASIC AUTH) + }; + var req = http.request(options, satisfyAlexa); + req.end(); + } +} + + +exports.handler = function (event, context) { + + var dtvControl = new DTVControl(); + dtvControl.execute(event, context); + +}; diff --git a/index.zip b/index.zip new file mode 100644 index 0000000..e103102 Binary files /dev/null and b/index.zip differ