1. Overview: Mengapa Firebase untuk IoT?
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
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.
ESP32 / Raspberry Pi
β
βΌ (HTTPS POST)
ββββββββββββββββββββ
β Cloud Functions β β Serverless backend
β (Node.js) β
βββββββββ¬βββββββββββ
β
βββββββ΄βββββββ
βΌ βΌ
βββββββββββ ββββββββββββββββ
βFirestoreβ β FCM Push β
βDatabase β β Notification β
ββββββ¬βββββ ββββββββββββββββ
β
βΌ (Real-time sync)
ββββββββββββββββ
β Web/Mobile β β Firebase Auth (login)
β Dashboard β β Firestore SDK (real-time)
ββββββββββββββββ
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
Langkah Register Web App: 1. Di Firebase Console β Project Settings β General 2. Scroll ke bagian "Your apps" 3. Klik ikon Web (>) untuk register web app 4. Masukkan nama app (misal: "iot-dashboard") 5. Centang "Also set up Firebase Hosting" (opsional) 6. Klik "Register app" 7. Salin konfigurasi Firebase yang muncul
Langkah 3: Inisialisasi Firebase di Project
// Import Firebase SDK (modular v9+)
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// Konfigurasi dari Firebase Console
const firebaseConfig = {
apiKey: "AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXX",
authDomain: "iot-smart-home.firebaseapp.com",
projectId: "iot-smart-home",
storageBucket: "iot-smart-home.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abcdef123456"
};
// Inisialisasi Firebase
const app = initializeApp(firebaseConfig);
// Inisialisasi layanan Authentication dan Firestore
export const auth = getAuth(app);
export const db = getFirestore(app);
export default app;
Instalasi SDK Firebase
# Instalasi Firebase SDK untuk web (via npm)
npm install firebase
# Atau gunakan CDN (untuk project tanpa bundler/Vite)
# <script type="module">
# import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js";
# import { getAuth } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-auth.js";
# import { getFirestore } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-firestore.js";
# </script>
Firebase API key tidak perlu disembunyikan β ini aman karena keamanan Firebase bergantung pada Security Rules, bukan pada API key. Namun, tetap gunakan environment variables (.env) untuk konsistensi dan kemudahan pengelolaan project.
3. Autentikasi Email & Password
Metode autentikasi paling dasar adalah email dan password. Cocok untuk proyek IoT pribadi atau tim kecil. Berikut implementasi lengkapnya:
Aktifkan Email/Password di Firebase Console
- Buka Firebase Console β Authentication β Sign-in method
- Klik "Email/Password"
- Aktifkan toggle "Enable"
- Klik "Save"
Registrasi User Baru
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "./firebase-config.js";
async function registerUser(email, password) {
try {
// Buat akun baru
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
console.log("User berhasil didaftarkan:", user.uid);
console.log("Email:", user.email);
return user;
} catch (error) {
// Handle error umum
switch (error.code) {
case "auth/email-already-in-use":
console.error("Email sudah terdaftar!");
break;
case "auth/weak-password":
console.error("Password terlalu lemah (minimal 6 karakter)");
break;
case "auth/invalid-email":
console.error("Format email tidak valid");
break;
default:
console.error("Error:", error.message);
}
throw error;
}
}
// Contoh penggunaan di form
document.getElementById("registerForm").addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("email").value;
const password = document.getElementById("password").value;
await registerUser(email, password);
});
Login User
import { signInWithEmailAndPassword, signOut, onAuthStateChanged } from "firebase/auth";
import { auth } from "./firebase-config.js";
// Login dengan email dan password
async function loginUser(email, password) {
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
console.log("Login berhasil!", userCredential.user.email);
return userCredential.user;
} catch (error) {
switch (error.code) {
case "auth/user-not-found":
console.error("User tidak ditemukan");
break;
case "auth/wrong-password":
console.error("Password salah");
break;
case "auth/too-many-requests":
console.error("Terlalu banyak percobaan login. Coba lagi nanti.");
break;
default:
console.error("Error login:", error.message);
}
throw error;
}
}
// Logout
async function logoutUser() {
await signOut(auth);
console.log("User berhasil logout");
}
// Monitor status auth (penting untuk Single Page App)
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("User login:", user.email);
// Tampilkan dashboard, sembunyikan halaman login
document.getElementById("dashboard").style.display = "block";
document.getElementById("loginPage").style.display = "none";
} else {
console.log("User belum login");
// Tampilkan halaman login, sembunyikan dashboard
document.getElementById("dashboard").style.display = "none";
document.getElementById("loginPage").style.display = "block";
}
});
Fungsi onAuthStateChanged() adalah listener yang dipanggil setiap kali status login berubah. Ini sangat penting di SPA (Single Page Application) karena menentukan halaman mana yang ditampilkan. Selalu pasang listener ini di awal inisialisasi app.
4. Social Login: Google & GitHub
Social login memudahkan user untuk masuk tanpa perlu mengingat password baru. Firebase mendukung Google, GitHub, Facebook, Twitter, dan Apple Sign-In.
Aktifkan Google Sign-In
- Buka Firebase Console β Authentication β Sign-in method
- Klik "Google"
- Aktifkan toggle, masukkan email support project
- Klik "Save"
import { signInWithPopup, GoogleAuthProvider, GithubAuthProvider } from "firebase/auth";
import { auth } from "./firebase-config.js";
// === Google Sign-In ===
async function signInWithGoogle() {
try {
const provider = new GoogleAuthProvider();
provider.addScope("email");
provider.addScope("profile");
const result = await signInWithPopup(auth, provider);
const user = result.user;
console.log("Google login berhasil!");
console.log("Nama:", user.displayName);
console.log("Email:", user.email);
console.log("Photo:", user.photoURL);
// Dapatkan Google Access Token (untuk akses Google API lain)
const credential = GoogleAuthProvider.credentialFromResult(result);
const token = credential.accessToken;
return user;
} catch (error) {
console.error("Error Google login:", error.code, error.message);
throw error;
}
}
// === GitHub Sign-In ===
async function signInWithGitHub() {
try {
const provider = new GithubAuthProvider();
provider.addScope("repo");
const result = await signInWithPopup(auth, provider);
const user = result.user;
console.log("GitHub login berhasil!");
console.log("Username:", user.displayName);
console.log("Email:", user.email);
return user;
} catch (error) {
if (error.code === "auth/account-exists-with-different-credential") {
console.error("Email sudah terdaftar dengan provider lain!");
}
throw error;
}
}
// Pasang event listener ke tombol
document.getElementById("btnGoogle").addEventListener("click", signInWithGoogle);
document.getElementById("btnGitHub").addEventListener("click", signInWithGitHub);
Social login hanya bekerja dari domain yang terdaftar di Firebase Console. Buka Authentication β Settings β Authorized domains dan tambahkan domain kamu (misal: localhost, dashboard.iotkamu.com). Tanpa ini, popup login akan error auth/unauthorized-domain.
5. Cloud Firestore Database
Cloud Firestore adalah database NoSQL berbasis dokumen yang menyimpan data dalam koleksi dan dokumen. Strukturnya mirip JSON tetapi dengan fitur query yang lebih kuat dan skalabilitas tinggi.
Aktifkan Firestore
- Buka Firebase Console β Build β Firestore Database
- Klik "Create database"
- Pilih mode: Start in test mode (untuk development) atau Production mode
- Pilih lokasi server terdekat (misal:
asia-southeast2untuk Jakarta) - Klik "Enable"
Konsep Data Firestore
Collection: "devices"
βββ Document: "device-001"
β βββ name: "Sensor Suhu Ruang Server"
β βββ type: "temperature"
β βββ location: "Lantai 2, Ruang Server"
β βββ owner_uid: "abc123"
β βββ Sub-collection: "readings"
β βββ Doc: "2026-06-25T10:00:00"
β β βββ suhu: 28.5
β β βββ kelembaban: 72.0
β βββ Doc: "2026-06-25T10:05:00"
β βββ suhu: 28.7
β βββ kelembaban: 71.5
β
βββ Document: "device-002"
β βββ name: "Sensor Kelembaban Tanah"
β βββ type: "soil_moisture"
β βββ location: "Kebun Belakang"
β
βββ Document: "device-003"
βββ name: "Relay Lampu Teras"
βββ type: "relay"
Collection = Grup dokumen (seperti "tabel")
Document = Record data (seperti "baris")
Field = Kolom data (string, number, boolean, array, map)
Sub-collection = Koleksi bersarang dalam dokumen
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:
Create β Menambah Data
import { collection, doc, setDoc, addDoc, serverTimestamp } from "firebase/firestore";
import { db, auth } from "./firebase-config.js";
// === Metode 1: addDoc() β ID dokumen otomatis ===
async function addDevice(deviceData) {
try {
const docRef = await addDoc(collection(db, "devices"), {
name: deviceData.name,
type: deviceData.type,
location: deviceData.location,
owner_uid: auth.currentUser.uid,
status: "online",
created_at: serverTimestamp(),
updated_at: serverTimestamp()
});
console.log("Device ditambahkan dengan ID:", docRef.id);
return docRef.id;
} catch (error) {
console.error("Error menambah device:", error);
throw error;
}
}
// === Metode 2: setDoc() β ID manual ===
async function addReading(deviceId, readingData) {
try {
const readingId = new Date().toISOString(); // ID berdasarkan timestamp
const readingRef = doc(db, "devices", deviceId, "readings", readingId);
await setDoc(readingRef, {
suhu: readingData.suhu,
kelembaban: readingData.kelembaban,
timestamp: serverTimestamp()
});
console.log("Data sensor ditambahkan:", readingId);
} catch (error) {
console.error("Error menambah data:", error);
throw error;
}
}
// Contoh penggunaan
await addDevice({
name: "Sensor Suhu Gudang",
type: "temperature",
location: "Gudang Utama"
});
await addReading("device-001", {
suhu: 28.5,
kelembaban: 72.0
});
Read β Membaca Data
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
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.
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!
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
# 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.
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();
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: