Skip to main content
This guide walks you through connecting an ESP32 to PumpLink. By the end, your device will appear in the dashboard and respond to activation commands.

pumplink-esp32-firmware

Clone the starter repo to get all files ready to configure and flash.

What you need

  • An ESP32 board (any variant — ESP32-WROOM, ESP32-S3, etc.)
  • A relay module wired to your ESP32 (or just an LED for testing)
  • Arduino IDE installed
  • A PumpLink account — sign up free

Step 1 — Register your device

Sign in to the PumpLink dashboard, go to Devices → Add device, give it a name, and click Register. You’ll see a Device ID and a Password shown once. Copy both immediately — the password is never shown again. If you lose it, you’ll need to regenerate credentials and reflash.
The password is shown exactly once. Store it securely before closing the dialog.

Step 2 — Create your project

Install ESP32 board support

In Arduino IDE → Preferences, add this to Additional boards manager URLs:
Then go to Tools → Board → Boards Manager, search ESP32, and install.

Install dependencies

In Arduino IDE → Tools → Manage Libraries, install:
  • PubSubClient by Nick O’Leary

Create the sketch

Create a new sketch folder and add the following files:

config.h


ca_cert.h

This is the Let’s Encrypt root CA certificate chain. It allows the ESP32 to verify the TLS connection to mqtt.pumplink.dev without disabling certificate verification.
The CA certificate above verifies mqtt.pumplink.dev’s TLS certificate chain. You do not need to update this when PumpLink renews its broker certificate — the root CA is valid until 2035.

Name the sketch file to match your folder name (e.g. a folder named pumplink_esp32 needs pumplink_esp32.ino).

Step 3 — Flash

Open pumplink_esp32.ino in Arduino IDE, select your board and port under Tools, then click Upload. Open the Serial Monitor at 115200 baud and you should see:

Step 4 — Verify

Go to the PumpLink dashboard — your device should appear as Online. To trigger an activation without writing any client code, connect to the broker with MQTT Explorer using your device’s username and password (same host and port as your firmware — mqtt.pumplink.dev:42743, TLS enabled). Then:
  1. Subscribe to device/42/# (replace 42 with your device ID) to watch all traffic for your device.
  2. Publish on to device/42/command.
Your relay should click on immediately, and the device should publish to device/42/ack within 10 seconds. Publish off to the same command topic to turn it back off — the device must ack that too, within the same 10 seconds, or the backend marks it UNKNOWN and refuses to re-activate it until it hears back. The serial monitor will show:
This manual publish is just for testing. In production, the backend publishes on/off to the command topic on your behalf when a user triggers an activation from the dashboard or API — see the device contract for the full handshake.

Using PlatformIO instead

If you prefer PlatformIO in VS Code over the Arduino IDE, the same three files work as-is — just place them under src/ and add a platformio.ini:
Change board to match your specific board if needed (e.g. esp32-s3-devkitc-1). Save config.h and ca_cert.h from above into src/, and save the sketch from above as src/main.cpp. Build and flash with:

Troubleshooting

Device doesn’t appear in dashboard
  • Check serial monitor for connection errors
  • Verify MQTT_USERNAME is your numeric device ID (e.g. "42" not "device_42")
  • Verify MQTT_PASSWORD is correct — regenerate from dashboard if unsure
TLS handshake fails
  • Confirm mqtt.pumplink.dev resolves from your network
  • The CA cert in ca_cert.h must be complete and unmodified
Relay doesn’t click
  • Verify RELAY_PIN matches your wiring
  • Most relay modules are active HIGH — digitalWrite(HIGH) closes the relay
Ack timeout (device shows offline after activation, or won’t re-activate)
  • The backend expects an ack within 10 seconds of sending "on" or "off" — a missed off-ack marks the device UNKNOWN and blocks the next activation until it hears back
  • Check that topicAck() publishes successfully — look for [MQTT] ack sent in serial after both command: on and command: off
  • If a device gets stuck UNKNOWN, it self-heals the moment it publishes its real state to device/{id}/status — reconnecting is usually enough if your firmware reports status on connect

Next steps