Friday, July 3, 2020

Hey google whats the temperature in my house

For a complete index to all my stories click this text.

This is the last in a series of 3 stories about getting Google Home to give us information about the sensors in our home.

Let me summarise the goal.
We can give Google Home Assistant many commands if we have a home automation system. We can tell Google Home Assistant to put the lights on or off, we can tell it to raise the temperature in our home and we can tell it to set the color of our lamps to red etc etc etc. All depending on wether we have the right equipment to achieve this.

What you can not do however is ask your Assistant what the temperature in your home is. Or ask it wether the lights in your room are on or off. If the information you want to get is from the room you are in, that is not very interesting.
But how about sitting in your lazy chair in the living room and asking your assistant wether the lights in the attick are off, or if the garage door was closed. And that is just what I am going to show you here.



The idea rose when I was playing with the Google Home notifier library. I could make Google say any sentence I wanted and then I could have it inform me about the temperature in my hobby room when I pressed a button on my ESP32. You can re-read those stories here:
http://lucstechblog.blogspot.com/2020/03/esp32-makes-google-assistant-talk.html
http://lucstechblog.blogspot.com/2020/04/esp-makes-google-assistant-talk-part-2.html


Pressing a button to get the information is no real fun. No, we want to ask the Assistant what the temperature is.
Then it occurred to me that I could trigger IFTTT with the Google Home Assistant. And if I triggered IFTTT I could have IFTTT send a webhook to an ESP. And with that webhook I could initiate the Google Notifier Library to have Google say the temperature.

Presto that is what we want and that way we can ask our assistant anything we want !!!!

So this is going to be a lengthy post. It is not difficult to achieve this but it involves many steps. Make sure you understand each step and you can replicate this and apply it for your own purposes.

The overall picture

Before we start with the details I am going to tell you how this works.

First you need to come up with a trigger word. A word that will trigger the Google Home Assistant to send your question to IFTTT. In this example I use the word HOME as the trigger word.

Next you will have to define what you want to know. In this example I want to know the temperature and the status of my LIVING ROOM LIGHT SWITCH.
To get this information I speak out the words OK GOOGLE HOME TEMPERATURE or OK GOOGLE HOME LIVING ROOM LIGHT SWITCH. Google Home Assistant hears these words and the HOME word makes sure that the words are send to IFTTT

IFTTT then activates a webhook that will send the word TEMPERATURE or the words LIVING ROOM LIGHT SWITCH to my ESP32. In the mean time it tells the Assistant to inform you that the information is being checked.

The webserver in the ESP32 receives the words from IFTTT and checks which action must be taken. In the case the word TEMPERATURE is received it will check the temperature from the Dallas DS18B20

The server then forms a sentence with the temperature and sends that (by use of the library) to the Google Home Assistant.

And the last step is that the Google Home Assistant speaks out the requested information.

Breadboard

For demonstration purposes I made a setup in which I attached a Dallas DS18B20 thermometer to an ESP32. We are going to ask the Google Home Assistant what the temperature in our house is.



The breadboard setup is simple. Just a Dallas DS18B20 thermometer with a push-up resistor.
If you do not have a DS18B20 in stock use a potmeter, LDR or anything you might have that can supply a value. Even a simple switch would do the trick. Just adjust the software accordingly.

Prerequisites

Like I showed you in the previous two articles in this series: to get this working we need 2 libraries.

The first one is esp8266-google-tss which can be found here:
https://github.com/horihiro/esp8266-google-tts
and the second one is esp8266-google-home-notifier which can be found here:  
https://github.com/horihiro/esp8266-google-home-notifier

I urge you to install the latest Arduino IDE and then you can find the libraries also in the Libary manager found under the Sketch tab of the IDE.

The first library being esp8266-google-tts takes some text as input and sends it to Google. Google makes an MP3 file from that text.
The second library, esp8266-google-home-notifier, gets the MP3 file and sends it to your Google Home.

Next to that you need to know the name of your Google Home Assistant.
There are two ways to find your assistant. Both have to be done on your Android Phone.

If you gave Google Assistant installed on your phone swipe to the assistant screen and scroll down till you see the name of the Google Home Assitant. Mine is called Living Room speaker.

The second way to find your Assistant is to open the Assistant App and there you can also find the name of your Assistant. Again you can see the name Living Room speaker

With this information you are ready to start programming.

The program.

