Membuat Web Dashboard untuk aplikasi Internet of Things [1]

Aplikasi Web Internet of Things
IoT Web Dashboard
Web Dashboard Internet of Things, ThingSpeak Web Dashboard Application, Sistem Monitoring IoT berbasis web

User Interface akan membantu pengguna dalam memahami data yang ditampilkan oleh sistem. Berkaitan dengan itu, dalam pengaplikasian Internet of Things maka aplikasi user interface yang paling relevan adalah berbasis web. Dalam perkembangannya, aplikasi berbasis web dapat dikonversi ke aplikasi adroid (apk) maupun aplikasi desktop (tentunya dengan mempertahankan corenya -browser based). Karena orientasinya sebatas share saja maka dalam tutorial ini akan saja coba jelaskan agar mudah dipahami (secara sayanya juga gak expert-expert amat). 
Membuat Web Dashboard untuk aplikasi Internet of Things
Secara umum, cara kerja dari implementasi IoT menggunakan platform ThingSpeak adalah perangkat kita yang dilapangan(baik perangkat embedded, PC, dll) mengirimkan data ke server ThingSpeak (yang selanjutnya disimpan pada Channel di Akun TS). Data yang sudah disimpan, dapat kita akses menggunakan metode web API. Web API ThingSpeak mempunyai beberapa fitur yang sangat cukup untuk kebutuhan pemantauan tinggal disesuaikan dengan request yang akan digunakan. Seperti menampilkan data terakhir, menampilkan data pada kolom tertentu, dll. 

Konfigurasi ThingSpeak
Karena prosesnya adalah menampilkan data yang ada di ThingSpeak, maka pastikan terlebih dahulu terkait konfigurasinya (channel, API key, field). Sebagai contoh saya akan menggunakan channel pada tutorial ini dan akan menampilkan informasi terkait suhu dan kelembaban.
Membuat Web Dashboard untuk aplikasi Internet of Things

Install XAMPP
Karena dalam pemrograman web ini menggunakan php, maka diperlukan php service. Kamu juga dapat menggunakan aplikasi lain sejenis seperti WAMP atau LAMP(linux). Apabila sudah terinstall jalankan servicenya (Apache dan MySQL).
Membuat Web Dashboard untuk aplikasi Internet of Things

Desain aplikasi
Langkah pertama adalah proses login terlebih dahulu. Jadi nanti dipastikan akan menggunakan database untuk proses ini. Tutorial membuat sistem login dapat dilihat pada tutorial ini (pelajari tutorialnya)
Aplikasi Web Server IoT
Setelah sukses login, maka tampilan dashboard dapat diakses. Untuk Dashboard akan saya coba menampilkan beberapa informasi seperti Grafik, data terakhir, atau rekap data (dalam bentuk tabel). Untuk tampilan dashboard, saya menggunakan template boostrap dashboard SB Admin

Implementasi

  • Download template login dari tutorial yang telah dipelajari diatas (atau download disini)
  • Ubah nama folder(rename) login-bootstrap4 menjadi iot_monitoring (bebas sesuai selera). Pastikan lokasinya ada di directory C:\xampp\htdocs
Aplikasi Web Server IoT
  • Buka php MyAdmin kemudian buat database dengan nama abc_database
Aplikasi Web Server IoT
  • Klik pada database abc_database > Import > Chose File (pilih file sql yang ada pada folder C:\xampp\htdocs\iot_monitoring\abc_database.sql ) > klik Go (pojok kanan bawah)

Web Dashboard IoT monitoring
Web Dashboard IoT monitoring
Simple ThingSpeak Web Dashboard application
  • Bila sukses maka pada database abc_database akan ada tabel users

Simple ThingSpeak Web Dashboard application
  • Download Template SB Admin 2 kemudian ekstrak here
  • Copy seluruh file yang ada di folder hasil ekstrak kemudian paste di C:\xampp\htdocs\iot_monitoring\main_pages
Simple ThingSpeak Web Dashboard application
using ThingSpeak data for personal dashboard

  • Hapus file index.html kemudian Edit file index.php (saya menggunakan notepad ++). Hapus isinya dan timpa (copy-paste) dengan kode dibawah ini, kemudian simpan!
