Posted on Leave a comment

Publish MQTT using Javascript

Continuation to the previous post about the Automatic IoT Gate control, once we have connected the ESP8266 gate Opener to listen to the message broker, we will need a mechanism to be able to publish the message to the node it was listening to.

In the previous post, the ESP8266 was listening to the “/homeautomation/gate” topic. So in this post we are trying to create a simple website to publish “ON” and “OFF”message to this topic. This can be achieved with the following Javascript code:

<script src="https://assets.shiftr.io/js/mqtt-2.9.0.js"></script>
<script>
// Note: This line is only required when running in node.js 
var client = mqtt.connect('mqtt://try:try@broker.shiftr.io', {
    clientId: 'ESP8266' 
}); 
client.on('connect', function(){
       console.log('client has connected!');   
});
</script>
<script language="javascript">
function colorchange(id){
     var xmlhttp;
     xmlhttp=new XMLHttpRequest();
     if(document.getElementById(id).name == 'OFF' ){
         client.publish('/homeautomation/gate', 'ON');
         document.getElementById(id).name = 'ON';
         xmlhttp.open("GET","a.htm?ON",true);
         xmlhttp.send();
 } else { 
    client.publish('/homeautomation/gate', 'OFF'); 
    document.getElementById(id).name= 'OFF'; 
    xmlhttp.open("GET","a.htm?OFF",true);
    xmlhttp.send(); 
}
}
</script>

In the code above, we are using the broker.shiftr.io as the MQTT broker, and I am using their public try:try account, so please change this to your own account and password to ensure security.

The html code is crafted in such a way using the css to make it looks like an ON/OFF button, this is shown below, full credit to the author that made such and outstanding button.

The code that publish the “ON” message is executed from the “colorchange” function as below:

client.publish('/homeautomation/gate', 'ON');

and the code that publish the “OFF” message is executed from the same function as below:

client.publish('/homeautomation/gate', 'OFF');

If all is well you should see the “ON” and “OFF:” message being published to /homeautomation/gate topic, as shown in the below screen shot.

The full source code for the html page can be found in the following link. Please let me know if you like this post and subscribe for more projects related to IoT. Feel free to share this also.

Posted on Leave a comment

Connecting the IoT Remote Gate Opener to MQTT

Now that we have a reasonable understanding about MQTT, we can connect our IoT Gate Remote from the previous post to the MQTT broker.

The idea is to have our Remote Gate opener listen to the message in the MQTT broker. Looking at our previous example, we have setup 2 topics in the message broker, “/homeautomation” and “/hello”, we can expand the “/homeautomation” into

/homeautomation/gate

When a message is send to “/homeautomation/gate” topic, our ESP8266 will get the message and we can act on it, which mean we can open or close the gate.

So we need to modify the code so that we can subscribe to this topic. This can be done with the following:

MQTTClient client; 
// MQTT info
 const char* thehostname = "broker.shiftr.io";
 const char* user = "tokenusername";
 const char* user_password = "tokenpassword";
 const char* id = "ESP8266";

Serial.print("\nconnecting…");
   while (!client.connect(id, user, user_password)) {
     Serial.print(".");
     delay(1000);
   }
Serial.println("\nconnected!");
client.subscribe("/homeautomation/gate");

Once this you had subscribe to the topic, we need to modify the code to perform the action when we received the message. In this example let us assume the message that we are going to receive is “OPEN”. Assuming we have the following code in the Setup() section:

void setup() {  
...
  client.begin(thehostname, net);
  client.onMessage(messageReceived);
...
}

And to act on the message, we need to process the message in the messageReceived() function as below:

void messageReceived(String &topic, String &payload) {
   Serial.println("incoming: " + topic + " - " + payload);
if (payload == "OPEN"){
// open the door
digitalWrite(LEDpin,LOW); //LED ON
} else if (payload == "CLOSE") {
// close the door
digitalWrite(LEDpin,HIGH);
}
}

Now you should be able to control the Remove Gate from the internet. We can test this by posting the “OPEN” and “CLOSE” message to the topic.

