Building a Smart Door Unlock System with MQTT and ESP-IDF(ESP32) with Acknowledgement

29
0

Introduction:

In the rapidly evolving landscape of smart home technology, security remains a top priority for homeowners. A smart door unlock system leveraging MQTT (Message Queuing Telemetry Transport) and ESP-IDF (Espressif IoT Development Framework) not only ensures seamless access control but also adds an extra layer of sophistication to your home security setup. In this blog post, we’ll guide you through the process of creating a robust smart door unlock system with MQTT, utilizing ESP-IDF, and implementing acknowledgement for every pub-sub request.

The Foundation: Understanding MQTT

MQTT serves as the communication protocol for our smart door unlock system. It enables efficient communication between devices, ensuring a reliable and lightweight connection. The publish-subscribe model allows devices to exchange messages through a central broker.

Setting up MQTT Broker:

Begin by setting up an MQTT broker – the central hub for communication. You can use popular services like Mosquitto or set up your own broker using tools like RabbitMQ.

Check first part of Smart Door Unlock system to get more clarity of the project,

Leveraging ESP-IDF for Implementation:

ESP-IDF, developed by Espressif, provides a comprehensive framework for building IoT applications on ESP32 and ESP8266 platforms. Let’s dive into the steps to integrate ESP-IDF for our smart door unlock system.

1. ESP-IDF Installation:

Follow the official ESP-IDF installation guide to set up the development environment on your machine.

2. Configuring MQTT on ESP-IDF:

Integrate the MQTT library into your ESP-IDF project by including the necessary headers and configuring the MQTT parameters such as broker address, port, and client ID.

3. Implementing Pub-Sub Mechanism:

Develop the logic for both publishing (sending requests) and subscribing (receiving and acknowledging requests) on your ESP32 or ESP8266 device.

Acknowledgement: Ensuring Secure Communication

One crucial aspect of our smart door unlock system is the implementation of acknowledgment for every pub-sub request. This enhances the reliability and security of the system.

1. Acknowledgment Protocol:

Define a simple acknowledgment protocol to ensure that each request is received and processed successfully. Implement a mechanism to resend the request if an acknowledgment is not received within a specified time.

2. Error Handling:

Develop a robust error-handling mechanism to handle situations where acknowledgments are not received or when there is a communication failure. This ensures the system’s resilience in various scenarios.

Watch full video for more clarity,

https://youtu.be/5GPObHmhOZk

Full Program: Unlocking the Smart Door Unlock

Finally, let’s provide a snippet of the program to give you a head start in building your smart door unlock system with acknowledgement signal. For the complete code and detailed explanations, visit Smart Door Unlock System.

/* Smart Door Unlock with acknowledgement for MQTT (over TCP) Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "esp_log.h"
#include "mqtt_client.h"
#include "driver/gpio.h"

static const char *TAG = "MQTT_EXAMPLE";


static void log_error_if_nonzero(const char *message, int error_code)
{
    if (error_code != 0) {
        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

/*
 * @brief Event handler registered to receive MQTT events
 *
 *  This function is called by the MQTT client event loop.
 *
 * @param handler_args user data registered to the event.
 * @param base Event base for the handler(always MQTT Base in this example).
 * @param event_id The id for the received event.
 * @param event_data The data for the event, esp_mqtt_event_handle_t.
 */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        msg_id = esp_mqtt_client_publish(client, "/topic/door/status", "Locked", 0, 1, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

        msg_id = esp_mqtt_client_subscribe(client, "/topic/door/unlock", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        msg_id = esp_mqtt_client_subscribe(client, "/topic/door/status", 1);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        // msg_id = esp_mqtt_client_unsubscribe(client, "/topic/door/status");
        // ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;

    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        msg_id = esp_mqtt_client_publish(client, "/topic/door/unlock", "data", 0, 0, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);

        if (strstr(event->topic,"/topic/door/unlock")!=NULL)
        {
            if (strstr(event->data,"Open")!=NULL)
            {
                printf("Door Unlocked!!!");
                gpio_set_level(GPIO_NUM_4,1);
                vTaskDelay(100);
                gpio_set_level(GPIO_NUM_4,0);
                msg_id = esp_mqtt_client_publish(client, "/topic/door/status", "Unlocked", 0, 1, 0);
                ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

            }
            
        }
        
        // Smart Door Unlock with acknowledgement signal update
        if (strstr(event->topic,"/topic/door/status")!=NULL)
        {
            if (strstr(event->data,"Unlocked")!=NULL)
            {
                printf("Door Unlocked!!!");
                vTaskDelay(1000);
                msg_id = esp_mqtt_client_publish(client, "/topic/door/status", "Locked", 0, 1, 0);
                ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

            }
            
        }
        
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
            log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));

        }
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}

static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = CONFIG_BROKER_URL,
    };
#if CONFIG_BROKER_URL_FROM_STDIN
    char line[128];

    if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0) {
        int count = 0;
        printf("Please enter url of mqtt broker\n");
        while (count < 128) {
            int c = fgetc(stdin);
            if (c == '\n') {
                line[count] = '\0';
                break;
            } else if (c > 0 && c < 127) {
                line[count] = c;
                ++count;
            }
            vTaskDelay(10 / portTICK_PERIOD_MS);
        }
        mqtt_cfg.broker.address.uri = line;
        printf("Broker url: %s\n", line);
    } else {
        ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
        abort();
    }
#endif /* CONFIG_BROKER_URL_FROM_STDIN */

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(client);
}

void app_main(void)
{
    gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);

    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("outbox", ESP_LOG_VERBOSE);

    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());

    mqtt_app_start();
}

Use this application to setup MQTT for the device,

Smart Door Unlock System using ESP32 and MQTT

Conclusion:

Congratulations! You’ve just embarked on the journey of creating a state-of-the-art smart door unlock system using MQTT and ESP-IDF. For a comprehensive guide, including the full program and detailed explanations, head over to YourWebsite.com/SmartDoorUnlock.

Stay tuned for more exciting developments in the world of IoT and home automation. Your secure, smart home awaits!

Also, check out our other playlist Rasa ChatbotInternet of thingsDockerPython ProgrammingMachine LearningNatural Language ProcessingMQTTTech NewsESP-IDF etc.
Become a member of our social family on youtube here.
Stay tuned and Happy Learning. βœŒπŸ»πŸ˜ƒ
Happy coding, and may your NLP endeavors be both enlightening and rewarding! ❀️πŸ”₯πŸš€πŸ› οΈπŸ‘πŸ’‘

Leave a Reply