Saeid Moghadam
Published © MIT

Soifgo – Bluetooth & MQTT IoT Controller

Control devices via Bluetooth and MQTT using ESP8266

IntermediateWork in progress5 hours86
Soifgo – Bluetooth & MQTT IoT Controller

Things used in this project

Story

Read more

Schematics

ESP8266_mqtt

Code

esp8266_mqtt

Arduino
https://soifgo.github.io/soifgo/tutorials/server/Esp8266_wifi_mqtt/esp8266_mqtt.html
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <PubSubClient.h>

ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);

const char* mqtt_server = "test.mosquitto.org";
const int mqtt_port = 1883;
const char* mqtt_recv_topic = "soifgo_send";

String ssid = "";
String password = "";
String ap_pass = "";

unsigned long lastCheck = 0;
const unsigned long checkInterval = 15000;
int reconnectAttempts = 0;
const int maxReconnectAttempts = 4;

void handleRoot() {
  String mac = WiFi.macAddress();
  String html = "<h1>WiFi Setup</h1>"
                "<p><b>MAC Address:</b> " + mac + "</p>"
                "<form action='/savewifi' method='POST'>"
                "WiFi SSID: <input type='text' name='ssid'><br>"
                "WiFi Password: <input type='text' name='pass'><br>"
                "<input type='submit' value='Save WiFi'>"
                "</form><hr>"
                "<form action='/saveap' method='POST'>"
                "AP SSID: <b>ESP_Config</b><br>"
                "AP Password: <input type='text' name='ap_pass' placeholder='min 8 chars'><br>"
                "<input type='submit' value='Save AP'>"
                "</form><hr>"
                "<form action='/reset' method='POST'>"
                "<input type='submit' value='Reset EEPROM & Restart'>"
                "</form>";
  server.send(200, "text/html", html);
}

void handleSaveWiFi() {
  ssid = server.arg("ssid");
  password = server.arg("pass");

  for (int i = 0; i < 200; i++) EEPROM.write(i, 0);

  EEPROM.write(0, ssid.length());
  for (int i = 0; i < ssid.length(); i++) EEPROM.write(i+1, ssid[i]);

  EEPROM.write(100, password.length());
  for (int i = 0; i < password.length(); i++) EEPROM.write(i+101, password[i]);

  EEPROM.commit();

  server.send(200, "text/html", "WiFi Saved! Restarting...");
  delay(1500);
  ESP.restart();
}

void handleSaveAP() {
  ap_pass = server.arg("ap_pass");

  if (ap_pass.length() < 8) {
    server.send(200, "text/html", "Error: Password must be at least 8 characters!");
    return;
  }

  for (int i = 200; i < 400; i++) EEPROM.write(i, 0);

  EEPROM.write(300, ap_pass.length());
  for (int i = 0; i < ap_pass.length(); i++) EEPROM.write(i+301, ap_pass[i]);

  EEPROM.commit();

  server.send(200, "text/html", "AP Password Saved! Restarting...");
  delay(2000);
  ESP.restart();
}

void handleReset() {
  for (int i = 0; i < 512; i++) {
    EEPROM.write(i, 0);
  }
  EEPROM.commit();

  server.send(200, "text/html", "EEPROM cleared! Restarting...");
  delay(2000);
  ESP.restart();
}

void loadCredentials() {
  int ssidLen = EEPROM.read(0);
  ssid = "";
  for (int i = 0; i < ssidLen; i++) ssid += char(EEPROM.read(i+1));

  int passLen = EEPROM.read(100);
  password = "";
  for (int i = 0; i < passLen; i++) password += char(EEPROM.read(i+101));

  int apPassLen = EEPROM.read(300);
  ap_pass = "";
  for (int i = 0; i < apPassLen; i++) ap_pass += char(EEPROM.read(i+301));
}

void connectWiFi() {
  loadCredentials();

  bool connected = false;

  if (ssid.length() > 0) {
    WiFi.begin(ssid.c_str(), password.c_str());
    Serial.print("Connecting to saved WiFi: ");
    Serial.println(ssid);
    int retries = 0;
    while (WiFi.status() != WL_CONNECTED && retries < 5) {
      delay(500);
      Serial.print(".");
      retries++;
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("\nConnected!");
      Serial.print("IP: ");
      Serial.println(WiFi.localIP());
      connected = true;
    } else {
      Serial.println("\nWiFi connect failed.");
    }
  }

  if (!connected) {
    if (ap_pass.length() < 8) ap_pass = "12345678";
    WiFi.softAP("ESP_Config", ap_pass.c_str());
    Serial.println("Started AP: ESP_Config, password: " + ap_pass);
    Serial.print("AP IP: ");
    Serial.println(WiFi.softAPIP());
  }
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  if (String(topic) == mqtt_recv_topic) {
    Serial.println(message);
  }
}

bool reconnectMQTT() {
  if (!client.connected()) {
    String clientId = "ESP8266Client-" + String(ESP.getChipId());
    if (client.connect(clientId.c_str())) {
      client.subscribe(mqtt_recv_topic);
      Serial.println("MQTT connected");
      reconnectAttempts = 0;
      return true;
    } else {
      reconnectAttempts++;
      Serial.println("MQTT reconnect failed");
      return false;
    }
  }
  return true;
}

void setup() {
  Serial.begin(115200);
  EEPROM.begin(512);    

  connectWiFi();

  server.on("/", handleRoot);
  server.on("/savewifi", handleSaveWiFi);
  server.on("/saveap", handleSaveAP);
  server.on("/reset", handleReset);
  server.begin();

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(mqttCallback);
}

void loop() {
  server.handleClient();

  if (WiFi.status() == WL_CONNECTED) {
    if (!client.connected()) {
      reconnectMQTT();
    }
    client.loop();
  }

  if (millis() - lastCheck > checkInterval) {
    lastCheck = millis();

    if (WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi lost  reconnecting...");
      connectWiFi();
    }

    if (!client.connected()) {
      if (!reconnectMQTT() && reconnectAttempts >= maxReconnectAttempts) {
        Serial.println("Too many fails  Restarting...");
        ESP.restart();
      }
    }
  }



  static String serialBuffer = "";
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '\n') {
      serialBuffer.trim();
      if (serialBuffer.length() > 0) {
        int sepIndex = serialBuffer.indexOf(':');
        if (sepIndex > 0) {
          String topicPart   = serialBuffer.substring(0, sepIndex);
          String payloadPart = serialBuffer.substring(sepIndex + 1);
          String fullTopic   = "soifgo_" + topicPart;
          client.publish(fullTopic.c_str(), payloadPart.c_str());
        }
      }
      serialBuffer = "";
    } else {
      serialBuffer += c;
    }
  }
}

Credits

Saeid Moghadam
2 projects • 0 followers
Electrical & electronics engineer sharing simple beginner‑level projects. Still learning, still improving. Feedback helps me grow.

Comments