I hope you enjoy this post, if you have any questions please don’t hesitate to ask and subscribe to my blog to get more frequent update on projects that I am currently working on.

Posted on Leave a comment

IoT Remote Gate Opener

I am helping my brother to make a remote Gate opener. He have a remote that can open the gate, but being in this day and age, we would like to connect everything to the Internet. So the concept can be seen in the following picture:

IoT Remote Gate Opener circuit
Remote Gate Opener

The brain consist of ESP8266, which is connected to relay that will trigger the remote. The original idea is to have some sort of sensor (magnetic) that can be detected using Hall Effect sensor to detect when the gate had been closed or opened. Then to be able to access this remotely from anywhere in the world, we can connect this to Node-RED and subsequently able to access this via Apple Homekit.

To start off as the proof of concept and to reduce the complexity, we revert back to the basics, by just connecting the ESP8266 to a relay that will activate the remote to open and close the Gate door. To start off follow the following steps:

Step 1. Gather the components

Components for ESP8266 with Relay

We will need ESP8266, Relay module, and PCB to connect the two together. You can connect the two module together by soldering it on to the PCB. Connect the 3.3 Volt pin from ESP8266 to VCC of the Relay module, and GND from the ESP8266 to the GND of the Relay module, and finally for this example, I am connecting the pin D5 to the IN pin of the Relay module. Note that the Relay IN is active LOW, this means that the relay will be activated (Green LED on Relay board turn ON) when IN is LOW. The fully assembled board looks like the following picture.

Fully assembled ESP8266 with Relay module

Step 2. Modify the Remote

Remote Modification
Remote Wiring

In the image above, we solder 2 wire across the button that can activate the Gate. This two wire will be connected by the Relay module later on.

Step 3. Uploading the Arduino Code

The idea is to use ESP8266 as a webserver. This will allow us to show a setting page to connect the ESP8266 to the WiFi without having to hardcode the WiFi access points in the code. The website will also serve as the command to turn the Relay ON and OFF. Thanks for the handy work of Martyn Currey on how to create JavaScipt and AJAX within the ESP8266, and also some AJAX code to update ESP8266 from Circuits4you, I was able to massage the AJAX code into my previous Arduino code for the Temperature sensor. The final result looks like the following picture.

ESP8266 Webserver
ESP8266 Webserver

Once the ESP8266 is connected to the WiFi, only then the “Switch” button will appear in the webserver interface. When the ESP8266 is not connected to the WiFi, by default it will revert to be an Access Point, this will allow you to connect and configure the WiFi settings.

When you click on the “Switch” it will turn the relay ON, and thus simulating the press of the remote button to open the gate. Because we don’t have any feedback from the Gate in this solution, we will need to turn the “Switch” off manually, otherwise the button on the gate remote will be pressed and the battery will drain.

In the next section we will dive in a bit deeper into the Arduino code. If you are not interested in the code, you can skip this section and just upload the code straight away into the ESP8266. When the ESP8266 load up the first time you will be able to see the AP as coded in “settings.h” file. The AP name is “ESP-Gate” with the default password defined in the file. You can change this to make sure it is much more secure.

define CLOCK_NAME "ESP-Gate"
define WIFI_AP_NAME CLOCK_NAME
define WIFI_APPSK "DefaultAPPassword" // default AP password

Step 4. Arduino Code deep dive

The Arduino code comes in 5 files, and here are the list of the files:

  1. ESP8266GateSwitchV2: This is the main file where the magic happens. Pay special attention to the following sections (void setup(), void handleLED(), void handleRoot(), void loop()).
  2. Clock.h: This file is the header file for the CLOCK
  3. mainPage.h: This file is the webserver html file which get served when you connect to the ESP8266 web server
  4. ntp: This file consist of the function to connect to the ntp server to synchronise the clock
  5. settings.h: This file contain most of the settings for the project.

Void setup() section

#include <ESP8266WebServer.h>
// Create an instance of the server
// specify the port to listen on as an argument
ESP8266WebServer server(80);

