smart home with google assistant alexa

Smart Home with Google Assistant & Alexa using NodeMCU ESP8266

Make a Smart Home with Google Assistant & Alexa using NodeMCU ESP8266 & Sinric Pro. Explained with Circuit and CODE & used FREE tools.

In this IoT project, I have explained how to make Smart Home with Google Assistant and Alexa using NodeMCU ESP8266 and Sinric Pro. With this NodeMCU ESP8266 project, you can control 3 home appliances with Google Assistant, Alexa, and manual switches. You can also control the relays from Google Home and Amazon Alexa App from anywhere in the world. You can control the relay module from the manual switches if there is no internet available.

And you don’t need any Google Nest or Amazon Echo Dot devices for this voice control home automation project.

Smart Home with Google Assistant and Alexa

With this home automation project, you can control & monitor the real-time feedback of the relays in the Google Home and Alexa App from anywhere in the world. If the WiFi is available, the NodeMCU will automatically connect with the Wi-Fi.

Smart Home with Google Assistant

For this project, I have used all the FREE tools. So if you follow all steps, you can easily make this Smart Home System with Google Home and Amazon Alexa to control the appliances with voice commands.

Circuit of the NodeMCU Home Automation

NodeMCU home automation circuit

The circuit is very simple, I have used D1, D2, D5 & D6 GPIO to control the 4-channel relay module.

And the GPIO SD3, D3, D7 & RX are connected with manual switches to control the relay module manually.

I have used the INPUT_PULLUP function in Arduino IDE instead of using the pull-up resistors with each switch.

As per the source code, when the control pins of the relay module receive the LOW signal the respective relay will turn on and the relay will turn off for the HIGH signal in the control pin.

I have used a 5V 2Amp mobile charger to supply the circuit.

**The Boot will fail if SD3 and D3 are grounded during the Boot process. So manual switch-S1 and switch-S2 must be OFF during NodeMCU Boot.

Now, if you want to use pushbuttons then just connect the pushbuttons across the GPIO pins and GND pin instead of switches.

Required Components for the NodeMCU projects

Components for the NodeMCU projects
  1. NodeMCU
  2. 4-channel 5V SPDT Relay Module
  3. Manual Switches or Pushbuttons
  4. Amazon Echo Dot (optional)
  5. Google Nest Mini (optional)

Tutorial video on Smart Home with Google & Alexa

In the tutorial video, I have covered the following steps in detail.

  • Control 3 relays with Google Assistant, Alexa, and switches.
  • Create an account and add devices in Sinric Pro
  • Programming the NodeMCU with Arduino IDE
  • Connect Sinric Pro and add IoT devices with Amazon Alexa App.
  • Connect Sinric Pro and add IoT devices with Google Home App.

Sinric Pro FREE account setup

For this smart house project, I have used the Sinric Pro Free account. First, you have to add 3 devices to the Sinric Pro account.

I have already explained, how to set up and add devices to Sinric Pro in the following article.

Sinric Pro Account Setup

Program NodeMCU with Arduino IDE

In the Tutorial video, I have explained all the steps to program the NodeMCU using Arduino IDE.

  1. Update the Preferences –> Aditional boards Manager URLs: https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.json
  2. Then install the ESP8266 board from the Board manager or Click Here to download the ESP8266 board.
  3. Download the required libraries from the following links:
  • Sinric Pro by Boris Jaeger (Download Sinric Pro examples for ESP8266 & ESP32)
  • WebSockets by Markus Sattler (minimum Version 2.3.5)
  • ArduinoJson by Benoit Blanchon (minimum Version 6.12.0)

Click Here to visit the GitHub page of Sinric Pro for more details.

**Please download the latest version of the libraries from the given links. Then install the libraries at Arduino IDE – SketchInclude LibraryAdd Zip Library.

Code for NodeMCU home automation system

// Uncomment the following line to enable serial debug output
//#define ENABLE_DEBUG

#ifdef ENABLE_DEBUG
       #define DEBUG_ESP_PORT Serial
       #define NODEBUG_WEBSOCKETS
       #define NDEBUG
#endif 

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include "SinricPro.h"
#include "SinricProSwitch.h"

#include <map>

#define WIFI_SSID         "YOUR-WIFI-NAME"    
#define WIFI_PASS         "YOUR-WIFI-PASSWORD"
#define APP_KEY           "YOUR-APP-KEY"      // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET        "YOUR-APP-SECRET"   // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"

