Conexão MQTT instável

Olá, estou com problemas em relação a conexão MQTT. Eu estou programando 4 sensores em um esp32 pela plataforma arduino IDE para conseguir ter a visualização dos valores em tempo real na plataforma da WegNology. Os valores chegam na plataforma, porém em um determinado momento a conexão no MQTT fica instável, e fica conectando e desconectando. Já tentei trocar o Wi-Fi, mas não resolve, segue a programação:

#include <WiFi.h>
#include <AsyncMqttClient.h>

// Informações de rede Wi-Fi
#define WIFI_SSID "FEM"
#define WIFI_PASSWORD "13@03xxxxx"

#define TdsSensorPin 34
#define VREF 3.3
#define SCOUNT 30
#define SOUND_SPEED 0.034

// Configurações MQTT
#define MQTT_HOST "broker.app.wnology.io"
#define MQTT_PORT 1883
#define MQTT_CLIENT_ID "652684f3a7915d9xxxxxx"
#define MQTT_USERNAME "22452d0e-bbed-4690-9d28-6xxxxxx"
#define MQTT_PASSWORD "c9b158314fb47ba2e433b77bde02d1a24a3c35a20423d2d9911f8f7xxxxx"

// Tópico MQTT para publicar os dados
#define MQTT_PUB_TDS "wnology/652684f3a7915d963xxxxxxx/state"
#define MQTT_PUB_TEMP "wnology/652684f3a7915d963xxxxxxx/state"
#define MQTT_PUB_DIST "wnology/652684f3a7915d963xxxxxxx/state"

// Intervalo de publicação dos dados em milissegundos
const long interval = 1000;
unsigned long previousMillis = 0;
float soma = 0;
const int nAmostras = 5;
double read_adc;

int analogBuffer[SCOUNT];
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0;
int copyIndex = 0;

const int pinoAnalogico = 35;
float averageVoltage = 0;
float tdsValue = 0;
float temperature = 25;

const int trigPin = 5;
const int echoPin = 18;
long duration;
float distanceCm;


// median filtering algorithm
int getMedianNum(int bArray[], int iFilterLen){
  int bTab[iFilterLen];
  for (byte i = 0; i<iFilterLen; i++)
    bTab[i] = bArray[i];
  int i, j, bTemp;
  for (j = 0; j < iFilterLen - 1; j++) {
    for (i = 0; i < iFilterLen - j - 1; i++) {
      if (bTab[i] > bTab[i + 1]) {
        bTemp = bTab[i];
        bTab[i] = bTab[i + 1];
        bTab[i + 1] = bTemp;
      }
    }
  }
  if ((iFilterLen & 1) > 0){
    bTemp = bTab[(iFilterLen - 1) / 2];
  }
  else {
    bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
  }
  return bTemp;
}

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

void connectToWifi() {
  Serial.println("Conectando ao Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void connectToMqtt() {
  Serial.println("Conectando ao MQTT...");
  mqttClient.connect();
}

void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[Evento Wi-Fi] evento: %d\n", event);
  switch (event) {
    case SYSTEM_EVENT_STA_GOT_IP:
      Serial.println("Wi-Fi conectado");
      Serial.println("Endereço IP: ");
      Serial.println(WiFi.localIP());
      connectToMqtt();
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("Wi-Fi desconectado");
      xTimerStop(mqttReconnectTimer, 0);
      xTimerStart(wifiReconnectTimer, 0);
      break;
  }
}

void onMqttConnect(bool sessionPresent) {
  Serial.println("Conectado ao MQTT.");
  Serial.print("Sessão presente: ");
  Serial.println(sessionPresent);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Desconectado do MQTT.");
  if (WiFi.isConnected()) {
    if (reason == AsyncMqttClientDisconnectReason::TLS_BAD_FINGERPRINT) {
      Serial.println("Erro de impressão digital TLS inválida.");
    } else if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
      Serial.println("Conexão TCP com o servidor MQTT perdida.");
    }
    xTimerStart(mqttReconnectTimer, 0);
    xTimerStart(mqttReconnectTimer, 0);
  }
}

void onMqttPublish(uint16_t packetId) {
  Serial.print("Publicação confirmada.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  pinMode(TdsSensorPin, INPUT);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input

  mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
  wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));

  WiFi.onEvent(WiFiEvent);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  mqttClient.setClientId(MQTT_CLIENT_ID);
  mqttClient.setCredentials(MQTT_USERNAME, MQTT_PASSWORD);

  connectToWifi();
}