void setup() {
DebugStart();
timer = 200;
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LEDpin, OUTPUT); // setup LED
digitalWrite(LEDpin, HIGH); // Relay Active LOW
setupWiFi(1); // SetupAP mode
setupTime();
server.on("/", handleRoot);
server.on("/form", handleForm);
server.on("/setLED", handleLED);
server.begin();
}

This section will initialise the LEDpin, which is the trigger connected to the IN input of the Relay module. We will need to set the LEDpin to HIGH, because the relay module is active LOW. Initially setupWiFi will be called to try to connect to the WiFi, if this fail the program will defaulted to AP mode. SetupTime() will attempt to setup the time by synchonising the time with ntp server. The next couple of line define what function will be called when the webserver is being invoked. For example, handleRoot function will be called when the root of the webserver is being accessed. The handleForm function will be callled when the “/form” is being called, this is called when we setting up the Wifi parameter as well a a few other settings of the clock, daylight savings, etc. Finally “/setLED” will be called when we “button” is being pressed to activate the Relay.

void handleLED() section

void handleLED() {
String ledState = "OFF";
String t_state = server.arg("LEDstate"); //Refer xhttp.open("GET", "setLED?LEDstate="+led, true);
Serial.println(t_state);
if(t_state == "1"){
digitalWrite(LEDpin,LOW); //LED ON
ledState = "ON"; //Feedback parameter
}
else {
digitalWrite(LEDpin,HIGH); //LED OFF
ledState = "OFF"; //Feedback parameter
}
server.send(200, "text/plane", ledState); //Send web page
}

If we look at the handleLED function above, this is where the Relay is being activated. When the AJAX code post the LEDstate parameters back to the webserver, this section will check whether the LEDState parameter value is equal to 1 or 0, if it is 1, the code will write LEDpin output to LOW, and activate the Relay, and if the parameter value is 0, the code will write LEDpin output to HIGH, and deactivated the Relay. The ledState feedback parameter is just to make our life easier when debugging the code, this will show on the website whether the ledState is ON or OFF via AJAX return code.

void loop() section

void loop() {
server.handleClient();
if (timeStatus() != timeNotSet){
time_t t = now();
}
}

This section of the code is very simple, all it needs to do is to make sure the server.handleClient() function is called, to ensure that ESP8266 will allow client to connect to it’s webserver.

void handleRoot() section

void handleRoot() {
DebugLn("handleRoot");
String s = MAIN_page;
if (WiFi.status() == WL_CONNECTED) {
s += ButtonControl;
// check led state
boolean pinStatus = digitalRead(LEDpin);
if (pinStatus==LOW) {
s.replace("@@NA@@", "ON");
s.replace("@@SW@@", "ON");
s.replace("@@Checked@@", "checked");
}
else {
s.replace("@@NA@@", "OFF");
s.replace("@@SW@@", "OFF");
s.replace("@@Checked@@", "");
}
}
s+= WifiSetting;
time_t t = now();
s.replace("@@SSID@@", settings.ssid);
s.replace("@@PSK@@", settings.psk);
s.replace("@@TZ@@", String(settings.timezone));
s.replace("@@USDST@@", settings.usdst?"checked":"");
s.replace("@@HOUR@@", String(adjustedHour(t)));
s.replace("@@MIN@@", String(minute(t)));
s.replace("@@NTPSRV@@", settings.timeserver);
s.replace("@@NTPINT@@", String(settings.interval));
s.replace("@@SYNCSTATUS@@", timeStatus() == timeSet ? "OK" : "Overdue");
s.replace("@@CLOCKNAME@@", settings.name);
s.replace("@@UPDATERESPONSE@@", httpUpdateResponse);
httpUpdateResponse = "";
server.send(200, "text/html", s);
}

This section deals on how the root of the webserver should look like. It will first get the MAIN_page content from mainPage.h file, and then substitute the checkbox status based on the reading of the LEDpin. If the currently the LEDpin is LOW, that means the switch is active, so it will need to show the “switch” as on. And if the reading is HIGH, this means that the switch is not active, so it will need to show the “switch” as off. Then the rest of the code is to display the WiFi SSID, time zone, ntp server, update interval, device name.

