Pendahuluan — Sensor Tanpa Router di Tengah

Sejauh ini, hampir semua artikel Seri 2 mengasumsikan router WiFi ada: ESP32 connect ke AP, lalu HTTP (#6), MQTT (#7), atau broker (#16).

Di lapangan, tidak selalu demikian. Greenhouse besar, gudang, atau kebun punya node sensor di ujung yang jauh dari router — sinyal WiFi lemah, tapi jarak antar board ESP32 dekat. Di sinilah ESP-NOW masuk: protokol peer-to-peer Espressif untuk kirim paket kecil antar ESP32 tanpa router.

Artikel Jalur D ini membahas pola paling umum: sensor node (ESP-NOW only) → gateway node (ESP-NOW + WiFi + MQTT) → broker → Grafana (#19). Ini pola sensor + gateway klasik untuk IoT lapangan.

Prasyarat: Paham koneksi WiFi ESP32 (#4), DHT22 (#5), dan dasar MQTT (#7). Disarankan baca REST vs MQTT (#20) untuk konteks kapan butuh infrastruktur penuh.

Apa Itu ESP-NOW?

ESP-NOW adalah protokol wireless proprietary Espressif, built-in di chip ESP32/ESP8266. Karakteristik utama:

  • Tanpa router — komunikasi langsung antar MAC address
  • Payload kecil — maksimal ~250 byte per paket
  • Latency rendah — cocok untuk trigger, remote control, telemetry ringan
  • Channel WiFi — kedua board harus di channel yang sama (1–13), meski tidak connect ke AP
  • Enkripsi opsional — PMK/LMK untuk peer terenkripsi

ESP-NOW vs WiFi/MQTT vs LoRa

ProtokolJangkauInfrastrukturCocok untuk
ESP-NOW~200 m LOS (tergantung antena)2+ ESP32, tanpa routerSensor lokal → gateway dekat
WiFi + MQTT (#7)Seluruh jaringan APRouter + broker (#16)Dashboard, multi-subscriber
REST (#6)LAN APRouterDebug cepat, satu klien
LoRa (#26)Kilometer2× ESP32 + modul SX1278Sensor sangat jauh, data jarang

ESP-NOW bukan pengganti MQTT — ia mengisi celah antara node sensor dan gateway yang punya WiFi. Lihat juga perbandingan di #20.

Yang Kamu Butuhkan

  • 2× ESP32 (DevKit v1 atau serupa) — satu sensor, satu gateway
  • DHT22 di node sensor (opsional BME280 dari #13)
  • Router WiFi hanya di gateway — untuk forward ke MQTT
  • Kabel USB ×2 untuk flash & baca MAC address

Estimasi biaya: ~Rp 80–120rb per ESP32 + sensor — total ~Rp 200–250rb untuk lab dua node.

Arsitektur Sensor + Gateway

KomponenPeranKoneksi
ESP32 Sensor + DHT22Baca suhu & kelembaban, kirim paket kecilESP-NOW saja — tanpa router WiFi
ESP32 GatewayTerima paket ESP-NOW, publish ke MQTTESP-NOW + WiFi STA ke router
Mosquitto (#16)Broker pusatTopic kodingindonesia/esp32/dht22/data
Grafana (#19)Dashboard histori (opsional)Subscribe / Telegraf dari broker

Alur data secara singkat:

  [ ESP32 Sensor — DHT22 ]
      |
      |  ESP-NOW (peer-to-peer, tanpa router)
      |  struct: suhu, kelembaban, unix
      |  deep sleep (#11) — hemat baterai
      v
  [ ESP32 Gateway ]
      |
      |  WiFi STA → router rumah/kantor
      |  MQTT publish :1883
      |  topic: kodingindonesia/esp32/dht22/data
      v
  [ Mosquitto @ 192.168.1.50 ]  (#16)
      |
      +-- mosquitto_sub / subscriber Python (#18)
      +-- Grafana dashboard (#19)

Sensor node hemat daya: bangun → baca sensor → kirim ESP-NOW → tidur (deep sleep #11). Gateway selalu hidup, terima paket, publish MQTT dengan timestamp NTP (#34).

MAC Address & Pairing

Setiap ESP32 punya MAC address WiFi STA unik. Wajib dicatat sebelum pairing:

#include <WiFi.h>

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  Serial.print("MAC STA: ");
  Serial.println(WiFi.macAddress());
}

Flash sketch di atas ke kedua board — catat MAC gateway, misalnya 24:6F:28:AA:BB:02, dan MAC sensor 24:6F:28:AA:BB:01. Ganti placeholder di sketch berikut dengan nilai nyata dari Serial Monitor.

Pro tip: Tempel label fisik di tiap board (SENSOR / GATEWAY + MAC) agar tidak tertukar saat debug.

Struktur Data Bersama

Pakai struct yang sama di sender dan receiver — maksimal 250 byte:

typedef struct __attribute__((packed)) {
  float suhu;
  float kelembaban;
  uint32_t unix;  // opsional dari RTC/NTP di sensor; gateway bisa isi ulang
} sensor_packet_t;

Contoh nilai setelah gateway publish MQTT (konsisten Seri 2):

{"suhu":28.5,"kelembaban":65.2,"timestamp":"2026-07-02T14:30:00","unix":1782977400}

Sketch Sensor — ESP-NOW Sender

#include <esp_now.h>
#include <WiFi.h>
#include <DHT.h>

#define DHT_PIN 4
#define GATEWAY_MAC {0x24, 0x6F, 0x28, 0xAA, 0xBB, 0x02}  // GANTI_MAC_GATEWAY

DHT dht(DHT_PIN, DHT22);

typedef struct __attribute__((packed)) {
  float suhu;
  float kelembaban;
  uint32_t unix;
} sensor_packet_t;

uint8_t gatewayMac[] = GATEWAY_MAC;

void onSent(const uint8_t* mac, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "ESP-NOW OK" : "ESP-NOW GAGAL");
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  dht.begin();

  if (esp_now_init() != ESP_OK) {
    Serial.println("esp_now_init gagal");
    return;
  }
  esp_now_register_send_cb(onSent);

  esp_now_peer_info_t peer = {};
  memcpy(peer.peer_addr, gatewayMac, 6);
  peer.channel = 1;
  peer.encrypt = false;
  esp_now_add_peer(&peer);
}

void loop() {
  sensor_packet_t pkt;
  pkt.suhu = dht.readTemperature();
  pkt.kelembaban = dht.readHumidity();
  pkt.unix = 1782977400;  // production: NTP (#34)

  esp_now_send(gatewayMac, (uint8_t*)&pkt, sizeof(pkt));
  delay(5000);
}

Sketch Gateway — ESP-NOW Receiver + MQTT

Gateway: terima ESP-NOW, lalu publish ke broker 192.168.1.50 topic kodingindonesia/esp32/dht22/data — pola #7 + auth #16.

#include <esp_now.h>
#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "GANTI_NAMA_WIFI";
const char* pass = "GANTI_PASSWORD_WIFI";
const char* mqtt_host = "192.168.1.50";
const char* mqtt_user = "kindo_esp32";
const char* mqtt_pass = "GANTI_PASSWORD_MQTT";
const char* topic = "kodingindonesia/esp32/dht22/data";

WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);

typedef struct __attribute__((packed)) {
  float suhu;
  float kelembaban;
  uint32_t unix;
} sensor_packet_t;

void onRecv(const uint8_t* mac, const uint8_t* data, int len) {
  if (len != sizeof(sensor_packet_t)) return;
  sensor_packet_t pkt;
  memcpy(&pkt, data, sizeof(pkt));

  char json[128];
  snprintf(json, sizeof(json),
    "{\"suhu\":%.1f,\"kelembaban\":%.1f,\"unix\":%lu}",
    pkt.suhu, pkt.kelembaban, (unsigned long)pkt.unix);
  mqtt.publish(topic, json);
  Serial.println(json);
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) { delay(300); }

  mqtt.setServer(mqtt_host, 1883);
  mqtt.connect("kindo-espnow-gw", mqtt_user, mqtt_pass);

  if (esp_now_init() != ESP_OK) return;
  esp_now_register_recv_cb(onRecv);
}

void loop() {
  if (!mqtt.connected()) mqtt.connect("kindo-espnow-gw", mqtt_user, mqtt_pass);
  mqtt.loop();
}

Multi-Node & Topologi Star

Satu gateway bisa menerima data dari banyak sensor ESP-NOW. Pola umum di greenhouse atau gudang:

  • Star topology — semua sensor kirim ke satu gateway; gateway publish MQTT dengan field node_id di JSON
  • Daftar peer — di gateway, panggil esp_now_add_peer untuk setiap MAC sensor
  • Di sensor — cukup satu peer (MAC gateway); tidak perlu tahu MAC sensor lain

Contoh payload gateway dengan identitas node:

{"node":"greenhouse-1","suhu":28.5,"kelembaban":65.2,"unix":1782977400}

Topic MQTT bisa diperluas: kodingindonesia/esp32/greenhouse-1/dht22/data — pola hierarki sama dengan artikel #7. Subscriber Python (#18) atau Telegraf (#19) bisa filter per node.

Pro tip: Batasi jumlah peer aktif (~20 pada ESP32) dan interval kirim agar gateway tidak kelebihan beban CPU saat WiFi + MQTT + ESP-NOW berjalan bersamaan.

Debugging ESP-NOW di Serial Monitor

Saat pertama kali setup, aktifkan log verbose di kedua board:

  1. Print MAC STA di setup() — wajib sebelum pairing
  2. Di sender: pantau callback onSentESP_NOW_SEND_SUCCESS vs gagal
  3. Di gateway: print panjang paket di onRecv — harus sama dengan sizeof(sensor_packet_t)
  4. Cek WiFi.channel() di gateway setelah connect — samakan di peer.channel sensor
  5. Matikan power save WiFi sementara jika paket hilang acak: WiFi.setSleep(false)

Jika MQTT publish OK tapi ESP-NOW gagal, masalah ada di radio layer — jangan buru-buru ganti broker atau sketch MQTT.

Channel WiFi & Koeksistensi

ESP-NOW memakai channel radio yang sama dengan interface WiFi STA. Aturan praktis:

  • Set peer.channel = 1 di kedua sisi — atau samakan dengan channel AP gateway
  • Gateway yang connect ke router: channel mengikuti AP — sensor harus set channel yang sama
  • Gunakan WiFi.channel() di gateway, print ke Serial, lalu hardcode di sensor (atau simpan di NVS #12)

Deep Sleep + ESP-NOW di Node Sensor

Kombinasi ideal untuk baterai: sensor tidak perlu maintain WiFi association — cukup WiFi.mode(WIFI_STA), init ESP-NOW, kirim, lalu esp_deep_sleep_start(). Pola detail di #11.

Pro tip: Setelah esp_deep_sleep, ESP32 reboot — init ESP-NOW ulang di setup() setiap bangun.

Keamanan ESP-NOW

  • Default encrypt = false — OK untuk lab dalam ruangan
  • Produksi: set peer.encrypt = true + PMK (Primary Master Key) 16 byte sama di kedua firmware
  • Jangan broadcast MAC ke publik jika sistem kontrol (relay/pintu) — whitelist peer saja
  • Gateway tetap amankan MQTT dengan TLS #17 jika ke internet

Integrasi Dashboard & Histori

Setelah gateway publish MQTT, alur sama dengan artikel sebelumnya:

ESP-NOW hanya menggantikan hop pertama (sensor → gateway); selebihnya stack MQTT biasa.

Checklist: Kapan Pakai ESP-NOW?

  1. Sensor jauh dari router, tapi dekat ke ESP32 lain? → ESP-NOW
  2. Butuh kirim < 250 byte, interval pendek? → ESP-NOW
  3. Butuh jangkau kilometer? → LoRa (#26), bukan ESP-NOW
  4. Butuh banyak subscriber langsung dari sensor? → MQTT (#7)
  5. Node baterai + gateway solar/USB? → ESP-NOW sensor + MQTT gateway

Uji Coba (Lab)

# 1. Catat MAC kedua board dari Serial Monitor
# 2. Flash sender ke sensor, receiver+MQTT ke gateway
# 3. Di laptop:
mosquitto_sub -h 192.168.1.50 -t "kodingindonesia/esp32/dht22/data" -v
  1. Power sensor — dalam 5 detik JSON muncul di mosquitto_sub
  2. Matikan sensor — stream berhenti; gateway tetap online
  3. Jauhkan sensor >30 m atau balik dinding — amati packet loss
  4. Ubah channel salah di sensor — tidak ada data (debug channel)
  5. Cek Grafana (#19) — titik suhu naik jika Telegraf/subscriber jalan

FAQ Singkat

ESP-NOW butuh internet?
Tidak. Hanya butuh dua ESP32 di jangkau radio. Internet/WiFi hanya di gateway jika mau forward MQTT.
Bisa lebih dari 2 board?
Ya — satu gateway bisa daftar banyak peer esp_now_add_peer. Sensor broadcast ke gateway, atau star topology.
ESP8266 support ESP-NOW?
Ya, tapi API sedikit berbeda. Artikel ini fokus ESP32.
Bentrok dengan WiFi router?
Tidak jika channel diselaraskan. Gateway connect WiFi + ESP-NOW simultan didukung ESP32.

Tips & Troubleshooting

  • ESP-NOW GAGAL: MAC gateway salah atau channel beda — cek onSent callback
  • MQTT tidak publish: Gateway WiFi/MQTT bermasalah — debug terpisah dari ESP-NOW
  • Data korup: struct tidak packed sama di kedua sketch — ukuran harus identik
  • Range pendek: Normal di dalam bangunan; antena eksternal atau LoRa (#26) untuk jarak jauh
  • Payload >250 byte: Pecah paket atau kirim field penting saja; atau pakai WiFi/MQTT
  • MAC berubah? Tidak untuk STA — tapi tulis di label agar tidak tertukar board

Keamanan & Produksi

  • Ganti GANTI_NAMA_WIFI, GANTI_PASSWORD_WIFI, GANTI_PASSWORD_MQTT — jangan commit ke GitHub
  • Pakai NVS + WiFiManager (#12) di gateway untuk deploy lapangan
  • Aktifkan enkripsi ESP-NOW jika data kontrol (relay, kunci)
  • Placeholder MAC — selalu ganti dengan MAC nyata dari hardware kamu

Langkah Selanjutnya (Jalur D)

  • LoRa SX1278 (#26): sensor jarak jauh (ratusan meter–km) menggantikan/perluas ESP-NOW
  • MQTT TLS (#17) — amankan hop gateway → broker
  • Deep sleep (#11) — optimalkan node sensor baterai
  • Grafana (#19) — visualisasi data dari gateway MQTT
  • Capstone greenhouse (#39) — multi-node ESP-NOW + pompa MQTT

Dengan ESP-NOW, kamu bisa menaruh sensor di sudut yang WiFi router tidak jangkau — asalkan ada gateway ESP32 di tengah yang menjembatani ke MQTT. Lanjutkan Seri 2 di halaman artikel Koding Indonesia.