Friday, September 18, 2020

Sending data from ESP to Domoticz

For an index to all of my stories click this text

As you know by now I am using Domoticz as my home automation system. For those who have not read previous posts on this weblog a short introduction. Domoticz is Open Source software that runs on a Raspberry Pi (amongst others) and is the heart of you home automation system. It can switch lights, set the thermostat, check temperature communicate with your telly and stereo check your energy consumption etc. etc. All depending on the use of commercial systems like Philips Hue and 433Mhz light switches to home build sensors. You can find Domoticz here: https://www.domoticz.com/

Domoticz can be controlled in several ways. You can use the original remote controls that are supplied with your lightning system, and Domoticz registers which lights are on or off. Next to that you can control everything from a dashboard on webpage. And there is an app for IOS and Android.

As my girlfriend is something of a computer illiterate I build a special app for her. It is installed on her Android Phone and she can control all lights in our house but the app does not allow her to modify settings in Domoticz. This way she can use the system without fearing to disorganise things.

I myself use the original Domoticz app which allows me to have more control over things. To have full control however, you will have to access the Dashboard through your computer. There is even a scripting language for complete control. You can make scripts that automatically dim the lights when you set your TV on, or set the fan on when temperature rises above a certain level. etc etc etc.

I wanted something else. I wanted control over certain devices in a different way. So I decided to use an ESP8266 as a controller.
Besides that. I am a tinkerer. So whats more fun than getting total control over the systems in your home.

First step

The first step I wanted to examine is how to set a light switch ON and OFF using an ESP8266. I am not going to use ESP-Basic here, I am going to do this with the Arduino IDE.

To set a light ON or OFF we need to know in which way we can send commands to Domoticz. Lucky for us Domoticz is well documented. You can find the complete documentation here: https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s

I was particularly interested in switching lights ON and OFF and you can find that part further down the documentation: https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Turn_a_light.2Fswitch_on
First have a look at the the commands. To set a light ON we need to send the following command:

/json.htm?type=command&param=switchlight&idx=99&switchcmd=On

And to set the light OFF we (obviously) need to issue the following command:

/json.htm?type=command&param=switchlight&idx=99&switchcmd=Off

However in the beginning of the documentation it says that the complete format for the command is:
http://192.168.1.2:8080/json.htm?type=command&param=udevice&idx=$idx&nvalue=0&svalue=79

So to switch a light on we have to replace the JSON part of the command with the part we need and that gives for our purposes the following command:

http://192.168.1.2:8080//json.htm?type=command&param=switchlight&idx=99&switchcmd=On

In this we need to replace several parameters.
First we need to replace the IP adress with the IP adress Domoticz has in our network.
The port 8080 remains the same.
And then we have to know which number (idx) the switch has in our Domoticz system.

Finding Domoticz IP number.



Normally you will know the IP number Domoticz has in your network. You can type Domoticz in your webbrowser (I am using Firefox) and the IP adress will show up.



You can also open the webpage of your router (mine is a Zyxell) and there you can find the information.



As you can see Domoticz is located at IP adress 192.168.1.66 in my case.

Look for the IP adress in your own system and write it down as we will need it in the program.

Finding the IDX of the switch.

The next step is to find the IDX number of the switch we are going to control.



Open the Domoticz Dashboard and on the top left tab entry click on settings (instellingen in Dutch).



Click on devices and choose to diplay only the used devices. Above you can see part of the screen and the arrow points at the lamp we are going to control : Lucs room lampje. The lamp has the IDX number 3 as you can see at the beginning of the line.

Now we have all the information we need.

The first test.

PLEASE USE THIS PROGRAM WITH A LMAP IN YOUR HOBBYROOM/MANCAVE AND TRY NOT TO ANNOY YOUR SPOUSE / KIDS / ROOM-MATE !!

The first test is just a simple program that switches the lamp ON, waits 20 seconds, and switches it OFF again. This is the basic principle for controling Domoticz.

