Disusun Oleh (Kelompok 1 TIA):
| Muhammad Naufal Aziz | 24051204001 |
| Muhammad Rifqi Al Hafidh | 24051204009 |
| Ig. Krisna Wijaya Prihandono | 24051204032 |
| Ahmad Syihan Arijuddin | 24051204035 |
PENDAHULUAN
Perkembangan teknologi Internet of Things (IoT) telah mengubah paradigma pemantauan parameter lingkungan secara drastis dari sistem terisolasi menjadi sistem terintegrasi berbasis jaringan nirkabel dan antarmuka web. Pemantauan variabel suhu dan kelembapan udara secara real-time memiliki peran yang sangat krusial di berbagai sektor industri, seperti otomatisasi rumah pintar (smart home), sistem pertanian presisi, laboratorium steril, dan pusat data (data center).
Dalam implementasinya, platform mikrokontroler seperti Arduino Uno dan ESP32 menawarkan pendekatan arsitektur yang berbeda. Arduino Uno dikenal sebagai platform mikrokontroler 8-bit berdaya rendah yang sangat andal untuk akuisisi sinyal fisik melalui Pin I/O dan Analog-to-Digital Converter (ADC). Namun, karena tidak memiliki modul jaringan onboard, Arduino Uno memerlukan perantara (middleware) berupa komputer/laptop yang menjalankan skrip Python Flask dan komunikasi USB Serial (PySerial) untuk menyajikan data sensor ke jaringan web lokal.
Di sisi lain, ESP32 hadir sebagai System-on-Chip (SoC) 32-bit yang dilengkapi dengan modul Wi-Fi dan Bluetooth terintegrasi. Dengan memori Flash dan RAM yang jauh lebih besar, ESP32 sanggup bertindak secara independen sebagai Embedded HTTP Web Server tanpa bergantung pada komputer host. Melalui dua pendekatan arsitektur ini, praktikum Demo Tugas 4 dirancang untuk mengimplementasikan dan membandingkan secara komprehensif sistem pemantauan lingkungan berbasis sensor DHT11, baik menggunakan skema jembatan USB Serial-Flask pada Arduino Uno maupun skema Embedded Web Server mandiri pada ESP32.
Berdasarkan latar belakang di atas, rumusan masalah dalam praktikum ini adalah sebagai berikut:
1. Bagaimana merancang dan mengimplementasikan sistem akuisisi data suhu, kelembapan (DHT11), dan nilai analog (pin A0) berbasis Arduino Uno melalui komunikasi USB Serial menuju backend Python Flask?
2. Bagaimana merancang dan mengimplementasikan sistem monitoring lingkungan berbasis ESP32 sebagai Embedded Web Server mandiri dengan konektivitas Wi-Fi Station (STA)?
3. Bagaimana struktur transmisi data JSON dan mekanisme polling HTTP pada frontend HTML/CSS/JavaScript untuk memperbarui antarmuka web secara real-time?
4. Bagaimana perbandingan performa, fleksibilitas jaringan, dan kelebihan/keterbatasan antara arsitektur sistem berbasis Arduino Uno-Flask dan ESP32 Standalone Web Server?
Tujuan dari penyusunan laporan praktikum ini adalah:
1. Menganalisis arsitektur hardware dan mekanisme komunikasi USB Serial 9600 baud antara Arduino Uno dan framework Python Flask.
2. Menganalisis pengkonfigurasian mode Wi-Fi Station (STA) dan penanganan HTTP request/response JSON pada ESP32 Web Server.
3. Membangun antarmuka dashboard web yang responsif, interaktif (fitur Light/Dark mode, progress bar ADC, dan grafik Canvas real-time), serta terintegrasi dengan REST API JSON.
4. Menyajikan evaluasi komparatif teknis antara arsitektur terikat PC (Arduino-Flask) dan arsitektur mandiri awan/lokal (ESP32 Standalone).
Penulisan laporan ini diharapkan memberikan manfaat teoritis dan praktis bagi mahasiswa dan pengembang sistem embedded:
1. Memberikan pemahaman mendalam mengenai integrasi perangkat keras sensorik dengan teknologi web modern (HTML5, CSS3, JavaScript Fetch API).
2. Menjadi panduan teknis mengenai pemilihan arsitektur mikrokontroler yang tepat sesuai dengan kebutuhan infrastruktur jaringan dan ketersediaan perangkat perantara.
TINJAUAN PUSTAKA
Internet of Things (IoT) merupakan arsitektur komputasi yang menghubungkan objek fisik bertipe embedded system ke jaringan internet atau jaringan area lokal (LAN). Dalam IoT, data sensorik dikumpulkan oleh mikrokontroler, diproses, dan ditransmisikan ke pengguna melalui protokol komunikasi standar. Antarmuka web (web dashboard) merupakan sarana visualisasi utama yang memungkinkan pemantauan variabel fisik secara jarak jauh melalui peramban web (browser) tanpa memerlukan penginstalan perangkat lunak khusus pada sisi klien.
Arduino Uno merupakan papan pengembang mikrokontroler berbasis chip ATmega328P (arsitektur 8-bit) yang beroperasi pada frekuensi jam 16 MHz. Papan ini memiliki 14 pin I/O digital dan 6 pin input analog dengan unit Converter Analog-ke-Digital (ADC) 10-bit (rentang nilai digital 0 hingga 1023). Karena tidak memiliki pengontrol jaringan terintegrasi, komunikasi data outbound dikirimkan menggunakan protokol UART (Universal Asynchronous Receiver-Transmitter) melalui port USB Serial pada kecepatan baud (baud rate) 9600 bps.
ESP32 merupakan System-on-Chip (SoC) buatan Espressif Systems yang ditenagai oleh prosesor dual-core Tensilica Xtensa LX6 32-bit berkecepatan hingga 240 MHz. ESP32 mendukung konektivitas Wi-Fi 802.11 b/g/n dan Bluetooth 4.2 BR/EDR/BLE. Dalam mode Station (WIFI_STA), ESP32 terhubung ke Access Point lokal dan memperoleh IP address lokal melalui DHCP. Dengan pustaka WebServer.h, ESP32 mampu menangani HTTP GET Request pada port 80 dan melayani halaman web statis (HTML yang disimpan dalam memori flash PROGMEM) serta REST API berformat JSON secara responsif.
DHT11 adalah sensor gabungan yang mengukur suhu udara (rentang 0-50 °C dengan akurasi ±2 °C) dan kelembapan relatif/Relative Humidity (rentang 20-90% RH dengan akurasi ±5%). Sensor ini menggunakan elemen pengukur kelembapan tipe kapasitif dan thermistor NTC untuk suhu, yang dihubungkan ke mikrokontroler bawaan 8-bit. Komunikasi data menggunakan protokol kustom 1-Wire digital (single-bus) yang mentransmisikan paket data 40-bit setiap sampel pembacaan.
Python Flask adalah micro-web framework yang digunakan pada sisi PC/laptop untuk menerima data dari Arduino Uno. Pustaka PySerial (serial.Serial) secara kontinu membaca stream data serial dari COM port (misalnya COM3 pada 9600 baud) dalam thread terpisah (multithreading). Flask kemudian memformat data tersebut menjadi objek JSON pada endpoint HTTP /api/data, sehingga dapat diakses oleh JavaScript browser melalui metode Fetch API secara periodik (polling interval 2 detik).
Berikut adalah rincian perangkat keras dan perangkat lunak yang digunakan dalam pengembangan kedua proyek monitoring pada praktikum Demo Tugas 4:
| Komponen Hardware | Spesifikasi / Parameter | Fungsi Utama |
|---|---|---|
| Arduino Uno R3 | ATmega328P, 16 MHz, 5V | Papan mikrokontroler akuisisi data Proyek 1 |
| ESP32 Dev Module | Dual-Core 240 MHz, 3.3V, Wi-Fi | SoC & Embedded Web Server Proyek 2 |
| Sensor DHT11 | Digital 1-Wire (Data: Pin D2 / GPIO 13) | Mengukur suhu (°C) dan kelembapan (% RH) |
| Input Analog A0 | ADC 10-bit Arduino (0 - 1023) | Membaca sampel masukan tegangan analog |
| Kabel USB Data | USB Type-A to Type-B / Micro-USB | Catu daya & media transmisi serial COM |
| Kabel Jumper DuPont | Female-to-Female / Male-to-Female | Koneksi interkoneksi pin fisik sensor |
| Laptop / PC Host | Windows / Linux, Wi-Fi LAN | Menjalankan Python Flask & Browser Client |
| Software / Pustaka | Teknologi / Bahasa | Peran & Fungsi Sistem |
|---|---|---|
| Arduino IDE | C / C++ Embedded | Mengembangkan dan melakukan kompilasi & upload firmware |
| DHT Sensor Library | Pustaka C++ (DHT.h) | Membaca protokol timing 1-Wire dari sensor DHT11 |
| Python 3 + Flask | Python Web Backend | Menyediakan HTTP Server & REST API endpoint /api/data |
| PySerial | Pustaka Python Serial | Membuka port COM3 dan melakukan parsing baris CSV serial |
| WiFi.h & WebServer.h | Pustaka Core ESP32 | Mengatur koneksi Wi-Fi STA dan Web Server port 80 |
| HTML5, CSS3, JavaScript | Frontend Web Standard | Menampilkan Dashboard, Fetch API, Theme Toggle & Canvas |
PEMBAHASAN
Pada Proyek 1, sistem dirancang untuk membaca data suhu, kelembapan, dan masukan analog A0 menggunakan Arduino Uno. Karena Arduino Uno tidak dilengkapi pengontrol jaringan nirkabel onboard, arsitektur difungsikan dalam bentuk hybrid (USB Serial Bridge):
a. Sisi Mikrokontroler (Arduino Uno): Program dht11_serial.ino membaca suhu dan kelembapan dari sensor DHT11 yang terhubung ke pin digital D2 setiap 2000 ms. Pada saat bersamaan, program membaca nilai tegangan analog pada pin A0 menggunakan fungsi analogRead(A0). Hasil pembacaan digabungkan menjadi sebuah string terformat CSV (Comma-Separated Values) dengan struktur: temperature,humidity,adcValue (contoh: '28.4,71.0,523') dan dikirimkan melalui USB Serial pada baud rate 9600 bps.
b. Sisi Middleware / Backend (Python Flask): Aplikasi app.py pada PC membuka koneksi ke port COM3 menggunakan pustaka PySerial. Sebuah daemon thread (threading.Thread) dijalankan khusus untuk membaca baris serial secara kontinu tanpa mengganggu respon HTTP server Flask. Data CSV dipisahkan (split), dikonversi ke tipe float/int, dan disimpan ke variabel global. Flask menyediakan endpoint REST API pada /api/data yang mengembalikan payload JSON berformat: {"temperature": 28.4, "humidity": 71.0, "adc": 523, "status": "Connected"}.
c. Sisi Frontend (HTML/CSS/JavaScript): Antarmuka web disajikan melalui index.html dan style.css. Skrip JavaScript menjalankan fungsi pollingsetInterval(updateData, 2000) untuk mengambil data dari /api/data secara periodik. Dashboard menampilkan kartu sensorik interaktif, persentase nilai ADC pada progress bar visual (0-1023 setara 0-100%), indikator status koneksi, serta tombol beralih mode tampilan terang/gelap (Light/Dark mode) dengan penyimpanan state di localStorage browser.
Pada Proyek 2, sistem ditingkatkan menjadi arsitektur tersemat mandiri (Standalone Embedded System) tanpa ketergantungan pada komputer host sebagai backend server:
a. Sisi Mikrokontroler (ESP32): Firmware ESP32 menginisialisasi sensor DHT11 pada GPIO 13 dan mengaktifkan mode Wi-Fi Station (WiFi.mode(WIFI_STA)). ESP32 terhubung ke router/hotspot lokal menggunakan kredensial SSID dan password yang telah ditentukan. Setelah berhasil tersambung, ESP32 memperoleh IP address lokal dari DHCP router.
b. Sisi Web Server Tersemat: Menggunakan pustaka WebServer.h pada port 80, ESP32 mendaftarkan dua handler route utama: (1) Route root / melayani seluruh dokumen HTML/CSS/JS yang disimpan dalam variabel string PROGMEM (memori flash) menggunakan server.send_P(). (2) Route API /data mengembalikan objek JSON {"temperature": 33.0, "humidity": 34.0} secara langsung dari RAM ESP32.
c. Mekanisme Non-Blocking & Reconnect Wi-Fi: Program memanfaatkan fungsi millis() untuk mengeksekusi dua jadwal tugas independen tanpa fungsi delay(): pembacaan sensorik DHT11 setiap 2000 ms dan pengecekan status jaringan Wi-Fi setiap 10.000 ms. Jika koneksi Wi-Fi terputus, ESP32 secara otomatis memanggil WiFi.disconnect() dan melakukan re-koneksi ulang tanpa menghentikan eksekusi loop utama.
d. Frontend & Grafik Real-Time HTML Canvas: Antarmuka web menjalankan JavaScript polling ke endpoint relatif /data setiap 3000 ms. Selain memperbarui kartu teks suhu dan kelembapan, JavaScript mengelola array riwayat dataSuhu dan dataLembap hingga maksimal 40 titik data (MAX_TITIK = 40). Grafik riwayat digambar secara dinamis pada elemen HTML Canvas menggunakan warna garis merah (#ef4444) untuk suhu dan biru (#3b82f6) untuk kelembapan.
Tabel berikut menyajikan analisis perbandingan teknis antara arsitektur Arduino Uno + Flask dan ESP32 Standalone Web Server:
| Kriteria Evaluasi | Proyek 1: Arduino Uno + Flask | Proyek 2: ESP32 Standalone Web Server |
|---|---|---|
| Arsitektur Sistem | Hybrid (Arduino -> USB Serial -> Laptop PC -> Flask) | Embedded Standalone (ESP32 -> Wi-Fi Router -> Client) |
| Kebutuhan Host PC | Wajib ada PC/Laptop yang menyalakan app.py dan USB COM | Tidak memerlukan Host PC; beroperasi independen |
| Media Transmisi Data | Kabel USB Serial (Baud Rate 9600 bps) | Nirkabel Wi-Fi 802.11 b/g/n (Port 80 HTTP) |
| Fitur Input Analog | Tersedia pembacaan ADC 10-bit pada Pin A0 (0 - 1023) | Fokus pada data digital DHT11 (GPIO 13) |
| Visualisasi Grafik | Progress bar ADC visual & kartu statistik desimal | Grafik tren histori 40 titik data berbasis HTML Canvas |
| Resiliensi Jaringan | Tergantung pada stabilitas port COM USB dan Flask host | Memiliki fitur Auto-Reconnect Wi-Fi setiap 10 detik |
// File: dht11_serial.ino
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
int adcValue = analogRead(A0);
if (isnan(humidity) || isnan(temperature)) {
Serial.println("ERROR");
} else {
Serial.print(temperature);
Serial.print(",");
Serial.print(humidity);
Serial.print(",");
Serial.println(adcValue);
}
delay(2000);
}# File: app.py
from flask import Flask, render_template, jsonify
import serial
import threading
import time
app = Flask(__name__)
SERIAL_PORT = "COM3"
BAUD_RATE = 9600
temperature = 0.0
humidity = 0.0
adc_value = 0
arduino_status = "Disconnected"
try:
arduino = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
arduino_status = "Connected"
except Exception:
arduino = None
def read_serial():
global temperature, humidity, adc_value, arduino_status
while True:
if arduino is not None:
try:
data = arduino.readline().decode("utf-8").strip()
if data:
if data == "ERROR":
continue
values = data.split(",")
if len(values) == 3:
temperature = float(values[0])
humidity = float(values[1])
adc_value = int(values[2])
arduino_status = "Connected"
except Exception:
arduino_status = "Disconnected"
time.sleep(0.1)
thread = threading.Thread(target=read_serial)
thread.daemon = True
thread.start()
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/data")
def get_data():
return jsonify({
"temperature": temperature,
"humidity": humidity,
"adc": adc_value,
"status": arduino_status
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=False)<!-- File: templates/index.html (Snippet Frontend Polling) -->
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Environmental Monitor - Arduino Uno</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<div class="app">
<header class="header">
<h1>Environmental Monitor</h1>
<button id="theme-toggle" onclick="toggleTheme()"><span id="theme-icon">
☀️
</span> Light</button>
</header>
<main class="dashboard">
<div class="sensor-card">
<span class="card-label">TEMPERATURE</span>
<span id="temperature">--</span> °C
</div>
<div class="sensor-card">
<span class="card-label">HUMIDITY</span>
<span id="humidity">--</span> %
</div>
<div class="sensor-card">
<span class="card-label">ANALOG VALUE</span>
<span id="adc">--</span> ADC
<div class="adc-progress"><div id="adc-bar" class="adc-progress-bar"></div></div>
</div>
</main>
</div>
<script>
function updateData() {
fetch("/api/data")
.then(res => res.json())
.then(data => {
document.getElementById("temperature").textContent = Number(data.temperature).toFixed(1);
document.getElementById("humidity").textContent = Number(data.humidity).toFixed(1);
document.getElementById("adc").textContent = data.adc;
document.getElementById("adc-bar").style.width = ((data.adc / 1023) * 100) + "%";
});
}
setInterval(updateData, 2000);
</script>
</body>
</html>// File: esp32_dht11_webserver.ino
#include <DHT.h>
#include <WiFi.h>
#include <WebServer.h>
const char* WIFI_SSID = "tareyou";
const char* WIFI_PASS = "pwr54321";
#define DHT_PIN 13
#define DHT_TYPE DHT11
const unsigned long INTERVAL_BACA = 2000;
const unsigned long INTERVAL_RECONNECT = 10000;
DHT dht(DHT_PIN, DHT_TYPE);
WebServer server(80);
float suhuTerakhir = 0;
float lembapTerakhir = 0;
bool sensorOK = false;
unsigned long terakhirBaca = 0;
unsigned long terakhirReconnect = 0;
const char HALAMAN[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Monitoring Suhu dan Kelembapan ESP32</title>
<style>
* { box-sizing: border-box; }
body { margin:0; font-family:system-ui,Arial,sans-serif; background:#f1f5f9; color:#0f172a; }
main { max-width:800px; margin:0 auto; padding:16px; }
.cards { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:16px; }
.card { background:#fff; border-radius:12px; padding:20px; text-align:center; box-shadow:0 1px 4px rgba(0,0,0,.08); }
.value { font-size:2.6rem; font-weight:700; }
canvas { width:100%; height:220px; display:block; }
</style>
</head>
<body>
<main>
<h2>Monitoring Suhu & Kelembapan ESP32</h2>
<span id="status" class="badge">Menunggu data...</span>
<section class="cards">
<div class="card"><p>Suhu</p><p class="value"><span id="temp">--</span> °C</p></div>
<div class="card"><p>Kelembapan</p><p class="value"><span id="hum">--</span> %</p></div>
</section>
<section style="margin-top:16px;">
<canvas id="chart"></canvas>
</section>
</main>
<script>
var MAX_TITIK = 40;
var dataSuhu = [], dataLembap = [];
async function ambilData() {
try {
var res = await fetch("/data", { cache: "no-store" });
var d = await res.json();
if (d.temperature !== null) {
document.getElementById("temp").textContent = d.temperature.toFixed(1);
document.getElementById("hum").textContent = d.humidity.toFixed(1);
dataSuhu.push(d.temperature);
dataLembap.push(d.humidity);
if (dataSuhu.length > MAX_TITIK) { dataSuhu.shift(); dataLembap.shift(); }
}
} catch(e) {}
}
setInterval(ambilData, 3000);
</script>
</body>
</html>
)rawliteral";
void handleRoot() {
server.send_P(200, "text/html; charset=utf-8", HALAMAN);
}
void handleData() {
String json;
if (sensorOK) {
json = "{\"temperature\":" + String(suhuTerakhir, 1) + ","humidity":" + String(lembapTerakhir, 1) + "}";
} else {
json = "{\"temperature\":null,"humidity":null}";
}
server.sendHeader("Cache-Control", "no-store");
server.send(200, "application/json", json);
}
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
int percobaan = 0;
while (WiFi.status() != WL_CONNECTED && percobaan < 30) {
delay(500);
percobaan++;
}
server.on("/", handleRoot);
server.on("/data", handleData);
server.begin();
}
void loop() {
server.handleClient();
unsigned long sekarang = millis();
if (WiFi.status() != WL_CONNECTED && sekarang - terakhirReconnect >= INTERVAL_RECONNECT) {
terakhirReconnect = sekarang;
WiFi.disconnect();
WiFi.begin(WIFI_SSID, WIFI_PASS);
}
if (sekarang - meingat_baca >= INTERVAL_BACA) {
terakhirBaca = sekarang;
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
sensorOK = false;
} else {
sensorOK = true;
suhuTerakhir = t;
lembapTerakhir = h;
}
}
}PENUTUP
Berdasarkan hasil pengujian dan analisis pada praktikum Demo Tugas 4, dapat ditarik beberapa kesimpulan utama:
1. Implementasi sistem monitoring lingkungan berbasis Arduino Uno berhasil melakukan akuisisi data suhu, kelembapan (DHT11), dan tegangan analog (A0) yang ditransmisikan secara kontinu melalui USB Serial 9600 baud. Framework Python Flask dan PySerial terbukti andal dalam memproses baris CSV serial dan menyajikannya sebagai REST API berformat JSON pada port 5000.
2. Implementasi sistem monitoring berbasis ESP32 berhasil membuktikan keunggulan arsitektur Standalone Embedded Web Server. Dalam mode Wi-Fi Station (STA), ESP32 mampu menangani HTTP GET request pada port 80 untuk menyajikan antarmuka HTML/CSS/JavaScript (stored in PROGMEM) serta endpoint /data secara independen tanpa bergantung pada komputer host.
3. Antarmuka dashboard web pada kedua proyek mampu melakukan polling data secara interaktif dan responsif, serta dilengkapi fitur visualisasi tingkat tinggi seperti kalkulasi persentase ADC 10-bit pada progress bar dan grafik histori real-time hingga 40 titik data berbasis HTML Canvas.
4. Penggunaan logika pewaktuan non-blocking berbasis fungsi millis() pada ESP32 terbukti sangat efektif untuk mengelola tugas ganda (pembacaan sensor 2 detik dan fitur auto-reconnect Wi-Fi 10 detik) tanpa menyebabkan kemacetan eksekusi program.
Untuk pengembangan dan penyempurnaan sistem monitoring IoT lebih lanjut di masa mendatang, disarankan beberapa poin berikut:
1. Pengintegrasian Database Terdistribusi: Menyimpan data histori suhu dan kelembapan ke dalam database seperti MySQL, PostgreSQL, atau InfluxDB agar data tidak hilang saat halaman peramban web direfresh.
2. Migrasi ke Protokol Real-Time Nirkabel: Mengganti metode HTTP Polling dengan protokol WebSocket atau Server-Sent Events (SSE) guna mengurangi overhead header HTTP dan meningkatkan efisiensi transmisi data real-time.
3. Peningkatan Fitur Keamanan: Menambahkan lapisan autentikasi pengguna (login session) serta mengimplementasikan enkripsi HTTPS (SSL/TLS) dan captive portal konfigurasi Wi-Fi (Wi-Fi Manager) pada ESP32 untuk mengamankan kredensial jaringan.
DAFTAR PUSTAKA
[1] A. S. Tanenbaum and D. J. Wetherall, Computer Networks, 5th ed. Boston, MA: Pearson Education, 2011.
[2] Espressif Systems, ESP32 Technical Reference Manual, Version 4.5, Espressif Systems, 2022.
[3] M. Banzi and M. Shiloh, Getting Started with Arduino, 4th ed. Sebastopol, CA: Make Community, 2022.
[4] M. Grinberg, Flask Web Development: Developing Web Applications with Python, 2nd ed. Sebastopol, CA: O'Reilly Media, 2018.
[5] Adafruit Industries, Adafruit DHT Humidity & Temperature Sensor Library Documentation, 2023. [Online]. Available: https://github.com/adafruit/DHT-sensor-library
LAMPIRAN
Video Demo: https://www.youtube.com/watch?v=R-DfE26hE2g
Tidak ada komentar:
Posting Komentar