2024-11-29 20:28:25 +00:00
|
|
|
#include "SerialService.h"
|
|
|
|
|
#include <WiFi.h>
|
|
|
|
|
#include <PubSubClient.h>
|
|
|
|
|
|
|
|
|
|
#ifndef MqttService_h
|
|
|
|
|
#define MqttService_h
|
|
|
|
|
|
2024-12-03 16:19:16 +00:00
|
|
|
#define WIFI_FAIXA "100"
|
|
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
const String TopicoRecepcao = "disp/tx/";
|
|
|
|
|
const String TopicoTransmissao = "disp/rx/";
|
|
|
|
|
|
2024-12-05 12:52:28 +00:00
|
|
|
unsigned long ultimaTentativaConexao = 0; // Tempo da última tentativa de conexão
|
|
|
|
|
const unsigned long intervaloTentativa = 5000; // 5 segundos
|
|
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
class MqttService {
|
|
|
|
|
private:
|
2024-12-03 16:19:16 +00:00
|
|
|
const char* server = "192.168." WIFI_FAIXA ".105";
|
2024-11-29 20:28:25 +00:00
|
|
|
int port = 1883;
|
2024-12-05 12:52:28 +00:00
|
|
|
const char* user = "";
|
|
|
|
|
const char* password = "";
|
2024-11-29 20:28:25 +00:00
|
|
|
String mqtt_mod_id; // Alterado para String
|
|
|
|
|
WiFiClient wifiClient;
|
|
|
|
|
PubSubClient mqttClient;
|
|
|
|
|
|
|
|
|
|
// Ponteiros para funções de callback
|
|
|
|
|
void (*messageCallback)(ProtocoloSerial) = nullptr;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
bool MqttIsConnected = false;
|
|
|
|
|
|
|
|
|
|
MqttService() : mqttClient(wifiClient) {
|
|
|
|
|
mqttClient.setServer(server, port);
|
2024-12-05 12:52:28 +00:00
|
|
|
mqttClient.setBufferSize(2048);
|
2024-11-29 20:28:25 +00:00
|
|
|
mqttClient.setCallback([this](char* topic, byte* payload, unsigned int length) {
|
|
|
|
|
this->processMessage(topic, payload, length);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setModID(const String& mqtt_id) {
|
|
|
|
|
mqtt_mod_id = mqtt_id; // Atribui diretamente a String
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setMessageCallback(void (*callback)(ProtocoloSerial)) {
|
|
|
|
|
messageCallback = callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool InicializarComunicacaoMqtt() {
|
2024-12-05 12:52:28 +00:00
|
|
|
// Verifica se já passou o intervalo necessário para uma nova tentativa
|
|
|
|
|
if (millis() - ultimaTentativaConexao < intervaloTentativa) {
|
|
|
|
|
PrintTela("Aguardando para próxima tentativa de conexão MQTT...");
|
|
|
|
|
return MqttIsConnected; // Retorna o estado atual sem tentar reconectar
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ultimaTentativaConexao = millis(); // Atualiza o tempo da última tentativa
|
|
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
connect();
|
2024-12-05 12:52:28 +00:00
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
if (MqttIsConnected) {
|
|
|
|
|
PrintTela("Tamanho máximo de mensagens: " + String(mqttClient.getBufferSize()));
|
2024-12-05 12:52:28 +00:00
|
|
|
LimparMensagensRetidas(TopicoRecepcao + mqtt_mod_id); // Limpa mensagens retidas
|
2024-11-29 20:28:25 +00:00
|
|
|
subscribe(TopicoRecepcao);
|
|
|
|
|
}
|
2024-12-05 12:52:28 +00:00
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
return MqttIsConnected;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void connect() {
|
|
|
|
|
while (!mqttClient.connected()) {
|
|
|
|
|
PrintTela("Conectando ao broker MQTT...", false);
|
|
|
|
|
//if (mqttClient.connect(mqtt_mod_id.c_str(), user, password)) {
|
|
|
|
|
if (mqttClient.connect(mqtt_mod_id.c_str())) {
|
|
|
|
|
PrintTela("Conectado ao broker MQTT!");
|
|
|
|
|
MqttIsConnected = true;
|
|
|
|
|
} else {
|
|
|
|
|
PrintTela("Falha ao conectar, rc=", false);
|
|
|
|
|
PrintTela((String)mqttClient.state());
|
|
|
|
|
MqttIsConnected = false;
|
|
|
|
|
delay(2000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-05 12:52:28 +00:00
|
|
|
void LimparMensagensRetidas(const String& topico) {
|
|
|
|
|
if (mqttClient.connected()) {
|
|
|
|
|
// Publica uma mensagem vazia com o flag Retain para limpar mensagens retidas
|
|
|
|
|
if (mqttClient.publish(topico.c_str(), "", true)) {
|
|
|
|
|
Serial.println("Mensagem retida limpa no tópico: " + topico);
|
|
|
|
|
} else {
|
|
|
|
|
Serial.println("Falha ao limpar mensagem retida no tópico: " + topico);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Serial.println("Broker MQTT desconectado, não foi possível limpar mensagens retidas.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
void subscribe(String topico) {
|
|
|
|
|
String fullTopic = topico + mqtt_mod_id; // Concatena o ID ao tópico base
|
|
|
|
|
mqttClient.subscribe(fullTopic.c_str());
|
|
|
|
|
PrintTela("Inscrito no tópico: ", false);
|
|
|
|
|
PrintTela(fullTopic);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void unsubscribe(String topico) {
|
|
|
|
|
String fullTopic = topico + mqtt_mod_id; // Concatena o ID ao tópico base
|
|
|
|
|
mqttClient.unsubscribe(fullTopic.c_str()); // Remove a inscrição de cada tópico
|
|
|
|
|
PrintTela("Desinscrito do tópico: ", false);
|
|
|
|
|
PrintTela(fullTopic);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool publish(String message) {
|
|
|
|
|
String fullTopic = TopicoTransmissao + mqtt_mod_id; // Concatena o ID ao tópico base
|
|
|
|
|
|
|
|
|
|
// Verifica se está conectado ao broker antes de tentar publicar
|
|
|
|
|
if (mqttClient.connected()) {
|
|
|
|
|
bool success = mqttClient.publish(fullTopic.c_str(), message.c_str(), true); // Publica a mensagem
|
|
|
|
|
if (success) {
|
|
|
|
|
PrintTela("Mensagem enviada com sucesso para ", false);
|
|
|
|
|
} else {
|
|
|
|
|
PrintTela("Falha ao enviar mensagem para ", false);
|
|
|
|
|
}
|
|
|
|
|
PrintTela(fullTopic, false); // Imprime o tópico completo para verificação
|
|
|
|
|
PrintTela(": ", false);
|
|
|
|
|
PrintTela(message);
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
} else {
|
|
|
|
|
PrintTela("Erro: Conexão com o broker MQTT perdida. Tentando reconectar...");
|
|
|
|
|
InicializarComunicacaoMqtt(); // Tenta reconectar
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void loop() {
|
2024-12-05 12:52:28 +00:00
|
|
|
if (mqttClient.connected()) {
|
2024-11-29 20:28:25 +00:00
|
|
|
mqttClient.loop();
|
|
|
|
|
}
|
2024-12-05 12:52:28 +00:00
|
|
|
else {
|
|
|
|
|
InicializarComunicacaoMqtt();
|
|
|
|
|
}
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EnviarDados(String Mod_ID, String Mensagem) {
|
|
|
|
|
if (MqttIsConnected) {
|
|
|
|
|
String ProtocoloEnvio = Mod_ID + SplitMessage + Mensagem;
|
|
|
|
|
publish(ProtocoloEnvio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Processa a mensagem recebida e aciona o callback correspondente
|
|
|
|
|
void processMessage(char* topic, byte* payload, unsigned int length) {
|
|
|
|
|
String topicStr(topic);
|
|
|
|
|
String message;
|
|
|
|
|
for (unsigned int i = 0; i < length; i++) {
|
|
|
|
|
message += (char)payload[i];
|
|
|
|
|
}
|
|
|
|
|
PrintTela("Mensagem recebida no tópico ", false);
|
|
|
|
|
PrintTela(topicStr, false);
|
|
|
|
|
PrintTela(": ", false);
|
|
|
|
|
PrintTela(message);
|
|
|
|
|
|
|
|
|
|
if (topicStr == TopicoRecepcao + mqtt_mod_id) {
|
|
|
|
|
std::vector<String> Partes = SplitString(message, SplitMessage);
|
|
|
|
|
if (Partes.size() == 4) {
|
|
|
|
|
ProtocoloSerial objeto;
|
|
|
|
|
objeto.idMensagem = Partes[0].toInt();
|
|
|
|
|
objeto.Mod_ID = Partes[1];
|
|
|
|
|
objeto.funcao = (F_Code)(Partes[2].toInt());
|
|
|
|
|
objeto.protocolo = Partes[3];
|
|
|
|
|
if (mqtt_mod_id == objeto.Mod_ID && messageCallback) {
|
|
|
|
|
messageCallback(objeto);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|