Do not set the delay shorter as 20 seconds. If you do the lamp will switch ON and OFF but Domoticz will not be able to react fast enough so status of the lamp will not be displayed on its dashboard.



#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

// WiFi settings
#define wifi_ssid "ROUTERNAME"
#define wifi_password "PASSWORD"

// HTTP Domoticz settings
const char* host = "192.168.1.66";
const int   port = 8080;

HTTPClient http;
int toggle = 0;

void setup() {
  Serial.begin(115200);
  setup_wifi();           
}

void switchonoff(){
    // Here is the Json format that Domoticz expects
    // /json.htm?type=command&param=switchlight&idx=99&switchcmd=On
      String url = "/json.htm?type=command&param=switchlight&idx=";
        url += String(3);
        toggle= 1 - toggle;
        if (toggle==0){
        url += "&switchcmd=Off"; 
        }
        else   
        {
          url += "&switchcmd=On";
        }
      sendToDomoticz(url);
  }  

void loop() {
  switchonoff();
  delay (20000);
}

//Connect to wifi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.begin(wifi_ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connection Established");
  Serial.print("IP Adress : ");
  Serial.print(WiFi.localIP());
}


void sendToDomoticz(String url){
  Serial.print("Connecting to ");
  Serial.println(host);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  http.begin(host,port,url);
  int httpCode = http.GET();
    if (httpCode) {
      if (httpCode == 200) {
        String payload = http.getString();
        Serial.println("Domoticz response "); 
        Serial.println(payload);
      }
    }
  Serial.println("closing connection");
  http.end();
}


We'll go over the program step by step.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

We need to include these two libraries to communicate over HTTP.

// WiFi settings
#define wifi_ssid "ROUTERNAME"
#define wifi_password "PASSWORD"

// HTTP Domoticz settings
const char* host = "192.168.1.66";
const int   port = 8080;

Here the settings are defined which gives our program the information it needs to communicatie with your router and Domoticz. Make sure you fill in your own credentials for the ROUTERNAME and PASSWORD and replace the IP number for Domoticz with the number you found as described earlier.

HTTPClient http;
int toggle = 0;

An instance is created for the HTTPClient library called simply http. and a variable is created called toggle which will switch the light from ON to OFF.

void switchonoff(){
    // Here is the Json format that Domoticz expects
    // /json.htm?type=command&param=switchlight&idx=99&switchcmd=On
      String url = "/json.htm?type=command&param=switchlight&idx=";
        url += String(3);
        toggle= 1 - toggle;
        if (toggle==0){
        url += "&switchcmd=Off";
        }
        else  
        {
          url += "&switchcmd=On";
        }
      sendToDomoticz(url);
  }

Remember the code we found in the documentation:
http://192.168.1.2:8080//json.htm?type=command&param=switchlight&idx=99&switchcmd=On

The code above only builds the JSON part.

url += String(3);

Fill in the IDX you found for your lamp as described before in this article.

sendToDomoticz(url);

When the URL is build we call the routine that actually sends it to Domoticz.

void sendToDomoticz(String url){
  Serial.print("Connecting to ");
  Serial.println(host);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  http.begin(host,port,url);
  int httpCode = http.GET();
    if (httpCode) {
      if (httpCode == 200) {
        String payload = http.getString();
        Serial.println("Domoticz response ");
        Serial.println(payload);
      }
    }
  Serial.println("closing connection");
  http.end();
}

In this routine there is a lot of debug information printed to the serial port so you can see if everythingb goes well. There is however just one line that is really important:

http.begin(host,port,url);

This line sends the build URL to the host (IP number of Domoticz, previous defined) and port number.

The next lines check what Domoticz sends back and displays that on the serial monitor.

Run the program.

Domoticz Dashboard

Open the Domoticz Dashboard and look at the selected switch.





As you can see the lamp will switch on and 20 seconds later it will switch off again. As you can check the lamp itself you can also see this happening at the Domoticz Dashboard. Although it will take several seconds for the Dashboard to react. That is why the delay of minimal 20 seconds is so important in the program.

More next time.
Till then experiment for yourself.
Have fun

