Even eaiser now to send sms, email, activate wemo, and a host of other goodies

IFTTT just announced a “maker channel”, can now easily use electric imp via the agent to trigger any action channels at ifttt. All done with just a simple api post, worth checking out. I have not try it out yet, I am sure some of you have or will, do share examples.
Thanks,
Ken

I played with the IFTTT Maker Channel while it was in Beta, and it is super simple to use!

Here’s a really simple wrapper class I wrote for sending triggers to IFTTT… it’s hardly worth wrapping in class, but this was for a workshop :slight_smile:

https://github.com/beardedinventor/imp201/blob/master/webservices/2_webserviceClass.agent.nut

The second parameter of the trigger function let’s you pass in a table with value1, value2, and value3 if you want!

Hey, beardedinventor. Thanks for the info and for the code. I just got an electric imp and trying to make it to record temperatures to google doc using IFTTT. Using your function (from your gihub) in the agent code, i got it to trigger my recipe on IFTTT but i can’t get it to record values. I did add my “reading” data when calling the trigger function (as a third argument in the trigger function call). And the data is encoded correctly because if i do a server.log(body), i get a printout of a {“temp”: x} in the log on electric imp IDE which is the temperature recorded by the Imp. So it seems that the value1 gets posted correctly but IFTTT doesn’t record it in my spreadsheet. The only things that are recorded are Time of Occurance and Event Name but no Value1. I studied the Maker function and info on IFTTT but still can’t figure out what i am doing wrong.

I am very new to electric imp, IFTTT, github and i haven’t done much programming since college. Soo… i’ll keep researching for an answer but if there is something obvious that i am missing, i would love help. Thanks!

Hi beardedinventor,
Can you show an simple example of agent & devide code to trigger IFTTT maker?
Thanks,
Ken

@kenkoknz - Yeah absolutely! If you have a particular application in mind I can mock that out for you (otherwise I’ll just make a random example)…

Cool, lets start with the really basic, a switch on IMP, when activated trigger IFTTT maker. I am sure will only take you a few seconds!
Thanks,
Ken

Ok, here’s a simple example where a button activates an IFTTT Maker channel Trigger.

I’m using the Button class becuase I think it’s nifty, and makes for pretty code :slight_smile:

Device Code:

`
#require “Button.class.nut:1.1.0”

btn <- Button(hardware.pin1, DIGITAL_IN, Button.NORMALLY_LOW);

btn.onPress(function() {
agent.send(“btnPress”, null);
});
`

Agent Code:

`
class IFTTT {
static TRIGGER_URL = “https://maker.ifttt.com/trigger/%s/with/key/%s”;

_key = null;

constructor(key) {
    this._key = key;
}

function trigger(eventName, data = null, cb = null) {
    data = data ? data : { };
    
    local url = format(TRIGGER_URL, eventName, _key);
    local headers = { "content-type": "application/json" };
    local body = http.jsonencode(data);

    http.post(url, headers, body).sendasync(function(resp) {
        if(200 > resp.statuscode || resp.statuscode >= 300) {
            if (cb)  imp.wakeup(0, function() { cb(resp.body, resp); });
            return;
        }
        
        if (cb) imp.wakeup(0, function() { cb(null, resp); });
    }.bindenv(this));
}

}

ifttt <- IFTTT("<-- YOUR_TOKEN -->");

device.on(“btnPress”, function(nullData) {
ifttt.trigger(“button”, {}, function(err, resp) {
if (err) {
// If an error occured, log it
server.error(“Failed to activate IFTTT trigger :(”);
server.error(err);
return;
}
// Log success if it worked!
server.log(“Success!!”);
});
});`

Hey Beardedinventor,

I’ll try this implementation for my temp logger. In the meantime, do you have any suggestions why this agent code doesn’t post data? It triggers IFTTT but no data comes through.

`
// Agent Code
#require "Dweetio.class.nut:1.0.0"

// Create a Dweet instance
//local client = DweetIO();

// Add a function to post data from the device to your stream

function trigger(key, eventName, data = {}) {
    local url = "https://maker.ifttt.com/trigger/" + eventName + "/with/key/" + key;
    local headers = {
        "content-type": "application/json"
    };
    
    
    local body = http.jsonencode(data);
    server.log(body);
    
    //local request= http.post(url, headers, body);
    //local response = request.sendsync();
    
    http.post(url, headers, body).sendasync(function(resp) {
        if(200 > resp.statuscode || resp.statuscode >= 300) {
            server.error(resp.body)
            return;
        }
        server.log("Success!");
    });
    
    
}


function postReading(reading) {
    // Note: reading is the data passed from the device, ie.
    // a Squirrel table with the key 'temp'
   //client.dweet("_ZUbZulYePrV", reading, null);
   trigger("cKI0qLqAwVYA8dXQZ8NEgk", "temp_reading", reading);
   // server.log(reading);
}

// Register the function to handle data messages from the device
device.on("reading", postReading);
`

