Bayangkan ada dua kurir yang mengantar pesan dari ESP32 ke server: kurir HTTP dan kurir MQTT. Keduanya membawa isi pesan yang sama, lalu server menyimpan hasil kiriman, menghitung kualitas pengiriman, dan menampilkan perbandingan keduanya di dashboard.
Secara teknis, firmware di ESP32_Firmware/src/main.cpp mengirim payload periodik ke POST /api/http-data (HTTP) dan ke broker topic iot/esp32/suhu (MQTT). Jalur HTTP diproses ApiController::storeHttp, jalur MQTT diproses worker mqtt_worker.php, lalu keduanya tersimpan idempotent ke tabel eksperimens.
1. ESP32
Membaca sensor lalu menyiapkan paket data.
2. HTTP + MQTT
Paket dikirim lewat dua jalur berbeda.
3. Database
Server menyimpan hasil kiriman dan menghitung metrik.
4. Dashboard
Hasil perbandingan tampil realtime untuk analisis.
Bagaimana Data Mengalir di Sistem Ini
Bahasa sederhana: data bergerak dari alat (ESP32), masuk ke server, disimpan di database, dihitung statistiknya, lalu ditampilkan di dashboard.
Versi teknis: sendHTTP() dan sendMQTT() di firmware mengirim payload; HTTP diterima ApiController::storeHttp, MQTT diterima callback di mqtt_worker.php; data masuk Eksperimen::updateOrCreate; dashboard memanggil StatisticsService dari DashboardController::index.
Untuk pembaca awam: halaman ini menjelaskan siapa mengirim data, ke mana data pergi, apa yang dihitung, dan bagaimana hasilnya dibaca di dashboard.
Untuk pembaca teknis: sistem membandingkan telemetry MQTT vs HTTP dari ESP32, menyimpan keduanya ke MySQL, lalu mengeksekusi statistik komparatif (summary, reliability, t-test) sebelum render chart dan panel analisis.
Firmware (ESP32)
File: ESP32_Firmware/src/main.cpp. Mengirim HTTP dan MQTT secara periodik (default keduanya 10 detik) dengan field telemetry lengkap dan packet sequence.
HTTP Ingress
Rute POST /api/http-data -> ApiController::storeHttp, memakai middleware throttle:http-data dan ingest.key.
MQTT Ingress
Tidak ditangani controller Laravel. MQTT incoming diproses worker mandiri mqtt_worker.php lalu di-upsert ke eksperimens.
Dashboard
Rute GET / -> DashboardController::index, statistik dihitung oleh StatisticsService, frontend di resources/views/dashboard.blade.php.
Arsitektur Aktual (Berbasis Kode)
Versi awam: ada dua jalur pengiriman dari ESP32, lalu kedua jalur bertemu di database untuk dianalisis bersama.
Versi teknis: diagram berikut mengikuti jalur runtime yang benar-benar ada di repository ini tanpa asumsi tambahan di luar kode.
Diagram SVG inline ini mengikuti jalur kode aktual: perhitungan latency terjadi di ingest backend (HTTP controller + MQTT worker), sedangkan T-Test terjadi di StatisticsService sebelum dashboard dirender.
Timeline Visual: HTTP Request/Response vs MQTT Publish/Subscribe
Versi awam: kedua protokol berangkat dari titik waktu sensor yang sama, tetapi pola perjalanannya berbeda. HTTP menunggu balasan request, sedangkan MQTT publish lalu diproses subscriber worker.
Versi teknis: timeline ini memetakan timestamp_esp, fase transmit, momen server menerima data, dan langkah latency_ms dihitung pada backend ingest. Jalur HTTP terkait sendHTTP() + ApiController::storeHttp; jalur MQTT terkait sendMQTT() + mqtt_worker.php.
Peta Route Laravel (Aktual)
Method
Path
Handler
Tujuan
GET
/
DashboardController@index
Dashboard utama
POST
/api/http-data
ApiController@storeHttp
HTTP ingest dari ESP32
GET
/simulation
SimulationController@index
UI simulasi
POST
/simulation/start|stop|tick|reset
SimulationController
Kontrol simulasi
GET/POST
/reset-data
DashboardController
Reset telemetry real
GET
/admin/login
AdminConfigController@loginForm
Login admin
GET/POST/PATCH/DELETE
/admin/config/*
AdminConfigController
Provisioning runtime + firmware
GET
/doc
view('doc')
Halaman dokumentasi teknis ini
Controller HTTP dan Worker MQTT
Versi awam: pintu HTTP dijaga oleh Laravel, sedangkan pintu MQTT dijaga oleh worker khusus. Keduanya mengecek data sebelum menyimpan.
Versi teknis: route API menggunakan middleware throttle:http-data + ingest.key. MQTT berjalan sebagai proses subscriber tersendiri dengan validasi manual, lalu keduanya melakukan upsert idempotent ke tabel yang sama.
HTTP path (ApiController::storeHttp)
Memvalidasi semua field telemetry wajib beserta batas nilainya.
Menghitung latency_ms dari waktu server UTC dikurangi timestamp_esp.
Juga subscribe debug topic iot/esp32/debug dan update storage/app/esp32_debug_heartbeat.json.
Catatan penting: repository ini tidak memiliki controller Laravel khusus MQTT ingest. Ingestion MQTT ditangani proses mandiri mqtt_worker.php.
Struktur JSON Payload yang Dipakai Runtime
Versi awam: payload adalah "isi paket" yang dibawa dari ESP32 ke server. Di dalamnya ada data utama sensor dan data tambahan untuk diagnosis kualitas jaringan.
Versi teknis: builder payload firmware (fillProtocolPayload()) selalu mengirim field telemetry wajib ditambah field diagnostik seperti RSSI, TX duration, payload bytes, dan counter keberhasilan/kegagalan kirim.
Bagian ini sengaja ditulis dua lapis: paragraf pertama untuk pemahaman awam, paragraf kedua untuk akurasi teknis sesuai kode.
Latency
Versi awam: latency adalah lama waktu dari data dikirim oleh alat sampai diterima server. Semakin kecil, data terasa semakin cepat sampai.
Versi teknis: baik HTTP maupun MQTT menghitung latency_ms = abs(server_utc - timestamp_esp) menggunakan Carbon::floatDiffInMilliseconds() di ApiController dan mqtt_worker.php, lalu disimpan ke eksperimens.latency_ms.
Konsumsi Daya
Versi awam: sistem memperkirakan "biaya energi" setiap kali ESP32 mengirim data. Ini bukan alat ukur listrik langsung, tetapi estimasi berbasis kondisi kirim.
Versi teknis: firmware menghitung powerMw = voltage * totalCurrentMa di estimateProtocolPower() dengan komponen RSSI, ukuran payload, durasi kirim, overhead protokol, fail ratio, suhu, dan kelembapan. Nilai dikirim sebagai field daya lalu disimpan backend ke daya_mw.
Reliability / Packet Delivery Ratio
Versi awam: reliability menunjukkan seberapa konsisten data sampai tanpa hilang. Jika banyak nomor paket yang "loncat", skor reliability turun.
Versi teknis: backend menghitung sequence reliability dari packet_seq per device (received / expected * 100) dengan aturan segmentasi reboot/jump. Skor akhir adalah gabungan sequence, field completeness, dan transmission health via combineReliability().
Independent Sample T-Test
Versi awam: T-Test membantu menjawab apakah perbedaan MQTT dan HTTP itu kemungkinan "benar berbeda", bukan hanya kebetulan data sesaat.
Versi teknis: StatisticsService::tTest() menghitung pooled variance, standard error, dan t_value untuk latency_ms dan daya_mw. Signifikansi ditetapkan dengan batas tetap |t| > 1.96, sementara p_value ditampilkan sebagai nilai aproksimasi.
Mekanisme Perhitungan Latency
Controller HTTP dan worker MQTT menggunakan formula latency yang sama.
HTTP dan MQTT memakai protocol overhead yang berbeda (HTTP lebih tinggi).
Penalty naik saat rasio gagal meningkat (httpSendFail/mqttSendFail).
Durasi transmisi, ukuran payload, RSSI, dan delta lingkungan memengaruhi estimasi.
Formula bersifat deterministik (jalur firmware saat ini tidak memakai baseline acak).
Packet Delivery Ratio (Reliability Backend)
Backend tidak menyimpan field terpisah bernama PDR, namun sequence reliability dihitung sebagai received / expected * 100 dan dipakai di skor reliability total.
Syarat minimum: tiap grup minimal memiliki 2 baris.
Edge case standardError == 0 ditangani eksplisit (grup konstan).
p_value memakai fungsi aproksimasi (normal CDF untuk df besar, bin kasar untuk df kecil).
Dashboard menampilkan panel T-test terpisah untuk latency dan power.
Contoh Nyata dari Satu Siklus Data
Tujuan bagian ini adalah membuat angka-angka penelitian lebih mudah dibayangkan. Angka contoh di bawah menggunakan pola rumus yang sama dengan kode runtime.
Contoh 1: Satu siklus kirim data
Versi awam: ESP32 membaca sensor, lalu mengirim paket ke HTTP dan MQTT hampir berdekatan, kemudian server menyimpan keduanya.
Versi teknis: firmware membuat payload lewat fillProtocolPayload() (termasuk packet_seq, timestamp_esp, daya, sensor_read_seq), lalu backend melakukan updateOrCreate berdasarkan kunci unik paket.
Contoh 2: Perhitungan latency
timestamp_esp = 1772021517 (UTC second)
timestamp_server= 1772021518.320 (UTC with millisecond)
latency_ms = abs(1772021518.320 - 1772021517) * 1000
= 1320 ms
Versi awam: data sampai sekitar 1,32 detik setelah waktu cap di alat.
Versi teknis: ini persis pola di Carbon::floatDiffInMilliseconds() dengan abs() di jalur HTTP dan MQTT worker.
Versi awam: semakin jelek sinyal, semakin lama kirim, dan semakin besar paket, maka daya estimasi cenderung naik.
Versi teknis: komponen angka di atas mengikuti komponen real di fungsi estimateProtocolPower() firmware.
Contoh 4: Membaca p-value dan signifikansi
Versi awam: jika hasil menunjukkan perbedaan signifikan, artinya dua jalur komunikasi punya performa yang memang berbeda secara statistik.
Versi teknis: di kode saat ini keputusan signifikan ditentukan oleh |t_value| > 1.96. Nilai p_value ditampilkan sebagai aproksimasi pendukung interpretasi (bukan perhitungan exact Student-t untuk semua df).
Kenapa Sistem Ini Dibuat Seperti Ini?
Alasan membandingkan MQTT dan HTTP
Versi awam: penelitian butuh pembanding yang adil. Karena itu data yang mirip dikirim lewat dua jalur berbeda agar bisa dilihat mana yang lebih cepat dan lebih stabil.
Versi teknis: firmware mengirim field yang sama ke HTTP dan MQTT, backend menyimpan pada tabel dan skema yang sama (dibedakan kolom protokol) sehingga analisis statistik antar-protokol bisa langsung dibandingkan.
Alasan worker MQTT dipisah
Versi awam: jalur MQTT bersifat "menunggu pesan terus-menerus", jadi lebih cocok ditangani proses khusus yang selalu hidup.
Versi teknis: repository ini memang tidak memiliki controller ingest MQTT di Laravel; ingest MQTT dijalankan oleh proses mandiri mqtt_worker.php dengan reconnect loop, fallback host, dan lock file untuk mencegah worker ganda.
Alasan memakai T-Test
Versi awam: rata-rata saja belum cukup. T-Test dipakai untuk mengecek apakah selisih dua protokol cukup kuat secara statistik.
Versi teknis: StatisticsService menghitung independent sample t-test untuk latency dan daya, lalu dashboard menampilkan parameter utama (N, mean, variance, std dev, t-value, p-value, interpretasi).
Struktur Database dan Relasi Tabel
devices (id PK)
|-< eksperimens.device_id FK (1:N)
|-< simulated_eksperimens.device_id FK (1:N)
'- 1:1 device_firmware_profiles.device_id FK (unique)
app_settings (standalone key-value runtime overrides)
Tabel telemetry (eksperimens)
Kolom inti: device_id, protokol, suhu, kelembapan, timestamp_esp, timestamp_server, latency_ms, daya_mw, plus kolom diagnostik lainnya.
Unique key untuk idempotent ingestion: (device_id, protokol, packet_seq).
Tabel telemetry simulasi
simulated_eksperimens mencerminkan bentuk telemetry yang sama dengan unique key yang sama, namun dipisah dari tabel telemetry real.
Contoh query (troubleshooting runtime)
-- Latest real rows by protocol
SELECT id, device_id, protokol, packet_seq, latency_ms, daya_mw, timestamp_server
FROM eksperimens
WHERE protokol IN ('MQTT', 'HTTP')
ORDER BY COALESCE(timestamp_server, created_at) DESC
LIMIT 20;
-- Required field completeness audit for MQTT scope
SELECT
COUNT(*) AS total_rows,
SUM(CASE WHEN suhu IS NULL THEN 1 ELSE 0 END) AS missing_suhu,
SUM(CASE WHEN kelembapan IS NULL THEN 1 ELSE 0 END) AS missing_kelembapan,
SUM(CASE WHEN packet_seq IS NULL THEN 1 ELSE 0 END) AS missing_packet_seq
FROM eksperimens
WHERE UPPER(protokol) = 'MQTT';
Alur: Data Masuk sampai Render Dashboard
Versi awam: setelah data disimpan di database, sistem mengolahnya menjadi angka ringkas agar pengguna bisa langsung melihat siapa yang lebih cepat, lebih hemat daya, dan lebih stabil.
Versi teknis: DashboardController::index mengambil data protocol dari model telemetry, memanggil StatisticsService untuk summary/reliability/t-test, menyusun payload chart, lalu mengirim semua hasil ke resources/views/dashboard.blade.php.
ESP32 mengirim payload HTTP dan MQTT dengan field telemetry lengkap.
Jalur HTTP masuk ke ApiController; jalur MQTT masuk ke mqtt_worker.php.
Kedua jalur menghitung latency dan melakukan idempotent upsert ke eksperimens.
DashboardController@index mengambil sampel MQTT dan HTTP (window analisis: 50, window chart: tidak terbatas).
StatisticsService menghitung summary stats, reliability, dan T-test.
Data quality warnings dan panel field completeness.
Protocol payload diagnostics (row MQTT/HTTP terbaru + nilai delta).
Chart komparatif: latency dan power.
Hasil independent sample T-test untuk latency dan power.
Widget floating realtime link monitor (ping/throughput).
Validasi pada Ingest dan Statistik Backend
Validasi ingest
device_id harus ada di tabel devices.
kelembapan dibatasi pada rentang 0..100.
timestamp_esp dibatasi pada rentang epoch 1000000000..4102444800.
packet_seq harus >= 1.
rssi_dbm dibatasi pada rentang -120..0.
Jalur HTTP memakai validator Laravel; jalur MQTT memakai pengecekan manual di worker.
Aturan validasi statistik
T-test mensyaratkan minimal 2 baris data per protokol.
Menolak kasus df=0 dan standard error denominator=0.
Scope reliability memprioritaskan baris dengan packet_seq non-null saat tersedia.
Kelengkapan field wajib mengecek 15 field telemetry yang konsisten untuk MQTT dan HTTP.
Batasan Sistem (Berdasarkan Kode Saat Ini)
p_value pada T-test memakai aproksimasi, terutama kasar untuk df kecil.
Critical value di kode bersifat tetap (+/-1.96), tidak menyesuaikan df secara dinamis.
daya_mw adalah estimasi sisi firmware, bukan pembacaan sensor listrik langsung.
Latency bergantung pada validitas jam ESP32; drift NTP atau epoch tidak sinkron akan menurunkan kualitas metrik.
Sequence reliability memakai aturan segmentasi (reboot/jump handling), sehingga lompatan sangat besar diperlakukan sebagai segmen baru, bukan loss kontinu.
Ingestion MQTT bergantung pada proses worker mandiri; jika worker down, telemetry MQTT tidak tersimpan.
Dokumentasi ini implementation-bound; update halaman ini saat schema telemetry, formula, atau runtime path berubah.
Glossary / Daftar Istilah
Setiap istilah ditulis dua lapis: penjelasan sederhana untuk pembaca umum, lalu penjelasan teknis sesuai implementasi kode di repository ini.
idempotent upsert
Sederhana: mengirim data yang sama berulang kali tidak membuat data dobel.
Teknis: HTTP dan MQTT memakai updateOrCreate dengan identitas (device_id, protokol, packet_seq), diperkuat unique index database dengan kombinasi key yang sama.
packet_seq
Sederhana: nomor urut paket agar sistem tahu ada paket yang hilang atau berulang.
Teknis: firmware menaikkan httpPacketSeq dan mqttPacketSeq saat kirim; backend memakai nilai ini untuk dedup idempotent dan menghitung sequence reliability.
window analysis
Sederhana: sistem hanya mengambil data terbaru dalam jumlah tertentu agar analisis tetap ringan dan relevan.
Teknis: DASHBOARD_ANALYSIS_WINDOW (default 50) dipakai StatisticsService::getProtocolData(); chart memakai DASHBOARD_CHART_WINDOW (default 0 (unlimited)).
latency_ms
Sederhana: waktu tempuh data dari ESP32 sampai server, dalam milidetik.
Teknis: dihitung sebagai abs(server_utc - timestamp_esp) di ApiController::storeHttp dan mqtt_worker.php, lalu disimpan ke kolom latency_ms.
daya_mw
Sederhana: perkiraan konsumsi daya saat pengiriman data.
Teknis: firmware menghitung daya lewat estimateProtocolPower() lalu backend menyimpannya ke kolom daya_mw. Ini estimasi model, bukan pembacaan sensor listrik langsung.
Independent Sample T-Test
Sederhana: uji statistik untuk mengecek apakah perbedaan dua kelompok data cukup kuat secara ilmiah.
Teknis: fungsi StatisticsService::tTest() menghitung pooled variance, standard error, dan t_value untuk data MQTT vs HTTP pada metrik latency_ms dan daya_mw.
p-value
Sederhana: angka yang membantu menilai apakah perbedaan bisa dianggap kebetulan atau tidak.
Teknis: di project ini p_value berasal dari fungsi aproksimasi calculatePValue() (normal CDF untuk df besar, bin kasar untuk df kecil), sehingga bersifat indikatif.
publish/subscribe
Sederhana: pengirim menaruh pesan ke topik, penerima yang berlangganan topik itu akan memprosesnya.
Teknis: firmware sendMQTT() melakukan publish ke topic konfigurasi, lalu mqtt_worker.php melakukan subscribe dan menyimpan payload ke database.
request/response
Sederhana: pengirim meminta server memproses data, lalu server membalas status hasilnya.
Teknis: firmware sendHTTP() mengirim request ke /api/http-data, ApiController::storeHttp memproses/validasi/upsert, kemudian mengembalikan response JSON dengan status kode HTTP.