Anda di sini

Pemrograman

[Tutorial Lengkap] Kontrol Lampu via Internet of Things dengan Antarmuka Web

Aditya Suranata - 24 September 2019 14:26:34 0

Setelah mendapatkan akun cloud MQTTBroker, dilanjutkan dengan memprogram NodeMCU agar dapat terhubung dengan Cloud MQTTBroker. Kode program berisi pembacaan sensor, dan kontrol lampu. Pada sesi ini perserta dapat melakukan kontrol dan monitorinng perangkat IoTnya melalui Internet.

Setelah menyelesaikan prosedur sign up pada CloudMQTT, periksa informasi instance kita pada halaman instance information, Informasi kredensial penting yang harus kita catat untuk dapat digunakan pada NodeMCU adalah server, user, password, dan port.

Disisi NodeMCU, kita akan menggunakan MQTT client yang mendukung ESP8266 (chip inti dari NodeMCU), yang dinamakan PubSubClient. Pustakanya dapat diinstall melalui Arduino IDE library atau dengan menyalin file penyerta ke folder Documents/Arduino/Libraries.

Pertama-tama, kita memulai dengan menambahkan libraries yang diperlukan untuk semua fungsionalitas. Kita memerlukan library ESP8266WiFi, agar dapat menghubungkan NodeMCU ke jaringan WiFi, dan menggunakan library PubSubClient agar dapat menghubungkan NodeMCU ke MQTT broker dan publish/subscribe pesan pada topik terkait.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

Kemudian, kita perlu mendeklarasikan beberapa variabel global untuk koneksi kita. Tentunya, kita, memerlukan kredensial untuk mengakses WiFi, untuk menghubungkan diri ke jaringan WiFi. Berikut adalah potongan kode yang digunakan untuk menyetel kredensial untuk menghubung ke WiFi:

const char* ssid = "YourNetworkName";
const char* password =  "YourNetworkPassword";

Kita juga memerlukan informasi dan kredensial dari server CloudMQTT. Sebagai mana dipaparkan pada sesi sebelumnya kita perlu mengetahui alamat server, port, username dan password. Sesuaikan nilai berikut dengan konfigurasi masing-masing:

const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 12948;
const char* mqttUser = "YourMqttUser";
const char* mqttPassword = "YourMqttUserPassword";

Setelah itu, kita perlu mendeklarasikan objek dari class WiFiClient, yang memungkinkan kita untuk membuat koneksi ke IP dan port spesifik. Kita juga perlu mendeklarasikan sebuah objek dari class PubSubClient, yang mana menerima masukan dari konstruktor yang sebelumnya didefinisikan oleh WiFiClient.

Konstruktor dari class ini dapat menerima sejumlah argumen lainnya, sebagai mana dapat dilihat di halaman dokumentasinya (http://pubsubclient.knolleary.net/api.html#setserver).

WiFiClient espClient;
PubSubClient client(espClient);

Sekarang, lanjut dari fungsi setup, kita membuka koneksi serial, sehingga kita dapat melihat output dari hasil program kita. Kita juga menghubungkan alatnya ke jaringan WiFi.

Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");

Selanjutnya, kita perlu menspesifikasikan alamat dan nomer port dari MQTT server. Untuk itu, kita memanggil metode setServer dari objek PubSubClient, argumen pertamanya adalah alamat dan yang kedua adalah nomer port. Variabel yang berisi nilainya telah kita definisikan sebelumnya, dalam bentuk string konstan.

client.setServer(mqttServer, mqttPort);

Kemudian, kita menggunakan metode setCallback pada objek yang sama untuk fungsi penanganan yang dieksekusi ketika pesan MQTT diterima. Kita akan menganalisis lebih dalam fungsi ini nanti.

client.setCallback(callback);

Sekarang, kita akan menghubungkan alatnya ke MQTT server, masi tetap di fungsi setup. Sebagaimana yang kita lakukan pada bagian menghubungkan ke jaringan WiFi, kita menghubungkan ke server dalam perulangan loop hingga sukses terhubung.

Jadi, kita menggunakan perulangan while (while loop) berdasarkan output dari metode connected pada objek PubSubClient, yang mana akan mengembalikan nilai true jika koneksinya terbangun dengan baik atau false jika tidak.

Untuk melakukan koneksi yang sebenarnya, kita memanggil methode connect, yang menerima masukan berupa id pengenal unik dari klien kita, yang mana akan kita namai "ESP8266Client", dan data autentikasi berupa nama pengguna dan sandi, yang telah kita definisikan sebelumnya. Ini akan mengembalikan nilai trua jika koneksinya berhasil dan false jika gagal.

Wanti-wanti jika gagal, kita bisa memanggil metode state pada objek PubSubClient, yang mana aka mengembalikan kode yang berisi informasi mengenai mengapa koneksinya gagal. Berikut adalah kode program untuk perulangan koneksinya:

while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.println(client.state());
      delay(2000);
    }
}