//Enter the device IDs here
#define device_ID_1   "SWITCH_ID_NO_1_HERE"
#define device_ID_2   "SWITCH_ID_NO_2_HERE"
#define device_ID_3   "SWITCH_ID_NO_3_HERE"
#define device_ID_4   "SWITCH_ID_NO_4_HERE"

// define the GPIO connected with Relays and switches
#define RelayPin1 5  //D1
#define RelayPin2 4  //D2
#define RelayPin3 14 //D5
#define RelayPin4 12 //D6

#define SwitchPin1 10  //SD3
#define SwitchPin2 0   //D3 
#define SwitchPin3 13  //D7
#define SwitchPin4 3   //RX

#define wifiLed   16   //D0

// comment the following line if you use a toggle switches instead of tactile buttons
//#define TACTILE_BUTTON 1

#define BAUD_RATE   9600

#define DEBOUNCE_TIME 250

typedef struct {      // struct for the std::map below
  int relayPIN;
  int flipSwitchPIN;
} deviceConfig_t;


// this is the main configuration
// please put in your deviceId, the PIN for Relay and PIN for flipSwitch
// this can be up to N devices...depending on how much pin's available on your device ;)
// right now we have 4 devicesIds going to 4 relays and 4 flip switches to switch the relay manually
std::map<String, deviceConfig_t> devices = {
    //{deviceId, {relayPIN,  flipSwitchPIN}}
    {device_ID_1, {  RelayPin1, SwitchPin1 }},
    {device_ID_2, {  RelayPin2, SwitchPin2 }},
    {device_ID_3, {  RelayPin3, SwitchPin3 }},
    {device_ID_4, {  RelayPin4, SwitchPin4 }}     
};

typedef struct {      // struct for the std::map below
  String deviceId;
  bool lastFlipSwitchState;
  unsigned long lastFlipSwitchChange;
} flipSwitchConfig_t;

std::map<int, flipSwitchConfig_t> flipSwitches;    // this map is used to map flipSwitch PINs to deviceId and handling debounce and last flipSwitch state checks
                                                  // it will be setup in "setupFlipSwitches" function, using informations from devices map

void setupRelays() { 
  for (auto &device : devices) {           // for each device (relay, flipSwitch combination)
    int relayPIN = device.second.relayPIN; // get the relay pin
    pinMode(relayPIN, OUTPUT);             // set relay pin to OUTPUT
    digitalWrite(relayPIN, HIGH);
  }
}

void setupFlipSwitches() {
  for (auto &device : devices)  {                     // for each device (relay / flipSwitch combination)
    flipSwitchConfig_t flipSwitchConfig;              // create a new flipSwitch configuration

    flipSwitchConfig.deviceId = device.first;         // set the deviceId
    flipSwitchConfig.lastFlipSwitchChange = 0;        // set debounce time
    flipSwitchConfig.lastFlipSwitchState = true;     // set lastFlipSwitchState to false (LOW)--

    int flipSwitchPIN = device.second.flipSwitchPIN;  // get the flipSwitchPIN

    flipSwitches[flipSwitchPIN] = flipSwitchConfig;   // save the flipSwitch config to flipSwitches map
    pinMode(flipSwitchPIN, INPUT_PULLUP);                   // set the flipSwitch pin to INPUT
  }
}

bool onPowerState(String deviceId, bool &state)
{
  Serial.printf("%s: %s\r\n", deviceId.c_str(), state ? "on" : "off");
  int relayPIN = devices[deviceId].relayPIN; // get the relay pin for corresponding device
  digitalWrite(relayPIN, !state);             // set the new relay state
  return true;
}

void handleFlipSwitches() {
  unsigned long actualMillis = millis();                                          // get actual millis
  for (auto &flipSwitch : flipSwitches) {                                         // for each flipSwitch in flipSwitches map
    unsigned long lastFlipSwitchChange = flipSwitch.second.lastFlipSwitchChange;  // get the timestamp when flipSwitch was pressed last time (used to debounce / limit events)

    if (actualMillis - lastFlipSwitchChange > DEBOUNCE_TIME) {                    // if time is > debounce time...

      int flipSwitchPIN = flipSwitch.first;                                       // get the flipSwitch pin from configuration
      bool lastFlipSwitchState = flipSwitch.second.lastFlipSwitchState;           // get the lastFlipSwitchState
      bool flipSwitchState = digitalRead(flipSwitchPIN);                          // read the current flipSwitch state
      if (flipSwitchState != lastFlipSwitchState) {                               // if the flipSwitchState has changed...
#ifdef TACTILE_BUTTON
        if (flipSwitchState) {                                                    // if the tactile button is pressed 
#endif      
          flipSwitch.second.lastFlipSwitchChange = actualMillis;                  // update lastFlipSwitchChange time
          String deviceId = flipSwitch.second.deviceId;                           // get the deviceId from config
          int relayPIN = devices[deviceId].relayPIN;                              // get the relayPIN from config
          bool newRelayState = !digitalRead(relayPIN);                            // set the new relay State
          digitalWrite(relayPIN, newRelayState);                                  // set the trelay to the new state

          SinricProSwitch &mySwitch = SinricPro[deviceId];                        // get Switch device from SinricPro
          mySwitch.sendPowerStateEvent(!newRelayState);                            // send the event
#ifdef TACTILE_BUTTON
        }
#endif      
        flipSwitch.second.lastFlipSwitchState = flipSwitchState;                  // update lastFlipSwitchState
      }
    }
  }
}

