Merge branch 'op_control' of http://zendioninc.com.br:3000/Zendion/agrobot_base into op_control

This commit is contained in:
Diego Freitas 2026-03-26 17:10:21 -03:00
commit eee7bacc54
24 changed files with 354 additions and 73 deletions

View File

@ -76,7 +76,7 @@ namespace AgroBase.Forms.IHM
if (res == DialogResult.Yes)
{
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
if (Variaveis.OperacaoEmAndamento.Modo == Enums.ModoOperacao.Manual)
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo == Enums.ModoOperacao.Manual)
{
this.Close();
}
@ -168,7 +168,7 @@ namespace AgroBase.Forms.IHM
lblMapaCarregado.Text = "Operação: " + Variaveis.OperacaoEmAndamento.Descricao;
txtModoOperacao.Text = Variaveis.OperacaoEmAndamento.Modo.ToString();
txtModoOperacao.Text = (Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido).ToString();
bool opLiberada = _Sensoriamento.OperacaoLiberada;
txtOperacaoLiberada.Text = opLiberada ? "Sim" : "Não";
txtOperacaoLiberada.ForeColor = opLiberada ? Color.Black : Color.Red;
@ -197,7 +197,7 @@ namespace AgroBase.Forms.IHM
lblCorrecaoGPS.Text = (_Sensoriamento.Gps.Ntrip_ativado ? "N " : "B ") + _Sensoriamento.Gps.IdadeCorrecao + ": " + _Sensoriamento.Gps.QualidadeFix.ToString();
lblPrecisaoGPS.Text = $"Precisão: {_Sensoriamento.Gps.PrecisaoCm.ToString("0.00")} cm";
bool automatico = Variaveis.OperacaoEmAndamento.Modo != ModoOperacao.Manual;
bool automatico = Variaveis.OperacaoEmAndamento.Parametros?.ControleAutomatico ?? false;
cmbModoControle.Enabled = !automatico;
tkbVelocidade.Enabled = !automatico;
tkbAnguloDirecional.Enabled = !automatico;
@ -527,7 +527,7 @@ namespace AgroBase.Forms.IHM
// Iniciar o arraste
private void BrakePanel_MouseDown(object sender, MouseEventArgs e)
{
if (Variaveis.OperacaoEmAndamento.Modo != Enums.ModoOperacao.Manual)
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo != Enums.ModoOperacao.Manual)
{
return;
}
@ -541,7 +541,7 @@ namespace AgroBase.Forms.IHM
// Movimentar o botão de freio
private void BrakePanel_MouseMove(object sender, MouseEventArgs e)
{
if (Variaveis.OperacaoEmAndamento.Modo != Enums.ModoOperacao.Manual)
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo != Enums.ModoOperacao.Manual)
{
return;
}
@ -583,7 +583,7 @@ namespace AgroBase.Forms.IHM
// Soltar o botão de freio
private void BrakePanel_MouseUp(object sender, MouseEventArgs e)
{
if (Variaveis.OperacaoEmAndamento.Modo != Enums.ModoOperacao.Manual)
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo != Enums.ModoOperacao.Manual)
{
return;
}

View File

@ -230,7 +230,7 @@ namespace AgroBase.Forms.Operacoes
chb.Checked = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == Dispositivo && x.Mandatorio);
}
txtModoOperacao.Text = Variaveis.OperacaoEmAndamento.Modo.ToString();
txtModoOperacao.Text = (Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido).ToString();
txtDescricao.Text = Variaveis.OperacaoEmAndamento.Descricao;
txtCriadoEm.Text = new FileInfo(path).CreationTime.ToString("dd/MM/yyyy HH:mm");
txtRuasPercorrer.Text = (Variaveis.OperacaoEmAndamento.Trajetoria?.Corredores?.Count() ?? 0).ToString();

View File

@ -29,7 +29,7 @@ namespace AgroBase.Forms.Operacoes
cmbOperacao.Items.Clear();
cmbOperacao.Items.AddRange(Enum.GetNames(typeof(ModoOperacao)));
cmbOperacao.SelectedIndex = (int)Variaveis.OperacaoEmAndamento.Modo;
cmbOperacao.SelectedIndex = (int)Variaveis.OperacaoEmAndamento.Parametros?.Modo;
var chbModulos = gpbModulos.Controls.OfType<CheckBox>().Where(x => x.Name.Contains("chbD_")).ToList();
chbModulos.ForEach(chb =>
@ -151,7 +151,7 @@ namespace AgroBase.Forms.Operacoes
if (chbSalvar.Checked)
{
//OperacaoModel.SalvarOperacaoPersonalizada(Variaveis.OperacaoEmAndamento);
MessageBox.Show("Operação " + Enum.GetName(typeof(ModoOperacao), Variaveis.OperacaoEmAndamento.Modo) + " salva com sucesso!", "Sucesso");
MessageBox.Show($"Operação {Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido} salva com sucesso!", "Sucesso");
}
}
@ -164,7 +164,7 @@ namespace AgroBase.Forms.Operacoes
{
string operacaoPath = ofd.FileName;
//Variaveis.OperacaoEmAndamento = OperacaoModel.CarregarOperacaoPersonalizada(operacaoPath);
MessageBox.Show("Operação " + Enum.GetName(typeof(ModoOperacao), Variaveis.OperacaoEmAndamento.Modo) + " carregada com sucesso!", "Sucesso");
MessageBox.Show($"Operação {Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido} carregada com sucesso!", "Sucesso");
CarregarParametros();
}

View File

@ -30,7 +30,7 @@ namespace AgroBase.Forms.Operacoes
List<PictureBox> picsCamSoloSeg = new List<PictureBox>();
List<PictureBox> picsCamSoloOverlay = new List<PictureBox>();
List<CameraWorkerItemModel> LogsCam_Caminho = new List<CameraWorkerItemModel>();
OperacaoModel operacaoSelecionada = new OperacaoModel(Enums.ModoOperacao.NaoDefinido);
OperacaoModel operacaoSelecionada = new OperacaoModel();
private readonly TopDownBboxView view_top_down = new TopDownBboxView();
private readonly FrontalBboxView view_frontal = new FrontalBboxView();
private readonly Bbox3DViewer view_3d = new Bbox3DViewer();
@ -1168,8 +1168,9 @@ namespace AgroBase.Forms.Operacoes
lblPercentualOperacao.Text = $"Operação {Log.Trajetoria.ProgressoTrajeto.ToString("0.00")}%";
FuncoesGlobais.PreencheValorProgressBar(pgbPercentualOperacao, Log.Trajetoria.ProgressoTrajeto);
double distanciaAtual = Log.Modo == Enums.ModoOperacao.MapaGPS ? Log.Trajetoria.DistanciaPercorrida : Log.Movimentacao.DistanciaPercorridaTotal;
double distanciaTotal = Log.Modo == Enums.ModoOperacao.MapaGPS ? LogsOperacao[LogsOperacao.Count - 1].Trajetoria.DistanciaTotal : LogsOperacao[LogsOperacao.Count - 1].Movimentacao.DistanciaPercorridaTotal;
bool comTrajetoria = new List<Enums.ModoOperacao>() { Enums.ModoOperacao.MapaGPS, Enums.ModoOperacao.RetornoBase }.Contains(Log.Modo);
double distanciaAtual = comTrajetoria ? Log.Trajetoria.DistanciaPercorrida : Log.Movimentacao.DistanciaPercorridaTotal;
double distanciaTotal = comTrajetoria ? LogsOperacao[LogsOperacao.Count - 1].Trajetoria.DistanciaTotal : LogsOperacao[LogsOperacao.Count - 1].Movimentacao.DistanciaPercorridaTotal;
txtDistanciaPercorrida.Text = distanciaAtual.ToString("0.00") + " m / " + distanciaTotal.ToString("0.00") + " m";
double percentualRua = Log.Trajetoria.CorredorAtual.Progresso;

View File

@ -1,6 +1,5 @@
using AgroBase.Models;
using AgroBase.Services;
using AgroBase.Services.Operadores;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
@ -551,6 +550,7 @@ namespace AgroBase.Forms
private void btnRetornarBase_Click(object sender, EventArgs e)
{
//OperacaoModel.CarregarParametrosOperacaoPadrao(ModoOperacao.RetornoBase, true);
Variaveis.OperacaoEmAndamento.Trajetoria.IniciarRetornoBase(VariaveisOperacao.PosicaoBase);
Variaveis.OperacaoEmAndamento.Simulando = true;
}

View File

