Blynk + MQTT : 3 lamps and 3 physical buttons

Hello friends.
After some research, I made everything work as I wanted it to.
Now I would like to improve.
I’m trying to add MQTT connection in the project.

NodeMCU + 3 Relays + 3 lamps + 3 physical buttons (push button)

Here is the code that is working:

#include <ESP8266WiFi.h> //INCLUSÃO DE BIBLIOTECA
#include <BlynkSimpleEsp8266.h> //INCLUSÃO DE BIBLIOTECA

char auth[] = "XXXXXXXXX"; //AUTH TOKEN (FORNECIDO PELO PROJETO NO BLYNK E POR E-MAIL)

char ssid[] = "XXXXXXXXXXX"; //VARIÁVEL QUE ARMAZENA O NOME DA REDE SEM FIO EM QUE VAI CONECTAR
char pass[] = "XXXXXXXXXXX"; //VARIÁVEL QUE ARMAZENA A SENHA DA REDE SEM FIO EM QUE VAI CONECTAR

const int relePin1 = D2; //PINO EM QUE O RELÉ ESTÁ CONECTADO
const int relePin2 = D3; //PINO EM QUE O RELÉ ESTÁ CONECTADO
const int relePin3 = D4; //PINO EM QUE O RELÉ ESTÁ CONECTADO

const int pulsadorPin1 = D5; //PINO EM QUE O PULSADOR ESTÁ CONECTADO
const int pulsadorPin2 = D6; //PINO EM QUE O PULSADOR ESTÁ CONECTADO
const int pulsadorPin3 = D7; //PINO EM QUE O PULSADOR ESTÁ CONECTADO

BlynkTimer timer; //OBJETO DO TIPO BlynkTimer

void checkPhysicalButton(); //FUNÇÃO checkPhysicalButton

int releState1 = HIGH; //ESTADO INICIAL DO RELÉ
int releState2 = HIGH; //ESTADO INICIAL DO RELÉ
int releState3 = HIGH; //ESTADO INICIAL DO RELÉ
int pulsadorState1 = HIGH; //ESTADO INICIAL DO PULSADOR
int pulsadorState2 = HIGH; //ESTADO INICIAL DO PULSADOR
int pulsadorState3 = HIGH; //ESTADO INICIAL DO PULSADOR

void setup(){
  
  Blynk.begin(auth, ssid, pass); //INICIALIZA A COMUNICAÇÃO BLYNK INFORMANDO OS PARÂMETROS

  pinMode(relePin1, OUTPUT); //DECLARA O PINO COMO SAÍDA
  pinMode(relePin2, OUTPUT); //DECLARA O PINO COMO SAÍDA
  pinMode(relePin3, OUTPUT); //DECLARA O PINO COMO SAÍDA
  pinMode(pulsadorPin1, INPUT_PULLUP); //DECLARA O PINO COMO ENTRADA E ATIVA O RESISTOR INTERNO DE PULL UP DO ESP
  pinMode(pulsadorPin2, INPUT_PULLUP); //DECLARA O PINO COMO ENTRADA E ATIVA O RESISTOR INTERNO DE PULL UP DO ESP
  pinMode(pulsadorPin3, INPUT_PULLUP); //DECLARA O PINO COMO ENTRADA E ATIVA O RESISTOR INTERNO DE PULL UP DO ESP
  digitalWrite(relePin1, releState1); //RELÉ RECEBE O ESTADO INICIAL
  digitalWrite(relePin2, releState2); //RELÉ RECEBE O ESTADO INICIAL
  digitalWrite(relePin3, releState3); //RELÉ RECEBE O ESTADO INICIAL

  timer.setInterval(100L, checkPhysicalButton); //DEFINE O INTERVALO DE 100 MILISSEGUNDOS(100L = 100 MILISSEGUNDOS) PARA EXECUÇÃO DA FUNÇÃO checkPhysicalButton
}

BLYNK_CONNECTED() { //FUNÇÃO QUE VERIFICA A CONEXÃO COM O SERVIDOR
  Blynk.syncVirtual(V2); //REQUISITA O ÚLTIMO ESTADO DO PINO VIRTUAL 2
  Blynk.syncVirtual(V3); //REQUISITA O ÚLTIMO ESTADO DO PINO VIRTUAL 3
  Blynk.syncVirtual(V4); //REQUISITA O ÚLTIMO ESTADO DO PINO VIRTUAL 4
}

BLYNK_WRITE(V2) { //FUNÇÃO QUE MUDA O ESTADO DO RELÉ QUANDO O BOTÃO NO APP É PRESISONADO
  releState1 = param.asInt(); //VARIÁVEL RESPONSÁVEL POR RECEBER E ARMAZENAR O DADO VINDO DO APP
  digitalWrite(relePin1, releState1); //ALTERNA O ESTADO ATUAL DO RELÉ
}
BLYNK_WRITE(V3) { //FUNÇÃO QUE MUDA O ESTADO DO RELÉ QUANDO O BOTÃO NO APP É PRESISONADO
  releState2 = param.asInt(); //VARIÁVEL RESPONSÁVEL POR RECEBER E ARMAZENAR O DADO VINDO DO APP
  digitalWrite(relePin2, releState2); //ALTERNA O ESTADO ATUAL DO RELÉ
}
BLYNK_WRITE(V4) { //FUNÇÃO QUE MUDA O ESTADO DO RELÉ QUANDO O BOTÃO NO APP É PRESISONADO
  releState3 = param.asInt(); //VARIÁVEL RESPONSÁVEL POR RECEBER E ARMAZENAR O DADO VINDO DO APP
  digitalWrite(relePin3, releState3); //ALTERNA O ESTADO ATUAL DO RELÉ
}

void checkPhysicalButton(){ //FUNÇÃO QUE VERIFICA O PRESSIONAMENTO DO PULSADOR
  
  if (digitalRead(pulsadorPin1) == LOW) { //SE LEITURA DO PULSADOR FOR IGUAL A LOW, FAZ
    
    if (pulsadorState1 != LOW) { //SE O ESTADO DO PULSADOR FOR DIFERENTE DE LOW (OU SEJA, HIGH), FAZ

      releState1 = !releState1; //ESTADO DO RELÉ, RECEBE O ESTADO ATUAL INVERTIDO
      digitalWrite(relePin1, releState1); //ALTERNA O ESTADO ATUAL DO RELÉ

      Blynk.virtualWrite(V2, releState1); //ATUALIZA NO WIDGET O ESTADO ATUAL (INDEPENDENTE SE FOI ACIONADO VIA APP OU PULSADOR)
    }
    pulsadorState1 = LOW; //ESTADO DO PULSADOR RECEBE LOW
  }else{ //SENÃO, FAZ
    pulsadorState1 = HIGH; //ESTADO DO PULSADOR RECEBE HIGH
  }
  
  if (digitalRead(pulsadorPin2) == LOW) { //SE LEITURA DO PULSADOR FOR IGUAL A LOW, FAZ
    
    if (pulsadorState2 != LOW) { //SE O ESTADO DO PULSADOR FOR DIFERENTE DE LOW (OU SEJA, HIGH), FAZ

      releState2 = !releState2; //ESTADO DO RELÉ, RECEBE O ESTADO ATUAL INVERTIDO
      digitalWrite(relePin2, releState2); //ALTERNA O ESTADO ATUAL DO RELÉ

      Blynk.virtualWrite(V3, releState2); //ATUALIZA NO WIDGET O ESTADO ATUAL (INDEPENDENTE SE FOI ACIONADO VIA APP OU PULSADOR)
    }
    pulsadorState2 = LOW; //ESTADO DO PULSADOR RECEBE LOW
  }else{ //SENÃO, FAZ
    pulsadorState2 = HIGH; //ESTADO DO PULSADOR RECEBE HIGH
  }
  
  if (digitalRead(pulsadorPin3) == LOW) { //SE LEITURA DO PULSADOR FOR IGUAL A LOW, FAZ
    
    if (pulsadorState3 != LOW) { //SE O ESTADO DO PULSADOR FOR DIFERENTE DE LOW (OU SEJA, HIGH), FAZ

      releState3 = !releState3; //ESTADO DO RELÉ, RECEBE O ESTADO ATUAL INVERTIDO
      digitalWrite(relePin3, releState3); //ALTERNA O ESTADO ATUAL DO RELÉ

      Blynk.virtualWrite(V4, releState3); //ATUALIZA NO WIDGET O ESTADO ATUAL (INDEPENDENTE SE FOI ACIONADO VIA APP OU PULSADOR)
    }
    pulsadorState3 = LOW; //ESTADO DO PULSADOR RECEBE LOW
  }else{ //SENÃO, FAZ
    pulsadorState3 = HIGH; //ESTADO DO PULSADOR RECEBE HIGH
  }
}