To get this working we need to have the libraries to find and contact the Google Home Assitant. Then the program waits till it gets a notification from IFTTT and when it does it needs to read the sensor data and send a sentence to the libraries that your Assistant will speak out loud.
To achieve this we will load the libraries and start a webserver that listens to incoming commands.

 /* 
 =================================================  
 * Program by Luc Volders  
 * http://lucstechblog.blogspot.nl/  
 * Program gets temperature from DS18B20
 *================================================*/  
 #include <WiFi.h>  
 #include <esp8266-google-home-notifier.h>

 #include <OneWire.h>
 #include <DallasTemperature.h>

 #define ONE_WIRE_BUS 23             //D23 of ESP32

 OneWire oneWire(ONE_WIRE_BUS); 
 DallasTemperature dallas(&oneWire); // reference to Dallas Temperature.
 
 WiFiClient client;  
 WiFiServer server(80);  
 const char* ssid = "XXXXXXXXXXXX";  
 const char* password = "YYYYYYYYYYYYYYY";  
 String  txtnotify;

 GoogleHomeNotifier ghn;
 
 String command ="";   
  
 void setup()  
 {  
  Serial.begin(115200);  
  dallas.begin();
  connectWiFi();  
  server.begin();  

  const char displayName[] = "Living Room speaker";

  Serial.println("connecting to Google Home...");
  if (ghn.device(displayName, "en") != true) 
  {
  Serial.println(ghn.getLastError());
  return;
  }
  Serial.print("found Google Home(");
  Serial.print(ghn.getIPAddress());
  Serial.print(":");
  Serial.print(ghn.getPort());
  Serial.println(")");
 }  
 
 void loop()  
 {  
   client = server.available();  
   if (!client) return;   
   Serial.print("received : ");
   
   command = checkClient();  
   Serial.println(command);
   
   if (command == "temperature")
   {
   dallas.requestTemperatures();                // get temperatures  
   Serial.print("Temperature is: ");
   Serial.println(dallas.getTempCByIndex(0));   // 0 refers to the first DS18b20
   txtnotify  = "the temperature is ";
   txtnotify = txtnotify + String(int(dallas.getTempCByIndex(0)));
   txtnotify = txtnotify + " degrees";
   ghn.notify(txtnotify.c_str());
   }
   
   if (command == "living%20room%20light%20switch")
   { 
    ghn.notify("The living room light is on");
   }
   command = "";  
 }  
 
 
 void connectWiFi()  
 {  
  Serial.println("Connecting to WIFI");  
  WiFi.begin(ssid, password);  
  while ((!(WiFi.status() == WL_CONNECTED)))  
  {  
   delay(300);  
   Serial.print("..");  
  }  
  Serial.println("");  
  Serial.println("WiFi connection established");  
  Serial.print("IP number is : ");  
  Serial.println((WiFi.localIP()));  
 }  
 
 String checkClient (void)  
 {  
  while(!client.available()) delay(1);   
  String request = client.readStringUntil('\r');  
  request.remove(0, 5);  
  request.remove(request.length()-9,9);  
  return request;  
 }  

As you will need to adapt this to your own needs and settings I will give you an explanation of each part in the program.

 #include <WiFi.h>  
 #include <esp8266-google-home-notifier.h>

 #include <OneWire.h>
 #include <DallasTemperature.h>

 #define ONE_WIRE_BUS 23             //D23 of ESP32

 OneWire oneWire(ONE_WIRE_BUS); 
 DallasTemperature dallas(&oneWire); // reference to Dallas Temperature.
 
 WiFiClient client;  
 WiFiServer server(80);  
 const char* ssid = "XXXXXXXXXXXX";  
 const char* password = "YYYYYYYYYYYYYYY";  
 String  txtnotify;

 GoogleHomeNotifier ghn;
 
 String command ="";

As you can see the libraries are loaded. The Wifi library is needed to build the webserver and the webclient. The library for the Google Home Assitant will automatically load the other library. The Onewire libary and the DallasTemperature library are necessarry for the DS18B20 thermometer. You do not need them if you are using a potmeter or an LDR as the sensor.

Do not forget to replace the XXXXXXXXX and YYYYYY with the credentials for your router.

In the setup() the Serial port is activated. We will use that to display information about IP-adress and sensor readings for checking. The connectWifi routine is just a subroutine that connects the ESP32 to the router and is a routine that is used in every program that connects an ESP to a router.

const char displayName[] = "Living Room speaker";

This line is very important. Fill in the name of your Assistant which you found in your APP. Do this exact otherwise the library will not be able to find the Assistant on your network and the complete project will not work.

If you spelled the name right the setup will give your Google Home Assistants IP number in the Serial monitor. Otherwise it will give an error.

The loop() starts with a check wether the server and client are available. Then the program waits till the checkClient routine has received a word or sentence.
So the webserver just sits here waiting till it gets some information from the outside world. If information is received that will be printed in the Serial Monitor as a check to see if the right words were received.

In this program I am testing for 2 commands. The first is temperature the second is living room light switch.

   if (command == "temperature")
   {
   dallas.requestTemperatures();                // get temperatures  
   Serial.print("Temperature is: ");
   Serial.println(dallas.getTempCByIndex(0));   // 0 refers to the first DS18b20
   txtnotify  = "the temperature is ";
   txtnotify = txtnotify + String(int(dallas.getTempCByIndex(0)));
   txtnotify = txtnotify + " degrees";
   ghn.notify(txtnotify.c_str());
   }

