ESP32 Firmware for BLE Wi-Fi Provisioning and Secure MQTT with X.509 Authentication to ThingsBoard

In a previous post, I explained how to secure ThingsBoard using X.509 client certificate authentication and enable auto-provisioning.
This post focuses on the ESP32 firmware implementation, covering BLE-based Wi-Fi provisioning (using protocomm), secure MQTT with TLS and X.509 client certificates, and persistent certificate storage in SPIFFS.

GitHub Repository: maksonlee/esp32-ble-mqtt-x509-thingsboard


Features

  • BLE provisioning using protocomm
  • SPIFFS-based certificate storage
  • MQTT over TLS (mqtts://) using X.509 client auth
  • Auto-provisioning on ThingsBoard using cert CN
  • Telemetry publishing every second
  • Modular, extensible C firmware using ESP-IDF

Development Environment

This guide is developed and tested on Windows using PowerShell and ESP-IDF v5.4.1.
If you’re on macOS or Linux, adapt file paths and environment variable syntax accordingly.


Project Structure

esp32-ble-mqtt-x509-thingsboard/
├── main/
│   ├── app_event.c/.h             # Event loop abstraction
│   ├── app_main.c                 # Main entry task
│   ├── cert_manager.c/.h          # SPIFFS X.509 loader
│   ├── dht11.c/.h                 # Optional: DHT11 sensor logic
│   ├── mqtt_client_handler.c/.h   # MQTT init and telemetry
│   ├── spiffs_utils.c/.h          # SPIFFS mounting and helpers
│   ├── wifi_provisioning.c/.h     # BLE Wi-Fi setup via protocomm
│   ├── CMakeLists.txt
│   └── Kconfig.projbuild
├── spiffs_root/                   # Place certs/keys here (not versioned)
├── spiffs_image/                  # Output SPIFFS image
├── CMakeLists.txt
├── sdkconfig
└── README.md

SPIFFS Certificate Setup

Place these files inside spiffs_root/:

  • device.crt – X.509 client certificate
  • device.key – Matching private key
  • server_chain.pem – Trusted CA chain (root + intermediate)

Generate the SPIFFS image:

python $env:IDF_PATH/components/spiffs/spiffsgen.py 0x40000 .\spiffs_root .\spiffs_image\spiffs.bin

Replace 0x40000 with the size defined in your partitions.csv (not offset).


Flashing the Firmware

  • Build and Flash the Application
idf.py build
idf.py -p COMX flash

This flashes the firmware, bootloader, and partition table.

  • Flash SPIFFS Image Separately
esptool.py --chip esp32 --port COMX write_flash 0x290000 .\spiffs_image\spiffs.bin

Make sure the offset 0x290000 matches the SPIFFS partition offset defined in your partitions.csv.


BLE Wi-Fi Provisioning

This firmware uses ESP-IDF’s protocomm BLE interface for secure provisioning. You can use Espressif’s official app:

📲 ESP BLE Provisioning (Android/iOS)

Steps:

  • Power on the device.
  • Connect via the app using BLE.
  • Enter your SSID and password.
  • ESP32 saves credentials and connects to Wi-Fi.

MQTT over TLS with X.509 Auth

After connecting to Wi-Fi, the ESP32 uses:

  • device.crt as its identity (CN = device ID)
  • device.key as private key
  • server_chain.pem as trusted CA chain

The firmware connects to:

mqtts://thingsboard.yourdomain.com:8883

This triggers auto-provisioning on ThingsBoard based on the certificate’s Common Name (CN).


Telemetry Format

Once connected, the ESP32 publishes telemetry every second:

{
  "temperature": 23.5,
  "humidity": 56
}

You can modify the content in mqtt_client_handler.c to add other sensors or fields.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top