@ -66,6 +66,7 @@ namespace AgroBase
this.gpbControleDirecional = new System.Windows.Forms.GroupBox();
this.gpbAtalhos = new System.Windows.Forms.GroupBox();
this.pnlAtalhos = new System.Windows.Forms.Panel();
this.btnSimuladorMapeamentoVisual = new System.Windows.Forms.Button();
this.btnVisualWorker = new System.Windows.Forms.Button();
this.btnTreinamentoIA = new System.Windows.Forms.Button();
this.btnOID = new System.Windows.Forms.Button();
@ -93,7 +94,6 @@ namespace AgroBase
this.btnForcarAtualizacao = new System.Windows.Forms.Button();
this.clbRotinas = new System.Windows.Forms.CheckedListBox();
this.btnAtualizarRotinas = new System.Windows.Forms.Button();
this.btnSimuladorMapeamentoVisual = new System.Windows.Forms.Button();
this.gpbAcoes.SuspendLayout();
this.erroStrip.SuspendLayout();
this.pnlLateral.SuspendLayout();
@ -517,6 +517,17 @@ namespace AgroBase
this.pnlAtalhos.Size = new System.Drawing.Size(112, 286);
this.pnlAtalhos.TabIndex = 0;
//
// btnSimuladorMapeamentoVisual
//
this.btnSimuladorMapeamentoVisual.Location = new System.Drawing.Point(5, 487);
this.btnSimuladorMapeamentoVisual.Margin = new System.Windows.Forms.Padding(2);
this.btnSimuladorMapeamentoVisual.Name = "btnSimuladorMapeamentoVisual";
this.btnSimuladorMapeamentoVisual.Size = new System.Drawing.Size(84, 20);
this.btnSimuladorMapeamentoVisual.TabIndex = 34;
this.btnSimuladorMapeamentoVisual.Text = "Mapeamento";
this.btnSimuladorMapeamentoVisual.UseVisualStyleBackColor = true;
this.btnSimuladorMapeamentoVisual.Click += new System.EventHandler(this.btnSimuladorMapeamentoVisual_Click);
//
// btnVisualWorker
//
this.btnVisualWorker.Location = new System.Drawing.Point(5, 463);
@ -818,17 +829,6 @@ namespace AgroBase
this.btnAtualizarRotinas.UseVisualStyleBackColor = true;
this.btnAtualizarRotinas.Click += new System.EventHandler(this.btnAtualizarRotinas_Click);
//
// btnSimuladorMapeamentoVisual
//
this.btnSimuladorMapeamentoVisual.Location = new System.Drawing.Point(5, 487);
this.btnSimuladorMapeamentoVisual.Margin = new System.Windows.Forms.Padding(2);
this.btnSimuladorMapeamentoVisual.Name = "btnSimuladorMapeamentoVisual";
this.btnSimuladorMapeamentoVisual.Size = new System.Drawing.Size(84, 20);
this.btnSimuladorMapeamentoVisual.TabIndex = 34;
this.btnSimuladorMapeamentoVisual.Text = "Mapeamento";
this.btnSimuladorMapeamentoVisual.UseVisualStyleBackColor = true;
this.btnSimuladorMapeamentoVisual.Click += new System.EventHandler(this.btnSimuladorMapeamentoVisual_Click);
//
// frmPrincipal
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -910,7 +910,6 @@ namespace AgroBase
private System.Windows.Forms.GroupBox gpbAtalhos;
private System.Windows.Forms.GroupBox gpbOperacao;
private System.Windows.Forms.Label lblModoOperacao;
private System.Windows.Forms.ComboBox cmbModoOperacao;
private System.Windows.Forms.Button btnIniciarOperacao;
private System.Windows.Forms.Label lblKmh;
public System.Windows.Forms.TrackBar trkKmh;
@ -945,6 +944,7 @@ namespace AgroBase
private System.Windows.Forms.Button btnTreinamentoIA;
private System.Windows.Forms.Button btnVisualWorker;
private System.Windows.Forms.Button btnSimuladorMapeamentoVisual;
public System.Windows.Forms.ComboBox cmbModoOperacao;
}
}

View File

@ -34,7 +34,7 @@ namespace AgroBase
cmbModoOperacao.Items.Clear();
cmbModoOperacao.Items.AddRange(Enum.GetNames(typeof(ModoOperacao)));
cmbModoOperacao.SelectedIndex = (int)Variaveis.OperacaoEmAndamento.Modo;
cmbModoOperacao.SelectedIndex = (int)(Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido);
}
private async void frmPrincipal_FormClosing(object sender, FormClosingEventArgs e)

View File

@ -176,7 +176,8 @@
Manual = 1,
MapaGPS = 2,
TreinamentoIA = 3,
MapeamentoVisual = 4
MapeamentoVisual = 4,
RetornoBase = 5
}
public enum StatusOperacao

View File

