2024-01-03 10:52:37 +00:00
|
|
|
// Dispositivo: Atuador
|
2025-02-03 19:54:39 +00:00
|
|
|
// Versão Firmware: 8
|
|
|
|
|
// Ultima atualização: 29/11/2024
|
|
|
|
|
// Atualização: Implementado MQTT
|
|
|
|
|
|
|
|
|
|
#include <ArduinoJson.h>
|
|
|
|
|
#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"
|
2024-01-23 17:10:34 +00:00
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
|
2024-04-02 18:33:15 +00:00
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
|
2025-02-03 19:54:39 +00:00
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
|
|
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel.h"
|
|
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\BombaPressurizadoraModel.h"
|
|
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorFluxoModel.h"
|
|
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorMassaModel.h"
|
|
|
|
|
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorPressaoModel.h"
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Configurações do IP estático
|
|
|
|
|
IPAddress local_IP(192, 168, String(WIFI_FAIXA).toInt(), 13); // 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)
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Instancia o serviço MQTT
|
|
|
|
|
MqttService mqttService;
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
#define D_Code Atu
|
|
|
|
|
#define VERSION 8
|
|
|
|
|
const String Mod_ID = "Atu";
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
#define _pinoLED RGB_BUILTIN
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
long _baudRate = 115200;
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
bool Conectado = false;
|
|
|
|
|
bool Verificando = false;
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
int _TaxaAmostragem = 1000;
|
|
|
|
|
volatile bool RequisitarDados = false;
|
|
|
|
|
int latenciaLoop = 0;
|
2024-02-29 20:01:02 +00:00
|
|
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
std::vector<Rele*> listaBicos;
|
|
|
|
|
std::vector<BombaPressurizadora*> listaBombas;
|
|
|
|
|
std::vector<SensorFluxo*> listaSensoresFluxo;
|
|
|
|
|
std::vector<SensorMassa*> listaSensoresMassa;
|
|
|
|
|
std::vector<SensorPressao*> listaSensoresPressao;
|
2024-02-29 20:01:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void InicializarComunicacaoMQTT(bool RenovarConexao) {
|
|
|
|
|
if (RenovarConexao) {
|
|
|
|
|
mqttService.unsubscribe(TopicoRecepcao);
|
|
|
|
|
delay(1000);
|
|
|
|
|
}
|
|
|
|
|
mqttService.setModID(Mod_ID);
|
|
|
|
|
mqttService.InicializarComunicacaoMqtt();
|
|
|
|
|
mqttService.setMessageCallback(ProcessarProtocolo);
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void setup() {
|
|
|
|
|
Serial.begin(_baudRate);
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
InicializarConexaoWifi(local_IP, gateway, subnet, primaryDNS);
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
if (!WifiIsConnected) {
|
|
|
|
|
connectToWiFi();
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
if (WifiIsConnected) {
|
|
|
|
|
PrintTela("Conectado com sucesso");
|
2024-04-02 18:33:15 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
else {
|
|
|
|
|
PrintTela("Erro ao se conectar ao wifi");
|
|
|
|
|
ESP.restart();
|
2024-04-02 18:33:15 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
delay(100);
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
if (WifiIsConnected) {
|
|
|
|
|
InicializarComunicacaoMQTT(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void loop() {
|
|
|
|
|
unsigned long startLoop = millis();
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
if (!RequisitarDados) {
|
|
|
|
|
enviarLogsPeriodicamente();
|
|
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
mqttService.loop();
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
for (auto* bomba : listaBombas) {
|
|
|
|
|
bomba->Loop();
|
|
|
|
|
}
|
|
|
|
|
for (auto* sensor : listaSensoresFluxo) {
|
|
|
|
|
sensor->Loop();
|
|
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
delay(1);
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
latenciaLoop = millis() - startLoop;
|
|
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// 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
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
enviarDadosSensores(); // Chama o método que já envia os dados do sensor via MQTT
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void enviarDadosSensores() {
|
|
|
|
|
if (Conectado && !Verificando) {
|
|
|
|
|
PrintTela("Atualizando dados dos sensores...");
|
2024-04-02 18:33:15 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Aferir dados dos sensores
|
|
|
|
|
for (auto* bico : listaBicos) {
|
|
|
|
|
bico->AtualizarLeitura();
|
2024-04-02 18:33:15 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Aferir dados dos sensores
|
|
|
|
|
for (auto* sensor : listaSensoresFluxo) {
|
|
|
|
|
sensor->AtualizarLeitura();
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Aferir dados dos sensores
|
|
|
|
|
for (auto* sensor : listaSensoresMassa) {
|
|
|
|
|
sensor->RequisitarDados();
|
2024-04-02 18:33:15 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Aferir dados dos sensores
|
|
|
|
|
for (auto* sensor : listaSensoresPressao) {
|
|
|
|
|
sensor->RequisitarDados();
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
String jsonString = MontarMensagemSensores() + String(EndLine);
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
mqttService.EnviarDados(Mod_ID, jsonString);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
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 bicos pulverizadores
|
|
|
|
|
JsonArray bicosArray = jsonDoc.createNestedArray("BicosPulverizadores");
|
|
|
|
|
for (const auto* sensor : listaBicos) {
|
|
|
|
|
JsonObject sensorData = bicosArray.createNestedObject();
|
|
|
|
|
sensorData["Id"] = sensor->_ID;
|
|
|
|
|
sensorData["Iniciado"] = sensor->Iniciado;
|
|
|
|
|
sensorData["Leitura"] = sensor->_Status;
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Array JSON para bombas pressurizadoras
|
|
|
|
|
JsonArray bombasArray = jsonDoc.createNestedArray("BombasPressurizadoras");
|
|
|
|
|
for (const auto* sensor : listaBombas) {
|
|
|
|
|
JsonObject sensorData = bombasArray.createNestedObject();
|
|
|
|
|
sensorData["Id"] = sensor->_ID;
|
|
|
|
|
sensorData["Iniciado"] = sensor->Iniciado;
|
|
|
|
|
sensorData["Estado"] = sensor->EstadoLeitura;
|
|
|
|
|
sensorData["Potencia"] = sensor->PercentualPotenciaLeitura;
|
|
|
|
|
sensorData["PressaoSP"] = sensor->_PressaoSP;
|
|
|
|
|
sensorData["Pressao"] = sensor->sensorPressao->Pressao;
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Array JSON para sensores de fluxo
|
|
|
|
|
JsonArray sensoresFluxoArray = jsonDoc.createNestedArray("SensoresFluxo");
|
|
|
|
|
for (const auto* sensor : listaSensoresFluxo) {
|
|
|
|
|
JsonObject sensorData = sensoresFluxoArray.createNestedObject();
|
|
|
|
|
sensorData["Id"] = sensor->_ID;
|
|
|
|
|
sensorData["Iniciado"] = sensor->Iniciado;
|
|
|
|
|
sensorData["Pulsos"] = sensor->_PulsosLeitura;
|
|
|
|
|
sensorData["Periodo"] = sensor->_PeriodoTotalLeitura;
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Array JSON para sensores de massa
|
|
|
|
|
JsonArray sensoresMassaArray = jsonDoc.createNestedArray("SensoresMassa");
|
|
|
|
|
for (const auto* sensor : listaSensoresMassa) {
|
|
|
|
|
JsonObject sensorData = sensoresMassaArray.createNestedObject();
|
|
|
|
|
sensorData["Id"] = sensor->_ID;
|
|
|
|
|
sensorData["Iniciado"] = sensor->Iniciado;
|
|
|
|
|
sensorData["Leitura"] = sensor->leituraMassa;
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Array JSON para sensores de pressao
|
|
|
|
|
JsonArray sensoresPressaoArray = jsonDoc.createNestedArray("SensoresPressao");
|
|
|
|
|
for (const auto* sensor : listaSensoresPressao) {
|
|
|
|
|
JsonObject sensorData = sensoresPressaoArray.createNestedObject();
|
|
|
|
|
sensorData["Id"] = sensor->_ID;
|
|
|
|
|
sensorData["Iniciado"] = sensor->Iniciado;
|
|
|
|
|
sensorData["Pressao"] = sensor->Pressao;
|
|
|
|
|
sensorData["Leitura"] = sensor->leitura;
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
// Serializa o JSON para uma string
|
|
|
|
|
String jsonString;
|
|
|
|
|
serializeJson(jsonDoc, jsonString);
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
int messageSize = jsonString.length();
|
|
|
|
|
PrintTela("Tamanho da mensagem: ", false);
|
|
|
|
|
PrintTela((String)messageSize);
|
2024-01-03 10:52:37 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
return jsonString;
|
|
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
|
|
|
|
|
|
2024-02-29 20:01:02 +00:00
|
|
|
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
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;
|
|
|
|
|
}
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
if (Mensagem.idMensagem > 0) {
|
|
|
|
|
EnviarDadosSerial(Mod_ID, MontarProtocoloMensagemRecebida(Mensagem.idMensagem));
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void ProcessarChk(ProtocoloSerial Mensagem) {
|
|
|
|
|
Verificando = true;
|
|
|
|
|
mqttService.EnviarDados(Mod_ID, MontarProtocoloVerificacao(D_Code, VERSION, Conectado));
|
|
|
|
|
delay(2000);
|
|
|
|
|
Verificando = false;
|
|
|
|
|
}
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void ProcessarCfg(ProtocoloSerial Mensagem) {
|
|
|
|
|
std::vector<String> 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";
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
|
|
|
Conectado = Conectar;
|
|
|
|
|
Verificando = false;
|
2024-02-29 20:01:02 +00:00
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
enviarDadosSensores();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
S_Code componente = (S_Code)Partes[1].toInt();
|
|
|
|
|
String config = Partes[2];
|
|
|
|
|
|
|
|
|
|
switch (componente) {
|
|
|
|
|
case sBIC: {
|
|
|
|
|
Rele::InicializarLista(listaBicos, config, Mod_ID);
|
|
|
|
|
break;
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
case sBMB: {
|
|
|
|
|
BombaPressurizadora::InicializarLista(listaBombas, config, Mod_ID, listaSensoresPressao);
|
|
|
|
|
break;
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
case sFLX: {
|
|
|
|
|
SensorFluxo::InicializarLista(listaSensoresFluxo, config, Mod_ID);
|
|
|
|
|
break;
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
case sMAS: {
|
|
|
|
|
SensorMassa::InicializarLista(listaSensoresMassa, config, Mod_ID);
|
|
|
|
|
break;
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
case sPRS: {
|
|
|
|
|
SensorPressao::InicializarLista(listaSensoresPressao, config, Mod_ID);
|
|
|
|
|
break;
|
2024-02-29 20:01:02 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-02 18:33:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-03 19:54:39 +00:00
|
|
|
void ProcessarCmd(ProtocoloSerial Mensagem) {
|
|
|
|
|
std::vector<String> Partes = SplitString(Mensagem.protocolo, SplitParams);
|
|
|
|
|
String ID = Partes[0];
|
|
|
|
|
S_Code componente = (S_Code)Partes[1].toInt();
|
|
|
|
|
|
|
|
|
|
switch (componente) {
|
|
|
|
|
case sBIC: {
|
|
|
|
|
for (auto* _rele : listaBicos) {
|
|
|
|
|
if (_rele->_ID == ID) {
|
|
|
|
|
Estado novoEstado = (Estado)Partes[2].toInt();
|
|
|
|
|
_rele->AtualizarStatus(novoEstado);
|
2024-01-03 10:52:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
break;
|
2024-01-03 10:52:37 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
case sBMB: {
|
|
|
|
|
for (auto* _bomba : listaBombas) {
|
|
|
|
|
if (_bomba->_ID == ID) {
|
|
|
|
|
_bomba->_EstadoControle = (Estado)(Partes[2].toInt());
|
|
|
|
|
_bomba->_PressaoSP = Partes[3].toDouble();
|
|
|
|
|
_bomba->AlterarStatusBomba();
|
2024-04-02 18:33:15 +00:00
|
|
|
}
|
2024-01-03 10:52:37 +00:00
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
break;
|
2024-01-03 10:52:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-03 19:54:39 +00:00
|
|
|
|
|
|
|
|
void ProcessarReq(ProtocoloSerial Mensagem) {
|
|
|
|
|
enviarDadosSensores();
|
|
|
|
|
}
|
|
|
|
|
|