Ajustes na barra pulverizadora
This commit is contained in:
parent
59c1326d0a
commit
c4cf9a2742
|
|
@ -51,6 +51,9 @@ namespace OperationControl.Controls
|
|||
public static readonly DependencyProperty LongitudeProperty = DependencyProperty.Register(nameof(Longitude), typeof(double), typeof(MapViewControl), new PropertyMetadata(0.0, OnViewPropertyChanged));
|
||||
public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(nameof(Scale), typeof(double), typeof(MapViewControl), new PropertyMetadata(5000.0, OnViewPropertyChanged));
|
||||
public static readonly DependencyProperty MbTilesPathProperty = DependencyProperty.Register(nameof(MbTilesPath), typeof(string), typeof(MapViewControl), new PropertyMetadata(string.Empty, OnMbTilesPathChanged));
|
||||
|
||||
public string PathMapaSelecionado;
|
||||
|
||||
public double Latitude
|
||||
{
|
||||
get => (double)GetValue(LatitudeProperty);
|
||||
|
|
@ -122,7 +125,10 @@ namespace OperationControl.Controls
|
|||
public List<StreetMapDictionaryModel> RuasMapaCarregado;
|
||||
|
||||
public event EventHandler<StreetMapClickedEventArgs>? StreetMapClicked;
|
||||
private bool ParametrizandoOperacao => !(VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Iniciada ?? false) && (VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Status ?? StatusOperacao.NaoIniciado) == StatusOperacao.Parametrizando;
|
||||
private bool ParametrizandoOperacao =>
|
||||
!(VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Iniciada ?? false) &&
|
||||
(VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Status ?? StatusOperacao.NaoIniciado) == StatusOperacao.Parametrizando &&
|
||||
((App)System.Windows.Application.Current).Shell.Dock?._vm?._viewOperacaoRight?._vm?.SecaoAtual == ViewModels.Views.Operacao.SecaoRightBar.Parametrizacao;
|
||||
protected virtual void OnStreetMapClicked(string streetId)
|
||||
{
|
||||
StreetMapClicked?.Invoke(this, new StreetMapClickedEventArgs(streetId, RuasMapaCarregado.Where(x => x.Selected).Select(x => x.Id).ToList()));
|
||||
|
|
@ -653,15 +659,15 @@ namespace OperationControl.Controls
|
|||
|
||||
if (dlg.ShowDialog() == true)
|
||||
{
|
||||
var path = dlg.FileName;
|
||||
if (path.EndsWith(".shp", StringComparison.OrdinalIgnoreCase))
|
||||
PathMapaSelecionado = dlg.FileName;
|
||||
if (PathMapaSelecionado.EndsWith(".shp", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var geojson = ConvertShpToGeoJson(path);
|
||||
var geojson = ConvertShpToGeoJson(PathMapaSelecionado);
|
||||
AddGeoJsonLayer(geojson);
|
||||
}
|
||||
else
|
||||
{
|
||||
var geojson = File.ReadAllText(path);
|
||||
var geojson = File.ReadAllText(PathMapaSelecionado);
|
||||
AddGeoJsonLayer(geojson);
|
||||
}
|
||||
}
|
||||
|
|
@ -800,19 +806,21 @@ namespace OperationControl.Controls
|
|||
}
|
||||
|
||||
|
||||
public void LoadMapFile(string path)
|
||||
public void LoadMapFile(string? path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
|
||||
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path) || path == PathMapaSelecionado)
|
||||
return;
|
||||
|
||||
if (path.EndsWith(".shp", StringComparison.OrdinalIgnoreCase))
|
||||
PathMapaSelecionado = path;
|
||||
|
||||
if (PathMapaSelecionado.EndsWith(".shp", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var geojson = ConvertShpToGeoJson(path);
|
||||
var geojson = ConvertShpToGeoJson(PathMapaSelecionado);
|
||||
AddGeoJsonLayer(geojson);
|
||||
}
|
||||
else
|
||||
{
|
||||
var geojson = File.ReadAllText(path);
|
||||
var geojson = File.ReadAllText(PathMapaSelecionado);
|
||||
AddGeoJsonLayer(geojson);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<UserControl x:Class="OperationControl.Controls.Pulverizador.BicoLequeIndicator"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:OperationControl.Controls.Pulverizador"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="120" d:DesignWidth="120">
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
MinWidth="56"
|
||||
MinHeight="80"
|
||||
d:DesignWidth="80"
|
||||
d:DesignHeight="88">
|
||||
|
||||
<UserControl.Resources>
|
||||
<!-- pode reaproveitar as mesmas cores do outro control -->
|
||||
<SolidColorBrush x:Key="LineBrush" Color="#FFB0BAC8"/>
|
||||
<SolidColorBrush x:Key="SprayBrush" Color="#FF00A8E8"/>
|
||||
<SolidColorBrush x:Key="CommandOnBrush" Color="#FFE74C3C"/>
|
||||
<SolidColorBrush x:Key="CommandOffBrush" Color="#FFB0BAC8"/>
|
||||
|
|
@ -17,33 +17,36 @@
|
|||
<SolidColorBrush x:Key="TextPrimary" Color="#FFF5F7FA"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="0">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<!-- dados -->
|
||||
<RowDefinition Height="30"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<!-- desenho -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Dados do bico (mock, depois a gente binda) -->
|
||||
<UniformGrid Grid.Row="0" Rows="2" Columns="2" Height="30" Width="90" HorizontalAlignment="Center">
|
||||
<!-- infos -->
|
||||
<!-- infos -->
|
||||
<StackPanel Grid.Row="0"
|
||||
Orientation="Vertical"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Center">
|
||||
|
||||
<TextBlock Text="{Binding Vazao, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F1} mL/s}" Foreground="{StaticResource TextSecondary}" FontSize="10" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding TempoAtuado, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F1} s}" Foreground="{StaticResource TextSecondary}" FontSize="10" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding AnguloControle, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F0}°}" Foreground="{StaticResource TextSecondary}" FontSize="10" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Atuacoes, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0} x}" Foreground="{StaticResource TextSecondary}" FontSize="10" HorizontalAlignment="Center"/>
|
||||
</UniformGrid>
|
||||
|
||||
<!-- Desenho do bico + leque -->
|
||||
<Canvas x:Name="DrawCanvas" Grid.Row="1" Margin="0,2,0,0" Width="Auto" Height="80">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<TextBlock Text="{Binding Atuacoes, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0}x}" Foreground="{StaticResource TextSecondary}" FontSize="10" Margin="0 0 5 0"/>
|
||||
<TextBlock Text="{Binding TempoAtuado, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F1} s}" Foreground="{StaticResource TextSecondary}" FontSize="10" HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Solenoide -->
|
||||
<Rectangle x:Name="SolenoidRect" Width="14" Height="14" Fill="{StaticResource TextPrimary}" Stroke="{StaticResource CommandOffBrush}" StrokeThickness="3" Canvas.Left="53" Canvas.Top="0"/>
|
||||
<!-- desenho -->
|
||||
<Grid Grid.Row="1">
|
||||
<Canvas x:Name="DrawCanvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<Polygon x:Name="SprayPolygon" Stroke="{StaticResource SprayBrush}" StrokeThickness="2" Fill="#2200A8E8" Visibility="Collapsed"/>
|
||||
|
||||
<!-- Linha central do jato -->
|
||||
<Line x:Name="CenterLine" Stroke="{StaticResource SprayBrush}" StrokeThickness="2" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Visibility="Collapsed"/>
|
||||
<Line x:Name="CenterLine" Stroke="{StaticResource SprayBrush}" StrokeThickness="2" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Visibility="Collapsed"/>
|
||||
|
||||
<!-- Leque (triângulo) -->
|
||||
<Polygon x:Name="SprayPolygon" Stroke="{StaticResource SprayBrush}" StrokeThickness="2" Fill="#2200A8E8" Visibility="Collapsed"/>
|
||||
</Canvas>
|
||||
<Rectangle x:Name="SolenoidRect" Width="14" Height="14" RadiusX="2" RadiusY="2" Fill="{StaticResource TextPrimary}" Stroke="{StaticResource CommandOffBrush}" StrokeThickness="3"/>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
|
@ -1,179 +1,166 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Point = System.Windows.Point;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace OperationControl.Controls.Pulverizador
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BicoControl.xaml
|
||||
/// </summary>
|
||||
public partial class BicoLequeIndicator : UserControl
|
||||
{
|
||||
public BicoLequeIndicator()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += (s, e) => UpdateGeometry();
|
||||
|
||||
Loaded += (_, __) => UpdateGeometry();
|
||||
SizeChanged += (_, __) => UpdateGeometry();
|
||||
}
|
||||
|
||||
#region DependencyProperties básicas
|
||||
|
||||
// Comando enviado para a solenoide
|
||||
public bool IsCommandOn
|
||||
{
|
||||
get => (bool)GetValue(IsCommandOnProperty);
|
||||
set => SetValue(IsCommandOnProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty IsCommandOnProperty = DependencyProperty.Register(nameof(IsCommandOn), typeof(bool), typeof(BicoLequeIndicator), new PropertyMetadata(false, OnVisualPropertyChanged));
|
||||
public static readonly DependencyProperty IsCommandOnProperty =
|
||||
DependencyProperty.Register(nameof(IsCommandOn), typeof(bool), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(false, OnVisualPropertyChanged));
|
||||
|
||||
// Leitura de ligado (se está realmente pulverizando)
|
||||
public bool IsSpraying
|
||||
{
|
||||
get => (bool)GetValue(IsSprayingProperty);
|
||||
set => SetValue(IsSprayingProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty IsSprayingProperty = DependencyProperty.Register(nameof(IsSpraying), typeof(bool), typeof(BicoLequeIndicator), new PropertyMetadata(false, OnVisualPropertyChanged));
|
||||
public static readonly DependencyProperty IsSprayingProperty =
|
||||
DependencyProperty.Register(nameof(IsSpraying), typeof(bool), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(false, OnVisualPropertyChanged));
|
||||
|
||||
// Ângulo central do jato (0 = vertical; positivo gira p/ esquerda, negativo p/ direita)
|
||||
public double AnguloControle
|
||||
{
|
||||
get => (double)GetValue(AnguloControleProperty);
|
||||
set => SetValue(AnguloControleProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty AnguloControleProperty = DependencyProperty.Register(nameof(AnguloControle), typeof(double), typeof(BicoLequeIndicator), new PropertyMetadata(0.0, OnGeometryPropertyChanged));
|
||||
public static readonly DependencyProperty AnguloControleProperty =
|
||||
DependencyProperty.Register(nameof(AnguloControle), typeof(double), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(0.0, OnGeometryPropertyChanged));
|
||||
|
||||
// Abertura total do leque (em graus) – ex: 110°
|
||||
public double OpeningAngle
|
||||
{
|
||||
get => (double)GetValue(OpeningAngleProperty);
|
||||
set => SetValue(OpeningAngleProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty OpeningAngleProperty = DependencyProperty.Register(nameof(OpeningAngle), typeof(double), typeof(BicoLequeIndicator), new PropertyMetadata(110.0, OnGeometryPropertyChanged));
|
||||
public static readonly DependencyProperty OpeningAngleProperty =
|
||||
DependencyProperty.Register(nameof(OpeningAngle), typeof(double), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(110.0, OnGeometryPropertyChanged));
|
||||
|
||||
// Vazao instantanea (mL/s)
|
||||
public double Vazao
|
||||
{
|
||||
get => (double)GetValue(VazaoProperty);
|
||||
set => SetValue(VazaoProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty VazaoProperty = DependencyProperty.Register(nameof(Vazao), typeof(double), typeof(BicoLequeIndicator), new PropertyMetadata(0.0, OnGeometryPropertyChanged));
|
||||
public static readonly DependencyProperty VazaoProperty =
|
||||
DependencyProperty.Register(nameof(Vazao), typeof(double), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(0.0));
|
||||
|
||||
// Tempo atuado (s)
|
||||
public double TempoAtuado
|
||||
{
|
||||
get => (double)GetValue(TempoAtuadoProperty);
|
||||
set => SetValue(TempoAtuadoProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty TempoAtuadoProperty = DependencyProperty.Register(nameof(TempoAtuado), typeof(double), typeof(BicoLequeIndicator), new PropertyMetadata(0.0, OnGeometryPropertyChanged));
|
||||
public static readonly DependencyProperty TempoAtuadoProperty =
|
||||
DependencyProperty.Register(nameof(TempoAtuado), typeof(double), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(0.0));
|
||||
|
||||
// Atuacoes
|
||||
public int Atuacoes
|
||||
{
|
||||
get => (int)GetValue(AtuacoesProperty);
|
||||
set => SetValue(AtuacoesProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty AtuacoesProperty = DependencyProperty.Register(nameof(Atuacoes), typeof(int), typeof(BicoLequeIndicator), new PropertyMetadata(0, OnGeometryPropertyChanged));
|
||||
|
||||
#endregion
|
||||
public static readonly DependencyProperty AtuacoesProperty =
|
||||
DependencyProperty.Register(nameof(Atuacoes), typeof(int), typeof(BicoLequeIndicator),
|
||||
new PropertyMetadata(0));
|
||||
|
||||
private static void OnGeometryPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctrl = (BicoLequeIndicator)d;
|
||||
ctrl.UpdateGeometry();
|
||||
if (d is BicoLequeIndicator ctrl)
|
||||
ctrl.UpdateGeometry();
|
||||
}
|
||||
|
||||
private static void OnVisualPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctrl = (BicoLequeIndicator)d;
|
||||
ctrl.UpdateVisualState();
|
||||
if (d is BicoLequeIndicator ctrl)
|
||||
ctrl.UpdateVisualState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atualiza cor da solenoide e visibilidade do leque.
|
||||
/// </summary>
|
||||
private void UpdateVisualState()
|
||||
{
|
||||
if (SolenoidRect == null || SprayPolygon == null)
|
||||
if (SolenoidRect == null || SprayPolygon == null || CenterLine == null)
|
||||
return;
|
||||
|
||||
var onBrush = (Brush)FindResource("CommandOnBrush");
|
||||
var offBrush = (Brush)FindResource("CommandOffBrush");
|
||||
|
||||
SolenoidRect.Stroke = IsCommandOn ? onBrush : offBrush;
|
||||
|
||||
SprayPolygon.Visibility = IsSpraying && OpeningAngle > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
CenterLine.Visibility = IsSpraying ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recalcula geometria do leque e da linha central a partir do ângulo central e abertura.
|
||||
/// </summary>
|
||||
private void UpdateGeometry()
|
||||
{
|
||||
if (DrawCanvas == null || SprayPolygon == null || CenterLine == null)
|
||||
if (DrawCanvas == null || SprayPolygon == null || CenterLine == null || SolenoidRect == null)
|
||||
return;
|
||||
|
||||
double width = DrawCanvas.ActualWidth;
|
||||
double height = DrawCanvas.ActualHeight;
|
||||
if (width <= 0) width = 120;
|
||||
if (height <= 0) height = 80;
|
||||
|
||||
// Origem do bico (ponto da solenoide)
|
||||
if (width <= 0) width = 60;
|
||||
if (height <= 0) height = 40;
|
||||
|
||||
double originX = width / 2.0;
|
||||
double originY = 10.0; // um pouco abaixo do topo
|
||||
double originY = 8.0;
|
||||
|
||||
double length = height - 10.0; // comprimento do jato até próximo do solo
|
||||
double length = Math.Max(16.0, height - 10.0);
|
||||
|
||||
// Metade da abertura em radianos
|
||||
double halfAngleRad = OpeningAngle * 0.5 * Math.PI / 180.0;
|
||||
|
||||
// Deslocamento horizontal na base do leque
|
||||
double dx = Math.Tan(halfAngleRad) * length;
|
||||
|
||||
// Pontos em sistema local (0,0 = bico; y para baixo)
|
||||
Point apex = new Point(0, 0);
|
||||
Point leftLocal = new Point(-dx, length);
|
||||
Point rightLocal = new Point(dx, length);
|
||||
Point centerLocal = new Point(0, length);
|
||||
|
||||
// Rotação pelo ângulo central (em radianos).
|
||||
double theta = AnguloControle * Math.PI / 180.0;
|
||||
double cos = Math.Cos(theta);
|
||||
double sin = Math.Sin(theta);
|
||||
|
||||
Point Rot(Point p) => new Point(
|
||||
Point Rotate(Point p) => new Point(
|
||||
p.X * cos - p.Y * sin,
|
||||
p.X * sin + p.Y * cos);
|
||||
|
||||
Point apexR = Rot(apex);
|
||||
Point leftR = Rot(leftLocal);
|
||||
Point rightR = Rot(rightLocal);
|
||||
Point centerR = Rot(centerLocal);
|
||||
Point apexR = Rotate(apex);
|
||||
Point leftR = Rotate(leftLocal);
|
||||
Point rightR = Rotate(rightLocal);
|
||||
Point centerR = Rotate(centerLocal);
|
||||
|
||||
// Translada para as coordenadas do Canvas
|
||||
apexR.Offset(originX, originY);
|
||||
leftR.Offset(originX, originY);
|
||||
rightR.Offset(originX, originY);
|
||||
centerR.Offset(originX, originY);
|
||||
|
||||
// Atualiza Polygon do leque
|
||||
var pts = new PointCollection { leftR, apexR, rightR };
|
||||
SprayPolygon.Points = pts;
|
||||
SprayPolygon.Points = new PointCollection { leftR, apexR, rightR };
|
||||
|
||||
// Atualiza linha central do jato
|
||||
CenterLine.X1 = apexR.X;
|
||||
CenterLine.Y1 = apexR.Y;
|
||||
CenterLine.X2 = centerR.X;
|
||||
CenterLine.Y2 = centerR.Y;
|
||||
|
||||
// Reposiciona a solenoide exatamente na origem
|
||||
Canvas.SetLeft(SolenoidRect, originX - SolenoidRect.Width / 2.0);
|
||||
Canvas.SetTop(SolenoidRect, originY - SolenoidRect.Height / 2.0);
|
||||
|
||||
UpdateVisualState();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,5 +226,4 @@ namespace OperationControl.Controls.Pulverizador
|
|||
protected void OnPropertyChanged([CallerMemberName] string propName = null)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace OperationControl.Controls.Pulverizador
|
||||
{
|
||||
class Converters
|
||||
public class BarraTopConverter : IMultiValueConverter
|
||||
{
|
||||
}
|
||||
public double MinAlturaCm { get; set; } = 50.0;
|
||||
public double MaxAlturaCm { get; set; } = 80.0;
|
||||
public double TopMinPx { get; set; } = 18.0;
|
||||
public double TopMaxPx { get; set; } = 62.0;
|
||||
|
||||
public class AlturaBarraToMarginFisicaConverter : IValueConverter
|
||||
{
|
||||
public double GroundTop { get; set; } = 80.0; // Y do solo
|
||||
public double Top80Px { get; set; } = 20.0; // Y da barra quando está a 80 cm
|
||||
public double AlturaMaxCm { get; set; } = 80.0;
|
||||
public double BarraOffset { get; set; } = 13.0;
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is double alturaCm)
|
||||
{
|
||||
alturaCm = Math.Clamp(alturaCm, 0, AlturaMaxCm);
|
||||
|
||||
double distanciaPx = GroundTop - Top80Px; // px que representam 80 cm
|
||||
double pxPorCm = distanciaPx / AlturaMaxCm; // regra de 3
|
||||
double alturaPx = alturaCm * pxPorCm;
|
||||
|
||||
double yBarra = GroundTop - alturaPx; // Y da barra na GRID
|
||||
|
||||
double marginTop = yBarra - BarraOffset; // compensa o offset interno
|
||||
|
||||
return new Thickness(33, marginTop, 33, 0);
|
||||
}
|
||||
|
||||
return new Thickness(33, 0, 33, 0);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> System.Windows.Data.Binding.DoNothing;
|
||||
}
|
||||
|
||||
public class BicoPositionFisicaConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length < 5)
|
||||
return 0.0;
|
||||
if (values.Length < 2)
|
||||
return new Thickness(0);
|
||||
|
||||
if (values[0] is not double barraWidth ||
|
||||
values[1] is not int index ||
|
||||
values[2] is not int qtd ||
|
||||
values[3] is not double distEntreBicosCm ||
|
||||
values[4] is not double comprimentoBarraCm)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
if (values[0] is not double alturaCm || values[1] is not double areaHeight)
|
||||
return new Thickness(0);
|
||||
|
||||
if (qtd <= 0 || barraWidth <= 0 || comprimentoBarraCm <= 0)
|
||||
return 0.0;
|
||||
if (MaxAlturaCm <= MinAlturaCm)
|
||||
return new Thickness(0);
|
||||
|
||||
// garante valores válidos
|
||||
distEntreBicosCm = Math.Max(0.0, distEntreBicosCm);
|
||||
double extraOffset = 0.0;
|
||||
if (parameter != null)
|
||||
double.TryParse(parameter.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out extraOffset);
|
||||
|
||||
if (qtd == 1)
|
||||
{
|
||||
// 1 bico: centro da barra
|
||||
return barraWidth / 2.0;
|
||||
}
|
||||
double h = Math.Max(MinAlturaCm, Math.Min(MaxAlturaCm, alturaCm));
|
||||
double t = (h - MinAlturaCm) / (MaxAlturaCm - MinAlturaCm);
|
||||
|
||||
// span "ideal" em cm (do primeiro ao último bico)
|
||||
double spanIdealCm = (qtd - 1) * distEntreBicosCm;
|
||||
double maxTop = Math.Min(TopMaxPx, Math.Max(TopMinPx, areaHeight - 20));
|
||||
double top = maxTop - (t * (maxTop - TopMinPx));
|
||||
|
||||
// Se o span ideal for maior que a barra física, comprimimos
|
||||
double escala = 1.0;
|
||||
if (spanIdealCm > comprimentoBarraCm && qtd > 1)
|
||||
{
|
||||
escala = comprimentoBarraCm / spanIdealCm;
|
||||
}
|
||||
|
||||
double distEfetivaCm = distEntreBicosCm * escala;
|
||||
double spanEfetivoCm = (qtd - 1) * distEfetivaCm;
|
||||
|
||||
// centraliza o conjunto de bicos na barra
|
||||
double offsetCm = (comprimentoBarraCm - spanEfetivoCm) / 2.0;
|
||||
|
||||
// posição em cm do bico atual
|
||||
double xCm = offsetCm + index * distEfetivaCm;
|
||||
|
||||
// regra de 3: cm → px
|
||||
double pxPorCm = barraWidth / comprimentoBarraCm;
|
||||
double xPx = xCm * pxPorCm;
|
||||
|
||||
return xPx;
|
||||
return new Thickness(0, top + extraOffset, 0, 0);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
|
|
@ -116,12 +54,11 @@ namespace OperationControl.Controls.Pulverizador
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
// px por cm na faixa do solo (usando comprimento da barra como referência física)
|
||||
double pxPorCm = totalWidth / comprimentoBarraCm;
|
||||
double widthPx = larguraRuaCm * pxPorCm;
|
||||
|
||||
// não deixa a rua ficar maior que a área disponível
|
||||
if (widthPx > totalWidth) widthPx = totalWidth;
|
||||
if (widthPx > totalWidth)
|
||||
widthPx = totalWidth;
|
||||
|
||||
return widthPx;
|
||||
}
|
||||
|
|
@ -134,7 +71,8 @@ namespace OperationControl.Controls.Pulverizador
|
|||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length < 4) return new Thickness(0);
|
||||
if (values.Length < 4)
|
||||
return new Thickness(0);
|
||||
|
||||
if (values[0] is not double totalWidth ||
|
||||
values[1] is not double erroLateralCm ||
|
||||
|
|
@ -150,19 +88,14 @@ namespace OperationControl.Controls.Pulverizador
|
|||
|
||||
double center = totalWidth / 2.0;
|
||||
|
||||
// erro > 0 = robô desviado pra direita → rua aparece indo pra esquerda
|
||||
// erro > 0 = robô está para a direita, então a rua aparece deslocando para a esquerda
|
||||
double roadCenter = center - erroLateralCm * pxPorCm;
|
||||
|
||||
double left = roadCenter - widthPx / 2.0;
|
||||
|
||||
// SEM travas aqui: pode ser negativo ou maior que totalWidth
|
||||
// o Grid com ClipToBounds cuida de cortar o desenho
|
||||
|
||||
return new Thickness(left, 0, 0, 0);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,192 +1,253 @@
|
|||
<UserControl x:Class="OperationControl.Controls.PulverizadorIndicator"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:OperationControl.Controls.Pulverizador"
|
||||
mc:Ignorable="d" Width="458" Height="123">
|
||||
<!-- ========= RECURSOS ========= -->
|
||||
<UserControl.Resources>
|
||||
<local:BicoPositionFisicaConverter x:Key="BicoPositionFisicaConverter" />
|
||||
<local:AlturaBarraToMarginFisicaConverter x:Key="AlturaBarraToMarginFisicaConverter" GroundTop="80" Top80Px="7" AlturaMaxCm="80" />
|
||||
<local:RuaWidthFisicaConverter x:Key="RuaWidthFisicaConverter" />
|
||||
<local:RuaOffsetFisicaConverter x:Key="RuaOffsetFisicaConverter" />
|
||||
xmlns:ctrl="clr-namespace:OperationControl.Controls"
|
||||
mc:Ignorable="d"
|
||||
MinWidth="420"
|
||||
MinHeight="150"
|
||||
d:DesignWidth="900"
|
||||
d:DesignHeight="180">
|
||||
|
||||
<SolidColorBrush x:Key="BgBrush" Color="#FF101820"/>
|
||||
<SolidColorBrush x:Key="CardBrush" Color="#FF1C2530"/>
|
||||
<SolidColorBrush x:Key="LineBrush" Color="#FFB0BAC8"/>
|
||||
<SolidColorBrush x:Key="AccentBrush" Color="#FF00A8E8"/>
|
||||
<SolidColorBrush x:Key="CommandBrush" Color="#FFE74C3C"/>
|
||||
<SolidColorBrush x:Key="SprayBrush" Color="#FF00A8E8"/>
|
||||
<UserControl.Resources>
|
||||
<local:BarraTopConverter x:Key="BarraTopConverter" MinAlturaCm="50" MaxAlturaCm="80" TopMinPx="18" TopMaxPx="62"/>
|
||||
|
||||
<local:RuaWidthFisicaConverter x:Key="RuaWidthFisicaConverter"/>
|
||||
<local:RuaOffsetFisicaConverter x:Key="RuaOffsetFisicaConverter"/>
|
||||
|
||||
<SolidColorBrush x:Key="CardBrush" Color="#FF162437"/>
|
||||
<SolidColorBrush x:Key="LineBrush" Color="#FFD4DBE5"/>
|
||||
<SolidColorBrush x:Key="TextPrimary" Color="#FFF5F7FA"/>
|
||||
<SolidColorBrush x:Key="TextSecondary" Color="#FFB0BAC8"/>
|
||||
|
||||
<Style x:Key="Card" TargetType="Border">
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
<Setter Property="Background" Value="{StaticResource CardBrush}"/>
|
||||
<Setter Property="Padding" Value="8"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
</Style>
|
||||
<SolidColorBrush x:Key="GroundBrush" Color="#AA8B0000"/>
|
||||
<SolidColorBrush x:Key="CropBrush" Color="#5F6A36"/>
|
||||
|
||||
<Style x:Key="SectionTitle" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextSecondary}"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="InfoLabelStyle" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextSecondary}"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="InfoValueStyle" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextPrimary}"/>
|
||||
<Setter Property="FontSize" Value="15"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Margin" Value="0,0,0,6"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<!-- ========= LAYOUT ========= -->
|
||||
<Grid Background="Transparent" Margin="0" ClipToBounds="True">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<!-- Vista de trás -->
|
||||
</Grid.RowDefinitions>
|
||||
<Border Background="{StaticResource CardBrush}" CornerRadius="12" Padding="12">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="72"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- ===================== VISTA TRASEIRA / LEQUES ===================== -->
|
||||
<Border Grid.Row="1" Style="{StaticResource Card}">
|
||||
<Grid>
|
||||
<!-- ===================== ESQUERDA ===================== -->
|
||||
<Grid Grid.Column="0" Margin="0,0,10,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="24"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="18"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Text="" Style="{StaticResource SectionTitle}"/>
|
||||
<TextBlock Grid.Row="0" Text="{Binding AlturaBarra, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}, StringFormat={}{0:F0} cm}" Foreground="{StaticResource TextPrimary}" FontSize="16" FontWeight="SemiBold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
|
||||
<Grid Grid.Row="1" Margin="10,0,10,-8">
|
||||
<!-- Cota de altura à esquerda -->
|
||||
<Canvas Width="50" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="{StaticResource TextSecondary}" FontSize="10" Canvas.Top="-15" Canvas.Left="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding AlturaBarra, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F0} cm}" />
|
||||
<Slider Minimum="50" Maximum="80" Value="{Binding AlturaBarra, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}" Orientation="Vertical" Height="58" VerticalAlignment="Top" IsDirectionReversed="False" HorizontalAlignment="Center" Canvas.Left="5" />
|
||||
</Canvas>
|
||||
<Grid Grid.Row="1" x:Name="AreaRegua" Margin="0,8,0,30">
|
||||
<!-- Slider -->
|
||||
<Slider Minimum="50"
|
||||
Maximum="80"
|
||||
Value="{Binding AlturaBarra, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Orientation="Vertical"
|
||||
Width="30"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
IsDirectionReversed="False"
|
||||
Margin="0,0,0,0"/>
|
||||
|
||||
<!-- Bicos e leques (traseira) -->
|
||||
<Canvas x:Name="canvasPai">
|
||||
<Canvas.Margin>
|
||||
<Binding Path="AlturaBarra" RelativeSource="{RelativeSource AncestorType=UserControl}" Converter="{StaticResource AlturaBarraToMarginFisicaConverter}" />
|
||||
</Canvas.Margin>
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- Barra -->
|
||||
<Line x:Name="linhaBarra" X1="4" Y1="10" X2="250" Y2="10" Stroke="{StaticResource LineBrush}" StrokeThickness="4" StrokeStartLineCap="Round" StrokeEndLineCap="Round" HorizontalAlignment="Left" VerticalAlignment="Center" Height="20" Canvas.Left="50" Canvas.Top="5" Width="256" />
|
||||
<Rectangle Grid.Row="2" Fill="Transparent"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Bicos dinâmicos -->
|
||||
<ItemsControl ItemsSource="{Binding Bicos, RelativeSource={RelativeSource AncestorType=UserControl}}" AlternationCount="1000">
|
||||
<!-- ===================== CENTRO ===================== -->
|
||||
<Grid Grid.Column="1" Margin="0,0,10,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="85"/>
|
||||
<RowDefinition Height="33"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- área dos bicos -->
|
||||
<Grid Grid.Row="0" x:Name="AreaTecnica">
|
||||
|
||||
<Grid VerticalAlignment="Top">
|
||||
<Grid.Margin>
|
||||
<MultiBinding Converter="{StaticResource BarraTopConverter}" ConverterParameter="5">
|
||||
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}" Path="AlturaBarra"/>
|
||||
<Binding ElementName="AreaTecnica" Path="ActualHeight"/>
|
||||
</MultiBinding>
|
||||
</Grid.Margin>
|
||||
|
||||
<!-- barra -->
|
||||
<Border Height="5" Background="{StaticResource LineBrush}" CornerRadius="3" VerticalAlignment="Top"/>
|
||||
|
||||
<!-- bicos -->
|
||||
<ItemsControl ItemsSource="{Binding Bicos, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}}" Margin="0,-35,0,0">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas />
|
||||
<UniformGrid Rows="1" Columns="{Binding QtdBicos, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}}" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<!-- Define onde cada item fica no Canvas -->
|
||||
<ItemsControl.ItemContainerStyle>
|
||||
<Style TargetType="ContentPresenter">
|
||||
<Setter Property="Canvas.Top" Value="-27" />
|
||||
<Setter Property="Canvas.Left">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource BicoPositionFisicaConverter}">
|
||||
<!-- largura visível da barra em px -->
|
||||
<Binding ElementName="linhaBarra" Path="ActualWidth" />
|
||||
<!-- índice do bico (do modelo) -->
|
||||
<Binding Path="Index" />
|
||||
<!-- quantidade total de bicos -->
|
||||
<Binding Path="QtdBicos" RelativeSource="{RelativeSource AncestorType=UserControl}" />
|
||||
<!-- distância entre bicos em cm -->
|
||||
<Binding Path="DistanciaEntreBicosCm" RelativeSource="{RelativeSource AncestorType=UserControl}" />
|
||||
<!-- comprimento da barra em cm -->
|
||||
<Binding Path="ComprimentoBarraCm" RelativeSource="{RelativeSource AncestorType=UserControl}" />
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
</ItemsControl.ItemContainerStyle>
|
||||
|
||||
<!-- Como desenhar cada bico -->
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type local:BicoModel}">
|
||||
<local:BicoLequeIndicator AnguloControle="{Binding AnguloControle}" OpeningAngle="{Binding OpeningAngle}" IsCommandOn="{Binding IsCommandOn}" IsSpraying="{Binding IsSpraying}" Vazao="{Binding Vazao}" TempoAtuado="{Binding TempoAtuado}" Atuacoes="{Binding Atuacoes}" />
|
||||
<local:BicoLequeIndicator HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Margin="2,0,2,0"
|
||||
AnguloControle="{Binding AnguloControle}"
|
||||
OpeningAngle="{Binding OpeningAngle}"
|
||||
IsCommandOn="{Binding IsCommandOn}"
|
||||
IsSpraying="{Binding IsSpraying}"
|
||||
Vazao="{Binding Vazao}"
|
||||
TempoAtuado="{Binding TempoAtuado}"
|
||||
Atuacoes="{Binding Atuacoes}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Canvas>
|
||||
|
||||
<!-- Bomba Pressurizadora -->
|
||||
<Canvas Width="50" HorizontalAlignment="Right" Margin="0,0,0,0">
|
||||
<!-- Título -->
|
||||
<TextBlock Text="Bomba" FontSize="10" Canvas.Top="-30" Canvas.Left="10" TextAlignment="Right" Width="50">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource SectionTitle}">
|
||||
<Setter Property="Foreground" Value="LightGray"/>
|
||||
|
||||
<Style.Triggers>
|
||||
<!-- Quando a bomba estiver ligada -->
|
||||
<DataTrigger Binding="{Binding IsBombaOn, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="True">
|
||||
<Setter Property="Foreground" Value="#4CD964"/>
|
||||
</DataTrigger>
|
||||
|
||||
<!-- Quando desligada -->
|
||||
<DataTrigger Binding="{Binding IsBombaOn, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="False">
|
||||
<Setter Property="Foreground" Value="#FFB0BAC8"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
|
||||
<!-- Dados da bomba (pressão e tempo) -->
|
||||
<StackPanel Orientation="Vertical" Canvas.Left="10" Canvas.Top="-18" TextBlock.TextAlignment="Right">
|
||||
<!-- Linha 1: pressão -->
|
||||
<TextBlock Text="Pressão" Foreground="{StaticResource TextSecondary}" FontSize="10"/>
|
||||
<TextBlock Text="{Binding PressaoLinha, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F2} psi}" Foreground="{StaticResource TextPrimary}" FontSize="12" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||
|
||||
<!-- Linha 2: tempo ligado -->
|
||||
<TextBlock Text="Tempo" Foreground="{StaticResource TextSecondary}" FontSize="10"/>
|
||||
<TextBlock Text="{Binding TempoAtuado, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F2} s}" Foreground="{StaticResource TextPrimary}" FontSize="12" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||
|
||||
<!-- Linha 3: vazao -->
|
||||
<TextBlock Text="Vazão" Foreground="{StaticResource TextSecondary}" FontSize="10"/>
|
||||
<TextBlock Text="{Binding VazaoInstantanea, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:F2} mL/s}" Foreground="{StaticResource TextPrimary}" FontSize="12" FontWeight="SemiBold"/>
|
||||
</StackPanel>
|
||||
</Canvas>
|
||||
|
||||
<!-- Solo + Rua -->
|
||||
<Grid Height="13" VerticalAlignment="Top" Margin="-18,80,-18,0" ClipToBounds="True">
|
||||
|
||||
<!-- Cana (fundo) -->
|
||||
<Border Background="#5F6A36" CornerRadius="0,0,8,8"/>
|
||||
|
||||
<!-- Rua (faixa vermelha que desliza) -->
|
||||
<Border Height="13" HorizontalAlignment="Left" Background="#AA8B0000" CornerRadius="0,0,8,8">
|
||||
|
||||
<!-- Largura da rua em px -->
|
||||
<Border.Width>
|
||||
<MultiBinding Converter="{StaticResource RuaWidthFisicaConverter}">
|
||||
<!-- largura em px da faixa do solo -->
|
||||
<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="ActualWidth"/>
|
||||
<!-- largura da rua em cm -->
|
||||
<Binding Path="LarguraRuaCm"/>
|
||||
<!-- comprimento físico representado (cm) -->
|
||||
<Binding Path="ComprimentoBarraCm"/>
|
||||
</MultiBinding>
|
||||
</Border.Width>
|
||||
|
||||
<!-- Deslocamento lateral da rua -->
|
||||
<Border.Margin>
|
||||
<MultiBinding Converter="{StaticResource RuaOffsetFisicaConverter}">
|
||||
<!-- largura em px -->
|
||||
<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="ActualWidth"/>
|
||||
<!-- erro lateral em cm (0 centro, - esquerda, + direita) -->
|
||||
<Binding Path="ErroLateralCm"/>
|
||||
<!-- largura rua cm -->
|
||||
<Binding Path="LarguraRuaCm"/>
|
||||
<!-- comprimento barra cm (escala px/cm) -->
|
||||
<Binding Path="ComprimentoBarraCm"/>
|
||||
</MultiBinding>
|
||||
</Border.Margin>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- solo -->
|
||||
<Grid Grid.Row="1" ClipToBounds="True" Margin="8,0,8,0">
|
||||
<Border Background="{StaticResource CropBrush}" CornerRadius="0,0,8,8"/>
|
||||
|
||||
<Border HorizontalAlignment="Left" Background="{StaticResource GroundBrush}" CornerRadius="0,0,8,8">
|
||||
<Border.Width>
|
||||
<MultiBinding Converter="{StaticResource RuaWidthFisicaConverter}">
|
||||
<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="ActualWidth"/>
|
||||
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}" Path="LarguraRuaCm"/>
|
||||
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}" Path="ComprimentoBarraCm"/>
|
||||
</MultiBinding>
|
||||
</Border.Width>
|
||||
|
||||
<Border.Margin>
|
||||
<MultiBinding Converter="{StaticResource RuaOffsetFisicaConverter}">
|
||||
<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="ActualWidth"/>
|
||||
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}" Path="ErroLateralCm"/>
|
||||
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}" Path="LarguraRuaCm"/>
|
||||
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}" Path="ComprimentoBarraCm"/>
|
||||
</MultiBinding>
|
||||
</Border.Margin>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
<!-- ===================== DIREITA ===================== -->
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="10"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="28"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="Bomba"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource SectionTitle}">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextSecondary}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsBombaOn, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}}" Value="True">
|
||||
<Setter Property="Foreground" Value="#4CD964"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
|
||||
<Grid Grid.Row="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,2,0,2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Pressão -->
|
||||
<Grid Grid.Row="0" Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Text="Pressão"
|
||||
Style="{StaticResource InfoLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding PressaoLinha, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}, StringFormat={}{0:F1} psi}"
|
||||
Foreground="{StaticResource TextPrimary}"
|
||||
FontSize="13"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Tempo -->
|
||||
<Grid Grid.Row="1" Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Text="Tempo"
|
||||
Style="{StaticResource InfoLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding TempoAtuado, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}, StringFormat={}{0:F1} s}"
|
||||
Foreground="{StaticResource TextPrimary}"
|
||||
FontSize="13"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Vazão -->
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Text="Vazão"
|
||||
Style="{StaticResource InfoLabelStyle}"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding VazaoInstantanea, RelativeSource={RelativeSource AncestorType={x:Type ctrl:PulverizadorIndicator}}, StringFormat={}{0:F1} mL/s}"
|
||||
Foreground="{StaticResource TextPrimary}"
|
||||
FontSize="13"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
|
|
@ -7,28 +7,22 @@ using UserControl = System.Windows.Controls.UserControl;
|
|||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for PulverizadorIndicator.xaml
|
||||
/// </summary>
|
||||
public partial class PulverizadorIndicator : UserControl
|
||||
{
|
||||
public PulverizadorIndicator()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
RebuildBicos();
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
|
||||
public double DistanciaEntreBicosCm
|
||||
{
|
||||
get => (double)GetValue(DistanciaEntreBicosCmProperty);
|
||||
set => SetValue(DistanciaEntreBicosCmProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DistanciaEntreBicosCmProperty = DependencyProperty.Register(nameof(DistanciaEntreBicosCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(50.0));
|
||||
|
||||
public static readonly DependencyProperty DistanciaEntreBicosCmProperty =
|
||||
DependencyProperty.Register(nameof(DistanciaEntreBicosCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(50.0));
|
||||
|
||||
public double ComprimentoBarraCm
|
||||
{
|
||||
|
|
@ -36,7 +30,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(ComprimentoBarraCmProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ComprimentoBarraCmProperty = DependencyProperty.Register(nameof(ComprimentoBarraCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(103.7));
|
||||
public static readonly DependencyProperty ComprimentoBarraCmProperty =
|
||||
DependencyProperty.Register(nameof(ComprimentoBarraCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(103.7));
|
||||
|
||||
public double AlturaBarra
|
||||
{
|
||||
|
|
@ -44,7 +39,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(AlturaBarraProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AlturaBarraProperty = DependencyProperty.Register(nameof(AlturaBarra), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(50.0));
|
||||
public static readonly DependencyProperty AlturaBarraProperty =
|
||||
DependencyProperty.Register(nameof(AlturaBarra), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(50.0));
|
||||
|
||||
public bool IsBombaOn
|
||||
{
|
||||
|
|
@ -52,7 +48,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(IsBombaOnProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsBombaOnProperty = DependencyProperty.Register(nameof(IsBombaOn), typeof(bool), typeof(PulverizadorIndicator), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsBombaOnProperty =
|
||||
DependencyProperty.Register(nameof(IsBombaOn), typeof(bool), typeof(PulverizadorIndicator), new PropertyMetadata(false));
|
||||
|
||||
public double PressaoLinha
|
||||
{
|
||||
|
|
@ -60,8 +57,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(PressaoLinhaProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PressaoLinhaProperty = DependencyProperty.Register(nameof(PressaoLinha), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
|
||||
public static readonly DependencyProperty PressaoLinhaProperty =
|
||||
DependencyProperty.Register(nameof(PressaoLinha), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
|
||||
public double TempoAtuado
|
||||
{
|
||||
|
|
@ -69,7 +66,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(TempoAtuadoProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TempoAtuadoProperty = DependencyProperty.Register(nameof(TempoAtuado), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
public static readonly DependencyProperty TempoAtuadoProperty =
|
||||
DependencyProperty.Register(nameof(TempoAtuado), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
|
||||
public double VazaoInstantanea
|
||||
{
|
||||
|
|
@ -77,7 +75,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(VazaoInstantaneaProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VazaoInstantaneaProperty = DependencyProperty.Register(nameof(VazaoInstantanea), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
public static readonly DependencyProperty VazaoInstantaneaProperty =
|
||||
DependencyProperty.Register(nameof(VazaoInstantanea), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
|
||||
public int QtdBicos
|
||||
{
|
||||
|
|
@ -85,7 +84,9 @@ namespace OperationControl.Controls
|
|||
set => SetValue(QtdBicosProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty QtdBicosProperty = DependencyProperty.Register(nameof(QtdBicos), typeof(int), typeof(PulverizadorIndicator), new PropertyMetadata(VariaveisEquipamento.QuantidadeBicosPulverizadores, OnQtdBicosChanged));
|
||||
public static readonly DependencyProperty QtdBicosProperty =
|
||||
DependencyProperty.Register(nameof(QtdBicos), typeof(int), typeof(PulverizadorIndicator),
|
||||
new PropertyMetadata(VariaveisEquipamento.QuantidadeBicosPulverizadores, OnQtdBicosChanged));
|
||||
|
||||
public double LarguraRuaCm
|
||||
{
|
||||
|
|
@ -93,8 +94,8 @@ namespace OperationControl.Controls
|
|||
set => SetValue(LarguraRuaCmProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LarguraRuaCmProperty = DependencyProperty.Register(nameof(LarguraRuaCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(150.0));
|
||||
|
||||
public static readonly DependencyProperty LarguraRuaCmProperty =
|
||||
DependencyProperty.Register(nameof(LarguraRuaCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(150.0));
|
||||
|
||||
public double ErroLateralCm
|
||||
{
|
||||
|
|
@ -102,22 +103,24 @@ namespace OperationControl.Controls
|
|||
set => SetValue(ErroLateralCmProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ErroLateralCmProperty = DependencyProperty.Register(nameof(ErroLateralCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
|
||||
public static readonly DependencyProperty ErroLateralCmProperty =
|
||||
DependencyProperty.Register(nameof(ErroLateralCm), typeof(double), typeof(PulverizadorIndicator), new PropertyMetadata(0.0));
|
||||
|
||||
public ObservableCollection<BicoModel> Bicos { get; } = new();
|
||||
|
||||
private static void OnQtdBicosChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (PulverizadorIndicator)d;
|
||||
ctl.RebuildBicos();
|
||||
if (d is PulverizadorIndicator ctl)
|
||||
ctl.RebuildBicos();
|
||||
}
|
||||
|
||||
private void RebuildBicos()
|
||||
{
|
||||
Bicos.Clear();
|
||||
|
||||
for (int i = 0; i < QtdBicos; i++)
|
||||
int quantidade = QtdBicos < 0 ? 0 : QtdBicos;
|
||||
|
||||
for (int i = 0; i < quantidade; i++)
|
||||
{
|
||||
Bicos.Add(new BicoModel
|
||||
{
|
||||
|
|
@ -132,10 +135,5 @@ namespace OperationControl.Controls
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ namespace OperationControl.Models
|
|||
{
|
||||
public class AppShell
|
||||
{
|
||||
public static readonly bool Mock = true;
|
||||
|
||||
private readonly System.Timers.Timer tmrComunicacao = new(1000) { AutoReset = true };
|
||||
private int tmrComunicacaoTicks = 0;
|
||||
private bool tmrComunicacaoTicking = false;
|
||||
|
|
@ -33,6 +35,93 @@ namespace OperationControl.Models
|
|||
Main = new MainWindow();
|
||||
Dock = new DockWindow();
|
||||
Dock.Show();
|
||||
|
||||
if (Mock)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
VariaveisControleOperacao.AdicionarNovoRoverNaRede("01", "192.168.1.100");
|
||||
VariaveisControleOperacao.RoversNaRede.FirstOrDefault().DadosLeitura = new AgroBase.Models.Operacoes.OperacaoParametrosDadosModel()
|
||||
{
|
||||
StatusRover = StatusModulo.Operante,
|
||||
Operacao = new AgroBase.Models.Operacoes.OperacaoParametrosDadosOperacaoModel()
|
||||
{
|
||||
Status = StatusOperacao.Parametrizando
|
||||
},
|
||||
Atuador = new AgroBase.Models.Operacoes.OperacaoParametrosDadosAtuadorModel()
|
||||
{
|
||||
Bombas = new List<AgroBase.Models.Operacoes.OperacaoParametrosDadosBombaModel>()
|
||||
{
|
||||
new AgroBase.Models.Operacoes.OperacaoParametrosDadosBombaModel()
|
||||
{
|
||||
ComandoEstado = true,
|
||||
LeituraEstado = true,
|
||||
ID = "BOMBA",
|
||||
ID_Num = 10,
|
||||
Inicializado = true,
|
||||
Potencia = 50,
|
||||
TempoAtuado = 3000
|
||||
}
|
||||
},
|
||||
Bicos = new List<AgroBase.Models.Operacoes.OperacaoParametrosDadosBicoModel>()
|
||||
{
|
||||
new AgroBase.Models.Operacoes.OperacaoParametrosDadosBicoModel()
|
||||
{
|
||||
AnguloAbertura = 30,
|
||||
ComandoAngulo = 0,
|
||||
ComandoEstado = true,
|
||||
ID = "B01",
|
||||
ID_Num = 1,
|
||||
Inicializado = true,
|
||||
LeituraAngulo = 0,
|
||||
LeituraEstado = true,
|
||||
Posicao = 1,
|
||||
QtdAtuacoes = 5,
|
||||
TempoAtuado = 300,
|
||||
VazaoInstantaneaMLs = 15,
|
||||
VazaoMediaMLs = 30,
|
||||
VolumeVazadoML = 325
|
||||
},
|
||||
new AgroBase.Models.Operacoes.OperacaoParametrosDadosBicoModel()
|
||||
{
|
||||
AnguloAbertura = 30,
|
||||
ComandoAngulo = 0,
|
||||
ComandoEstado = true,
|
||||
ID = "B02",
|
||||
ID_Num = 2,
|
||||
Inicializado = true,
|
||||
LeituraAngulo = 0,
|
||||
LeituraEstado = false,
|
||||
Posicao = 1,
|
||||
QtdAtuacoes = 5,
|
||||
TempoAtuado = 300,
|
||||
VazaoInstantaneaMLs = 15,
|
||||
VazaoMediaMLs = 30,
|
||||
VolumeVazadoML = 325
|
||||
},
|
||||
new AgroBase.Models.Operacoes.OperacaoParametrosDadosBicoModel()
|
||||
{
|
||||
AnguloAbertura = 30,
|
||||
ComandoAngulo = 0,
|
||||
ComandoEstado = false,
|
||||
ID = "B03",
|
||||
ID_Num = 3,
|
||||
Inicializado = true,
|
||||
LeituraAngulo = 0,
|
||||
LeituraEstado = true,
|
||||
Posicao = 2,
|
||||
QtdAtuacoes = 5,
|
||||
TempoAtuado = 300,
|
||||
VazaoInstantaneaMLs = 15,
|
||||
VazaoMediaMLs = 30,
|
||||
VolumeVazadoML = 325
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void tmrComunicacao_Elapsed()
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ namespace OperationControl.Models
|
|||
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
(((App)Application.Current).Shell.Dock?.DataContext as DockWindowViewModel)?.AtualizarDadosTela(rover);
|
||||
((App)Application.Current).Shell.Dock?._vm?.AtualizarDadosTela(rover);
|
||||
}));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -237,7 +237,7 @@ namespace OperationControl.Models
|
|||
}
|
||||
foreach (var rover in rovers_atual)
|
||||
{
|
||||
rover.Alive = (DateTime.Now - rover.UltimoContato).TotalSeconds < TempoRoverVivo;
|
||||
rover.Alive = AppShell.Mock || (DateTime.Now - rover.UltimoContato).TotalSeconds < TempoRoverVivo;
|
||||
if (!rover.Alive)
|
||||
{
|
||||
//((App)Application.Current).Shell.Main?.MAP?.markers?.UpdateMarkerInfo(rover.RoverId, status: AgroBase.Models.Enums.StatusOperacao.Erro);
|
||||
|
|
|
|||
|
|
@ -221,8 +221,7 @@ namespace OperationControl.ViewModels
|
|||
// string fix = GnssService.FixMode(); // "No Fix", "3D", "RTK Float", "RTK Fixed"
|
||||
// double? hdop = GnssService.Hdop();
|
||||
|
||||
bool conectado = Variaveis.GpsService?.IsConnected ?? false; // <-- seu método real aqui
|
||||
conectado = true;
|
||||
bool conectado = AppShell.Mock || (Variaveis.GpsService?.IsConnected ?? false);
|
||||
|
||||
if (!conectado)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -126,6 +126,26 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
SelecionarAlerta(alerta);
|
||||
}
|
||||
|
||||
|
||||
SeveridadeAlerta DeParaStatus(StatusModulo status, bool mandatorio)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case StatusModulo.Operante:
|
||||
return SeveridadeAlerta.Info;
|
||||
case StatusModulo.Alerta:
|
||||
return SeveridadeAlerta.Warning;
|
||||
case StatusModulo.Falha:
|
||||
return mandatorio ? SeveridadeAlerta.Critical : SeveridadeAlerta.Error;
|
||||
case StatusModulo.Conectado:
|
||||
return mandatorio ? SeveridadeAlerta.Warning : SeveridadeAlerta.Info;
|
||||
case StatusModulo.Desconectado:
|
||||
return mandatorio ? SeveridadeAlerta.Critical : SeveridadeAlerta.Error;
|
||||
default:
|
||||
return SeveridadeAlerta.Info;
|
||||
}
|
||||
}
|
||||
|
||||
public void AtualizarListaAlertasRoverSelecionado(string rover_id)
|
||||
{
|
||||
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover_id);
|
||||
|
|
@ -133,25 +153,6 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
var dados_leitura = rover?.DadosLeitura;
|
||||
if (dados_leitura?.ModulosSaude == null) return;
|
||||
|
||||
SeveridadeAlerta DeParaStatus(StatusModulo status, bool mandatorio)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case StatusModulo.Operante:
|
||||
return SeveridadeAlerta.Info;
|
||||
case StatusModulo.Alerta:
|
||||
return SeveridadeAlerta.Warning;
|
||||
case StatusModulo.Falha:
|
||||
return mandatorio ? SeveridadeAlerta.Critical : SeveridadeAlerta.Error;
|
||||
case StatusModulo.Conectado:
|
||||
return mandatorio ? SeveridadeAlerta.Warning : SeveridadeAlerta.Info;
|
||||
case StatusModulo.Desconectado:
|
||||
return mandatorio ? SeveridadeAlerta.Critical : SeveridadeAlerta.Error;
|
||||
default:
|
||||
return SeveridadeAlerta.Info;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mod in dados_leitura.ModulosSaude)
|
||||
{
|
||||
if (mod.saude_individual.Any())
|
||||
|
|
@ -181,6 +182,113 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void AtualizarListaAlertasTodosRovers()
|
||||
{
|
||||
App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
var alertasEsperados = new List<AlertaModel>();
|
||||
|
||||
foreach (var rover in VariaveisControleOperacao.RoversNaRede)
|
||||
{
|
||||
var dadosLeitura = rover?.DadosLeitura;
|
||||
if (dadosLeitura?.ModulosSaude == null)
|
||||
continue;
|
||||
|
||||
foreach (var mod in dadosLeitura.ModulosSaude)
|
||||
{
|
||||
if (mod.saude_individual != null && mod.saude_individual.Any())
|
||||
{
|
||||
foreach (var ind in mod.saude_individual)
|
||||
{
|
||||
if (ind.status == StatusModulo.Operante)
|
||||
continue;
|
||||
|
||||
alertasEsperados.Add(new AlertaModel
|
||||
{
|
||||
Rover_ID = rover.RoverId,
|
||||
Modulo = mod.modulo,
|
||||
Mod_ID = ind.label,
|
||||
Severidade = DeParaStatus(ind.status, ind.em_uso),
|
||||
Mensagem = string.Join(", ", ind.motivos ?? new List<string>()),
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mod.status == StatusModulo.Operante)
|
||||
continue;
|
||||
|
||||
bool mandatorio = rover.ModulosMandatorios?.Any(x =>
|
||||
x.Dispositivo == mod.modulo && x.Mandatorio) ?? false;
|
||||
|
||||
alertasEsperados.Add(new AlertaModel
|
||||
{
|
||||
Rover_ID = rover.RoverId,
|
||||
Modulo = mod.modulo,
|
||||
Mod_ID = null,
|
||||
Severidade = DeParaStatus(mod.status, mandatorio),
|
||||
Mensagem = string.Join(", ", mod.motivos ?? new List<string>()),
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string GerarChave(string roverId, T_Code modulo, string? modId)
|
||||
=> $"{roverId}|{modulo}|{modId ?? ""}";
|
||||
|
||||
var mapaEsperado = alertasEsperados.ToDictionary(
|
||||
x => GerarChave(x.Rover_ID, x.Modulo, x.Mod_ID),
|
||||
x => x);
|
||||
|
||||
var alertasAtuais = AlertasAtivos.ToList();
|
||||
|
||||
// Remove os alertas que não deveriam mais existir
|
||||
foreach (var atual in alertasAtuais)
|
||||
{
|
||||
var chave = GerarChave(atual.Rover_ID, atual.Modulo, atual.Mod_ID);
|
||||
if (!mapaEsperado.ContainsKey(chave))
|
||||
{
|
||||
AlertasAtivos.Remove(atual);
|
||||
|
||||
if (ToastAlerta == atual)
|
||||
LimparToast();
|
||||
}
|
||||
}
|
||||
|
||||
// Adiciona ou atualiza os alertas esperados
|
||||
foreach (var esperado in alertasEsperados)
|
||||
{
|
||||
var existente = AlertasAtivos.FirstOrDefault(x =>
|
||||
x.Rover_ID == esperado.Rover_ID &&
|
||||
x.Modulo == esperado.Modulo &&
|
||||
x.Mod_ID == esperado.Mod_ID);
|
||||
|
||||
if (existente == null)
|
||||
{
|
||||
AlertasAtivos.Add(esperado);
|
||||
MostrarToast(esperado);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool mudou =
|
||||
existente.Mensagem != esperado.Mensagem ||
|
||||
existente.Severidade != esperado.Severidade;
|
||||
|
||||
existente.Mensagem = esperado.Mensagem;
|
||||
existente.Severidade = esperado.Severidade;
|
||||
|
||||
if (mudou)
|
||||
{
|
||||
existente.Timestamp = DateTime.Now;
|
||||
MostrarToast(existente);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -94,16 +94,19 @@ namespace OperationControl.ViewModels
|
|||
|
||||
public void AtualizarDados(GPSModel dados)
|
||||
{
|
||||
LatitudeTexto = dados.Latitude.ToString("F6");
|
||||
LongitudeTexto = dados.Longitude.ToString("F6");
|
||||
AltitudeTexto = $"{dados.Altitude:F1} m";
|
||||
HeadingTexto = $"{dados.OrientacaoReal:F1}°";
|
||||
FixTexto = dados.QualidadeFix.ToString();
|
||||
PrecisaoTexto = $"{dados.PrecisaoCm:F2} cm";
|
||||
SatelitesTexto = dados.NumeroSatelites.ToString();
|
||||
IdadeCorrecaoTexto = $"{dados.IdadeCorrecao:F1} s";
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
LatitudeTexto = dados.Latitude.ToString("F6");
|
||||
LongitudeTexto = dados.Longitude.ToString("F6");
|
||||
AltitudeTexto = $"{dados.Altitude:F1} m";
|
||||
HeadingTexto = $"{dados.OrientacaoReal:F1}°";
|
||||
FixTexto = dados.QualidadeFix.ToString();
|
||||
PrecisaoTexto = $"{dados.PrecisaoCm:F2} cm";
|
||||
SatelitesTexto = dados.NumeroSatelites.ToString();
|
||||
IdadeCorrecaoTexto = $"{dados.IdadeCorrecao:F1} s";
|
||||
|
||||
AtualizarCorFix(dados.QualidadeFix);
|
||||
AtualizarCorFix(dados.QualidadeFix);
|
||||
});
|
||||
}
|
||||
|
||||
private void AtualizarCorFix(TiposCorrecaoGPS fix)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using AgroBase.Models.Operacoes;
|
|||
using Newtonsoft.Json.Linq;
|
||||
using OperationControl.ViewModels.Views.Operacao;
|
||||
using OperationControl.Controls;
|
||||
using static OpenTK.Graphics.OpenGL.GL;
|
||||
|
||||
namespace OperationControl.ViewModels
|
||||
{
|
||||
|
|
@ -136,7 +137,7 @@ namespace OperationControl.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private bool _baseFixada;
|
||||
private bool _baseFixada = AppShell.Mock;
|
||||
public bool BaseFixada
|
||||
{
|
||||
get => _baseFixada;
|
||||
|
|
@ -343,10 +344,8 @@ namespace OperationControl.ViewModels
|
|||
CenterContent = _viewOperacaoCenter;
|
||||
RightContent = _viewOperacaoRight;
|
||||
BottomContent = _viewOperacaoBottom;
|
||||
CriarMarcadorBase(_viewOperacaoCenter?.MapaOperacao);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_ultimoMapaCarregado))
|
||||
_viewOperacaoCenter?.MapaOperacao?.LoadMapFile(_ultimoMapaCarregado);
|
||||
CriarMarcadorBase(_viewOperacaoCenter?.Mapa);
|
||||
AtualizarDadosMapa(null);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -371,25 +370,18 @@ namespace OperationControl.ViewModels
|
|||
AtualizarProgressoFixacaoBase(bf.Progresso, bf.ProgressoStr);
|
||||
if (bf.Progresso >= 100) FinalizarFixacaoBase(true, bf.ProgressoStr);
|
||||
}
|
||||
switch (CurrentStep)
|
||||
MapViewControl? Mapa = CurrentStep == DockStep.PreparacaoMapa ? _viewPreparacaoMapa?.MapaPreparacao : CurrentStep == DockStep.ParametrizacaoRover ? _viewOperacaoCenter?.Mapa : null;
|
||||
if (CurrentStep == DockStep.PreparacaoMapa)
|
||||
{
|
||||
case DockStep.PreparacaoMapa:
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
_viewPreparacaoMapaTop?._vm?.AtualizarDados(dados);
|
||||
_viewPreparacaoMapa?.MapaPreparacao?.markers?.UpdateMarkerPosition(VariaveisControleOperacao.BaseMarkerID, lat: dados?.Latitude, lon: dados?.Longitude, heading: dados?.OrientacaoReal);
|
||||
});
|
||||
break;
|
||||
|
||||
case DockStep.ParametrizacaoRover:
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers?.UpdateMarkerPosition(VariaveisControleOperacao.BaseMarkerID, lat: dados?.Latitude, lon: dados?.Longitude, heading: dados?.OrientacaoReal);
|
||||
break;
|
||||
_viewPreparacaoMapaTop?._vm?.AtualizarDados(dados);
|
||||
}
|
||||
Mapa?.markers?.UpdateMarkerPosition(VariaveisControleOperacao.BaseMarkerID, lat: dados?.Latitude, lon: dados?.Longitude, heading: dados?.OrientacaoReal);
|
||||
}
|
||||
|
||||
public void AtualizarDadosMapa(OperacaoParametrosModel dados)
|
||||
public void AtualizarDadosMapa(OperacaoParametrosModel? dados)
|
||||
{
|
||||
_viewOperacaoCenter?.MapaOperacao?.CarregarDadosMapa(dados?.Mapa, dados?.RuasPercorrer);
|
||||
_viewOperacaoCenter?.Mapa?.LoadMapFile(_ultimoMapaCarregado);
|
||||
_viewOperacaoCenter?.Mapa?.CarregarDadosMapa(dados?.Mapa, dados?.RuasPercorrer);
|
||||
}
|
||||
|
||||
#region TELA 2
|
||||
|
|
@ -500,6 +492,131 @@ namespace OperationControl.ViewModels
|
|||
#endregion
|
||||
|
||||
#region TELA 3
|
||||
public void AtualizarListaRovers(List<OperacaoParametrosModel> rovers_atual)
|
||||
{
|
||||
var cards = rovers_atual.Select(x => new RoverCardModel()
|
||||
{
|
||||
EquipamentoId = x.IP,
|
||||
NumeroSerie = x.RoverId,
|
||||
Status = x.DadosLeitura?.StatusRover ?? AgroBase.Models.Enums.StatusModulo.Desconectado
|
||||
}).ToArray();
|
||||
|
||||
_viewOperacaoRight?._vm?.AtualizarListaRovers(cards);
|
||||
|
||||
foreach (var rover in cards)
|
||||
{
|
||||
if (!_viewOperacaoCenter?.Mapa?.markers?.Added(rover.NumeroSerie) ?? false)
|
||||
{
|
||||
var roverDados = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover.NumeroSerie);
|
||||
if (roverDados != null)
|
||||
{
|
||||
_viewOperacaoCenter?.Mapa?.markers?.AddMarker(
|
||||
rover.NumeroSerie,
|
||||
false,
|
||||
lat: roverDados.DadosLeitura?.Gnss?.Latitude ?? 0,
|
||||
lon: roverDados.DadosLeitura?.Gnss?.Longitude ?? 0,
|
||||
heading: roverDados.DadosLeitura?.Gnss?.OrientacaoReal ?? 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AtualizarDadosTela(OperacaoParametrosModel rover)
|
||||
{
|
||||
if (rover == null) return;
|
||||
var obj = rover.DadosLeitura;
|
||||
if (obj == null) return;
|
||||
|
||||
var simulacao = obj.Controle?.SimulacaoMPC?.Select(x => new double[] { x.longitude, x.latitude })?.ToList();
|
||||
_viewOperacaoCenter?.Mapa?.markers.UpdateMarkerPosition(rover.RoverId, lat: obj.Gnss?.Latitude, lon: obj.Gnss?.Longitude, heading: obj.Gnss?.OrientacaoReal, predict: simulacao);
|
||||
_viewOperacaoCenter?.Mapa?.markers.UpdateMarkerInfo(rover.RoverId, status: obj.Operacao?.Status ?? AgroBase.Models.Enums.StatusOperacao.NaoIniciado);
|
||||
|
||||
//_viewOperacaoBottom?._vm?.AtualizarListaAlertasRoverSelecionado(rover.RoverId);
|
||||
_viewOperacaoBottom?._vm?.AtualizarListaAlertasTodosRovers();
|
||||
|
||||
if (rover.RoverId != VariaveisControleOperacao.SelectedRoverId) return;
|
||||
|
||||
var conexao = obj.ModulosSaude?.FirstOrDefault(x => x.modulo == AgroBase.Models.Enums.T_Code.Ipb);
|
||||
double c = conexao?.saude ?? 0;
|
||||
double conexao_latencia = conexao?.detalhes?["avg_rtt"]?.Value<double>() ?? 0.0;
|
||||
double conexao_perda = conexao?.detalhes?["loss_pct"]?.Value<double>() ?? 0.0;
|
||||
double bwTot = conexao?.detalhes?["bw_total_mbps"]?.Value<double>() ?? 0;
|
||||
string comunicacao = $"{conexao_latencia:0.00} ms {bwTot:0.00} Mbps";
|
||||
string comunicacao_extended = $"{conexao_latencia:0.00} ms {conexao_perda:F2}% {bwTot:0.00} Mbps";
|
||||
|
||||
_viewOperacaoLeft?._vm?.AtualizarRover(
|
||||
rover?.Descricao ?? "",
|
||||
obj.Controle?.PercentualVelocidadeSPKmh ?? 0,
|
||||
obj.Controle?.Angulo ?? 0,
|
||||
obj.Controle?.TipoMovimento ?? AgroBase.Models.Enums.TipoMovimentoDirecional.Diagnostico,
|
||||
obj.Refrigeracao?.Temperatura ?? 0,
|
||||
obj.Bateria?.PercentualBateria ?? 0,
|
||||
obj.Atuador?.PercentualReservatorio ?? 0,
|
||||
$"{c}%",
|
||||
$"{obj.Gnss?.QualidadeFix ?? AgroBase.Models.Enums.TiposCorrecaoGPS.SemCorrecao} {obj.Gnss?.PrecisaoCm:F2} cm"
|
||||
);
|
||||
|
||||
_viewOperacaoRight?._vm?.AtualizarResumo(r =>
|
||||
{
|
||||
r.Operacao = (obj.Operacao?.Liberada ?? false) ? "🔓 Liberada" : "🔒 Bloqueada";
|
||||
r.Modo = obj.Operacao == null ? "-" : obj.Operacao.Modo.ToString();
|
||||
r.Status = obj.Operacao == null ? "-" : $"{obj.Operacao.Status}" + (obj.Operacao.Status == AgroBase.Models.Enums.StatusOperacao.Aguardando ? $" ({obj.Operacao.TempoAguardandoSegs:0}s)" : "");
|
||||
r.Carro = obj.Trajetoria == null ? "-" : obj.Trajetoria.StatusCarro.ToString();
|
||||
r.Temperatura = $"{(obj.PerformanceNcp?.CPU_temp ?? 0):0.00} °C";
|
||||
r.RuaAtual = obj.Trajetoria == null ? "-" : $"{obj.Trajetoria.CorredorAtualDistanciaPercorrida:0.00} m / " + $"{obj.Trajetoria.CorredorAtualDistanciaTotal:0.00} m " + $"({obj.Trajetoria.CorredorAtualIdx + 1})";
|
||||
r.AreaTotal = obj.Trajetoria == null ? "-" : $"{obj.Trajetoria.DistanciaPercorrida:0.00} m / " + $"{obj.Trajetoria.DistanciaTotal:0.00} m";
|
||||
r.Bateria = obj.Bateria == null ? "-" : $"{obj.Bateria.TensaoInstantanea:0.00} V " + $"({TimeSpan.FromMinutes(obj.Bateria.TempoEstimadoRestanteMinutos):dd\\.hh\\:mm\\:ss} " + $"{obj.Bateria.DistanciaEstimadaRestanteMetros:0.00} m)";
|
||||
r.Herbicida = obj.Atuador == null ? "-" : $"{obj.Atuador.VolumeReservatorioL:0.00} L " + $"({TimeSpan.FromMinutes(obj.Atuador.TempoEstimadoRestanteMinutos):hh\\:mm\\:ss} " + $"{obj.Atuador.DistanciaEstimadaRestanteMetros:0.00} m)";
|
||||
r.Infestacao = obj.Atuador == null ? "-" : $"{obj.Atuador.HerbicidaPorAtuacaoMl:0.00} mL/atuação";
|
||||
r.Conexao = comunicacao == null ? "-" : $"{comunicacao}";
|
||||
r.Duracao = obj.Operacao == null ? "00:00:00 / 00:00:00" : $"{TimeSpan.FromSeconds(obj.Operacao.TempoDecorridoSegs):hh\\:mm\\:ss} / " + $"{(string.IsNullOrWhiteSpace(obj.Trajetoria?.TempoEstimadoOperacao) ? "00:00:00" : obj.Trajetoria.TempoEstimadoOperacao)}";
|
||||
|
||||
// Opcionais para progress bars, caso queira evoluir o resumo
|
||||
r.RuaAtualPercentual = obj.Trajetoria?.PercentualRuaAtual ?? 0;
|
||||
r.AreaTotalPercentual = obj.Trajetoria?.PercentualOperacao ?? 0;
|
||||
r.BateriaPercentual = obj.Bateria?.PercentualBateria ?? 0;
|
||||
r.HerbicidaPercentual = obj.Atuador?.PercentualReservatorio ?? 0;
|
||||
r.InfestacaoPercentual = obj.Atuador?.PercentualErvasTerreno ?? 0;
|
||||
});
|
||||
|
||||
_viewOperacaoCenter?.Diagnostico?._vm?.AtualizarDados(rover);
|
||||
_viewOperacaoCenter?.Diagnostico?.AtualizarGraficos();
|
||||
|
||||
var bomba = obj.Atuador?.Bombas?.FirstOrDefault();
|
||||
var ATU = _viewOperacaoCenter.Monitoramento.Pulverizador;
|
||||
ATU.ComprimentoBarraCm = AgroBase.Models.VariaveisEquipamento.ComprimentoBarraPulverizadoraCm;
|
||||
ATU.DistanciaEntreBicosCm = AgroBase.Models.VariaveisEquipamento.DistanciaEntreBicosCm;
|
||||
ATU.AlturaBarra = obj?.Controle?.AlturaBarra ?? AgroBase.Models.VariaveisEquipamento.AlturaBarraPulverizadoraCm;
|
||||
ATU.IsBombaOn = bomba?.LeituraEstado ?? false;
|
||||
ATU.PressaoLinha = obj?.Atuador?.PressaoLinhaPsi ?? 0;
|
||||
ATU.VazaoInstantanea = obj?.Atuador?.VazaoInstantaneaMLs ?? 0;
|
||||
ATU.TempoAtuado = (bomba?.TempoAtuado ?? 0) / 1000.0;
|
||||
|
||||
double erroLateral = ((obj?.Trajetoria?.DistanciaEsquerda ?? 0) - (obj?.Trajetoria?.DistanciaDireita ?? 0)) / 2.0 * 100.0;
|
||||
ATU.LarguraRuaCm = 100.0;
|
||||
ATU.ErroLateralCm = erroLateral;
|
||||
|
||||
if (ATU.QtdBicos != obj?.Atuador?.Bicos?.Count)
|
||||
{
|
||||
ATU.QtdBicos = obj?.Atuador?.Bicos?.Count ?? AgroBase.Models.VariaveisEquipamento.QuantidadeBicosPulverizadores;
|
||||
}
|
||||
|
||||
foreach (var bico in ATU.Bicos)
|
||||
{
|
||||
var _bc = obj?.Atuador?.Bicos?.FirstOrDefault(x => (x.Posicao - 1) == bico.Index);
|
||||
if (_bc == null) continue;
|
||||
|
||||
bico.OpeningAngle = _bc.AnguloAbertura;
|
||||
bico.AnguloControle = _bc.ComandoAngulo;
|
||||
bico.IsCommandOn = _bc.ComandoEstado;
|
||||
bico.IsSpraying = _bc.LeituraEstado;
|
||||
bico.Vazao = _bc.VazaoInstantaneaMLs;
|
||||
bico.Atuacoes = _bc.QtdAtuacoes;
|
||||
bico.TempoAtuado = _bc.TempoAtuado / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void AtualizarTopOperacaoBase()
|
||||
{
|
||||
|
|
@ -558,117 +675,12 @@ namespace OperationControl.ViewModels
|
|||
}
|
||||
|
||||
|
||||
public void AtualizarListaRovers(List<OperacaoParametrosModel> rovers_atual)
|
||||
{
|
||||
var cards = rovers_atual.Select(x => new RoverCardModel()
|
||||
{
|
||||
EquipamentoId = x.IP,
|
||||
NumeroSerie = x.RoverId,
|
||||
Status = x.DadosLeitura?.StatusRover ?? AgroBase.Models.Enums.StatusModulo.Desconectado
|
||||
}).ToArray();
|
||||
|
||||
_viewOperacaoRight?._vm?.AtualizarListaRovers(cards);
|
||||
|
||||
foreach (var rover in cards)
|
||||
{
|
||||
if (!_viewOperacaoCenter?.MapaOperacao?.markers?.Added(rover.NumeroSerie) ?? false)
|
||||
{
|
||||
if (rover.NumeroSerie == VariaveisControleOperacao.BaseMarkerID)
|
||||
{
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers?.AddMarker(
|
||||
rover.NumeroSerie,
|
||||
true,
|
||||
lat: Variaveis.GpsService?.UltimaLeitura?.Latitude ?? 0,
|
||||
lon: Variaveis.GpsService?.UltimaLeitura?.Longitude ?? 0,
|
||||
heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal ?? 0,
|
||||
label: "Base"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
var roverDados = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover.NumeroSerie);
|
||||
if (roverDados != null)
|
||||
{
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers?.AddMarker(
|
||||
rover.NumeroSerie,
|
||||
false,
|
||||
lat: roverDados.DadosLeitura?.Gnss?.Latitude ?? 0,
|
||||
lon: roverDados.DadosLeitura?.Gnss?.Longitude ?? 0,
|
||||
heading: roverDados.DadosLeitura?.Gnss?.OrientacaoReal ?? 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AtualizarDadosTela(OperacaoParametrosModel rover)
|
||||
{
|
||||
if (rover == null) return;
|
||||
var obj = rover.DadosLeitura;
|
||||
if (obj == null) return;
|
||||
|
||||
var simulacao = obj.Controle?.SimulacaoMPC?.Select(x => new double[] { x.longitude, x.latitude })?.ToList();
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers.UpdateMarkerPosition(rover.RoverId, lat: obj.Gnss?.Latitude, lon: obj.Gnss?.Longitude, heading: obj.Gnss?.OrientacaoReal, predict: simulacao);
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers.UpdateMarkerInfo(rover.RoverId, status: obj.Operacao?.Status ?? AgroBase.Models.Enums.StatusOperacao.NaoIniciado);
|
||||
|
||||
_viewOperacaoBottom?._vm?.AtualizarListaAlertasRoverSelecionado(rover.RoverId);
|
||||
|
||||
if (rover.RoverId == VariaveisControleOperacao.SelectedRoverId)
|
||||
{
|
||||
var conexao = obj.ModulosSaude?.FirstOrDefault(x => x.modulo == AgroBase.Models.Enums.T_Code.Ipb);
|
||||
double c = conexao?.saude ?? 0;
|
||||
double conexao_latencia = conexao?.detalhes?["avg_rtt"]?.Value<double>() ?? 0.0;
|
||||
double conexao_perda = conexao?.detalhes?["loss_pct"]?.Value<double>() ?? 0.0;
|
||||
double bwTot = conexao?.detalhes?["bw_total_mbps"]?.Value<double>() ?? 0;
|
||||
string comunicacao = $"{conexao_latencia:0.00} ms {bwTot:0.00} Mbps";
|
||||
string comunicacao_extended = $"{conexao_latencia:0.00} ms {conexao_perda:F2}% {bwTot:0.00} Mbps";
|
||||
|
||||
_viewOperacaoLeft?._vm?.AtualizarRover(
|
||||
rover?.Descricao ?? "",
|
||||
obj.Controle?.PercentualVelocidadeSPKmh ?? 0,
|
||||
obj.Controle?.Angulo ?? 0,
|
||||
obj.Controle?.TipoMovimento ?? AgroBase.Models.Enums.TipoMovimentoDirecional.Diagnostico,
|
||||
obj.Refrigeracao?.Temperatura ?? 0,
|
||||
obj.Bateria?.PercentualBateria ?? 0,
|
||||
obj.Atuador?.PercentualReservatorio ?? 0,
|
||||
$"{c}%",
|
||||
$"{obj.Gnss?.QualidadeFix ?? AgroBase.Models.Enums.TiposCorrecaoGPS.SemCorrecao} {obj.Gnss?.PrecisaoCm:F2} cm"
|
||||
);
|
||||
|
||||
_viewOperacaoRight?._vm?.AtualizarResumo(r =>
|
||||
{
|
||||
r.Operacao = (obj.Operacao?.Liberada ?? false) ? "🔓 Liberada" : "🔒 Bloqueada";
|
||||
r.Modo = obj.Operacao == null ? "-" : obj.Operacao.Modo.ToString();
|
||||
r.Status = obj.Operacao == null ? "-" : $"{obj.Operacao.Status}" + (obj.Operacao.Status == AgroBase.Models.Enums.StatusOperacao.Aguardando ? $" ({obj.Operacao.TempoAguardandoSegs:0}s)" : "");
|
||||
r.Carro = obj.Trajetoria == null ? "-" : obj.Trajetoria.StatusCarro.ToString();
|
||||
r.Temperatura = $"{(obj.PerformanceNcp?.CPU_temp ?? 0):0.00} °C";
|
||||
r.RuaAtual = obj.Trajetoria == null ? "-" : $"{obj.Trajetoria.CorredorAtualDistanciaPercorrida:0.00} m / " + $"{obj.Trajetoria.CorredorAtualDistanciaTotal:0.00} m " + $"({obj.Trajetoria.CorredorAtualIdx + 1})";
|
||||
r.AreaTotal = obj.Trajetoria == null ? "-" : $"{obj.Trajetoria.DistanciaPercorrida:0.00} m / " + $"{obj.Trajetoria.DistanciaTotal:0.00} m";
|
||||
r.Bateria = obj.Bateria == null ? "-" : $"{obj.Bateria.TensaoInstantanea:0.00} V " + $"({TimeSpan.FromMinutes(obj.Bateria.TempoEstimadoRestanteMinutos):dd\\.hh\\:mm\\:ss} " + $"{obj.Bateria.DistanciaEstimadaRestanteMetros:0.00} m)";
|
||||
r.Herbicida = obj.Atuador == null ? "-" : $"{obj.Atuador.VolumeReservatorioL:0.00} L " + $"({TimeSpan.FromMinutes(obj.Atuador.TempoEstimadoRestanteMinutos):hh\\:mm\\:ss} " + $"{obj.Atuador.DistanciaEstimadaRestanteMetros:0.00} m)";
|
||||
r.Infestacao = obj.Atuador == null ? "-" : $"{obj.Atuador.HerbicidaPorAtuacaoMl:0.00} mL/atuação";
|
||||
r.Conexao = comunicacao == null ? "-" : $"{comunicacao}";
|
||||
r.Duracao = obj.Operacao == null ? "00:00:00 / 00:00:00" : $"{TimeSpan.FromSeconds(obj.Operacao.TempoDecorridoSegs):hh\\:mm\\:ss} / " + $"{(string.IsNullOrWhiteSpace(obj.Trajetoria?.TempoEstimadoOperacao) ? "00:00:00" : obj.Trajetoria.TempoEstimadoOperacao)}";
|
||||
|
||||
// Opcionais para progress bars, caso queira evoluir o resumo
|
||||
r.RuaAtualPercentual = obj.Trajetoria?.PercentualRuaAtual ?? 0;
|
||||
r.AreaTotalPercentual = obj.Trajetoria?.PercentualOperacao ?? 0;
|
||||
r.BateriaPercentual = obj.Bateria?.PercentualBateria ?? 0;
|
||||
r.HerbicidaPercentual = obj.Atuador?.PercentualReservatorio ?? 0;
|
||||
r.InfestacaoPercentual = obj.Atuador?.PercentualErvasTerreno ?? 0;
|
||||
});
|
||||
|
||||
_viewOperacaoCenter?.Diagnostico?._vm?.AtualizarDados(rover);
|
||||
_viewOperacaoCenter?.Diagnostico?.AtualizarGraficos();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnRoverSelecionadoChanged(string roverId)
|
||||
{
|
||||
_viewOperacaoRight?._vm?.DestacarRoverNoMapa(roverId);
|
||||
}
|
||||
|
||||
private void OnRoverSelecionadoChanged(RoverCardModel rover)
|
||||
{
|
||||
bool dados_base = rover == null;
|
||||
|
|
@ -683,7 +695,7 @@ namespace OperationControl.ViewModels
|
|||
VariaveisControleOperacao.RoverEmFoco?.RuasPercorrer?.Clear();
|
||||
AtualizarDadosMapa(VariaveisControleOperacao.RoverEmFoco);
|
||||
VariaveisControleOperacao.SelectedRoverId = VariaveisControleOperacao.BaseMarkerID;
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers?.SetMarkerFocused(VariaveisControleOperacao.SelectedRoverId, true);
|
||||
_viewOperacaoCenter?.Mapa?.markers?.SetMarkerFocused(VariaveisControleOperacao.SelectedRoverId, true);
|
||||
|
||||
_viewOperacaoCenter?._vm?.SelecionarRoverLista(rover);
|
||||
|
||||
|
|
@ -693,7 +705,7 @@ namespace OperationControl.ViewModels
|
|||
else
|
||||
{
|
||||
VariaveisControleOperacao.SelectedRoverId = rover.NumeroSerie.ToString();
|
||||
_viewOperacaoCenter?.MapaOperacao?.markers?.SetMarkerFocused(VariaveisControleOperacao.SelectedRoverId, true);
|
||||
_viewOperacaoCenter?.Mapa?.markers?.SetMarkerFocused(VariaveisControleOperacao.SelectedRoverId, true);
|
||||
AtualizarDadosTela(VariaveisControleOperacao.RoverEmFoco);
|
||||
|
||||
VariaveisControleOperacao.RequisitarParametrosOperacao();
|
||||
|
|
@ -703,12 +715,15 @@ namespace OperationControl.ViewModels
|
|||
|
||||
_viewOperacaoCenter?._vm?.SelecionarRoverLista(rover);
|
||||
|
||||
AtualizarDadosMapa(VariaveisControleOperacao.RoverEmFoco);
|
||||
|
||||
AtualizarTopOperacaoRover(VariaveisControleOperacao.SelectedRoverId, ModoOperacaoAtual == ModoOperacao.Manual);
|
||||
}
|
||||
}
|
||||
private void OnSecaoSelecionadaChanged(SecaoRightBar secao)
|
||||
{
|
||||
_viewOperacaoCenter?._vm?.DefinirSecao(secao);
|
||||
AtualizarDadosMapa(VariaveisControleOperacao.RoverEmFoco);
|
||||
}
|
||||
|
||||
private void OnLerParametrosSolicitado()
|
||||
|
|
@ -727,7 +742,7 @@ namespace OperationControl.ViewModels
|
|||
|
||||
var rover = VariaveisControleOperacao.RoverEmFoco;
|
||||
|
||||
VariaveisControleOperacao.EnviarParametrosOperacao(new OperacaoParametrosModel()
|
||||
var novosParametros = new OperacaoParametrosModel()
|
||||
{
|
||||
Modo = parametros.Modo ?? AgroBase.Models.Enums.ModoOperacao.NaoDefinido,
|
||||
Descricao = parametros.Descricao,
|
||||
|
|
@ -740,9 +755,20 @@ namespace OperationControl.ViewModels
|
|||
ModulosMandatorios = rover?.ModulosMandatorios,
|
||||
ParametrosMandatorios = rover?.ParametrosMandatorios,
|
||||
|
||||
RuasPercorrer = _viewOperacaoCenter?.MapaOperacao?.RuasMapaCarregado?.Where(x => x.Selected)?.Select(x => x.Id)?.ToList(),
|
||||
Mapa = _viewOperacaoCenter?.MapaOperacao?.CriarDadosMapa()
|
||||
});
|
||||
RuasPercorrer = _viewOperacaoCenter?.Mapa?.RuasMapaCarregado?.Where(x => x.Selected)?.Select(x => x.Id)?.ToList(),
|
||||
Mapa = _viewOperacaoCenter?.Mapa?.CriarDadosMapa()
|
||||
};
|
||||
|
||||
VariaveisControleOperacao.EnviarParametrosOperacao(novosParametros);
|
||||
|
||||
VariaveisControleOperacao.RoverEmFoco.Modo = novosParametros.Modo;
|
||||
VariaveisControleOperacao.RoverEmFoco.Descricao = novosParametros.Descricao;
|
||||
VariaveisControleOperacao.RoverEmFoco.QtdCamerasSolo = novosParametros.QtdCamerasSolo;
|
||||
VariaveisControleOperacao.RoverEmFoco.QtdBicos = novosParametros.QtdBicos;
|
||||
VariaveisControleOperacao.RoverEmFoco.CapacidadeReservatorio = novosParametros.CapacidadeReservatorio;
|
||||
VariaveisControleOperacao.RoverEmFoco.Controle = novosParametros.Controle;
|
||||
VariaveisControleOperacao.RoverEmFoco.RuasPercorrer = novosParametros.RuasPercorrer;
|
||||
VariaveisControleOperacao.RoverEmFoco.Mapa = novosParametros.Mapa;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -87,49 +87,23 @@
|
|||
</Grid.RowDefinitions>
|
||||
|
||||
<DockPanel Grid.Row="0" Margin="0,0,0,8">
|
||||
<TextBlock Text="Câmera de ervas"
|
||||
DockPanel.Dock="Left"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#E6E6E6"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock Text="Câmera de ervas" DockPanel.Dock="Left" FontSize="12" FontWeight="SemiBold" Foreground="#E6E6E6" VerticalAlignment="Center"/>
|
||||
|
||||
<ComboBox x:Name="cmbCameraTraseiraFrameTipo"
|
||||
Width="130"
|
||||
Height="26"
|
||||
HorizontalAlignment="Right"
|
||||
SelectionChanged="cmbCameraTraseiraFrameTipo_SelectionChanged"/>
|
||||
<ComboBox x:Name="cmbCameraTraseiraFrameTipo" Width="130" Height="26" HorizontalAlignment="Right" SelectionChanged="cmbCameraTraseiraFrameTipo_SelectionChanged"/>
|
||||
|
||||
<TextBlock Text="10 fps • 193 kbps • 5,41% erva • 0,00% cana"
|
||||
Margin="12,0,8,0"
|
||||
Foreground="#AFAFAF"
|
||||
FontSize="11"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"/>
|
||||
<TextBlock Text="10 fps • 193 kbps • 5,41% erva • 0,00% cana" Margin="12,0,8,0" Foreground="#AFAFAF" FontSize="11" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
</DockPanel>
|
||||
|
||||
<Grid Grid.Row="1" Background="Black">
|
||||
<TextBlock Text="SEM SINAL"
|
||||
Foreground="Gray"
|
||||
FontSize="18"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock Text="SEM SINAL" Foreground="Gray" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
|
||||
<Image x:Name="imgVideoWeed"
|
||||
Stretch="Uniform"
|
||||
RenderOptions.BitmapScalingMode="LowQuality"/>
|
||||
<Image x:Name="imgVideoWeed" Stretch="Uniform" RenderOptions.BitmapScalingMode="LowQuality"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- MAPA -->
|
||||
<Border Grid.Row="1" Grid.Column="0"
|
||||
Margin="0,6,6,0"
|
||||
Padding="10"
|
||||
CornerRadius="10"
|
||||
Background="#202020"
|
||||
BorderBrush="#353535"
|
||||
BorderThickness="1">
|
||||
<Border Grid.Row="1" Grid.Column="0" Margin="0,6,6,0" Padding="10" CornerRadius="10" Background="#202020" BorderBrush="#353535" BorderThickness="1">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
|
|
@ -137,12 +111,7 @@
|
|||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="Mapa e posição do rover"
|
||||
Margin="0,0,0,8"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#E6E6E6"/>
|
||||
<TextBlock Grid.Row="0" Text="Mapa e posição do rover" Margin="0,0,0,8" FontSize="12" FontWeight="SemiBold" Foreground="#E6E6E6"/>
|
||||
|
||||
<controls:MapViewControl x:Name="MapaMonitoramento" MarkerClicked="MAP_MarkerClicked" StreetMapClicked="MAP_StreetMapClicked" Grid.Row="1" Latitude="-22.1726572492617" Longitude="-47.3952163870556" Scale="5000" />
|
||||
</Grid>
|
||||
|
|
@ -157,12 +126,12 @@
|
|||
|
||||
<!-- PULVERIZADOR -->
|
||||
<Border Grid.Row="0"
|
||||
Margin="0,0,0,6"
|
||||
Padding="10"
|
||||
CornerRadius="10"
|
||||
Background="#202020"
|
||||
BorderBrush="#353535"
|
||||
BorderThickness="1">
|
||||
Margin="0,0,0,6"
|
||||
Padding="10"
|
||||
CornerRadius="10"
|
||||
Background="#202020"
|
||||
BorderBrush="#353535"
|
||||
BorderThickness="1">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
|
|
@ -171,27 +140,21 @@
|
|||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="Pulverizador"
|
||||
Margin="0,0,0,8"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#E6E6E6"/>
|
||||
Text="Pulverizador"
|
||||
Margin="0,0,0,8"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#E6E6E6"/>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<controls:PulverizadorIndicator x:Name="ATU"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
<controls:PulverizadorIndicator Grid.Row="1"
|
||||
x:Name="areaPulverizador"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- AÇÕES RÁPIDAS -->
|
||||
<Border Grid.Row="1"
|
||||
Padding="10"
|
||||
CornerRadius="10"
|
||||
Background="#202020"
|
||||
BorderBrush="#353535"
|
||||
BorderThickness="1">
|
||||
<Border Grid.Row="1" Padding="10" CornerRadius="10" Background="#202020" BorderBrush="#353535" BorderThickness="1">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
|
|
@ -199,12 +162,7 @@
|
|||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="Ações rápidas"
|
||||
Margin="0,0,0,8"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#E6E6E6"/>
|
||||
<TextBlock Grid.Row="0" Text="Ações rápidas" Margin="0,0,0,8" FontSize="12" FontWeight="SemiBold" Foreground="#E6E6E6"/>
|
||||
|
||||
<UniformGrid Grid.Row="1" Rows="2" Columns="2" Margin="0,4,0,0">
|
||||
<Button Content="Retorno à base" Margin="4"/>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ namespace OperationControl.Views.Operacao
|
|||
|
||||
private TcpVideoReceiver videoFront;
|
||||
private TcpVideoReceiver videoWeed;
|
||||
public PulverizadorIndicator Pulverizador => areaPulverizador;
|
||||
|
||||
public MonitoramentoView()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<!-- MAPA -->
|
||||
<Grid Visibility="{Binding ExibirMapa, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<Border Margin="12" Padding="0" CornerRadius="10" Background="#202020" BorderBrush="#353535" BorderThickness="1" ClipToBounds="True">
|
||||
<controls:MapViewControl x:Name="MapaOperacao" MarkerClicked="MAP_MarkerClicked" StreetMapClicked="MAP_StreetMapClicked" Latitude="-22.1726572492617" Longitude="-47.3952163870556" Scale="5000" />
|
||||
<controls:MapViewControl x:Name="areaMapa" MarkerClicked="MAP_MarkerClicked" StreetMapClicked="MAP_StreetMapClicked" Latitude="-22.1726572492617" Longitude="-47.3952163870556" Scale="5000" />
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
using OperationControl.Controls;
|
||||
using OperationControl.Models;
|
||||
using OperationControl.ViewModels.Views.Operacao;
|
||||
using OperationControl.ViewModels.Views.Operacao.Diagnostico;
|
||||
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace OperationControl.Views.Operacao
|
||||
{
|
||||
|
|
@ -13,6 +9,7 @@ namespace OperationControl.Views.Operacao
|
|||
public partial class OperacaoCenterView : System.Windows.Controls.UserControl
|
||||
{
|
||||
public OperacaoCenterViewModel _vm;
|
||||
public MapViewControl Mapa => _vm?.ConteudoAtual == OperacaoCenterConteudo.Mapa ? areaMapa : _vm?.ConteudoAtual == OperacaoCenterConteudo.Monitoramento ? Monitoramento?.MapaMonitoramento : null;
|
||||
public MonitoramentoView Monitoramento => areaMonitor;
|
||||
public DiagnosticoView Diagnostico => areaDiagnostico;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue