Amazon Alexa?

Just wondering if anyone has managed to control an imp directly from an Amazon Alexa device? I saw this video that claiming that “Using the Alexa Skills Kit (ASK) to control an electric imp is stupidly trivial and deliciously fun”.https://www.youtube.com/watch?v=PwMYEoho8wU
Aron’s idea of trivial is not the same as mine given the experience I’ve had trying to follow the Amazon walkthrough (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/steps-to-create-a-smart-home-skill).

It would be really great to have an imp agent handle Alexa voice commands, I’m surprised this hasn’t already been covered here. I’ve noticed the provision of the AWSRequestV4 library but I’m just not understanding how this all fits together. Where’s Aron when you need him? :slight_smile:

He’s around I’m sure :slight_smile:

I got my Dot a couple days ago and while I didn’t write any custom skill yet like Aron did, last night it took me about 10 minutes to get Alexa to trigger LEDs on my imp via IFTTT. Not as cool as using a custom skill but pretty easy to do.

If anyone is interested in details, I can provide them but in a nutshell, I used IFTTT with Alexa “Say a specific phrase” trigger to make a web request to the Maker channel which calls an endpoint in my agent code. Very simple integration that unfortunately doesn’t send back any content that Alexa can say but it works.

@merlin13

would like to see your code…

For some arcane reason, IFTTT isn’t available to Alexa in the UK so that simple method won’t work for me. There is, however, a walk-through guide (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/steps-to-create-a-smart-home-skill) that pretty much delivers the goods. It just needs an http request to the agent to be inserted in function “callDeviceCloud”. The walk-through creates a skill adaptor for Smart Home integration rather than a general skill which suited me better, but once you get into writing skills it’s all pretty similar.

I played around and did a quick&dirty integration with a general skill.

i like how amazon implemented to Test the Skill.

thanks async agent to device communication i have basic code running to get/do different things with alexa+imp.

Alexa, ask Imp about my indoor/outdoor temperature (humidity)
Alexa, tell imp to open/close the Garage Door
Alexa, tell imp to switch the heater on/off

after cleaning the code a little bit and giving a few credits i could put it to my github repository.

That sounds very cool Chrischi. do you have some code running on the Lambda compute service that talks to your imp agent or is there a direct communication? I found it very hard working with the online IDE for Lambda so I ended up trimming down the handler function to the point where it just passed entire events to the imp agent which does all the parsing. I didn’t get around to finding out if there was any way of bypassing the handler altogether and passing the event out direct to my agent.

i use the lambda service to talk with the agent and passing the user intent to it.

i think you can’t get a direct communication between the agent and echo

@Chrischi Can you post the agent code, please? I have no idea how the agent is to handle the request from the Lambda function.

`
//agent code
const TIMEOUT = 15; // close hanging async requests after 15 seconds
responses <- {};

// create unique keys for responses table
function generateKey() {
local key = math.rand();
while (key in responses) key = math.rand();
return key.tostring();
}

function responseWatchdog() {
imp.wakeup(1, responseWatchdog);

local t = time();
foreach(key, response in responses) {
    if (t - response.t > TIMEOUT) {
        responses[key].resp.send(408, "Agent Timeout");
        delete responses[key];
    }
}

} responseWatchdog();

device.on(“asyncdata”, function(data) {
if (!(data.k in responses)) {
server.log(format(“response %s already timed-out.”, data.t));
return;
}
responses[data.k].resp.send(200, http.jsonencode(data.d));
delete responses[data.k];
});

http.onrequest(function(req, resp) {
try {
local path = req.path.tolower();

    // if user sends response to /asyncdata/...
    if (path.find("/alexa") == 0) {
        // generate key, and store the response object
        local responseKey = generateKey();
        responses[responseKey] <- { resp = resp, t = time() };
        
        // this is what we're asking the agent for
        local requestedData = "unknown";
        
        if (path == "/alexa/temp" || path == "/alexa/temp/") requestedData = "temp";
        else if (path == "/alexa/outtemp" || path == "/alexa/outtemp/") requestedData = "outtemp";
        else if (path == "/alexa/hum" || path == "/alexa/hum/") requestedData = "hum";

        // request asyncdata from the device:
            // k is the response key - we'll use this in the response
            // r is what we're looking for from the device
            // d is an object that will store the data
        device.send("alexa", { k = responseKey, r = requestedData, d = null });
        return;
    }
    if ("garage" in req.query) {
          device.send("garage", req.query["garage"]);
          resp.send(204, html);
      }
      else {
    // if they send a response anywhere else, just send a 200 back
    resp.send(404, "Unknown");
      }
} catch(ex) {
    // if there was an error, send a 500 back
    resp.send(500, "Internal Agent Error: " + ex);
}

});
`

Quick & Dirty. Don’t know from where i got the async code.
So credits go to some unknown guy.