void loop(){
  
  Blynk.run(); //INICIALIZA O BLYNK
  timer.run(); //INICIALIZA O TIMER
}

And the frustrated attempt to introduce MQTT (Initially just publish):

#include <ESP8266WiFi.h> //INCLUSÃO DE BIBLIOTECA
#include <BlynkSimpleEsp8266.h> //INCLUSÃO DE BIBLIOTECA
#include <PubSubClient.h>

WiFiClient espClient;
PubSubClient client(espClient);

char auth[] = "XXXXXXXXXXX"; //AUTH TOKEN (FORNECIDO PELO PROJETO NO BLYNK E POR E-MAIL)

char ssid[] = "XXXXXXXXXXXXX"; //VARIÁVEL QUE ARMAZENA O NOME DA REDE SEM FIO EM QUE VAI CONECTAR
char pass[] = "XXXXXXXXXXX"; //VARIÁVEL QUE ARMAZENA A SENHA DA REDE SEM FIO EM QUE VAI CONECTAR
const char* mqtt_server = "192.168.0.127";
const char* mqtt_username = "mqtt";
const char* mqtt_password = "mqttpw";

const int relePin1 = D2; //PINO EM QUE O RELÉ ESTÁ CONECTADO
const int relePin2 = D3; //PINO EM QUE O RELÉ ESTÁ CONECTADO
const int relePin3 = D4; //PINO EM QUE O RELÉ ESTÁ CONECTADO

const int pulsadorPin1 = D5; //PINO EM QUE O PULSADOR ESTÁ CONECTADO
const int pulsadorPin2 = D6; //PINO EM QUE O PULSADOR ESTÁ CONECTADO
const int pulsadorPin3 = D7; //PINO EM QUE O PULSADOR ESTÁ CONECTADO

const char* state_topicv2 = "casa/escritorio/luz/state";
const char* state_topicv3 = "casa/varanda/luz/state";
const char* state_topicv4 = "casa/quintal/luz/state";
const char* set_topicv2 = "casa/escritorio/luz/set";
const char* set_topicv3 = "casa/varanda/luz/set";
const char* set_topicv4 = "casa/quintal/luz/set";

int ReCnctFlag;  // Reconnection Flag
int ReCnctCount = 0;  // Reconnection counter

BlynkTimer timer; //OBJETO DO TIPO BlynkTimer

void checkPhysicalButton(); //FUNÇÃO checkPhysicalButton

int releState1 = HIGH; //ESTADO INICIAL DO RELÉ
int releState2 = HIGH; //ESTADO INICIAL DO RELÉ
int releState3 = HIGH; //ESTADO INICIAL DO RELÉ
int pulsadorState1 = HIGH; //ESTADO INICIAL DO PULSADOR
int pulsadorState2 = HIGH; //ESTADO INICIAL DO PULSADOR
int pulsadorState3 = HIGH; //ESTADO INICIAL DO PULSADOR

// conectando ao servidor por MQTT
void connect_client() {
  // Espera ate estar conectado ao servidor
  while (!client.connected()) {
    // Cria cliente ID randômico
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Tentativa de conexão
    if (client.connected(clientId.c_str())) {
     
    } else {
      // Espera 5 segundo e tenta novamente
      delay(5000);
    }
  }
}

