Beginner Tutorial: IFTTT Publish an Event + Spark Internet Button

Hey @rocksetta,

Looks like a neat project.
The way you do your timing is a bit unconventional, since it now depends on loop completion time, which can vary, as you may have noticed.

There are several ways you can use to remedy this, to make it more stable.

The simple-yet-not-so-great option: (this is blocking)

void loop() {
  // do stuff
  delay(3* 1000); //3s delay
}

The-more-common-solution: https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing (they explain it better than I’ll ever be able to)

The-really-fancy-stuff: (recently released software timers :smile:)
https://docs.particle.io/reference/firmware/photon/#software-timers

2 Likes

@christine @Steph

What a great lesson for my grade 11/12 students. They setup the above circuit and loaded the above .ino.

Then setup IFTTT using either the website or the App.

Activated Particle as a trigger channel in IFTTT.

Chose “New Event Published” .

All I really had to give them was these two images.

For the trigger:

and for the action:

More than half the class managed to do the extra step of: controlling the LED on a second groups Photon, when a bright light was brought near the first groups light sensor. Amazingly easy lesson. Super powerful results.

Thanks Particle.

4 Likes

@Moors7 @christine

Thanks for the tip about the Timer function. Here is the new version of the .ino which works much better, no random firing of the IFTTT. It now gets one reading every 7 seconds.

    //PUT YOUR GLOBAL VARIABLES HERE
    
    Timer myTimer1(7000, my7sFunction);   // activate function every 7 seconds
                                         // Must hold the light on while D7 flashes
    
        
     // Any general setup stuff goes here   
    void setup(){
        
        pinMode(D0, OUTPUT);
        pinMode(D7, OUTPUT);
        myTimer1.start();
        Particle.subscribe("my-lamp-on", myLampFunction, MY_DEVICES);  
        // for using the "DO" IFTTT button or the IF this then that                                                                      
        // must remove ", MY_DEVICES" for Public anyone to access

    }
    
    
    void loop(){
         
      // your looping stuff here
    
    }
    
    
    void my7sFunction(){
        
        static int myCount = 0;
        myCount++;    // not really used but good to keep count
        
        digitalWrite(D7, 1);   // D7 On, flash D7 every 7 seconds
        delay(20);
        digitalWrite(D7, 0);   // D7 Off
        
        if (analogRead(A0) >= 1000){  
            Spark.publish("bright-light", "1000", 60, PRIVATE);
        } 
    
        if (analogRead(A0) <= 30){
            Spark.publish("no-light", "30", 60, PRIVATE);
        } 
          
    }
    
    
    void myLampFunction(const char *event, const char *data){   
 // for the "DO" or "IF" IFTTT buttons
    
            digitalWrite(D0, 1);   // flash D0 for 2 seconds
            delay(2000);
            
            digitalWrite(D0, 0);   // D7 Off
    
      }
1 Like

Glad to see its working. If I might add one more thing: software timers are to be treated as interrupts, and should thus ideally be kept as simple/short as possible. Use it to set a flag which you can check for in your loop. The code you’ve currently got probably work, but if you can make that change, that’d be better :smile:

Thanks @Moors7. Had no idea how to do your suggestion until I found this bit of code.

The isrFlag makes a ton of sense.

2 Likes

So I took @Moors7 suggestion and rewrote my code. Here is the working product. Interesting when using IFTTT, I switched back and forth between a few of my students particle logins and I had to set my Particle.subscribe to public (by removing , MY_DEVICES) even though I was correctly logged into IFTTT and particle as one of my students trying to access the students photon. Almost as if IFTTT had remembered my first particle login so when I cleared that and logged in as a student to particle from within IFTTT, IFTTT thought I did not have access to the new photon. My suggestion is that, if you have problems with subscribe is to start with public and then work towards making things private.

Most people can start with private since they will not be switching back and forth between logins like I was doing.

//PUT YOUR GLOBAL VARIABLES HERE
volatile bool myFlag1 = false;
          int myCount = 0;

Timer myTimer1(7000, my7sFunction);   // activate function every 7 seconds

  

void my7sFunction(){
    
    myFlag1 = true;

}  
  
    
 // Any general setup stuff goes here   
void setup(){
    
    pinMode(D0, OUTPUT);
    pinMode(D7, OUTPUT);
    
    myTimer1.start();
    Particle.subscribe("my-lamp-on", myLampFunction);   //, MY_DEVICES
    // for using the "DO" IFTTT button or the "IF" this then that
    // must remove ", MY_DEVICES" for Public anyone to access
    
}