void setupWiFi()
{
  Serial.printf("\r\n[Wifi]: Connecting");
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.printf(".");
    delay(250);
  }
  digitalWrite(wifiLed, LOW);
  Serial.printf("connected!\r\n[WiFi]: IP-Address is %s\r\n", WiFi.localIP().toString().c_str());
}

void setupSinricPro()
{
  for (auto &device : devices)
  {
    const char *deviceId = device.first.c_str();
    SinricProSwitch &mySwitch = SinricPro[deviceId];
    mySwitch.onPowerState(onPowerState);
  }

  SinricPro.begin(APP_KEY, APP_SECRET);
  SinricPro.restoreDeviceStates(true);
}

void setup()
{
  Serial.begin(BAUD_RATE);

  pinMode(wifiLed, OUTPUT);
  digitalWrite(wifiLed, HIGH);

  setupRelays();
  setupFlipSwitches();
  setupWiFi();
  setupSinricPro();
}

void loop()
{
  SinricPro.handle();
  handleFlipSwitches();
}

Enter the APP KEY and APP SECRET with Wi-Fi name and Wi-Fi password in the code.

You can get the APP KEY and APP SECRET under the Credentials menu in Sinric Pro

#define WIFI_SSID         "YOUR-WIFI-NAME"    
#define WIFI_PASS         "YOUR-WIFI-PASSWORD"
#define APP_KEY           "YOUR-APP-KEY"
#define APP_SECRET        "YOUR-APP-SECRET"

Also, enter the device id in the code. You will find the Device ID from the Devices menu.

//Enter the device IDs here
#define device_ID_1   "SWITCH_ID_NO_1_HERE"
#define device_ID_2   "SWITCH_ID_NO_2_HERE"
#define device_ID_3   "SWITCH_ID_NO_3_HERE"
#define device_ID_4   "SWITCH_ID_NO_4_HERE"

**When you add a device in Sinric Pro, a unique ID is assigned to that device. If you create 3 devices, then there will be 3 unique device IDs.

As I have used the free Sinric pro account, so I have entered the 3-device IDs. (Sinric Pro gives 3 devices for FREE)

Uncomment the following line if you use pushbuttons instead of toggle switches.

//#define TACTILE_BUTTON 1

After uploading the code to NodeMCU, please refer to the following articles for connecting the Sinric Pro Account with Amazon Alexa and Google Home App.

After doing all these steps, now you control the appliances with Google Assistant and Alexa.

NodeMCU control Relays with Alexa App

Control Relays with Alexa App

If the NodeMCU is connected with WiFi, then you can ask Alexa, to turn on the light [“Alexa, Turn ON Room Light“]. Thus, you can control the appliances like light, fan, etc with voice commands using Amazon Alexa App, and also monitor the current status of the switches from anywhere in the world from the Alexa App.

NodeMCU control Relays with Google Assistant

Smart Home with Google Assistant

You can also ask Google Assistant, to turn on the light [“Hey Google, Turn ON the Room Light“]. Thus, you can control the appliances like light, fan, etc with voice commands using Google Assistant, and also monitor the current status of the switches from anywhere in the world from the Google Home App.

Control relays manually with Switches

You can always control the appliances manually with switches or push buttons. and if the NodeMCU is connected with the Wi-Fi, then you can monitor the real-time status in Google Home and Alexa App.

PCB for the NodeMCU Smart Home

Solder the Components on PCB

If you want, you can also use this PCB to make the circuit compact and give the project a professional look.

Smart Home with Google Assistant & Alexa

I hope you like this Smart house IoT projects idea with the NodeMCU ESP8266.

Click Here for more such ESP8266 projects.

Please do share your feedback on this IoT project. Thank you for your time.