Project tutorial
Smart Switch Using Arduino and Alexa

Smart Switch Using Arduino and Alexa © GPL3+

Temperature sensor is used to control a switch (relay) to turn on or off the device.

  • 59 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project

List of materials

Total cost of the project is about $30.

This project is divided into three parts. First, we use Heroku to create an app and link GitHub with Heroku. Second, we build an Amazon Alexa skill to implement our work (most important part). Third, we setup our hardware and program it using Arduino IDE.

Heroku is a cloud platform as a service (PaaS) supporting several programming languages that is used as a web application deployment model.

First, go to heroku site create a new account or login there. Link is given:

Let's start with creating a new app. I have given my app the name "iottempswitch".

Once the app is made go to GitHub:

Login there or signup if you do not have an account. Once logged in, create new repository.

When you click, you will see page like this.

Give any name you want to choose and then press create repository. After that you will see page like this.

On this page, click on README and you will see page like this.

On this page, give the description you want to share with others. After that, click on commit new file.

Next, click on upload button. You will see a page like this.

There are two options: either you drag-and-drop the folder or choose the file. Download the required files from below.

After selecting the files, press commit changes. You will see page like this.

Once done, it will look like this.

Next we upload three libraries. Click again on the upload file, upload the required files.

Create a new file, name it Procfile and write web: python After that commit it.

Create new file, name it requirements.txt and write websockets==3.2.

Create new file, name it runtime.txt and write python-3.6.3 or python-3.6.4

Open app which you created at Heroku then go to deploy section.

Click on GitHub you will see like this.

Give repository name which you created at GitHub side. In my case it is Smart-Relay. Copy that and paste it here. You will see like this.

Once your link is shown click on connect. You will see like this.

Next, click on deploy branch.

After completing deploy you will see like this.

Now, we have created our app successfully. Go to setting and use this link for Amazon and Arduino program.

We have successfully linked Heroku with Github.

2. Amazon

On Amazon Developer site we use Amazon skill to control switch trigger by setting temperature and humidity.

  • Go to Developer console.
  • Go to Alexa then select Alexa Skill Kit and then create new skill by clicking on Add new skill. When you add new skill you will see skill information page.

1. Skill Information

We have to provide skill type, language, name.

  • It will ask for skill name and language.
  • Name ==> Select any name.
  • Language ==> Choose according to your region or country.
  • On next page it will ask for skill type, there are three skill type namely custom, flash briefing, smart home.
  • Skill type ==> select custom.

After that you will see a page like this.

2. Interaction Model

Now invocation name comes under interaction model before it comes under skill information.

  • Go to invocation section and give any you want to use.
  • Invocation name ==> which you use while communicating with Alexa.

For example: Alexa, ask sensor to turn switch trigger on or Alexa, ask light on, here invocation names are sensor and light.

  • Firstly, we create new intents. Click on Add (on left hand side) and give any name you want I used "smartswitch". After that add slots type.
  • Give slot type name "measurement_type" and slot values "temperature" and "humidity".
  • After that add slot type name "query" and slot values are "what" and "is". It will look like this.
  • After that add slot type "switchstate" and slot values are "on" and "off".
  • Add another slot type "tempscale" and slot values are "fahrenheit" and "celcuis".
  • After that add new slot type here we use existing slot type for that we have to click on use existing slot.In existing slot search for amazon.number and select this and add it. After adding it you will see it in slot types.

So we are done with slot types; in total, we are using 5 slot types. Now, move to the next step.

Click on intent which we created, in my case it is smartswitch. At the bottom you will see intent slot.

  • Create a new slot, give it name "Switch_State" and map it to "switchstate" by using drop down button.
  • Create new slot, give it name "Sensor_Values" and map it to "measurement_type".
  • Create new slot, give it name "query" and map it to "query".
  • After that create new slot "tmp_scale" and map it to "tempscale".
  • Create new slot "Numbers" and map it to "Amazon.Number".

Now we are done with Intent slots. We are using 5 intent slots. After this we move to Sample Utterances.

Add this sample utterances.

set switch trigger to {Numbers} percent {tmp_scale} 
{query} is the switch state 
{Switch_State} switch trigger 
set switch trigger to {Numbers} degree {tmp_scale} 
turn switch {Switch_State} 
{query} switch {Switch_State} 
{query} is the current {Sensor_Values} 