void loop() {
  static unsigned long analogSampleTimepoint = millis();

  if (millis() - analogSampleTimepoint > 40U) {
    analogSampleTimepoint = millis();
    analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin);
    analogBufferIndex++;
    if (analogBufferIndex == SCOUNT) {
      analogBufferIndex = 0;
    }
  }

  static unsigned long printTimepoint = millis();

  if (millis() - printTimepoint > 800U) {
    printTimepoint = millis();
    for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++) {
      analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
      averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 4096.0;
      float compensationCoefficient = 1.0 + 0.02 * (temperature - 25.0);
      float compensationVoltage = averageVoltage / compensationCoefficient;
      tdsValue = (133.42 * compensationVoltage * compensationVoltage * compensationVoltage - 255.86 * compensationVoltage * compensationVoltage + 857.39 * compensationVoltage) * 0.5;
      float ecValue = tdsValue * 2 / 100;
      Serial.print("TDS Value:");
      Serial.print(tdsValue, 0);
      Serial.println("ppm");
      Serial.print("Valor de EC:");
      Serial.print(ecValue, 2);
      Serial.println("mS/cm");

      soma = 0;
      for (int i = 0; i < nAmostras; i++) {
        soma += analogRead(pinoAnalogico);
      }
      read_adc = soma / nAmostras;
      Serial.print("ADC=");
      Serial.print(read_adc);
      Serial.println();

      unsigned long currentMillis = millis();

      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        // Leitura do sensor LM36
        int valorAnalogico = analogRead(pinoAnalogico);
        float tensao = ((valorAnalogico * 0.00080566)+ 0.13);
        float temp = ((tensao - 0.5) / 0.01);

        Serial.print("Temperatura (LM36): ");
        Serial.print(temp);
        Serial.println("C");

        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
       
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
  
  duration = pulseIn(echoPin, HIGH);
  
  distanceCm = duration * SOUND_SPEED/2;
  
  Serial.print("Distance (cm): ");
  Serial.println(distanceCm);
  
  delay(1000);

        // Formata os dados em JSON para o sensor TDS
        String jsonTDS = "{\"data\": {\"tds\": " + String(tdsValue) + ", \"ec\": " + String(ecValue)+ "} }";
        char jsonBufferTDS[jsonTDS.length() + 1];
        jsonTDS.toCharArray(jsonBufferTDS, sizeof(jsonBufferTDS));

        // Formata os dados em JSON para o sensor LM36
        String jsonTemp = "{\"data\": {\"temperature\": " + String(temp) + "} }";
        char jsonBufferTemp[jsonTemp.length() + 1];
        jsonTemp.toCharArray(jsonBufferTemp, sizeof(jsonBufferTemp));

        // Formata os dados em JSON para o sensor HCSR-04
        String jsonDist = "{\"data\": {\"distance\": " + String(distanceCm) + "} }";
        char jsonBufferDist[jsonDist.length() + 1];
        jsonDist.toCharArray(jsonBufferDist, sizeof(jsonBufferDist));

        // Publica os dados MQTT
        mqttClient.publish(MQTT_PUB_TDS, 0, false, jsonBufferTDS);
        mqttClient.publish(MQTT_PUB_TEMP, 0, false, jsonBufferTemp);
        mqttClient.publish(MQTT_PUB_DIST, 0, false, jsonBufferDist);
      }
    }
  }
}


Consegue me ajudar?

1 Curtida

Bom dia Gabriel, tudo bem?

Poderia me informar de quanto em quanto tempo os dados estão subindo para a plataforma?
Pelo seu código são 3 variáveis, correto?

1 Curtida

Isso mesmo, são 3 variáveis e as informações são mandadas de segundo em segundo. Tem alguma ideia do que posso fazer??

1 Curtida

Boa tarde, Gabriel!

A desconexão pode ocorrer devido a várias situações.
Analisando seu código, me parece ele faz ingestão excessiva de dados, que vamos explicar adiante.
Você pode consultar em nossa documentação a listagem completa dos motivos de desconexão:

Vamos analisar duas causas que podem ocorrer:

1 - Alta taxa de ingestão de dados.
erro: Connection <outbound|inbound> throughput limit exceeded :
Temos o limite de 30 mensagens a cada 15 segundos, ou seja, analisando seu código (posso estar enganado), mas me parece que você “dispara” 3 payloads por segundo, então já ultrapassa este limite, veja a documentação:

Você pode disparar 1 só payload com as 3 temperaturas juntas.
Tente montar algo assim:

{ "data" 
   { "tds" : valor_TDS , 
     "temperature" :  valor_Temperatura , 
     "distance" ; valor_Distancia
   } 
}

2 - keepalive timeout
Muito provavelmente seu problema é o item 1, mas vale trazermos esta informação aqui.
É importante saber a configuração deste timeout “no seu device”.
O Keepalive timeout força uma espécie de PING que seu device precisa enviar para informar que “está vivo”, caso contrário, o servidor irá fechar a comunicação.

No mesmo link acima, na documentação é citado este timeout, que na Plataforma está em 90 segundos (por isto que acredito que seu problema seja o Item1, visto que seu device comunica a cada segundo).

Quando se utiliza bibliotecas de Arduino para ESP32 ou ESP8266, é necessário saber como está ajustada esta variável.

existem bibliotecas nas quais você pode ajustar este valor, por exemplo:

client.setKeepAlive( MQTT_KEEPALIVE );

Outras causas da desconexão ocorrem, como a própria renovação de conexão em redes de telefonia, que ocorre com certa frequência, causando quedas durante o dia.

2 Curtidas