Switching 5 relays via Google Home, IFTTT & Particle


#1

Not sure if this is a good place to ask this but I’ve just got voice command to connect to one or more relays as a revised simple led on/off script. But I want to add a bank of relays via gpio numbers.

How to switch individual relays has me stumped within one script. I set up the IFTTT commands and then connect to the script below but want to set up commands for each relay. So typical commnad “Relay 1 on” “Relay 1 off”, etc. How do I do this?

I know I need some sort of If then else nesting but can anyone give me any pointers?


int relay02 = D4; //pin to which relay is connected
int relay03 = D5; //ditto
int relay04 = D6; //ditto
int relay05 = D7; //ditto
int relay06 = D8; //ditto

bool vin = LOW; //a virtual boolean variable

// setup() is run only once, it's where we set up GPIO and initialise peripherals
void setup() {
    
  // Setup GPIO
  pinMode(relay02,OUTPUT); // relay2 pin is set as output
  digitalWrite(relay02,HIGH);
  pinMode(relay03,OUTPUT); // relay3 pin is set as output
  digitalWrite(relay03,HIGH);
  pinMode(relay04,OUTPUT); // etc
  digitalWrite(relay04,HIGH);  
  pinMode(relay05,OUTPUT);
  digitalWrite(relay05,HIGH); 
  pinMode(relay06,OUTPUT);
  digitalWrite(relay06,HIGH);  
  
   // Subscribe to events published by IFTTT using Particle.subscribe
  Particle.subscribe("LOWERPATH-OFFxxx", myHandler2); // turning off .. Want to vary this as Relay 01, 02 etc 
  Particle.subscribe("LOWERPATH-ONxxx", thisHandler2); // turning on...I Want to add more commands to switch differing relays.
}

// loop() runs continuously, it's our infinite loop.
void loop() {
     if (vin==HIGH)
     {
         digitalWrite(relay02,LOW); //I want to IF this part, ie, If LOWERPATH-OFFxxx Then 
         digitalWrite(relay03,LOW); // If Relay3-ON then.. etc
         digitalWrite(relay04,LOW);
         digitalWrite(relay05,LOW);
         digitalWrite(relay06,LOW);
     }
else if (vin==LOW)
      {
         digitalWrite(relay02,HIGH);
         digitalWrite(relay03,HIGH);
         digitalWrite(relay04,HIGH);
         digitalWrite(relay05,HIGH);
         digitalWrite(relay06,HIGH);
                  
     }

}

//our events are called when IFTTT applets are triggered
void myHandler2(const char *event, const char *data)
{
    vin=LOW;
}
void thisHandler2(const char *event, const char *data)
{
     vin=HIGH;

IFTTT does not send anything to Particle
Project guidance
#2

Could you format you code so that it displays nicely?

You can do it with:

```cpp
your code
```


#3

You say that you have 6 relays but I only count 5, 2 through 6.

I assume this is for Raspberry Pi.

You’re also missing the closing } for thisHandler2.


#4

Thanks, done that.


#5

I’ve cleaned up the code a bit but could you explain exactly what modifications you need?:

Since you’re using IFTTT and (probably just one device will run this code) I’d recommend using “Call a function” on IFTTT. That way you would need only one Particle cloud function in you code that would parse any request from IFTTT to turn relays on or off.

Normally I’d do this entirely on my own but I’d like for you to provide some some input as this is your project.

#include "Particle.h"

int relay[5] = {D4,D5,D6,D7,D8};

bool vin = LOW; //a virtual boolean variable

//our events are called when IFTTT applets are triggered
void offHandler(const char *event, const char *data)
{
        vin=LOW;
}
void onHandler(const char *event, const char *data)
{
        vin=HIGH;
}

// setup() is run only once, it's where we set up GPIO and initialise peripherals
void setup() {

        for (int i = 0; i < 5; i++) // Setup GPIO
        {
                pinMode(relay[i], OUTPUT); // set as output
                digitalWrite(relay[i], HIGH); // set HIGH
        }

        // Subscribe to events published by IFTTT using Particle.subscribe
        Particle.subscribe("LOWERPATH-OFFxxx", offHandler); // turning off .. Want to vary this as Relay 01, 02 etc
        Particle.subscribe("LOWERPATH-ONxxx", onHandler); // turning on...I Want to add more commands to switch differing relays.
}

// loop() runs continuously, it's our infinite loop.
void loop() {
        if (vin==HIGH)
        {
                //I want to IF this part, ie, If LOWERPATH-OFFxxx Then
                // If Relay3-ON then.. etc

                for (int i = 0; i < 5; i++) // Setup GPIO
                {
                        digitalWrite(relay[i], LOW); // set LOW
                }
        }
        else if (vin==LOW)
        {
                for (int i = 0; i < 5; i++) // Setup GPIO
                {
                        digitalWrite(relay[i], HIGH); // set HIGH
                }
        }
}

#6

Hi thanks, sorry for being unclear.

