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 certificatedevice.key
– Matching private keyserver_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 keyserver_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.