Untuk menyelesaikan fungsi setupnya, kita akan mempublish pesan pada suatu topik. Untuk melakukan itu, kita memanggil metode publish, yang menerima argumen input berupa topik dan pesan. Pada kasus ini, kita akan mempublish sebuah pesan yang mengatakan "Hello from ESP9266" pada topik "esp/test".

client.publish("esp/test", "Hello from ESP8266");

Kemudian, kita akan mensubscribe ke topik yang sama, sehingga kita bisa menerima pesan dari publisher lainnya. Untuk melakukan itu, kita memanggil metode subscribe, memberikan masukan berupa argumen dengan nama topik yang sama.

client.subscribe("esp/test");

Periksa fungsi setup berikut yang telah ditulis secara lengkap:

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.println(client.state());
      delay(2000);
    }
  }
  client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
}

Fungsi Callback

Setelah inisialisasi, kita perlu menentukan fungsi callback, yang akan menangani pesan masuk dari topik yang kita subscribe.

Argumen dari fungsi ini adalah nama topik, payload (dalam byte) dan ukuran dari pesannya. Fungsi ini mestinya cukup mengembalikan void/kosong.

Pada fungsi ini, kita pertama-tama mencetak nama topiknya ke serial port, lalu mencetak setiap byte dari pesan yang diterima. Karena kita juga memiliki panjang pesan sebagai argumen dari fungsi, ini dapat dilakukan dengan mudah menggunakan perulangan.

Periksa keseleruhuan kode fungsinya sebagai berikut:

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
}

Main loop

Pada fungsi main loop, kita hanya akan memanggil metode loop dari PubSubClient. Fungsi ini harus dipanggil secara reguler agar memungkinkan client untuk memproses pesan masuk dan menjaga koneksinya dengan server.

void loop() {
  client.loop();
}

Periksa kode lengkap dari awal hingga akhir sebagai berikut:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "YourNetworkName";
const char* password =  "YourNetworkPassword";
const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 12948;
const char* mqttUser = "YourMqttUser";
const char* mqttPassword = "YourMqttUserPassword";
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.println(client.state());
      delay(2000);
    }
  }
  client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
}
void loop() {
  client.loop();
}

Berikut adalah kode program lengkap yang telah ditambahkan dua subscribe (saklar & dimmer) dan satu publish (sensor). Subscribe saklar untuk menyalakan dan mematikan lampu, subscribe dimmer untuk menerangkan dan meredupkan lampu, dan publish sensor untuk mengirim data pembacaan sensor potensiometer.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "......";
const char* password =  ""......";";
const char* mqttServer = ""......";";
const int mqttPort = "......";;
const char* mqttUser = ""......";";
const char* mqttPassword = ""......";";
WiFiClient espClient;
PubSubClient client(espClient);
int dataSensor = 0;
int dataSensorMapped = 0;
int dataSensorMappedBefore = 0;
void setup() {
  pinMode(D1, OUTPUT);
  pinMode(A0, INPUT);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.println(client.state());
      delay(2000);
    }
  }
  client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
  client.subscribe("esp/saklar");
  client.subscribe("esp/dimmer");
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
  if (strcmp(topic,"esp/saklar")==0){
    if((char)payload[0] == '1')
    {
      digitalWrite(D1, HIGH);
      Serial.println("Turning on lamp");
    }
    else{
      digitalWrite(D1, LOW);
      Serial.println("Turning off lamp");
    } 
  }
  else if(strcmp(topic,"esp/dimmer")==0){
    payload[length] = '\0';
    int pwmVal = atoi((char *)payload);
    analogWrite(D1, pwmVal);
  }
}
long NOW = millis();
long LAST_SENT = 0;
void loop() {
  client.loop();
  NOW = millis();
  if(NOW - LAST_SENT > 1500){
    dataSensor = analogRead(A0);
    dataSensorMapped = map(dataSensor, 0, 1023, 0, 100);
    if(dataSensorMapped != dataSensorMappedBefore){
      Serial.print("Publishing to esp/sensor: ");
      Serial.println(dataSensorMapped);
      client.publish("esp/sensor", String(dataSensorMapped).c_str());
      dataSensorMappedBefore = dataSensorMapped;
    }
    LAST_SENT = NOW;
  }
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {
      Serial.print("failed with state ");
      Serial.println(client.state());
      delay(2000);
    }
  }
}

