Monday, November 21, 2016

Amazon Dot: Let's Turn Something On

Last post <link> we got data all the way from a Raspberry Pi up to Amazon and back to the Dot and it was able to say,  "The temperature is 79 degrees, " and we were excited. What, you got an error? How the heck do you troubleshoot this thing?

Fortunately, there actually is a way of doing this, even with the fact that they pass complex JSON strings around to carry data from one subsystem to another. The screen you got last time:


has the json string you need to test directly into the Lamba function we created in a previous post <link>. Simply copy the entire 'Lambda Request' and then paste it into the test screen for the Lambda function. I know this description leaves a lot of questions, so let's look a bit closer:

First copy the entire text from the Lambda Request shown above, then go to the Lambda Management Console:


Then select Actions -> Configure Test Event


They don't have a blank test event or something really close to what you need, so just chooses the first one 'GetNextFact' and replace ALL the text inside the edit box with what you saved above. This will replace the default with what you want. Save it; you have to scroll down on the page to get the save button to show.

Now, you're ready to actually feed the JSON to your Lambda function. You can now press the 'Test' button and see what happens. I can't really be much help on specific errors because I can't know in advance what kinds of problems you'll hit, but there should be enough information to get you started.

You can also edit the test event you just created to test other things, I used one test event to test most of my information requests; things like 'temperature', 'rainfall', by just changing the intent name inside the JSON string.

Now you have some hope of being able to debug this thing, so let's walk through adding control of something from the Dot. This time I'm going to start with the voice interaction and work down to the Raspberry Pi at my house instead of the other way around. The reason for doing it this way is because we now have the basic infrastructure in place and adding things is easier from the Dot back to the Pi. We'll start at the Alexa Interaction Model which looks like this:


There needs to be an intent added and I'm using the one I added first to my setup. The intent is ControlEastPatioLight and it has two 'slots', on and off, so I named the type onOff. Very clever of me. Just below the intent window, I added a new slot called (duh) onOff:


And the contents of the slot is:


What's happening is that Alexa doesn't send the actual text that is spoken, it sends intents which may contain enumerations to the Lambda function. Enumerations are simply things that can be chosen from a pre-defined list. In this case the two slot values I chose were 'on' and 'off'. I could have used 0 and 1, or Fred and Mary, it doesn't matter what they are, what matters is that they make sense to you because you have to use them later in actually controlling your devices.

Now, for the utterances, I used the simplest ones I could think of:


I highlighted the two above that I use for the light. The '{state}' refers back to the intent I created above and will be replaced with either on or off from the slot definition based on what you actually say to the Dot. Alexa actually parses through the sound and inserts its best guess about you said into the JSON string that will be sent to the Lambda function. So, save this work and go test it in the test screen:


Your Lambda Response will be an error because you haven't added the code yet, but the test generated the Lambda Request you'll need to test the new capability you're adding, so copy it out of the Request window and go over to the Lambda function and paste it into the test configuration before it gets lost:


It's not ready to test yet since we don't have any code to support it, but save it now for uses later. We're going to add code now to support the new intent. In the code window which you will see after you save the  event template you want to add the code. The window is small and hard to use, but you can scroll all the way down to the bottom of the little code window and there will be a button to expand it to full screen, I use this to edit since there just isn't enough visible to get proper context for changes:


The button is in the image above over on the right; I put the cursor there so you could find it. I searched for this for about 20 minutes the first time.

Add a couple of lines into the intent handling to get you to a routine that will format the mqtt request that the AWSIoT needs:


I highlighted the lines in the picture above. Now you need the code to create the mqtt request:


It just barely fit on the screen. Since you've already done this once, it should be easily recognized with the difference being the payload object and a call to updateThingShadow(). I think it's pretty intuitive what is going on here. A JSON fragment string is created with the content of the slot created above and passed off to the shadow as a 'desired' item. Now you're starting to understand why I described the operation of a 'Device Shadow' so carefully back a few posts ago <link>; the interaction of the shadow and the code on the Raspberry Pi is very important to getting this stuff working.  I know how big a pain in the bottom it is to read from a post and try to type it in, so here's the code above you can copy and paste with:

