348 lines
9.8 KiB
C++
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();
|
|
}
|
|
|