Melakukan pengujian melalui CloudMQTT WebSocket UI

Setelah kode program lengkap di atas diprogram ke NodeMCU tentunya dengan merubah beberapa parameter seperti kredensial WiFi dan CloudMQTT dan telah memastikan melalui serial monitor bahwa koneksi ke CloudMQTT telah berhasil dilakukan oleh NodeMCU seperti terlihat pada Gambar 2.21, kita dapat membuka halaman WebSocket UI dari akun CloudMQTT kita untuk mencoba mengirim perintah ke NodeMCU dan membaca data sensor yang dikirim oleh NodeMCU. Sebagai contoh kita dapat mengirim perintah pada topik esp/saklar dengan nilai 1 untuk menyalakan lampu, dengan 0 untuk memadamkan. Selain itu topik esp/dimmer juga dapat dicoba dengan memberikan nilai 0 hingga 255 untuk menyetel terang redup lampu. Pada topik esp/sensor si NodeMCU akan mempublish datanya setiap kali kita memutar-mutar potensiometer.

Web Interfacing

Setelah dapat dilakukan kontrol dan monitoring perangkat IoT melalui Internet, selanjutnya pada sesi ini dilanjutkan dengan membuat antarmuka web moderen sederhana untuk kontrol & monitoring sistem IoT yang telah dibuat.

Tampilan yang dibuat menggunakan beberapa framework pemrograman web seperti Bootstrap 3 untuk membuat komponen UI seperti tombol, slider dan progress bar, juga framework javascript jQuery untuk memanipulasi data dan MQTTPaho untuk menangani koneksi dan integrasi dengan CloudMQTT. File yang berisi kode sumber web interface telah disediakan untuk mempermudah pengujian, pada file index.html perlu dilakukan beberapa penyesuaian seperti alamat server, nomer port, username dan password dari instance CloudMQTT kita. Berikut adalah kode lengkap dari file index.html yang berisi web interface:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="js/jquery-1.12.4.js"></script>
    <script src="js/mqttws31.js"></script>
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>ESP8266 WebIface</title>
    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="css/bootstrap-toggle.min.css" rel="stylesheet">
    <link href="css/bootstrap-slider.min.css" rel="stylesheet">
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script type="text/javascript">
        jQuery(document).ready(function(){
            // Create a client instance
            client = new Paho.MQTT.Client("postman.cloudmqtt.com", 38155,"WebIface");
            //Example client = new Paho.MQTT.Client("m11.cloudmqtt.com", 32903, "web_" + parseInt(Math.random() * 100, 10));
            // set callback handlers
            client.onConnectionLost = onConnectionLost;
            client.onMessageArrived = onMessageArrived;
            var options = {
                useSSL: true,
                userName: "isi username",
                password: "isi password",
                onSuccess:onConnect,
                onFailure:doFail
            }
            // connect the client
            client.connect(options);
            // called when the client connects
            function onConnect() {
                // Once a connection has been made, make a subscription and send a message.
                console.log("onConnect");
                client.subscribe("/cloudmqtt");
                client.subscribe("esp/sensor");
                /*message = new Paho.MQTT.Message("Hello CloudMQTT");
                message.destinationName = "/cloudmqtt";
                client.send(message);*/
            }
            function doFail(e){
                console.log(e);
            }
            // called when the client loses its connection
            function onConnectionLost(responseObject) {
                if (responseObject.errorCode !== 0) {
                  console.log("onConnectionLost:"+responseObject.errorMessage);
                }
            }
            // called when a message arrives
            function onMessageArrived(message) {
                console.log("onMessageArrived:"+message.payloadString);
                if(message.destinationName == "esp/sensor"){
                    $('#pgbar-sensor').css({'width': message.payloadString+'%'});
                    $('#pgbar-sensor').attr({'aria-valuenow': message.payloadString});
                    $('#pgbar-sensor').html(message.payloadString+'%');
                }
            }
        });
    </script>
    <style type="text/css">
        .slider.slider-horizontal {
            width: 100%;
            height: 20px;
        }
        .text-bold {
            font-weight: bold;
        }
    </style>
  </head>
  <body>
    <div class="container">
        <div class="row">
            <div class="col-sm-12 text-center">
                <h1>My IoT Dashboard</h1>
                <hr>
                <div class="panel panel-primary">
                    <div class="panel-heading"> <h3 class="panel-title text-bold"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Monitoring</h3></div>
                    <div class="panel-body">
                        <div class="progress">
                          <div id="pgbar-sensor" class="progress-bar progress-bar-danger progress-bar-striped active" role="progressbar"
                          aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">
                            Data sensor: 0%
                          </div>
                        </div>
                    </div>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading"> <h3 class="panel-title text-bold"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> Controlling</h3></div>
                    <div class="panel-body">
                        <div class="form-group">
                            <input id="slider-dimmer" type="text" data-slider-min="0" data-slider-max="1023" data-slider-step="20" data-slider-value="0" width="100%" />
                        </div>
                        <hr>
                        <div class="form-group">
                            <input id="btn-saklar" type="checkbox" checked data-toggle="toggle" data-onstyle="warning" data-width="100%" />
                        </div>
                    </div>
                </div>
            </div>
            <
        </div>
    </div>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
    <script src="js/bootstrap-toggle.min.js"></script>
    <script src="js/bootstrap-slider.min.js"></script>
    <script type="text/javascript">
        // jQuery Script
        jQuery(document).ready(function(){
            $("#slider-dimmer").slider();
            $("#slider-dimmer").on("slide", function(slideEvt) {
                message = new Paho.MQTT.Message(slideEvt.value.toString());
                message.destinationName = "esp/dimmer";
                client.send(message);
            });
            $('#btn-saklar').change(function() {
                message = new Paho.MQTT.Message($(this).prop('checked') ? '1' : '0');
                message.destinationName = "esp/saklar";
                client.send(message);
            })
        });
    </script>
  </body>