I hope you like this post, and please subscribe if you haven’t done so. And let me know if you have any questions.

Posted on Leave a comment

Connecting ESP8266 to MQTT broker

So what is MQTT, according to mqtt.org, it is a connectivity protocol used to connect machine to machine, used for Internet of Things (IoT). It was designed as an extremely light weight publish/subscribe messaging transport. In short it is the messaging designed for Internet of Things devices to allow robust connectivity when faced with challenged bandwidth limitation, and power consumption. It stands for Message Queuing Telemetry Transport.

MQTT how it works

The concept of MQTT is a Publish/Subscribe system. This means that there is at least one system that publish a message on a topic and there is at least one system that subscribe to the “topic” to receive “messages”. The “Messages” are information that are being exchange between the devices. “Topic” are series of strings separated by a forward slash (/), each topic is separated by the forward slash.

MQTT Broker

MQTT Broker is responsible for receiving messages and forwarding the messages to the devices that are interested (Subscribed) to the topic. There are a few MQTT Broker that you can use. In this example we will use the one called https://shiftr.io/try.

You can also installed your own message broker (Mosquitto broker) into Raspberry Pi to relay all the messages for your home automation projects.

Getting Started with MQTT Broker

Start by getting a free account with shiftr.io, then follow the documentation to create the Namespace and Token. The Token is username and password pair that will be used to authenticate the client, the one that will publish or subscribe to the messages. The token will be used in the following section of the code:

const char* user = "tokenusername";
const char* user_password = "tokenpassword";

You will need to download the MQTT library to send the message to the MQTT broker. The initialisation is done using the following code:

#include <MQTT.h>
MQTTClient client;

During the setup you will need to connect the onMessage event to the function that be executed when the message is received, this is done with the following code:

void setup() {  
...
client.begin(thehostname, net);
client.onMessage(messageReceived);
...
}

In the loop section of the code, you will need to execute the client.loop() function and the following code will try to connect to the message broker and at the same it will publish “Alive” message to the “/hello” topic.

void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "Alive");
}

}

Here are the connect() function, which will attempt to connect to the WiFi and upon connection will subscribe to the “/hello” topic.

void connect() {
Serial.print("checking wifi…");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting…");
while (!client.connect(id, user, user_password)) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}

Here are the full source code from the example above:

// MQTT Test client
//
// 128x64 OLED pinout:
// GND goes to ground
// Vin goes to 3.3V
// Data to I2C SDA (GPIO 4)
// Clk to I2C SCL (GPIO 2)
// Add MQTT
#include <TimeLib.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>
#include <MQTT.h>

char ssid[] = "ssidname"; // your network SSID (name)
char pass[] = "ssidpassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
// MQTT info
const char* thehostname = "broker.shiftr.io";
const char* user = "tokenusername";
const char* user_password = "tokenpassword";
const char* id = "ESP8266";
SSD1306 display(0x3c, 4, 2); //0x3d for the Adafruit 1.3" OLED, 0x3C being the usual address of the OLED
void connect() {
Serial.print("checking wifi…");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting…");
while (!client.connect(id, user, user_password)) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
//Setup Rest Client
WiFi.begin(ssid, pass);
Wire.pins(4, 2); // Start the OLED with GPIO 4 and 2 on ESP-01
Wire.begin(4, 2); // 4=sda, 2=scl
display.init();
display.flipScreenVertically();
display.drawString(0, 24, "Connected.");
display.display();
client.begin(thehostname, net);
client.onMessage(messageReceived);
connect();
delay(1000);
}
int timer =0;
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "Alive");
}
//delay(1000);
}

If everything goes well, you should be able to see the message being published to the topic that you are monitoring. In the example above the message will go from the ESP8266 device to the /hello topic.

The message being published is “Alive” message, as shown at the top left hand corner. This will keep being published every seconds.

That’s all for now, I hope this post is useful as an introduction to the MQTT. Please share this if you like, or provide some comments. The next step from here is to modify the Temperature sensor to use the MQTT, stay tune if you would like to know about this.