Stack Overflow: A New Way for Developers to Get Support for Alexa

Now you can find Alexa-specific tags and topics in the AWS Collective on Stack Overflow. Ask questions and get help from badged experts and the Alexa developer community!

question

MPCPRO avatar image
MPCPRO asked

Getting alexa to read JSON (Temperature and Humidity from arduino uno)

Hey guys.

I am really new into programming but I am trying to find a way so I can ask alexa "TemperatureHumidity" etc. I followed mostly this guide here:

https://www.hackster.io/44560/amazon-echo-read-temperature-and-humidity-from-sensor-0d9b73

But he used PHP to post his json information while my Arduino Uno with Ethernetshield is posting my temperature and humidity in json only. (Check it out here: http://mpconline.tk:1470 )

Example (incase my arduino is offline:

{,"temperature":"17.00","humidity":"33.00"}

I copied his Node.js 6.10 code to my lambda coding, but I am trying to find a way to modify it to read the json from my arduino uno. The only thing I can see I have to change is the host , path and port (which I did). Though I am still unable to get Alexa to get anything from my site. Something about:

"The remote endpoint could not be called, or the response it returned was invalid."

So I was wondering if anyone couild go through the example code I used to see if there's anything obvious I should have changed?

'use strict';


/**
 * This sample demonstrates a simple skill built with the Amazon Alexa Skills Kit.
 * The Intent Schema, Custom Slots, and Sample Utterances for this skill, as well as
 * testing instructions are located at http://amzn.to/1LzFrj6
 *
 * For additional samples, visit the Alexa Skills Kit Getting Started guide at
 * http://amzn.to/1LGWsLG
 */


var http = require('http');


// --------------- 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: shouldEndSession
    };
}


function buildResponse(sessionAttributes, speechletResponse) {
    return {
        version: '1.0',
        sessionAttributes,
        response: speechletResponse,
    };
}




// --------------- 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 to P H P o C. How can I help you?"
    // 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 = "How can I help you?";
    const shouldEndSession = false;


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


function handleSessionEndRequest(callback) {
    const cardTitle = 'Session Ended';
    const speechOutput = 'Thank you for trying the Alexa Skills Kit sample. 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 createTemperatureAttributes(temperature) {
    return {
        temperature: temperature
    };
}


/**
 * Read temperature in the session and prepares the speech to reply to the user.
 */
function readTemperatureInSession(intent, session, callback) {
    const cardTitle = intent.name;
    let repromptText = '';
    let sessionAttributes = {};
    const shouldEndSession = true;
    let speechOutput = '';
	var body = '';


	//Update 
	var httpPromise = new Promise( function(resolve,reject){
		http.get({
			host: '192.168.1.207',
			path: '',
			port: '1470'
		}, function(response) {
			// Continuously update stream with data
			response.on('data', function(d) {
				body += d;
			});
			response.on('end', function() {
				// Data reception is done, do whatever with it!
				console.log(body);
				resolve('Done Sending');
			});
		});
	});
	httpPromise.then(
		function(data) {
			var info = JSON.parse(body);
			console.log('Function called succesfully:', data);
			sessionAttributes = createTemperatureAttributes(info.temperature);
			speechOutput = "Temperature is " + info.temperature + " degree Celsius. Humidity is " + info.humidity + " percent";
			repromptText = "Temperature is " + info.temperature + " degree Celsius. Humidity is " + info.humidity + " percent";
			console.log(speechOutput);
			callback(sessionAttributes,buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
		},
		function(err) {
			console.log('An error occurred:', err);
		}
	);
}


// --------------- 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 === 'TemperatureHumidity') {
        readTemperatureInSession(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
}




// --------------- 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) => {
    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]') {
             context.fail("Invalid Application ID");
        }
        */


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


        if (event.request.type === 'LaunchRequest') {
            onLaunch(event.request,
                event.session,
                function callback(sessionAttributes, speechletResponse) {
					context.succeed(buildResponse(sessionAttributes, speechletResponse));
				});
        } else if (event.request.type === 'IntentRequest') {
            onIntent(event.request,
                event.session,
                function callback(sessionAttributes, speechletResponse) {
					context.succeed(buildResponse(sessionAttributes, speechletResponse));
				});
        } else if (event.request.type === 'SessionEndedRequest') {
            onSessionEnded(event.request, event.session);
            context.succeed();
        }
    } catch (e) {
        context.fail("Exception: " + e);
    }
};

If you also need my arduino json code part: (t is the live temperature reading, while h is the live humidity reading).

            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: application/json");  // JSON response type
            client.println("Connection: close");               // close connection after response
            client.println();
            // open JSON
            client.print("{");
            // temperature
            client.print(",\"temperature\":\"");
            client.print(t);
            client.print("\"");
            // humidity
            client.print(",\"humidity\":\"");
            client.print(h);
            client.print("\"");
            // close json
            client.println("}");


My Intent Schema and Sample Utterances:

{
  "intents": [
    {
      "intent": "TemperatureHumidity"
    }
  ]
}
TemperatureHumidity tell me temperature and humidity
TemperatureHumidity tell me current temperature and humidity
alexa smart homethermostat
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

davorin avatar image
davorin answered

Alexa only allows connections to HTTPS port 443 with a valid SSL certificate...

Even for local network connections like getting a camera feed from a Raspberry Pi requires this.

10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

MPCPRO avatar image
MPCPRO answered

So, I gotta find a way to get my arduino to post its info to another third party that has a valid SSL Certificate, which then alexa can use?

1 comment
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Tsuneki@Amazon avatar image Tsuneki@Amazon commented ·

Hi MPCPRO,

Please check SSL options here for details.

0 Likes 0 ·