<?php 
session_start();
if ( !isset($_SESSION['name'])){// handling if dont'have session

 header('location:../index.php'); 
 exit();
} 
$name = $_SESSION['name'];
?>
<!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, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Main Station- Dashboard</title>

  <!-- Custom fonts for this template-->
  <link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template-->
  <link href="css/sb-admin-2.min.css" rel="stylesheet">

</head>

<body id="page-top">

  <!-- Page Wrapper -->
  <div id="wrapper">

    <!-- Sidebar -->
    <ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">

      <!-- Sidebar - Brand -->
      <a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
        <div class="sidebar-brand-icon rotate-n-15">
          <i class="fa fa-desktop"></i>
        </div>
        <div class="sidebar-brand-text mx-3">Main Station</div>
      </a>

      <!-- Divider -->
      <hr class="sidebar-divider my-0">

      <!-- Nav Item - Dashboard -->
      <li class="nav-item active">
        <a class="nav-link" href="index.html">
          <i class="fas fa-fw fa-tachometer-alt"></i>
          <span>Dashboard</span></a>
      </li>

      <!-- Divider -->
      <hr class="sidebar-divider">

      <!-- Heading -->
      <div class="sidebar-heading">
        Data Report
      </div>

      <!-- Nav Item - Pages Collapse Menu -->
      <li class="nav-item">
        <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
          <i class="fas fa-fw fa-rocket"></i>
          <span>Station</span>
        </a>
        <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
          <div class="bg-white py-2 collapse-inner rounded">
            <h6 class="collapse-header">Station List</h6>
            <a class="collapse-item" href="#">Station 1</a>
            <a class="collapse-item" href="#">Station 2</a>
          </div>
        </div>
      </li>
      <!-- Nav Item - Utilities Collapse Menu -->
      <li class="nav-item">
        <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities" aria-expanded="true" aria-controls="collapseUtilities">
          <i class="fas fa-fw fa-table"></i>
          <span>Raw Data</span>
        </a>
        <div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities" data-parent="#accordionSidebar">
          <div class="bg-white py-2 collapse-inner rounded">
            <h6 class="collapse-header">Data Table:</h6>
            <a class="collapse-item" href="#">Station 1</a>
            <a class="collapse-item" href="#">Station 2</a>
          </div>
        </div>
      </li>
    <!-- Nav Item - Tables -->
      <li class="nav-item">
        <a class="nav-link" href="#">
          <i class="fas fa-fw fa-map-marker"></i>
          <span>Location</span></a>
      </li>

    

      <!-- Divider -->
      <hr class="sidebar-divider d-none d-md-block">

      <!-- Sidebar Toggler (Sidebar) -->
      <div class="text-center d-none d-md-inline">
        <button class="rounded-circle border-0" id="sidebarToggle"></button>
      </div>

    </ul>
    <!-- End of Sidebar -->

    <!-- Content Wrapper -->
    <div id="content-wrapper" class="d-flex flex-column">

      <!-- Main Content -->
      <div id="content">

        <!-- Topbar -->
        <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">

          <!-- Sidebar Toggle (Topbar) -->
          <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
            <i class="fa fa-bars"></i>
          </button>

          <!-- Topbar Search -->
          <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
            <div class="input-group">
              <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
              <div class="input-group-append">
                <button class="btn btn-primary" type="button">
                  <i class="fas fa-search fa-sm"></i>
                </button>
              </div>
            </div>
          </form>

          <!-- Topbar Navbar -->
          <ul class="navbar-nav ml-auto">

            <!-- Nav Item - Search Dropdown (Visible Only XS) -->
            <li class="nav-item dropdown no-arrow d-sm-none">
              <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="fas fa-search fa-fw"></i>
              </a>
              <!-- Dropdown - Messages -->
              <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">
                <form class="form-inline mr-auto w-100 navbar-search">
                  <div class="input-group">
                    <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
                    <div class="input-group-append">
                      <button class="btn btn-primary" type="button">
                        <i class="fas fa-search fa-sm"></i>
                      </button>
                    </div>
                  </div>
                </form>
              </div>
            </li>

           
            <div class="topbar-divider d-none d-sm-block"></div>

            <!-- Nav Item - User Information -->
            <li class="nav-item dropdown no-arrow">
              <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <span class="mr-2 d-none d-lg-inline text-gray-600 small"><?php echo $name; ?></span>
                <img class="img-profile rounded-circle" src="https://source.unsplash.com/QAB-WJcbgJk/60x60">
              </a>
              <!-- Dropdown - User Information -->
              <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
                <a class="dropdown-item" href="#">
                  <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
                  Profile
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
                  Settings
                </a>
                <a class="dropdown-item" href="#">
                  <i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
                  Activity Log
                </a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
                  <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
                  Logout
                </a>
              </div>
            </li>

          </ul>

        </nav>
        <!-- End of Topbar -->

        <!-- Begin Page Content -->
        <div class="container-fluid">

          <!-- Page Heading -->
          <div class="d-sm-flex align-items-center justify-content-between mb-4">
            <h1 class="h3 mb-0 text-gray-800">Dashboard</h1>
            <a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>
          </div>

          <!-- Content Row -->
          <div class="row">

            <!-- Total Data -->
            <div class="col-xl-3 col-md-6 mb-4">
              <div class="card border-left-primary shadow h-100 py-2">
                <div class="card-body">
                  <div class="row no-gutters align-items-center">
                    <div class="col mr-2">
                      <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Total Data</div>
                      <div class="h5 mb-0 font-weight-bold text-gray-800">20</div>
                    </div>
                    <div class="col-auto">
                      <i class="fas fa-table fa-2x text-gray-300"></i>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <!-- Average Temperature -->
            <div class="col-xl-3 col-md-6 mb-4">
              <div class="card border-left-success shadow h-100 py-2">
                <div class="card-body">
                  <div class="row no-gutters align-items-center">
                    <div class="col mr-2">
                      <div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Average Temperature</div>
                      <div class="h5 mb-0 font-weight-bold text-gray-800">27.5</div>
                    </div>
                    <div class="col-auto">
                      <i class="fas fa-thermometer-empty fa-2x text-gray-300"></i>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <!-- Average Humidity -->
            <div class="col-xl-3 col-md-6 mb-4">
              <div class="card border-left-info shadow h-100 py-2">
                <div class="card-body">
                  <div class="row no-gutters align-items-center">
                    <div class="col mr-2">
                      <div class="text-xs font-weight-bold text-info text-uppercase mb-1">Average Humidity</div>
                      <div class="row no-gutters align-items-center">
                        <div class="col-auto">
                          <div class="h5 mb-0 mr-3 font-weight-bold text-gray-800">50</div>
                        </div>
                        <div class="col">
                          <div class="progress progress-sm mr-2">
                            <div class="progress-bar bg-info" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
                          </div>
                        </div>
                      </div>
                    </div>
                    <div class="col-auto">
                      <i class="fas fa-percent fa-2x text-gray-300"></i>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <!-- Device Online -->
            <div class="col-xl-3 col-md-6 mb-4">
              <div class="card border-left-warning shadow h-100 py-2">
                <div class="card-body">
                  <div class="row no-gutters align-items-center">
                    <div class="col mr-2">
                      <div class="text-xs font-weight-bold text-success text-uppercase mb-1">Device Online</div>
                      <div class="h5 mb-0 font-weight-bold text-gray-800">1</div>
                    </div>
                    <div class="col-auto">
                      <i class="fas fa-rocket fa-2x text-gray-300"></i>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- Content Row -->

          <div class="row">

            <!-- Area Chart -->
            <div class="col-xl-6 col-lg-6">
              <div class="card shadow mb-4">
                <!-- Card Header - Dropdown -->
                <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
                  <h6 class="m-0 font-weight-bold text-primary">Temperature</h6>
                  <div class="dropdown no-arrow">
                    <a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                      <i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
                    </a>
                    <div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
                      <div class="dropdown-header">Dropdown Header:</div>
                      <a class="dropdown-item" href="#">Action</a>
                      <a class="dropdown-item" href="#">Another action</a>
                      <div class="dropdown-divider"></div>
                      <a class="dropdown-item" href="#">Something else here</a>
                    </div>
                  </div>
                </div>
                <!-- Card Body -->
                <div class="card-body">
                  <div class="chart-area">
     <!-- Chart_temperature -->
     <iframe src='https://tradingeconomics.com/embed/?s=idntemp&v=201801181706v20200716&h=300&w=600&ref=/indonesia/temperature' 
     height='260' width='450'  frameborder='0' scrolling='no'></iframe>
     <br />source: <a href='https://tradingeconomics.com/indonesia/temperature'>tradingeconomics.com</a>
      </div>
                </div>
              </div>
            </div>

            <!-- Area Chart -->
            <div class="col-xl-6 col-lg-6">
              <div class="card shadow mb-4">
                <!-- Card Header - Dropdown -->
                <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
                  <h6 class="m-0 font-weight-bold text-primary">Humidity</h6>
                  <div class="dropdown no-arrow">
                    <a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                      <i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
                    </a>
                    <div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
                      <div class="dropdown-header">Dropdown Header:</div>
                      <a class="dropdown-item" href="#">Action</a>
                      <a class="dropdown-item" href="#">Another action</a>
                      <div class="dropdown-divider"></div>
                      <a class="dropdown-item" href="#">Something else here</a>
                    </div>
                  </div>
                </div>
                <!-- Card Body -->
                <div class="card-body">
                  <div class="chart-area">
        <!-- Chart_humidity -->
                    <iframe src='https://tradingeconomics.com/embed/?s=idntemp&v=201801181706v20200716&h=300&w=600&ref=/indonesia/temperature' 
     height='260' width='450'  frameborder='0' scrolling='no'></iframe>
     <br />source: <a href='https://tradingeconomics.com/indonesia/temperature'>tradingeconomics.com</a>
      </div>
                </div>
              </div>
            </div>

          
        </div>
        <!-- /.container-fluid -->

      </div>
      <!-- End of Main Content -->

      <!-- Footer -->
      <footer class="sticky-footer bg-white">
        <div class="container my-auto">
          <div class="copyright text-center my-auto">
            <span>Copyright &copy; Your Website 2020</span>
          </div>
        </div>
      </footer>
      <!-- End of Footer -->

    </div>
    <!-- End of Content Wrapper -->

  </div>
  <!-- End of Page Wrapper -->

  <!-- Scroll to Top Button-->
  <a class="scroll-to-top rounded" href="#page-top">
    <i class="fas fa-angle-up"></i>
  </a>

  <!-- Logout Modal-->
  <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
          <button class="close" type="button" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
        <div class="modal-footer">
          <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
          <a class="btn btn-primary" href="logout.php">Logout</a>
        </div>
      </div>
    </div>
  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="vendor/jquery/jquery.min.js"></script>
  <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="js/sb-admin-2.min.js"></script>

  <!-- Page level plugins -->
  <script src="vendor/chart.js/Chart.min.js"></script>

  <!-- Page level custom scripts -->
  <script src="js/demo/chart-area-demo.js"></script>
  <script src="js/demo/chart-pie-demo.js"></script>

</body>

</html>
  • Nah selanjutnya mari kita akses melalui web browser (chrome, opera, fire fox) aplikasi web yang telah dibuat. Akses ke URL http://localhost/iot_monitoring/ , masukkan username = admin dan password = admin . Apabila tidak ada kendala maka proses login akan sukses dan menuju ke dashboard. 
Aplikasi web server IoT

Aplikasi web server IoT
tampilan dashboard

Kustomisasi Tampilan Data
Data yang ditulis hanya sebagai acuan tampilan dan letak. Selanjutnya mari kita isi dengan tampilan data dari Channel ThingSpeak.
1. Widget Grafik 
Grafik yang ada pada ThingSpeak dapat kita masukkan kedalam dashboard kita. Pastikan channel sudah terisi data sehingga grafik telah terbuat. Buka chart kemudian klik pada bagian iframe. Selanjutnya copy kode iframe yang muncul.
Aplikasi web server IoT
Aplikasi web server IoT
Edit kembali file index.php (C:\xampp\htdocs\iot_monitoring\main_pages\index.php). Cari (Ctrl+F) bagian "Chart_temperature" kemudian paste code dengan menimpa iframe yang sudah ada. Lakukan hal yang sama untuk tampilan chart humidity ("Chart_humidity"). Simpan file dan reload halaman dashboard.
Aplikasi web server IoT
Bootstrap IoT Dashboard
tampilan dashboard dengan grafik ThingSpeak

Nah untuk selanjutnya kita akan melakukan kostumisasi tampilan data pada bagian card total_data, average_temperature, average_humidity. Semoga bermanfaat

untuk Membuat Web Dashboard untuk aplikasi Internet of Things bagian kedua dapat dilihat disini