1882 lines
80 KiB
C#
1882 lines
80 KiB
C#
using AgroBase.Services;
|
||
using AgroBase.Services.Operadores;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Forms;
|
||
using static AgroBase.Models.Enums;
|
||
|
||
namespace AgroBase.Models.Modules
|
||
{
|
||
public class AtuadorModel : DispositivoBaseModel
|
||
{
|
||
public T_Code Dispositivo { get; set; } = T_Code.Atu;
|
||
public string Modulo_ID { get; set; } = T_Code.Atu.ToString();
|
||
public byte _EnderecoCAN_Tx { get; set; } = 0x13;
|
||
public byte _EnderecoCAN_Rx { get; set; } = 0x14;
|
||
public int _TaxaAmostragem { get; set; } = 1000;
|
||
public double FrequenciaBase
|
||
{
|
||
get
|
||
{
|
||
return 1.0 / (_TaxaAmostragem / 1000.0);
|
||
}
|
||
}
|
||
public bool RequisitarDados { get; set; } = true;
|
||
public static int TempoLimiteConexao { get; set; } = 8000;
|
||
public bool Conectado
|
||
{
|
||
get
|
||
{
|
||
DateTime Agora = DateTime.Now;
|
||
bool modConectado = DadosLeitura.UltimoComandoRespondido.AddMilliseconds(TempoLimiteConexao) > Agora;
|
||
return modConectado;
|
||
}
|
||
}
|
||
public bool ConexaoAtiva
|
||
{
|
||
get
|
||
{
|
||
return HealthWorkerService.ModulosSaude.Any(x => x.modulo == Dispositivo && x.status == StatusModulo.Operante);
|
||
}
|
||
}
|
||
public bool AtuPronto { get; set; } = false;
|
||
|
||
public double AnguloBarraEsquerda { get; set; }
|
||
public double AnguloBarraDireita { get; set; }
|
||
public double AnguloBarraAltura { get; set; }
|
||
|
||
public static PinoutDataModel Pinout { get; set; }
|
||
public static List<FuncoesPinout> Funcoes { get; set; } = new List<FuncoesPinout>()
|
||
{
|
||
FuncoesPinout.SDA,
|
||
FuncoesPinout.SCL,
|
||
};
|
||
//public int QuantidadeBicos { get; set; } = 4;
|
||
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;
|
||
|
||
public AsyncTaskTimerModel tmrRegistrador;
|
||
private int _TempoReconexaoComponentes = 5;
|
||
private int _VezesLeituraReconexao = 0;
|
||
public AtuadorMensagemJsonModel DadosLeitura { get; set; } = new AtuadorMensagemJsonModel();
|
||
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;
|
||
}
|
||
}
|
||
private SensorModel SensorAnguloBarraAltura
|
||
{
|
||
get
|
||
{
|
||
var sMAG = Sensores?.FirstOrDefault(x => x.Componente == S_Code.sMAG && x.ID.Contains("ALT"));
|
||
return sMAG;
|
||
}
|
||
}
|
||
|
||
public HerbicideCounterService ContadorCarga = new HerbicideCounterService(VariaveisEquipamento.CapacidadeReservatorio, VariaveisEquipamento.DensidadeHerbicida);
|
||
|
||
#region VAZAO
|
||
private SensorModel SensorFluxoLinha => Sensores.FirstOrDefault(x => x.Componente == S_Code.sFLX && x.ID == "FLXLN");
|
||
public double VolumeVazaoAferido { get; set; } = 0;
|
||
public double _FluxoMlRef { get; set; } = 600;
|
||
public double _FluxoPulsoRef { get; set; } = 538;
|
||
public double VazaoFluxoMLpSInstantanea => SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Fluxo)?.atual?.valor ?? 0;
|
||
public double VazaoFluxoMLpSInstantaneaCalc
|
||
{
|
||
get
|
||
{
|
||
int pulsos = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.QtdPulsos)?.atual?.valor ?? 0.0);
|
||
int periodo = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Periodo)?.atual?.valor ?? 0.0);
|
||
if (pulsos <= 0 || periodo <= 0) return 0.0;
|
||
|
||
double frequencia = (double)pulsos / (double)periodo * 1000.0; // Hz
|
||
|
||
// Equação do fabricante: F = 8.1*q - 3 (q em L/min)
|
||
double q_L_min = (frequencia + 3.0) / 8.1;
|
||
// Limites físicos do sensor (do próprio anúncio): 0.3–10 L/min
|
||
if (q_L_min < 0) q_L_min = 0; // evita negativo perto do zero
|
||
if (q_L_min > 10.0) q_L_min = 10.0; // opcional: clamp no máximo
|
||
// Converte para mL/s
|
||
double q_mL_s = q_L_min * (1000.0 / 60.0);
|
||
return q_mL_s;
|
||
}
|
||
}
|
||
private DateTime _ultimoRegistroVazao; // Armazena o horário da última atualização
|
||
public double VazaoMediaMLs { get; set; }
|
||
public double VolumeVazadoML { get; set; }
|
||
public double TempoAtuado { get; set; }
|
||
private List<AtuadorBicoModel> bicosAtivosAnterior;
|
||
public void AtualizaTempoAtuadoGeral()
|
||
{
|
||
DateTime agora = DateTime.Now;
|
||
|
||
// Quem está ativo AGORA
|
||
var bicosAtivos = BicosPulverizadores.Where(x => x.Inicializado && x._EstadoLeitura == Estado.Ligado).ToList();
|
||
|
||
bool algumBicoAtivo = bicosAtivos.Count > 0;
|
||
|
||
bool algumBicoAtivoAnterior = bicosAtivosAnterior?.Any() ?? false;
|
||
|
||
// Início de uma "sessão" (transição OFF -> ON)
|
||
if (algumBicoAtivo && !algumBicoAtivoAnterior)
|
||
{
|
||
_ultimoRegistroVazao = agora; // inicia integração a partir daqui
|
||
|
||
// (opcional) se você quer métricas por sessão, zere volumes/médias aqui
|
||
// foreach (var b in BicosPulverizadores) { b.VolumeVazadoML = 0; b.VazaoMediaMLs = 0; }
|
||
// _tempoAtuadoBicoSeg.Clear();
|
||
}
|
||
|
||
// Fim de sessão (transição ON -> OFF)
|
||
if (!algumBicoAtivo && algumBicoAtivoAnterior)
|
||
{
|
||
AtualizaVazaoEVolume(bicosAtivosAnterior, agora);
|
||
|
||
_ultimoRegistroVazao = DateTime.MinValue;
|
||
VazaoMediaMLs = TempoAtuado > 0 ? (VolumeVazadoML / TempoAtuado) : 0;
|
||
|
||
// zera instantânea quando não tem bico ativo
|
||
foreach (var b in BicosPulverizadores)
|
||
b.VazaoInstantaneaMLs = 0;
|
||
}
|
||
|
||
// Integra vazão/volume enquanto tiver bico ativo
|
||
AtualizaVazaoEVolume(bicosAtivos, agora);
|
||
|
||
// Atualiza indicadores
|
||
AtualizaPercentualErvas();
|
||
|
||
bicosAtivosAnterior = new List<AtuadorBicoModel>(bicosAtivos);
|
||
}
|
||
private void AtualizaVazaoEVolume(List<AtuadorBicoModel> bicosAtivos, DateTime agora)
|
||
{
|
||
// Só integra se houver bicos ativos
|
||
if (bicosAtivos == null || bicosAtivos.Count == 0)
|
||
return;
|
||
|
||
// Captura vazão total instantânea (ml/s)
|
||
double vazaoTotalInst = VazaoFluxoMLpSInstantanea;
|
||
|
||
if (_ultimoRegistroVazao == default || _ultimoRegistroVazao == DateTime.MinValue)
|
||
return;
|
||
|
||
// dt em segundos
|
||
double dt = (agora - _ultimoRegistroVazao).TotalSeconds;
|
||
_ultimoRegistroVazao = agora;
|
||
|
||
if (dt <= 0) return;
|
||
|
||
// ======== GERAL ========
|
||
VolumeVazadoML += vazaoTotalInst * dt;
|
||
TempoAtuado += dt;
|
||
VazaoMediaMLs = TempoAtuado > 0 ? (VolumeVazadoML / TempoAtuado) : 0;
|
||
|
||
// ======== POR BICO (divide por ativos) ========
|
||
double vazaoPorBicoInst = vazaoTotalInst / bicosAtivos.Count;
|
||
|
||
foreach (var bico in bicosAtivos)
|
||
{
|
||
// Instantânea por bico
|
||
bico.VazaoInstantaneaMLs = vazaoPorBicoInst;
|
||
|
||
// Volume por bico (ml) = (ml/s) * s
|
||
bico.VolumeVazadoML += vazaoPorBicoInst * dt;
|
||
|
||
bico.TempoAtuado += dt;
|
||
|
||
bico.VazaoMediaMLs = bico.TempoAtuado > 0 ? (bico.VolumeVazadoML / bico.TempoAtuado) : 0;
|
||
}
|
||
}
|
||
private void AtualizaPercentualErvas()
|
||
{
|
||
//double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento.TempoDecorridoSeg * 1000.0;
|
||
double tempoTotalOperacao = (Variaveis.OperacaoEmAndamento.Sensoriamento?.Movimentacao?.TempoMovimentoSegs ?? 0) * 1000.0;
|
||
|
||
if (tempoTotalOperacao > 0)
|
||
{
|
||
var percentual = Math.Round((TempoAtuado / tempoTotalOperacao) * 100.0, 2);
|
||
PercentualErvasTerreno = percentual;
|
||
}
|
||
else
|
||
{
|
||
PercentualErvasTerreno = 0;
|
||
}
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region PRESSAO
|
||
private SensorModel SensorPressaoLinha
|
||
{
|
||
get
|
||
{
|
||
return Sensores.FirstOrDefault(x => x.Componente == S_Code.sPRS && x.ID == "PRSLN");
|
||
}
|
||
}
|
||
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;
|
||
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);
|
||
return pressao;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
public double PercentualErvasTerreno { get; set; } = 0;
|
||
|
||
public static AtuadorModel CarregarParametrosIniciais()
|
||
{
|
||
AtuadorModel Atuador = new AtuadorModel()
|
||
{
|
||
_EnderecoCAN_Tx = 0x12,
|
||
_EnderecoCAN_Rx = 0x12,
|
||
_TaxaAmostragem = 1000,
|
||
RequisitarDados = true,
|
||
// 11 ~ 50
|
||
Sensores = new List<SensorModel>()
|
||
{
|
||
// pressao 11 ~ 20
|
||
new SensorModel()
|
||
{
|
||
ID = "PRSLN",
|
||
ID_Num = 11,
|
||
Descricao = "Pressão na linha principal",
|
||
Componente = S_Code.sPRS,
|
||
Aferir = true,
|
||
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,
|
||
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 ~ 40
|
||
new SensorModel()
|
||
{
|
||
ID = "MASRS",
|
||
ID_Num = 31,
|
||
Descricao = "Massa do reservatório de herbicida",
|
||
Componente = S_Code.sMAS,
|
||
Aferir = true,
|
||
Mandatorio = true,
|
||
Funcoes = new List<FuncoesPinout>()
|
||
{
|
||
FuncoesPinout.DT,
|
||
FuncoesPinout.SCK,
|
||
},
|
||
Parametros = new List<SensorParametroModel>()
|
||
{
|
||
new SensorParametroModel()
|
||
{
|
||
Descricao = "Offset",
|
||
Enviar = true,
|
||
Escalar = true,
|
||
QtdBytes = 2,
|
||
Valor = "0.0"
|
||
}
|
||
},
|
||
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"
|
||
}
|
||
}
|
||
},
|
||
// magnetico 41 ~ 50
|
||
new SensorModel()
|
||
{
|
||
ID = "MAGESQ",
|
||
Descricao = "Angulo Barra Esquerda",
|
||
ID_Num = 41,
|
||
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,
|
||
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 = "°"
|
||
},
|
||
}
|
||
},
|
||
new SensorModel()
|
||
{
|
||
ID = "MAGALT",
|
||
Descricao = "Angulo Barra Altura",
|
||
ID_Num = 43,
|
||
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 = "2",
|
||
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 ~ 51
|
||
BombasPressurizadoras = new List<AtuadorBombaModel>()
|
||
{
|
||
new AtuadorBombaModel()
|
||
{
|
||
ID = "BMBLN",
|
||
ID_Num = 51,
|
||
Sensor_ID_Num = 11,
|
||
ComandoAtuar = false,
|
||
Componente = S_Code.sBMB,
|
||
Comandar = true,
|
||
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,
|
||
}
|
||
}
|
||
},
|
||
new AtuadorBombaModel()
|
||
{
|
||
ID = "BMBAGT",
|
||
ID_Num = 52,
|
||
Sensor_ID_Num = -1,
|
||
ComandoAtuar = false,
|
||
Componente = S_Code.sBMB,
|
||
Comandar = true,
|
||
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,
|
||
}
|
||
}
|
||
},
|
||
},
|
||
// 61 ~ 67
|
||
BicosPulverizadores = new List<AtuadorBicoModel>(),
|
||
};
|
||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++)
|
||
{
|
||
int posicao = (i + 1);
|
||
Atuador.BicosPulverizadores.Add(new AtuadorBicoModel()
|
||
{
|
||
ID = "B" + posicao.ToString("00"),
|
||
ID_Num = 60 + posicao,
|
||
Componente = S_Code.sBIC,
|
||
Posicao = posicao,
|
||
Inicializado = false,
|
||
AnguloControle = 0,
|
||
AnguloAbertura = 30,
|
||
Comandar = true,
|
||
Mandatorio = true,
|
||
ComandoAtuar = false,
|
||
AtuacaoNivelAlto = true,
|
||
Funcoes = new List<FuncoesPinout>()
|
||
{
|
||
FuncoesPinout.Solenoide,
|
||
FuncoesPinout.Servo,
|
||
},
|
||
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,
|
||
}
|
||
}
|
||
});
|
||
}
|
||
return Atuador;
|
||
}
|
||
|
||
public void LimparDados<T>(T _dados)
|
||
{
|
||
var Dados = _dados as AtuadorModel;
|
||
Dados.DadosLeitura = new AtuadorMensagemJsonModel();
|
||
Dados.DadosLeitura.Momento = DateTime.MinValue;
|
||
Dados.AtuPronto = false;
|
||
Dados.PercentualErvasTerreno = 0;
|
||
Dados.BombasPressurizadoras.ForEach(x => x.Funcoes = x.Funcoes.Distinct().ToList());
|
||
|
||
ReiniciarLeituras(Dados);
|
||
}
|
||
|
||
public void ReiniciarLeituras(AtuadorModel Dados)
|
||
{
|
||
Dados.Sensores.ForEach(x =>
|
||
{
|
||
x.ValoresLeituras.ForEach(l =>
|
||
{
|
||
l.atual = new CanCommandFreqModel<dynamic>();
|
||
});
|
||
});
|
||
|
||
Dados.BicosPulverizadores.ForEach(x =>
|
||
{
|
||
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>();
|
||
});
|
||
});
|
||
|
||
Dados.BombasPressurizadoras.ForEach(x =>
|
||
{
|
||
x.ComandoAtuar = false;
|
||
x.ValoresLeituras.ForEach(l =>
|
||
{
|
||
l.atual = new CanCommandFreqModel<dynamic>();
|
||
});
|
||
});
|
||
|
||
Dados.VolumeVazaoAferido = 0;
|
||
Dados._ultimoRegistroVazao = DateTime.MinValue;
|
||
Dados.VolumeVazadoML = 0;
|
||
Dados.VazaoMediaMLs = 0;
|
||
Dados.TempoAtuado = 0;
|
||
Dados.AnguloBarraAltura = 0;
|
||
Dados.AnguloBarraDireita = 0;
|
||
Dados.AnguloBarraEsquerda = 0;
|
||
Dados.PercentualErvasTerreno = 0;
|
||
}
|
||
|
||
public async Task<bool> VerificaDispositivoConectado()
|
||
{
|
||
if (!CanManager.CanService.IsConnected) return false;
|
||
|
||
if (Variaveis.OperacaoEmAndamento.DispAtu == null) return false;
|
||
|
||
CanManager.CanService.RegistrarHandler(_EnderecoCAN_Rx, _AtuHandler);
|
||
|
||
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 (Conectado)
|
||
{
|
||
DefinirDispositivo();
|
||
Variaveis.OperacaoEmAndamento.DispAtu?.EnviarProtocolosConfiguracao();
|
||
}
|
||
|
||
return Conectado;
|
||
}
|
||
|
||
private void DefinirDispositivo()
|
||
{
|
||
if (!SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Dispositivo && x.Mod_ID == Modulo_ID))
|
||
{
|
||
SerialService.DispositivosMapeados.Add(new DispositivoDetalhesModel()
|
||
{
|
||
Dispositivo = DadosLeitura.Dispositivo,
|
||
Endereco = CanManager.CanService._portName,
|
||
Versao = DadosLeitura.Versao.ToString(),
|
||
Mod_ID = Modulo_ID
|
||
});
|
||
|
||
Variaveis.OperacaoEmAndamento.ModsCalibragem[Dispositivo] = new Dictionary<string, bool>();
|
||
Variaveis.OperacaoEmAndamento.Sensoriamento.InserirLog(Dispositivo, StatusModulo.Conectado, 0, "Dispositivo conectado");
|
||
}
|
||
}
|
||
|
||
public void RequisitarDadosModulo(int ID_Num, CanMessagePosicaoDados posicaoTx, CanMessagePosicaoDados posicaoRx, bool aguardaResposta)
|
||
{
|
||
Variaveis.OperacaoEmAndamento.DispAtu?.AdicionarMensagemFila(ID_Num, posicaoTx, posicaoRx, null, aguardaResposta);
|
||
}
|
||
|
||
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComandoReset()
|
||
{
|
||
return (
|
||
Variaveis.ID_Num_sMOD,
|
||
CanMessagePosicaoDados.Command1,
|
||
new byte[]
|
||
{
|
||
(byte)Estado.Reset
|
||
}
|
||
);
|
||
}
|
||
|
||
public List<(int, CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(bool Conectar)
|
||
{
|
||
// Inicializar o dicionário
|
||
List<(int, CanMessagePosicaoDados, byte[])> config = new List<(int, CanMessagePosicaoDados, byte[])>();
|
||
|
||
if (!DadosLeitura.Conectado)
|
||
{
|
||
// Adicionar configuração do ProtocoloMOD
|
||
var protocoloMOD = ModConfig(Conectar);
|
||
config.AddRange(protocoloMOD);
|
||
}
|
||
|
||
bool configurarTodos = !DadosLeitura.Conectado && Conectar;
|
||
|
||
// Adicionar configurações dos Sensores que devem ser aferidos
|
||
var sensoresConfig = SensoresConfig(Conectar, configurarTodos);
|
||
config.AddRange(sensoresConfig);
|
||
|
||
// Adicionar configurações dos Bicos
|
||
var bicosConfig = BicosConfig(Conectar, configurarTodos);
|
||
config.AddRange(bicosConfig);
|
||
|
||
// Adicionar configurações das Bombas
|
||
var bombasConfig = BombasConfig(Conectar, configurarTodos);
|
||
config.AddRange(bombasConfig);
|
||
|
||
return config;
|
||
}
|
||
|
||
private List<(int, CanMessagePosicaoDados, byte[])> ModConfig(bool Conectar)
|
||
{
|
||
var config = new List<byte>
|
||
{
|
||
(byte)(Conectar ? 1 : 0),
|
||
(byte)(_TaxaAmostragem / 10),
|
||
(byte)(RequisitarDados ? 1 : 0),
|
||
};
|
||
|
||
config.AddRange(PinoutModel.PinoProtocolo(Pinout, Funcoes, false));
|
||
|
||
return new List<(int, CanMessagePosicaoDados, byte[])>
|
||
{
|
||
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config1, config.ToArray()),
|
||
};
|
||
}
|
||
|
||
private List<(int, CanMessagePosicaoDados, byte[])> SensoresConfig(bool Conectar, bool ConfigurarTodos)
|
||
{
|
||
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;
|
||
}
|
||
(CanMessagePosicaoDados posicao, byte[] payload) = sensor.ProtocoloConfiguracao(Pinout, Conectar, Dispositivo);
|
||
if (payload != null)
|
||
{
|
||
config.Add((sensor.ID_Num, posicao, payload));
|
||
}
|
||
}
|
||
|
||
return config;
|
||
}
|
||
|
||
private List<(int, CanMessagePosicaoDados, byte[])> BicosConfig(bool Conectar, bool ConfigurarTodos)
|
||
{
|
||
var config = new List<(int, CanMessagePosicaoDados, byte[])>();
|
||
|
||
foreach (var bico in BicosPulverizadores.Where(x => (x.Comandar && (ConfigurarTodos ? true : x.Inicializado != Conectar)) || (!x.Comandar && x.Inicializado)))
|
||
{
|
||
if (!bico.Comandar && bico.Inicializado)
|
||
{
|
||
Conectar = false;
|
||
}
|
||
(CanMessagePosicaoDados posicao, var payload) = bico.ProtocoloConfiguracao(Pinout, Conectar);
|
||
if (payload != null)
|
||
{
|
||
config.Add((bico.ID_Num, posicao, payload));
|
||
}
|
||
}
|
||
|
||
return config;
|
||
}
|
||
|
||
private List<(int, CanMessagePosicaoDados, byte[])> BombasConfig(bool Conectar, bool ConfigurarTodos)
|
||
{
|
||
var config = new List<(int, CanMessagePosicaoDados, byte[])>();
|
||
|
||
foreach (var bomba in BombasPressurizadoras.Where(x => (x.Comandar && (ConfigurarTodos ? true : x.Inicializado != Conectar)) || (!x.Comandar && x.Inicializado)))
|
||
{
|
||
if (!bomba.Comandar && bomba.Inicializado)
|
||
{
|
||
Conectar = false;
|
||
}
|
||
List<(CanMessagePosicaoDados, byte[])> dados = bomba.ProtocoloConfiguracao(Pinout, Conectar);
|
||
foreach (var dado in dados)
|
||
{
|
||
config.Add((bomba.ID_Num, dado.Item1, dado.Item2));
|
||
}
|
||
}
|
||
|
||
return config;
|
||
}
|
||
|
||
|
||
public void IniciarRegistrador()
|
||
{
|
||
if (!(tmrRegistrador?.IsRunning ?? false))
|
||
{
|
||
LimparDados(this);
|
||
|
||
PararRegistrador();
|
||
|
||
tmrRegistrador = new AsyncTaskTimerModel("tmrRegistrador_" + T_Code.Atu.ToString(), tmrRegistrador_Tick, _TaxaAmostragem);
|
||
tmrRegistrador.Start();
|
||
}
|
||
}
|
||
|
||
public void PararRegistrador()
|
||
{
|
||
tmrRegistrador?.Dispose();
|
||
}
|
||
|
||
public async Task tmrRegistrador_Tick()
|
||
{
|
||
if (Variaveis.Fechando) return;
|
||
|
||
tmrRegistrador.SetInterval(_TaxaAmostragem);
|
||
|
||
if (SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Atu) && (_VezesLeituraReconexao >= _TempoReconexaoComponentes))
|
||
{
|
||
Variaveis.OperacaoEmAndamento.DispAtu?.EnviarProtocolosConfiguracao();
|
||
|
||
_VezesLeituraReconexao = 0;
|
||
}
|
||
else
|
||
{
|
||
_VezesLeituraReconexao++;
|
||
}
|
||
|
||
|
||
if (DadosLeitura.Conectado)
|
||
{
|
||
if (RequisitarDados)
|
||
{
|
||
RequisitarDadosModulo(Variaveis.ID_Num_sTOD, CanMessagePosicaoDados.DadosAll, CanMessagePosicaoDados.DadosAll, true);
|
||
}
|
||
VerificaControleLeitura();
|
||
}
|
||
|
||
AtualizaComponentesIniciados();
|
||
}
|
||
|
||
private void VerificaControleLeitura()
|
||
{
|
||
if (Variaveis.Fechando) return;
|
||
|
||
foreach (var bico in BicosPulverizadores.Where(x => x.Comandar && x.Inicializado))
|
||
{
|
||
Estado comandoEstado = bico.ComandoAtuar ? Estado.Ligado : Estado.Desligado;
|
||
if (comandoEstado != bico._EstadoLeitura || bico.AnguloControle != bico._AnguloBicoLeitura)
|
||
{
|
||
GeneralJoystick.EnviarComandoAtuador(bico.Componente, bico.ID, Status: bico.ComandoAtuar, Valor: bico.AnguloControle);
|
||
}
|
||
}
|
||
|
||
foreach (var bomba in BombasPressurizadoras.Where(x => x.Comandar && x.Inicializado))
|
||
{
|
||
// Desligar a bomba caso nao tenha herbicida suficiente no recipiente
|
||
if (!ContadorCarga.PulverizadorLiberado)
|
||
{
|
||
if (bomba._EstadoLeitura == Estado.Ligado)
|
||
{
|
||
GeneralJoystick.EnviarComandoAtuador(bomba.Componente, bomba.ID, Status: false);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (Variaveis.OperacaoEmAndamento.Iniciado && Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico)
|
||
{
|
||
if (bomba._EstadoLeitura == Estado.Desligado)
|
||
{
|
||
GeneralJoystick.EnviarComandoAtuador(bomba.Componente, bomba.ID, Status: true);
|
||
}
|
||
}
|
||
|
||
Estado comandoEstado = bomba.ComandoAtuar ? Estado.Ligado : Estado.Desligado;
|
||
double pressaoSp = Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
|
||
if (comandoEstado != bomba._EstadoLeitura || pressaoSp != bomba._PressaoSP)
|
||
{
|
||
GeneralJoystick.EnviarComandoAtuador(bomba.Componente, bomba.ID, Status: bomba.ComandoAtuar, Valor: pressaoSp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
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))
|
||
{
|
||
bomba.Inicializado = false;
|
||
}
|
||
foreach (var bico in BicosPulverizadores.Where(x => x.Inicializado && x.UltimaLeitura.AddMilliseconds(TempoLimiteConexao) < Agora))
|
||
{
|
||
bico.Inicializado = false;
|
||
}
|
||
foreach (var sensor in Sensores.Where(x => x.Inicializado && x.UltimaLeitura.AddMilliseconds(TempoLimiteConexao) < Agora))
|
||
{
|
||
sensor.Inicializado = false;
|
||
}
|
||
}
|
||
|
||
|
||
public async Task<bool> RealizarTestesIniciais(bool forcar)
|
||
{
|
||
var calAtu = Variaveis.OperacaoEmAndamento.ModsCalibragem[T_Code.Atu];
|
||
|
||
// Ligar bomba
|
||
foreach (var Bomba in BombasPressurizadoras.Where(x => x.Comandar))
|
||
{
|
||
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)
|
||
{
|
||
break;
|
||
}
|
||
|
||
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true);
|
||
|
||
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);
|
||
}
|
||
|
||
await Task.Delay(3000);
|
||
|
||
foreach (var Bico in BicosPulverizadores.Where(x => x.Comandar && x.Inicializado))
|
||
{
|
||
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: false);
|
||
}
|
||
|
||
await FuncoesGlobais.AguardarCondicaoAsync(Bomba.AtingiuPressao, 4000, 200);
|
||
|
||
BombaOk = Bomba.AtingiuPressao();
|
||
if (BombaOk)
|
||
{
|
||
calAtu[Bomba.ID] = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Testar os bicos
|
||
foreach (var Bico in BicosPulverizadores.Where(x => x.Comandar))
|
||
{
|
||
calAtu.TryGetValue(Bico.ID, out var cal);
|
||
if (!forcar && cal && calAtu[Bico.ID]) continue;
|
||
|
||
calAtu[Bico.ID] = false;
|
||
|
||
if (Bico.Inicializado)
|
||
{
|
||
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: true);
|
||
|
||
await Task.Delay(200);
|
||
|
||
GeneralJoystick.EnviarComandoAtuador(Bico.Componente, Bico.ID, Status: false);
|
||
|
||
calAtu[Bico.ID] = true;
|
||
}
|
||
}
|
||
|
||
await Task.Delay(1000);
|
||
|
||
bool sucesso = calAtu.All(x => x.Value);
|
||
|
||
return sucesso;
|
||
}
|
||
|
||
public List<Task> RealizarCalibragemAsync(bool forcar)
|
||
{
|
||
List<Task> tasks = new List<Task>();
|
||
var DispAtu = Variaveis.OperacaoEmAndamento.DispAtu;
|
||
if (DispAtu != null)
|
||
{
|
||
tasks.Add(DispAtu.Dados.RealizarTestesIniciais(forcar).ContinueWith(t => {
|
||
if (t.IsFaulted)
|
||
Console.WriteLine($"Erro no referenciamento do módulo {Modulo_ID}: {t.Exception?.InnerException?.Message}");
|
||
if (t.IsCompleted)
|
||
{
|
||
var calAtu = Variaveis.OperacaoEmAndamento.ModsCalibragem[T_Code.Atu];
|
||
var v = calAtu.Select(x => $"{x.Key} " + (x.Value ? "Sim" : "Não"));
|
||
Console.WriteLine($"Task de referenciamento do módulo {Modulo_ID} finalizada: " + string.Join(", ", v));
|
||
}
|
||
|
||
}));
|
||
}
|
||
return tasks;
|
||
}
|
||
|
||
|
||
|
||
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);
|
||
if (SensorAnguloBarraAltura != null)
|
||
RequisitarDadosModulo(SensorAnguloBarraAltura.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;
|
||
else if (sensor.ID_Num == SensorAnguloBarraAltura.ID_Num)
|
||
AnguloBarraAltura = 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;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
public class AtuadorBicoModel
|
||
{
|
||
public string ID { get; set; }
|
||
public int ID_Num { get; set; }
|
||
public int Posicao { get; set; }
|
||
public S_Code Componente { get; set; } = S_Code.sBIC;
|
||
public bool AtuacaoNivelAlto { get; set; }
|
||
public double AnguloControle { get; set; }
|
||
public double AnguloAbertura { get; set; }
|
||
public bool ComandoAtuar { get; set; }
|
||
public bool Comandar { get; set; }
|
||
public bool Mandatorio { get; set; }
|
||
public bool Liberado
|
||
{
|
||
get
|
||
{
|
||
return !Mandatorio || (Comandar && Inicializado);
|
||
}
|
||
}
|
||
public List<FuncoesPinout> Funcoes { get; set; }
|
||
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);
|
||
public int _AnguloBicoLeitura => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.LeituraAngulo)?.atual?.valor ?? 0;
|
||
|
||
|
||
public (CanMessagePosicaoDados, byte[]) ProtocoloConfiguracao(PinoutDataModel pinout, bool conectar)
|
||
{
|
||
var pino = pinout.Pinos.FirstOrDefault(p => p.ComponenteID == ID);
|
||
|
||
var data = new byte[]
|
||
{
|
||
(byte)Componente,
|
||
(byte)(conectar ? 1 : 0),
|
||
(byte)(AtuacaoNivelAlto ? 1 : 0),
|
||
0x00, //(byte)Servo_ID_Num,
|
||
(byte)(pino?.Barramento ?? TiposBarramentos.CONTROLADOR),
|
||
(byte)(pino?.Pino ?? PinoutUtils.PINO_INVALIDO)
|
||
};
|
||
|
||
return (CanMessagePosicaoDados.Config1, data);
|
||
}
|
||
|
||
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando()
|
||
{
|
||
return (
|
||
ID_Num,
|
||
CanMessagePosicaoDados.Command1,
|
||
new byte[]
|
||
{
|
||
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
|
||
(byte)AnguloControle
|
||
}
|
||
);
|
||
}
|
||
|
||
|
||
public List<List<double[]>> TrechosAtuado { get; set; } = new List<List<double[]>>();
|
||
public int Atuacoes { get; set; } = 0;
|
||
public double TempoAtuado { get; set; } = 0;
|
||
|
||
|
||
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,
|
||
ID_Num = ID_Num,
|
||
VolumeVazadoML = VolumeVazadoML,
|
||
TrechosAtuado = TrechosAtuado,
|
||
VazaoInstantaneaMLs = VazaoInstantaneaMLs,
|
||
_estadoLeituraAnterior = _estadoLeituraAnterior,
|
||
ValoresLeituras = new List<SensorValoresLeituraModel>(ValoresLeituras),
|
||
VazaoMediaMLs = VazaoMediaMLs,
|
||
Posicao = Posicao,
|
||
TempoAtuado = TempoAtuado,
|
||
};
|
||
|
||
return clone;
|
||
}
|
||
}
|
||
|
||
public class AtuadorBombaModel
|
||
{
|
||
public string ID { get; set; }
|
||
public int ID_Num { get; set; }
|
||
public bool ComandoAtuar { get; set; }
|
||
public S_Code Componente { get; set; } = S_Code.sBMB;
|
||
public int Sensor_ID_Num { get; set; }
|
||
public bool Comandar { get; set; }
|
||
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
|
||
{
|
||
get
|
||
{
|
||
return ValoresLeituras.OrderByDescending(x => x.atual.lidoEm).FirstOrDefault()?.atual?.lidoEm ?? DateTime.MinValue;
|
||
}
|
||
}
|
||
public List<SensorValoresLeituraModel> ValoresLeituras { 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 List<(CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(PinoutDataModel pinout, bool conectar)
|
||
{
|
||
List<byte> config1 = new List<byte>()
|
||
{
|
||
(byte)Componente,
|
||
(byte)(conectar ? 1 : 0),
|
||
(byte)Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha,
|
||
(byte)Sensor_ID_Num,
|
||
(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),
|
||
};
|
||
|
||
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),
|
||
};
|
||
|
||
return new List<(CanMessagePosicaoDados, byte[])>()
|
||
{
|
||
(CanMessagePosicaoDados.Config1, config1.ToArray()),
|
||
(CanMessagePosicaoDados.Config2, config2.ToArray()),
|
||
};
|
||
}
|
||
|
||
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando()
|
||
{
|
||
return (
|
||
ID_Num,
|
||
CanMessagePosicaoDados.Command1,
|
||
new byte[]
|
||
{
|
||
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
|
||
(byte)(Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha)
|
||
}
|
||
);
|
||
}
|
||
|
||
public bool AtingiuPressao() => Variaveis.OperacaoEmAndamento.DispAtu.Dados.PressaoLinha >= Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
|
||
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
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);
|
||
|
||
// 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);
|
||
|
||
// 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
|
||
{
|
||
public DateTime Momento { get; set; }
|
||
public bool Conectado { get; set; }
|
||
public T_Code Dispositivo { get; set; }
|
||
public int Versao { get; set; }
|
||
public string Mod_ID { get; set; }
|
||
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; }
|
||
public DateTime UltimoComandoRespondido { get; set; }
|
||
}
|
||
|
||
public class AtuHandler : ICanMessageHandler
|
||
{
|
||
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 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;
|
||
}
|
||
|
||
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++)
|
||
{
|
||
try
|
||
{
|
||
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)
|
||
{
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
public void ProcessarMensagem(CanMessage mensagem)
|
||
{
|
||
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)mensagem.DataRx[0];
|
||
byte ID_Num = mensagem.DataRx[1];
|
||
var data = mensagem.DataRx;
|
||
|
||
S_Code componente = DetectarComponenteDoID_Num(ID_Num);
|
||
|
||
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
|
||
|
||
//Console.WriteLine($"[ATU] Componente={componente.ToString()}, ID_Num={ID_Num}, Data={FuncoesGlobais.ConverterComandoBytesParaTexto(data)}");
|
||
|
||
switch (componente)
|
||
{
|
||
case S_Code.sMOD:
|
||
{
|
||
switch (posicao)
|
||
{
|
||
case CanMessagePosicaoDados.Status:
|
||
{
|
||
T_Code tipoModulo = (T_Code)data[2];
|
||
bool conectado = data[3] == 1;
|
||
int versao = data[4];
|
||
|
||
//Console.WriteLine($"[ATU] Resposta {ID_Num} recebida. Tipo={tipoModulo}, Conectado={conectado}, Versão={versao}");
|
||
|
||
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;
|
||
}
|
||
case S_Code.sBIC:
|
||
{
|
||
switch (posicao)
|
||
{
|
||
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)
|
||
{
|
||
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);
|
||
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { qtdPulsos, periodo, vazao });
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case S_Code.sMAS:
|
||
{
|
||
switch (posicao)
|
||
{
|
||
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);
|
||
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { raw, massa });
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case S_Code.sPRS:
|
||
{
|
||
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 pressao = ConverterByteParaDouble(data, 4);
|
||
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { raw, pressao });
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case S_Code.sBMB:
|
||
{
|
||
switch (posicao)
|
||
{
|
||
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 percentualPotencia = data[3];
|
||
int pressaoSp = data[4];
|
||
int pressaoAtual = data[5];
|
||
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado, percentualPotencia, pressaoSp, pressaoAtual });
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
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;
|
||
}
|
||
|
||
}
|
||
|
||
Dados.DadosLeitura.UltimoComandoRespondido = DateTime.Now;
|
||
|
||
Variaveis.OperacaoEmAndamento.DispAtu.Dados.AtualizarDadosSensoresExternos(componente, ID_Num);
|
||
}
|
||
}
|
||
|
||
|
||
}
|