Turning Your ESP32 into an IoT Lock: A Hands-On Tutorial

This tutorial will guide you through the process of transforming an ESP32 into a functional IoT lock controlled via a Flutter app. You’ll learn about hardware setup, ESP32 programming, and Flutter app development, with detailed code snippets and explanations to build a fully operational system.

Part 1: Hardware Setup and ESP32 Programming

Hardware Required:

  • ESP32 development board
  • Solenoid lock or motorized lock
  • NPN transistor (e.g., 2N2222)
  • Diode (e.g., 1N4007 for EMF protection)
  • Power supply appropriate for the lock
  • Jumper wires and breadboard
  • 1kΩ resistor
  • (Optional) Pull-down resistor

ESP32 Circuit Setup:

  1. Connect the Solenoid Lock:
    • Connect the solenoid lock’s positive wire to the power supply’s positive terminal.
    • Connect the solenoid lock’s negative wire to the collector of the NPN transistor.
  2. Transistor Connections:
    • Connect the emitter of the NPN transistor to the ground of the power supply.
    • Connect the base of the NPN transistor to a GPIO pin on the ESP32 (e.g., GPIO 23) through a 1kΩ resistor.
  3. Diode Placement:
    • Place the diode across the solenoid’s terminals, with the cathode connected to the positive side.
  4. Optional:
    • Add a pull-down resistor between the GPIO pin and ground to prevent unintended triggering of the transistor due to floating states.

ESP32 Code:

  1. Install Necessary Tools:
    • Install Arduino IDE and add ESP32 support.
    • Install the PubSubClient library for MQTT communication.
  2. Programming the ESP32:
    • Connect to WiFi.
    • Connect to an MQTT broker.
    • Subscribe to a topic for receiving lock commands (e.g., lock/control).
    • Use a GPIO pin to control the lock.
#include <WiFi.h>
#include <PubSubClient.h>

// WiFi credentials
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

// MQTT Broker details
const char* mqtt_broker = "broker.hivemq.com";
const char* topic = "lock/control";
const char* mqtt_username = "user"; // Not needed for public brokers
const char* mqtt_password = "pass"; // Not needed for public brokers
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
    delay(10);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
    }
}

void callback(char* topic, byte* message, unsigned int length) {
    String messageTemp;
    for (int i = 0; i < length; i++) {
        messageTemp += (char)message[i];
    }
    if (messageTemp == "LOCK") {
        digitalWrite(23, HIGH);  // Lock the lock
    } else if (messageTemp == "UNLOCK") {
        digitalWrite(23, LOW);   // Unlock the lock
    }
}

void reconnect() {
    while (!client.connected()) {
        if (client.connect("ESP32Client", mqtt_username, mqtt_password)) {
            client.subscribe(topic);
        } else {
            client.loop();
            delay(5000);
        }
    }
}

void setup() {
    Serial.begin(115200);
    setup_wifi();
    client.setServer(mqtt_broker, mqtt_port);
    client.setCallback(callback);
    pinMode(23, OUTPUT); // Set GPIO 23 as output for lock control
}

void loop() {
    if (!client.connected()) {
        reconnect();
    }
    client.loop();
}
  1. Modify the callback function to control the lock:
    • Use digitalWrite(23, HIGH); to lock and digitalWrite(23, LOW); to unlock based on the received message.

Part 2: Flutter App Development

Flutter App Setup:

  1. Install Flutter SDK:
    • Ensure Flutter SDK is installed on your development machine.
  2. Create a New Project:
    • Create a new Flutter project using your preferred IDE or the command line.
  3. Add MQTT Client Package:
    • Open pubspec.yaml and add mqtt_client and optionally flutter_bloc for state management.
yamlCopy codedependencies:
  flutter:
    sdk: flutter
  mqtt_client: ^9.0.0
  flutter_bloc: ^7.0.0

Flutter MQTT Service:

  1. Create a Service for MQTT:
    • This service will manage the MQTT connection, subscription, and message publishing.
dartCopy codeimport 'package:mqtt_client/mqtt_client.dart' as mqtt;

class MQTTService {
  late mqtt.MqttClient client;
  late mqtt.MqttConnectionState connectionState;

  void connect() async {
    client = mqtt.MqttClient('broker.hivemq.com', '');
    client.port = 1883;
    client.keepAlivePeriod = 60;

    try {
      await client.connect();
    } catch (e) {
      print('Exception: $e');
      client.disconnect();
    }

    client.updates!.listen((List<mqtt.MqttReceivedMessage<mqtt.MqttMessage>> c) {
      final mqtt.MqttPublishMessage message = c[0].payload as mqtt.MqttPublishMessage;
      final payload = mqtt.MqttPublishPayload.bytesToStringAsString(message.payload.message);

      print('Received message:$payload from topic: ${c[0].topic}>');
    });
  }

  void publish(String topic, String message) {
    final builder = mqtt.MqttClientPayloadBuilder();
    builder.addString(message);
    client.publishMessage(topic, mqtt.MqttQos.exactlyOnce, builder.payload!);
  }
}

Flutter UI for Lock Control:

  1. Build a Simple UI:
    • Create a UI with buttons to send “LOCK” and “UNLOCK” commands to your ESP32 via MQTT.
dartCopy codeimport 'package:flutter/material.dart';
import 'mqtt_service.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final MQTTService _mqttService = MQTTService();

  @override
  void initState() {
    super.initState();
    _mqttService.connect();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('IoT Lock Control'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () => _mqttService.publish("lock/control", "LOCK"),
                child: Text('Lock'),
              ),
              ElevatedButton(
                onPressed: () => _mqttService.publish("lock/control", "UNLOCK"),
                child: Text('Unlock'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Conclusion

This tutorial has guided you through setting up an IoT lock with an ESP32 and controlling it via a Flutter app using MQTT. The ESP32 code handles the lock mechanism and communicates with an MQTT broker to receive commands, while the Flutter app acts as a client, sending lock/unlock commands. By following these steps, you can integrate hardware with mobile applications for IoT solutions.

Safety Note: Always be cautious when handling electrical components and power supplies to avoid injury or damage.

Final Testing:

Verify that the MQTT messages are being sent and received correctly.

Ensure your ESP32 is properly connected and powered.

Test the lock and unlock functionality using the Flutter app.