Pernahkah Anda membutuhkan mekanisme untuk memantau parameter lingkungan, seperti suhu dan kelembaban, mulai dari perangkat seluler, tablet, ataupun komputer secara real-time melalui jaringan? Rancangan sistem IoT berikut menyediakan implementasi dasarnya. Dalam konfigurasi ini, NodeMCU ESP8266 berfungsi sebagai unit pengendali yang terhubung ke jaringan WiFi lokal dan menginisiasi web server mandiri. Setelah server aktif, ESP8266 melakukan akuisisi data suhu dan kelembaban relatif menggunakan sensor DHT11/DHT22, kemudian menyajikan hasil pengukuran tersebut melalui antarmuka web yang dapat diakses dari perangkat klien apa pun. Sebelum melanjutkan ke tahap implementasi, terdapat beberapa konsep dasar yang perlu dipahami. Jika Anda belum familiar dengan salah satu materi yang direferensikan di bawah ini, disarankan untuk mempelajarinya terlebih dahulu.
Menghubungkan Sensor DHT11/DHT22 ke ESP8266
Integrasi sensor DHT11/DHT22 dengan modul ESP8266 dilakukan dengan konfigurasi rangkaian yang relatif sederhana. Tempatkan terlebih dahulu ESP8266 pada breadboard sehingga masing-masing baris pin berada pada jalur terpisah. Posisikan modul sensor pada breadboard di area berdekatan dengan ESP8266 untuk meminimalkan panjang jalur. Sambungkan pin VCC sensor ke rail 3.3 V pada ESP8266, dan hubungkan pin GND ke rail ground yang sama. Jalur data sensor kemudian dikonfigurasikan menuju pin D8 pada ESP8266 sebagai input digital. Untuk memastikan integritas sinyal dan menjaga kondisi idle pada level HIGH, pasang resistor pull-up 10 kΩ antara pin VCC dan jalur data. Implementasi resistor ini penting untuk menjaga stabilitas komunikasi satu-kawat (one-wire protocol) antara sensor dan ESP8266. Diagram berikut mengilustrasikan topologi pengkabelannya.
Menginstal Pustaka Sensor DHT
Untuk mengaktifkan proses akuisisi data dari sensor, diperlukan instalasi library DHT yang menyediakan implementasi protokol komunikasi dan fungsi-fungsi abstraksi tingkat tinggi. Pustaka tersebut dapat diperoleh melalui Library Manager pada lingkungan pengembangan Arduino.
Untuk melakukan instalasi, navigasikan ke Sketch > Include Library > Manage Libraries…. Setelah jendela Library Manager terbuka, tunggu hingga sistem menyelesaikan proses sinkronisasi dan pemutakhiran indeks pustaka sehingga daftar pustaka yang tersedia dan terpasang diperbarui secara penuh.
Filter hasil pencarian dengan memasukkan kata kunci “DHT sensor” pada kolom filter Library Manager. Dari daftar pustaka yang muncul, identifikasi paket Adafruit DHT Sensor Library. Setelah pustaka yang sesuai ditemukan, pilih entri tersebut dan klik Install untuk memulai proses instalasi dependensi secara otomatis.
Pustaka DHT Sensor bergantung pada kerangka Adafruit Unified Sensor sebagai lapisan abstraksi perangkat keras. Oleh karena itu, lakukan pencarian “Adafruit Unified Sensor” melalui Library Manager dan instal pustaka tersebut untuk memastikan seluruh dependensi backend terpenuhi.
Baca juga: Cara Menggunakan Layar LCD I2C dengan ESP8266
Membuat Server Web ESP8266 menggunakan mode WiFi Station (STA)
Sekarang, beralih ke tahap implementasi inti. Sesuai ruang lingkup proyek, modul ESP8266 akan dikonfigurasi dalam mode Station (STA) untuk menginisiasi web server yang dapat diakses oleh klien mana pun pada jaringan WiFi yang sama. Sebelum mengunggah sketsa ke papan, pastikan Anda memperbarui dua variabel konfigurasi jaringan dengan SSID dan kata sandi WiFi Anda agar ESP8266 dapat melakukan proses association dan authentication ke access point yang sudah ada.
const char* ssid = "YourNetworkName"; // Enter SSID here
const char* password = "YourPassword"; //Enter Password here
Setelah selesai, cobalah sketsa tersebut, lalu kami akan membahasnya secara detail.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "DHT.h"
// Uncomment one of the lines below for whatever DHT sensor type you're using!
//#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
/*Put your SSID & Password*/
const char* ssid = "YourNetworkName"; // Enter SSID here
const char* password = "YourPassword"; //Enter Password here
ESP8266WebServer server(80);
// DHT Sensor
uint8_t DHTPin = D8;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
float Temperature;
float Humidity;
void setup() {
Serial.begin(115200);
delay(100);
pinMode(DHTPin, INPUT);
dht.begin();
Serial.println("Connecting to ");
Serial.println(ssid);
//connect to your local wi-fi network
WiFi.begin(ssid, password);
//check wi-fi is connected to wi-fi network
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
server.on("/", handle_OnConnect);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}
void handle_OnConnect() {
Temperature = dht.readTemperature(); // Gets the values of the temperature
Humidity = dht.readHumidity(); // Gets the values of the humidity
server.send(200, "text/html", SendHTML(Temperature,Humidity));
}
void handle_NotFound(){
server.send(404, "text/plain", "Not found");
}
String SendHTML(float Temperaturestat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP8266 Weather Report</title>\n";
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 NodeMCU Weather Report</h1>\n";
ptr +="<p>Temperature: ";
ptr +=(int)Temperaturestat;
ptr +="°C</p>";
ptr +="<p>Humidity: ";
ptr +=(int)Humiditystat;
ptr +="%</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Mengakses Server Web
Setelah mengunggah sketsa, buka Serial Monitor pada 115200 baud dan tekan tombol RESET pada NodeMCU. Jika semuanya baik-baik saja, program akan menampilkan alamat IP dinamis yang diperoleh dari router Anda serta pesan "Server HTTP dimulai".
Selanjutnya, buka peramban web dan akses alamat IP yang sebelumnya ditampilkan pada Serial Monitor. Setelah permintaan HTTP dikirim, modul ESP8266 akan merespons dengan menyajikan halaman web yang memuat data pembacaan suhu dan kelembaban relatif secara real-time.
Penjelasan Kode Detail
Sketsa diawali dengan mengimpor pustaka ESP8266WiFi.h, yang menyediakan himpunan fungsi tingkat rendah dan API protokol jaringan yang diperlukan untuk menginisialisasi antarmuka WiFi dan membangun koneksi ke infrastruktur WLAN. Selanjutnya, pustaka ESP8266WebServer.h disertakan untuk memanfaatkan abstraksi server HTTP bawaan, memungkinkan konfigurasi endpoint serta penanganan permintaan dan respons HTTP tanpa perlu mengelola proses parsing atau protokol secara manual. Terakhir, pustaka DHT.h ditambahkan sebagai driver antarmuka sensor untuk melakukan inisialisasi modul DHT serta mengeksekusi rutinitas pembacaan suhu dan kelembaban melalui jalur data digital.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "DHT.h"
Selanjutnya, menentukan jenis sensor DHT yang digunakan. Hapus komentar pada baris yang sesuai di bawah ini!
//#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
Karena web server pada ESP8266 dioperasikan dalam mode Station (STA), modul akan berperan sebagai klien yang melakukan asosiasi ke infrastruktur WiFi yang telah tersedia. Oleh karena itu, parameter SSID dan kata sandi jaringan harus didefinisikan secara eksplisit agar stack WiFi ESP8266 dapat melakukan proses autentikasi, asosiasi, dan memperoleh konektivitas IP pada jaringan tersebut.
/*Put your SSID & Password*/
const char* ssid = "YourNetworkName"; // Enter SSID here
const char* password = "YourPassword"; //Enter Password her
e
Setelah itu, membuat objek pustaka ESP8266WebServer agar dapat mengakses fungsinya. Konstruktor objek ini menerima port yang akan didengarkan oleh server sebagai parameter. Karena HTTP menggunakan port 80 secara default, maka akan menggunakan nilai ini. Hal ini memungkinkan Anda untuk terhubung ke server tanpa menentukan port di URL.
// declare an object of WebServer library
ESP8266WebServer server(80);
Selanjutnya, tentukan nomor pin GPIO pada NodeMCU ESP8266 yang terhubung dengan pin Data sensor Anda dan buat objek DHT. Dengan demikian, Anda dapat mengakses fungsi-fungsi khusus pustaka DHT.
// DHT Sensor
uint8_t DHTPin = D8;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
Ada dua variabel float yang diatur, yaitu suhu dan kelembaban.
- float Temperature;
- float Humidity;
Di Dalam Fungsi Setup()
Di dalam fungsi setup(), konfigurasi awal untuk layanan web server diinisialisasi. Tahap pertama mencakup aktivasi antarmuka Serial sebagai kanal debugging dan pemantauan runtime. Selanjutnya, pin GPIO yang digunakan oleh sensor dikonfigurasi dalam mode INPUT untuk memastikan karakteristik impedansi dan akuisisi sinyal digital sesuai spesifikasi. Setelah itu, instance objek DHT diinisialisasi sehingga driver dapat menyiapkan protokol komunikasi satu-kawat (single-wire protocol) yang digunakan sensor untuk mentransmisikan data suhu dan kelembaban.
Serial.begin(115200);
delay(100);
pinMode(DHTPin, INPUT);
dht.begin();
Kemudian, gunakan fungsi WiFi.begin() untuk terhubung ke jaringan WiFi. Fungsi ini menerima SSID (Nama Jaringan) dan kata sandi sebagai parameter.
Serial.println("Connecting to ");
Serial.println(ssid);
//connect to your local wi-fi network
WiFi.begin(ssid, password);
Saat ESP8266 mencoba terhubung ke jaringan, Anda dapat menggunakan fungsi WiFi.status() untuk memeriksa status konektivitas.
//check wi-fi is connected to wi-fi network
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Setelah terhubung ke jaringan, fungsi WiFi.localIP() digunakan untuk mencetak alamat IP yang ditetapkan ke ESP8266.
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
Untuk menangani permintaan HTTP yang masuk, Anda harus menentukan kode mana yang akan dieksekusi ketika URL tertentu diakses. Untuk ini, gunakan metode .on(). Metode ini menerima dua parameter, yaitu jalur URL relatif dan nama fungsi yang akan dieksekusi ketika URL tersebut dikunjungi.
Kode di bawah ini menunjukkan bahwa ketika server menerima permintaan HTTP pada jalur root (/), server akan memanggil fungsi handle_OnConnect(). Perlu dicatat bahwa URL yang ditentukan adalah jalur relatif.
server.on("/", handle_OnConnect);
Kami belum menentukan apa yang harus dilayani server jika klien meminta URL yang tidak ditentukan dengan server.on(). Seharusnya server akan memberikan respons kesalahan 404 (Halaman Tidak Ditemukan). Untuk mencapai hal ini, gunakan metode server.onNotFound().
server.onNotFound(handle_NotFound);
Sekarang, untuk memulai server, Anda dapat memanggil metode begin() dari objek server.
server.begin();
Serial.println("HTTP server started");
Di Dalam Fungsi Loop()
Permintaan HTTP yang masuk ditangani dalam fungsi loop. Untuk ini, gunakan metode handleClient() dari objek server.
server.handleClient();
Sekarang Anda harus menulis fungsi handle_OnConnect(), yang sebelumnya Anda lampirkan ke URL root (/) dengan server.on. Anda memulai fungsi ini dengan membaca nilai suhu dan kelembaban dari sensor. Gunakan metode send untuk merespons permintaan HTTP. Meskipun metode ini dapat dipanggil dengan sejumlah argumen berbeda, bentuk yang paling sederhana memerlukan kode respons HTTP, tipe konten, dan konten.
Parameter pertama yang diberikan ke metode kirim adalah kode 200 (salah satu kode status HTTP), yang sesuai dengan respons OK. Kemudian, tentukan tipe kontennya sebagai "text/html", dan terakhir, berikan fungsi kustom SendHTML(), yang menghasilkan halaman HTML dinamis berisi pembacaan suhu dan kelembaban.
void handle_OnConnect() {
Temperature = dht.readTemperature(); // Gets the values of the temperature
Humidity = dht.readHumidity(); // Gets the values of the humidity
server.send(200, "text/html", SendHTML(Temperature,Humidity));
}
Demikian pula, sebuah handler khusus diimplementasikan untuk memproses permintaan yang tidak sesuai dengan rute yang terdefinisi, yaitu dengan membangkitkan respons HTTP 404 (Not Found). Handler ini memastikan bahwa setiap permintaan ke endpoint yang tidak valid ditangani secara terstruktur dan menghasilkan keluaran diagnostik yang sesuai.
void handle_NotFound(){
server.send(404, "text/plain", "Not found");
}
Setiap kali web server ESP8266 menerima request dari klien, fungsi sendHTML() dipanggil untuk mengonstruksi respons halaman web. Fungsi ini menyusun markup HTML secara programatis dengan melakukan string concatenation terhadap elemen-elemen HTML, kemudian mengembalikan hasilnya ke metode server.send() yang sebelumnya telah dikonfigurasi untuk menangani pengiriman respons HTTP. Parameter pembacaan suhu dan kelembaban diteruskan ke fungsi tersebut sehingga konten halaman dapat dirender secara dinamis berdasarkan data sensor terkini. Sebagai bagian dari struktur respons, deklarasi <!DOCTYPE html> wajib dikirimkan pada awal dokumen untuk menginformasikan ke klien bahwa konten yang disajikan mengikuti standar HTML modern.
String SendHTML(float Temperaturestat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
Elemen viewport <meta> membuat halaman web responsif, memastikan tampilannya bagus di semua perangkat. Tag judul menentukan judul halaman.
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP8266 Weather Report</title>\n";
Menata Halaman Web
Setelah itu, kita akan menggunakan CSS untuk menata tampilan keseluruhan halaman web. Kita pilih font Helvetica dan tentukan konten yang akan ditampilkan sebagai blok sebaris dan rata tengah.
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
Baris kode berikutnya melakukan konfigurasi gaya melalui deklarasi CSS, mencakup penetapan parameter warna, pemilihan font family, serta definisi spacing eksternal (margin) untuk elemen <body>, <h1>, dan <p>. Pengaturan ini memastikan konsistensi tampilan dan tata letak saat halaman dirender oleh klien.
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
Mengatur Judul Halaman Web
Selanjutnya, judul halaman web akan diatur. Anda dapat mengubah teks ini menjadi teks apa pun yang sesuai untuk aplikasi Anda.
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 Weather Report</h1>\n";
Menampilkan Suhu dan Kelembaban di Halaman Web
Kami menggunakan tag paragraf untuk menampilkan nilai suhu dan kelembaban. Perhatikan bahwa nilai-nilai ini dikonversi menjadi bilangan bulat menggunakan pengecoran tipe.
ptr +="<p>Temperature: ";
ptr +=(int)Temperaturestat;
ptr +="°C</p>";
ptr +="<p>Humidity: ";
ptr +=(int)Humiditystat;
ptr +="%</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Menata Halaman Web agar Terlihat Lebih Menarik
Programmer cenderung mengabaikan estetika, tetapi dengan sedikit usaha, halaman web kita dapat terlihat lebih menarik. Tangkapan layar di bawah ini akan memberi Anda gambaran tentang apa yang akan kita lakukan.
Luar biasa, bukan? Selanjutnya kita tambahkan styling pada halaman HTML. Gantilah implementasi fungsi SendHTML() pada sketsa sebelumnya dengan potongan kode berikut yang menyertakan stylesheet dan markup yang diperluas; unggah sketsa yang telah diperbarui, lalu kita akan melakukan pembahasan rinci terhadap perubahan tersebut.
String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewpor
String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
ptr +="<title>ESP8266 Weather Report</title>\n";
ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
ptr +="body{margin-top: 50px;}\n";
ptr +="h1 {margin: 50px auto 30px;}\n";
ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
ptr +=".data{padding: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 Weather Report</h1>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side temperature-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
ptr +="<div class=\"side-by-side temperature\">";
ptr +=(int)TempCstat;
ptr +="<span class=\"superscript\">°C</span></div>\n";
ptr +="</div>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side humidity-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
ptr +="<div class=\"side-by-side humidity\">";
ptr +=(int)Humiditystat;
ptr +="<span class=\"superscript\">%</span></div>\n";
ptr +="</div>\n";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Penjelasan Kode
Kita telah mengetahui bahwa deklarasi `<!DOCTYPE>` menginformasikan user agent bahwa dokumen yang dikirimkan menggunakan sintaks HTML, sementara elemen `<meta name="viewport">` menginstruksikan browser untuk menerapkan skala dan perilaku layout responsif. Pada implementasi ini, perbedaannya terletak pada penggunaan web font eksternal melalui Google Fonts. Layanan tersebut menyediakan kumpulan font berbasis web yang dapat digunakan secara bebas, baik untuk kebutuhan komersial maupun non-komersial.
Untuk halaman ini, font keluarga Open Sans akan digunakan sebagai primary typeface. Font tersebut ditautkan melalui elemen `<link>` yang ditempatkan di bagian `<head>` dokumen HTML, yang akan memicu pengambilan resource font dari server Google.
Dalam konfigurasi ini, dipilih beberapa font weights, yakni 300 (Light), 400 (Regular), dan 600 (Semi-Bold). Anda dapat menambahkan weight tambahan sesuai kebutuhan, namun perlu diperhatikan bahwa semakin banyak varian weight dan gaya yang dimuat, semakin besar ukuran total resource, sehingga meningkatkan page load time.
Gaya miring (italic) juga dapat dimuat dengan menambahkan sufiks `i` pada nilai weight (misalnya `400i` untuk Regular Italic).
Perlu dicatat bahwa web font dari Google diambil secara on-demand saat halaman dimuat; oleh karena itu, perangkat klien harus memiliki koneksi internet aktif agar font tersebut dapat ditampilkan dengan benar. Tanpa koneksi, browser akan menerapkan fallback font standar sistem.
String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
Selanjutnya, kita akan menerapkan font Open Sans ke seluruh dokumen HTML. Kita juga harus menentukan sans-serif sebagai font cadangan. Jika font pertama yang ditentukan gagal dimuat, peramban akan mencoba memuat font cadangan.
ptr +="<title>ESP8266 Weather Report</title>\n";
ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
ptr +="body{margin-top: 50px;}\n";
ptr +="h1 {margin: 50px auto 30px;}\n";
Berikutnya, kita menerapkan aturan CSS untuk komponen Kelembaban & Suhu yang mencakup ikon, judul, dan nilai. Ketiga elemen tersebut diatur dalam satu kolom dengan perataan vertikal. Area ikon dibentuk menjadi lingkaran melalui penerapan `border-radius: 50%` serta penetapan dimensi tetap sebesar 30 piksel pada properti tinggi dan lebar.
ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
ptr +=".data{padding: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
Selanjutnya, sistem menampilkan data suhu yang direpresentasikan melalui sebuah ikon vektor berukuran kecil. Ikon tersebut merupakan objek Scalable Vector Graphics (SVG) yang dideklarasikan menggunakan elemen `<svg>`. Pembuatan aset SVG tidak membutuhkan keterampilan pemrograman tingkat lanjut, karena grafik dapat dirancang menggunakan perangkat seperti Google SVG Editor. Setelah elemen ikon dirender, aplikasi kemudian memuat dan menampilkan nilai suhu aktual yang diperoleh dari sensor.
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 NodeMCU Weather Report</h1>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side temperature-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
ptr +="<div class=\"side-by-side temperature\">";
ptr +=(int)TempCstat;
ptr +="<span class=\"superscript\">°C</span></div>\n";
ptr +="</div>\n";
Ikon ini digunakan untuk memvisualisasikan data kelembaban, yang juga direpresentasikan sebagai objek Scalable Vector Graphics (SVG). Setelah proses render dan pencetakan nilai kelembaban selesai, sistem melakukan penutupan seluruh elemen markup yang sebelumnya dibuka, termasuk elemen `<body>` dan `<html>`.
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side humidity-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
ptr +="<div class=\"side-by-side humidity\">";
ptr +=(int)Humiditystat;
ptr +="<span class=\"superscript\">%</span></div>\n";
ptr +="</div>\n";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Penjelasan Kode
Deklarasi `<!DOCTYPE>` berfungsi untuk menginformasikan user-agent bahwa dokumen yang dikirim merupakan dokumen HTML, sedangkan elemen viewport `<meta>` mengonfigurasi karakteristik responsivitas pada perangkat dengan berbagai ukuran layar. Pada tahap ini, perbedaannya terletak pada penggunaan Google Fonts sebagai sumber tipografi eksternal. Google Fonts menyediakan ratusan font web yang dapat digunakan secara gratis, baik untuk keperluan komersial maupun non-komersial.
Dalam implementasi ini, font keluarga Open Sans digunakan sebagai font utama. Penyematan font dilakukan melalui elemen `<link>` yang ditempatkan di dalam bagian `<head>` dokumen HTML untuk memuat sumber daya tipografi dari server Google.
Untuk kebutuhan tampilan, dipilih tiga varian ketebalan font: 300 (Light), 400 (Regular), dan 600 (Semi-Bold). Meskipun lebih banyak varian bobot font dapat ditambahkan, perlu diperhatikan bahwa pemuatan terlalu banyak varian akan berdampak pada peningkatan waktu *resource loading* halaman.
Selain itu, varian italic dapat dimuat dengan menambahkan sufiks `i` pada nilai ketebalan font; misalnya, `400i` akan memuat varian Regular Italic.
Perlu diketahui bahwa pemuatan Google Fonts bersifat dinamis dan dilakukan secara remote. Oleh karena itu, font tidak akan ditampilkan apabila perangkat pengguna tidak memiliki koneksi internet aktif saat mengakses halaman.
String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
Selanjutnya, kita akan menerapkan font Open Sans ke seluruh dokumen HTML. Kita juga harus menentukan sans-serif sebagai font cadangan. Jika font pertama yang ditentukan gagal dimuat, peramban akan mencoba memuat font cadangan.
ptr +="<title>ESP8266 Weather Report</title>\n";
ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
ptr +="body{margin-top: 50px;}\n";
ptr +="h1 {margin: 50px auto 30px;}\n";
Selanjutnya, lakukan penerapan style CSS untuk komponen Kelembaban dan Suhu, yang meliputi elemen ikon, judul, serta nilai pengukuran. Ketiga elemen tersebut diatur agar tersusun secara vertikal dan terpusat dalam satu kolom. Untuk membentuk latar belakang ikon berbentuk lingkaran, properti `border-radius` dikonfigurasikan pada nilai 50%, dengan dimensi elemen ditetapkan sebesar 30 piksel untuk tinggi maupun lebarnya.
ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
ptr +=".data{padding: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
Selanjutnya, sistem merender nilai suhu yang diperoleh dari sensor dan menampilkannya berdampingan dengan ikon indikator suhu berukuran kecil. Ikon tersebut direpresentasikan sebagai objek Scalable Vector Graphics (SVG) yang dideklarasikan menggunakan elemen `<svg>`. Pembuatan aset SVG tidak memerlukan kompetensi pemrograman tingkat lanjut, karena grafik vektor tersebut dapat dihasilkan melalui berbagai editor, seperti Google SVG Editor. Setelah proses pemuatan ikon, nilai suhu aktual yang dibaca oleh sensor kemudian disisipkan ke dalam output halaman secara dinamis.
ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 NodeMCU Weather Report</h1>\n";
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side temperature-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
ptr +="<div class=\"side-by-side temperature\">";
ptr +=(int)TempCstat;
ptr +="<span class=\"superscript\">°C</span></div>\n";
ptr +="</div>\n";
Ikon berikut digunakan sebagai indikator visual untuk parameter kelembaban, yang direpresentasikan sebagai elemen Scalable Vector Graphics (SVG) tambahan. Setelah nilai kelembaban berhasil diekstraksi dari sensor dan ditampilkan bersamaan dengan ikon tersebut, sistem kemudian menutup seluruh elemen markup yang masih terbuka, termasuk tag <body> dan <html>, guna memastikan struktur dokumen HTML tersusun secara valid dan sesuai spesifikasi.
ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side humidity-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
ptr +="<div class=\"side-by-side humidity\">";
ptr +=(int)Humiditystat;
ptr +="<span class=\"superscript\">%</span></div>\n";
ptr +="</div>\n";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Peningkatan 1 – Penyegaran Halaman Otomatis
Salah satu optimalisasi yang dapat diterapkan adalah mekanisme penyegaran otomatis pada halaman untuk memperbarui nilai sensor secara berkala. Fungsi ini dapat diaktifkan dengan mengonfigurasi elemen `<meta>` tertentu di dalam dokumen HTML, yang menginstruksikan *client browser* untuk melakukan pemuatan ulang (auto-refresh) pada interval waktu yang telah ditentukan.
<meta http-equiv="refresh" content="2" >
Masukkan kode ini ke dalam tag <head> dokumen Anda; tag meta ini akan memerintahkan browser untuk menyegarkan setiap dua detik.
Peningkatan 2 – Memuat Data Sensor Secara Dinamis dengan AJAX
Melakukan refresh penuh pada halaman web menjadi tidak efisien, terutama untuk halaman berukuran besar. Pendekatan yang lebih optimal adalah menggunakan AJAX (Asynchronous JavaScript and XML), yang memungkinkan pengambilan data dari server secara asinkron di latar belakang tanpa memuat ulang seluruh halaman.
Dalam JavaScript, objek `XMLHttpRequest` biasanya digunakan untuk mengimplementasikan mekanisme AJAX. Objek ini mengirim permintaan GET secara *silent* ke server dan memperbarui elemen tertentu pada halaman. Perlu dicatat bahwa AJAX bukan teknologi baru ataupun bahasa pemrograman terpisah; melainkan pemanfaatan gabungan teknologi yang sudah ada dengan pola kerja asinkron. Dengan AJAX, Anda dapat:
- Mengambil data dari server setelah halaman selesai dimuat.
- Menerima pembaruan data secara dinamis tanpa *reload*.
- Mengirim data ke server di latar belakang.
Berikut adalah skrip AJAX yang akan digunakan; tempatkan skrip tersebut sebelum tag penutup `<head>`.
ptr +="<script>\n";
ptr +="setInterval(loadDoc,200);\n";
ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";
ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
ptr +="};\n";
ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";
ptr +="</script>\n";
Penjelasan Kode
Karena skrip AJAX hanyalah JavaScript, skrip tersebut harus diapit oleh tag <script>. Kita akan menggunakan fungsi JavaScript setInterval() untuk membuat fungsi ini memanggil dirinya sendiri berulang kali. Fungsi ini membutuhkan dua parameter, yaitu fungsi yang akan dieksekusi dan interval waktu (dalam milidetik).
ptr +="<script>\n";
ptr +="setInterval(loadDoc,200);\n";
Fungsi loadDoc() adalah bagian terpenting dari skrip ini. Dalam fungsi ini, sebuah objek XMLHttpRequest() dibuat. Objek ini digunakan untuk meminta data dari web server.
ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";
Metode xhttp.onreadystatechange() dipanggil setiap kali readyState berubah. Properti readyState merepresentasikan status XMLHttpRequest. Properti ini memiliki salah satu nilai yang tercantum di bawah ini.
0: permintaan belum diinisialisasi
1: koneksi server dibuat
2: permintaan diterima
3: permintaan diproses
4: permintaan selesai dan respons siap
Properti status menyimpan status objek XMLHttpRequest. Properti ini memiliki salah satu nilai yang tercantum di bawah ini.
200: "OK"
403: "Dilarang"
404: "Halaman tidak ditemukan"
Ketika readyState bernilai 4 dan status bernilai 200, respons selesai, dan konten elemen dengan ID 'webpage' (div yang berisi nilai suhu dan kelembaban) diperbarui.
ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
ptr +="};\n";
Fungsi open() dan send() kemudian digunakan untuk memulai permintaan HTTP.
ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";
Baca juga: Cara Mudah Membuat Weather Station Menggunakan ESP8266 dan BME280
Siap Untuk Membuat Proyek Impianmu Menjadi Kenyataan?
Klik di sini untuk chat langsung via WhatsApp dan dapatkan dukungan langsung dari tim ahli kami!







0 Komentar