void setup(){
  
  Blynk.begin(auth, ssid, pass); //INICIALIZA A COMUNICAÇÃO BLYNK INFORMANDO OS PARÂMETROS
  client.setServer(mqtt_server, 1883); //Configura servidor

  pinMode(relePin1, OUTPUT); //DECLARA O PINO COMO SAÍDA
  pinMode(relePin2, OUTPUT); //DECLARA O PINO COMO SAÍDA
  pinMode(relePin3, OUTPUT); //DECLARA O PINO COMO SAÍDA
  pinMode(pulsadorPin1, INPUT_PULLUP); //DECLARA O PINO COMO ENTRADA E ATIVA O RESISTOR INTERNO DE PULL UP DO ESP
  pinMode(pulsadorPin2, INPUT_PULLUP); //DECLARA O PINO COMO ENTRADA E ATIVA O RESISTOR INTERNO DE PULL UP DO ESP
  pinMode(pulsadorPin3, INPUT_PULLUP); //DECLARA O PINO COMO ENTRADA E ATIVA O RESISTOR INTERNO DE PULL UP DO ESP
  digitalWrite(relePin1, releState1); //RELÉ RECEBE O ESTADO INICIAL
  digitalWrite(relePin2, releState2); //RELÉ RECEBE O ESTADO INICIAL
  digitalWrite(relePin3, releState3); //RELÉ RECEBE O ESTADO INICIAL

  timer.setInterval(100L, checkPhysicalButton); //DEFINE O INTERVALO DE 100 MILISSEGUNDOS(100L = 100 MILISSEGUNDOS) PARA EXECUÇÃO DA FUNÇÃO checkPhysicalButton
  
  // Verifica se está conectado ao servidor MQTT. Se nao, tenta conectar-se.
  if (!client.connected()) {
    connect_client();
  }
}

BLYNK_CONNECTED() { //FUNÇÃO QUE VERIFICA A CONEXÃO COM O SERVIDOR
  Blynk.syncVirtual(V2); //REQUISITA O ÚLTIMO ESTADO DO PINO VIRTUAL 2
  Blynk.syncVirtual(V3); //REQUISITA O ÚLTIMO ESTADO DO PINO VIRTUAL 3
  Blynk.syncVirtual(V4); //REQUISITA O ÚLTIMO ESTADO DO PINO VIRTUAL 4
}

BLYNK_WRITE(V2) { //FUNÇÃO QUE MUDA O ESTADO DO RELÉ QUANDO O BOTÃO NO APP É PRESISONADO
  releState1 = param.asInt(); //VARIÁVEL RESPONSÁVEL POR RECEBER E ARMAZENAR O DADO VINDO DO APP
  digitalWrite(relePin1, releState1); //ALTERNA O ESTADO ATUAL DO RELÉ
  client.publish(state_topicv2,releState1); //ALTERA O ESTADO ATUAL NO MQTT
}
BLYNK_WRITE(V3) { //FUNÇÃO QUE MUDA O ESTADO DO RELÉ QUANDO O BOTÃO NO APP É PRESISONADO
  releState2 = param.asInt(); //VARIÁVEL RESPONSÁVEL POR RECEBER E ARMAZENAR O DADO VINDO DO APP
  digitalWrite(relePin2, releState2); //ALTERNA O ESTADO ATUAL DO RELÉ
  client.publish(state_topicv3,releState2); //ALTERA O ESTADO ATUAL NO MQTT
}
BLYNK_WRITE(V4) { //FUNÇÃO QUE MUDA O ESTADO DO RELÉ QUANDO O BOTÃO NO APP É PRESISONADO
  releState3 = param.asInt(); //VARIÁVEL RESPONSÁVEL POR RECEBER E ARMAZENAR O DADO VINDO DO APP
  digitalWrite(relePin3, releState3); //ALTERNA O ESTADO ATUAL DO RELÉ
  client.publish(state_topicv4,releState3); //ALTERA O ESTADO ATUAL NO MQTT
}