After this save model and build it.

Wait for model to be build after that click on configuration.

3. Endpoint

Select HTTPS and add link which was generated while creating Heroku app. In my case it is After adding link, for SSL certificate select second option and click on next.

Good going, we have successfully created our custom skill.

3. Arduino

For ESP8266

Step 1

  • Open Arduino IDE.Then go to File ==> Preference.

Step 2

Step 3

  • Open Board Manager by going to Tools ==> Board ==> Board Manager.

Step 4

  • Open Boards Manager and search for nodemcu.

Step 5

After that download ESP8266WiFi library.

  • Open library Manager : Sketch ==> Include library ==> Manage Libraries.

Step 6

  • Search for ESP8266WiFi library:

Step 7

  • Select board ==> Generic ESP8266 Module.
  • Before uploading the code we need three libraries: Libraries

Move these libraries to the libraries folder of Arduino.

You have to change three things in code SSID, PWD and your heroku app link. After that upload the code. For ESP modules you have to press flash button while uploading the code and then press reset button one time and then release the flash button.

After uploading the code, open the terminal. you will see output.

4. Component Description

1. Relay

Relay is an electromagnetic device which is used to isolate two circuits electrically and connect them magnetically. They are very useful devices and allow one circuit to switch another one while they are completely separate. They are often used to interface an electronic circuit (working at a low voltage) to an electrical circuit which works at very high voltage. For example, a relay can make a 5V DC battery circuit to switch a 230V AC mains circuit.

How it works

A relay switch can be divided into two parts: input and output. The input section has a coil which generates magnetic field when a small voltage from an electronic circuit is applied to it. This voltage is called the operating voltage. Commonly used relays are available in different configuration of operating voltages like 6V, 9V, 12V, 24V etc. The output section consists of contactors which connect or disconnect mechanically. In a basic relay there are three contactors: normally open (NO), normally closed (NC) and common (COM). At no input state, the COM is connected to NC. When the operating voltage is applied the relay coil gets energized and the COM changes contact to NO. Different relay configurations are available like SPST, SPDT, DPDT etc, which have different number of changeover contacts. By using proper combination of contactors, the electrical circuit can be switched on and off. Get inner details about structure of a relay switch.

The COM terminal is the common terminal. If the COIL terminals are energized with the rated voltage, the COM and the NO terminals have continuity. If the COIL terminals are not energized, then the COM and the NO terminals have no continuity.

The NC terminal is the Normally Closed terminal. It is the terminal that can be powered on even if the relay doesn't receive any or sufficient voltage to operate.

The NO terminal is the Normally Open terminal. It is the terminal where you place the output that you want on when the relay receives its rated voltage. If there is no voltage to the COIL terminals or insufficient voltage, the output is open and receives no voltage. When the COIL terminals receive the rated voltage or a little under, the NO terminal receives sufficient voltage and can turn on the device on the output.

2. DHT temperature sensor

DHT11 is a Humidity and Temperature Sensor, which generates calibrated digital output. DHT11 can be interface with any micro controller like Arduino, Raspberry Pi, etc. and get instantaneous results. DHT11 is a low cost humidity and temperature sensor which provides high reliability and long term stability.

3. ESP8266 Complete Description

The ESP8266 WiFi Module is a self-contained SOC with integrated TCP/IP protocol stack that can give any microcontroller access to your WiFi network. The ESP8266 is capable of either hosting an application networking functions from another application. Each ESP8266 module comes pre-programmed with an AT command.

The ESP8266 supports APSD for VoIP applications and Bluetooth co-existence interfaces, it contains a self-calibrated RF allowing it to work under all operating conditions, and requires no external RF parts.


  • 802.11 b/g/n
  • Wi-Fi Direct (P2P), soft-AP
  • Integrated TCP/IP protocol stack
  • Integrated TR switch, balun, LNA, power amplifier and matching network
  • Integrated PLLs, regulators, DCXO and power management units
  • +19.5dBm output power in 802.11b mode
  • Power down leakage current of <10uA
  • 1MB Flash Memory
  • Integrated low power 32-bit CPU could be used as application processor
  • SDIO 1.1 / 2.0, SPI, UART
  • STBC, 1×1 MIMO, 2×1 MIMO
  • A-MPDU & A-MSDU aggregation & 0.4ms guard interval
  • Wake up and transmit packets in < 2ms
  • Standby power consumption of < 1.0mW (DTIM3)