As you can see the program checks for the word temperature. You can alter this to your own needs or whishes. Just make sure you remember which words you are going to use to have the Assistant react on.

If the word - temperature - is received the Dallas thermometer is checked and a string is build which the Google Home Assistant is going to speak out. The string consists of the words "the temperature is " and the value the DS18B20 gives.

ghn.notify(txtnotify.c_str());

As the Google Home Notifier library only accepts a c-string we have to convert our information to the c-string format.

In this example program I build a request for another kind of information.


   if (command == "living%20room%20light%20switch")
   { 
    ghn.notify("The living room light is on");
   }

These lines test for -- living room light switch --. So when I say that command to the Google Home Assistant it will check for the living room lights.
However this is just an example for your convenience so in this program it does nothing besides having your Assistant speak the words: "The living room light is on"
I am just putting this her so you can see how you can expand the program to check for any sensor reading you might want to build in. Just remember that IFTTT will not send spaces. These will be replaced by %20 so make sure you fill %20 in at each place in the sentence where there is a space like I did above.

ESP32 with a fixed IP adress

When you start the program the ESP32 will get an IP adress from your router and shows that in the Serial Monitor.

However if the ESP32 is powered down and restarted it might get a new and different IP adress. This provides us with a problem. IFTTT is going to send information to our router and the router needs to know which device wants that information.
So in the router you will need to do something that is called port forwarding. You will need to open a door (port) to which IFTTT sends its info and the router knows to which device (the ESP32) that info has to be send to.
But if the IP adress of the ESP32 changes by powering down and powering up, the router does not have the new IP adress it has the old IP adress and the ESP32 will not get the required info.

So start with opening your routers webpage or app and find the IP adress of your ESP32.


As you can see in my router I found my ESP32 which is the last in the list of wireless devicess.


In my router I can click on the device and I will get the IP adress. Now choose "add device into static DHCP". This way the ESP32 will get a fixed IP adress and therefoer will get every time it restarts the same IP adress.



Open the portforwarding part in your router and add a new entry. Fill in the IP number of the ESP32 the trigger port (8085) and the translation port (80). If port 8085 is already in use you may use another port number. Just make sure you use the same number in IFTTT.

Done.

Your external IP adress

With the steps described above we know the ESP32's IP adress. But that is the adress within your own home (or office) network. There is also an internet IP adress which obviously is the adress your router has on the internet.

We are going to use IFTTT as a middle man in our project. So IFTTT has to send information to the ESP32. However IFTTT is a server somewhere in the world and it does not know your IP adress.


You can find your IP adress using the website: https://www.myip.com/

For my safety I blacked out all relevant information. But when you use this service the most important part is the first line with your IP adress on the internet. Write it down cause you need to fill it in, in the IFTTT part.

Last step: IFTTT

Make sure you have an account at IFTTT or otherwise create one. IFTTT is a great free service which can be used for many projects and other purposes and is therefore really worth checking out. I have written more then 10 stories on IFTTT on this weblog and you can check these for detailed information.

http://lucstechblog.blogspot.com/p/index-of-my-stories.html




Start with creating a new app and click on This.



As service type go as the picture shows you and Google Assistant will come up. Click on it.



The screen shows you several possibillities. Choose "Say a phrase with a text ingredient" which is on the left-bottom side.


As you can see I used home as the trigger word. So each time the Google Home Assistant hears the word home it will pass whatever you say to IFTTT. After the word home there is a $ sign. This is a variable that will hold any words you have said after the word home. So if you say HOME TEMPERATURE the $ will get the word TEMPERATURE.

The Assistant then speaks the words in the response:

ok give me a moment I check the $

and again $ will be replaced by whatever you said after the word home.

Now click on create trigger.



This part is finished so we are going to define what will happen. Click on That.


When the IF part was triggered we need to define what will happen. There are a lot of services available.


Type in webh and the webhooks icon will come up. Click on it.

There is only one action we can choose from and that is Make a web request. Click on it.



Here we are going to define the web request. It will be a GET request to our IP adress and port number.
In the URL fill in the IP adress and port number as defined in your router. It has to be in the form off: http://XXX.XXX.XXX.XXX:YYYY/TextField
Replace the XXX.XXX.XXX.XXX with the IP adress of the ESP32 and YYYY with the port number you assigned in the router (8085).

Then choose CREATE ACTION and we are done.

How to use it.

So now we can ask our Google Home Assistant what the temperature is in our house. Just say:

OK GOOGLE, HOME TEMPERATURE

Google will answer with;

OK GIVE ME A MOMENT I CHECK THE TEMPERATURE

and within a second or two a bell will ring and the Assistant will say:

THE TEMPERATURE IS XX DEGREES

YAY we have done it.
We can alter the ESP32 program to check for any word we want and then can ask it for any sensor information related to that word !!!

So we can not only command the Google Assistant but now we can actually ask it for relevant information !!!

Have fun and till next time.
Oh, and if you are starting with the ESP32 and IOT, don't forget to buy my book.

Luc Volders