# MQTT Manager Library for ESP32 A robust and feature-rich MQTT client library designed for ESP32 development with ESP-IDF framework. This library provides high-level MQTT communication with automatic reconnection, event callbacks, and optimized sensor data publishing for IoT applications. ## 📋 Features - ✅ **High-level MQTT API** - Simplified interface for complex MQTT operations - ✅ **Automatic reconnection** - Seamless reconnection on network failures - ✅ **Event-driven callbacks** - Real-time status updates and message notifications - ✅ **Quality of Service support** - Full QoS 0, 1, and 2 implementation - ✅ **Sensor data optimization** - Built-in JSON formatting for sensor data - ✅ **Publish/Subscribe support** - Complete bidirectional communication - ✅ **Thread-safe operations** - Safe for use in multi-task environments - ✅ **Memory efficient** - Optimized for resource-constrained devices - ✅ **Flexible configuration** - Customizable timeouts, keepalive, and authentication - ✅ **Comprehensive error handling** - Detailed error reporting and status tracking ## 📦 Installation ### Method 1: Git Submodule ```bash cd your_project_directory/lib git submodule add https://home.arcoa.eu:8413/esp32libs/mqtt_manager.git ``` ### Method 2: Manual Copy 1. Clone or download this repository 2. Copy the `mqtt_manager` folder to your project's `lib/` or `components/` directory 3. Include the header in your code: `#include "mqtt_manager.h"` ### Method 3: PlatformIO Library Add to your `platformio.ini`: ```ini lib_deps = git+https://home.arcoa.eu:8413/esp32libs/mqtt_manager.git ``` ## 🚀 Quick Start ### Basic Usage ```c #include "mqtt_manager.h" void mqtt_event_callback(mqtt_status_t status, const char *topic, const char *data, int data_len) { switch (status) { case MQTT_STATUS_CONNECTED: printf("MQTT Connected!\n"); break; case MQTT_STATUS_DISCONNECTED: printf("MQTT Disconnected\n"); break; case MQTT_STATUS_CONNECTING: printf("MQTT Connecting...\n"); break; case MQTT_STATUS_ERROR: printf("MQTT Error\n"); break; } if (topic && data) { printf("Received: %.*s on topic: %s\n", data_len, data, topic); } } void app_main(void) { // Configure MQTT mqtt_config_t config = { .broker_url = "mqtt://192.168.1.100", .broker_port = 1883, .client_id = "esp32_device_001", .username = NULL, // Optional .password = NULL, // Optional .keepalive = 60, .network_timeout_ms = 5000 }; // Initialize MQTT manager esp_err_t ret = mqtt_manager_init(&config, mqtt_event_callback); if (ret != ESP_OK) { printf("MQTT initialization failed: %s\n", esp_err_to_name(ret)); return; } // Start MQTT client mqtt_manager_start(); // Main application loop while (1) { if (mqtt_manager_is_connected()) { // Publish sensor data mqtt_manager_publish_string("sensors/temperature", "25.6", 0, 0); mqtt_manager_publish_string("sensors/humidity", "65.2", 0, 0); } vTaskDelay(pdMS_TO_TICKS(30000)); // Publish every 30 seconds } } ``` ### Sensor Data Publishing Example ```c #include "mqtt_manager.h" #include "dht22_sensor.h" void sensor_data_example(void) { // Initialize MQTT mqtt_config_t config = { .broker_url = "mqtt://iot.example.com", .broker_port = 1883, .client_id = "weather_station_01", .username = "sensor_user", .password = "sensor_pass", .keepalive = 60, .network_timeout_ms = 10000 }; mqtt_manager_init(&config, NULL); mqtt_manager_start(); // Initialize sensor dht22_init(GPIO_NUM_4); while (1) { if (mqtt_manager_is_connected()) { float temperature, humidity; if (dht22_read(&temperature, &humidity) == DHT22_OK) { // Publish formatted sensor data as JSON mqtt_manager_publish_sensor_data( "sensors/weather", temperature, humidity, "weather_station_01", 1, // QoS 1 for reliability 0 // No retain ); printf("Published: Temp=%.1f°C, Humidity=%.1f%%\n", temperature, humidity); } } vTaskDelay(pdMS_TO_TICKS(60000)); // Every minute } } ``` ### Subscribe and Command Processing ```c #include "mqtt_manager.h" void command_callback(mqtt_status_t status, const char *topic, const char *data, int data_len) { if (status == MQTT_STATUS_CONNECTED) { // Subscribe to command topics when connected mqtt_manager_subscribe("device/commands", 1); mqtt_manager_subscribe("device/config", 1); } if (topic && data) { if (strcmp(topic, "device/commands") == 0) { char command[64]; snprintf(command, sizeof(command), "%.*s", data_len, data); if (strcmp(command, "restart") == 0) { printf("Restart command received\n"); esp_restart(); } else if (strcmp(command, "status") == 0) { mqtt_manager_publish_string("device/status", "online", 1, 0); } } if (strcmp(topic, "device/config") == 0) { printf("Config update: %.*s\n", data_len, data); // Process configuration updates } } } void command_processing_example(void) { mqtt_config_t config = { .broker_url = "mqtts://secure-broker.com", .broker_port = 8883, .client_id = "smart_device_01", .username = "device", .password = "secure_password", .keepalive = 120, .network_timeout_ms = 10000 }; mqtt_manager_init(&config, command_callback); mqtt_manager_start(); // Application continues... } ``` ### TLS/SSL with Certificate Authentication For secure MQTT connections (mqtts://), you can provide a CA certificate for server verification: ```c #include "mqtt_manager.h" // Embedded CA certificate - from your src/certs/ca.crt file extern const uint8_t ca_crt_start[] asm("_binary_ca_crt_start"); void secure_mqtt_example(void) { mqtt_config_t config = { .broker_url = "mqtts://mqtt.example.com", .broker_port = 8883, .client_id = "secure_device_01", .username = "device_user", .password = "secure_password", .ca_cert_pem = (const char *)ca_crt_start, // Embedded CA certificate .keepalive = 60, .network_timeout_ms = 10000 }; mqtt_manager_init(&config, mqtt_callback); mqtt_manager_start(); } ``` #### Embedding Certificates in Firmware To embed a CA certificate in your firmware: 1. **Place certificate file:** ``` src/certs/ca.crt ``` 2. **Update src/CMakeLists.txt:** ```cmake idf_component_register( SRCS ${app_sources} EMBED_TXTFILES "certs/ca.crt" ) ``` 3. **Reference in your code:** ```c extern const uint8_t ca_crt_start[] asm("_binary_ca_crt_start"); extern const uint8_t ca_crt_end[] asm("_binary_ca_crt_end"); // Use in config mqtt_config_t config = { .ca_cert_pem = (const char *)ca_crt_start, // ... other config }; ``` The symbol name format is `_binary__start` and `_binary__end` where slashes are converted to underscores. ## 📚 API Reference ### Data Types #### `mqtt_status_t` (Enum) MQTT connection status values: | Value | Description | When Triggered | | ------------------------------ | ---------------------- | ------------------------------------ | | `MQTT_STATUS_DISCONNECTED` (0) | Client is disconnected | Initial state, connection lost | | `MQTT_STATUS_CONNECTING` (1) | Connection in progress | Before connect attempt | | `MQTT_STATUS_CONNECTED` (2) | Successfully connected | After successful connection | | `MQTT_STATUS_ERROR` (3) | Error state | Connection failures, protocol errors | #### `mqtt_config_t` (Struct) Configuration structure for MQTT client: ```c typedef struct { const char *broker_url; // MQTT broker URL (e.g., "mqtt://192.168.1.100") int broker_port; // MQTT broker port (usually 1883 for non-secure) const char *client_id; // Unique client identifier const char *username; // Username (can be NULL if not required) const char *password; // Password (can be NULL if not required) const char *ca_cert_pem; // CA certificate in PEM format (NULL to disable TLS verification) int keepalive; // Keepalive interval in seconds (0 for default) int network_timeout_ms; // Network timeout in milliseconds (0 for default) } mqtt_config_t; ``` **Field Descriptions:** - `broker_url`: Full URL with protocol (mqtt://, mqtts://, ws://, wss://) - `broker_port`: Standard ports: 1883 (mqtt), 8883 (mqtts), 80 (ws), 443 (wss) - `client_id`: Must be unique across all clients connecting to the broker - `username`/`password`: Authentication credentials (set to NULL if not needed) - `ca_cert_pem`: PEM-formatted CA certificate for TLS/SSL verification (set to NULL to skip verification, or provide embedded certificate from firmware) - `keepalive`: Heartbeat interval (recommended: 60-300 seconds) - `network_timeout_ms`: Socket timeout (recommended: 5000-30000ms) #### `mqtt_event_callback_t` (Function Pointer) Event callback function type: ```c typedef void (*mqtt_event_callback_t)(mqtt_status_t status, const char *topic, const char *data, int data_len); ``` **Parameters:** - `status`: Current MQTT connection status - `topic`: Topic name (only valid for received messages) - `data`: Message payload (only valid for received messages) - `data_len`: Length of message data ### Constants & Default Values | Constant | Default Value | Description | | ----------------------- | ------------- | ----------------------------- | | Default Port (mqtt://) | 1883 | Standard MQTT port | | Default Port (mqtts://) | 8883 | Secure MQTT port | | Default Keepalive | 120 seconds | Connection heartbeat interval | | Default Network Timeout | 10000ms | Socket operation timeout | | Maximum Topic Length | 256 chars | MQTT topic length limit | | Maximum Payload Size | 1024 bytes | Single message size limit | ### Functions #### Initialization Functions ##### `esp_err_t mqtt_manager_init(const mqtt_config_t *config, mqtt_event_callback_t event_callback)` Initialize the MQTT manager with configuration and optional event callback. **Parameters:** - `config`: Pointer to MQTT configuration structure - `event_callback`: Optional callback function for MQTT events (can be NULL) **Returns:** - `ESP_OK`: Initialization successful - `ESP_ERR_INVALID_ARG`: Invalid configuration or NULL config pointer - `ESP_ERR_INVALID_STATE`: Already initialized - `ESP_ERR_NO_MEM`: Insufficient memory - `ESP_FAIL`: Initialization failed **Technical Details:** - Initializes ESP MQTT client with provided configuration - Sets up event handlers for connection management - Configures automatic reconnection logic - Validates all configuration parameters **Example:** ```c mqtt_config_t config = { .broker_url = "mqtt://broker.example.com", .broker_port = 1883, .client_id = "my_device", .keepalive = 60 }; esp_err_t ret = mqtt_manager_init(&config, my_callback); if (ret != ESP_OK) { ESP_LOGE("APP", "MQTT init failed: %s", esp_err_to_name(ret)); } ``` ##### `esp_err_t mqtt_manager_deinit(void)` Deinitialize MQTT manager and free all resources. **Returns:** - `ESP_OK`: Success - `ESP_FAIL`: Cleanup failed **Technical Details:** - Stops MQTT client if running - Unregisters event handlers - Frees allocated memory - Resets internal state **Example:** ```c mqtt_manager_stop(); mqtt_manager_deinit(); ``` #### Connection Management Functions ##### `esp_err_t mqtt_manager_start(void)` Start the MQTT client and initiate connection. **Returns:** - `ESP_OK`: Client started successfully - `ESP_ERR_INVALID_STATE`: Not initialized or already started - `ESP_FAIL`: Failed to start client **Technical Details:** - Begins connection attempt to configured broker - Triggers `MQTT_STATUS_CONNECTING` event - Automatic reconnection on connection loss - Non-blocking operation **Example:** ```c if (mqtt_manager_start() == ESP_OK) { printf("MQTT client started\n"); } ``` ##### `esp_err_t mqtt_manager_stop(void)` Stop the MQTT client and disconnect. **Returns:** - `ESP_OK`: Client stopped successfully - `ESP_ERR_INVALID_STATE`: Not initialized or not started **Technical Details:** - Gracefully disconnects from broker - Stops automatic reconnection - Triggers `MQTT_STATUS_DISCONNECTED` event - Maintains initialization state **Example:** ```c mqtt_manager_stop(); ``` ##### `mqtt_status_t mqtt_manager_get_status(void)` Get current MQTT connection status. **Returns:** - Current `mqtt_status_t` value **Example:** ```c mqtt_status_t status = mqtt_manager_get_status(); if (status == MQTT_STATUS_CONNECTED) { printf("MQTT is connected\n"); } ``` ##### `bool mqtt_manager_is_connected(void)` Check if MQTT client is currently connected. **Returns:** - `true`: Connected to broker - `false`: Not connected **Example:** ```c if (mqtt_manager_is_connected()) { mqtt_manager_publish_string("status", "online", 0, 0); } ``` ##### `esp_err_t mqtt_manager_reconnect(void)` Force immediate reconnection attempt. **Returns:** - `ESP_OK`: Reconnection initiated - `ESP_ERR_INVALID_STATE`: Not initialized - `ESP_FAIL`: Reconnection failed **Technical Details:** - Disconnects current connection (if any) - Immediately attempts reconnection - Useful for recovering from network errors **Example:** ```c // Force reconnection after network change mqtt_manager_reconnect(); ``` #### Publishing Functions ##### `int mqtt_manager_publish(const char *topic, const char *data, int len, int qos, int retain)` Publish raw data to an MQTT topic. **Parameters:** - `topic`: Topic to publish to (maximum 256 characters) - `data`: Message payload data - `len`: Length of data (0 for automatic string length) - `qos`: Quality of Service (0, 1, or 2) - `retain`: Retain flag (0 = no retain, 1 = retain) **Returns:** - Message ID (positive integer) on success - `-1` on error **QoS Levels:** - **QoS 0**: At most once delivery (fire and forget) - **QoS 1**: At least once delivery (acknowledged) - **QoS 2**: Exactly once delivery (assured) **Example:** ```c // Publish binary data uint8_t sensor_data[] = {0x01, 0x02, 0x03, 0x04}; int msg_id = mqtt_manager_publish("device/data", (char*)sensor_data, 4, 1, 0); ``` ##### `int mqtt_manager_publish_string(const char *topic, const char *message, int qos, int retain)` Publish string message to an MQTT topic. **Parameters:** - `topic`: Topic to publish to - `message`: String message to publish - `qos`: Quality of Service (0, 1, or 2) - `retain`: Retain flag (0 = no retain, 1 = retain) **Returns:** - Message ID on success, -1 on error **Example:** ```c // Simple string publishing mqtt_manager_publish_string("sensors/status", "online", 1, 1); mqtt_manager_publish_string("alerts/temperature", "HIGH", 2, 0); ``` ##### `int mqtt_manager_publish_sensor_data(const char *topic, float temperature, float humidity, const char *device_id, int qos, int retain)` Publish sensor data as formatted JSON. **Parameters:** - `topic`: Topic to publish to - `temperature`: Temperature value in Celsius - `humidity`: Humidity percentage value - `device_id`: Device identifier string - `qos`: Quality of Service (0, 1, or 2) - `retain`: Retain flag **Returns:** - Message ID on success, -1 on error **JSON Format:** ```json { "device_id": "device_name", "temperature": 25.6, "humidity": 65.2, "timestamp": 1672531200 } ``` **Example:** ```c // Publish sensor data with automatic JSON formatting int msg_id = mqtt_manager_publish_sensor_data( "sensors/weather", 23.5, // temperature 68.2, // humidity "outdoor_01", // device_id 1, // QoS 1 0 // no retain ); ``` #### Subscription Functions ##### `int mqtt_manager_subscribe(const char *topic, int qos)` Subscribe to an MQTT topic. **Parameters:** - `topic`: Topic pattern to subscribe to - `qos`: Requested Quality of Service (0, 1, or 2) **Returns:** - Message ID on success, -1 on error **Topic Patterns:** - `sensors/temperature` - Exact topic - `sensors/+` - Single-level wildcard - `sensors/#` - Multi-level wildcard **Example:** ```c // Subscribe to specific topics mqtt_manager_subscribe("device/commands", 1); mqtt_manager_subscribe("sensors/+", 0); // All sensors mqtt_manager_subscribe("alerts/#", 2); // All alerts ``` ##### `int mqtt_manager_unsubscribe(const char *topic)` Unsubscribe from an MQTT topic. **Parameters:** - `topic`: Topic to unsubscribe from **Returns:** - Message ID on success, -1 on error **Example:** ```c // Unsubscribe from topic mqtt_manager_unsubscribe("device/commands"); ``` ## 🔧 Configuration Guide ### Broker URL Formats ```c // Standard MQTT (unencrypted) .broker_url = "mqtt://192.168.1.100" .broker_url = "mqtt://broker.example.com" // Secure MQTT over TLS .broker_url = "mqtts://secure-broker.com" // WebSocket MQTT .broker_url = "ws://broker.example.com" .broker_url = "wss://secure-broker.com" ``` ### Authentication Configuration ```c // No authentication mqtt_config_t config = { .broker_url = "mqtt://public-broker.com", .client_id = "my_device", .username = NULL, .password = NULL }; // Username/password authentication mqtt_config_t config = { .broker_url = "mqtt://private-broker.com", .client_id = "authenticated_device", .username = "device_user", .password = "secure_password" }; ``` ### Performance Tuning ```c // High-performance configuration mqtt_config_t config = { .broker_url = "mqtt://high-perf-broker.com", .broker_port = 1883, .client_id = "fast_device", .keepalive = 30, // Shorter keepalive for faster detection .network_timeout_ms = 3000 // Shorter timeout for responsiveness }; // Reliable configuration mqtt_config_t config = { .broker_url = "mqtt://reliable-broker.com", .broker_port = 1883, .client_id = "reliable_device", .keepalive = 300, // Longer keepalive for stability .network_timeout_ms = 15000 // Longer timeout for reliability }; ``` ## 📖 Usage Patterns ### IoT Sensor Station ```c void iot_sensor_station(void) { // Configure MQTT for sensor data mqtt_config_t config = { .broker_url = "mqtt://iot.example.com", .broker_port = 1883, .client_id = "sensor_station_01", .username = "sensors", .password = "sensor_password", .keepalive = 60, .network_timeout_ms = 10000 }; mqtt_manager_init(&config, sensor_event_callback); mqtt_manager_start(); // Main sensor loop while (1) { if (mqtt_manager_is_connected()) { // Read multiple sensors float temperature, humidity, pressure; if (read_sensors(&temperature, &humidity, &pressure) == ESP_OK) { // Publish individual readings char temp_str[16], hum_str[16], press_str[16]; snprintf(temp_str, sizeof(temp_str), "%.2f", temperature); snprintf(hum_str, sizeof(hum_str), "%.2f", humidity); snprintf(press_str, sizeof(press_str), "%.2f", pressure); mqtt_manager_publish_string("sensors/temperature", temp_str, 0, 0); mqtt_manager_publish_string("sensors/humidity", hum_str, 0, 0); mqtt_manager_publish_string("sensors/pressure", press_str, 0, 0); // Publish combined data mqtt_manager_publish_sensor_data("sensors/combined", temperature, humidity, "station_01", 1, 0); } } vTaskDelay(pdMS_TO_TICKS(30000)); // Every 30 seconds } } ``` ### Remote Control Device ```c void remote_control_callback(mqtt_status_t status, const char *topic, const char *data, int data_len) { static bool subscribed = false; if (status == MQTT_STATUS_CONNECTED && !subscribed) { mqtt_manager_subscribe("device/+/command", 1); mqtt_manager_subscribe("device/+/config", 1); subscribed = true; // Announce device online mqtt_manager_publish_string("device/status", "online", 1, 1); } if (topic && data) { char command[128]; snprintf(command, sizeof(command), "%.*s", data_len, data); if (strstr(topic, "/command")) { printf("Command received: %s\n", command); if (strcmp(command, "led_on") == 0) { gpio_set_level(GPIO_NUM_2, 1); mqtt_manager_publish_string("device/status", "led_on", 0, 0); } else if (strcmp(command, "led_off") == 0) { gpio_set_level(GPIO_NUM_2, 0); mqtt_manager_publish_string("device/status", "led_off", 0, 0); } else if (strcmp(command, "restart") == 0) { mqtt_manager_publish_string("device/status", "restarting", 1, 0); vTaskDelay(pdMS_TO_TICKS(1000)); esp_restart(); } } if (strstr(topic, "/config")) { printf("Config update: %s\n", command); // Process configuration changes } } } void remote_control_device(void) { mqtt_config_t config = { .broker_url = "mqtt://control-server.com", .broker_port = 1883, .client_id = "remote_device_01", .username = "devices", .password = "device_access", .keepalive = 60 }; mqtt_manager_init(&config, remote_control_callback); mqtt_manager_start(); } ``` ### Data Logging System ```c typedef struct { float value; uint32_t timestamp; char source[32]; } sensor_reading_t; void data_logger_system(void) { mqtt_config_t config = { .broker_url = "mqtt://logger.example.com", .broker_port = 1883, .client_id = "data_logger_01", .keepalive = 120, .network_timeout_ms = 15000 }; mqtt_manager_init(&config, NULL); mqtt_manager_start(); sensor_reading_t reading; while (1) { if (mqtt_manager_is_connected()) { // Collect data from multiple sources reading.timestamp = (uint32_t)time(NULL); // Temperature sensor if (get_temperature(&reading.value) == ESP_OK) { strcpy(reading.source, "DHT22"); char json_data[256]; snprintf(json_data, sizeof(json_data), "{\"value\":%.2f,\"timestamp\":%u,\"source\":\"%s\"}", reading.value, reading.timestamp, reading.source); mqtt_manager_publish_string("data/temperature", json_data, 1, 0); } // Additional sensors... // Humidity, pressure, light, etc. } vTaskDelay(pdMS_TO_TICKS(60000)); // Log every minute } } ``` ## 🧩 Integration Examples ### With WiFi Manager ```c #include "mqtt_manager.h" #include "wifi_manager.h" void wifi_mqtt_integration(void) { // Initialize WiFi first esp_err_t ret = wifi_manager_init("MyWiFi", "password", wifi_event_callback); if (ret != ESP_OK) return; wifi_manager_start(); // Wait for WiFi connection if (wifi_manager_wait_for_connection(30000)) { printf("WiFi connected, starting MQTT...\n"); mqtt_config_t config = { .broker_url = "mqtt://local-broker", .client_id = "wifi_device" }; mqtt_manager_init(&config, mqtt_event_callback); mqtt_manager_start(); } else { printf("WiFi connection failed\n"); } } ``` ### With LED Status Indication ```c #include "mqtt_manager.h" #include "led_manager.h" void mqtt_status_callback(mqtt_status_t status, const char *topic, const char *data, int data_len) { switch (status) { case MQTT_STATUS_CONNECTING: led_manager_set_color_by_name("Orange", true); // Blinking orange break; case MQTT_STATUS_CONNECTED: led_manager_set_color_by_name("Green", false); // Solid green break; case MQTT_STATUS_DISCONNECTED: case MQTT_STATUS_ERROR: led_manager_set_color_by_name("Red", true); // Blinking red break; } } void mqtt_led_integration(void) { led_manager_init(GPIO_NUM_8); mqtt_config_t config = { .broker_url = "mqtt://broker.com", .client_id = "led_device" }; mqtt_manager_init(&config, mqtt_status_callback); mqtt_manager_start(); } ``` ## 🔍 Troubleshooting ### Common Issues 1. **Connection Timeouts** ```c // Increase network timeout mqtt_config_t config = { .broker_url = "mqtt://slow-broker.com", .network_timeout_ms = 30000, // 30 seconds .keepalive = 300 // 5 minutes }; ``` 2. **Authentication Failures** ```c // Verify credentials mqtt_config_t config = { .broker_url = "mqtt://secure-broker.com", .client_id = "unique_device_id", // Must be unique .username = "correct_username", .password = "correct_password" }; ``` 3. **Message Publishing Failures** ```c // Check connection before publishing if (mqtt_manager_is_connected()) { int msg_id = mqtt_manager_publish_string("test", "data", 1, 0); if (msg_id == -1) { ESP_LOGE("MQTT", "Publish failed"); mqtt_manager_reconnect(); } } ``` ### Network Issues **Intermittent Connections:** - Check WiFi stability - Increase keepalive interval - Monitor broker logs **Slow Publishing:** - Use QoS 0 for non-critical data - Reduce message frequency - Optimize payload size ### Debug Functions ```c void mqtt_debug_info(void) { mqtt_status_t status = mqtt_manager_get_status(); printf("MQTT Status: "); switch (status) { case MQTT_STATUS_DISCONNECTED: printf("DISCONNECTED\n"); break; case MQTT_STATUS_CONNECTING: printf("CONNECTING\n"); break; case MQTT_STATUS_CONNECTED: printf("CONNECTED\n"); break; case MQTT_STATUS_ERROR: printf("ERROR\n"); break; } if (mqtt_manager_is_connected()) { // Test publish int msg_id = mqtt_manager_publish_string("debug/test", "ping", 0, 0); printf("Test message ID: %d\n", msg_id); } } ``` ## 📄 License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## 🤝 Contributing 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/AmazingFeature`) 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) 4. Push to the branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request ## 📈 Version History See [CHANGELOG.md](CHANGELOG.md) for version history and changes. ## ⚡ Performance Notes - **Memory usage**: ~2KB RAM (including buffers) - **CPU impact**: Minimal, event-driven architecture - **Network efficiency**: Automatic reconnection with exponential backoff - **Message throughput**: Up to 100 messages/second (depending on QoS) - **Latency**: <100ms for QoS 0, <500ms for QoS 1/2 ## 🔗 Related Libraries - **[wifi_manager](../wifi_manager/README.md)** - WiFi connection management - **[led_manager](../led_manager/README.md)** - Status indication - **[dht22_sensor](../dht22_sensor/README.md)** - Temperature/humidity sensor ## 🎯 Use Cases - **IoT Sensor Networks** - Centralized data collection - **Home Automation** - Device control and monitoring - **Industrial IoT** - Equipment monitoring and alerts - **Smart Agriculture** - Environmental monitoring - **Remote Monitoring** - Asset tracking and status - **Data Logging** - Persistent sensor data collection