I want to use google home commands like "turn relay two off, turn relay 4 off etc.

In my code above there are two handlers on and off, I guess I want 5 of them, or 10, 5 on and 5 off commands, two for each connected relay. If that makes sense in coding. these would be called by the google automation script at IFTTT? Or rather 10 individual scripts at IFTTT as commands to the script above.

I notice you have put #include “particle.h” ?

Yes this is a Pi project


#7

What I’m trying to say is that this could be done with just one handler or cloud function where IFTTT would send a command telling the Pi which relay to turn on or off. This would be done using arguments. IFTTT would call the cloud function and send the arguments of which relay and what state to change.

An example of such arguments would be “1H”, which the Raspberry Pi would interpret as “set relay 1 to HIGH”.

Ideally you wouldn’t need to make 10 different IFTTT applets if you could google home in IFTTT to process the relay number and state to pass onto the Particle action.

You don’t need to worry about this, its necessary for my build environment.


#8

What you say makes perfect sense I think, except I don’t know how to do that!

Using WEBIOPI and js I have web interface switching already but wanted to link it to google home for voice switching and this led me here. But somehow integrating directly via IFTT makes more sense i just don’t know how.

Sample…

 webiopi().ready(function()
 {
        		webiopi().setFunction(17,"out");
        		webiopi().setFunction(27,"out");
				webiopi().setFunction(22,"out");
				webiopi().setFunction(5,"out");
				webiopi().setFunction(15,"out");
				webiopi().setFunction(6,"out");
        		
        		var content, button;
        		content = $("#content");
        		   		
        		button = webiopi().createGPIOButton(17,"Inside");
        		content.append(button);
        		
        		button = webiopi().createGPIOButton(27,"Exterior");
        		content.append(button);
				
        		button = webiopi().createGPIOButton(22,"Outside Light (2way)");
        		content.append(button);
								
        		button = webiopi().createGPIOButton(5,"WALKWAY");
        		content.append(button);

        		button = webiopi().createGPIOButton(15,"SCREEN");
        		content.append(button);

        		button = webiopi().createGPIOButton(6," RELAY 5 ");
        		content.append(button);
        		
        		webiopi().digitalRead(17,"out");

			webiopi().digitalRead(27,"out");

			webiopi().digitalRead(22,"out");

			webiopi().digitalRead(5,"out");

			webiopi().digitalRead(15,"out");

			webiopi().digitalRead(6,"out");


        });

and a css to style and read states for a web page


body {
						background-color:#FFFFFF;
						background-image:url('/img/xxx.png');
						background-repeat:no-repeat;
						background-position:center;
						background-size:contain;
						font: bold 18px/25px Arial, sans-serif;
						color:White;
				}
        
        		button {
        				display: block;
        				position: relative;
        				margin: 18px;
        				padding: 0 6px;
        				text-align: center;
        				text-decoration: none;
        				width: 220px;
        				height: 38px;
        				font: bold 18px/25px Arial, sans-serif;    				
        				color: black;
        				
        				text-shadow: 1px 1px 1px rgba(255,255,255, .22);
        				-webkit-border-radius: 16px;
   						-moz-border-radius: 16px;
    					border-radius: 16px;
 
    					-webkit-box-shadow: 1px 1px 1px rgba(0,0,0, .20), inset 1px 1px 1px rgba(255,255,255, .44);
    					-moz-box-shadow: 1px 1px 1px rgba(0,0,0, .20), inset 1px 1px 1px rgba(255,255,255, .44);
    					box-shadow: 1px 1px 1px rgba(0,0,0, .20), inset 1px 1px 1px rgba(255,255,255, .44);
 
    					-webkit-transition: all 0.15s ease;
    					-moz-transition: all 0.15s ease;
    					-o-transition: all 0.15s ease;
    					-ms-transition: all 0.15s ease;
    					transition: all 0.15s ease;
        		}
        		
        		input[type=range] {
        				display: block;
        				width: 220px;
        				height: 38px;
        		}
        		
        		#gpio17.LOW {
        				background-color: Red;
        				color: White;
        		}
        		
        		#gpio17.HIGH {
        				background-color: Gray;
        				color: Black;
        		}
        		
        		#gpio27.LOW {
        				background-color: Red;
        				color: White;
        		}
        		
        		#gpio27.HIGH {
        				background-color: Gray;
        				color: Black;
        		}
        		
        		#gpio22.LOW {
        				background-color: Red;
        				color: LightGray;
        		}
        		
        		#gpio22.HIGH {
        				background-color: Gray;
        				color: Red;
        		}
        		
        		#gpio5.LOW {
        				background-color: Red;
        				color: White;
        		}
        		
        		#gpio5.HIGH {
        				background-color: Gray;
        				color: Black;
        		}

		        		
        		#gpio15.HIGH {
        				background-color: Blue;
        				color: White;
        		}
        		
        		#gpio15.LOW {
        				background-color: LightGray;
        				color: Black;

        		}

        		#gpio6.LOW {
        				background-color: Red;
        				color: Orange;
        		}
        		
        		#gpio6.HIGH {
        				background-color: Gray;
        				color: Red;
        		}

Hope this clarifes how I currently have it working without IFTT or Particle, voice etc


#9

I think this would be doable with the Google Assistant trigger:

Say a phrase with both a number and a text ingredient

And the Particle action:

Call a function

I’ll check what exactly you need to type in.


#10

I have this sort working for one or all relays but not for individual relays and if I run it along side my existing web interface code it overrides it rather than integrates (sad face!). I’m in over my head but really want to have a go.


#11

Pretty soon we’ll have it working well for individual relays.


#12

I just ran the tidy up you did of my mess and it works well, I even added a short time delay between switches to avoid overloads etc. so now my original problem of individual switching remains. Thank you for your help so far.


#13

OK, Here is the link to the IFTTT applet: https://ifttt.com/applets/Hq26QGiv-ok-google-turn-on-off-relay

And here is the code:

#include "Particle.h"

int relay[5] = {D4,D5,D6,D7,D8};

//our events are called when IFTTT applets are triggered
void offHandler(const char *event, const char *data)
{
        for (int i = 0; i < 5; i++) // Setup GPIO
        {
                digitalWrite(relay[i], LOW); // set LOW
        }
}
void onHandler(const char *event, const char *data)
{
        for (int i = 0; i < 5; i++) // Setup GPIO
        {
                digitalWrite(relay[i], HIGH); // set LOW
        }
}

int setRelay(String args)
{
        bool relayState;
        int commaLoc = args.indexOf(",");

        String relayString = args.substring(0,commaLoc);
        String stateString = args.substring(commaLoc+1);

        Particle.publish("log", relayString + " " + stateString);

        if (stateString.equals("on")) {
                relayState = LOW;
        }
        else {
                relayState = HIGH;
        }

        int relayNumber = relayString.toInt();

        pinMode(relay[relayNumber-1], OUTPUT); // set as output
        digitalWrite(relay[relayNumber-1], relayState);

        return 0;
}

// setup() is run only once, it's where we set up GPIO and initialise peripherals
void setup() {

        for (int i = 0; i < 5; i++) // Setup GPIO
        {
                pinMode(relay[i], OUTPUT); // set as output
                digitalWrite(relay[i], HIGH); // set HIGH
        }

        // Subscribe to events published by IFTTT using Particle.subscribe
        Particle.subscribe("LOWERPATH-OFFxxx", offHandler); // turning off .. Want to vary this as Relay 01, 02 etc
        Particle.subscribe("LOWERPATH-ONxxx", onHandler); // turning on...I Want to add more commands to switch differing relays.

        Particle.function("setRelay", setRelay);
}

// loop() runs continuously, it's our infinite loop.
void loop() {

// empty because handlers and cloud function manage the relays

}

I am not a Particle employee. All contributions I make are done out of my own interest to serve the Particle Community. You can donate to support my efforts if you are feeling generous: https://nrobinson.me/

EDIT: It seems like IFTTT is having trouble importing the applet from the link. I’ve attached a screenshot if that helps you make the applet yourself.


#14

Hi,
I’ve set up the IFTTT applet as an exact copy of yours. But think i’m missing something. If I say “set relay 5 on” Google responds with “OK Turning relay 5 on” but nothing happens.
I realise I can say Turn relay 876 purple and google reflects this but of course nothing happens?
How do I know which relay the Particle script will switch -

I also assume I can remove

        // Subscribe to events published by IFTTT using Particle.subscribe
        Particle.subscribe("LOWERPATH-OFFxxx", offHandler); // turning off .. Want to vary this as Relay 01, 02 etc
        Particle.subscribe("LOWERPATH-ONxxx", onHandler); // turning on...I Want to add more commands to switch differing relays.

I’m still confused how this could work? Do I need to assign names to relay switches (gpio pins)?
Thanks so much for your input though.


#15

If you open the Particle console and watch the events coming from the Pi you should see the “log” event which contains the number of the relay and the state it sets.


#16

OK, I said “Set relay 5 on” and the console showed

5 off 5 off

I then tried “Turn relay D5 off” and got

D5 off D5 off

But no response from the relays?


#17

Did you make the IFTTT applet correctly?


#18

Yes I think so. Here it is


an example from the IFTTT log is…
Ingredients
CreatedAt
October 3, 2018 at 11:51PM
NumberField
5
TextField
on

The console shows duplicate responses as shown in my previous post, is this correct?


#19

You may have missed the , separating NumberField and TextField


#20

Just some notes on your code - even (or especially) if this is just some pointer for users new to this it should show best practice to avoid manifesting practices that may need to be unlearned later on

  • it might be better to not use String but rather standard C string functions
  • you may want to constrain the the relayNumber on parsing and only execute the active part when valid values are provided
  • you may want to consider returning some useful value (e.g. return relayNumber*100 + relayState;) from your Particle.function() handler