vicente zavala
Published © LGPL

IoT Home Automation

IoT Home Automation. Control light switch through google home assistant plus weather forecaster using openweathermap.

AdvancedShowcase (no instructions)1,337
IoT Home Automation

Things used in this project

Hardware components

WiFi Kit 8
×1
3.3v Relay
×1
Resistor 100k ohm
Resistor 100k ohm
×1
1N4007 – High Voltage, High Current Rated Diode
1N4007 – High Voltage, High Current Rated Diode
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Arduino Proto Shield
Arduino Proto Shield
×1

Software apps and online services

Maker service
IFTTT Maker service

Story

Read more

Schematics

wiring

ISR PushButton

Code

Weather

Arduino
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

// WiFi parameters
const char  *ssid     = "xxxxxxxx";
const char  *password = "xxxxxxxx";

ESP8266WebServer server(80);

const char *getWeatherCondition()
{
  // Initialise condition
  const char* condition;
    
  if (WiFi.status() == WL_CONNECTED) 
  {
    HTTPClient http;  //Declare an object of class HTTPClient
    http.begin("http://api.openweathermap.org/data/2.5/weather?lat=xxxxxxx&lon=xxxxxxxxxxxx&appid=xxxxxxxxxxx");
    int httpCode = http.GET();
 
    if (httpCode > 0) 
    {
      // Get payload
      String payload = http.getString();
  
      // JSON buffer 
      const size_t bufferSize = JSON_ARRAY_SIZE(3) + 2*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_S  IZE(6) + JSON_OBJECT_SIZE(12) + 480;
      DynamicJsonBuffer jsonBuffer(bufferSize);
      // Parse JSON data
  
      const char *json  = payload.c_str();
      JsonObject &root  = jsonBuffer.parseObject(json);
        
      // Root object
      JsonArray   &weather  = root["weather"];
      JsonObject  &weather0 = weather[0];
  
      // Get main report
      condition = weather0["main"];
    }
      
      http.end();   //Close connection
  }
    
  return condition;
}

void handleRoot() 
{
  // Call weather API
  const char *condition_now = getWeatherCondition();
  server.send(200, "text/plain", condition_now);
}

void handleNotFound()
{
  String message = "Bad request!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  
  for (uint8_t i=0; i<server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
    
  server.send(404, "text/plain", message);
}

void setup() 
{
  Serial.begin(115200);
  // Connect to WiFi
  
  WiFi.begin(ssid, password);
    
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
    
  // Move to next line
  Serial.println();
  
  // Print WiFi Parameters
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");
}

void loop()
{
  server.handleClient();
}

ISR

Arduino
uint8_t GPIO_Pin = D6;

void setup() 
{
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(GPIO_Pin), IntCallback, RISING);
}

void loop() {}

void IntCallback()
{
  Serial.print("Stamp(ms): ");
  Serial.println(millis());
}

WebSocketClient

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

const char* ssid     	= "enter your ssid"; 
const char* password 	= "enter ssid password";
char 		host[] 		= "yourapp.herokuapp.com";

int 		port 		= 80;
char 		path[] 		= "/ws"; 

ESP8266WiFiMulti 		WiFiMulti;
WebSocketsClient 		webSocket;

const int 	relayPin 	= D7;

DynamicJsonBuffer 		jsonBuffer;
String 					currState;
int 		pingCount 	= 0;

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) 
{
	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(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);
	}
}

Credits

vicente zavala

vicente zavala

11 projects • 24 followers
Freelance Programmer, Internet Of Things (IOT), CNC Plasma Cutting Creator, AI, DL, ML, Hardware Software Hacker.

Comments