readme
This commit is contained in:
989
README.md
Normal file
989
README.md
Normal file
@@ -0,0 +1,989 @@
|
||||
# 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...
|
||||
}
|
||||
```
|
||||
|
||||
## 📚 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)
|
||||
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)
|
||||
- `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
|
||||
Reference in New Issue
Block a user