DEV Community

John  Ajera
John Ajera

Posted on

Building an ESP32-C3 WiFi MQTT Client for IoT Data Streaming (DevKitM-1 / Rust-1)

Building an ESP32-C3 WiFi MQTT Client for IoT Data Streaming (DevKitM-1 / Rust-1)

The Problem: Connecting ESP32 Devices to the Cloud

When building IoT projects with ESP32 devices, one of the biggest challenges is establishing reliable cloud connectivity. Hardcoded MQTT broker settings create several problems:

  • Deployment Complexity: Different environments need different MQTT brokers
  • Security Risk: Broker credentials are visible in source code
  • Maintenance Nightmare: Updating broker settings requires recompiling and reflashing
  • No Real-time Monitoring: Difficult to verify data is reaching the cloud

A Practical Solution: Externalized MQTT Configuration with Real-time Monitoring

Here's a comprehensive approach that extends WiFi connectivity with MQTT cloud streaming while keeping the code clean and maintainable:

πŸ” Externalized Configuration Management

  • WiFi and MQTT credentials stored in separate files
  • Template files for easy setup and deployment
  • Git-ignored credentials to prevent accidental commits
  • No hardcoded passwords or broker settings in source code

πŸ“‘ Real-time Data Streaming

  • Device sensor data published every 30 seconds
  • Heartbeat messages every 60 seconds for health monitoring
  • JSON-formatted messages for easy cloud processing
  • Command handling for remote device control

πŸ’‘ Visual Status Indicators

  • Built-in LED shows WiFi and MQTT connection status
  • Fast blink = Strong signal + MQTT connected
  • Medium blink = Medium signal + MQTT connected
  • Slow blink = Weak signal + MQTT connected
  • LED off = No WiFi connection

πŸ”„ Robust Connection Management

  • Auto-reconnection for both WiFi and MQTT
  • Independent monitoring every 5-10 seconds
  • Graceful handling of network failures
  • Comprehensive error logging

πŸ› οΈ Arduino IDE Ready

  • Works seamlessly with Arduino IDE
  • Simple library management (PubSubClient, ArduinoJson)
  • Easy setup scripts for Windows and Linux/Mac
  • No complex build systems or CLI tools

Code Architecture

Main Sketch Structure

##include <WiFi.h>
##include <PubSubClient.h>
##include <ArduinoJson.h>
##include "wifi_config.h"    // WiFi credentials (gitignored)
##include "mqtt_config.h"    // MQTT broker settings (gitignored)

##define LED_PIN 7 // ESP32C3 built-in LED

// Publishing intervals
const unsigned long DATA_PUBLISH_INTERVAL = 30000; // 30 seconds
const unsigned long HEARTBEAT_INTERVAL = 60000;    // 60 seconds

void setup() {
  // Initialize serial, LED, WiFi, and MQTT
  connectToWiFi();
  setupMQTT();
}

void loop() {
  // Monitor connections and publish data
  checkWiFiConnection();
  checkMQTTConnection();

  if (wifiConnected && mqttConnected) {
    publishDeviceData();
    publishHeartbeat();
  }

  updateLEDStatus();
  mqttClient.loop();
}
Enter fullscreen mode Exit fullscreen mode

Configuration Management

// wifi_config.h (gitignored)
const char* WIFI_SSID = "YourWiFiNetwork";
const char* WIFI_PASSWORD = "YourWiFiPassword";

// mqtt_config.h (gitignored)
const char* MQTT_BROKER = "broker.hivemq.com";
const int MQTT_PORT = 1883;
const char* MQTT_CLIENT_ID = "ESP32_Client";
const char* MQTT_TOPIC_PREFIX = "esp32/device";
Enter fullscreen mode Exit fullscreen mode

Key Features Explained

1. Real-time Data Publishing

The device publishes comprehensive sensor data every 30 seconds:

void publishDeviceData() {
  DynamicJsonDocument doc(512);
  doc["device_id"] = MQTT_CLIENT_ID;
  doc["timestamp"] = millis();
  doc["wifi_rssi"] = WiFi.RSSI();
  doc["wifi_ssid"] = WiFi.SSID();
  doc["free_heap"] = ESP.getFreeHeap();
  doc["uptime"] = millis() / 1000;
  doc["mqtt_connected"] = mqttConnected;

  String topic = String(MQTT_TOPIC_PREFIX) + "/data";
  String payload;
  serializeJson(doc, payload);

  mqttClient.publish(topic.c_str(), payload.c_str());
}
Enter fullscreen mode Exit fullscreen mode