The only data IFTTT accepts are “value1”, “value2”, and “value3”.

You want to change your postReading method to:

`
function postReading(reading) {
// Note: reading is the data passed from the device, ie.
// a Squirrel table with the key ‘temp’
//client.dweet("_ZUbZulYePrV", reading, null);

//trigger(“cKI0qLqAwVYA8dXQZ8NEgk”, “temp_reading”, reading);
trigger(“cKI0qLqAwVYA8dXQZ8NEgk”, { “value1”: reading.temp });

// server.log(reading);

}
`

That’s it! I got it working. Thank you!!

Hello cherepuga-

I’m running the same application (internet connected thermometer). I followed the instructions at:

The data is currently going to - https://data.sparkfun.com/gardenroom

I would like to instead post the data to a Google spreadsheet. The IFTTT trigger seems like the easiest method. When convenient - please post your device and agent code (minus the IFTTT key!). Thanks!

Well I finally got this working to send an SMS using the agent. I made the mistake of copying the code in the IFTTT library page that reads:

ifttt.trigger(“something_happened”, function(err, response) {

but to work that line needs to be:

ifttt.sendEvent(“something_happened”, function(err, response) {

hope that saves someone a bit of time.

Can someone change that in the library example?

Thanks for the catch @Bellancal - we’ve updated the examples in the README :slight_smile:

Hey, @expresso2222, sorry for the delay. Had a bit too much going on at work and so my IOT projects are on hold…

My agent code is the same as i posted above except for the corrections by beardedinventor. It works fine but IFTTT has not been at all reliable in processing the data. It keeps loosing data points and disconnecting from the feed. I contacted IFTTT support and all they told me is that its a known issue and they are working on it.

I have since then moved on to using Xively Personal. It has been entirely reliable and has more capabilities. Xively stores the data and it can be retrieved using curl. There are also android apps that can pull data from Xively for real time access. And i would imagine it wouldn’t be too hard to write one yourself if you know what you are doing. (i don’t :))

Let me know what if you want to see the xively code. I think I used the code by BeardedInventor and i distinctly remember getting off github… but now i can’t find it. Anyway, let me know and i’ll post mine.

We actually have a Xively library, you can find it (along with sample usage as usual) here:

https://github.com/electricimp/xively

It’s been quite awhile since I last played with Xively, and I know a LOT has changed since I last looked at it (though it sounds like ‘Xively Personal’ may be what ‘Xively’ used to be??).

Anywho - enjoy :slight_smile:

@cherepuga Please post the final agent and device code. I’m trying to set up my Electric IMP Env tail with Xively or IFTTT. Thanks!

@expresso2222 here you go

Device:

`
// Device Code
#require “Si702x.class.nut:1.0.0”
#require “APDS9007.class.nut:1.0.0”
#require “LPS25H.class.nut:1.0.0”

// Instance the Si702x and save a reference in tempHumidSensor
hardware.i2c89.configure(CLOCK_SPEED_400_KHZ);
local tempHumidSensor = Si702x(hardware.i2c89);
local pressureSensor = LPS25H(hardware.i2c89)
pressureSensor.enable(true);

local lightOutputPin = hardware.pin5
lightOutputPin.configure(ANALOG_IN)

local lightEnablePin = hardware.pin7
lightEnablePin.configure(DIGITAL_OUT, 1)

local lightSensor = APDS9007(lightOutputPin, 47000, lightEnablePin)

// Configure the LED (on pin 2) as digital out with 0 start state
local led = hardware.pin2;
led.configure(DIGITAL_OUT, 0);

// This function will be called regularly to take the temperature
// and log it to the device’s agent

function takeReadings() {
tempHumidSensor.read(function(reading) {
// The read() method is passed a function which will be
// called when the temperature data has been gathered.
// This ‘callback’ function also needs to handle our
// housekeeping: flash the LED to show a reading has
// been taken; send the data to the agent;
// put the device to sleep

    // Create a Squirrel table to hold the data - handy if we 
    // later want to package up other data from other sensors
    
    local data = {};

    // Get the temperature using the Si7020 object’s readTemp() method
    // Add the temperature using Squirrel’s 'new key' operator
    
    

    data.temp <- (reading.temperature*1.8)+32;
    data.humid <- (reading.humidity);
    
    pressureSensor.read(function(pressure) {
    data.pressure <- pressure;
    
    
    data.light <- lightSensor.read();
    //server.log(data.light);
    
   
    
   
    server.log(hardware.voltage());
   
    data.voltage <- hardware.voltage();
   

    // Send the packaged data to the agent
    agent.send("reading", data);
    

    // Flash the LED to show we've taken a reading
    flashLed();
   
    imp.onidle(function() { 
        server.sleepfor(150);
    
    });
    });
});

}

function flashLed() {
// Turn the LED on (write a HIGH value)
led.write(1);

// Pause for half a second
imp.sleep(0.15);

// Turn the LED off
led.write(0);

}

takeReadings();

`

Agent:
`
//Growerbot code by Havoc (luizhavoc@gmail.com)
//thanks tombrew, this code is based on https://github.com/electricimp/examples/tree/master/tempBug
//thanks jwehr @ http://forums.electricimp.com/ for all the help debugging and adding to the code.

/* GLOBALS and CONSTANTS -----------------------------------------------------*/

const XIVELY_API_KEY = “your api key”;
const XIVELY_FEED_ID = “your feed id”;
const XIVELYCHANNEL1 = “temp”;
const XIVELYCHANNEL2 = “humidity”;
const XIVELYCHANNEL3 = “pressure”;
const XIVELYCHANNEL4 = “voltage”;
const XIVELYCHANNEL5 = “light”;
Xively <- {}; // this makes a ‘namespace’

/* CLASS AND GLOBAL FUNCTION DEFINITIONS -------------------------------------*/

// Xively “library”. See https://github.com/electricimp/reference/tree/master/webservices/xively

class Xively.Client {
ApiKey = null;
triggers = [];

constructor(apiKey) {
this.ApiKey = apiKey;
}

/*****************************************
 * method: PUT
 * IN:
 *   feed: a XivelyFeed we are pushing to
 *   ApiKey: Your Xively API Key
 * OUT:
 *   HttpResponse object from Xively
 *   200 and no body is success
 *****************************************/
function Put(feed){
	local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
	local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
	local request = http.put(url, headers, feed.ToJson());

	return request.sendsync();
}

/*****************************************
 * method: GET
 * IN:
 *   feed: a XivelyFeed we pulling from
 *   ApiKey: Your Xively API Key
 * OUT:
 *   An updated XivelyFeed object on success
 *   null on failure
 *****************************************/
function Get(feed){
	local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
	local headers = { "X-ApiKey" : ApiKey, "User-Agent" : "xively-Imp-Lib/1.0" };
	local request = http.get(url, headers);
	local response = request.sendsync();
	if(response.statuscode != 200) {
		server.log("error sending message: " + response.body);
		return null;
	}

	local channel = http.jsondecode(response.body);
	for (local i = 0; i < channel.datastreams.len(); i++)
	{
		for (local j = 0; j < feed.Channels.len(); j++)
		{
			if (channel.datastreams[i].id == feed.Channels[j].id)
			{
				feed.Channels[j].current_value = channel.datastreams[i].current_value;
				break;
			}
		}
	}

	return feed;
}

}

class Xively.Feed{
FeedID = null;
Channels = null;

constructor(feedID, channels)
{
    this.FeedID = feedID;
    this.Channels = channels;
}

function GetFeedID() { return FeedID; }

function ToJson()
{
    local json = "{ \"datastreams\": [";
    for (local i = 0; i < this.Channels.len(); i++)
    {
        json += this.Channels[i].ToJson();
        if (i < this.Channels.len() - 1) json += ",";
    }
    json += "] }";
    return json;
}

}

class Xively.Channel {
id = null;
current_value = null;

constructor(_id)
{
    this.id = _id;
}

function Set(value) { 
	this.current_value = value; 
}

function Get() { 
	return this.current_value; 
}

function ToJson() { 
	return http.jsonencode({id = this.id, current_value = this.current_value }); 
}

}

function postToXively(data, channel) {
xivelyChannel <- Xively.Channel(channel);
xivelyChannel.Set(data);
xivelyFeed <- Xively.Feed(XIVELY_FEED_ID, [xivelyChannel]);
local resp = xivelyClient.Put(xivelyFeed);
server.log("Posted to Xively: “+data+”, got return code: “+resp.statuscode+”, msg: "+resp.body);
}

/* REGISTER DEVICE CALLBACKS ------------------------------------------------*/
//this catches data sent from device
device.on(“reading”, function(temp) {

postToXively(temp.temp, XIVELYCHANNEL1);
postToXively(temp.humid, XIVELYCHANNEL2);
postToXively(temp.pressure, XIVELYCHANNEL3);
postToXively(temp.voltage, XIVELYCHANNEL4);
postToXively(temp.light, XIVELYCHANNEL5);
});

/*
device.on(“reading”, function(temp) {
//server.log(lux)
postToXively(temp.humid, XIVELYCHANNEL2);
});

/*
device.on(“soil”, function(soil) {
//server.log(soil)
postToXively(soil, XIVELYCHANNEL3);
});

device.on(“humid”, function(humid) {
//server.log(humid)
postToXively(humid, XIVELYCHANNEL4);
});
*/

/* RUNTIME BEGINS HERE -------------------------------------------------------*/

server.log(“Agent ready for work!”);

// instantiate our Xively client
xivelyClient <- Xively.Client(XIVELY_API_KEY);

//Display sensor data on Agent URL
function httpHandler (req, resp) {
server.log(“Agent got a request”);
resp.send(200, “Temp:” + “Light:” + “Soil:” + “Air Humidity:”);
}
http.onrequest(httpHandler);

`