void myLampFunction(const char *event, const char *data){    

    digitalWrite(D0, 1);   // flash D0 for 2 seconds
    delay(2000);
        
    digitalWrite(D0, 0);   // D0 Off

}



void loop(){
     
  // your looping stuff goes here
  
    if (myFlag1){
        
        myCount++;    // not really used, but good to keep count
        digitalWrite(D7, 1);   // turn D7 on
        delay(20);
        
        if (analogRead(A0) >= 1000){
           Particle.publish("bright-light", "1000", 60, PRIVATE);
        } 

        if (analogRead(A0) <= 30){
           Particle.publish("no-light", "30", 60, PRIVATE);
        } 
        
        digitalWrite(D7, 0);  // turn D7 off
        myFlag1 = false;      // reset timer variable
    }
  
}

This is a DRAFT:

It looks like a webpage can publish an event on IFTTT, using the Maker channel on IFTTT. Here is some working code. First a webpage code, with a form to POST data to IFTTT, an image of that page, then the IFTTT page, then an optional php page that saves the sent variables to a file as proof that the event was fired.

<html>
<head>


<title>HTML form to IFTTT </title>



</head>

<body onload="{
   myStorage1 = localStorage.getItem('myStoredText1')
   if(myStorage1  != null){     
      document.getElementById('myToken').value = myStorage1 
    }   
    myStorage2 = localStorage.getItem('myStoredText2')
    if(myStorage2  != null){
       document.getElementById('myDeviceId').value = myStorage2      
    }
          
}">



<h2 align=center>HTML form to IFTTT using the Maker Channel<br> </h2>



Device ID:<input id="myDeviceId" name="myCoreID" type=text size=50 placeholder="button_pressed4"> <br>



Access Token:<input id="myToken" name="access_token" type=password size=50 placeholder="5622ce6bba702ef6bd3456d5ed26aaa4a28d7c9"> <br>





<form name="myForm" method="POST" id="myCoolForm" ><br>

<input id="myParameter1" name="value1" type=text     size=50 value="d7-send-high"> 
<input id="myParameter2" name="value2" type=text     size=50 value="d7-send-low"> 
<input id="myParameter3" name="value3" type=text     size=50 value='{"fred":"tom","Mary":"45"}'> 

<input type=submit onclick="{
    document.myForm.action = 'https://maker.ifttt.com/trigger/' + document.all.myDeviceId.value + '/with/key/'+ document.all.myToken.value
}">

</form>



<input type="button" value="Store the Photon's Token and ID locally!" onClick="{
   localStorage.setItem('myStoredText1', document.all.myToken.value)   
   localStorage.setItem('myStoredText2', document.all.myDeviceId.value)
   alert( document.all.myToken.value + ' ' +document.all.myDeviceId.value + ' \nHas been stored')
}">






<br><br>




</body>
</html>

Here is an image of the page. Oops I forgot to change some of the statements from the page I took it from.

Here is the working IFTTT receipe. NOTE: YOU CAN ONLY SEND THREE VARIABLES THAT MUST BE CALLED value1, value2, value3.

The more advanced php page.

<?php

$myFile = "testFile.txt";

// opens the file for appending (file must already exist)
$fh = fopen($myFile, 'a');


$myPost = "value1 =". $_POST['value1'] . "value2 =" . $_POST['value2'] . "value3 =" . $_POST['value3'];

// Write to the file
fwrite($fh, $myPost);

fclose($fh);
?>

Here is what gets sent to the file called testFile.txt (which must be pre-saved on the php server)

value1 =d7-send-high, value2=d7-send-low, value3= {“fred”:“tom”,“Mary”:“45”}value2 =value3 =

strange the value2 =value3 = at the end of the line but that is what I got.

I will try to combine this stuff with my code for the photon in the post above. This could allow a mySQL database (or some other php code) to do some of the heavy computing for a photon and then returninformation back to the photon.

1 Like

So the above code is a bit confusing and my webpage has some remnents from old code that make it confusing so I started a new topic at

The firmware flash fails for me, with a fatal error caused by ‘sparkbutton’ - https://i.imgur.com/Og0mpDV.png

Is this due to a new naming of the button or something else?

Try including the Internet button library, then comment out the previous include (the one mentioned in the error).

Hi, Steph!

Thanks for posting this tutorial. I’m finally getting started with the Photon button. I see a comment below that says it’s an old one, which might be causing my issue…

When I load up the code in the Particle web-based ide, I get this error:

iftttbuttonpush.cpp:1:37: fatal error: SparkButton/SparkButton.h: No such file or directory
 #include "SparkButton/SparkButton.h"
compilation terminated.
make[1]: *** [../build/target/user/platform-6iftttbuttonpush.o] Error 1
make: *** [user] Error 2
Error: Could not compile. Please review your code.