Luc Volders

Friday, September 4, 2020

Arduino and ESP8266 interrupts

For an index to all my stories click this text

Using interrupts can be very handy when designing a project and yet up until now I have almost never used them in Arduino language. My vibration alarm used an interrupt to send an alarm message. That program was written in ESP-Basic, and not in Arduino C++ code.

As I am moving more and more towards to the Arduino IDE (to keep my programs compatible with the ESP32) I wanted to use the interrupts in my new programs. However that turned out to be a bit more complicated as I thought.

Interrupt

An interrupt on the ESP8266, ESP32 or Arduino (any version) is about the same as an interrupt in real life. You put the ketlle on, start reading a book and then the kettle whistles. That is an interrupt. Getting the kettle from the stove is called an interrupt service routine (ISR).

The complication emerges when you are busy getting the kettle from the stove when the cat starts to meow telling she wants to go out. Now what to do. Opening the door leaves the kettle whistling which is annoying. Ignoring the cat is an option. It depends on where you put your priorities.

The solution is to keep the interrupt service routine as short as possible so you will not get into problems when a second interrupt occurs. Meaning you'll take the ketle from the stove as quick as possible.

Or.... You could also ignore the cat till your done with the kettle. That is exactly what I am going to do in my programs.

Test setup



As a demo setup I'll use the Wemos D1 mini with a simple push button attachted to GPIO pin 4 (D2). Do not forget the pull-up resistor to make sure D3 is always HIGH until you push the button.

The test program



int Button = 4; // D2
int intproc = 0;

void setup() 
{
  Serial.begin(9600);
  delay(50);
  Serial.println("started");
  pinMode(Button, INPUT);
  attachInterrupt(digitalPinToInterrupt(Button), ButtonPressed, FALLING);
}
void loop() 
{
  if (intproc == 1)
  {
    Serial.println("The button is Pressed");
    delay (5000);
    intproc = 0;
    attachInterrupt(digitalPinToInterrupt(Button), ButtonPressed, FALLING);
  }
}

void ButtonPressed() 
{
  detachInterrupt(Button);
  intproc = 1;
}


Let us see how this works.

The program starts with attaching the button to IO port 4 which is D2 on the Wemos D1 Mini board. Then a variable intproc is declared and set at value 0.

In the setup first the Serial port is initialised and the word "started" is print on the Serial Monitor. The pin where the button is attached to is declared as an input which is obvious. And then the interrupt is started.

attachInterrupt(digitalPinToInterrupt(Button), ButtonPressed, FALLING);

This line attaches the interrupt to the Button pin. When an interrupt is detected the program jumps to the routine ButtonPressed. And lastly the interrupt is only activated when the pin goes from VCC to GND which is called FALLING.

So what happens when the button is pressed.
The program jumps to the ButtonPressde routine.

detachInterrupt(Button);

This command makes sure that the interrupt is disconnected from the Button IO pin. So when another interrupt occurs nothing will happen, as the interrupt is disabled. The variable intproc is set to 1.

The program now continues with the loop as if nothing has happened. In the loop intproc is tested. If the value is 1 that means that an interrupt has occured. The Serial Monitor notifies us by printing: The button is pressed. Then there is a delay of 5 seconds an after that intproc is set to 0 again and the interrupt is reactivated.

If an interrupt is detected then that interrupt is immediately disabled. So if another interrupt occurs (AKA you press the button again) nothing happens. The program does what it needs to do (wait 5 seconds) and then re-activates the interrupt.
If you press the button and keep it pressed the interrupt will be fired only once as it is only activated on a FALLING signal (from VCC to GND). If you press the button too soon after eachother, being within the 5 seconds delay, nothing will happen either.

There must be a delay for debouncing the button press. However 5 seconds is far too much. One second would be enough for normal purposes. After the delay let your program do whatever it needs to do and when finished you can attach the interrupt again.

I hope this makes things clear. At least it did for me.

Now let's use this in some neat projects.
That is for another story so........

Till next time
have fun

Luc Volders