void checkPhysicalButton(){ //FUNÇÃO QUE VERIFICA O PRESSIONAMENTO DO PULSADOR
  
  if (digitalRead(pulsadorPin1) == LOW) { //SE LEITURA DO PULSADOR FOR IGUAL A LOW, FAZ
    
    if (pulsadorState1 != LOW) { //SE O ESTADO DO PULSADOR FOR DIFERENTE DE LOW (OU SEJA, HIGH), FAZ

      releState1 = !releState1; //ESTADO DO RELÉ, RECEBE O ESTADO ATUAL INVERTIDO
      digitalWrite(relePin1, releState1); //ALTERNA O ESTADO ATUAL DO RELÉ
      client.publish(state_topicv2,releState1); //ALTERA O ESTADO ATUAL NO MQTT

      Blynk.virtualWrite(V2, releState1); //ATUALIZA NO WIDGET O ESTADO ATUAL (INDEPENDENTE SE FOI ACIONADO VIA APP OU PULSADOR)
    }
    pulsadorState1 = LOW; //ESTADO DO PULSADOR RECEBE LOW
  }else{ //SENÃO, FAZ
    pulsadorState1 = HIGH; //ESTADO DO PULSADOR RECEBE HIGH
  }
  
  if (digitalRead(pulsadorPin2) == LOW) { //SE LEITURA DO PULSADOR FOR IGUAL A LOW, FAZ
    
    if (pulsadorState2 != LOW) { //SE O ESTADO DO PULSADOR FOR DIFERENTE DE LOW (OU SEJA, HIGH), FAZ

      releState2 = !releState2; //ESTADO DO RELÉ, RECEBE O ESTADO ATUAL INVERTIDO
      digitalWrite(relePin2, releState2); //ALTERNA O ESTADO ATUAL DO RELÉ
      client.publish(state_topicv3,releState2); //ALTERA O ESTADO ATUAL NO MQTT

      Blynk.virtualWrite(V3, releState2); //ATUALIZA NO WIDGET O ESTADO ATUAL (INDEPENDENTE SE FOI ACIONADO VIA APP OU PULSADOR)
    }
    pulsadorState2 = LOW; //ESTADO DO PULSADOR RECEBE LOW
  }else{ //SENÃO, FAZ
    pulsadorState2 = HIGH; //ESTADO DO PULSADOR RECEBE HIGH
  }
  
  if (digitalRead(pulsadorPin3) == LOW) { //SE LEITURA DO PULSADOR FOR IGUAL A LOW, FAZ
    
    if (pulsadorState3 != LOW) { //SE O ESTADO DO PULSADOR FOR DIFERENTE DE LOW (OU SEJA, HIGH), FAZ

      releState3 = !releState3; //ESTADO DO RELÉ, RECEBE O ESTADO ATUAL INVERTIDO
      digitalWrite(relePin3, releState3); //ALTERNA O ESTADO ATUAL DO RELÉ
	  client.publish(state_topicv4,releState3); //ALTERA O ESTADO ATUAL NO MQTT

      Blynk.virtualWrite(V4, releState3); //ATUALIZA NO WIDGET O ESTADO ATUAL (INDEPENDENTE SE FOI ACIONADO VIA APP OU PULSADOR)
    }
    pulsadorState3 = LOW; //ESTADO DO PULSADOR RECEBE LOW
  }else{ //SENÃO, FAZ
    pulsadorState3 = HIGH; //ESTADO DO PULSADOR RECEBE HIGH
  }
}

void loop(){
  timer.run(); //INICIALIZA O TIMER
  if (Blynk.connected()) {  // If connected run as normal
    Blynk.run(); //INICIALIZA O BLYNK
  } else if (ReCnctFlag == 0) {  // If NOT connected and not already trying to reconnect, set timer to try to reconnect in 30 seconds
    ReCnctFlag = 1;  // Set reconnection Flag
    timer.setTimeout(30000L, []() {  // Lambda Reconnection Timer Function
      ReCnctFlag = 0;  // Reset reconnection Flag
      ReCnctCount++;  // Increment reconnection Counter
      Blynk.connect();  // Try to reconnect to the server
    });  // END Timer Function
  }
}

Can anybody help me?

Your connect_client function seems a bit stange to me. I use hard coded client IDs for my devices, but never use a connection test that involves using the client ID.
Your function would seem to generate a new random client ID each time it tests for an existing connection against that ID.

Also, I can’t see where you’re passing the MQTT username and password credentials to the MQTT server to set-up the connection (I am reading your code on a phone though).

Also, some versions of the pub sub client don’t work correctly when passing the username and password as variables in the connection string. The version I currently use needs them to be string literals (the values in quotation marks) within the actual connection string.

How are you planning to use the MQTT messages?
I use MQTT and Node-Red for virtually everything, but never mix Blynk and MQTT code on my devices. All the Blynk integration is done in Node-Red.

Pete.