Translate

Monitoring 2 Suhu via Website Hosting + Realtime Grafik DataLogger

Monitoring 2 Suhu via Website Hosting + Realtime Grafik DataLogger 
 

        Pada kesempatan kali ini saya akan menjelaskan mengenai bagaimana cara membuat sebuah alat yang daapaat memonitor 2 buah suhu secaraa terpisah tapi bisa dimasukkan ke dalam 1 website dan 1 database. untuk database saya menggunakan https://supabase.com dan untuk datamanager dan website saya menggunakan hosting dari infinityfree.com. untuk detailnya yaitu seperti berikut.
 
 
1. Skema
 

 
2. Interface
 




 
 
3. VIDEO HASILNYA
 

 
4. Program ESP32 - Batang / Semarang
 
 #include <WiFi.h>
#include <HTTPClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <time.h>

// ================= WIFI =================

const char* ssid = "wifihpku";
const char* password = "12345678";

// ================= SUPABASE =================

String supabaseURL =
"https://yizpzxixllbgixxxxxxx.supabase.co/rest/v1/suhu_data";

String supabaseKey =
"sb_publishable_mJNp2PCt9civsxe26URVYg_dxxxxxxx";

// ================= DEVICE =================

// ESP32 pertama

String device = "ESP32_BATANG";
String kota = "Batang";

// ESP32 kedua ubah menjadi:
// String device = "ESP32_SEMARANG";
// String kota = "Semarang";

// ================= DS18B20 =================

#define ONE_WIRE_BUS 13

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

void setup(){

Serial.begin(115200);

sensors.begin();

// WIFI

WiFi.begin(ssid,password);

Serial.print("Connecting");

while(WiFi.status()!=WL_CONNECTED){

delay(500);

Serial.print(".");

}

Serial.println();

Serial.println("WiFi Connected");

// waktu WIB

configTime(
7*3600,
0,
"pool.ntp.org",
"time.nist.gov"
);

}

String getTime(){

struct tm timeinfo;

if(!getLocalTime(&timeinfo)){

return "NULL";

}

char waktu[30];

strftime(

waktu,

sizeof(waktu),

"%Y-%m-%d %H:%M:%S",

&timeinfo

);

return String(waktu);

}

void kirimSupabase(float suhu){

if(WiFi.status()==WL_CONNECTED){

HTTPClient http;

http.begin(supabaseURL);

http.addHeader(
"Content-Type",
"application/json"
);

http.addHeader(
"apikey",
supabaseKey
);

http.addHeader(
"Authorization",
"Bearer "+supabaseKey
);

String data = "{";

data += "\"device\":\""+device+"\",";

data += "\"kota\":\""+kota+"\",";

data += "\"suhu\":"+String(suhu)+",";

data += "\"waktu\":\""+getTime()+"\"";

data += "}";

Serial.println(data);

int code=http.POST(data);

Serial.print("Response Supabase : ");

Serial.println(code);

http.end();

}

}

void loop(){

sensors.requestTemperatures();

float suhu = sensors.getTempCByIndex(0);

if(suhu == -127){

Serial.println("Sensor DS18B20 tidak terbaca");

return;

}

Serial.print("Suhu ");

Serial.print(kota);

Serial.print(" : ");

Serial.println(suhu);

kirimSupabase(suhu);

delay(5000);

}
 
 
 
5. Api.php
 
<?php

$supabase_url = "https://yizpzxixllbgixxxxxxx.supabase.co/rest/v1/suhu_data";

$supabase_key = "sb_publishable_mJNp2PCt9civsxe26URVYg_dxxxxxxx";

$curl = curl_init();

curl_setopt_array($curl,[

CURLOPT_URL => $supabase_url."?select=*&order=id.desc&limit=100",

CURLOPT_RETURNTRANSFER => true,

CURLOPT_HTTPHEADER => [

"apikey: ".$supabase_key,

"Authorization: Bearer ".$supabase_key,

"Content-Type: application/json"

]

]);

$response = curl_exec($curl);

curl_close($curl);

header("Content-Type: application/json");

echo $response;

?> 
 
 
6. index.php
 
<!DOCTYPE html>
<html>

<head>

<title>Monitoring Suhu ESP32</title>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<style>

*{
box-sizing:border-box;
}

body{

margin:0;
font-family:'Segoe UI',Arial,sans-serif;
background:#120021;
color:#ffd700;

}

