Home Automation with Alexa and Nodemcu (esp8266)

We can control the home appliances using Nodemcu using many methods and also there are lot of platforms like (Blynk, MQTT, Alexa and so on…). In this article we will see one of the method that is using Alexa assistant. We can control the home appliances like Light, FAN or TV using amazon alexa echo dot.

In this project, we will use third party interface for interaction between Alexa and noemcu. Here is the complete flow from user to Alexa, Alexa to sinric and Sinric to nodemcu (ESP8266).

Following are the required parts for this project,

  1. Nodemcu (ESP8266)
  2. Relay module
  3. Light bulb
  4. Few wires
  5. Bulb holders
  6. Amazon Echo Dot

We can connect any number of relay channels to Nodemcu but we will be using 2 channels only in this project.

Here is the connection diagram of the project

Connect 5V of Relay module to 5V/VIN of the nodemcu.
Connect Ground of relay module to ground of Nodemcu.
Connect Relay1 of relay module to ground of D0 pin of Nodemcu.
Connect Relay2 of relay module to ground of D1 pin of Nodemcu.

Now its time to add devices in the sinric. Create an account on sinric first. After Login you will land on Sinric dashboard same as follows.

Now, add new devices to the sinric. After adding a new device in the sinric you will get device id for that device. Device id is unique id for for each device and which will be used in the code.

Code Explanation:

In the code we have to update Sinric API_KEY and Device ID for each device we have added.

In the code two functions are used for turn ON the device and turn OFF the device and functions are turnOn and turnOff respectively. This two function will be triggered whenever there is request for ON/OFF.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h> //  https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
#include <ArduinoJson.h> // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
#include <StreamString.h>

#define LIGHT_1 16
#define LIGHT_2 5

ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
WiFiClient client;

///////////WiFi Setup/////////////

#define MyApiKey "25280b32-9f2f-4abe-9736-f1d59a1f484b" // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard
#define MySSID "hidden" // TODO: Change to your Wifi network SSID
#define MyWifiPassword "qwerty12345" // TODO: Change to your Wifi network password

/////////////////////////////////

#define HEARTBEAT_INTERVAL 300000 // 5 Minutes 

uint64_t heartbeatTimestamp = 0;
bool isConnected = false;

// deviceId is the ID assgined to your smart-home-device in sinric.com dashboard. Copy it from dashboard and paste it here

void turnOn(String deviceId) {
  if (deviceId == "5f4b7e42d1e9084a708199aa") // Device ID of first device
  {  
    Serial.print("Turn on device id: ");
    Serial.println(deviceId);
    digitalWrite(LIGHT_1, LOW);
  } 
  else if (deviceId == "5f4b8128d1e9084a70819a1c") // Device ID of second device
  { 
    Serial.print("Turn on device id: ");
    Serial.println(deviceId);
    digitalWrite(LIGHT_2, LOW);
  }
  else {
    Serial.print("Turn on for unknown device id: ");
    Serial.println(deviceId);    
  }     
}

void turnOff(String deviceId) {
   if (deviceId == "5f4b7e42d1e9084a708199aa") // Device ID of first device
   {  
     Serial.print("Turn off Device ID: ");
     Serial.println(deviceId);
     digitalWrite(LIGHT_1, HIGH);
   }
   else if (deviceId == "5f4b8128d1e9084a70819a1c") // Device ID of second device
   { 
     Serial.print("Turn off Device ID: ");
     Serial.println(deviceId);
     digitalWrite(LIGHT_2, HIGH);
  }
  else {
     Serial.print("Turn off for unknown device id: ");
     Serial.println(deviceId);    
  }
}

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
  switch(type) {
    case WStype_DISCONNECTED:
      isConnected = false;    
      Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
      break;
    case WStype_CONNECTED: {
      isConnected = true;
      Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
      Serial.printf("Waiting for commands from sinric.com ...\n");        
      }
      break;
    case WStype_TEXT: {
        Serial.printf("[WSc] get text: %s\n", payload);
        // Example payloads

        // For Switch or Light device types
        // {"deviceId": xxxx, "action": "setPowerState", value: "ON"} // https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html

        // For Light device type
        // Look at the light example in github
          
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject((char*)payload); 
        String deviceId = json ["deviceId"];     
        String action = json ["action"];
        
        if(action == "setPowerState") { // Switch or Light
            String value = json ["value"];
            if(value == "ON") {
                turnOn(deviceId);
            } else {
                turnOff(deviceId);
            }
        }
        else if (action == "SetTargetTemperature") {
            String deviceId = json ["deviceId"];     
            String action = json ["action"];
            String value = json ["value"];
        }
        else if (action == "test") {
            Serial.println("[WSc] received test command from sinric.com");
        }
      }
      break;
    case WStype_BIN:
      Serial.printf("[WSc] get binary length: %u\n", length);
      break;
  }
}

void setup() {
  Serial.begin(115200);
  
  WiFiMulti.addAP(MySSID, MyWifiPassword);
  Serial.println();
  Serial.print("Connecting to Wifi: ");
  Serial.println(MySSID);

  // Waiting for Wifi connect
  while(WiFiMulti.run() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  if(WiFiMulti.run() == WL_CONNECTED) {
    Serial.println("");
    Serial.print("WiFi connected. ");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }

  // server address, port and URL
  webSocket.begin("iot.sinric.com", 80, "/");

  // event handler
  webSocket.onEvent(webSocketEvent);
  webSocket.setAuthorization("apikey", MyApiKey);
  
  // try again every 5000ms if connection has failed
  webSocket.setReconnectInterval(5000);   // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets

  pinMode(LIGHT_1, OUTPUT);
  pinMode(LIGHT_2, OUTPUT);
  
   digitalWrite(LIGHT_1, HIGH);
   digitalWrite(LIGHT_2, HIGH);
}

void loop() {
  webSocket.loop();
  
  if(isConnected) {
      uint64_t now = millis();
      
      // Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. Thanks @MacSass
      if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
          heartbeatTimestamp = now;
          webSocket.sendTXT("H");          
      }
  }   
}

Mobile App configuration.

Now we will configure the Amazon Alexa mobile app. So, the mobile app is the only way to tell echo dot about new devices.

To add a new device, Go to the devices and click on Your Smart Home skills and then Enable Smart Home skills.

Now search for sinric skill, now click on Enable to Use, After enabling the skill, you will have to link your sinric account here. After Successfully link, you can see all the devices which were under Sinric.

Now you Turn ON or OFF device from here as well.

Demo and Tutorial

2 Replies to “Home Automation with Alexa and Nodemcu (esp8266)”

  1. bro your code show error :

    “DynamicJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6”

Leave a Reply

Your email address will not be published. Required fields are marked *