// Dispositivo: Sensoriamento // Versão Firmware: 13 // Ultima atualização: 29/11/2024 // Atualização: Implementado MQTT #include #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\MqttService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\WifiService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorTemperaturaModel.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorCorrenteModel.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SinaleiroModel.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ServoFreioModel.h" // Configurações do IP estático IPAddress local_IP(192, 168, String(WIFI_FAIXA).toInt(), 12); // IP fixo para o ESP IPAddress gateway(192, 168, String(WIFI_FAIXA).toInt(), 1); // Gateway padrão IPAddress subnet(255, 255, 255, 0); // Máscara de sub-rede IPAddress primaryDNS(8, 8, 8, 8); // Servidor DNS primário (opcional) // Instancia o serviço MQTT MqttService mqttService; #define D_Code Sen #define VERSION 13 String Mod_ID = "Sen"; #define _pinoLED RGB_BUILTIN long _baudRate = 115200; bool Conectado = false; bool Verificando = false; int _TaxaAmostragem = 1000; volatile bool RequisitarDados = false; int latenciaLoop = 0; PinoModel _pinoSDA = PinoModel(21, CONTROLADOR, _INPUT); PinoModel _pinoSCL = PinoModel(22, CONTROLADOR, _INPUT); std::vector listaSensoresTemperatura; std::vector listaSensoresCorrente; std::vector listaSinaleiros; std::vector listaReles; std::vector listaServoFreios; void InicializarComunicacaoMQTT(bool RenovarConexao) { if (RenovarConexao) { mqttService.unsubscribe(TopicoRecepcao); delay(1000); } mqttService.setModID(Mod_ID); mqttService.InicializarComunicacaoMqtt(); mqttService.setMessageCallback(ProcessarProtocolo); } void setup() { Serial.begin(_baudRate); iniciarMCP(D_Code, Mod_ID, _pinoSDA.num, _pinoSCL.num, 0x20, false); InicializarConexaoWifi(local_IP, gateway, subnet, primaryDNS); if (!WifiIsConnected) { connectToWiFi(); if (WifiIsConnected) { PrintTela("Conectado com sucesso"); } else { PrintTela("Erro ao se conectar ao wifi"); ESP.restart(); } } delay(100); if (WifiIsConnected) { InicializarComunicacaoMQTT(false); } } void loop() { unsigned long startLoop = millis(); if (!RequisitarDados) { enviarLogsPeriodicamente(); } mqttService.loop(); delay(1); latenciaLoop = millis() - startLoop; } // Função para enviar logs do sensor periodicamente via MQTT unsigned long ultimoEnvioLogs = 0; const unsigned long intervaloEnvioLogs = 1000; // 1 segundo void enviarLogsPeriodicamente() { unsigned long tempoAtual = millis(); // Verifica se o intervalo de 5 segundos já passou if (tempoAtual - ultimoEnvioLogs >= intervaloEnvioLogs) { ultimoEnvioLogs = tempoAtual; // Atualiza o tempo do último envio enviarDadosSensores(); // Chama o método que já envia os dados do sensor via MQTT } } void enviarDadosSensores() { if (Conectado && !Verificando) { PrintTela("Atualizando dados dos sensores..."); // Aferir dados dos sensores for (auto* sensor : listaSensoresTemperatura) { sensor->AferirTemperatura(); } // Aferir dados dos sensores for (auto* sensor : listaSensoresCorrente) { sensor->AferirCorrente(); } // Aferir dados dos sensores for (auto* sensor : listaSinaleiros) { sensor->AtualizarLeitura(); } // Aferir dados dos sensores for (auto* sensor : listaReles) { sensor->AtualizarLeitura(); } String jsonString = MontarMensagemSensores() + String(EndLine); mqttService.EnviarDados(Mod_ID, jsonString); } } String MontarMensagemSensores() { // Criação de um objeto JSON dinâmico com tamanho adequado DynamicJsonDocument jsonDoc(2048); // Adicionar campos gerais jsonDoc["Conectado"] = Conectado; jsonDoc["Mod_ID"] = Mod_ID; jsonDoc["QualidadeWifi"] = WiFi.RSSI(); jsonDoc["LatenciaLoop"] = latenciaLoop; // Array JSON para sensores de temperatura JsonArray sensoresTemperaturaArray = jsonDoc.createNestedArray("SensoresTemperatura"); for (const auto* sensor : listaSensoresTemperatura) { JsonObject sensorData = sensoresTemperaturaArray.createNestedObject(); sensorData["Id"] = sensor->_ID; sensorData["Iniciado"] = sensor->Iniciado; sensorData["Leitura"] = sensor->leitura; } // Array JSON para sensores de corrente JsonArray sensoresCorrenteArray = jsonDoc.createNestedArray("SensoresCorrente"); for (const auto* sensor : listaSensoresCorrente) { JsonObject sensorData = sensoresCorrenteArray.createNestedObject(); sensorData["Id"] = sensor->_ID; sensorData["Iniciado"] = sensor->Iniciado; sensorData["BusVoltage"] = sensor->busVoltage; sensorData["ShuntVoltage"] = sensor->shuntVoltage; sensorData["Current"] = sensor->current; sensorData["Power"] = sensor->power; } // Array JSON para sinaleiros JsonArray sinaleirosArray = jsonDoc.createNestedArray("Sinaleiros"); for (const auto* sensor : listaSinaleiros) { JsonObject sensorData = sinaleirosArray.createNestedObject(); sensorData["Id"] = sensor->_ID; sensorData["Iniciado"] = sensor->Iniciado; sensorData["Leitura"] = sensor->_StatusLeitura; sensorData["Comando"] = sensor->_Status; } // Array JSON para reles JsonArray relesArray = jsonDoc.createNestedArray("Reles"); for (const auto* sensor : listaReles) { JsonObject sensorData = relesArray.createNestedObject(); sensorData["Id"] = sensor->_ID; sensorData["Iniciado"] = sensor->Iniciado; sensorData["Leitura"] = sensor->_Status; } // Array JSON para servo freios JsonArray servoFreiosArray = jsonDoc.createNestedArray("ServoFreios"); for (const auto* sensor : listaServoFreios) { JsonObject sensorData = servoFreiosArray.createNestedObject(); sensorData["Id"] = sensor->_ID; sensorData["Iniciado"] = sensor->Iniciado; sensorData["Angulo"] = sensor->_Angulo; } // Serializa o JSON para uma string String jsonString; serializeJson(jsonDoc, jsonString); int messageSize = jsonString.length(); PrintTela("Tamanho da mensagem: ", false); PrintTela((String)messageSize); return jsonString; } void ProcessarProtocolo(ProtocoloSerial Mensagem) { switch (Mensagem.funcao) { case Chk: ProcessarChk(Mensagem); break; case Cfg: ProcessarCfg(Mensagem); break; case Cmd: ProcessarCmd(Mensagem); break; case Req: ProcessarReq(Mensagem); break; } if (Mensagem.idMensagem > 0) { mqttService.EnviarDados(Mod_ID, MontarProtocoloMensagemRecebida(Mensagem.idMensagem)); } } void ProcessarChk(ProtocoloSerial Mensagem) { Verificando = true; mqttService.EnviarDados(Mod_ID, MontarProtocoloVerificacao(D_Code, VERSION, Conectado)); delay(2000); Verificando = false; } void ProcessarCfg(ProtocoloSerial Mensagem) { std::vector Partes = SplitString(Mensagem.protocolo, SplitParams); T_Code Tipo = (T_Code)(Partes[0].toInt()); if (Tipo == Mod) { bool Conectar = Partes[1] == "1"; _TaxaAmostragem = Partes[2].toInt(); RequisitarDados = Partes[3] == "1"; TiposBarramentos pinoSDAB = (TiposBarramentos)Partes[4].toInt(); int pinoSDA = Partes[5].toInt(); TiposBarramentos pinoSCLB = (TiposBarramentos)Partes[6].toInt(); int pinoSCL = Partes[7].toInt(); if (pinoSDA > -1 && pinoSCL > -1) { _pinoSDA = PinoModel(pinoSDA, pinoSDAB, _INPUT); _pinoSCL = PinoModel(pinoSCL, pinoSCLB, _INPUT); Wire.end(); Wire.begin(_pinoSDA.num, _pinoSCL.num); } vTaskDelay(pdMS_TO_TICKS(100)); Conectado = Conectar; Verificando = false; enviarDadosSensores(); } else { S_Code componente = (S_Code)Partes[1].toInt(); String config = Partes[2]; switch (componente) { case sTMP: { SensorTemperatura::InicializarLista(listaSensoresTemperatura, config, Mod_ID); break; } case sCOR: { SensorCorrente::InicializarLista(listaSensoresCorrente, config, Mod_ID); break; } case sLED: { Sinaleiro::InicializarLista(listaSinaleiros, config, Mod_ID); break; } case sRLE: { Rele::InicializarLista(listaReles, config, Mod_ID); break; } case sFRO: { ServoFreio::InicializarLista(listaServoFreios, config, Mod_ID); break; } } } } void ProcessarCmd(ProtocoloSerial Mensagem) { std::vector Partes = SplitString(Mensagem.protocolo, SplitParams); String ID = Partes[0]; S_Code componente = (S_Code)Partes[1].toInt(); switch (componente) { case sLED: { for (auto* _led : listaSinaleiros) { if (_led->_ID == ID) { _led->_Status = (StatusLED)Partes[2].toInt(); _led->_Qtd = Partes[3].toInt(); _led->_TempoMs = Partes[4].toInt(); _led->_PausaMs = Partes[5].toInt(); return; } } break; } case sRLE: { for (auto* _rele : listaReles) { if (_rele->_ID == ID) { Estado novoEstado = (Estado)Partes[2].toInt(); _rele->AtualizarStatus(novoEstado); } } break; } case sFRO: { for (auto* _freio : listaServoFreios) { if (_freio->_ID == ID) { int novoAngulo = Partes[2].toInt(); _freio->AtualizarAngulo(novoAngulo); } } break; } } } void ProcessarReq(ProtocoloSerial Mensagem) { enviarDadosSensores(); }