.header{

background:linear-gradient(135deg,#5a189a,#240046);
padding:25px;
text-align:center;
box-shadow:0 5px 20px #000;

}

.header h1{

margin:0;
font-size:34px;

}

.header p{

color:#fff3a0;

}

.container{

width:92%;
margin:auto;

}

.map-box{

margin-top:25px;
background:#240046;
padding:25px;
border-radius:25px;
box-shadow:0 0 20px #000;
text-align:center;

}

.map-box h2{

color:#ffd700;

}

.peta{

width:90%;
max-width:1000px;
height:260px;
object-fit:cover;

border-radius:20px;

border:3px solid #7b2cbf;

}

.cards{

display:grid;
grid-template-columns:repeat(2,1fr);
gap:25px;

margin-top:25px;

}

.card{

background:#240046;
padding:25px;
border-radius:25px;
text-align:center;

box-shadow:0 0 20px #000;

}

.card h2{

color:#ffd700;

}

.nilai{

font-size:70px;
font-weight:bold;

color:#ffd700;

}

.status{

color:#00ff99;
font-weight:bold;

}

.panel{

background:#240046;
margin-top:25px;

padding:25px;

border-radius:25px;

box-shadow:0 0 20px #000;

}

.chart{

height:400px;

}

canvas{

width:100%!important;
height:100%!important;

}

table{

width:100%;
border-collapse:collapse;

}

th{

background:#5a189a;
color:#ffd700;

}

td,th{

padding:12px;
text-align:center;

border-bottom:1px solid #7b2cbf;

}

tr:hover{

background:#3c096c;

}

@media(max-width:700px){

.cards{

grid-template-columns:1fr;

}

}

</style>

</head>

<body>

<div class="header">

<h1>🌡 MONITORING SUHU ESP32</h1>

<p>DS18B20 Temperature Sensor</p>

</div>

<div class="container">

<!-- PETA -->

<div class="map-box">

<h2>🗺 PETA JAWA</h2>

<img src="jawa-map.png" class="peta">

</div>

<!-- NILAI SUHU -->

<div class="cards">

<div class="card">

<h2>📍 ESP32 BATANG</h2>

<div id="batang" class="nilai">

-- °C

</div>

<div class="status">

● ONLINE

</div>

</div>

<div class="card">

<h2>📍 ESP32 SEMARANG</h2>

<div id="semarang" class="nilai">

-- °C

</div>

<div class="status">

● ONLINE

</div>

</div>

</div>

<!-- GRAFIK -->

<div class="panel">

<h2>📈 Grafik Suhu Batang</h2>

<div class="chart">

<canvas id="grafikBatang"></canvas>

</div>

</div>

<div class="panel">

<h2>📈 Grafik Suhu Semarang</h2>

<div class="chart">

<canvas id="grafikSemarang"></canvas>

</div>

</div>

<!-- LOGGER -->

<div class="panel">

<h2>📋 Logger Data 100 Terakhir</h2>

<table>

<tr>

<th>No</th>
<th>Device</th>
<th>Kota</th>
<th>Suhu</th>
<th>Waktu</th>

</tr>

<tbody id="logger"></tbody>

</table>

</div>

</div>

<script>

let chartBatang;

let chartSemarang;

function loadData(){

fetch("api.php")

.then(res=>res.json())

.then(data=>{

let batang=[];

let semarang=[];

let waktuBatang=[];

let waktuSemarang=[];

let suhuBatang=0;

let suhuSemarang=0;

let idBatang=0;

let idSemarang=0;

data.slice().reverse().forEach(item=>{

if(item.device=="ESP32_BATANG"){

batang.push(Number(item.suhu));

waktuBatang.push(item.waktu);

if(Number(item.id)>idBatang){

idBatang=item.id;

suhuBatang=item.suhu;

}

}

if(item.device=="ESP32_SEMARANG"){

semarang.push(Number(item.suhu));

waktuSemarang.push(item.waktu);

if(Number(item.id)>idSemarang){

idSemarang=item.id;

suhuSemarang=item.suhu;

}

}

});

document.getElementById("batang").innerHTML =

Number(suhuBatang).toFixed(2)+" °C";

document.getElementById("semarang").innerHTML =

Number(suhuSemarang).toFixed(2)+" °C";

if(chartBatang){

chartBatang.destroy();

}

chartBatang=new Chart(

document.getElementById("grafikBatang"),

{

type:"line",

data:{

labels:waktuBatang,

datasets:[{

label:"ESP32 BATANG",

data:batang,

borderColor:"#ffd700",

backgroundColor:"rgba(255,215,0,0.2)",

fill:true,

tension:0.4,

borderWidth:3

}]

},

options:{

responsive:true,

maintainAspectRatio:false

}

}

);

if(chartSemarang){

chartSemarang.destroy();

}

chartSemarang=new Chart(

document.getElementById("grafikSemarang"),

{

type:"line",

data:{

labels:waktuSemarang,

datasets:[{

label:"ESP32 SEMARANG",

data:semarang,

borderColor:"#00ffff",

backgroundColor:"rgba(0,255,255,0.2)",

fill:true,

tension:0.4,

borderWidth:3

}]

},

options:{

responsive:true,

maintainAspectRatio:false

}

}

);

let html="";

data.forEach((item,index)=>{

html+=`

<tr>

<td>${index+1}</td>

<td>${item.device}</td>

<td>${item.kota}</td>

<td>${item.suhu} °C</td>

<td>${item.waktu}</td>

</tr>

`;

});

document.getElementById("logger").innerHTML=html;

});

}

loadData();

setInterval(loadData,5000);

</script>

</body>

</html> 
 
 

No comments:

Post a Comment