Pin Diagram and Pin Description

For connecting ESP Module with Arduino UNO we need Lm117 3.3 voltage regulator or any regulator because Arduino is not capable of providing 3.3 v to ESP8266.

Note: While uploading the code press flash button and then press reset button one time and then release flash button.

For connecting DHT11 sensor and relay we use two GPIO pins of ESP8266 Module. After uploading the code you can disconnect the RX, TX, GPIO0 pins.

I have used GPIO0 for DHT11 sensor and GPIO2 for relays. DHT11 sensor works fine with ESP8266 but for relays we need one extra thing, i.e, opto isolator or opto coupler.

5. Connections

ESP8266 === > DHT11

  • GPIO0 === > Output pin

ESP8266 === > Relay

  • GPIO2 ===> Input

ARDUINO ===> ESP8266

  • Gnd ===> Gnd
  • TX === > TX
  • RX === > RX
  • Reset Button === > RST
  • Flash Button === > GPIO0

6. After setup all the thing

We have successfully created our app, skill and our hardware is ready. So, its time to check.

For that your ESP8266 is powered on because our server is running on ESP8266. Here I have not connected any sensor to ESP8266 I am just checking whether its working or not but you can connect sensor, relay to ESP8266. Once it is connected to Heroku you will see connected. For testing go to Amazon skill which you created, then click on test page. Once it is verified its working I will connect my sensor to ESP8266. You can see results as shown below in Result section.

If you use it without connecting ESP8266 you get this error.

Utterance you can use

  • set switch trigger to {Numbers} percent {tmp_scale}

ex. set switch trigger to 50 percent humidity

  • {query} is the switch state

ex. on/off is the switch state

  • {Switch_State} switch trigger

ex. on/off switch trigger

  • set switch trigger to {Numbers} degree {tmp_scale}

ex. set switch trigger to 76 degree fahrenheit

ex. set switch trigger to 24 degree celcius

  • turn switch {Switch_State}

ex. turn switch on/off

Note: In this we are able to control the appliances like A.C, Fan, Cooler etc by setting or selecting appropriate temperature.

For example, A.C is connected to relay and we set temperature 24 degree Celsius once temperature is rising above that, temperature sensor will detect and turn ON the A.C. When temperature is maintained, it will again switch it off the A.C.

7. While talking to Alexa

  • Alexa, ask arduino to turn switch trigger on/off
  • Alexa, ask arduino to set switch trigger to 24 degree celsius.
  • Alexa, ask arduino to set switch trigger to 50 percent humidity.
  • Alexa, ask arduino to turn switch on/off


Temperature and humidity reading.

Set trigger to 90 percent humidity.

Set trigger for 21 degree celcius.

VUI Diagram


1. Set trigger for temperature and humidity (using Arduino)

2. Set trigger to 20 degree celsius (using Arduino)

3. Set trigger to 80 percent humidity (using Arduino)

File needed for GitHub. Please download from link given below.



