Blynk IoT Mobile App Control with ESP32: Virtual Pins and Events

Building an Android or iOS app from scratch is a project on its own. Blynk solves that for IoT: you design a phone dashboard by placing widgets such as buttons, gauges and charts, and the Blynk library on the ESP32 connects it to the Blynk cloud. The same template also gives you a web dashboard.

This tutorial uses the current Blynk IoT platform (the older "Blynk Legacy" app and its local server are discontinued). You will create a template with datastreams, control a relay from the phone, send temperature and humidity every five seconds, restore the relay state after a reboot, and trigger a push notification when it gets too hot.

Blynk Building Blocks

TermWhat it isIn this project
TemplateBlueprint shared by all devices of one product: datastreams, dashboards, events"Room Controller"
DeviceOne physical board created from a template, with its own auth tokenESP32 in the bedroom
DatastreamA named channel of data, usually mapped to a virtual pinV0 relay, V1 temperature, V2 humidity
Virtual pinA number V0 to V255 with no hardware meaning; your code decides what it doesV0 drives GPIO 26
WidgetUI element on the web or mobile dashboard bound to a datastreamSwitch, Gauge, Chart
EventA named condition that can send notificationshigh_temp

Virtual pins are the key idea. Instead of letting the app write directly to GPIO numbers, the app writes to V0, and your sketch's BLYNK_WRITE(V0) function decides what to do. This keeps hardware details in firmware and lets you validate commands.

Setting Up the Template

  1. Sign in at blynk.cloud and open Developer Zone > My Templates > New Template. Choose hardware ESP32 and connection type WiFi.
  2. Under Datastreams add: V0 "Relay", data type Integer, min 0, max 1; V1 "Temperature", Double, units °C, min 0, max 60; V2 "Humidity", Double, units %, min 0, max 100.
  3. Under Events & Notifications add an event with code high_temp, and enable push notifications for it.
  4. Under Web Dashboard add a Switch on V0, two Gauges on V1 and V2, and a Chart showing V1 and V2. Save.
  5. Go to Devices > New Device > From template, pick the template and create the device.
  6. Copy the three #define lines shown for the device: template ID, template name and auth token.
  7. In the Blynk IoT phone app, open the device and add a Button, Gauges and a Chart bound to the same datastreams.

Hardware

PartESP32 pinNotes
DHT22 dataGPIO 410 kΩ pull-up to 3.3 V
Relay module INGPIO 26Use a module with transistor driver and flyback diode; many 5 V modules accept a 3.3 V input
Relay module VCC / GND5V (VIN) / GNDCommon ground with the ESP32

The Sketch

Install the Blynk library by Volodymyr Shymanskyy from the Library Manager. The template and token defines must appear before the Blynk include.

ESP32 Blynk IoT: relay on V0, temperature on V1, humidity on V2, high_temp event
// Paste the three lines from your device page in the Blynk console
#define BLYNK_TEMPLATE_ID   "TMPLxxxxxxxx"
#define BLYNK_TEMPLATE_NAME "Room Controller"
#define BLYNK_AUTH_TOKEN    "YourDeviceAuthToken"
#define BLYNK_PRINT Serial          // connection logs on Serial Monitor

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>

char ssid[] = "YourWiFi";
char pass[] = "YourWiFiPassword";

const int RELAY_PIN = 26;
const bool RELAY_ACTIVE_LOW = true;  // most cheap relay modules switch ON with LOW
const float TEMP_LIMIT = 35.0;

DHT dht(4, DHT22);
BlynkTimer timer;
bool alerted = false;

void setRelay(bool on) {
  digitalWrite(RELAY_PIN, (on ^ RELAY_ACTIVE_LOW) ? HIGH : LOW);
}

// Runs whenever the app or web dashboard writes to V0
BLYNK_WRITE(V0) {
  int value = param.asInt();         // 0 or 1
  setRelay(value == 1);
  Serial.printf("Relay -> %d", value);
  Serial.println();
}

// Runs every time the board (re)connects to Blynk
BLYNK_CONNECTED() {
  Blynk.syncVirtual(V0);             // ask the server for the last V0 value
}

void sendSensor() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();
  if (isnan(t) || isnan(h)) return;
  Blynk.virtualWrite(V1, t);
  Blynk.virtualWrite(V2, h);

  // fire the event once per crossing, not every 5 seconds
  if (t > TEMP_LIMIT && !alerted) {
    Blynk.logEvent("high_temp", String("Temperature is ") + t + " C");
    alerted = true;
  } else if (t < TEMP_LIMIT - 2) {
    alerted = false;                 // 2 degree hysteresis
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  setRelay(false);                   // safe state until synced
  dht.begin();
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);  // connects Wi-Fi and Blynk
  timer.setInterval(5000L, sendSensor);
}

void loop() {
  Blynk.run();                       // must run often; no long delay() here
  timer.run();
}

How It Works

  • BLYNK_WRITE(V0) is a macro that defines a handler. param.asInt(), param.asFloat() and param.asStr() read the incoming value.
  • Blynk.virtualWrite(V1, t) sends a value to a datastream; the Blynk cloud stores it for charts and pushes it to open dashboards.
  • BLYNK_CONNECTED() with Blynk.syncVirtual(V0) asks the server to resend the last V0 value, which triggers BLYNK_WRITE(V0). After a power cut the relay returns to the state shown in the app.
  • BlynkTimer runs sendSensor every 5 seconds without delay(). A blocking delay would stop Blynk.run() and the board would appear offline.
  • Blynk.logEvent triggers the event defined in the template, which delivers the push notification. The flag prevents an event every five seconds.
  • Blynk.begin() blocks until both Wi-Fi and Blynk connect. For devices that must keep working offline, use WiFi.begin() with Blynk.config() and Blynk.connect() instead.

Troubleshooting

  • Compile error about BLYNK_TEMPLATE_ID: the defines must be above #include <BlynkSimpleEsp32.h>.
  • Device shows offline though Wi-Fi works: wrong auth token, or a token from a different device. Each device has its own token.
  • Switch toggles but relay does the opposite: change RELAY_ACTIVE_LOW.
  • Messages are dropped or the device gets disconnected: sending too often. Blynk enforces message rate limits; keep sensor updates at a few seconds or slower.
  • Notifications never arrive: the event code in the sketch must match the template exactly, and notifications must be enabled for that event and in the phone's app settings.

Summary

Blynk lets you build a phone and web interface for an ESP32 without writing app code. Templates define datastreams, virtual pins connect widgets to firmware handlers, BlynkTimer keeps the loop non-blocking, syncVirtual restores state after a reboot and logEvent delivers alerts. The trade-off is dependence on a third-party cloud and its plan limits, which is why the later smart home tutorial builds the same idea on your own MQTT broker.