Home automation with ESP8266

Hi, I am doing a project with google home, IFTTT and the NodeMCU ESP8266 board. Although i’m not using an Arduino board, i’m using Arduino IDE. In my IFTTT, webhooks template, the JSON script is,
{"location":"bedroom","device":"computer", "state":"off","query":"cmd"}
In the IDE script the line, it will change the “relayPin”(signal pin to relay) to control different relays based on the “device”.

if(device=="lights"){
              int relayPin = 16;
            }else if(device=="computer"){
              int relayPin = 5;
              pinMode(relayPin, OUTPUT);
            }

Although one of my applets, “turn computer off” (JSON code seen above) turns on both relays (pin 16, 5) instead of turning off pin 5. If anyone sees a problem that may be causing this please tell me.

Full IDE code,

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h>
#include <Hash.h>


// @@@@@@@@@@@@@@@ You only need to midify modify wi-fi and domain info @@@@@@@@@@@@@@@@@@@@
const char* ssid     = "NETGEAR56-5G"; //enter your ssid/ wi-fi(case sensitive) router name - 2.4 Ghz only
const char* password = "hungrysheep940";     // enter ssid password (case sensitive)
char host[] = "googlehome1.herokuapp.com"; //192.168.0.100 -enter your Heroku domain name like  "alexagoogleifttt.herokuapp.com" 
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

int port = 80;
char path[] = "/ws"; 
ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
 int relayPin = 16;
DynamicJsonBuffer jsonBuffer;
String currState;
int pingCount = 0;
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { //uint8_t *


    switch(type) {
        case WStype_DISCONNECTED:
           Serial.println("Disconnected! ");
           Serial.println("Connecting...");
               webSocket.begin(host, port, path);
               webSocket.onEvent(webSocketEvent);
            break;
            
        case WStype_CONNECTED:
            {
             Serial.println("Connected! ");
          // send message to server when Connected
            webSocket.sendTXT("Connected");
            }
            break;
            
        case WStype_TEXT:
            Serial.println("Got data");
              //data = (char*)payload;
           processWebScoketRequest((char*)payload);
            break;
            
        case WStype_BIN:

            hexdump(payload, length);
            Serial.print("Got bin");
            // send data to server
            webSocket.sendBIN(payload, length);
            break;
    }

}

void setup() {
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    
    pinMode(relayPin, OUTPUT);
    
      for(uint8_t t = 4; t > 0; t--) {
          delay(1000);
      }
    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    
    //Serial.println(ssid);
    WiFiMulti.addAP(ssid, password);

    //WiFi.disconnect();
    while(WiFiMulti.run() != WL_CONNECTED) {
      Serial.print(".");
        delay(100);
    }
    Serial.println("Connected to wi-fi");
    webSocket.begin(host, port, path);
    webSocket.onEvent(webSocketEvent);

}

void loop() {
    webSocket.loop();
	//If you make change to delay make sure adjust the ping
    delay(2000);
	// make sure after every 40 seconds send a ping to Heroku
	//so it does not terminate the websocket connection
	//This is to keep the conncetion alive between ESP and Heroku
	if (pingCount > 20) {
		pingCount = 0;
		webSocket.sendTXT("\"heartbeat\":\"keepalive\"");
	}
	else {
		pingCount += 1;
	}
}

void processWebScoketRequest(String data){

            JsonObject& root = jsonBuffer.parseObject(data);
            String device = (const char*)root["device"];
            String location = (const char*)root["location"];
            String state = (const char*)root["state"];
            String query = (const char*)root["query"];
            String message="";

            Serial.println(data);
            Serial.println(state);
            if(device=="lights"){
              int relayPin = 16;
            }else if(device=="computer"){
              int relayPin = 5;
              pinMode(relayPin, OUTPUT);
            }
            
            if(query == "cmd"){ //if query check state
              Serial.println("Recieved command!");
                    if(state=="on"){
                      digitalWrite(relayPin, HIGH);
                      message = "{\"state\":\"ON\"}";
                      currState = "ON";
                    }else{
                      digitalWrite(relayPin, LOW);
                      message = "{\"state\":\"OFF\"}";
                      currState = "OFF";
                    }
                  
            }else if(query == "?"){ //if command then execute   
              Serial.println("Recieved query!");
              int state = digitalRead(relayPin);
                 if(currState=="ON"){
                      message = "{\"state\":\"ON\"}";
                    }else{
                      message = "{\"state\":\"OFF\"}";
                    }
            }else{//can not recognized the command
              Serial.println("Command is not recognized!");
            }
            Serial.print("Sending response back");
            Serial.println(message);
                  // send message to server
                  webSocket.sendTXT(message);
                  if(query == "cmd" || query == "?"){webSocket.sendTXT(message);}
}

Skimming the code I found many problems. First of all the indentation: press ctrl-T in the IDE and it fixes that for you. Makes your code readable, it's a mess now.

Then I found this:

            Serial.println(state);
            if(device=="lights"){
              int relayPin = 16;
            }else if(device=="computer"){
              int relayPin = 5;
              pinMode(relayPin, OUTPUT);
            }
            
            if(query == "cmd"){ //if query check state
              Serial.println("Recieved command!");
                    if(state=="on"){
                      digitalWrite(relayPin, HIGH);
                      message = "{\"state\":\"ON\"}";
                      currState = "ON";
                    }else{
                      digitalWrite(relayPin, LOW);
                      message = "{\"state\":\"OFF\"}";
                      currState = "OFF";
                    }

That's just about the worst possible way of implementing this.

First of all, do define your pins at the start of the code, e.g.:

#define COMPUTER_RELAY 3
#define LIGHTS_RELAY 16

Then later refer to the relays through those names. More readable, less error.

Setting a relayPin somewhere to one of the relays and using it later is bad practice - very hard to figure out "what relay is it now?". On top of that, you declare the variable "int relayPin" inside a curly-braces block, so it's local to that block and that block only. The moment you leave the block it's gone, and may even revert to a value it had before.

pinMode is usually set in the setup() section of your code, normally pins are output or input throughout the whole program so that's where you set them and you don't have to touch that again.

So you'll have a lot of rewriting to do. I'm expecting to see a few lines such as:

if (query == "cmd" && device == "computer") {
  digitalWrite(COMPUTER_RELAY, HIGH);

Can also be done as a bunch of chained "if" and "if else" statements.

Thanks for all your tips, it's now working great!