</html>

Kode program dari Web Interface yang telah dibuat dapat diakses secara lokal melalui komputer/laptop. Namun untuk implementasi riil, interface ini dapat diunggah secara privat ke internet sehingga dapat diakses melalui alamat domain, misalnya seperti dashboardsaya.com. Dengan demikian, antarmuka dapat diakses dari mana saja melalui perangkat apapun yang mendukung teknologi web modern.

Ringkasan

Pada pelatihan ini kita mempelajari microcontroller basic dan internet of things. Mikrokontroler dipelajari karena teknologi IoT pada umumnya menggunakan mikrokontroler sebagai perangkat keras pengambil data dan pengendali instrument yang hendak dihubungkan ke Internet. Teknologi IoT memungkinkan segala macam benda mati maupun benda hidup untuk memiliki kemampuan komputasi dan terhubung satu sama lain. Dengan demikian, mereka dapat saling bertukar data dan meningkatkan fungsi dan efisiensi.

Secara teknis, kita menggunakan NodeMCU sebagai development board untuk mempermudah percobaan implementasi teknologi IoT, dibantu dengan Arduino IDE untuk memprogram. Selanjutnya, CloudMQTT mengambil peran sebagai broker online yang bertindak sebagai penengah antara alat kita dan web interface yang kita buat. Sehingga antara alat kita dan web interface yang berisi tampilan berupa tombol, slider dan progress bar dapat berinteraksi dengan alat kita secara online melalui Internet. Apabila kita memiliki banyak alat, maka masing-masing alat juga dapat berinteraksi satu sama lain tanpa melibatkan manusia di dalamnya. Mereka dapat bertukar data melalui metode publish dan subscribe dari library client MQTT yang kita pakai yaitu PubSubClient.

Selanjutnya, apa yang telah kira pelajari pada pelatihan ini dapat memberikan kita bayangan, bagaimana suatu benda mati/hidup dapat ditingkatkan fungsi dan efisiensinya menggunakan teknologi IoT. Kita dapat menambahkan lebih banyak lagi perangkat sensor dan aktuator untuk mencapai tujuan di dunia nyata, seperti yang telah dipaparkan pada bagian pengenalan IoT. Teknologi IoT dapat digunakan di semua bidang, mulai dari bisnis, kesehatan, pertanian, hingga rumahan dan edukasi. Berbagai materi dan pengetahuan tambahan mengenai konsep, arsitektur, hingga tutorial untuk implementasi teknis dari teknologi IoT telah tersedia melimpah di Internet.

795
Daftar Artikel Terkait
Image

Aditya Suranata

Aditya suka menulis, bukan hanya sekedar hobi, menulis menjadi medianya untuk mencurahkan pikiran dan perasaan. Di TutorKeren.com kebanyakan menyumbang tulisan sesuai dengan minat dan keahliannya yaitu pada kategori pemrograman dan elektronika. Selain itu juga gemar menulis mengenai hal-hal umum, seperti ilmu alam, sosial dan beberapa pengalamannya yang mungkin bisa berguna untuk orang lain.

Artikel Menarik Lainnya
Mari Gabung

Halo Emo 51 , Ada yang ingin disampaikan? Jangan sungkan untuk gabung diskusi ini. Silahkan Login dulu atau Daftar baru.