Tutorial komprehensif menggunakan Firebase Authentication dan Cloud Firestore untuk membangun backend aplikasi IoT — dari autentikasi user, database real-time, hingga security rules
Firebase adalah platform Backend-as-a-Service (BaaS) dari Google yang menyediakan berbagai layanan cloud tanpa perlu mengelola server sendiri. Untuk proyek IoT, Firebase sangat menarik karena menyediakan autentikasi user, database real-time, dan hosting dalam satu platform terintegrasi.
Bayangkan kamu punya proyek Smart Home — kamu tidak perlu membuat server API dari nol, mengelola database, atau membangun sistem login. Firebase menyediakan semuanya tinggal pakai.
Layanan Firebase yang Relevan untuk IoT
Layanan
Fungsi
Contoh Penggunaan IoT
Authentication
Manajemen user & login
Login ke dashboard monitoring IoT
Cloud Firestore
NoSQL database real-time
Menyimpan data sensor, konfigurasi device
Realtime Database
Database JSON real-time
Status device, kontrol relay real-time
Cloud Functions
Serverless functions
Proses data sensor, kirim notifikasi
Cloud Messaging (FCM)
Push notifications
Alert suhu tinggi ke HP user
Hosting
Web hosting statis
Deploy dashboard web IoT
Firestore vs Realtime Database
Firebase menyediakan dua database. Untuk kebanyakan proyek IoT modern, Cloud Firestore lebih direkomendasikan karena:
Struktur data lebih baik — Koleksi dan dokumen, bukan JSON tree besar
Query lebih kuat — Filter, sorting, dan pagination yang fleksibel
Scalability lebih baik — Sharding otomatis untuk data besar
Offline support — Sinkronisasi offline otomatis untuk mobile app
Composite index — Query dengan multiple filter dan sorting
💡 Contoh Use Case IoT
Smart Greenhouse: ESP32 mengirim data suhu dan kelembaban ke Cloud Functions via HTTP. Data disimpan di Firestore. User login ke dashboard web menggunakan Firebase Auth (Google Sign-In) dan melihat grafik real-time dari Firestore. Saat suhu melebihi threshold, Cloud Function mengirim push notification ke HP via FCM.
Diagram: Arsitektur Firebase untuk IoT
Arsitektur Firebase untuk IoT
2. Setup Firebase Authentication
Firebase Authentication menyediakan sistem login yang aman tanpa perlu membuat backend autentikasi dari nol. Mendukung email/password, Google, GitHub, Facebook, dan metode login lainnya.
Langkah 1: Buat Project Firebase
Buka https://console.firebase.google.com
Klik "Add project"
Masukkan nama project (misal: "iot-smart-home")
Aktifkan/nonaktifkan Google Analytics sesuai kebutuhan
Klik "Create project"
Langkah 2: Register Web App
Perbedaan utama dengan database relasional:
Aspek
SQL (MySQL)
Firestore (NoSQL)
Struktur
Tabel dengan baris dan kolom
Koleksi dengan dokumen
Schema
Tetap, harus didefinisikan
Fleksibel, bisa berbeda per dokumen
Relasi
JOIN antar tabel
Sub-collection atau referensi
Query
SQL
SDK dengan filter, sort, limit
Skalabilitas
Vertikal (tambah resource)
Horizontal (otomatis)
Real-time
Polling / external
Built-in real-time listener
6. CRUD Operations di Firestore
CRUD (Create, Read, Update, Delete) adalah operasi dasar database. Berikut implementasi lengkap dengan Cloud Firestore:
import { collection, doc, getDoc, getDocs, query, where, orderBy, limit } from "firebase/firestore";
import { db } from "./firebase-config.js";
// === Baca satu dokumen berdasarkan ID ===
async function getDevice(deviceId) {
const docRef = doc(db, "devices", deviceId);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("Data device:", docSnap.data());
return { id: docSnap.id, ...docSnap.data() };
} else {
console.log("Device tidak ditemukan!");
return null;
}
}
// === Baca semua device milik user yang sedang login ===
async function getUserDevices() {
const q = query(
collection(db, "devices"),
where("owner_uid", "==", auth.currentUser.uid),
orderBy("created_at", "desc"),
limit(50)
);
const querySnapshot = await getDocs(q);
const devices = [];
querySnapshot.forEach((doc) => {
devices.push({ id: doc.id, ...doc.data() });
});
console.log(`Ditemukan ${devices.length} device`);
return devices;
}
// === Baca data sensor dengan filter ===
async function getHighTempReadings(deviceId, minTemp) {
const q = query(
collection(db, "devices", deviceId, "readings"),
where("suhu", ">", minTemp),
orderBy("suhu", "desc"),
limit(10)
);
const snapshot = await getDocs(q);
return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
}
Update & Delete
JavaScript — Update & Delete Data
import { doc, updateDoc, deleteDoc, serverTimestamp } from "firebase/firestore";
import { db } from "./firebase-config.js";
// === Update data device ===
async function updateDevice(deviceId, newData) {
const deviceRef = doc(db, "devices", deviceId);
await updateDoc(deviceRef, {
...newData,
updated_at: serverTimestamp()
});
console.log("Device berhasil diupdate");
}
// Contoh: update status dan lokasi device
await updateDevice("device-001", {
status: "offline",
location: "Lantai 3, Ruang Lab"
});
// === Hapus device (termasuk sub-collection) ===
async function deleteDevice(deviceId) {
// PERINGATAN: Sub-collection tidak otomatis terhapus!
// Hapus sub-collection "readings" terlebih dahulu
const readings = await getDocs(collection(db, "devices", deviceId, "readings"));
const deletePromises = readings.docs.map(d => deleteDoc(d.ref));
await Promise.all(deletePromises);
// Hapus dokumen device
await deleteDoc(doc(db, "devices", deviceId));
console.log("Device dan semua data sensornya berhasil dihapus");
}
// === Batch write: operasi sekaligus ===
import { writeBatch } from "firebase/firestore";
async function batchUpdateStatus(deviceIds, status) {
const batch = writeBatch(db);
deviceIds.forEach(id => {
const deviceRef = doc(db, "devices", id);
batch.update(deviceRef, { status, updated_at: serverTimestamp() });
});
await batch.commit(); // Commit semua sekaligus
console.log(`${deviceIds.length} device diupdate sekaligus`);
}
7. Firestore Security Rules
Security Rules menentukan siapa yang boleh membaca, menulis, atau menghapus data. Tanpa rules yang benar, siapa saja bisa mengakses data sensor IoT kamu. Ini adalah lapisan keamanan paling penting di Firebase.
⚠️ Security Rules Bukan Opsional!
API key Firebase bersifat publik — siapa saja yang melihat source code web kamu bisa mengetahui API key-nya. Security Rules adalah satu-satunya pertahanan untuk melindungi data kamu. Jangan pernah menggunakan "test mode" di produksi!
Firestore — firestore.rules
rules_version = "2";
service cloud.firestore {
match /databases/{database}/documents {
// Helper function: cek apakah user sudah login
function isAuth() {
return request.auth != null;
}
// Helper function: cek apakah user adalah pemilik dokumen
function isOwner(userId) {
return request.auth.uid == userId;
}
// === Collection: devices ===
match /devices/{deviceId} {
// Baca: hanya pemilik device yang bisa melihat
allow read: if isAuth() && isOwner(resource.data.owner_uid);
// Buat: user yang login, owner_uid harus miliknya, wajib ada field tertentu
allow create: if isAuth()
&& request.resource.data.owner_uid == request.auth.uid
&& request.resource.data.keys().hasAll(["name", "type", "owner_uid"])
&& request.resource.data.name is string
&& request.resource.data.name.size() > 0;
// Update: hanya pemilik, owner_uid tidak bisa diubah
allow update: if isAuth()
&& isOwner(resource.data.owner_uid)
&& request.resource.data.owner_uid == resource.data.owner_uid;
// Hapus: hanya pemilik
allow delete: if isAuth() && isOwner(resource.data.owner_uid);
// Sub-collection: readings (data sensor)
match /readings/{readingId} {
// Baca: hanya pemilik parent device
allow read: if isAuth() && isOwner(
get(/databases/$(database)/documents/devices/$(deviceId)).data.owner_uid
);
// Tulis data baru: hanya pemilik, validasi tipe data
allow create: if isAuth()
&& isOwner(get(/databases/$(database)/documents/devices/$(deviceId)).data.owner_uid)
&& request.resource.data.suhu is number
&& request.resource.data.kelembaban is number;
// Data sensor TIDAK BOLEH diubah atau dihapus (integritas data)
allow update, delete: if false;
}
}
}
}
Testing Security Rules
Terminal — Test Security Rules
# Instalasi Firebase CLI
npm install -g firebase-tools
# Login ke Firebase
firebase login
# Jalankan emulator untuk test security rules secara lokal
firebase emulators:start --only firestore
# Deploy security rules ke production
firebase deploy --only firestore:rules
8. Real-Time Listeners
Fitur terbaik Firestore untuk IoT adalah real-time listener. Data yang berubah di database akan otomatis ter-update di semua client yang mendengarkan. Tidak perlu polling — Firestore melakukan push update ke client.
JavaScript — Real-Time Listener
import { collection, doc, onSnapshot, query, where, orderBy, limit } from "firebase/firestore";
import { db } from "./firebase-config.js";
// === Listener untuk satu dokumen (real-time) ===
function watchDevice(deviceId) {
const deviceRef = doc(db, "devices", deviceId);
const unsubscribe = onSnapshot(deviceRef, (docSnap) => {
if (docSnap.exists()) {
const data = docSnap.data();
console.log("Status device berubah:", data.status);
// Update UI secara real-time
document.getElementById("deviceName").textContent = data.name;
document.getElementById("deviceStatus").textContent = data.status;
document.getElementById("deviceStatus").className =
data.status === "online" ? "badge-success" : "badge-danger";
}
}, (error) => {
console.error("Error listening device:", error);
});
// Kembalikan fungsi unsubscribe untuk berhenti mendengarkan
return unsubscribe;
}
// === Listener untuk data sensor terbaru ===
function watchLatestReadings(deviceId) {
const q = query(
collection(db, "devices", deviceId, "readings"),
orderBy("timestamp", "desc"),
limit(10)
);
const unsubscribe = onSnapshot(q, (snapshot) => {
const readings = [];
snapshot.forEach((doc) => {
readings.push({ id: doc.id, ...doc.data() });
});
console.log(`Data sensor terbaru (${readings.length} records):`, readings);
// Update grafik di dashboard
updateChart(readings);
// Update gauge suhu
if (readings.length > 0) {
const latestSuhu = readings[0].suhu;
document.getElementById("gaugeSuhu").textContent = latestSuhu + "°C";
// Alert jika suhu kritis
if (latestSuhu > 35) {
showAlert("Suhu kritis! " + latestSuhu + "°C");
}
}
});
return unsubscribe;
}
// === Menggunakan listener ===
const unsubDevice = watchDevice("device-001");
const unsubReadings = watchLatestReadings("device-001");
// Berhenti mendengarkan saat tidak diperlukan (hemat kuota)
// unsubDevice();
// unsubReadings();
💡 Hemat Kuota Firestore
Firestore menghitung setiap dokumen yang dibaca sebagai 1 read operation (termasuk dari listener). Jika listener mendengarkan 100 dokumen dan masing-masing berubah 1x, itu = 200 read operations. Gunakan limit() dan where() untuk membatasi data yang didengarkan. Unsubscribe listener saat halaman tidak aktif.
9. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Firebase Auth dan Firestore:
Pertanyaan 1: Mengapa Firebase API key TAK PERLU disembunyikan di source code?
a) Karena API key sudah dienkripsi oleh Firebase
b) Karena keamanan Firebase bergantung pada Security Rules, bukan API key
c) Karena Firebase memblokir akses dari IP yang tidak dikenal
d) Karena API key otomatis berubah setiap hari
Pertanyaan 2: Apa perbedaan antara addDoc() dan setDoc() di Firestore?
a) addDoc() untuk update, setDoc() untuk create
b) addDoc() membuat ID otomatis, setDoc() menggunakan ID manual
c) addDoc() untuk collection, setDoc() untuk field
d) Tidak ada perbedaan, keduanya sama
Pertanyaan 3: Fungsi apa yang digunakan untuk memantau perubahan data secara real-time di Firestore?
a) getDoc()
b) watchDoc()
c) onSnapshot()
d) subscribe()
Pertanyaan 4: Dalam Security Rules, request.auth.uid merujuk ke apa?
a) UID dari Firebase project
b) UID dari user yang sedang melakukan request (sudah login)
c) UID dari device IoT yang sedang mengirim data
d) UID dari dokumen Firestore
Pertanyaan 5: Mengapa onSnapshot() perlu di-unsubscribe saat halaman tidak aktif?
a) Untuk menghemat kuota baca Firestore
b) Untuk menghindari error di browser
c) Untuk menghapus data dari cache
d) Tidak perlu di-unsubscribe, Firebase menanganinya otomatis