@ -595,7 +595,7 @@ namespace AgroBase
bool deveInterromper =
!Forms.IHM.frmDiagnosticos.Diagnosticando && !ForcarComando &&
(
Variaveis.OperacaoEmAndamento.Modo == ModoOperacao.Manual && (
Variaveis.OperacaoEmAndamento.Parametros?.Modo == ModoOperacao.Manual && (
Variaveis.OperacaoEmAndamento.Calibrando ||
!Variaveis.OperacaoEmAndamento.OperacaoLiberada ||
!Variaveis.OperacaoEmAndamento.Iniciado ||
@ -949,6 +949,8 @@ namespace AgroBase
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
var controle = Variaveis.OperacaoEmAndamento.Controle;
if (pControle == null || controle == null) return;
double velMin = pControle.MovVelocidadeCErvasPercent;
double velMax = pControle.MovVelocidadeSErvasPercent;

View File

@ -18,16 +18,15 @@ using AgroBase.Models.Operadores;
using AgroBase.Services.Operadores;
using AgroMonitor;
using Newtonsoft.Json.Linq;
using System.Globalization;
namespace AgroBase.Models
{
public class OperacaoModel
{
public OperacaoModel(ModoOperacao Modo)
public OperacaoModel()
{
this.Modo = Modo;
if (Variaveis.OperacaoEmAndamento != null)
{
tmrLogs?.Dispose();
@ -45,7 +44,6 @@ namespace AgroBase.Models
public ModoOperacao Modo { get; set; }
public StatusModulo Status { get; set; }
public string Descricao { get; set; }
public string OprPath { get; set; }
@ -222,7 +220,6 @@ namespace AgroBase.Models
OperacaoParametrosModel Parametros = new OperacaoParametrosModel()
{
Modo = Variaveis.OperacaoEmAndamento.Modo,
Descricao = descricao,
CapacidadeReservatorio = capacidadeReservatorio,
Controle = new OperacaoParametrosControleModel()
@ -356,7 +353,7 @@ namespace AgroBase.Models
var AtuConectado = (DispositivosService<AtuadorModel>)Variaveis.DispositivosConectados.FirstOrDefault(x => x.Dispositivo == T_Code.Atu);
var MvdConectado = (DispositivosService<MovimentacaoUnificadaModel>)Variaveis.DispositivosConectados.FirstOrDefault(x => x.Dispositivo == T_Code.Mvd);
tmrLogs?.Stop();
Variaveis.OperacaoEmAndamento = new OperacaoModel(Modo)
Variaveis.OperacaoEmAndamento = new OperacaoModel()
{
Iniciado = false,
DataInicio = DateTime.MinValue,
@ -374,6 +371,9 @@ namespace AgroBase.Models
switch (Modo)
{
case ModoOperacao.NaoDefinido:
p.ModulosMandatorios = new List<OperacaoModulosMandatoriosModel>();
break;
case ModoOperacao.Manual:
p.Controle = new OperacaoParametrosControleModel()
{
@ -853,6 +853,122 @@ namespace AgroBase.Models
};
}
break;
case ModoOperacao.RetornoBase:
p.Controle = new OperacaoParametrosControleModel()
{
RegistrarDadosPosProcessamento = false,
MovimentoAutomatico = true,
DirecionalAutomatico = true,
PulverizadorAutomatico = false,
SonarAtivado = false,
FrenagemAutomaticaAoParar = true,
ImuParadaPorInclinacao = true,
OakParadaPorObstaculo = true,
MpcMatrizCusto = false,
MpcHorizonte = 4.0,
MovVelocidadeSErvasPercent = 60,
MovVelocidadeCErvasPercent = 20,
DirAnguloMaximo = 30,
DirVelocidadeMovimento = 50,
DirTipoMovimento = TiposControladorDirecional.MPC,
AtuAlturaAreaPulverizacao = 10,
AtuDuracaoAtuacao = 200,
AtuPercentualErvasBicoOff = 2,
AtuPercentualErvasBicoOn = 1,
AtuPercentualInicioPulverizacao = 70,
AtuPressaoLinha = 85,
};
p.ModulosMandatorios = new List<OperacaoModulosMandatoriosModel>()
{
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Ipb,
Mandatorio = true,
Utilizar = true,
},
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Mov,
Mandatorio = true,
Utilizar = true,
},
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Dir,
Mandatorio = true,
Utilizar = true,
},
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Sen,
Mandatorio = true,
Utilizar = true,
},
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Atu,
Mandatorio = true,
Utilizar = true,
},
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Gps,
Mandatorio = true,
Utilizar = true,
},
new OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Snr,
Mandatorio = true,
Utilizar = true,
},
};
p.ParametrosMandatorios = new List<OperacaoParametrosMandatoriosModel>();
if (isagrobase)
{
Variaveis.OperacaoEmAndamento.frmOperacao = new frmOperacaoMapaGPS();
Variaveis.OperacaoEmAndamento.ControleAnterior = new OperacaoControleModel();
Variaveis.OperacaoEmAndamento.Controle = new OperacaoControleModel()
{
TipoMovimento = TipoMovimentoDirecional.RodasDianteiras,
Angulo = 0,
EmFreio = false,
PercentualVelocidadeSP = 0,
AlturaBarra = 50,
TiposControle = new List<OperacaoControleTipoModel>()
{
new OperacaoControleTipoModel()
{
Tipo = T_Code.Mov,
DelayEnvioComandoBase = 500,
DelayEnvioComando = 500,
DelayEnvioComandoExtra = 0,
Comandos = new List<string>(),
UltimoComando = DateTime.Now,
DirecaoAtual = Direcao.Parado,
UltimaDirecao = Direcao.Parado
},
new OperacaoControleTipoModel()
{
Tipo = T_Code.Dir,
DelayEnvioComandoBase = 300,
DelayEnvioComando = 300,
DelayEnvioComandoExtra = 0,
Comandos = new List<string>(),
UltimoComando = DateTime.Now,
DirecaoAtual = Direcao.Parado,
UltimaDirecao = Direcao.Parado
},
},
};
}
break;
}
p.ModulosMandatorios.Add(new OperacaoModulosMandatoriosModel() { Dispositivo = T_Code.Npc, Mandatorio = true, Utilizar = true });
@ -1044,7 +1160,7 @@ namespace AgroBase.Models
DataFim = DateTime.MinValue;
idxLog = 0;
ID = DataInicio.ToString("dd_MM_yyyy_HH_mm_ss") + "_" + Modo.ToString();
ID = DataInicio.ToString("dd_MM_yyyy_HH_mm_ss") + "_" + (Parametros?.Modo ?? ModoOperacao.NaoDefinido).ToString();
Directory.CreateDirectory(Variaveis.CaminhoOperacoes + ID + "/");
SalvarOperacao();
@ -1262,17 +1378,55 @@ namespace AgroBase.Models
public static string DeserializarDadosOperacao(string caminho, string arquivo)
{
string opPath = caminho.Replace("data.lgop", arquivo) + ".json";
string opStr = "";
if (File.Exists(opPath))
opStr = File.ReadAllText(opPath);
else
opStr = "[";
if (opStr != "" && !opStr.EndsWith("]"))
string pastaBase = Path.GetDirectoryName(caminho) ?? "";
// compatibilidade com o modelo antigo:
// data.lgop -> {arquivo}.json
string caminhoJsonAntigo = Path.Combine(pastaBase, arquivo + ".json");
if (File.Exists(caminhoJsonAntigo))
{
opStr += "]";
string opStr = File.ReadAllText(caminhoJsonAntigo);
if (!string.IsNullOrWhiteSpace(opStr) && !opStr.TrimEnd().EndsWith("]"))
opStr += "]";
return string.IsNullOrWhiteSpace(opStr) ? "[]" : opStr;
}
return opStr;
// novo modelo:
// {arquivo}_{idx}_{datahora}.jsonl
string[] arquivosJsonl = Directory.Exists(pastaBase)
? Directory.GetFiles(pastaBase, $"{arquivo}_*.jsonl")
.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)
.ToArray()
: Array.Empty<string>();
if (arquivosJsonl.Length == 0)
return "[]";
var sb = new StringBuilder();
sb.Append("[");
bool primeiro = true;
foreach (string arq in arquivosJsonl)
{
foreach (string linha in File.ReadLines(arq))
{
string json = linha?.Trim();
if (string.IsNullOrWhiteSpace(json))
continue;
if (!primeiro)
sb.Append(",");
sb.Append(json);
primeiro = false;
}
}
sb.Append("]");
return sb.ToString();
}
private void SalvarOperacao()
@ -1463,12 +1617,12 @@ namespace AgroBase.Models
return;
}
Variaveis.OperacaoEmAndamento.Sensoriamento.AtualizarDados();
Variaveis.OperacaoEmAndamento.Sensoriamento?.AtualizarDados();
//Variaveis.LoraService?.EnviarDadosParaBase();
if (Variaveis.OperacaoEmAndamento.Modo == ModoOperacao.Manual)
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo == ModoOperacao.Manual)
{
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento?.OperadorVisual;
Sonar?.Resumo?.AtualizarStatusBloqueio(true);
if (Sonar?.Resumo?.EnviarComandoParada ?? false)
{
@ -1781,7 +1935,7 @@ namespace AgroBase.Models
OperacaoSensoriamentoLogModel logGeral = Variaveis.OperacaoEmAndamento.Sensoriamento.Clone();
logGeral.Momento = Agora;
SalvarLog("operacao", logGeral, Fim);
SalvarLogLine("operacao", logGeral);
Variaveis.OperacaoEmAndamento.Sensoriamento.UltimoRegistroLog = DateTime.Now;
Variaveis.OperacaoEmAndamento.Controle.TiposControle.ForEach(x => x.Comandos.Clear());
@ -1812,7 +1966,7 @@ namespace AgroBase.Models
Potencia = Modulo.MovMotor.Potencia,
CicloTrabalho = Modulo.MovMotor.CicloTrabalho
};
SalvarLog(T_Code.Mov.ToString(), logMov, false);
SalvarLogLine(T_Code.Mov.ToString(), logMov);
DirSensoriamentoLogModel logDir = new DirSensoriamentoLogModel()
{
@ -1831,7 +1985,7 @@ namespace AgroBase.Models
AnguloFolgaCompensar = Modulo.DirMotor.AnguloFolgaCompensar,
AnguloReal = Modulo.DirMotor.AnguloReal
};
SalvarLog(T_Code.Dir.ToString(), logDir, false);
SalvarLogLine(T_Code.Dir.ToString(), logDir);
});
AtuSensoriamentoLogModel logAtu = new AtuSensoriamentoLogModel()
@ -1866,7 +2020,7 @@ namespace AgroBase.Models
}).ToList(),
UltimoComandoRespondido = Variaveis.OperacaoEmAndamento.DispAtu.Dados.DadosLeitura.Momento,
};
SalvarLog(T_Code.Atu.ToString(), logAtu, false);
SalvarLogLine(T_Code.Atu.ToString(), logAtu);
var senLeitura = Variaveis.OperacaoEmAndamento.DispSen.Dados;
SensoriamentoMensagemJsonModel logSen = new SensoriamentoMensagemJsonModel()
@ -1882,7 +2036,7 @@ namespace AgroBase.Models
Servos = new List<SensorServoModel>(senLeitura.Servos),
Sinaleiros = new List<SensorSinaleiroModel>(senLeitura.Sinaleiros),
};
SalvarLog(T_Code.Sen.ToString(), logSen, false);
SalvarLogLine(T_Code.Sen.ToString(), logSen);
SalvarLogCameraSolo();
SalvarLogCameraCaminho();
@ -1955,7 +2109,7 @@ namespace AgroBase.Models
if (conectada)
{
var cam_data = JsonConvert.DeserializeObject<Dictionary<string, object>>(RedisService.Get(RedisService.CamKey(Camera.Id)));
SalvarLog(camera_name, cam_data, false);
SalvarLogLine(camera_name, cam_data);
}
}
}
@ -1980,11 +2134,112 @@ namespace AgroBase.Models
if (conectada)
{
var cam_data = JsonConvert.DeserializeObject<Dictionary<string, object>>(RedisService.Get(RedisService.CamKey(Camera.Id)));
SalvarLog(Camera.Dispositivo.ToString(), cam_data, false);
SalvarLogLine(Camera.Dispositivo.ToString(), cam_data);
}
}
private static readonly object _lockLog = new object();
const long TAMANHO_MAX_LOG_BYTES = 50 * 1024 * 1024; // 50 MB
private void SalvarLogLine<T>(string arquivo, T objeto)
{
try
{
var pasta = Path.Combine(
Variaveis.CaminhoOperacoes,
Variaveis.OperacaoEmAndamento.ID
);
if (!Directory.Exists(pasta))
Directory.CreateDirectory(pasta);
string json = JsonConvert.SerializeObject(objeto, Formatting.None);
lock (_lockLog)
{
string caminhoAtual = ObterOuCriarArquivoLogAtual(pasta, arquivo, json);
File.AppendAllText(caminhoAtual, json + Environment.NewLine);
}
}
catch (Exception ex)
{
Console.WriteLine($"Erro ao salvar log '{arquivo}': {ex.Message}");
}
}
private string ObterOuCriarArquivoLogAtual(string pasta, string arquivoBase, string proximoJson)
{
var arquivosExistentes = Directory
.GetFiles(pasta, $"{arquivoBase}_*.jsonl")
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
.ToList();
string ultimoArquivo = arquivosExistentes.LastOrDefault();
if (string.IsNullOrWhiteSpace(ultimoArquivo))
return CriarNovoArquivoLog(pasta, arquivoBase, 1);
var info = new FileInfo(ultimoArquivo);
long tamanhoAposAppend =
info.Exists
? info.Length + System.Text.Encoding.UTF8.GetByteCount(proximoJson + Environment.NewLine)
: System.Text.Encoding.UTF8.GetByteCount(proximoJson + Environment.NewLine);
if (tamanhoAposAppend > TAMANHO_MAX_LOG_BYTES)
{
int proximoIdx = ExtrairIndiceArquivo(ultimoArquivo, arquivoBase) + 1;
return CriarNovoArquivoLog(pasta, arquivoBase, proximoIdx);
}
return ultimoArquivo;
}
private string CriarNovoArquivoLog(string pasta, string arquivoBase, int idx)
{
string horario = DateTime.Now.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
string nomeArquivo = $"{arquivoBase}_{idx:0000}_{horario}.jsonl";
string caminho = Path.Combine(pasta, nomeArquivo);
// já cria vazio para “reservar” o nome
using (File.Create(caminho)) { }
return caminho;
}
private int ExtrairIndiceArquivo(string caminhoArquivo, string arquivoBase)
{
try
{
string nome = Path.GetFileNameWithoutExtension(caminhoArquivo);
// esperado: {arquivo}_{idx}_{horario}
string prefixo = arquivoBase + "_";
if (!nome.StartsWith(prefixo, StringComparison.OrdinalIgnoreCase))
return 0;
string restante = nome.Substring(prefixo.Length);
string[] partes = restante.Split('_');
if (partes.Length < 2)
return 0;
if (int.TryParse(partes[0], out int idx))
return idx;
return 0;
}
catch
{
return 0;
}
}
#endregion
#region FORMULARIO
@ -1994,8 +2249,8 @@ namespace AgroBase.Models
if (Variaveis.OperacaoEmAndamento.OperacaoLiberada)
{
frmOperacao =
Modo == ModoOperacao.Manual ? new frmOperacaoManual() :
Modo == ModoOperacao.MapaGPS ? new frmOperacaoMapaGPS() :
Parametros?.Modo == ModoOperacao.Manual ? new frmOperacaoManual() :
Parametros?.Modo == ModoOperacao.MapaGPS ? new frmOperacaoMapaGPS() :
new Form();
frmOperacao.Show();
@ -2318,6 +2573,7 @@ namespace AgroBase.Models
{
public DateTime Momento { get; set; }
public ModoOperacao Modo { get; set; }
public bool ControleAutomatico { get; set; }
public StatusModulo Status { get; set; }
public string ErroOperacaoLiberada { get; set; }
public bool OperacaoLiberada { get; set; }
@ -2400,7 +2656,7 @@ namespace AgroBase.Models
double tmp_max = Math.Max(Variaveis.OperacaoEmAndamento.DadosPerformance?.GPU_temp ?? 0, Variaveis.OperacaoEmAndamento.DadosPerformance?.CPU_temp ?? 0);
_DispMvd?.Dados?.AtualizarDadosFreio();
_DispSen?.Dados?.AtualizarStatusSinaleiros(Variaveis.OperacaoEmAndamento.Modo, Variaveis.OperacaoEmAndamento.StatusAtual);
_DispSen?.Dados?.AtualizarStatusSinaleiros(Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido, Variaveis.OperacaoEmAndamento.StatusAtual);
_DispAtu?.Dados?.AtualizaTempoAtuadoGeral();
_Cooler?.Atualizar(tmp_max, DateTime.Now);
_Bateria?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0);
@ -2614,7 +2870,8 @@ namespace AgroBase.Models
OperacaoSensoriamentoLogModel dadosAtualizados = new OperacaoSensoriamentoLogModel()
{
Momento = DateTime.Now,
Modo = Variaveis.OperacaoEmAndamento.Modo,
Modo = Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido,
ControleAutomatico = Variaveis.OperacaoEmAndamento.Parametros?.ControleAutomatico ?? false,
Status = Variaveis.OperacaoEmAndamento.Status,
OperacaoLiberada = Variaveis.OperacaoEmAndamento.OperacaoLiberada,
OperacaoIniciada = Variaveis.OperacaoEmAndamento.Iniciado,
@ -2645,7 +2902,7 @@ namespace AgroBase.Models
ModulosSaude = HealthWorkerService.ModulosSaude.ToList(),
DispositivosMapeados = new List<DispositivoDetalhesModel>(SerialService.DispositivosMapeados),
ModsCalibragem = new Dictionary<T_Code, Dictionary<string, bool>>(Variaveis.OperacaoEmAndamento.ModsCalibragem),
Logs = Logs != null ? Logs.Where(x => x.Momento >= UltimoRegistroLog).ToList() : new List<OperacaoSensoriamentoLogErrosModel>(),
Logs = Logs != null ? Logs.Where(x => x?.Momento >= UltimoRegistroLog).ToList() : new List<OperacaoSensoriamentoLogErrosModel>(),
CoolerControl = dadosCooler
};
@ -2664,6 +2921,7 @@ namespace AgroBase.Models
return new OperacaoSensoriamentoLogModel()
{
Modo = Modo,
ControleAutomatico = ControleAutomatico,
Status = Status,
Momento = Momento,
ErroOperacaoLiberada = ErroOperacaoLiberada,

View File

@ -68,6 +68,8 @@ namespace AgroBase.Models.Operacoes
}
}
public bool ControleAutomatico => new List<ModoOperacao>() { ModoOperacao.MapaGPS, ModoOperacao.RetornoBase }.Contains(Modo ?? ModoOperacao.NaoDefinido);
private string _descricao;
public string Descricao
{
@ -511,7 +513,7 @@ namespace AgroBase.Models.Operacoes
Iniciada = op.Iniciado,
Liberada = op.OperacaoLiberada,
Status = op.StatusAtual,
Modo = op.Modo,
Modo = op.Parametros?.Modo ?? ModoOperacao.NaoDefinido,
ImpedimentoErro = op.ErroOperacaoLiberada,
TempoAguardandoSegs = op.TempoAguardandoSegs,
TempoDecorridoSegs = op.TempoDecorridoSegs,

View File

@ -979,7 +979,7 @@ namespace AgroBase.Models
public void LoopAtualizaDados()
{
if (Variaveis.OperacaoEmAndamento.Modo != ModoOperacao.MapaGPS)
if (!(Variaveis.OperacaoEmAndamento.Parametros?.ControleAutomatico ?? false))
return;
AtualizarPropriedadesPontosTrajetoria();
@ -1778,7 +1778,10 @@ namespace AgroBase.Models
if (!valido || pontosRetorno == null || pontosRetorno.Count < 1)
Variaveis.OperacaoEmAndamento.Sensoriamento?.InserirLog(T_Code.Trj, StatusModulo.Falha, 0, "Trajetória de retorno inválida.");
else
{
AplicarTrajetoriaFixaRetorno(pontosRetorno, "RetornoBase");
AtualizarDadosOperacaoParaRetorno();
}
}
private void AplicarTrajetoriaFixaRetorno(List<GPSModel> pontos, string motivo)
@ -1827,13 +1830,19 @@ namespace AgroBase.Models
_TrajetoriaFixa = traj;
Variaveis.OperacaoEmAndamento.Sensoriamento?.InserirLog(T_Code.Trj, StatusModulo.Operante, 100, $"[RETORNO] Trajetória aplicada ({motivo}) - Pontos: {traj.Count}");
}
private void AtualizarDadosOperacaoParaRetorno()
{
AutonomiaCorredor.Parar();
AtualizarDadosTrajetoria();
LoopAtualizaDados();
var _p = OperacaoModel.CarregarParametrosOperacaoPadrao(ModoOperacao.RetornoBase, false);
Variaveis.OperacaoEmAndamento.Parametros = _p;
if (!Variaveis.OperacaoEmAndamento.Iniciado)
{
Variaveis.OperacaoEmAndamento.Iniciado = true;

View File

@ -57,7 +57,7 @@ namespace AgroBase.Models
public static string CaminhoParametros { get; } = "Parametros/";
public static string CaminhoModelos { get; } = "C:\\AgroBaseModels\\";
public static List<IDispositivosService> DispositivosConectados { get; set; } = new List<IDispositivosService>();
public static OperacaoModel OperacaoEmAndamento { get; set; } = new OperacaoModel(ModoOperacao.MapaGPS);
public static OperacaoModel OperacaoEmAndamento { get; set; } = new OperacaoModel();
public static MqttService MqttServiceLocal { get; set; }
public static MqttService MqttServiceBase { get; set; }
public static LoRaEspService LoraService

View File

@ -261,7 +261,7 @@ namespace AgroBase.Services.Operadores
RedisService.AtualizarCampos(
CtxKey.DadosOperacao,
("configurado", true),
("modo", Variaveis.OperacaoEmAndamento.Modo),
("modo", Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido),
("tempo_aguardar_inicio_operacao", Variaveis.OperacaoEmAndamento.TempoIniciarOperacao),
("modulos_mandatorios", _Parametros.ModulosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
("modulos_opcionais", _Parametros.ModulosMandatorios.Where(x => !x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
@ -319,7 +319,7 @@ namespace AgroBase.Services.Operadores
)
);
if (Variaveis.OperacaoEmAndamento.Modo == Enums.ModoOperacao.MapaGPS && (Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?.Any() ?? false))
if ((Variaveis.OperacaoEmAndamento.Parametros?.ControleAutomatico ?? false) && (Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?.Any() ?? false))
{
var comando = new
{

View File

@ -379,7 +379,13 @@ namespace AgroBase.Services
});
if (PrimeiraExecucao)
{
OperacaoModel.CarregarParametrosOperacaoPadrao(ModoOperacao.MapaGPS, true);
//OperacaoModel.CarregarParametrosOperacaoPadrao(ModoOperacao.MapaGPS, true);
Func<bool> func = new Func<bool>(() =>
{
frmInstancial.frmPrincipal.cmbModoOperacao.SelectedIndex = (int)ModoOperacao.MapaGPS;
return true;
});
FuncoesGlobais.ExecutarMetodoComVerificacaoCrossThread(frmInstancial.frmPrincipal.cmbModoOperacao, func);
}
//DispositivosMapeados.ForEach(d => d.AtualizarDados());

View File

@ -105,7 +105,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool):
if _tipo_controle == TiposControladorDirecional.MPC:
op_modo = ModoOperacao(_operacao.get("modo", ModoOperacao.NaoDefinido.value))
if op_modo == ModoOperacao.MapaGPS:
if op_modo in [ModoOperacao.MapaGPS, ModoOperacao.RetornoBase]:
return _comando_mapa_gps_mpc(contexto)
elif op_modo == ModoOperacao.MapeamentoVisual:
return _comando_mapeamento_visual(contexto)

View File

@ -36,7 +36,7 @@ def definir_comando(filtro_vel: FiltroVelocidade, erro_orientacao: float = None)
reduzir_para_pulverizar = False
pontos_fim_corredor = -1
if op_modo == ModoOperacao.MapaGPS:
if op_modo in [ModoOperacao.MapaGPS, ModoOperacao.RetornoBase]:
_trajetoria = _contexto.get("Trajetoria", {})
status_carro = StatusCarroMapa(_trajetoria.get("status", StatusCarroMapa.Parado.value))
if erro_orientacao is None: erro_orientacao = _trajetoria.get("erro_angular", 0)

View File

@ -478,7 +478,7 @@ class ContextoGlobalRedis:
return
# 🔸 Modo MAPA GPS ou IA
if modo in [ModoOperacao.MapaGPS, ModoOperacao.TreinamentoIA, ModoOperacao.MapeamentoVisual]:
if modo in [ModoOperacao.MapaGPS, ModoOperacao.TreinamentoIA, ModoOperacao.MapeamentoVisual, ModoOperacao.RetornoBase]:
# Iniciando operacao
if (iniciado and not status_iniciado_anterior):
cls._iniciar_operacao()

View File

@ -39,6 +39,7 @@ class ModoOperacao(IntEnum):
MapaGPS = 2
TreinamentoIA = 3
MapeamentoVisual = 4
RetornoBase = 5
class StatusOperacao(IntEnum):
NaoIniciado = 0

View File

@ -39,10 +39,11 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
OnPropertyChanged(nameof(TextoAjuda));
OnPropertyChanged(nameof(StatusBrush));
if (VariaveisControleOperacao.RoverEmFoco != null)
var r = VariaveisControleOperacao.RoverEmFoco;
if (r != null)
{
VariaveisControleOperacao.RoverEmFoco.Controle.MovimentoAutomatico = !value;
VariaveisControleOperacao.RoverEmFoco.Controle.DirecionalAutomatico = !value;
r.Controle.MovimentoAutomatico = value ? false : r.ControleAutomatico;
r.Controle.DirecionalAutomatico = value ? false : r.ControleAutomatico;
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
{
Controle = VariaveisControleOperacao.RoverEmFoco?.Controle

Binary file not shown.

Binary file not shown.

Binary file not shown.