Pendahuluan — Dari HTTP ke HTTPS di ESP32
Seri 1 sudah mengajarkan WiFi (#4), web server lokal (#6), dan MQTT (#7). Di Tier 2, MQTT TLS (#17) mengamankan koneksi ke broker Mosquitto (#16) di jaringan lokal — misalnya 192.168.1.50.
Artikel Tier 2 ini fokus pada skenario berbeda: ESP32 memanggil REST API publik lewat HTTPS — webhook, layanan cloud, atau backend VPS di internet. Kita pakai WiFiClientSecure + HTTPClient, bukan protokol MQTT. Ini melengkapi REST vs MQTT (#20), Firebase (#30), dan persiapan capstone greenhouse (#39).
Prasyarat: Paham GPIO (#3), WiFi (#4), DHT22 (#5), dan idealnya sudah baca MQTT TLS (#17) agar tidak bingung antara TLS untuk broker vs TLS untuk HTTP.
HTTPS vs HTTP — Mengapa Harus Terenkripsi?
HTTP mengirim data sensor (suhu, lokasi, token API) dalam bentuk teks biasa — siapa pun di jaringan WiFi publik atau ISP bisa membaca paket. HTTPS membungkus HTTP di dalam TLS: server membuktikan identitas lewat sertifikat, lalu saluran terenkripsi.
| Aspek | HTTP | HTTPS |
|---|---|---|
| Port default | 80 | 443 |
| Enkripsi | Tidak | TLS 1.2+ |
| Verifikasi server | Tidak | Root CA |
| Cocok untuk API cloud | ❌ | ✅ |
| Web server ESP32 lokal (#6) | ✅ LAN | Opsional |
WiFiClientSecure vs WiFiClient Biasa
Library HTTPClient Arduino bisa memakai WiFiClient untuk URL http:// atau WiFiClientSecure untuk https://. Kelas secure menambahkan handshake TLS di atas TCP — mirip konsep di MQTT TLS (#17), tapi stack aplikasinya HTTP, bukan publish/subscribe.
WiFiClient— cukup untuk web server lokal (#6) di LANWiFiClientSecure— wajib untuk API eksternal, Firebase (#30), webhook produksi
Pro tip: Artikel ini tidak membutuhkan
SPI.h— tidak ada SD Card atau periferal SPI seperti di logging SD (#37). Cukup WiFi + sensor DHT22 (#5).
Perbedaan dengan MQTT TLS (#17)
| Topik | MQTT TLS (#17) | HTTPS REST (artikel ini) |
|---|---|---|
| Protokol | MQTT publish/subscribe | HTTP GET/POST request-response |
| Library utama | PubSubClient + WiFiClientSecure | HTTPClient + WiFiClientSecure |
| Port umum | 8883 (broker) | 443 (web API) |
| Target tipikal | Broker 192.168.1.50 | Domain publik api.example.com |
| Pola data | Topic + payload berkelanjutan | Endpoint + JSON sekali kirim |
Keduanya memakai setCACert() untuk verifikasi server — konsep sertifikat sama, konteks aplikasi berbeda. Baca #20 untuk memilih arsitektur proyek.
HTTPClient + WiFiClientSecure — Pola Dasar
Alur standar di firmware ESP32:
- Connect WiFi dengan placeholder
GANTI_NAMA_WIFI/GANTI_PASSWORD_WIFI - Instansiasi
WiFiClientSecure client - Panggil
client.setCACert(root_ca)dengan sertifikat CA yang di-embed http.begin(client, url)— pass client secure ke HTTPClientGETatauPOST→ bacahttp.getString()atau status codehttp.end()setiap selesai
Prasyarat & Koneksi WiFi
Sama seperti seluruh seri — jangan hardcode SSID/password di repo publik:
#include <WiFi.h>
const char* WIFI_SSID = "GANTI_NAMA_WIFI";
const char* WIFI_PASS = "GANTI_PASSWORD_WIFI";
void connectWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi OK");
}
Untuk deploy lapangan, simpan kredensial di NVS (#12) — pola yang sama dipakai di capstone #10.
Mendapatkan Root CA Certificate
Server HTTPS mempresentasikan rantai sertifikat; ESP32 perlu root CA (Certificate Authority) tepercaya untuk memverifikasi bahwa Anda benar-benar berbicara dengan server yang dimaksud — bukan penyerang man-in-the-middle.
Cara umum mengambil root CA (contoh untuk Let's Encrypt / ISRG):
openssl s_client -showcerts -connect api.example.com:443 < /dev/null 2>/dev/null \
| openssl x509 -outform PEM > ca.pem
Atau unduh bundle CA resmi dari dokumentasi penyedia API. Salin isi PEM ke variabel const char* root_ca di sketch.
Embed Sertifikat Root CA di Firmware
Sertifikat disimpan sebagai string multiline di flash — tidak perlu filesystem eksternal:
const char* root_ca =
"-----BEGIN CERTIFICATE-----\n"
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
"... baris base64 dari ca.pem ...\n"
"-----END CERTIFICATE-----\n";
Ganti baris tengah dengan isi file ca.pem Anda. Jangan commit sertifikat produksi sensitif jika organisasi Anda punya kebijakan khusus — untuk CA publik, ini aman.
setCACert — Verifikasi Server yang Benar
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
WiFiClientSecure secureClient;
void setupSecureHttp() {
secureClient.setCACert(root_ca);
// Opsional: setTimeout jika API lambat
secureClient.setTimeout(15000);
}
Tanpa setCACert, handshake TLS gagal atau library menolak koneksi — ESP32 tidak punya trust store lengkap seperti browser desktop.
setInsecure — Hanya untuk Development
Baris berikut mematikan verifikasi sertifikat:
secureClient.setInsecure(); // JANGAN di produksi!
Berguna saat prototyping cepat di lab — misalnya API self-signed tanpa CA. Di lapangan atau cloud, selalu pakai setCACert. Sama seperti peringatan di MQTT TLS (#17): jangan bawa kebijakan dev ke produksi.
HTTPS GET — Baca Data dari API
Contoh membaca konfigurasi atau status dari endpoint:
void httpsGetExample() {
HTTPClient http;
const char* url = "https://api.example.com/v1/status";
if (!http.begin(secureClient, url)) {
Serial.println("http.begin gagal");
return;
}
int code = http.GET();
if (code == HTTP_CODE_OK) {
String body = http.getString();
Serial.println(body);
} else {
Serial.printf("GET error: %d\n", code);
}
http.end();
}
Response bisa JSON — parse dengan ArduinoJson jika perlu threshold suhu untuk relay di artikel capstone #10.
HTTPS POST — Kirim Data Sensor JSON
Pola utama artikel ini: kirim pembacaan DHT22 (#5) ke backend REST, paralel atau pengganti MQTT:
void httpsPostSensor(float tempC, float humPct, long unixTs) {
HTTPClient http;
const char* url = "https://api.example.com/v1/sensors";
if (!http.begin(secureClient, url)) return;
http.addHeader("Content-Type", "application/json");
// Header auth — ganti dengan token Anda, jangan commit ke repo
http.addHeader("Authorization", "Bearer GANTI_TOKEN_API");
char payload[200];
snprintf(payload, sizeof(payload),
"{\"unix\":%ld,\"timestamp\":\"2026-07-02T14:30:00\","
"\"temp\":%.1f,\"hum\":%.1f,\"device\":\"esp32-dht22\"}",
unixTs, tempC, humPct);
int code = http.POST(payload);
Serial.printf("POST %d\n", code);
if (code > 0) {
Serial.println(http.getString());
}
http.end();
}
Payload JSON dengan Timestamp NTP
Gunakan waktu akurat dari NTP (#34) — contoh unix 1782977400 dan ISO 2026-07-02T14:30:00 konsisten di seluruh seri:
time_t now = time(nullptr); // setelah configTime() NTP
struct tm ti;
localtime_r(&now, &ti);
char iso[25];
strftime(iso, sizeof(iso), "%Y-%m-%dT%H:%M:%S", &ti);
char payload[220];
snprintf(payload, sizeof(payload),
"{\"unix\":%ld,\"timestamp\":\"%s\",\"temp\":%.1f,\"hum\":%.1f}",
(long)now, iso, tempC, humPct);
Backend Python (#18) bisa menerima POST HTTPS dengan skema field yang sama seperti payload MQTT — memudahkan migrasi dari broker ke REST.
Kontras: Broker Lokal 192.168.1.50 vs API HTTPS Publik
| Lingkungan | Alamat contoh | Protokol | Artikel terkait |
|---|---|---|---|
| Broker rumah / VPS LAN | 192.168.1.50:1883 | MQTT plain / TLS 8883 | #16, #17 |
| API cloud / SaaS | https://api.example.com | HTTPS 443 | #38 (ini) |
| Firebase | https://*.firebaseio.com | HTTPS + token | #30 |
| Web server ESP32 | http://192.168.1.x | HTTP LAN | #6 |
Node MQTT di LAN bisa pakai user kindo_esp32 dengan password GANTI_PASSWORD_MQTT — itu pola broker, bukan header REST. Jangan campur kredensial MQTT ke header Authorization API kecuali backend Anda memang mendesainnya demikian.
REST API vs MQTT — Kapan Pakai HTTPS?
Rangkuman dari #20:
- HTTPS REST — laporan berkala ke SaaS, webhook, integrasi HTTP-only, mobile backend
- MQTT — banyak device, real-time, broker pusat, dashboard Grafana (#19)
- Keduanya — hybrid seperti capstone #10: MQTT lokal + HTTPS backup ke cloud
Error Handling & Kode Respons HTTP
200 OK— sukses GET/POST201 Created— resource baru tersimpan401 Unauthorized— token API salah atau kedaluwarsa429 Too Many Requests— rate limit; tambah interval kirim-1dari HTTPClient — gagal TLS, DNS, atau timeout
Log kode ke Serial dan, jika perlu, simpan counter error di NVS (#12) untuk diagnosa setelah deep sleep (#11).
Timeout, Reconnect & Stabilitas WiFi
http.setTimeout(20000);
http.setReuse(false); // tutup koneksi bersih tiap request
Setelah deep sleep (#11), WiFi mungkin putus — panggil connectWiFi() ulang sebelum HTTPS. Untuk node yang hanya POST sekali per bangun, satu request lalu sleep sudah cukup.
Library Include — Tidak Perlu SPI.h
Daftar include untuk artikel ini:
WiFi.h— koneksi jaringanWiFiClientSecure.h— lapisan TLSHTTPClient.h— GET/POST HTTP(S)DHT.h— sensor demo (#5)- Tidak
SPI.h/SD.h— logging offline ada di #37
Sketch Lengkap — WiFi, GET, POST DHT22
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <DHT.h>
#include <time.h>
const char* WIFI_SSID = "GANTI_NAMA_WIFI";
const char* WIFI_PASS = "GANTI_PASSWORD_WIFI";
const char* root_ca =
"-----BEGIN CERTIFICATE-----\n"
"GANTI_DENGAN_ISI_CA_PEM_ANDA\n"
"-----END CERTIFICATE-----\n";
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
WiFiClientSecure client;
const char* API_POST = "https://api.example.com/v1/sensors";
const char* API_GET = "https://api.example.com/v1/config";
void setupNtp() {
configTime(7 * 3600, 0, "pool.ntp.org", "time.nist.gov");
struct tm ti;
while (!getLocalTime(&ti)) delay(200);
}
void setup() {
Serial.begin(115200);
dht.begin();
delay(2000);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
client.setCACert(root_ca);
setupNtp();
// Demo GET
HTTPClient httpGet;
if (httpGet.begin(client, API_GET)) {
int c = httpGet.GET();
Serial.printf("GET %d\n", c);
httpGet.end();
}
// Demo POST sensor
float t = dht.readTemperature();
float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) {
HTTPClient httpPost;
if (httpPost.begin(client, API_POST)) {
httpPost.addHeader("Content-Type", "application/json");
char body[180];
snprintf(body, sizeof(body),
"{\"unix\":1782977400,\"timestamp\":\"2026-07-02T14:30:00\","
"\"temp\":%.1f,\"hum\":%.1f}", t, h);
int c = httpPost.POST(body);
Serial.printf("POST %d\n", c);
httpPost.end();
}
}
}
void loop() {
delay(60000);
}
PlatformIO — Dependency
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
adafruit/DHT sensor library@^1.4
HTTPClient dan WiFiClientSecure sudah termasuk framework Arduino ESP32 — tidak perlu lib tambahan untuk TLS dasar.
Integrasi Dashboard & Otomasi
Data yang masuk via HTTPS POST bisa diolah server yang sama dengan pipeline MQTT:
- Python (#18) — endpoint Flask/FastAPI terima POST, simpan MySQL
- Grafana (#19) — grafik histori dari DB
- Node-RED (#23) — node HTTP In sebagai alternatif MQTT In
- Home Assistant (#21) — RESTful sensor jika HA expose webhook
Keamanan & Best Practice
- Selalu
setCACertdi produksi — hindarisetInsecure() - Jangan simpan token API atau password WiFi di Git — pakai
GANTI_*placeholder - Rotasi token jika firmware pernah bocor; simpan token di NVS (#12)
- HTTPS tidak menggantikan autentikasi aplikasi — tetap butuh API key atau OAuth di header
- Perbarui root CA jika penyedia ganti CA (jarang, tapi pernah terjadi)
- Pisahkan MQTT broker (
192.168.1.50) dari API publik — attack surface berbeda
Estimasi Biaya (Indonesia)
| Komponen | Harga (Rp) |
|---|---|
| ESP32 DevKit | 35.000 – 55.000 |
| DHT22 | 35.000 – 55.000 |
| Breadboard + jumper | 15.000 – 25.000 |
| API cloud gratis tier | 0 (Firebase #30, webhook, dll.) |
| VPS HTTPS (opsional) | 50.000 – 150.000 / bulan |
| Total hardware demo | ~85.000 – 135.000 |
Checklist Sebelum Demo
- ☐ WiFi connect dengan
GANTI_NAMA_WIFI/GANTI_PASSWORD_WIFI - ☐ Root CA benar — TLS handshake sukses (bukan
-1) - ☐
setInsecure()tidak aktif di build demo - ☐ GET mengembalikan
200atau respons yang diharapkan - ☐ POST JSON berisi
unix+ suhu/kelembaban DHT22 - ☐ Token API pakai placeholder
GANTI_TOKEN_API - ☐ Serial log menampilkan kode HTTP, bukan stack trace TLS
FAQ Singkat
- Sama dengan MQTT TLS (#17)?
- Tidak — #17 mengamankan broker MQTT; artikel ini mengamankan HTTP REST ke API web.
- Perlu SPI.h?
- Tidak — tidak ada SD Card. Lihat #37 jika butuh log offline.
- setInsecure aman di rumah?
- Hanya prototyping singkat. Untuk API produksi, wajib
setCACert. - Bisa gabung MQTT + HTTPS?
- Ya — MQTT ke
192.168.1.50untuk real-time, HTTPS untuk backup cloud (#20). - Firebase sudah HTTPS?
- Ya — #30 memakai pola serupa dengan token, bukan CA custom.
Tips & Troubleshooting
- HTTP -1 / connection refused: Cek URL, DNS, firewall router, dan validitas
root_ca - Certificate verify failed: Salah CA atau server pakai intermediate — unduh ulang chain yang benar
- 401 terus: Token salah; jangan pakai password MQTT sebagai Bearer token
- Heap low: Kurangi ukuran
String; pakai bufferchar[]untuk payload - DHT NaN: Sama seperti #5 — jangan POST jika bacaan invalid
- Deep sleep gagal POST: Beri waktu cukup setelah wake untuk WiFi + TLS sebelum sleep lagi (#11)
Deep Sleep, NVS & URL API
Simpan URL endpoint dan interval POST di NVS (#12) agar bisa ganti backend tanpa re-flash. Node deep sleep (#11) bangun → WiFi → NTP (#34) → satu POST HTTPS → tidur — hemat energi dibanding maintain koneksi MQTT persisten.
Hybrid: MQTT Lokal + HTTPS Cloud
Arsitektur capstone #10 bisa diperluas: publish ke broker 192.168.1.50 untuk Home Assistant (#21), sekaligus POST HTTPS ke VPS untuk rekan yang tidak punya akses LAN. Data dari SD Card (#37) bisa di-upload lewat HTTPS saat backlog sync.
Langkah Selanjutnya — Menuju Greenhouse #39
HTTPS REST melengkapi puzzle keamanan Tier 2 setelah MQTT TLS (#17). Anda sekarang bisa:
- Mengirim sensor ke API cloud dengan TLS dan verifikasi CA
- Membedakan kapan MQTT (#7), REST (#20), atau keduanya
- Mempersiapkan backend yang menerima JSON dengan timestamp
1782977400/2026-07-02T14:30:00
Di artikel berikutnya, capstone greenhouse (#39) akan menggabungkan multi-sensor, logging SD (#37), MQTT, dan HTTPS ke satu sistem monitoring kebun lengkap — lanjutkan di halaman artikel Koding Indonesia.