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

2006 lines
85 KiB
C#
Raw Normal View History

using AgroBase.Services;
2025-07-11 16:38:08 +00:00
using AgroBase.Services.Operadores;
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;
2025-07-23 15:14:50 +00:00
public double FrequenciaBase
{
get
{
return 1.0 / (_TaxaAmostragem / 1000.0);
}
}
2025-04-09 21:11:40 +00:00
public bool RequisitarDados { get; set; } = true;
2025-12-09 12:19:36 +00:00
public static int TempoLimiteConexao { get; set; } = 8000;
2025-07-23 15:14:50 +00:00
public bool Conectado
{
get
{
DateTime Agora = DateTime.Now;
bool modConectado = DadosLeitura.UltimoComandoRespondido.AddMilliseconds(TempoLimiteConexao) > Agora;
return modConectado;
2025-07-23 15:14:50 +00:00
}
}
public bool ConexaoAtiva
2025-04-09 21:11:40 +00:00
{
get
{
2025-07-11 16:38:08 +00:00
return HealthWorkerService.ModulosSaude.Any(x => x.modulo == Dispositivo && x.status == StatusModulo.Operante);
2025-04-09 21:11:40 +00:00
}
}
2025-07-11 16:38:08 +00:00
public bool AtuPronto { get; set; } = false;
2025-04-09 21:11:40 +00:00
public double AnguloBarraEsquerda { get; set; }
public double AnguloBarraDireita { get; set; }
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,
};
2025-11-24 16:05:50 +00:00
//public int QuantidadeBicos { get; set; } = 4;
2025-08-22 18:36:19 +00:00
public double DensidadeHerbicida { get; set; } = 1.0;
public List<AtuadorBicoModel> BicosPulverizadores { get; set; }
public List<AtuadorBombaModel> BombasPressurizadoras { get; set; }
public List<SensorModel> Sensores { get; set; }
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();
private SensorModel SensorAnguloBarraEsquerda
{
get
{
var sMAG = Sensores?.FirstOrDefault(x => x.Componente == S_Code.sMAG && x.ID.Contains("ESQ"));
return sMAG;
}
}
private SensorModel SensorAnguloBarraDireita
{
get
{
var sMAG = Sensores?.FirstOrDefault(x => x.Componente == S_Code.sMAG && x.ID.Contains("DIR"));
return sMAG;
}
}
public HerbicideCounterService ContadorCarga = new HerbicideCounterService(VariaveisEquipamento.CapacidadeReservatorio, VariaveisEquipamento.DensidadeHerbicida);
2024-04-01 11:03:25 +00:00
#region VAZAO
2026-05-21 22:48:36 +00:00
private SensorModel SensorFluxoLinha => Sensores.FirstOrDefault(x => x.Componente == S_Code.sFLX && x.ID == "FLXLN");
2026-05-21 22:48:36 +00:00
2024-04-01 11:03:25 +00:00
public double VolumeVazaoAferido { get; set; } = 0;
2026-05-21 22:48:36 +00:00
public double VazaoMaximaSensor_LMin { get; set; } = 20.0;
public double VazaoFluxoMLpSInstantanea => SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Fluxo)?.atual?.valor ?? 0;
2026-05-21 22:48:36 +00:00
public double VazaoFluxoMLpSInstantaneaCalc
2024-12-05 12:52:28 +00:00
{
2024-04-01 11:03:25 +00:00
get
{
2025-12-16 19:33:06 +00:00
int pulsos = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.QtdPulsos)?.atual?.valor ?? 0.0);
2026-05-21 22:48:36 +00:00
2025-12-16 19:33:06 +00:00
int periodo = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Periodo)?.atual?.valor ?? 0.0);
2026-05-21 22:48:36 +00:00
if (pulsos <= 0 || periodo <= 0)
return 0.0;
double frequencia = (double)pulsos / periodo * 1000.0;
// Fabricante: F = 8.1*q - 3, q em L/min
double q_L_min = (frequencia + 3.0) / 8.1;
2026-05-21 22:48:36 +00:00
if (q_L_min < 0)
q_L_min = 0;
if (q_L_min > VazaoMaximaSensor_LMin)
q_L_min = VazaoMaximaSensor_LMin;
return q_L_min * 1000.0 / 60.0;
}
}
public double VazaoFluxoMLpSReferencia
{
get
{
double direta = VazaoFluxoMLpSInstantanea;
if (direta > 0)
return direta;
return VazaoFluxoMLpSInstantaneaCalc;
2024-04-01 11:03:25 +00:00
}
}
2026-05-21 22:48:36 +00:00
private DateTime _ultimoRegistroVazao = DateTime.MinValue;
public double VazaoMediaMLs { get; set; }
public double VolumeVazadoML { get; set; }
public double TempoAtuado { get; set; }
2026-05-21 22:48:36 +00:00
private List<AtuadorBicoModel> bicosAtivosAnterior = new List<AtuadorBicoModel>();
2024-10-29 19:53:27 +00:00
public void AtualizaTempoAtuadoGeral()
{
2025-12-18 20:14:27 +00:00
DateTime agora = DateTime.Now;
2026-05-21 22:48:36 +00:00
var bicosAtivos = BicosPulverizadores.Where(x => x.Inicializado && x.ComandoAtuar).ToList();
2024-10-29 19:53:27 +00:00
2025-12-18 20:14:27 +00:00
bool algumBicoAtivo = bicosAtivos.Count > 0;
bool algumBicoAtivoAnterior = bicosAtivosAnterior?.Any() ?? false;
if (algumBicoAtivo && !algumBicoAtivoAnterior)
2026-05-21 22:48:36 +00:00
_ultimoRegistroVazao = agora;
2025-12-18 20:14:27 +00:00
if (!algumBicoAtivo && algumBicoAtivoAnterior)
{
AtualizaVazaoEVolume(bicosAtivosAnterior, agora);
2025-12-18 20:14:27 +00:00
_ultimoRegistroVazao = DateTime.MinValue;
foreach (var b in BicosPulverizadores)
b.VazaoInstantaneaMLs = 0;
}
2024-10-29 19:53:27 +00:00
2026-05-21 22:48:36 +00:00
if (algumBicoAtivo)
AtualizaVazaoEVolume(bicosAtivos, agora);
VazaoMediaMLs = TempoAtuado > 0 ? VolumeVazadoML / TempoAtuado : 0;
2025-12-18 20:14:27 +00:00
AtualizaPercentualErvas();
bicosAtivosAnterior = new List<AtuadorBicoModel>(bicosAtivos);
}
2026-05-21 22:48:36 +00:00
2025-12-18 20:14:27 +00:00
private void AtualizaVazaoEVolume(List<AtuadorBicoModel> bicosAtivos, DateTime agora)
2024-12-05 12:52:28 +00:00
{
2025-12-18 20:14:27 +00:00
if (bicosAtivos == null || bicosAtivos.Count == 0)
return;
2026-05-21 22:48:36 +00:00
if (_ultimoRegistroVazao == DateTime.MinValue)
{
_ultimoRegistroVazao = agora;
2024-12-05 12:52:28 +00:00
return;
2026-05-21 22:48:36 +00:00
}
2024-12-05 12:52:28 +00:00
2025-12-18 20:14:27 +00:00
double dt = (agora - _ultimoRegistroVazao).TotalSeconds;
_ultimoRegistroVazao = agora;
2026-05-21 22:48:36 +00:00
if (dt <= 0 || dt > 2.0)
return;
double vazaoTotalInst = VazaoFluxoMLpSReferencia;
if (vazaoTotalInst <= 0)
{
foreach (var bico in bicosAtivos)
bico.VazaoInstantaneaMLs = 0;
return;
}
VolumeVazadoML += vazaoTotalInst * dt;
TempoAtuado += dt;
2025-12-18 20:14:27 +00:00
double vazaoPorBicoInst = vazaoTotalInst / bicosAtivos.Count;
2024-12-05 12:52:28 +00:00
2025-12-18 20:14:27 +00:00
foreach (var bico in bicosAtivos)
2024-12-05 12:52:28 +00:00
{
2025-12-18 20:14:27 +00:00
bico.VazaoInstantaneaMLs = vazaoPorBicoInst;
bico.VolumeVazadoML += vazaoPorBicoInst * dt;
bico.TempoAtuado += dt;
2024-12-05 12:52:28 +00:00
2026-05-21 22:48:36 +00:00
bico.VazaoMediaMLs = bico.TempoAtuado > 0
? bico.VolumeVazadoML / bico.TempoAtuado
: 0;
}
}
2026-05-21 22:48:36 +00:00
private void AtualizaPercentualErvas()
{
2026-05-21 22:48:36 +00:00
double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento?.Movimentacao?.TempoMovimentoSegs ?? 0;
PercentualErvasTerreno = tempoTotalOperacao > 0 ? Math.Round((TempoAtuado / tempoTotalOperacao) * 100.0, 2) : 0;
2024-12-05 12:52:28 +00:00
}
2024-04-01 11:03:25 +00:00
#endregion
#region PRESSAO
private SensorModel SensorPressaoLinha
2024-12-02 19:12:39 +00:00
{
get
{
return Sensores.FirstOrDefault(x => x.Componente == S_Code.sPRS && x.ID == "PRSLN");
2024-12-02 19:12:39 +00:00
}
}
public double _PressaoVmin { get; set; } = 0.0;
public double _PressaoVmax { get; set; } = 4.5;
public double _PressaoMax { get; set; } = 174.045; // 1,2 MPa
public double PressaoLinha => SensorPressaoLinha?.ValoresLeituras.FirstOrDefault(x => x.funcao == FuncoesPinout.Pressao)?.atual?.valor ?? 0;
2024-04-01 11:03:25 +00:00
public double PressaoLinhaCalc
{
get
{
double _LeituraPressao = SensorPressaoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.LeituraBruta)?.atual?.valor ?? 0;
double tensao = FuncoesMatematicas.Map(_LeituraPressao, 0, 4095, 0, 3300) / 1000.0;
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,
// 11 ~ 50
Sensores = new List<SensorModel>()
2024-04-01 11:03:25 +00:00
{
// pressao 11 ~ 20
new SensorModel()
2024-04-01 11:03:25 +00:00
{
ID = "PRSLN",
ID_Num = 11,
Descricao = "Pressão na linha principal",
Componente = S_Code.sPRS,
Aferir = true,
2025-05-07 16:54:45 +00:00
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.Pressao,
},
Parametros = new List<SensorParametroModel>()
{
new SensorParametroModel()
{
Descricao = "Vmin",
Valor = "0",
QtdBytes = 1,
Escalar = false,
Enviar = false
},
new SensorParametroModel()
{
Descricao = "Vmax",
Valor = "4.5",
QtdBytes = 1,
Escalar = true,
Enviar = false
},
new SensorParametroModel()
{
Descricao = "Pmax",
Valor = "174",
QtdBytes = 1,
Escalar = false,
Enviar = false
},
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraBruta,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Pressao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
analise_health = true,
maximo = 120,
minimo = 0,
nominal = 85,
unidade_medida = "PSI"
}
}
},
// fluxo 21 ~ 30
new SensorModel()
{
ID = "FLXLN",
ID_Num = 21,
Descricao = "Fluxo na linha principal",
Componente = S_Code.sFLX,
2025-04-09 21:11:40 +00:00
Aferir = true,
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.QtdPulsos,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Periodo,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Fluxo,
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
analise_health = true,
maximo = 20,
minimo = 0,
nominal = 0,
unidade_medida = "mL/s"
}
}
},
// massa 31 ~ 35
new SensorModel()
{
ID = "MASRS",
ID_Num = 31,
Descricao = "Massa do reservatório de herbicida",
Componente = S_Code.sMAS,
2025-04-09 21:11:40 +00:00
Aferir = true,
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",
2025-05-01 18:27:01 +00:00
Enviar = true,
Escalar = true,
2025-05-01 18:27:01 +00:00
QtdBytes = 2,
2025-12-16 19:33:06 +00:00
Valor = "0.0"
2025-05-01 18:27:01 +00:00
}
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraBruta,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Massa,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
analise_health = true,
maximo = 35,
minimo = 0,
nominal = 30,
unidade_medida = "Kg"
}
2025-05-01 18:27:01 +00:00
}
},
// pressao 36 ~ 40
new SensorModel()
{
ID = "BOTLAV",
ID_Num = 36,
Descricao = "Botão para lavagem do sistema hidráulico",
Componente = S_Code.sBOT,
Aferir = true,
Mandatorio = false,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.Botao,
},
Parametros = new List<SensorParametroModel>(),
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Botao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraBruta,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.EstadoLeitura,
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
},
}
},
// magnetico 41 ~ 50
2025-12-04 13:51:11 +00:00
new SensorModel()
{
ID = "MAGESQ",
Descricao = "Angulo Barra Esquerda",
ID_Num = 41,
2025-12-04 13:51:11 +00:00
Componente = S_Code.sMAG,
Aferir = true,
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.I2C,
},
Parametros = new List<SensorParametroModel>()
{
new SensorParametroModel()
{
Descricao = "Endereço I2C",
Valor = "0x36",
QtdBytes = 1,
Escalar = false,
Enviar = true
},
new SensorParametroModel()
{
Descricao = "Canal MUX",
Valor = "0",
QtdBytes = 1,
Escalar = false,
Enviar = true
},
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraBruta,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
unidade_medida = ""
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraAngulo,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
unidade_medida = "°"
},
}
},
new SensorModel()
{
ID = "MAGDIR",
Descricao = "Angulo Barra Direita",
ID_Num = 42,
2025-12-04 13:51:11 +00:00
Componente = S_Code.sMAG,
Aferir = true,
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.I2C,
},
Parametros = new List<SensorParametroModel>()
{
new SensorParametroModel()
{
Descricao = "Endereço I2C",
Valor = "0x36",
QtdBytes = 1,
Escalar = false,
Enviar = true
},
new SensorParametroModel()
{
Descricao = "Canal MUX",
Valor = "1",
QtdBytes = 1,
Escalar = false,
Enviar = true
},
},
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraBruta,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
unidade_medida = ""
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraAngulo,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
unidade_medida = "°"
},
}
},
},
// 51 ~ 60
BombasPressurizadoras = new List<AtuadorBombaModel>()
{
new AtuadorBombaModel()
{
ID = "BMBLN",
ID_Num = 51,
Sensor_ID_Num = 11,
ComandoAtuar = false,
PressaoSP = 100,
Componente = S_Code.sBMB,
Comandar = true,
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.IN1,
FuncoesPinout.IN2,
},
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.PotenciaSP,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Potencia,
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.PressaoSP,
posicao = CanMessagePosicaoDados.Dados1,
indice = 3,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Pressao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 4,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.ModoControleBomba,
posicao = CanMessagePosicaoDados.Dados1,
indice = 5,
}
},
Controle = new AtuadorBombaModel.BombaModoControleModel()
{
Modo = ModoControleBomba.PID,
PotenciaMinPID = 40,
Kp = 6.0,
Ki = 0.2,
Kd = 0.0,
}
},
new AtuadorBombaModel()
{
ID = "BMBAGT",
ID_Num = 52,
Sensor_ID_Num = -1,
ComandoAtuar = false,
Componente = S_Code.sBMB,
PotenciaSP = 100,
Comandar = true,
Mandatorio = true,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.IN1,
FuncoesPinout.IN2,
},
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.PotenciaSP,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Potencia,
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.PressaoSP,
posicao = CanMessagePosicaoDados.Dados1,
indice = 3,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Pressao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 4,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.ModoControleBomba,
posicao = CanMessagePosicaoDados.Dados1,
indice = 5,
}
},
Controle = new AtuadorBombaModel.BombaModoControleModel()
{
Modo = ModoControleBomba.OnOff,
}
},
},
// 61 ~ 70
BicosPulverizadores = new List<AtuadorBicoModel>(),
2024-01-03 10:52:37 +00:00
};
2025-11-24 16:05:50 +00:00
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++)
2024-01-03 10:52:37 +00:00
{
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 = 60 + posicao,
Componente = S_Code.sBIC,
2025-04-09 21:11:40 +00:00
Posicao = posicao,
Inicializado = false,
AnguloNeutro = 90,
AnguloControle = 90,
AnguloAbertura = 30,
2025-04-09 21:11:40 +00:00
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,
FuncoesPinout.Servo,
2024-01-03 10:52:37 +00:00
},
2025-12-18 20:14:27 +00:00
VazaoMediaMLs = 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,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.ServoAnguloLeitura,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
}
}
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;
2025-07-11 16:38:08 +00:00
Dados.AtuPronto = false;
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;
x.AnguloControle = 0;
x.VazaoInstantaneaMLs = 0;
x.VolumeVazadoML = 0;
x.VazaoMediaMLs = 0;
x.TempoAtuado = 0;
x.Atuacoes = 0;
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.PotenciaSP = 0;
x.PressaoSP = 0;
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._ultimoRegistroVazao = DateTime.MinValue;
Dados.VolumeVazadoML = 0;
Dados.VazaoMediaMLs = 0;
Dados.TempoAtuado = 0;
Dados.AnguloBarraDireita = 0;
Dados.AnguloBarraEsquerda = 0;
Dados.PercentualErvasTerreno = 0;
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-07-17 17:53:42 +00:00
if (!CanManager.CanService.IsConnected) return false;
2025-05-06 18:47:59 +00:00
if (Variaveis.OperacaoEmAndamento.DispAtu == null) return false;
2025-07-17 17:53:42 +00:00
CanManager.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);
2025-07-23 15:14:50 +00:00
if (Conectado)
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
}
2025-07-23 15:14:50 +00:00
return Conectado;
}
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,
2025-07-17 17:53:42 +00:00
Endereco = CanManager.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
});
Variaveis.OperacaoEmAndamento.ModsCalibragem[Dispositivo] = new Dictionary<string, bool>();
Variaveis.OperacaoEmAndamento.Sensoriamento.InserirLog(Dispositivo, StatusModulo.Conectado, 0, "Dispositivo conectado");
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-12-18 18:11:30 +00:00
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComandoReset()
{
return (
Variaveis.ID_Num_sMOD,
CanMessagePosicaoDados.Command1,
new byte[]
{
(byte)Estado.Reset
}
);
}
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
//var sensoresConfig = SensoresConfig(Conectar, configurarTodos);
//config.AddRange(sensoresConfig);
2025-04-09 21:11:40 +00:00
// Adicionar configurações dos Bicos
//var bicosConfig = BicosConfig(Conectar, configurarTodos);
//config.AddRange(bicosConfig);
2025-04-09 21:11:40 +00:00
// Adicionar configurações das Bombas
//var bombasConfig = BombasConfig(Conectar, configurarTodos);
//config.AddRange(bombasConfig);
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[])> ModConfig(bool Conectar)
{
2025-07-23 15:14:50 +00:00
var config = new List<byte>
2025-04-09 21:11:40 +00:00
{
(byte)(Conectar ? 1 : 0),
2026-04-08 20:10:57 +00:00
(byte)(_TaxaAmostragem / 1000),
2025-04-09 21:11:40 +00:00
(byte)(RequisitarDados ? 1 : 0),
};
2025-07-23 15:14:50 +00:00
config.AddRange(PinoutModel.PinoProtocolo(Pinout, Funcoes, false));
2025-05-01 18:27:01 +00:00
return new List<(int, CanMessagePosicaoDados, byte[])>
{
2025-07-23 15:14:50 +00:00
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config1, config.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()
{
2025-12-18 18:11:30 +00:00
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-09-16 13:31:32 +00:00
VerificaControleLeitura();
}
2025-04-16 16:44:06 +00:00
AtualizaComponentesIniciados();
}
2025-09-16 13:31:32 +00:00
private void VerificaControleLeitura()
{
2025-12-18 18:11:30 +00:00
if (Variaveis.Fechando) return;
bool operacaoConcluida = Variaveis.OperacaoEmAndamento.Sensoriamento.StatusOperacao == StatusOperacao.Concluido;
bool pulverizadorAutomatico = Variaveis.OperacaoEmAndamento.Parametros?.Controle?.PulverizadorAutomatico ?? false;
foreach (var bico in BicosPulverizadores.Where(x => x.Inicializado))
2025-09-16 13:31:32 +00:00
{
bool statusDesejado = bico.Comandar && bico.ComandoAtuar;
if (pulverizadorAutomatico)
statusDesejado &= !operacaoConcluida && Variaveis.OperacaoEmAndamento.Iniciado;
Estado estadoDesejado = statusDesejado ? Estado.Ligado : Estado.Desligado;
double anguloDesejado = statusDesejado ? bico.AnguloControle : bico.AnguloNeutro;
bool estadoDivergente = estadoDesejado != bico._EstadoLeitura;
bool anguloDivergente = statusDesejado && Math.Abs(anguloDesejado - bico._AnguloBicoLeitura) > 0.01;
if (estadoDivergente || anguloDivergente)
2025-09-16 13:31:32 +00:00
{
GeneralJoystick.EnviarComandoAtuador(
bico.Componente,
bico.ID,
Status: statusDesejado,
Valores: new List<double?>() { anguloDesejado }
);
2025-09-16 13:31:32 +00:00
}
}
2025-09-16 13:31:32 +00:00
foreach (var bomba in BombasPressurizadoras.Where(x => x.Inicializado))
{
bool statusDesejado = bomba.Comandar && bomba.ComandoAtuar;
if (pulverizadorAutomatico)
statusDesejado &= ContadorCarga.PulverizadorLiberado && !operacaoConcluida && Variaveis.OperacaoEmAndamento.Iniciado;
Estado estadoDesejado = statusDesejado ? Estado.Ligado : Estado.Desligado;
double potenciaDesejada = statusDesejado ? bomba.PotenciaSP : 0;
double pressaoDesejada = statusDesejado ? bomba.PressaoSP : 0;
bool estadoDivergente = estadoDesejado != bomba._EstadoLeitura;
bool potenciaDivergente = Math.Abs(bomba._PotenciaSP - potenciaDesejada) > 1;
bool pressaoDivergente = bomba.Sensor_ID_Num > -1 && Math.Abs(bomba._PressaoSP - pressaoDesejada) > 0.05;
if (estadoDivergente || potenciaDivergente || pressaoDivergente)
{
GeneralJoystick.EnviarComandoAtuador(
bomba.Componente,
bomba.ID,
Status: statusDesejado,
Valores: new List<double?>() { potenciaDesejada, pressaoDesejada },
Comando: CanMessagePosicaoDados.Command1
);
2025-09-16 13:31:32 +00:00
}
}
2025-09-16 13:31:32 +00:00
}
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
}
}
2025-07-11 16:38:08 +00:00
public async Task<bool> RealizarTestesIniciais(bool forcar)
2025-07-11 16:38:08 +00:00
{
var calAtu = Variaveis.OperacaoEmAndamento.ModsCalibragem[Dispositivo];
2025-07-11 16:38:08 +00:00
// Ligar bomba
foreach (var Bomba in BombasPressurizadoras.Where(x => x.Comandar))
2025-07-11 16:38:08 +00:00
{
calAtu.TryGetValue(Bomba.ID, out var cal);
if (!forcar && cal && calAtu[Bomba.ID]) continue;
calAtu[Bomba.ID] = false;
// Sem herbicida no reservatorio, bomba nao precisa ligar
if (!Bomba.Inicializado || ContadorCarga.PercentualAtual < VariaveisEquipamento.PercentualReservatorioMin)
{
Variaveis.MostrarLog($"[AtuadorModel] [RealizarTestesIniciais] Bomba não iniciada ou nível do reservatório baixo, não irá ligar a bomba {Bomba.ID}");
continue;
}
Bomba.PotenciaSP = 100;
if (Bomba.ID == "BMBLN")
{
Bomba.Controle.Modo = Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuModoControle;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { (int)Bomba.Controle.Modo, Bomba.Controle.PotenciaMinPID, Bomba.Controle.Kp, Bomba.Controle.Ki, Bomba.Controle.Kd }, Comando: CanMessagePosicaoDados.Command2, Forcar: true);
Bomba.PressaoSP = Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { Bomba.PotenciaSP, Bomba.PressaoSP }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
else
{
Bomba.PressaoSP = -1;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { Bomba.PotenciaSP, Bomba.PressaoSP }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
if (Bomba.Sensor_ID_Num == -1)
{
Variaveis.MostrarLog($"[AtuadorModel] [RealizarTestesIniciais] Bomba {Bomba.ID} não possui um sensor de pressão, será controlada mecanicamente pelo pressostato");
calAtu[Bomba.ID] = true;
continue;
}
2025-07-11 16:38:08 +00:00
await FuncoesGlobais.AguardarCondicaoAsync(Bomba.AtingiuPressao, 3000, 200);
bool BombaOk = Bomba.AtingiuPressao();
if (BombaOk)
{
calAtu[Bomba.ID] = true;
}
else
{
foreach (var Bico in BicosPulverizadores.Where(x => x.Comandar && x.Inicializado))
{
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: true, Forcar: true);
}
2025-07-11 16:38:08 +00:00
await Task.Delay(3000);
2025-07-11 16:38:08 +00:00
foreach (var Bico in BicosPulverizadores.Where(x => x.Comandar && x.Inicializado))
{
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: false, Forcar: true);
}
await FuncoesGlobais.AguardarCondicaoAsync(Bomba.AtingiuPressao, 4000, 200);
BombaOk = Bomba.AtingiuPressao();
calAtu[Bomba.ID] = BombaOk;
}
2025-07-11 16:38:08 +00:00
}
// Testar os bicos
foreach (var Bico in BicosPulverizadores.Where(x => x.Comandar))
2025-07-11 16:38:08 +00:00
{
calAtu.TryGetValue(Bico.ID, out var cal);
if (!forcar && cal && calAtu[Bico.ID]) continue;
calAtu[Bico.ID] = false;
2025-07-11 16:38:08 +00:00
if (Bico.Inicializado)
{
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: true, Forcar: true);
2025-07-11 16:38:08 +00:00
await Task.Delay(200);
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: false, Forcar: true);
await Task.Delay(200);
calAtu[Bico.ID] = true;
2025-07-11 16:38:08 +00:00
}
}
await Task.Delay(1000);
bool sucesso = calAtu.All(x => x.Value);
return sucesso;
2025-07-11 16:38:08 +00:00
}
public List<Task> RealizarCalibragemAsync(bool forcar)
2025-07-11 16:38:08 +00:00
{
2025-07-17 11:19:42 +00:00
List<Task> tasks = new List<Task>();
2025-07-11 16:38:08 +00:00
var DispAtu = Variaveis.OperacaoEmAndamento.DispAtu;
if (DispAtu != null)
{
tasks.Add(DispAtu.Dados.RealizarTestesIniciais(forcar).ContinueWith(t => {
2025-07-17 11:19:42 +00:00
if (t.IsFaulted)
Variaveis.MostrarLog($"[AtuadorModel] [RealizarCalibragemAsync] Erro no referenciamento do módulo {Modulo_ID}: {t.Exception?.InnerException?.Message}");
2025-07-17 11:19:42 +00:00
if (t.IsCompleted)
{
var calAtu = Variaveis.OperacaoEmAndamento.ModsCalibragem[T_Code.Atu];
var v = calAtu.Select(x => $"{x.Key} " + (x.Value ? "Sim" : "Não"));
Variaveis.MostrarLog($"[AtuadorModel] [RealizarCalibragemAsync] Task de referenciamento do módulo {Modulo_ID} finalizada: " + string.Join(", ", v));
}
2025-07-17 11:19:42 +00:00
}));
}
2025-07-17 11:19:42 +00:00
return tasks;
2025-07-11 16:38:08 +00:00
}
public void RequisitarDadosSensoresExternos()
{
if (SensorAnguloBarraEsquerda != null)
RequisitarDadosModulo(SensorAnguloBarraEsquerda.ID_Num, CanMessagePosicaoDados.Dados1, CanMessagePosicaoDados.Dados1, true);
if (SensorAnguloBarraDireita != null)
RequisitarDadosModulo(SensorAnguloBarraDireita.ID_Num, CanMessagePosicaoDados.Dados1, CanMessagePosicaoDados.Dados1, true);
}
public void AtualizarDadosSensoresExternos(S_Code componente, int id_num)
{
switch (componente)
{
case S_Code.sMAG:
{
var sensor = Sensores.FirstOrDefault(x => x.ID_Num == id_num);
if (sensor == null) return;
double angulo = sensor.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.LeituraAngulo)?.atual?.valor ?? double.NaN;
if (sensor.ID_Num == SensorAnguloBarraEsquerda.ID_Num)
AnguloBarraEsquerda = angulo;
else if (sensor.ID_Num == SensorAnguloBarraDireita.ID_Num)
AnguloBarraDireita = angulo;
}
break;
case S_Code.sBIC:
{
var bico = BicosPulverizadores.FirstOrDefault(x => x.ID_Num == id_num);
if (bico == null) return;
if (bico._estadoLeituraAnterior == Estado.Desligado && bico._EstadoLeitura == Estado.Ligado)
{
bico.Atuacoes++;
bico._estadoLeituraAnterior = bico._EstadoLeitura;
}
}
break;
}
}
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; }
public double AnguloNeutro { get; set; }
public double AnguloControle { get; set; }
public double AnguloAbertura { get; set; }
public bool ComandoAtuar { get; set; }
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; }
2025-12-18 20:14:27 +00:00
public double VazaoMediaMLs { get; set; }
public double VazaoInstantaneaMLs { get; set; }
public double VolumeVazadoML { 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; }
public Estado _estadoLeituraAnterior { get; set; } = Estado.Desligado;
public Estado _EstadoLeitura => (Estado)(ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.EstadoLeitura)?.atual?.valor ?? 0);
2025-12-16 19:33:06 +00:00
public int _AnguloBicoLeitura => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.LeituraAngulo)?.atual?.valor ?? 0;
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),
0x00, //(byte)Servo_ID_Num,
2025-04-09 21:11:40 +00:00
(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),
(byte)AnguloControle
2025-04-09 21:11:40 +00:00
}
);
2024-01-03 10:52:37 +00:00
}
2024-03-11 20:04:48 +00:00
public List<List<double[]>> TrechosAtuado { get; set; } = new List<List<double[]>>();
public int Atuacoes { get; set; } = 0;
public double TempoAtuado { get; set; } = 0;
2024-10-29 19:53:27 +00:00
2024-03-11 20:04:48 +00:00
public AtuadorBicoModel Clone()
{
AtuadorBicoModel clone = new AtuadorBicoModel()
{
Comandar = Comandar,
AtuacaoNivelAlto = AtuacaoNivelAlto,
Atuacoes = Atuacoes,
ComandoAtuar = ComandoAtuar,
AnguloAbertura = AnguloAbertura,
AnguloControle = AnguloControle,
Inicializado = Inicializado,
Mandatorio = Mandatorio,
Componente = Componente,
Funcoes = Funcoes,
ID = ID,
2025-04-09 21:11:40 +00:00
ID_Num = ID_Num,
VolumeVazadoML = VolumeVazadoML,
TrechosAtuado = TrechosAtuado,
VazaoInstantaneaMLs = VazaoInstantaneaMLs,
_estadoLeituraAnterior = _estadoLeituraAnterior,
ValoresLeituras = new List<SensorValoresLeituraModel>(ValoresLeituras),
2025-12-18 20:14:27 +00:00
VazaoMediaMLs = VazaoMediaMLs,
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 double PotenciaSP { get; set; }
public double PressaoSP { get; set; }
public S_Code Componente { get; set; } = S_Code.sBMB;
public int Sensor_ID_Num { get; set; }
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);
}
}
public List<FuncoesPinout> Funcoes { get; set; }
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; }
public BombaModoControleModel Controle { get; set; }
public Estado _EstadoLeitura => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.EstadoLeitura)?.atual?.valor ?? Estado.Desligado;
public double _Potencia => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Potencia)?.atual?.valor ?? 0;
public bool _BombaLigada => _Potencia > 0;
public double _PressaoSP => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.PressaoSP)?.atual?.valor ?? 0;
public double _PotenciaSP => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.PotenciaSP)?.atual?.valor ?? 0;
public double _PressaoAtual => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Pressao)?.atual?.valor ?? 0;
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)PressaoSP,
(byte)Sensor_ID_Num,
(byte)(pinout.Pinos.FirstOrDefault(x => x.ComponenteID == ID && x.Funcao == FuncoesPinout.IN1)?.Pino ?? PinoutUtils.PINO_INVALIDO),
(byte)(pinout.Pinos.FirstOrDefault(x => x.ComponenteID == ID && x.Funcao == FuncoesPinout.IN2)?.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()),
};
2024-04-01 11:03:25 +00:00
}
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando(CanMessagePosicaoDados comando)
2024-04-01 11:03:25 +00:00
{
byte ConverterPIDParaByte(double valor)
{
// Escala x10:
// 8.0 -> 80
// 0.4 -> 4
// 1.5 -> 15
valor = FuncoesMatematicas.Clamp(valor, 0.0, 25.5);
return (byte)Math.Round(valor * 10.0);
}
switch (comando)
{
case CanMessagePosicaoDados.Command1:
return (
ID_Num,
comando,
new byte[]
{
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
(byte)(PotenciaSP),
(byte)(PressaoSP)
}
);
case CanMessagePosicaoDados.Command2:
return (
ID_Num,
comando,
new byte[]
{
(byte)Controle.Modo,
(byte)Controle.PotenciaMinPID,
ConverterPIDParaByte(Controle.Kp),
ConverterPIDParaByte(Controle.Ki),
ConverterPIDParaByte(Controle.Kd),
}
);
default:
throw new ArgumentOutOfRangeException(
nameof(comando),
comando,
"Comando CAN não suportado pela bomba pressurizadora.");
}
2024-04-01 11:03:25 +00:00
}
public bool AtingiuPressao() => _PressaoAtual >= Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
public class BombaModoControleModel
{
public ModoControleBomba Modo { get; set; } = ModoControleBomba.OnOff;
public double PotenciaMinPID { get; set; } = 30.0;
public double Kp { get; set; } = 6.0;
public double Ki { get; set; } = 0.2;
public double Kd { get; set; } = 0.0;
}
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);
}
}
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; }
public List<AtuadorBombaModel> BombasPressurizadoras { get; set; }
public List<SensorModel> Sensores { get; set; }
public List<SensorServoModel> Servos { get; set; }
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;
}
2025-12-04 13:51:11 +00:00
private ushort Converter2BytesU16(byte[] data, int idx)
{
return (ushort)((data[idx] << 8) | data[idx + 1]);
}
private double ConverterAngle100(byte[] data, int idx)
{
ushort v = (ushort)((data[idx] << 8) | data[idx + 1]);
return v / 100.0;
}
private S_Code DetectarComponenteDoID_Num(int ID_Num)
{
if (ID_Num == Variaveis.ID_Num_sMOD) return S_Code.sMOD;
if (ID_Num == Variaveis.ID_Num_sTOD) return S_Code.sTOD;
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-07-23 15:14:50 +00:00
private void AtualizarDados(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++)
{
2025-07-23 15:14:50 +00:00
try
{
2025-07-23 15:14:50 +00:00
var valor = valoresLeituras.FirstOrDefault(x => x.posicao == Posicao && x.indice == i);
if (valor != null)
{
var v = Parametros.Count > i ? (Parametros[i]) : -1;
if (v is sbyte || v is byte || v is short || v is ushort || v is int || v is uint || v is long || v is ulong || v is float || v is double || v is decimal)
{
v += valor.offset;
valor.atual.valor = v;
}
else
{
valor.atual.valor = v;
}
if (Posicao == CanMessagePosicaoDados.Status)
{
if (sensor != null)
sensor.Inicializado = v;
if (bomba != null)
bomba.Inicializado = v;
if (bico != null)
bico.Inicializado = v;
}
}
}
catch (Exception ex)
{
}
}
}
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;
S_Code componente = DetectarComponenteDoID_Num(ID_Num);
2025-07-23 15:14:50 +00:00
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
//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
2025-08-22 18:36:19 +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);
2025-08-22 18:36:19 +00:00
//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)
{
2025-07-23 15:14:50 +00:00
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
Estado estado = (Estado)data[2];
int angulo = data[3];
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado, angulo });
break;
}
}
break;
}
case S_Code.sFLX:
{
switch (posicao)
{
2025-07-23 15:14:50 +00:00
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
int qtdPulsos = data[2];
ushort periodo = Converter2BytesU16(data, 3);
double vazao = ConverterByteParaDouble(data, 5);
//Variaveis.MostrarLog($"[AtuadorModel] Vazao: {vazao}, pulsos: {qtdPulsos}, Periodo: {periodo}");
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { qtdPulsos, periodo, vazao });
break;
}
}
break;
}
case S_Code.sMAS:
{
switch (posicao)
{
2025-07-23 15:14:50 +00:00
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
double raw = ConverterByteParaDouble(data, 2);
double massa = ConverterByteParaDouble(data, 4);
//Variaveis.MostrarLog($"[AtuadorModel] Massa: {massa}, Raw: {raw}");
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { raw, massa });
break;
}
}
break;
}
case S_Code.sPRS:
{
switch (posicao)
{
2025-07-23 15:14:50 +00:00
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
ushort raw = Converter2BytesU16(data, 2);
double pressao = ConverterByteParaDouble(data, 4);
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { raw, pressao });
break;
}
}
break;
}
case S_Code.sBMB:
{
switch (posicao)
{
2025-07-23 15:14:50 +00:00
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
bool MalhaFechada = data[3] == 1;
2025-07-23 15:14:50 +00:00
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
Estado estado = (Estado)data[2];
int potenciaSp = data[3];
int percentualPotencia = data[4];
int pressaoSp = data[5];
int pressaoAtual = data[6];
ModoControleBomba modo = (ModoControleBomba)data[7];
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado, potenciaSp, percentualPotencia, pressaoSp, pressaoAtual, modo });
break;
}
}
break;
}
2025-12-04 13:51:11 +00:00
case S_Code.sMAG:
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
ushort raw = Converter2BytesU16(data, 2);
double angle = ConverterAngle100(data, 4);
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { raw, angle });
//Console.WriteLine($"[sMAG] {ID_Num}, Raw: {raw}, Angulo: {angle}");
break;
}
}
break;
}
case S_Code.sBOT:
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
bool pressionado = data[2] == 1;
bool leitura = data[3] == 1;
bool mudou = data[4] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { pressionado, leitura, mudou });
break;
}
}
break;
}
2025-04-09 21:11:40 +00:00
}
Dados.DadosLeitura.UltimoComandoRespondido = DateTime.Now;
Variaveis.OperacaoEmAndamento.DispAtu.Dados.AtualizarDadosSensoresExternos(componente, ID_Num);
2025-04-09 21:11:40 +00:00
}
}
2024-01-03 10:52:37 +00:00
}