function controlEastPatioLight (intent, session, callback) {
    var repromptText = null;
    var sessionAttributes = {};
    var shouldEndSession = false;
    var speechOutput = "";
    var newstate = intent.slots.state.value;

    //Set the light to 0 to turn it off
    var payloadObj={ "state":
                        { "desired":
                            {"eastPatioLight":newstate}
                        }
                 };
    //Prepare the parameters of the update call
    var paramsUpdate = {
        "thingName" : config.IOT_THING_NAME,
        "payload" : JSON.stringify(payloadObj)
    };

    //Update Device Shadow
    iotData.updateThingShadow(paramsUpdate, function(err, data) {
        if (err){
           console.log(err, err.stack); // an error occurred
        }
        else {
            speechOutput = "The east patio light has been turned " + newstate + "!";
            console.log(data);
            callback(sessionAttributes,buildSpeechletResponse(intent.name, speechOutput, repromptText, shouldEndSession));
        }    
    });
}


Be sure to change the various names to something you'll understand later.

Once again, we don't actually send a command to the Pi to change something, we send a desire. That desire is pulled off the mqtt queue and used to do the actual change, then we publish back the new state. But, if you get confused, go back and read the explanation I linked to in the last paragraph.

That's it for right now, the next post has a bunch of code in it for the raspberry pi to get the desire and do something about it. It's going to get confusing to both read and for me to write, so next post.

Have fun, and feel free to work ahead, you can actually see the desire created and sent over in AWSIot if you want to.

The next post in this series is here <link>

4 comments:

  1. Wow. I just read through all the posts on this and now I'm wondering if I want to go through all this to get the Dot working or just send it back? It looks like a pretty steep learning curve.
    More importantly however is the reliance on Amazon to continue to keep providing these services (which seem critical to the Dot's operation) going forward? The Dot could just become a $40.00 hockey puck if they don't. As you say it's a set of services not really open source.
    What happens when your internet goes down. Alexa? Alexa? Alexa?
    Don't get me wrong. I bought the little hockey puck and as soon as it arrives I going to use your GREAT blogs to get it going......I just wonder about it continuing down the road?
    We run the Wemo's without Belkin. I run my RadioThermostats of America without them, but Alexa without Amazon? That's another thing again.
    Thanks again Dave for excellent blogging.
    Glenn.

    ReplyDelete
    Replies
    1. If you go all the way back to the first blog I did on this little device, you'll see that I had exactly the same opinion. There were several times I wanted to throw it over the fence at the coyotes and then run over it with my 9000 pound tractor.

      But, once I got the first thing working, the whole architecture came into focus and I saw how I could use it. The second thing took about an hour to incorporate, the third less. Now, I can put something in just to see it work for fun. Granted, I was totally frustrated at the silly way they implemented it and the hoops I had to jump through to get it working at all.

      As for the internet, if it goes down, the Dot is a total hockey puck. If there's a slow down or heavy traffic, it's an annoying piece of plastic that can make you scream. However these cases are rare and only seem to happen about dinner time. I don't have a clue why that is, it just seems that way.

      I use it all the time to check the temperature, weather forecast for tomorrow, turn off the various lights, check the garage doors before bed, and will use it more when I have the time to incorporate the pool, water heater and such. Those things have taken a back seat to some other projects that jumped out and bit me the last couple of weeks.

      Don't get me wrong, I still use my web interface a lot. I use it to check on the house while I'm away, it sends me email about the state of the various device from time to time, and I'll still be expanding it a lot over time now that I can do it reasonably easily.

      The Dot is just another tool for controlling the house that I don't have to carry around. I currently have one in the bedroom and one in a place that serves my kitchen and recliner. I want one for the guest bedroom, the garage, two of the patios, etc. Basically, I want to be able to voice control all the devices from anywhere I happen to be around the house. I'll use the cell phone and web when I'm away from the house.

      I'll get the last post up here in a day or two ... or three, It's the one where I show the code for the Pi and how I handle the data that Alexa sends and should give folk enough information to do their own thing. I've been up to my neck in silly things breaking around the house that have gotten in the way of that piece. I also plan on an errata page where I'll mention stuff that I encountered along the way that could help other folk past some of the silly problems I ran into. That page will grow as I get more experience and learn some of the other pitfalls.

      Heck, this was almost a blog post all by itself.

      Delete
  2. Hey,
    first of all thank you for your nice Blog entry. Is there a way to send me the Files you generated ?. Im Working on the same kind of Project and it would be very nice if you could sent it to me. (I´m german sorry for my bad english)

    ReplyDelete
    Replies
    1. Nothing I do is secret, so yes I can send you what I have, or maybe I should put it up on github so you can get to it from there. Actually, github is probably the best solution, but a LOT of the work is out on Amazon and I'll have to get it from there and copy it to github.

      Let me know if you want something specific and I'll email it to you.

      Delete