Skip to content

Instantly share code, notes, and snippets.

@outofmbufs
Last active May 21, 2021 21:44
Show Gist options
  • Save outofmbufs/d6ced37b49a484c495f0 to your computer and use it in GitHub Desktop.
Save outofmbufs/d6ced37b49a484c495f0 to your computer and use it in GitHub Desktop.
Arduino code to trigger an IFTTT/Maker event
// The MIT License
//
// Copyright (c) 2015 Neil Webber
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>
//
// Ethernet MAC address to use.
// Usually Arduino Ethernet shields come with an address printed on
// them (sometimes on underside of the board). Use that one here.
//
byte mac[] = { 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }; // REPLACE WITH REAL ADDR
//
// IFTTT Maker parameters:
// Key -- Obtained when setting up/connecting the Maker channel in IFTTT
// Event -- Arbitrary name for the event; used in the IFTTT recipe.
//
char MakerIFTTT_Key[] = "r8X-blahblahYourKeyGoesHere";
char MakerIFTTT_Event[] = "arduino_example";
//
// The IFTTT/Maker channel allows for three values to be reported
// which can be used as "ingredients" in the IFTTT recipe.
//
// In this simple example the values come from:
// reading a PIN (reported as value1)
// reporting uptime in milliseconds (reported as value2)
// the string "hello, world!" (reported as value3)
//
//
#define READ_THIS_PIN 3 // will be reported as "value1"
// helper functions for constructing the POST data
// append a string or int to a buffer, return the resulting end of string
char *append_str(char *here, char *s) {
while (*here++ = *s++)
;
return here-1;
}
char *append_ul(char *here, unsigned long u) {
char buf[20]; // we "just know" this is big enough
return append_str(here, ultoa(u, buf, 10));
}
//
// This is called once per iteration to read the pin
// and send a POST to trigger the IFTTT/Maker event
//
void update_event() {
EthernetClient client = EthernetClient();
// connect to the Maker event server
client.connect("maker.ifttt.com", 80);
// construct the POST request
char post_rqst[256]; // hand-calculated to be big enough
char *p = post_rqst;
p = append_str(p, "POST /trigger/");
p = append_str(p, MakerIFTTT_Event);
p = append_str(p, "/with/key/");
p = append_str(p, MakerIFTTT_Key);
p = append_str(p, " HTTP/1.1\r\n");
p = append_str(p, "Host: maker.ifttt.com\r\n");
p = append_str(p, "Content-Type: application/json\r\n");
p = append_str(p, "Content-Length: ");
// we need to remember where the content length will go, which is:
char *content_length_here = p;
// it's always two digits, so reserve space for them (the NN)
p = append_str(p, "NN\r\n");
// end of headers
p = append_str(p, "\r\n");
// construct the JSON; remember where we started so we will know len
char *json_start = p;
// As described - this example reports a pin, uptime, and "hello world"
p = append_str(p, "{\"value1\":\"");
p = append_ul(p, analogRead(READ_THIS_PIN));
p = append_str(p, "\",\"value2\":\"");
p = append_ul(p, millis());
p = append_str(p, "\",\"value3\":\"");
p = append_str(p, "hello, world!");
p = append_str(p, "\"}");
// go back and fill in the JSON length
// we just know this is at most 2 digits (and need to fill in both)
int i = strlen(json_start);
content_length_here[0] = '0' + (i/10);
content_length_here[1] = '0' + (i%10);
// finally we are ready to send the POST to the server!
client.print(post_rqst);
client.stop();
}
// called once at system reset/startup time
void setup() {
// this sets up the network connection, including IP addr via DHCP
Ethernet.begin(mac);
// the input pin for this example
pinMode(READ_THIS_PIN, INPUT_PULLUP);
}
// how often to read the pins and update IFTTT
#define LOOP_DELAY_MSEC (300*1000L) // 5 minutes
// main body; called over and over if it ever returns
void loop() {
// DHCP lease check/renewal (library only sends request if expired)
Ethernet.maintain();
// read the pins, send to IFTTT/Maker
update_event();
// only "this often"
delay(LOOP_DELAY_MSEC);
}
@outofmbufs
Copy link
Author

You can make the program smaller (use less RAM) by moving string constants into the program memory space and out of RAM. Because the Arduino architecture separates program space addressing from data space addressing, the compiler can't do this for you transparently even with true string constants such as "This is a string constant". You have to do it yourself and the result is somewhat ugly.

But if your application needs more RAM space then it might be worth the hassle. Here's what you need to do:

Add

#include <avr/pgmspace.h>

to the include section up front

Add this function:

// special version for string literals in program memory
char *append_progstr(char *here, const PROGMEM char *pxx) {
    while (*here++ = pgm_read_byte(pxx++))
         ;
    return here-1;
}

Now for any string constant you are willing to take extra steps to move into the prom you can. The catch is you can't use string literals any more, you have to put the strings into variables declared in a special syntax. So it gets a little ugly. Here's what it looks like if we put a bunch of the header literals into program memory:

const char px[] PROGMEM = { " HTTP/1.1\r\nHost: maker.ifttt.com\r\nContent-Type: application/json\r\nContent-Length: " };

and then rewrite update_event to look like this at the beginning:

void update_event() {
    ... everything as before
    ...
    p = append_str(p, MakerIFTTT_Key);
    p = append_progstr(p, px);

where, as you can see, we replaced a bunch of string literals with one variable (px) and the special syntax to put that into program space (and the special function to access it from there).

You could also put the keys and the event name into program space pretty easily since they are already in variables. Replace their declarations up top with this:

const char MakerIFTTT_Key[] PROGMEM = "r8X-blahblahYourKeyGoesHere";
const char MakerIFTTT_Event[] PROGMEM = "arduino_example";

and change the corresponding append_str() calls into append_progstr() calls.

You can carry out this conversion on as many strings as you have the patience for though obviously the biggest bang for buck comes from converting the longest strings.

@ericoporto
Copy link

Hey! I needed to make a simple button! So I found your code and did it and it worked! Thank you!

@RalphBejj
Copy link

Thank you so much, but where can I find the code to control IFTTT with my Arduino Uno Wifi?
can't seem to find the code anywhere?

@bkkrunal
Copy link

Hi.
Thanks for sharing your work...
I was trying to make a call using GET request but could not achieve anything.
Your code worked for me, but I don't understand why GET was not working. Can you please suggest.
This works when I make GET request using hurl.it website...
Here is my loop function:

if(client.connect("maker.ifttt.com", 80))
{

//Key = kkkkkkkkkkkkkkkkkxxxxxxxxxx

strcat( post_rqst ,"GET maker.ifttt.com/trigger/TemperatureLog/with/key/kkkkkkkkkkkkkkkkkxxxxxxxxxx?value1=12");

Serial.println(post_rqst);
client.println(post_rqst); 
client.stop();

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment