agrobot_base/AgroBase/AgroBase/Models/Modules/AtuadorModel.cs

1347 lines
54 KiB
C#
Raw Normal View History

using AgroBase.Services;
2024-01-03 10:52:37 +00:00
using System;
using System.Collections.Generic;
2024-10-29 19:53:27 +00:00
using System.Drawing;
2024-01-03 10:52:37 +00:00
using System.Linq;
using System.Threading.Tasks;
2024-10-29 19:53:27 +00:00
using System.Windows.Forms;
2024-07-26 19:54:25 +00:00
using static AgroBase.Models.Enums;
2024-01-03 10:52:37 +00:00
namespace AgroBase.Models.Modules
{
public class AtuadorModel : DispositivoBaseModel
{
2025-04-09 21:11:40 +00:00
public T_Code Dispositivo { get; set; } = T_Code.Atu;
public string Modulo_ID { get; set; } = T_Code.Atu.ToString();
2025-05-01 18:27:01 +00:00
public byte _EnderecoCAN_Tx { get; set; } = 0x13;
public byte _EnderecoCAN_Rx { get; set; } = 0x14;
2025-04-09 21:11:40 +00:00
public int _TaxaAmostragem { get; set; } = 1000;
public bool RequisitarDados { get; set; } = true;
public static int PingsConsiderarConexao { get; set; } = 5;
public static int TempoLimiteConexao
{
get
{
return PingsConsiderarConexao * (Variaveis.OperacaoEmAndamento?.DispSen?._TaxaAmostragem ?? 1000);
}
}
public bool ConexaoAtiva
2025-04-09 21:11:40 +00:00
{
get
{
return VariaveisOperacao.Operadores.ModulosSaude.Any(x => x.modulo == Dispositivo && x.status == StatusModulo.Operante);
2025-04-09 21:11:40 +00:00
}
}
2024-04-15 10:57:37 +00:00
public static PinoutDataModel Pinout { get; set; }
2024-04-01 11:03:25 +00:00
public static List<FuncoesPinout> Funcoes { get; set; } = new List<FuncoesPinout>()
2024-04-15 10:57:37 +00:00
{
2024-04-01 11:03:25 +00:00
FuncoesPinout.SDA,
FuncoesPinout.SCL,
};
public int QuantidadeBicos { get; set; } = 4;
public double DensidadeHerbicida { get; set; } = 1.1;
2024-01-03 10:52:37 +00:00
public List<AtuadorBicoModel> BicosPulverizadores { get; set; } = new List<AtuadorBicoModel>();
public List<AtuadorBombaModel> BombasPressurizadoras { get; set; } = new List<AtuadorBombaModel>();
public List<SensorModel> Sensores { get; set; } = new List<SensorModel>();
public AtuadorBombaModel BombaPressurizadora
{
get
{
return BombasPressurizadoras.FirstOrDefault();
}
}
public string ScriptDeteccaoErvas { get; set; } = PythonService.ScriptWeedDetector;
2024-04-01 11:03:25 +00:00
public AsyncTaskTimerModel tmrRegistrador;
2024-12-05 12:52:28 +00:00
private int _TempoReconexaoComponentes = 5;
private int _VezesLeituraReconexao = 0;
public AtuadorMensagemJsonModel DadosLeitura { get; set; } = new AtuadorMensagemJsonModel();
2025-04-09 21:11:40 +00:00
public AtuHandler _AtuHandler = new AtuHandler();
2024-04-01 11:03:25 +00:00
#region MASSA
public double _MassaRef { get; set; } = 0.8;
public double _MassaLeituraRef { get; set; } = 40876.37;
public double _MassaLeituraExtra { get; set; } = 1895800; // 2015000.0;
public double MassaReservatorio
{
get
{
return Sensores.FirstOrDefault(x => x.Componente == S_Code.sMAS)?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Massa)?.atual?.valor ?? 0;
2024-04-01 11:03:25 +00:00
}
}
public double VolumeReservatorio
{
get
{
return MassaReservatorio / DensidadeHerbicida;
}
}
public double PercentualReservatorio
{
get
{
return VolumeReservatorio / Variaveis.OperacaoEmAndamento.CapacidadeReservatorio * 100.0;
2024-04-01 11:03:25 +00:00
}
}
#endregion
#region VAZAO
public double VolumeVazaoAferido { get; set; } = 0;
public double _FluxoMlRef { get; set; } = 600;
public double _FluxoPulsoRef { get; set; } = 538;
2024-12-05 12:52:28 +00:00
public double VazaoFluxoMLpSInstantanea
{
2024-04-01 11:03:25 +00:00
get
{
return Sensores.FirstOrDefault(x => x.Componente == S_Code.sFLX)?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Fluxo)?.atual?.valor ?? 0;
2024-04-01 11:03:25 +00:00
}
}
2024-12-05 12:52:28 +00:00
private double _somaVazao; // Acumula a soma da vazão para calcular a média
private int _contadorLeituras; // Conta o número de leituras feitas
private DateTime _ultimoRegistroVazao; // Armazena o horário da última atualização
public double VazaoFluxoMLpSMedia { get; set; }
2024-04-01 11:03:25 +00:00
public double VolumeVazaoML { get; set; }
public DateTime InicioAtuacao { get; set; } = DateTime.MinValue;
public double TempoAtuado { get; set; } = 0;
2024-10-29 19:53:27 +00:00
public void AtualizaTempoAtuadoGeral()
{
2024-12-05 12:52:28 +00:00
bool algumBicoAtivo = BicosPulverizadores.Any(x => x.Inicializado && x.ComandoAtuar);
2024-10-29 19:53:27 +00:00
if (algumBicoAtivo)
{
if (InicioAtuacao == DateTime.MinValue)
{
InicioAtuacao = DateTime.Now;
}
else
{
TempoAtuado += (DateTime.Now - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.Now;
}
}
else if (InicioAtuacao != DateTime.MinValue)
{
2024-10-29 19:53:27 +00:00
TempoAtuado += (DateTime.Now - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.MinValue;
}
2024-10-29 19:53:27 +00:00
AtualizaPercentualErvas();
2024-12-05 12:52:28 +00:00
AtualizaVazaoEVolume();
}
2024-10-29 19:53:27 +00:00
public void AtualizaPercentualErvas()
{
double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento.TempoDecorridoSeg * 1000.0;
2024-10-29 19:53:27 +00:00
if (tempoTotalOperacao > 0)
{
var percentual = Math.Round((TempoAtuado / tempoTotalOperacao) * 100.0, 2);
PercentualErvasTerreno = percentual;
2024-10-29 19:53:27 +00:00
}
else
{
PercentualErvasTerreno = 0;
}
}
2024-12-05 12:52:28 +00:00
public void AtualizaVazaoEVolume()
{
// Captura a vazão instantânea
double vazaoInstantanea = VazaoFluxoMLpSInstantanea;
if (_ultimoRegistroVazao == DateTime.MinValue)
{
_ultimoRegistroVazao = DateTime.Now;
return;
}
// Calcula o tempo decorrido desde a última atualização (em segundos)
double intervaloSegundos = (DateTime.Now - _ultimoRegistroVazao).TotalSeconds;
_ultimoRegistroVazao = DateTime.Now;
if (intervaloSegundos > 0)
{
// Atualiza o volume total vazado
VolumeVazaoML += vazaoInstantanea * intervaloSegundos;
// Acumula a vazão para o cálculo da média
_somaVazao += vazaoInstantanea;
_contadorLeituras++;
}
VazaoFluxoMLpSMedia = _contadorLeituras > 0 ? _somaVazao / _contadorLeituras : 0;
var BicosAtuados = BicosPulverizadores.Where(x => x.Inicializado && x.ComandoAtuar).ToList();
double vazaoInstantaneaBico = vazaoInstantanea / ((double)BicosAtuados.Count());
foreach (var Bico in BicosAtuados)
{
Bico.MediaNivelFluxo = vazaoInstantaneaBico;
}
}
2024-04-01 11:03:25 +00:00
#endregion
#region PRESSAO
public double _PressaoVmin { get; set; } = 0.0;
public double _PressaoVmax { get; set; } = 4.5;
public double _PressaoMax { get; set; } = 174.045; // 1,2 MPa
2024-12-02 19:12:39 +00:00
public double PressaoLinha
{
get
{
return Sensores.FirstOrDefault(x => x.Componente == S_Code.sPRS)?.ValoresLeituras.FirstOrDefault(x => x.funcao == FuncoesPinout.Pressao)?.atual?.valor ?? 0;
2024-12-02 19:12:39 +00:00
}
}
2024-04-01 11:03:25 +00:00
public double PressaoLinhaCalc
{
get
{
//double _LeituraPressao = ((FirmwareSensorPressao)Sensores.FirstOrDefault(x => x.Componente == S_Code.sPRS)?.Leitura)?.Leitura ?? 0;
double _LeituraPressao = 0;
double tensao = FuncoesMatematicas.Map(_LeituraPressao, 0, 4095, 0, 3300) / 1000.0;
2024-04-01 11:03:25 +00:00
double pressao = FuncoesMatematicas.Map(tensao, _PressaoVmin, _PressaoVmax, 0, _PressaoMax);
2024-04-01 11:03:25 +00:00
return pressao;
}
}
#endregion
2024-01-03 10:52:37 +00:00
public double PercentualErvasTerreno { get; set; } = 0;
2024-01-03 10:52:37 +00:00
public static AtuadorModel CarregarParametrosIniciais()
{
AtuadorModel Atuador = new AtuadorModel()
{
_EnderecoCAN_Tx = 0x12,
_EnderecoCAN_Rx = 0x12,
2025-04-09 21:11:40 +00:00
_TaxaAmostragem = 1000,
RequisitarDados = true,
2024-12-02 19:12:39 +00:00
QuantidadeBicos = 4,
BicosPulverizadores = new List<AtuadorBicoModel>(),
BombasPressurizadoras = new List<AtuadorBombaModel>()
2024-04-01 11:03:25 +00:00
{
new AtuadorBombaModel()
2024-04-01 11:03:25 +00:00
{
ID = "BOMBA",
2025-04-09 21:11:40 +00:00
ID_Num = 51,
Componente = S_Code.sBMB,
2025-04-09 21:11:40 +00:00
Comandar = true,
2025-05-07 16:54:45 +00:00
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.ENA,
FuncoesPinout.CS,
FuncoesPinout.INA,
FuncoesPinout.INB,
FuncoesPinout.PWM,
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.EstadoLeitura,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Potencia,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.PressaoSP,
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Pressao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 3,
}
}
2024-04-01 11:03:25 +00:00
}
},
Sensores = new List<SensorModel>()
{
new SensorModel()
{
ID = "FLXLN",
2025-04-09 21:11:40 +00:00
ID_Num = 61,
Descricao = "Fluxo na linha principal",
Componente = S_Code.sFLX,
2025-04-09 21:11:40 +00:00
Aferir = true,
2025-05-07 16:54:45 +00:00
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.Fluxo,
},
Parametros = new List<SensorParametroModel>(),
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Fluxo,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
analise_health = true,
maximo = 20,
minimo = 0,
nominal = 0,
unidade_medida = "mL/s"
}
}
},
new SensorModel()
{
ID = "MASRS",
2025-04-09 21:11:40 +00:00
ID_Num = 62,
Descricao = "Massa do reservatório de herbicida",
Componente = S_Code.sMAS,
2025-04-09 21:11:40 +00:00
Aferir = true,
2025-05-07 16:54:45 +00:00
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.DT,
FuncoesPinout.SCK,
},
2025-04-09 21:11:40 +00:00
Parametros = new List<SensorParametroModel>()
2025-05-01 18:27:01 +00:00
{
new SensorParametroModel()
{
Descricao = "Offset",
Enviar = true,
Escalar = false,
QtdBytes = 2,
Valor = "1895800"
}
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Massa,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
analise_health = true,
maximo = 35,
minimo = 0,
nominal = 30,
unidade_medida = "Kg"
}
2025-05-01 18:27:01 +00:00
}
},
new SensorModel()
{
ID = "PRSLN",
2025-04-09 21:11:40 +00:00
ID_Num = 63,
Descricao = "Pressão na linha principal",
Componente = S_Code.sPRS,
2025-04-09 21:11:40 +00:00
Aferir = true,
2025-05-07 16:54:45 +00:00
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.Pressao,
},
2025-04-09 21:11:40 +00:00
Parametros = new List<SensorParametroModel>()
2024-04-01 11:03:25 +00:00
{
2025-04-09 21:11:40 +00:00
new SensorParametroModel()
{
Descricao = "Vmin",
Valor = "0",
QtdBytes = 1,
Escalar = false,
Enviar = false
2025-04-09 21:11:40 +00:00
},
new SensorParametroModel()
{
Descricao = "Vmax",
Valor = "4.5",
QtdBytes = 1,
Escalar = true,
Enviar = false
2025-04-09 21:11:40 +00:00
},
new SensorParametroModel()
{
Descricao = "Pmax",
Valor = "174",
QtdBytes = 1,
Escalar = false,
Enviar = false
2025-04-09 21:11:40 +00:00
},
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Fluxo,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
analise_health = true,
maximo = 120,
minimo = 0,
nominal = 85,
unidade_medida = "PSI"
}
2025-04-09 21:11:40 +00:00
}
},
},
2024-01-03 10:52:37 +00:00
};
for (int i = 0; i < Atuador.QuantidadeBicos; i++)
{
2025-04-09 21:11:40 +00:00
int posicao = (i + 1);
2024-01-03 10:52:37 +00:00
Atuador.BicosPulverizadores.Add(new AtuadorBicoModel()
{
2025-04-09 21:11:40 +00:00
ID = "B" + posicao.ToString("00"),
ID_Num = 70 + posicao,
Componente = S_Code.sBIC,
2025-04-09 21:11:40 +00:00
Posicao = posicao,
Comandar = true,
2025-05-07 16:54:45 +00:00
Mandatorio = true,
2024-12-02 19:12:39 +00:00
ComandoAtuar = false,
2025-04-09 21:11:40 +00:00
AtuacaoNivelAlto = true,
2024-01-03 10:52:37 +00:00
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.Solenoide,
},
2025-05-07 16:54:45 +00:00
MediaNivelFluxo = 0,
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.EstadoLeitura,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
}
}
2024-01-03 10:52:37 +00:00
});
}
return Atuador;
}
2024-12-02 19:12:39 +00:00
public void LimparDados<T>(T _dados)
2024-07-18 18:00:14 +00:00
{
2024-12-02 19:12:39 +00:00
var Dados = _dados as AtuadorModel;
Dados.DadosLeitura = new AtuadorMensagemJsonModel();
Dados.DadosLeitura.Momento = DateTime.MinValue;
Dados.PercentualErvasTerreno = 0;
2024-12-02 19:12:39 +00:00
Dados.BombasPressurizadoras.ForEach(x => x.Funcoes = x.Funcoes.Distinct().ToList());
2024-10-29 19:53:27 +00:00
ReiniciarLeituras(Dados);
}
2024-12-02 19:12:39 +00:00
public void ReiniciarLeituras(AtuadorModel Dados)
2024-10-29 19:53:27 +00:00
{
Dados.Sensores.ForEach(x =>
{
x.ValoresLeituras.ForEach(l =>
{
l.atual = new CanCommandFreqModel<dynamic>();
});
});
2024-10-29 19:53:27 +00:00
Dados.BicosPulverizadores.ForEach(x =>
{
2024-12-02 19:12:39 +00:00
x.ComandoAtuar = false;
2024-10-29 19:53:27 +00:00
x.Atuacoes = 0;
x.TempoAtuado = 0;
x.InicioAtuacao = DateTime.MinValue;
x.ValoresLeituras.ForEach(l =>
{
l.atual = new CanCommandFreqModel<dynamic>();
});
2024-07-18 18:00:14 +00:00
});
2024-10-29 19:53:27 +00:00
Dados.BombasPressurizadoras.ForEach(x =>
2024-07-18 18:00:14 +00:00
{
2024-12-02 19:12:39 +00:00
x.ComandoAtuar = false;
x.ValoresLeituras.ForEach(l =>
{
l.atual = new CanCommandFreqModel<dynamic>();
});
2024-07-18 18:00:14 +00:00
});
2024-10-29 19:53:27 +00:00
2024-07-18 18:00:14 +00:00
Dados.VolumeVazaoAferido = 0;
2024-12-05 12:52:28 +00:00
Dados._somaVazao = 0;
Dados._contadorLeituras = 0;
Dados._ultimoRegistroVazao = DateTime.MinValue;
2024-07-18 18:00:14 +00:00
Dados.VolumeVazaoML = 0;
2024-12-05 12:52:28 +00:00
Dados.VazaoFluxoMLpSMedia = 0;
Dados.TempoAtuado = 0;
Dados.InicioAtuacao = DateTime.MinValue;
2024-07-18 18:00:14 +00:00
}
2025-05-06 18:47:59 +00:00
public async Task<bool> VerificaDispositivoConectado()
2024-01-03 10:52:37 +00:00
{
2025-05-06 18:47:59 +00:00
if (!CanService.IsConnected) return false;
2025-05-06 18:47:59 +00:00
if (Variaveis.OperacaoEmAndamento.DispAtu == null) return false;
2025-05-06 18:47:59 +00:00
CanService.RegistrarHandler(_EnderecoCAN_Rx, _AtuHandler);
2025-05-06 18:47:59 +00:00
RequisitarDadosModulo(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Status, CanMessagePosicaoDados.Status, true);
DateTime Inicio = DateTime.Now;
bool Respondido() => Variaveis.OperacaoEmAndamento.DispAtu.Dados.DadosLeitura.UltimoComandoRespondido > Inicio;
await FuncoesGlobais.AguardarCondicaoAsync(Respondido, 500, 50);
if (ConexaoAtiva)
2024-12-02 19:12:39 +00:00
{
2025-05-06 18:47:59 +00:00
DefinirDispositivo();
Variaveis.OperacaoEmAndamento.DispAtu?.EnviarProtocolosConfiguracao();
2024-12-02 19:12:39 +00:00
}
return ConexaoAtiva;
}
2025-04-09 21:11:40 +00:00
private void DefinirDispositivo()
{
2025-04-09 21:11:40 +00:00
if (!SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Dispositivo && x.Mod_ID == Modulo_ID))
{
SerialService.DispositivosMapeados.Add(new DispositivoDetalhesModel()
{
Dispositivo = DadosLeitura.Dispositivo,
Endereco = CanService._portName,
2025-04-09 21:11:40 +00:00
Versao = DadosLeitura.Versao.ToString(),
2025-05-06 18:47:59 +00:00
Mod_ID = Modulo_ID
2025-04-09 21:11:40 +00:00
});
}
}
2025-05-01 18:27:01 +00:00
public void RequisitarDadosModulo(int ID_Num, CanMessagePosicaoDados posicaoTx, CanMessagePosicaoDados posicaoRx, bool aguardaResposta)
{
2025-05-01 18:27:01 +00:00
Variaveis.OperacaoEmAndamento.DispAtu?.AdicionarMensagemFila(ID_Num, posicaoTx, posicaoRx, null, aguardaResposta);
}
2025-05-01 18:27:01 +00:00
public List<(int, CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(bool Conectar)
{
2025-04-09 21:11:40 +00:00
// Inicializar o dicionário
2025-05-01 18:27:01 +00:00
List<(int, CanMessagePosicaoDados, byte[])> config = new List<(int, CanMessagePosicaoDados, byte[])>();
2025-04-09 21:11:40 +00:00
if (!DadosLeitura.Conectado)
2025-04-09 21:11:40 +00:00
{
// Adicionar configuração do ProtocoloMOD
var protocoloMOD = ModConfig(Conectar);
config.AddRange(protocoloMOD);
2025-04-09 21:11:40 +00:00
}
bool configurarTodos = !DadosLeitura.Conectado && Conectar;
// Adicionar configurações dos Sensores que devem ser aferidos
2025-05-01 18:27:01 +00:00
var sensoresConfig = SensoresConfig(Conectar, configurarTodos);
config.AddRange(sensoresConfig);
2025-04-09 21:11:40 +00:00
// Adicionar configurações dos Bicos
2025-05-01 18:27:01 +00:00
var bicosConfig = BicosConfig(Conectar, configurarTodos);
2025-04-09 21:11:40 +00:00
config.AddRange(bicosConfig);
// Adicionar configurações das Bombas
2025-05-01 18:27:01 +00:00
var bombasConfig = BombasConfig(Conectar, configurarTodos);
2025-04-09 21:11:40 +00:00
config.AddRange(bombasConfig);
return config;
2024-01-03 10:52:37 +00:00
}
2025-05-01 18:27:01 +00:00
private List<(int, CanMessagePosicaoDados, byte[])> ModConfig(bool Conectar)
{
var config1 = new List<byte>
2025-04-09 21:11:40 +00:00
{
(byte)(Conectar ? 1 : 0),
(byte)(_TaxaAmostragem / 10),
2025-04-09 21:11:40 +00:00
(byte)(RequisitarDados ? 1 : 0),
};
2025-05-01 18:27:01 +00:00
var config2 = new List<byte>();
config2.AddRange(PinoutModel.PinoProtocolo(Pinout, Funcoes, false));
2025-05-01 18:27:01 +00:00
return new List<(int, CanMessagePosicaoDados, byte[])>
{
2025-05-01 18:27:01 +00:00
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config1, config1.ToArray()),
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config2, config2.ToArray()),
};
}
2025-05-01 18:27:01 +00:00
private List<(int, CanMessagePosicaoDados, byte[])> SensoresConfig(bool Conectar, bool ConfigurarTodos)
{
2025-05-01 18:27:01 +00:00
var config = new List<(int, CanMessagePosicaoDados, byte[])>();
foreach (var sensor in Sensores.Where(x => (x.Aferir && (ConfigurarTodos ? true : x.Inicializado != Conectar)) || (!x.Aferir && x.Inicializado)))
{
if (!sensor.Aferir && sensor.Inicializado)
{
Conectar = false;
}
2025-05-01 18:27:01 +00:00
(CanMessagePosicaoDados posicao, byte[] payload) = sensor.ProtocoloConfiguracao(Pinout, Conectar, Dispositivo);
2025-04-09 21:11:40 +00:00
if (payload != null)
{
2025-05-01 18:27:01 +00:00
config.Add((sensor.ID_Num, posicao, payload));
2025-04-09 21:11:40 +00:00
}
}
return config;
}
2025-05-01 18:27:01 +00:00
private List<(int, CanMessagePosicaoDados, byte[])> BicosConfig(bool Conectar, bool ConfigurarTodos)
2025-04-09 21:11:40 +00:00
{
2025-05-01 18:27:01 +00:00
var config = new List<(int, CanMessagePosicaoDados, byte[])>();
2025-04-09 21:11:40 +00:00
foreach (var bico in BicosPulverizadores.Where(x => (x.Comandar && (ConfigurarTodos ? true : x.Inicializado != Conectar)) || (!x.Comandar && x.Inicializado)))
2025-04-09 21:11:40 +00:00
{
if (!bico.Comandar && bico.Inicializado)
{
Conectar = false;
}
2025-05-01 18:27:01 +00:00
(CanMessagePosicaoDados posicao, var payload) = bico.ProtocoloConfiguracao(Pinout, Conectar);
2025-04-09 21:11:40 +00:00
if (payload != null)
{
2025-05-01 18:27:01 +00:00
config.Add((bico.ID_Num, posicao, payload));
2025-04-09 21:11:40 +00:00
}
}
2025-04-09 21:11:40 +00:00
return config;
}
2024-01-03 10:52:37 +00:00
2025-05-01 18:27:01 +00:00
private List<(int, CanMessagePosicaoDados, byte[])> BombasConfig(bool Conectar, bool ConfigurarTodos)
2024-01-03 10:52:37 +00:00
{
2025-05-01 18:27:01 +00:00
var config = new List<(int, CanMessagePosicaoDados, byte[])>();
2025-04-09 21:11:40 +00:00
foreach (var bomba in BombasPressurizadoras.Where(x => (x.Comandar && (ConfigurarTodos ? true : x.Inicializado != Conectar)) || (!x.Comandar && x.Inicializado)))
2025-04-09 21:11:40 +00:00
{
if (!bomba.Comandar && bomba.Inicializado)
{
Conectar = false;
}
2025-05-01 18:27:01 +00:00
List<(CanMessagePosicaoDados, byte[])> dados = bomba.ProtocoloConfiguracao(Pinout, Conectar);
foreach (var dado in dados)
2025-04-09 21:11:40 +00:00
{
2025-05-01 18:27:01 +00:00
config.Add((bomba.ID_Num, dado.Item1, dado.Item2));
2025-04-09 21:11:40 +00:00
}
}
return config;
}
2024-01-03 10:52:37 +00:00
public void IniciarRegistrador()
{
if (!(tmrRegistrador?.IsRunning ?? false))
{
LimparDados(this);
PararRegistrador();
tmrRegistrador = new AsyncTaskTimerModel("tmrRegistrador_" + T_Code.Atu.ToString(), tmrRegistrador_Tick, _TaxaAmostragem);
tmrRegistrador.Start();
}
}
2024-01-03 10:52:37 +00:00
public void PararRegistrador()
{
tmrRegistrador?.Dispose();
2024-01-03 10:52:37 +00:00
}
public async Task tmrRegistrador_Tick()
{
if (Variaveis.Fechando)
{
return;
}
tmrRegistrador.SetInterval(_TaxaAmostragem);
2024-12-05 12:52:28 +00:00
if (SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Atu) && (_VezesLeituraReconexao >= _TempoReconexaoComponentes))
{
Variaveis.OperacaoEmAndamento.DispAtu?.EnviarProtocolosConfiguracao();
_VezesLeituraReconexao = 0;
}
else
{
_VezesLeituraReconexao++;
}
if (DadosLeitura.Conectado)
{
2024-12-03 20:55:25 +00:00
if (RequisitarDados)
{
2025-05-01 18:27:01 +00:00
RequisitarDadosModulo(Variaveis.ID_Num_sTOD, CanMessagePosicaoDados.DadosAll, CanMessagePosicaoDados.DadosAll, true);
2024-12-03 20:55:25 +00:00
}
}
2025-04-16 16:44:06 +00:00
AtualizaComponentesIniciados();
}
2024-10-03 18:21:30 +00:00
public (bool, List<string>) StatusModulosATU()
{
var Bicos = BicosPulverizadores.Where(x => x.Comandar).ToList();
2025-05-07 16:54:45 +00:00
var BicosComFalha = Bicos.Where(x => !x.Liberado).ToList();
2024-10-03 18:21:30 +00:00
bool _bicosOperantes = !BicosComFalha.Any();
var _bomba = BombaPressurizadora;
2024-10-03 18:21:30 +00:00
var _sensorFluxo = Sensores.FirstOrDefault(x => x.Componente == S_Code.sFLX);
2025-05-07 16:54:45 +00:00
bool _sensorFluxoOperante = !_sensorFluxo?.Liberado ?? false;
2024-10-03 18:21:30 +00:00
var _sensorMassa = Sensores.FirstOrDefault(x => x.Componente == S_Code.sMAS);
2025-05-07 16:54:45 +00:00
bool _sensorMassaOperante = !_sensorMassa?.Liberado ?? false;
2024-10-03 18:21:30 +00:00
var _sensorPressao = Sensores.FirstOrDefault(x => x.Componente == S_Code.sPRS);
2025-05-07 16:54:45 +00:00
bool _sensorPressaoOperante = !_sensorPressao?.Liberado ?? false;
2024-10-03 18:21:30 +00:00
List<string> ModsComFalha = BicosComFalha.Select(x => x.ID).ToList();
2025-05-07 16:54:45 +00:00
bool _bombaOperante = _bomba?.Liberado ?? false;
2024-10-03 18:21:30 +00:00
if (!_bombaOperante)
{
ModsComFalha.Add(_bomba?.ID);
2024-10-03 18:21:30 +00:00
}
if (!_sensorFluxoOperante)
{
ModsComFalha.Add(_sensorFluxo.ID);
}
if (!_sensorMassaOperante)
{
ModsComFalha.Add(_sensorMassa.ID);
}
if (!_sensorPressaoOperante)
{
ModsComFalha.Add(_sensorPressao.ID);
}
2025-05-07 16:54:45 +00:00
bool _atuadorOperante = _bombaOperante && _bicosOperantes && _sensorPressaoOperante && _sensorMassaOperante && _sensorFluxoOperante;
2024-10-03 18:21:30 +00:00
return (_atuadorOperante, ModsComFalha);
}
2025-04-16 16:44:06 +00:00
private void AtualizaComponentesIniciados()
{
DateTime Agora = DateTime.Now;
bool modConectado = DadosLeitura.UltimoComandoRespondido.AddMilliseconds(TempoLimiteConexao) > Agora;
if (!modConectado && DadosLeitura.Conectado)
{
DadosLeitura.Conectado = false;
}
foreach (var bomba in BombasPressurizadoras.Where(x => x.Inicializado && x.UltimaLeitura.AddMilliseconds(TempoLimiteConexao) < Agora))
2025-04-16 16:44:06 +00:00
{
bomba.Inicializado = false;
2025-04-16 16:44:06 +00:00
}
foreach (var bico in BicosPulverizadores.Where(x => x.Inicializado && x.UltimaLeitura.AddMilliseconds(TempoLimiteConexao) < Agora))
2025-04-16 16:44:06 +00:00
{
bico.Inicializado = false;
2025-04-16 16:44:06 +00:00
}
foreach (var sensor in Sensores.Where(x => x.Inicializado && x.UltimaLeitura.AddMilliseconds(TempoLimiteConexao) < Agora))
2025-04-16 16:44:06 +00:00
{
sensor.Inicializado = false;
2025-04-16 16:44:06 +00:00
}
}
2024-01-03 10:52:37 +00:00
}
public class AtuadorBicoModel
{
public string ID { get; set; }
2025-04-09 21:11:40 +00:00
public int ID_Num { get; set; }
2024-01-03 10:52:37 +00:00
public int Posicao { get; set; }
public S_Code Componente { get; set; } = S_Code.sBIC;
public bool AtuacaoNivelAlto { get; set; }
2024-10-29 19:53:27 +00:00
private bool _atuado;
2024-12-02 19:12:39 +00:00
public bool ComandoAtuar
2024-10-29 19:53:27 +00:00
{
get
{
return _atuado;
}
set
{
_atuado = value;
AtualizaTempoAtuado();
}
}
2024-01-03 10:52:37 +00:00
public bool Comandar { get; set; }
2025-05-07 16:54:45 +00:00
public bool Mandatorio { get; set; }
public bool Liberado
{
get
{
return !Mandatorio || (Comandar && Inicializado);
}
}
2024-01-03 10:52:37 +00:00
public List<FuncoesPinout> Funcoes { get; set; }
public double MediaNivelFluxo { get; set; }
public bool Inicializado { get; set; }
public DateTime UltimaLeitura
{
get
{
return ValoresLeituras.OrderByDescending(x => x.atual.lidoEm).FirstOrDefault()?.atual?.lidoEm ?? DateTime.MinValue;
}
}
public List<SensorValoresLeituraModel> ValoresLeituras { get; set; } = new List<SensorValoresLeituraModel>();
2024-01-03 10:52:37 +00:00
2025-05-01 18:27:01 +00:00
public (CanMessagePosicaoDados, byte[]) ProtocoloConfiguracao(PinoutDataModel pinout, bool conectar)
2024-01-03 10:52:37 +00:00
{
2025-04-09 21:11:40 +00:00
var pino = pinout.Pinos.FirstOrDefault(p => p.ComponenteID == ID);
2025-05-01 18:27:01 +00:00
var data = new byte[]
2024-04-15 10:57:37 +00:00
{
(byte)Componente,
2025-04-09 21:11:40 +00:00
(byte)(conectar ? 1 : 0),
(byte)(AtuacaoNivelAlto ? 1 : 0),
(byte)(pino?.Barramento ?? TiposBarramentos.CONTROLADOR),
(byte)(pino?.Pino ?? PinoutUtils.PINO_INVALIDO)
2024-04-15 10:57:37 +00:00
};
2025-05-01 18:27:01 +00:00
return (CanMessagePosicaoDados.Config1, data);
2024-01-03 10:52:37 +00:00
}
2025-05-01 18:27:01 +00:00
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando()
2024-01-03 10:52:37 +00:00
{
2025-04-09 21:11:40 +00:00
return (
2025-05-01 18:27:01 +00:00
ID_Num,
CanMessagePosicaoDados.Command1,
2025-04-09 21:11:40 +00:00
new byte[]
{
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado)
}
);
2024-01-03 10:52:37 +00:00
}
2024-03-11 20:04:48 +00:00
2024-10-29 19:53:27 +00:00
public int Atuacoes { get; set; } = 0;
public DateTime InicioAtuacao { get; set; } = DateTime.MinValue;
public double TempoAtuado { get; set; } = 0;
private void AtualizaTempoAtuado()
{
if (_atuado)
{
if (InicioAtuacao == DateTime.MinValue)
{
InicioAtuacao = DateTime.Now;
}
else
{
TempoAtuado += (DateTime.Now - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.Now;
}
}
else if (InicioAtuacao != DateTime.MinValue)
{
TempoAtuado += (DateTime.Now - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.MinValue;
}
if (Variaveis.OperacaoEmAndamento.DispAtu != null)
{
Variaveis.OperacaoEmAndamento.DispAtu.Dados.AtualizaTempoAtuadoGeral();
}
}
2024-03-11 20:04:48 +00:00
public AtuadorBicoModel Clone()
{
AtuadorBicoModel clone = new AtuadorBicoModel()
{
Comandar = Comandar,
AtuacaoNivelAlto = AtuacaoNivelAlto,
Atuacoes = Atuacoes,
ComandoAtuar = ComandoAtuar,
Componente = Componente,
Funcoes = Funcoes,
ID = ID,
2025-04-09 21:11:40 +00:00
ID_Num = ID_Num,
InicioAtuacao = InicioAtuacao,
ValoresLeituras = new List<SensorValoresLeituraModel>(ValoresLeituras),
MediaNivelFluxo = MediaNivelFluxo,
Posicao = Posicao,
TempoAtuado = TempoAtuado
2024-03-11 20:04:48 +00:00
};
return clone;
}
2024-01-03 10:52:37 +00:00
}
2024-04-01 11:03:25 +00:00
public class AtuadorBombaModel
{
public string ID { get; set; }
2025-04-09 21:11:40 +00:00
public int ID_Num { get; set; }
2024-12-02 19:12:39 +00:00
public bool ComandoAtuar { get; set; }
public S_Code Componente { get; set; } = S_Code.sBMB;
2024-04-01 11:03:25 +00:00
public bool Comandar { get; set; }
2025-05-07 16:54:45 +00:00
public bool Mandatorio { get; set; }
public bool Liberado
{
get
{
return !Mandatorio || (Comandar && Inicializado);
}
}
2024-04-01 11:03:25 +00:00
public List<FuncoesPinout> Funcoes { get; set; } = new List<FuncoesPinout>();
public bool Inicializado { get; set; }
public DateTime UltimaLeitura
2024-12-02 19:12:39 +00:00
{
get
{
return ValoresLeituras.OrderByDescending(x => x.atual.lidoEm).FirstOrDefault()?.atual?.lidoEm ?? DateTime.MinValue;
2024-12-03 20:55:25 +00:00
}
}
public List<SensorValoresLeituraModel> ValoresLeituras { get; set; } = new List<SensorValoresLeituraModel>();
2024-04-01 11:03:25 +00:00
2024-04-01 11:03:25 +00:00
2025-05-01 18:27:01 +00:00
public List<(CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(PinoutDataModel pinout, bool conectar)
2024-04-01 11:03:25 +00:00
{
List<byte> config1 = new List<byte>()
2024-04-15 10:57:37 +00:00
{
(byte)Componente,
2025-04-09 21:11:40 +00:00
(byte)(conectar ? 1 : 0),
(byte)Variaveis.OperacaoEmAndamento.Controle.PressaoLinha,
(byte)(pinout.Pinos.FirstOrDefault(x => x.ComponenteID == ID && x.Funcao == FuncoesPinout.ENA)?.Pino ?? PinoutUtils.PINO_INVALIDO),
(byte)(pinout.Pinos.FirstOrDefault(x => x.Funcao == FuncoesPinout.CS)?.Pino ?? PinoutUtils.PINO_INVALIDO),
2024-04-15 10:57:37 +00:00
};
List<byte> config2 = new List<byte>()
{
(byte)Componente,
(byte)(pinout.Pinos.FirstOrDefault(x => x.Funcao == FuncoesPinout.INA)?.Pino ?? PinoutUtils.PINO_INVALIDO),
(byte)(pinout.Pinos.FirstOrDefault(x => x.Funcao == FuncoesPinout.INB)?.Pino ?? PinoutUtils.PINO_INVALIDO),
(byte)(pinout.Pinos.FirstOrDefault(x => x.Funcao == FuncoesPinout.PWM)?.Pino ?? PinoutUtils.PINO_INVALIDO),
};
2025-05-01 18:27:01 +00:00
return new List<(CanMessagePosicaoDados, byte[])>()
2025-04-16 16:44:06 +00:00
{
2025-05-01 18:27:01 +00:00
(CanMessagePosicaoDados.Config1, config1.ToArray()),
(CanMessagePosicaoDados.Config2, config2.ToArray()),
};
2024-04-01 11:03:25 +00:00
}
2025-05-01 18:27:01 +00:00
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando()
2024-04-01 11:03:25 +00:00
{
2025-04-09 21:11:40 +00:00
return (
2025-05-01 18:27:01 +00:00
ID_Num,
CanMessagePosicaoDados.Command1,
2025-04-09 21:11:40 +00:00
new byte[]
{
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
(byte)(Variaveis.OperacaoEmAndamento.Controle.PressaoLinha)
}
);
2024-04-01 11:03:25 +00:00
}
}
public class CalibragemVazao
{
public bool Calibrando { get; set; } = false;
public DateTime IniciadoEm { get; set; }
public double TempoCalibragem { get; set; } = 10000.0;
public double VolumeComputado { get; set; } = 0;
public List<double> PressoesAferidas { get; set; } = new List<double>();
public double MassaInicial { get; set; } = 0.0;
public double MassaFinal { get; set; } = 0.0;
public int QtdPulsos { get; set; } = 0;
public double Periodo { get; set; } = 0.0;
public double PressaoMedia
{
get
{
return PressoesAferidas.Average();
}
}
public double MassaPerdida
{
get
{
return (MassaInicial - MassaFinal) * 1000;
}
}
public double Q
{
get
{
return (double)VolumeComputado / (double)Periodo;
}
}
public double VolumeCalculado { get; set; } = 0.0;
public double d
{
get
{
return (double)MassaPerdida / (double)VolumeComputado;
}
}
public double x
{
get
{
return (double)VolumeComputado / (double)QtdPulsos;
}
}
public double Q2
{
get
{
return (double)x * (double)QtdPulsos;
}
}
}
2024-04-01 11:03:25 +00:00
2024-10-29 19:53:27 +00:00
public class AtuadorFuncoesGerais
{
public static void DesenharAtuadores(object sender, PaintEventArgs e, List<AtuBicoSensoriamentoLogModel> Bicos, bool BombaLigada, double PressaoLinha, double TempoBombaAtuada)
{
Panel myPanel = (Panel)sender;
// Habilita o double buffering temporariamente
myPanel.GetType().GetProperty("DoubleBuffered",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
?.SetValue(myPanel, true, null);
Graphics g = e.Graphics;
int QuantidadeBicos = Bicos.Count;
int panelWidth = myPanel.Width;
int circleDiameter = 40; // Diâmetro dos círculos grandes
int smallCircleDiameter = circleDiameter / 2; // Diâmetro dos círculos pequenos
int spaceBetweenCircles = (panelWidth - (circleDiameter * QuantidadeBicos)) / (QuantidadeBicos + 1);
int yPosition = (myPanel.Height - circleDiameter) / 3; // Centralizado verticalmente
for (int i = 0; i < QuantidadeBicos; i++)
{
int xPosition = spaceBetweenCircles + (i * (circleDiameter + spaceBetweenCircles));
// Desenha o contorno do círculo
g.DrawEllipse(Pens.Red, xPosition, yPosition, circleDiameter, circleDiameter);
// Preenche o círculo se o bico estiver aceso
if (Bicos[i].Atuado)
{
g.FillEllipse(Brushes.Red, xPosition, yPosition, circleDiameter, circleDiameter);
}
// Número do bico
string bicoNumero = Bicos[i].ID;
Font font = new Font("Arial", 10, FontStyle.Bold);
SizeF stringSize = g.MeasureString(bicoNumero, font);
float textXPosition = xPosition + (circleDiameter - stringSize.Width) / 2;
float textYPosition = yPosition + (circleDiameter - stringSize.Height) / 2;
g.DrawString(bicoNumero, font, Brushes.Black, textXPosition, textYPosition);
2024-12-05 12:52:28 +00:00
// Média de vazão (dentro do círculo, abaixo do número do bico)
string mediaFluxoTexto = $"{Bicos[i].MediaNivelFluxo:0.0} mL/s";
Font fontMediaFluxo = new Font("Arial", 6, FontStyle.Regular);
SizeF stringSizeMediaFluxo = g.MeasureString(mediaFluxoTexto, fontMediaFluxo);
float textXPositionMediaFluxo = xPosition + circleDiameter + 3;
float textYPositionMediaFluxo = textYPosition + 3; // Abaixo do número do bico
g.DrawString(mediaFluxoTexto, fontMediaFluxo, Brushes.Gray, textXPositionMediaFluxo, textYPositionMediaFluxo);
2024-10-29 19:53:27 +00:00
// Quantidade de atuações (abaixo do círculo)
string bicoAtuacao = Bicos[i].Atuacoes.ToString("000");
Font fontA = new Font("Arial", 8, FontStyle.Bold);
SizeF stringSizeA = g.MeasureString(bicoAtuacao, fontA);
float textXPositionA = xPosition + (circleDiameter - stringSizeA.Width) / 2;
float textYPositionA = circleDiameter + yPosition + 5;
g.DrawString(bicoAtuacao, fontA, Brushes.Black, textXPositionA, textYPositionA);
// Tempo atuado em segundos (acima do círculo)
string tempoAtuadoSegundos = $"{(Bicos[i].TempoAtuado / 1000.0):0.0}s";
Font fontTempo = new Font("Arial", 7, FontStyle.Regular);
SizeF stringSizeTempo = g.MeasureString(tempoAtuadoSegundos, fontTempo);
float textXPositionTempo = xPosition + (circleDiameter - stringSizeTempo.Width) / 2;
float textYPositionTempo = yPosition - stringSizeTempo.Height - 3;
g.DrawString(tempoAtuadoSegundos, fontTempo, Brushes.Gray, textXPositionTempo, textYPositionTempo);
// Círculo pequeno de status
int smallCircleXPosition = Convert.ToInt32(xPosition + circleDiameter - smallCircleDiameter / 1.3);
int smallCircleYPosition = Convert.ToInt32(yPosition + circleDiameter - smallCircleDiameter / 1.3);
Pen smallCirclePen = Pens.Blue;
Brush smallCircleBrush = Bicos[i].StatusBico ? Brushes.Blue : Brushes.Transparent;
g.DrawEllipse(smallCirclePen, smallCircleXPosition, smallCircleYPosition, smallCircleDiameter, smallCircleDiameter);
g.FillEllipse(smallCircleBrush, smallCircleXPosition, smallCircleYPosition, smallCircleDiameter, smallCircleDiameter);
}
// Representação da bomba hidráulica no canto inferior direito
int bombaSize = 20; // Tamanho do círculo principal da bomba
int bombaXPosition = myPanel.Width - bombaSize - 20; // 20px de margem do canto direito
int bombaYPosition = myPanel.Height - bombaSize - 20; // 20px de margem do canto inferior
// Desenha o corpo da bomba (um círculo)
g.DrawEllipse(Pens.Black, bombaXPosition, bombaYPosition, bombaSize, bombaSize);
g.FillEllipse(BombaLigada ? Brushes.Green : Brushes.Gray, bombaXPosition, bombaYPosition, bombaSize, bombaSize);
// Define o centro do círculo para ajudar no desenho das hélices
int centerX = bombaXPosition + bombaSize / 2;
int centerY = bombaYPosition + bombaSize / 2;
int heliceSize = bombaSize - 6; // Ajuste para manter as hélices dentro do círculo
// Desenha hélices no formato de arcos ou semi-círculos dentro do círculo
Pen helicePen = new Pen(Color.Black, 1);
g.DrawArc(helicePen, centerX - heliceSize / 2, centerY - heliceSize / 2, heliceSize, heliceSize, 45, 180);
g.DrawArc(helicePen, centerX - heliceSize / 2, centerY - heliceSize / 2, heliceSize, heliceSize, 225, 180);
// Desenha o "cano" da bomba (retângulo)
int tuboLargura = 5;
int tuboAltura = 15;
int tuboXPosition = bombaXPosition + bombaSize / 2 - tuboLargura / 2;
int tuboYPosition = bombaYPosition - tuboAltura;
g.FillRectangle(Brushes.Black, tuboXPosition, tuboYPosition, tuboLargura, tuboAltura);
// Texto para o tempo de atuação acima da bomba
string tempoAtuacaoTexto = $"{(TempoBombaAtuada / 1000.0):0.0}s";
Font fontTempoAtuacao = new Font("Arial", 6, FontStyle.Regular);
SizeF stringSizeTempoAtuacao = g.MeasureString(tempoAtuacaoTexto, fontTempoAtuacao);
float textXPositionTempoAtuacao = bombaXPosition + bombaSize / 2 - stringSizeTempoAtuacao.Width / 2;
float textYPositionTempoAtuacao = bombaYPosition - stringSizeTempoAtuacao.Height - 16; // 2px acima do círculo
g.DrawString(tempoAtuacaoTexto, fontTempoAtuacao, Brushes.Gray, textXPositionTempoAtuacao, textYPositionTempoAtuacao);
// Texto pequeno para a pressão ao lado da bomba
string pressaoTexto = $"{PressaoLinha:0.0} psi";
Font fontPressao = new Font("Arial", 6, FontStyle.Regular);
SizeF stringSizePressao = g.MeasureString(pressaoTexto, fontPressao);
float textXPositionPressao = bombaXPosition + bombaSize / 2 - stringSizePressao.Width / 2;
float textYPositionPressao = bombaYPosition + bombaSize + 2; // 2px abaixo do círculo
g.DrawString(pressaoTexto, fontPressao, Brushes.Black, textXPositionPressao, textYPositionPressao);
}
}
2025-04-16 16:44:06 +00:00
public class FirmwareBombaPressurizadora : IFirmwareSensorBase
{
2025-04-16 16:44:06 +00:00
public DateTime Momento { get; set; }
public string ID { get; set; }
2025-04-16 16:44:06 +00:00
public int ID_Num { get; set; }
public bool Iniciado { get; set; }
public CanCommandFreqModel<Estado> Estado { get; set; } = new CanCommandFreqModel<Estado>();
public CanCommandFreqModel<double> Potencia { get; set; } = new CanCommandFreqModel<double>();
public CanCommandFreqModel<double> PressaoSP { get; set; } = new CanCommandFreqModel<double>();
public CanCommandFreqModel<double> Pressao { get; set; } = new CanCommandFreqModel<double>();
}
public class AtuadorMensagemJsonModel
{
2024-12-05 17:11:38 +00:00
public DateTime Momento { get; set; }
public bool Conectado { get; set; }
2025-04-09 21:11:40 +00:00
public T_Code Dispositivo { get; set; }
public int Versao { get; set; }
public string Mod_ID { get; set; }
2024-12-05 17:11:38 +00:00
public int QualidadeWifi { get; set; }
public int LatenciaLoop { get; set; }
public List<AtuadorBicoModel> BicosPulverizadores { get; set; } = new List<AtuadorBicoModel>();
public List<AtuadorBombaModel> BombasPressurizadoras { get; set; } = new List<AtuadorBombaModel>();
public List<SensorModel> Sensores { get; set; } = new List<SensorModel>();
2025-04-09 21:11:40 +00:00
public DateTime UltimoComandoRespondido { get; set; }
}
public class AtuHandler : ICanMessageHandler
{
2025-05-06 18:47:59 +00:00
public T_Code Dispositivo { get; set; } = Variaveis.OperacaoEmAndamento.DispAtu?.Dados?.Dispositivo ?? T_Code.Atu;
private double ConverterByteParaDouble(byte[] data, int idx)
{
int raw = (data[idx] << 8) | data[idx + 1];
short _short = (short)raw;
double _value = _short / 100.0;
return _value;
}
private S_Code DetectarComponenteDoID_Num(int ID_Num)
{
if (ID_Num == Variaveis.ID_Num_sMOD) return S_Code.sMOD;
var Disp = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
var sensor = Disp.Sensores.FirstOrDefault(x => x.ID_Num == ID_Num);
var bico = Disp.BicosPulverizadores.FirstOrDefault(x => x.ID_Num == ID_Num);
var bomba = Disp.BombasPressurizadoras.FirstOrDefault(x => x.ID_Num == ID_Num);
return sensor?.Componente ?? bico?.Componente ?? bomba?.Componente ?? S_Code.sVZO;
}
2025-04-15 13:16:27 +00:00
private void DefinirOuCriar(int CompID_Num, CanMessagePosicaoDados Posicao, S_Code componente, List<dynamic> Parametros)
{
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
var sensor = Dados.Sensores.FirstOrDefault(x => x.ID_Num == CompID_Num);
var bomba = Dados.BombasPressurizadoras.FirstOrDefault(x => x.ID_Num == CompID_Num);
var bico = Dados.BicosPulverizadores.FirstOrDefault(x => x.ID_Num == CompID_Num);
List<SensorValoresLeituraModel> valoresLeituras = new List<SensorValoresLeituraModel>();
if (sensor != null) valoresLeituras = sensor.ValoresLeituras;
else if (bomba != null) valoresLeituras = bomba.ValoresLeituras;
else if (bico != null) valoresLeituras = bico.ValoresLeituras;
for (int i = 0; i < valoresLeituras.Where(x => x.posicao == Posicao).Count(); i++)
{
var valor = valoresLeituras.FirstOrDefault(x => x.indice == i);
if (valor != null)
{
valor.atual.valor = Parametros.Count > i ? (Parametros[i] + valor.offset) : -1;
}
}
}
2025-04-09 21:11:40 +00:00
public void ProcessarMensagem(CanMessage mensagem)
{
2025-05-01 18:27:01 +00:00
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)mensagem.DataRx[0];
byte ID_Num = mensagem.DataRx[1];
2025-04-09 21:11:40 +00:00
var data = mensagem.DataRx;
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
2025-04-09 21:11:40 +00:00
S_Code componente = DetectarComponenteDoID_Num(ID_Num);
Console.WriteLine($"[ATU] Componente={componente.ToString()}, ID_Num={ID_Num}, Data={FuncoesGlobais.ConverterComandoBytesParaTexto(data)}");
switch (componente)
2025-04-09 21:11:40 +00:00
{
case S_Code.sMOD:
2025-04-09 21:11:40 +00:00
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
T_Code tipoModulo = (T_Code)data[2];
bool conectado = data[3] == 1;
int versao = data[4];
2025-04-09 21:11:40 +00:00
Console.WriteLine($"[ATU] Resposta {ID_Num} recebida. Tipo={tipoModulo}, Conectado={conectado}, Versão={versao}");
2025-04-09 21:11:40 +00:00
Dados.DadosLeitura.Conectado = conectado;
Dados.DadosLeitura.Dispositivo = tipoModulo;
Dados.DadosLeitura.Versao = versao;
break;
}
}
break;
}
case S_Code.sTOD:
{
switch (posicao)
{
case CanMessagePosicaoDados.DadosAll:
{
double latenciaLoop = ConverterByteParaDouble(data, 2) * 100;
Dados.DadosLeitura.LatenciaLoop = Convert.ToInt32(latenciaLoop);
Console.WriteLine($"[ATU] Ciclo concluido. Latencia de loop: {latenciaLoop} ms");
break;
}
}
break;
2025-04-09 21:11:40 +00:00
}
case S_Code.sBIC:
{
switch (posicao)
{
case CanMessagePosicaoDados.Dados1:
{
Estado estado = (Estado)data[2];
2025-04-15 13:16:27 +00:00
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { estado });
break;
}
}
break;
}
case S_Code.sFLX:
{
switch (posicao)
{
case CanMessagePosicaoDados.Dados1:
{
double vazao = ConverterByteParaDouble(data, 2);
2025-04-15 13:16:27 +00:00
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { vazao });
break;
}
}
break;
}
case S_Code.sMAS:
{
switch (posicao)
{
case CanMessagePosicaoDados.Dados1:
{
double massa = ConverterByteParaDouble(data, 2);
2025-04-15 13:16:27 +00:00
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { massa });
break;
}
}
break;
}
case S_Code.sPRS:
{
switch (posicao)
{
case CanMessagePosicaoDados.Dados1:
{
double pressao = ConverterByteParaDouble(data, 2);
2025-04-15 13:16:27 +00:00
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { pressao });
break;
}
}
break;
}
case S_Code.sBMB:
{
switch (posicao)
{
case CanMessagePosicaoDados.Dados1:
{
Estado estado = (Estado)data[2];
int percentualPotencia = data[3];
int pressaoSp = data[4];
int pressaoAtual = data[5];
2025-04-15 13:16:27 +00:00
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { estado, percentualPotencia, pressaoSp, pressaoAtual });
break;
}
}
break;
}
2025-04-09 21:11:40 +00:00
}
Dados.DadosLeitura.UltimoComandoRespondido = DateTime.Now;
2025-04-09 21:11:40 +00:00
}
}
2024-01-03 10:52:37 +00:00
}