It seems to be saying I’m not including the SparkButton.h file correctly. Is there a different way to include that file?

See screengrab below.

Thanks!
Toby

Considering it’s the exact same issue as asked directly above, have you given that solution a try? https://docs.particle.io/guide/getting-started/build/photon/#using-libraries

@Moors7, Thanks for the quick reply.

Yes, I included the library at your suggestion (see updated screengrab below), but the result is the same.

Any thoughts on where to look next?

Toby

You’re still trying to include a library that doesn’t exist, then using that same non-existing library.

It should look something like this:

@Moors7: Ah thanks! Yup, that fixed that file reference error.

With the updated code, I'm getting all sorts of other errors (see below). I am well-versed in php, but this is my first go with a different code base. What's the best way to troubleshoot errors like these? Should I just work from the top-down?

iftttbuttonpush.cpp:3:1: error: 'SparkButton' does not name a type
 void setup();
 ^

iftttbuttonpush.cpp: In function 'void setup()':
iftttbuttonpush.cpp:15:5: error: 'b' was not declared in this scope
 
     ^

iftttbuttonpush.cpp: In function 'void loop()':
iftttbuttonpush.cpp:21:8: error: 'b' was not declared in this scope
 }
        ^

iftttbuttonpush.cpp:24:13: warning: 'Spark' is deprecated (declared at ../wiring/inc/spark_wiring_cloud.h:357): Spark is now Particle. [-Wdeprecated-declarations]
 Remember this particularly if there are things you DON'T want to run a lot. Like Spark.publish() */
             ^
iftttbuttonpush.cpp:32:8: error: 'b' was not declared in this scope
             b.allLedsOff();
        ^

iftttbuttonpush.cpp:35:13: warning: 'Spark' is deprecated (declared at ../wiring/inc/spark_wiring_cloud.h:357): Spark is now Particle. [-Wdeprecated-declarations]
     else {buttonAll = 0;}
             ^
iftttbuttonpush.cpp:43:8: error: 'b' was not declared in this scope
             b.ledOff(12);
        ^

iftttbuttonpush.cpp:46:13: warning: 'Spark' is deprecated (declared at ../wiring/inc/spark_wiring_cloud.h:357): Spark is now Particle. [-Wdeprecated-declarations]
     else {button1 = 0;}
             ^
iftttbuttonpush.cpp:54:8: error: 'b' was not declared in this scope
             b.ledOff(3);
        ^

iftttbuttonpush.cpp:57:13: warning: 'Spark' is deprecated (declared at ../wiring/inc/spark_wiring_cloud.h:357): Spark is now Particle. [-Wdeprecated-declarations]
     else {button2 = 0;}
             ^
iftttbuttonpush.cpp:65:8: error: 'b' was not declared in this scope
             b.ledOff(6);
        ^

iftttbuttonpush.cpp:68:13: warning: 'Spark' is deprecated (declared at ../wiring/inc/spark_wiring_cloud.h:357): Spark is now Particle. [-Wdeprecated-declarations]
     else {button3 = 0;}
             ^
make[1]: *** [../build/target/user/platform-6iftttbuttonpush.o] Error 1
make: *** [user] Error 2
Error: Could not compile. Please review your code.

Since it keeps yapping about the undeclared ‘b’, I think you haven’t changed the orange arrow line?
I prefer to start with the errors from bottom to top. Not quite sure why, but it’s mostly the bottom error causing the actual issue.

Thanks. I’ll start there.

It seems like the definition for the “b” variable is missing. Do you know off the top of your head how that variable might need to be defined? Seems like an object that would need to be instantiated with something like this:

b = new OBJECTNAME

Is this a normal instantiation in the “void setup()” function? If so, how and where are these usually defined?

Toby

D’oh! I still had the path wrong. I needed the preceding slash. :slight_smile: This gets rid of the errors:

#include "/InternetButton.h"

This or rather that

OBJECTNAME* b = new OBJECTNAME();

would be the way to instantiate an object constructed by calling the default constructor and store an instance pointer in b.
Subsequently you'd need to do all instance access like b->whatever().

But that

OBJECTNAME b = OBJECTNAME();
// or even better
OBJECTNAME b;

instantiates an object as instance variable and calls the default constructor for it.
And subsequent access would be done like b.whatever()

And if you are using Particle Build (Web IDE), you want to have that exactly like this

#include "InternetButton/InternetButton.h"

// InternetButton b = InternetButton(); // this will first create an instance b, and a temporary instance and then replace b with the temporary one (cumbersome to say the least)
InternetButton b;
1 Like