#include <dht.h>
#include <ArduinoJson.h> 
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h>
#include <Hash.h>
// @@@@@@@@@@@@@@@ You only need to modify wi-fi and domain info @@@@@@@@@@@@@@@@@@@@
const char* ssid     = ""; //enter your ssid/ wi-fi(case sensitive) router name - 2.4 Ghz only
const char* password = "";     // enter ssid password (case sensitive)
char host[] = ""; //- better your Heroku domain name like  "" 
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#define dht_dpin 5          // GPIO 5 (D1) OR for ESP change it to GPIO0
const int relayPin = 16;    // GPIO 16 (D0) OR change it to GPIO2
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
dht DHT;
int port = 80;
char path[] = "/ws"; 
ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
DynamicJsonBuffer jsonBuffer; 
String currState;
int pingCount = 0;
String triggerName ="";
String triggerVal ="";
int triggerEnabled = 0;
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { //uint8_t *

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

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


void setup() {
    pinMode(relayPin, OUTPUT);
      for(uint8_t t = 4; t > 0; t--) {
    Serial.print("Connecting to ");
    WiFiMulti.addAP(ssid, password);

    while( != WL_CONNECTED) {
    Serial.println("Connected to wi-fi");
    webSocket.begin(host, port, path);


void loop() {

    if (triggerEnabled==1){
  //If you make change to delay make sure adjust the ping
	// 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;
    	}else {pingCount += 1;}

void processWebScoketRequest(String data){
            String jsonResponse = "{\"version\": \"1.0\",\"sessionAttributes\": {},\"response\": {\"outputSpeech\": {\"type\": \"PlainText\",\"text\": \"<text>\"},\"shouldEndSession\": true}}";
            JsonObject& root = jsonBuffer.parseObject(data);
            String query = root["query"];
            String message="";
            if(query == "cmd"){ //if query check state
                      String value = root["value"];  
                      Serial.println("Recieved command!");
                      digitalWrite(relayPin, HIGH);
                      message = "{\"state\":\"ON\"}";
                      currState = "ON";
                    }else if (value=="off"){
                      digitalWrite(relayPin, LOW);
                      message = "{\"state\":\"OFF\"}";
                      currState = "OFF";
                    }else if (value=="deactivate"){
                      //deactivate trigger
                      triggerEnabled = 0;
                      String object = root["object"];
                      //set trigger for temp and humidity
                      triggerName = object;
                      triggerVal = value;
                      triggerEnabled = 1;
                    jsonResponse.replace("<text>", "It is done");
            }else if(query == "?"){ //if command then execute   
              Serial.println("Recieved query!");
              int state = digitalRead(relayPin);
              String value = root["value"];
                      message = "{\"state\":\"ON\"}";
                      message = "{\"state\":\"OFF\"}";
                }else if(value=="humidity"){
                  //response with current humidity DHT.humidity
                  Serial.println("Humidity response...");
                  jsonResponse.replace("<text>", "current humidity is " + String(DHT.humidity) + " percent");
                }else if(value=="temperature"){  
                  //response with current temperature DHT.temperature /Celcius2Fahrenheit(DHT.temperature)
                  Serial.println("Temp response...");
                  jsonResponse.replace("<text>", "current temperature is " + String(Celcius2Fahrenheit(DHT.temperature))+ " fahrenheit");
            }else{//can not recognized the command
              Serial.println("Command is not recognized!");
            //jsonResponse.replace("<text>", "Garage door " + instance + " is " + message );
            Serial.print("Sending response back");
                  // send message to server
                  if(query == "cmd" || query == "?"){webSocket.sendTXT(jsonResponse);}

void setTrigger(String obj, String val){
  Serial.print("Trigger is set for ");
  Serial.print(" ");
  if(String("fahrenheit") == obj){
      Serial.println("Fahrenheit trigger on!");
        digitalWrite(relayPin, HIGH);
        digitalWrite(relayPin, LOW);
  }else if(String("celsius") == obj){
          Serial.println("Celcius trigger on!");
            digitalWrite(relayPin, HIGH);
            digitalWrite(relayPin, LOW);
          Serial.println("Humidity trigger on!");
          digitalWrite(relayPin, HIGH);
          }else{digitalWrite(relayPin, LOW);

void getTemp(){
    Serial.print("Current humidity = ");
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print("C  ");
    Serial.println("F  ");
  delay(800);//Don't try to access too frequently... in theory
  //should be once per two seconds, fastest,
  //but seems to work after 0.8 second.

double Celcius2Fahrenheit(double celsius){return celsius * 9 / 5 + 32;}
import websockets
import asyncio
import json
import time, os

class HttpWSSProtocol(websockets.WebSocketServerProtocol):
    rwebsocket = None
    rddata = None

    async def handler(self):
            #while True:
            request_line, headers = await websockets.http.read_message(self.reader)
            method, path, version = request_line[:-2].decode().split(None, 2)
        except Exception as e:


        # TODO: Check headers etc. to see if we are to upgrade to WS.
        if path == '/ws':
            # HACK: Put the read data back, to continue with normal WS handling.
            self.reader.feed_data(headers.as_bytes().replace(b'\n', b'\r\n'))

            return await super(HttpWSSProtocol, self).handler()
                return await self.http_handler(method, path, version)
            except Exception as e:


    async def http_handler(self, method, path, version):
        response = ''
        try :
            alexaRequest = self.reader._buffer.decode('utf-8')
            RequestJson = json.loads(alexaRequest)['request']['intent']['slots']

            if 'is' not in RequestJson['query'].values() and 'what' not in RequestJson['query'].values():

                if 'value' not in RequestJson['Switch_State'].keys():
                    value = RequestJson['Numbers']['value']
                    obj = RequestJson['tmp_scale']['value']
                    jsonRequest = {"object": obj.lower(), "value": value, "query": "cmd"}
                    state = RequestJson['Switch_State']['value']
                    print({"object": "switch", "value": state, "query": "cmd"})
                    jsonRequest = {"object": "switch", "value": state, "query": "cmd"}
                if 'value' in RequestJson['Sensor_Values'].keys():
                    if 'temperature' in RequestJson['Sensor_Values']['value']:
                        #print('What is the current temperature?')
                        print({"object": "temperature", "value": "temperature", "query": "?"})
                        jsonRequest = {"object": "temperature", "value": "temperature", "query": "?"}
                        # {"object":"humidity","query":"?"}
                        print('What is the current humidity?')
                        # {"object":"humidity","query":"?"}
                        print({"object": "humidity", "value": "humidity", "query": "?"})
                        jsonRequest = {"object": "humidity", "value": "humidity", "query": "?"}
                    print('What is the switch state?')
                    # {"object":"switch","query":"?"}
                    print({"object": "switch", "value": "state", "query": "?"})
                    jsonRequest = {"object": "switch", "value": "state", "query": "?"}
            with open('data.json', 'w') as outfile:
                json.dump(json.dumps(jsonRequest), outfile)
                #await self.rwebsocket.send(alexaRequest)
            await self.rwebsocket.send(json.dumps(jsonRequest))

            # #wait for response and send it back to IFTTT
            self.rddata = await self.rwebsocket.recv()
            #val ='{"version": "1.0","sessionAttributes": {},"response": {"outputSpeech": {"type": "PlainText","text": "It is done"},"shouldEndSession": true}}'
            response = '\r\n'.join([
                'HTTP/1.1 200 OK',
                'Content-Type: text/json',
                '' + self.rddata,
        except Exception as e:

def updateData(data):
    HttpWSSProtocol.rddata = data

async def ws_handler(websocket, path):
    game_name = 'g1'
        with open('data.json') as data_file:
            data = json.load(data_file)
        HttpWSSProtocol.rwebsocket = websocket
        await websocket.send(data)
        data ='{"empty":"empty"}'
        while True:
            data = await websocket.recv()
    except Exception as e:

def _read_ready(self):
    if self._conn_lost:
        data = self._sock.recv(self.max_size)
    except (BlockingIOError, InterruptedError):
    except Exception as exc:
        self._fatal_error(exc, 'Fatal read error on socket transport')
        if data:
            if self._loop.get_debug():
                print("%r received EOF")
            keep_open = self._protocol.eof_received()
            if keep_open:
                # We're keeping the connection open so the
                # protocol can write more, but we still can't
                # receive more, so remove the reader callback.

asyncio.selector_events._SelectorSocketTransport._read_ready = _read_ready

port = int(os.getenv('PORT', 5687))#5687
start_server = websockets.serve(ws_handler, '', port, klass=HttpWSSProtocol)
#'Listening on port %d', port)

  "name": "Alexa SmartSwitch Temp",
  "description": "Works with IOT devices over the firewall with Alexa skills",
  "repository": "",
  "logo": "",
  "keywords": ["esp8266", "google home", "wihtout ifttt", "iot", "arduino", "Alexa Skills", "Temperature"]
"{\"object\": \"switch\", \"value\": \"on\", \"query\": \"cmd\"}"


Used for programming the ESP
Arduino esp zicqmiqpct
VUI Diagram
Alexa2 xnua9gr2fz
Used after uploading the program to the ESP
Arduino alexa ynlluz2d54


Similar projects you might like

Alexa Based Smart Home Monitoring

Project tutorial by Adithya TG

  • 57 respects

Smart Pool: Alexa Controlled Pool Manager

Project tutorial by Benjamin Winiarski

  • 7 respects

Hygge Home - Alexa Smart Bath

Project tutorial by J Howard

  • 18 respects

Alexa Doorman: Who Is at My Door?

Project tutorial by MD R. Islam

  • 28 respects

Enable Alexa Control to your Ceiling Fan

Project tutorial by Jithin Thulase

  • 9 respects
Add projectSign up / Login