2. Health Monitoring with Heartbeat

Regular heartbeat messages ensure device health monitoring:

void publishHeartbeat() {
  DynamicJsonDocument doc(256);
  doc["device_id"] = MQTT_CLIENT_ID;
  doc["timestamp"] = millis();
  doc["status"] = "alive";
  doc["wifi_connected"] = wifiConnected;
  doc["mqtt_connected"] = mqttConnected;

  String topic = String(MQTT_TOPIC_PREFIX) + "/heartbeat";
  String payload;
  serializeJson(doc, payload);

  mqttClient.publish(topic.c_str(), payload.c_str());
}
Enter fullscreen mode Exit fullscreen mode

3. Remote Device Control

The device responds to MQTT commands for remote control:

void handleCommand(JsonDocument &doc) {
  if (doc.containsKey("led")) {
    String ledCommand = doc["led"];
    if (ledCommand == "on") {
      digitalWrite(LED_PIN, HIGH);
      Serial.println("LED turned ON via MQTT");
    } else if (ledCommand == "off") {
      digitalWrite(LED_PIN, LOW);
      Serial.println("LED turned OFF via MQTT");
    }

    // Send acknowledgment
    publishCommandResponse("led", ledCommand, "success");
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Smart LED Status System

The LED provides instant visual feedback about connection status:

void updateLEDStatus() {
  if (!wifiConnected) {
    // No WiFi - LED off
    digitalWrite(LED_PIN, LOW);
  } else if (!mqttConnected) {
    // WiFi connected, no MQTT - slow blink
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState);
    ledBlinkInterval = 1000; // 1 second
  } else {
    // Both connected - show signal strength
    int rssi = WiFi.RSSI();
    if (rssi > -50) {
      // Strong signal - fast blink
      ledBlinkInterval = 100; // 100ms
    } else if (rssi > -70) {
      // Medium signal - medium blink
      ledBlinkInterval = 500; // 500ms
    } else {
      // Weak signal - slow blink
      ledBlinkInterval = 1000; // 1 second
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

MQTT Message Types and Frequency

Published Messages

Message Type Frequency Topic Purpose
Device Data Every 30 seconds esp32/device/data Sensor data and status
Heartbeat Every 60 seconds esp32/device/heartbeat Health monitoring
Connection Status On connect esp32/device/status Connection confirmation
Command Response Per command esp32/device/response Command acknowledgments

Subscribed Messages

Message Type Topic Purpose
Commands esp32/device/commands Remote device control
Configuration esp32/device/config Settings updates

Setup Instructions

1. Hardware Requirements

  • ESP32 C3 DevKitM1 board
  • USB cable for programming and power
  • WiFi network with internet access
  • MQTT broker (public test broker included)

2. Software Setup

  1. Install Arduino IDE
  2. Add ESP32 board package URL:
   https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Enter fullscreen mode Exit fullscreen mode
  1. Install "ESP32 by Espressif Systems" from Boards Manager
  2. Install required libraries:
    • PubSubClient by Nick O'Leary
    • ArduinoJson by Benoit Blanchon

3. Project Configuration

  1. Run setup script: ./setup.sh (Linux/Mac) or setup.bat (Windows)
  2. Edit wifi_config.h with your WiFi credentials
  3. Edit mqtt_config.h with your MQTT broker settings
  4. Select board: "ESP32C3 Dev Module"
  5. Upload and monitor at 115200 baud

4. Testing MQTT Messages

Use web-based MQTT clients to monitor messages:

5. Expected Serial Output

When everything is working correctly, you'll see output like this:

ESP32C3 WiFi Connection
Connecting to WiFi...
SSID: RWN
...
WiFi Connected!
IP: 192.168.12.11
RSSI: -51 dBm
Setup complete!
MQTT disconnected! Attempting to reconnect...
Connecting to MQTT broker: test.mosquitto.org
MQTT connected!
Subscribed to: esp32/device/commands
Subscribed to: esp32/device/config
βœ“ Data published to: esp32/device/data
  Payload: {"device_id":"ESP32_Client","timestamp":30032,"wifi_rssi":-52,"wifi_ssid":"RWN","free_heap":201648,"uptime":30,"mqtt_connected":true}
βœ“ Heartbeat published to: esp32/device/heartbeat
βœ“ Data published to: esp32/device/data
  Payload: {"device_id":"ESP32_Client","timestamp":60118,"wifi_rssi":-48,"wifi_ssid":"RWN","free_heap":199964,"uptime":60,"mqtt_connected":true}
Enter fullscreen mode Exit fullscreen mode

Security Considerations

βœ… Improvements Over Hardcoded Settings

  • Credentials are externalized from source code
  • Template files provide clear setup instructions
  • Git ignores actual credentials
  • No secrets in version control
  • MQTT messages contain no sensitive data

⚠️ Security Limitations

  • Credentials are still stored in plain text
  • No encryption at rest
  • Public MQTT broker for testing
  • Consider this a starting point, not a complete security solution

πŸ”’ For Production Use, Consider:

  • AWS IoT Core with X.509 certificates
  • Encrypted MQTT connections (MQTTS)
  • Device authentication and secure boot
  • Private MQTT brokers
  • OTA updates for configuration changes

Troubleshooting Common Issues

MQTT Connection Fails

  • Verify MQTT broker settings in mqtt_config.h
  • Check internet connectivity
  • Try different MQTT broker (test.mosquitto.org)
  • Verify broker port (1883 for standard MQTT)

No Messages in MQTT Client

  • Check ESP32 Serial Monitor for "MQTT connected!" message
  • Verify topic subscription: esp32/device/#
  • Ensure both WiFi and MQTT are connected
  • Check LED status indicators

WiFi Connection Fails

  • Verify credentials in wifi_config.h
  • Check WiFi network availability
  • Ensure 2.4GHz network (ESP32 doesn't support 5GHz)

Board Not Found

  • Check USB connection and drivers
  • Verify COM port selection
  • Try different USB cable

Project Structure

esp32-wifi-mqtt-cpp/
β”œβ”€β”€ esp32-wifi-mqtt/
β”‚   β”œβ”€β”€ esp32-wifi-mqtt.ino        # Main Arduino sketch
β”‚   β”œβ”€β”€ wifi_config_template.h     # WiFi credentials template
β”‚   β”œβ”€β”€ mqtt_config_template.h     # MQTT configuration template
β”‚   β”œβ”€β”€ setup.sh                   # Linux/Mac setup script
β”‚   └── setup.bat                  # Windows setup script
β”œβ”€β”€ .gitignore                     # Git ignore rules
β”œβ”€β”€ LICENSE                        # MIT License
└── README.md                      # Comprehensive documentation
Enter fullscreen mode Exit fullscreen mode

Why This Approach Works

For Development

  • Clean separation of concerns
  • Easy to test with different brokers
  • No accidental credential commits
  • Clear project structure
  • Real-time message monitoring

For Field Deployment

  • Simple setup process
  • Visual feedback for troubleshooting
  • Robust connection handling
  • Easy configuration updates
  • Comprehensive error logging

For Production Scaling

  • Foundation for AWS IoT Core integration
  • Terraform infrastructure automation
  • Fleet management capabilities
  • Cloud data processing pipeline
  • Enterprise-grade security

Next Steps

This foundation can be extended with:

  • AWS IoT Core Integration: Enterprise cloud connectivity
  • Terraform Infrastructure: Automated cloud deployment
  • Fleet Management: Scale to hundreds of devices
  • Data Analytics: Cloud-based data processing
  • OTA Updates: Remote firmware updates
  • Advanced Security: Certificate-based authentication

Conclusion

Building reliable IoT cloud connectivity doesn't have to be complicated. This ESP32 WiFi MQTT client demonstrates how to:

  • Stream real-time data to the cloud
  • Provide visual feedback for troubleshooting
  • Handle connection issues gracefully
  • Maintain clean, readable code
  • Deploy easily in the field
  • Scale to production environments

This approach provides a solid foundation for IoT projects that need reliable cloud connectivity without complex infrastructure requirements.

Ready to connect your ESP32 to the cloud? Start with externalized configuration and real-time monitoring. It's a small change that makes a big difference in reliability and maintainability!

πŸ“ Full Project Details

For the complete source code, setup instructions, and examples, check out the full project:

ESP32 WiFi MQTT Client Project

The repository includes:

  • Complete Arduino sketch with WiFi and MQTT functionality
  • Template files for easy setup
  • Comprehensive README with troubleshooting
  • Setup scripts for Windows and Linux/Mac
  • AWS IoT Core integration roadmap
  • Terraform infrastructure automation

What's your experience with IoT cloud connectivity? Have you found better approaches for MQTT integration? Let me know in the comments!

IoT #ESP32 #Arduino #MQTT #WiFi #CloudConnectivity #EmbeddedSystems #C++ #DataStreaming #AWS

Top comments (0)