webserver + ajax dengan Nodemcu (esp8266) (aplikasi monitoring suhu dan kelembaban)

Monitoring atau kegiatan pemantauan bisa dilakukan dari jarak jauh melalui sistem komunikasi internet maupun metode komunikasi lainnya. Salah satu unsur monitoring data adalah display atau tampilan dimana beberapa aspek yang perlu diperhatikan adalah :

  1. Informatif, data yang ditampilkan mampu memberikan perspektif kondisi yang ada, sebagai contoh tampilan grafik: selain menunjukkan data juga akan memberikan gambaran pergerakan dari data-data sebelumnya (naik/turun).
  2. Real time. yaitu datayang tampil merupakan data lapangan saat ini dan terus diperbaharui dalam frekuensi tertentu dimana semakin besar akan semakin realtime.
  3. Bandwidth, adalah besarnya lalu lintas data yang terpakai oleh aktifitas monitoring, jadi sistem yang baik perlu mempertimbangkan metode lalu lintas data sekecil mungkin tanpa mengurangi aspek lainnya.
  4. Kenyamanan, berkaitan dengan design dan pola dinamik tampilan saat perubahan data.

Ajax

Asynchronous Javascript and XML (Ajax) adalah metode lalu lintas data web secara asynchronous (dibelakang layar) antara interface web (browser) dengan server yang bertujuan memberikan fitur interaktif kepada pengguna.

penggunaan ajax memungkinkan update data fleksibel tanpa perlu melakukan aksi (menekan tombl update) atau refresh halaman web.

Tampilan monitoring suhu dan kelembaban menggunakan nodemcu:

Komponen yang digunakan dalam perancangan monitoring suhu dan kelembaban berbasis webserver nodemcu :

  1. Nodemcu
  2. DHT11

Skema ajax webserver dengan nodemcu:

Sketch/program webserver nodemcu dengan ajax relatime:

#define jumlahData        5
#define hotspotSSID       "XXXXXXXX"
#define hotspotPassword   "XXXXXXXX"
#define pinDHT            D4

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include <dht.h>

dht DHT;

ESP8266WebServer server(80);

struct Data
{
  uint32_t index;
  float temperatur;
  float kelembaban;
};

Data data[jumlahData];
byte ringIndex;
uint32_t indexDataDHT;
long millisBacaSensor;

void handleRoot() {
  char buffer[] =
    "<html><head>"
    "  <title>Temperatur dan Kelembaban</title>"
    "  <meta charset='UTF-8'>"
    "  <script src='https://code.highcharts.com/highcharts.js'></script>"
    "</head>"
    "<body>"
    "  <center>"
    "    <h1>Temperatur dan Kelembaban</h1>"
    "    <h2>Grafik Temperatur dan Kelembaban</h2>"
    "    <div id='grafik' style='height:400px;'></div>"
    "  </center>"
    "<script type='text/javascript'>"
    "  var timerId = setInterval('updateGrafik()', 1000);"
    "  var grafik = Highcharts.chart('grafik', {"
    "    title: {text: ''},"
    "    xAxis: {title: {text: 'index'},categories: [],rotation:90,},"
    "    yAxis: ["
    "      {labels: {format: '{value} °C',style: {color: Highcharts.getOptions().colors[1]}},title: {text: 'Temperatur'},},"
    "      {labels: {format: '{value} %',style: {color: Highcharts.getOptions().colors[1]}},title: {text: 'Kelembaban'},opposite: true,}, ],"
    "    credits: {enabled: false},"
    "    series: ["
    "      {name: 'Temperatur',yAxis: 0,data: []}, "
    "      {name: 'Kelembaban',yAxis: 1,data: []}, ]"
    "  });"
    "  function updateGrafik(){"
    "    var xhttp = new XMLHttpRequest();"
    "    xhttp.onreadystatechange = function() {"
    "      if (this.readyState == 4 && this.status == 200) {"
    "        eval(this.responseText.trim());}};"
    "    xhttp.open('GET', '/updateData', true);"
    "    xhttp.send(); }"
    "</script>"
    "</body></html>";
  server.send(200, "text/html", buffer);
}

void handleNotFound()
{
  server.send(404, "text/plain", "Alamat tidak ditemukan");
}

void updateData()
{
  char buffer[1000];
  byte index;

  strcpy(buffer, "grafik.xAxis[0].setCategories([");

  index = ringIndex;
  for (byte i = 0; i < jumlahData; i++)
  {
    sprintf(&buffer[strlen(buffer)], "%lu,", data[index].index);
    index++;
    index %= jumlahData;
  }
  strcpy(&buffer[strlen(buffer)], "]);");

  strcpy(&buffer[strlen(buffer)], "grafik.series[0].setData([");
  index = ringIndex;
  for (byte i = 0; i < jumlahData; i++)
  {
    dtostrf(data[index].temperatur, 8, 2, &buffer[strlen(buffer)]);
    strcpy(&buffer[strlen(buffer)], ",");
    index++;
    index %= jumlahData;
  }
  strcpy(&buffer[strlen(buffer)], "]);");

  strcpy(&buffer[strlen(buffer)], "grafik.series[1].setData([");
  index = ringIndex;
  for (byte i = 0; i < jumlahData; i++)
  {
    dtostrf(data[index].kelembaban, 8, 2, &buffer[strlen(buffer)]);
    strcpy(&buffer[strlen(buffer)], ",");
    index++;
    index %= jumlahData;
  }
  strcpy(&buffer[strlen(buffer)], "]);");

  server.send(200, "text/html", buffer);

}


void setup(void) {
  Serial.begin(9600);
  Serial.println("Web server dengan fitur ajax menggunakan nodemcu (aplikasi monitor suhu dan kelembaban)");
  Serial.println("https://www.project.semesin.com");
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(hotspotSSID, hotspotPassword);
  Serial.println("");

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

  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(hotspotSSID);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/updateData", updateData);
  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop(void) {
  server.handleClient();

  if (millisBacaSensor < millis())
  {
    millisBacaSensor = millis() + 1000;

    if (DHT.read11(pinDHT) == DHTLIB_OK)
    {
      data[ringIndex].index = indexDataDHT;
      data[ringIndex].temperatur = DHT.temperature;
      data[ringIndex].kelembaban = DHT.humidity;

      indexDataDHT++;

      ringIndex++;
      ringIndex %= jumlahData;
    }
  }
}

Library: