agrobot_base/Firmware/Modulos/Sensoriamento/Sensoriamento.ino

348 lines
9.8 KiB
C++

// Dispositivo: Sensoriamento
// Versão Firmware: 13
// 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"
#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<SensorTemperatura*> listaSensoresTemperaturaNTC;
std::vector<SensorCorrente*> listaSensoresCorrente;
std::vector<Sinaleiro*> listaSinaleiros;
std::vector<Rele*> listaReles;
std::vector<ServoFreio*> 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 : listaSensoresTemperaturaNTC) {
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 : listaSensoresTemperaturaNTC) {
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<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";
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 sNTC: {
SensorTemperatura::InicializarLista(listaSensoresTemperaturaNTC, 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<String> 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();
}