Limpiando el codigo de MainWindow y MainViewModel

This commit is contained in:
Miguel 2024-05-18 10:53:04 +02:00
parent 77ff643642
commit 664d325de8
15 changed files with 619 additions and 255 deletions

View File

@ -20,6 +20,9 @@
<None Remove="Icons\save.png" /> <None Remove="Icons\save.png" />
<None Remove="Icons\start.png" /> <None Remove="Icons\start.png" />
<None Remove="Icons\stop.png" /> <None Remove="Icons\stop.png" />
<None Remove="imagenes\filler.png" />
<None Remove="imagenes\motorNegro.png" />
<None Remove="imagenes\motorVerde.png" />
<None Remove="motor2.png" /> <None Remove="motor2.png" />
<None Remove="tank.png" /> <None Remove="tank.png" />
</ItemGroup> </ItemGroup>
@ -42,7 +45,6 @@
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="OpenCvSharp4.Windows" Version="4.9.0.20240103" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -58,7 +60,9 @@
<Resource Include="Icons\save.png" /> <Resource Include="Icons\save.png" />
<Resource Include="Icons\start.png" /> <Resource Include="Icons\start.png" />
<Resource Include="Icons\stop.png" /> <Resource Include="Icons\stop.png" />
<Resource Include="imagenes\motor2.png" /> <Resource Include="imagenes\filler.png" />
<Resource Include="imagenes\motorNegro.png" />
<Resource Include="imagenes\motorVerde.png" />
<Resource Include="imagenes\tank.png" /> <Resource Include="imagenes\tank.png" />
</ItemGroup> </ItemGroup>

View File

@ -37,14 +37,9 @@ namespace CtrEditor
public DatosDeTrabajo datosDeTrabajo { get; } public DatosDeTrabajo datosDeTrabajo { get; }
public ObservableCollection<string> listaImagenes { get; private set; } // Publicación de las claves del diccionario public ObservableCollection<string> listaImagenes { get; private set; } // Publicación de las claves del diccionario
public ObservableCollection<TipoSimulable> ListaOsBase { get; } = new ObservableCollection<TipoSimulable>(); public ObservableCollection<TipoSimulable> ListaOsBase { get; } = new ObservableCollection<TipoSimulable>();
private ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
public PLCViewModel plcViewModelData;
public Stopwatch stopwatch_PLCRefresh; public Stopwatch stopwatch_PLCRefresh;
public Stopwatch stopwatch_SimRefresh; public Stopwatch stopwatch_SimRefresh;
private bool isSimulationRunning;
private bool isConnected;
public SimulationManagerFP simulationManager = new SimulationManagerFP(); public SimulationManagerFP simulationManager = new SimulationManagerFP();
private readonly DispatcherTimer _timerSimulacion; private readonly DispatcherTimer _timerSimulacion;
@ -59,11 +54,153 @@ namespace CtrEditor
public ICommand TBConnectPLCCommand { get; } public ICommand TBConnectPLCCommand { get; }
public ICommand TBDisconnectPLCCommand { get; } public ICommand TBDisconnectPLCCommand { get; }
public ICommand OpenWorkDirectoryCommand { get; }
// Evento que se dispara cuando se selecciona una nueva imagen // Evento que se dispara cuando se selecciona una nueva imagen
public event EventHandler<string> ImageSelected; public event EventHandler<string> ImageSelected;
public event EventHandler<TickSimulacionEventArgs> TickSimulacion; public event EventHandler<TickSimulacionEventArgs> TickSimulacion;
public event Action<UserControl> OnUserControlSelected; public event Action<UserControl> OnUserControlSelected;
private bool isSimulationRunning;
private bool isConnected;
public PLCViewModel plcViewModelData;
private osBase _selectedItemOsList;
private string _selectedImage = null;
private ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
private float _left;
private float _top;
public float CanvasLeft
{
get => _left;
set
{
_left = value;
OnPropertyChanged(nameof(CanvasLeft));
}
}
public float CanvasTop
{
get => _top;
set
{
_top = value;
OnPropertyChanged(nameof(CanvasTop));
}
}
public bool IsSimulationRunning
{
get => isSimulationRunning;
set
{
isSimulationRunning = value;
OnPropertyChanged(nameof(IsSimulationRunning));
CommandManager.InvalidateRequerySuggested(); // Notificar que el estado de los comandos ha cambiado
}
}
public bool IsConnected
{
get => isConnected;
set
{
isConnected = value;
OnPropertyChanged(nameof(IsConnected));
CommandManager.InvalidateRequerySuggested();
}
}
public string directorioTrabajo
{
get => EstadoPersistente.Instance.directorio;
set
{
if (value != null)
{
EstadoPersistente.Instance.directorio = value; // Actualizar el estado persistente
EstadoPersistente.Instance.GuardarEstado(); // Guardar el estado actualizado
datosDeTrabajo.CargarImagenes();
listaImagenes = new ObservableCollection<string>(datosDeTrabajo.Imagenes.Keys); // Actualizar claves
SelectedImage = null;
if (listaImagenes.FirstOrDefault() != null)
SelectedImage = listaImagenes.FirstOrDefault();
OnPropertyChanged(nameof(directorioTrabajo)); // Notificar el cambio de propiedad
OnPropertyChanged(nameof(listaImagenes)); // Notificar que la lista de imágenes ha cambiado
}
}
}
public PLCViewModel PLCViewModel
{
get { return plcViewModelData; }
set
{
plcViewModelData = value;
OnPropertyChanged(nameof(PLCViewModel));
}
}
public string SelectedImage
{
get => _selectedImage;
set
{
if (_selectedImage != value && value != null)
{
StopSimulation();
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
_selectedImage = value;
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
LoadStateObjetosSimulables();
}
_selectedImage = value;
OnPropertyChanged(nameof(SelectedImage));
}
}
public osBase SelectedItemOsList
{
get => _selectedItemOsList;
set
{
if (_selectedItemOsList != value)
{
_selectedItemOsList = value;
OnPropertyChanged(nameof(SelectedItemOsList));
}
}
}
private TipoSimulable _selectedItem = null;
public TipoSimulable SelectedItem
{
get => _selectedItem;
set
{
if (_selectedItem != value)
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem)); // Notificar que la propiedad ha cambiado
}
}
}
public ObservableCollection<osBase> ObjetosSimulables
{
get => _objetosSimulables;
set
{
if (_objetosSimulables != value)
{
_objetosSimulables = value;
OnPropertyChanged(nameof(ObjetosSimulables));
}
}
}
public MainViewModel() public MainViewModel()
{ {
OpenWorkDirectoryCommand = new RelayCommand(OpenWorkDirectory); OpenWorkDirectoryCommand = new RelayCommand(OpenWorkDirectory);
@ -101,33 +238,44 @@ namespace CtrEditor
} }
private TipoSimulable _selectedItem = null;
public TipoSimulable SelectedItem public void CrearUserControl(Type tipoSimulable)
{ {
get => _selectedItem; // Crear una nueva instancia del osBase correspondiente
set osBase? newosBase = UserControlFactory.GetInstanceForType(tipoSimulable);
if (newosBase != null)
{ {
if (_selectedItem != value) if (CrearUsercontrol(newosBase))
{ // Añadir el nuevo osBase a la colección de objetos simulables
_selectedItem = value; ObjetosSimulables.Add(newosBase);
OnPropertyChanged(nameof(SelectedItem)); // Notificar que la propiedad ha cambiado
}
} }
} }
private bool CrearUsercontrol(osBase osObjeto)
{
Type tipoObjeto = osObjeto.GetType();
// Obtén el UserControl correspondiente para el tipo de objeto
UserControl? userControl = UserControlFactory.GetControlForType(tipoObjeto);
if (userControl != null)
{
// Asignar los datos al UserControl
UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager);
osObjeto._mainViewModel = this;
OnUserControlSelected?.Invoke(userControl);
return true;
}
return false;
}
private void ExecuteDoubleClick(object parameter) private void ExecuteDoubleClick(object parameter)
{ {
if (parameter is TipoSimulable tipoSimulable) if (parameter is TipoSimulable tipoSimulable)
{ {
// Crear una nueva instancia del osBase correspondiente CrearUserControl(tipoSimulable.Tipo);
osBase? newosBase = UserControlFactory.GetInstanceForType(tipoSimulable.Tipo);
if (newosBase != null)
{
if (CrearUsercontrol(newosBase))
// Añadir el nuevo osBase a la colección de objetos simulables
ObjetosSimulables.Add(newosBase);
}
} }
} }
@ -144,28 +292,6 @@ namespace CtrEditor
} }
} }
public bool IsSimulationRunning
{
get => isSimulationRunning;
set
{
isSimulationRunning = value;
OnPropertyChanged(nameof(IsSimulationRunning));
CommandManager.InvalidateRequerySuggested(); // Notificar que el estado de los comandos ha cambiado
}
}
public bool IsConnected
{
get => isConnected;
set
{
isConnected = value;
OnPropertyChanged(nameof(IsConnected));
CommandManager.InvalidateRequerySuggested();
}
}
private void StartSimulation() private void StartSimulation()
{ {
foreach (var objetoSimulable in ObjetosSimulables) foreach (var objetoSimulable in ObjetosSimulables)
@ -238,77 +364,6 @@ namespace CtrEditor
} }
//protected virtual void OnTickSimulacion(TickSimulacionEventArgs e)
//{
// TickSimulacion?.Invoke(this, e);
//}
public string directorioTrabajo
{
get => EstadoPersistente.Instance.directorio;
set
{
if (value != null)
{
EstadoPersistente.Instance.directorio = value; // Actualizar el estado persistente
EstadoPersistente.Instance.GuardarEstado(); // Guardar el estado actualizado
datosDeTrabajo.CargarImagenes();
listaImagenes = new ObservableCollection<string>(datosDeTrabajo.Imagenes.Keys); // Actualizar claves
SelectedImage = null;
if (listaImagenes.FirstOrDefault() != null)
SelectedImage = listaImagenes.FirstOrDefault();
OnPropertyChanged(nameof(directorioTrabajo)); // Notificar el cambio de propiedad
OnPropertyChanged(nameof(listaImagenes)); // Notificar que la lista de imágenes ha cambiado
}
}
}
public PLCViewModel PLCViewModel
{
get { return plcViewModelData; }
set
{
plcViewModelData = value;
OnPropertyChanged(nameof(PLCViewModel));
}
}
private string _selectedImage = null;
public string SelectedImage
{
get => _selectedImage;
set
{
if (_selectedImage != value && value != null)
{
StopSimulation();
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
_selectedImage = value;
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
LoadStateObjetosSimulables();
}
_selectedImage = value;
OnPropertyChanged(nameof(SelectedImage));
}
}
private osBase _selectedItemOsList;
public osBase SelectedItemOsList
{
get => _selectedItemOsList;
set
{
if (_selectedItemOsList != value)
{
_selectedItemOsList = value;
OnPropertyChanged(nameof(SelectedItemOsList));
}
}
}
public ICommand OpenWorkDirectoryCommand { get; }
private void OpenWorkDirectory() private void OpenWorkDirectory()
{ {
var dialog = new VistaFolderBrowserDialog(); var dialog = new VistaFolderBrowserDialog();
@ -322,20 +377,6 @@ namespace CtrEditor
// Lista de osBase // Lista de osBase
// //
public ObservableCollection<osBase> ObjetosSimulables
{
get => _objetosSimulables;
set
{
if (_objetosSimulables != value)
{
_objetosSimulables = value;
OnPropertyChanged(nameof(ObjetosSimulables));
}
}
}
public void Save() public void Save()
{ {
SaveStateObjetosSimulables(); SaveStateObjetosSimulables();
@ -423,28 +464,6 @@ namespace CtrEditor
} }
private bool CrearUsercontrol(osBase osObjeto)
{
Type tipoObjeto = osObjeto.GetType();
// Obtén el UserControl correspondiente para el tipo de objeto
UserControl? userControl = UserControlFactory.GetControlForType(tipoObjeto);
if (userControl != null)
{
// Asignar los datos al UserControl
UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager);
osObjeto._mainViewModel = this;
OnUserControlSelected?.Invoke(userControl);
return true;
}
return false;
}
// Implementación de INotifyPropertyChanged... // Implementación de INotifyPropertyChanged...
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;

View File

@ -22,7 +22,6 @@ using UserControl = System.Windows.Controls.UserControl;
using CheckBox = System.Windows.Controls.CheckBox; using CheckBox = System.Windows.Controls.CheckBox;
using Orientation = System.Windows.Controls.Orientation; using Orientation = System.Windows.Controls.Orientation;
using ListBox = System.Windows.Controls.ListBox; using ListBox = System.Windows.Controls.ListBox;
//using OpenCvSharp;
namespace CtrEditor namespace CtrEditor
@ -70,6 +69,33 @@ namespace CtrEditor
} }
} }
private (float X, float Y) ObtenerCentroCanvasPixels()
{
var scaleTransform = ImagenEnTrabajoCanvas.LayoutTransform as ScaleTransform;
float scaleX = (float)(scaleTransform?.ScaleX ?? 1.0);
float scaleY = (float)(scaleTransform?.ScaleY ?? 1.0);
// Obtiene el área visible del ScrollViewer
float visibleWidth = (float)ImagenEnTrabajoScrollViewer.ViewportWidth;
float visibleHeight = (float)ImagenEnTrabajoScrollViewer.ViewportHeight;
// Obtiene la posición actual del desplazamiento ajustada por el zoom
float offsetX = (float)ImagenEnTrabajoScrollViewer.HorizontalOffset / scaleX;
float offsetY = (float)ImagenEnTrabajoScrollViewer.VerticalOffset / scaleY;
// Calcula el centro visible ajustado
float centerX = offsetX + (visibleWidth / scaleX) / 2;
float centerY = offsetY + (visibleHeight / scaleY) / 2;
return (centerX, centerY);
}
private (float X, float Y) ObtenerCentroCanvasMeters()
{
var c = ObtenerCentroCanvasPixels();
return (PixelToMeter.Instance.calc.PixelsToMeters(c.X), PixelToMeter.Instance.calc.PixelsToMeters(c.Y));
}
private void AgregarUserControl(UserControl userControl) private void AgregarUserControl(UserControl userControl)
{ {
if (userControl is IDataContainer dataContainer) if (userControl is IDataContainer dataContainer)
@ -78,26 +104,12 @@ namespace CtrEditor
if (!NuevoOS.Inicializado) // Aun no fue inicializado if (!NuevoOS.Inicializado) // Aun no fue inicializado
{ {
Random rnd = new Random(); Random rnd = new Random();
// Obtiene el factor de escala
var scaleTransform = ImagenEnTrabajoCanvas.LayoutTransform as ScaleTransform;
double scaleX = scaleTransform?.ScaleX ?? 1.0;
double scaleY = scaleTransform?.ScaleY ?? 1.0;
// Obtiene el área visible del ScrollViewer var centro = ObtenerCentroCanvasPixels();
double visibleWidth = ImagenEnTrabajoScrollViewer.ViewportWidth;
double visibleHeight = ImagenEnTrabajoScrollViewer.ViewportHeight;
// Obtiene la posición actual del desplazamiento ajustada por el zoom
double offsetX = ImagenEnTrabajoScrollViewer.HorizontalOffset / scaleX;
double offsetY = ImagenEnTrabajoScrollViewer.VerticalOffset / scaleY;
// Calcula el centro visible ajustado
double centerX = offsetX + (visibleWidth / scaleX) / 2;
double centerY = offsetY + (visibleHeight / scaleY) / 2;
// Ajusta la posición del UserControl para que esté centrado en el área visible // Ajusta la posición del UserControl para que esté centrado en el área visible
double leftPixels = centerX - (userControl.ActualWidth / 2); double leftPixels = centro.X - (userControl.ActualWidth / 2);
double topPixels = centerY - (userControl.ActualHeight / 2); double topPixels = centro.Y - (userControl.ActualHeight / 2);
// Establece la posición del UserControl // Establece la posición del UserControl
NuevoOS.Left = PixelToMeter.Instance.calc.PixelsToMeters((float)leftPixels + (float)(rnd.NextDouble() - 0.5) ); NuevoOS.Left = PixelToMeter.Instance.calc.PixelsToMeters((float)leftPixels + (float)(rnd.NextDouble() - 0.5) );

View File

@ -31,6 +31,8 @@ namespace CtrEditor.ObjetosSim
return new ucTanque(); return new ucTanque();
if (tipoObjeto == typeof(osSensTemperatura)) if (tipoObjeto == typeof(osSensTemperatura))
return new ucSensTemperatura(); return new ucSensTemperatura();
if (tipoObjeto == typeof(osFiller))
return new ucFiller();
// Puedes añadir más condiciones para otros tipos // Puedes añadir más condiciones para otros tipos
@ -58,6 +60,8 @@ namespace CtrEditor.ObjetosSim
return new osTanque(); return new osTanque();
if (tipoObjeto == typeof(osSensTemperatura)) if (tipoObjeto == typeof(osSensTemperatura))
return new osSensTemperatura(); return new osSensTemperatura();
if (tipoObjeto == typeof(osFiller))
return new osFiller();
// Puedes añadir más condiciones para otros tipos // Puedes añadir más condiciones para otros tipos

View File

@ -18,6 +18,7 @@ using System.Windows.Media;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics;
using Siemens.Simatic.Simulation.Runtime; using Siemens.Simatic.Simulation.Runtime;
using System.Windows.Media.Imaging;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -33,6 +34,7 @@ namespace CtrEditor.ObjetosSim
public interface IDataContainer public interface IDataContainer
{ {
[JsonIgnore]
osBase? Datos { get; set; } osBase? Datos { get; set; }
void Resize(float width, float height); void Resize(float width, float height);
void Move(float Left, float Top); void Move(float Left, float Top);
@ -48,6 +50,7 @@ namespace CtrEditor.ObjetosSim
public bool Inicializado = false; public bool Inicializado = false;
[JsonIgnore]
protected UserControl? _visualRepresentation = null; protected UserControl? _visualRepresentation = null;
public abstract string Nombre { get; set; } public abstract string Nombre { get; set; }
@ -241,6 +244,28 @@ namespace CtrEditor.ObjetosSim
return simulationManager.AddLine(coords.Start, coords.End); return simulationManager.AddLine(coords.Start, coords.End);
} }
public ImageSource ImageFromPath(string value)
{
if (value is string stringValue)
{
return new BitmapImage(new Uri(stringValue, UriKind.RelativeOrAbsolute));
}
return null;
}
static protected T GetLastElement<T>(List<T> list) where T : class
{
if (list.Count > 0)
{
return list[list.Count - 1];
}
else
{
return null;
}
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;

View File

@ -13,8 +13,12 @@
<Grid> <Grid>
<Image Source="/motor2.png" <Image Source="/motor2.png"
Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}" Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
Stretch="Uniform"/> Stretch="Uniform">
<Image.RenderTransform>
<RotateTransform Angle="{Binding Angulo}" />
</Image.RenderTransform>
</Image>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -27,9 +27,9 @@ namespace CtrEditor.ObjetosSim
private string _nombre = "Ejemplo"; private string _nombre = "Ejemplo";
private float _ancho; private float _ancho;
private float _alto; private float _alto;
private float _angulo;
private float _left; private float _left;
private float _top; private float _top;
private float _angulo;
public override float Left public override float Left
{ {
@ -112,7 +112,7 @@ namespace CtrEditor.ObjetosSim
{ {
} }
public override void UpdateControl() public override void UpdateControl(int elapsedMilliseconds)
{ {
} }

24
ObjetosSim/ucFiller.xaml Normal file
View File

@ -0,0 +1,24 @@
<UserControl x:Class="CtrEditor.ObjetosSim.ucFiller"
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:CtrEditor.ObjetosSim"
mc:Ignorable="d"
xmlns:convert="clr-namespace:CtrEditor.Convertidores">
<UserControl.Resources>
<convert:MeterToPixelConverter x:Key="MeterToPixelConverter"/>
</UserControl.Resources>
<Grid>
<Image Source="/imagenes/filler.png"
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
Stretch="Uniform">
<Image.RenderTransform>
<RotateTransform Angle="{Binding Angulo}" />
</Image.RenderTransform>
</Image>
</Grid>
</UserControl>

242
ObjetosSim/ucFiller.xaml.cs Normal file
View File

@ -0,0 +1,242 @@
using CtrEditor.Convertidores;
using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
namespace CtrEditor.ObjetosSim
{
/// <summary>
/// Interaction logic for ucFiller.xaml
/// </summary>
public class osFiller : osBase
{
// Otros datos y métodos relevantes para la simulación
private string _nombre = "Filler";
private float _ancho;
private float _alto;
private float _left;
private float _top;
private float _angulo;
private float _botellas_hora;
private float _velocidad_actual;
private float _diametro_botella;
private string _tag_consenso;
private bool _consenso;
private float TiempoRestante;
private List<simCircle> Botellas = new List<simCircle>();
public bool Consenso
{
get => _consenso;
set
{
_consenso = value;
OnPropertyChanged(nameof(Consenso));
}
}
public float Botellas_hora
{
get => _botellas_hora;
set
{
_botellas_hora = value;
OnPropertyChanged(nameof(Botellas_hora));
}
}
public float Velocidad_actual_percentual
{
get => _velocidad_actual;
set
{
_velocidad_actual = value;
OnPropertyChanged(nameof(Velocidad_actual_percentual));
}
}
public float Diametro_botella
{
get => _diametro_botella;
set
{
_diametro_botella = value;
OnPropertyChanged(nameof(Diametro_botella));
}
}
public string Tag_consenso
{
get => _tag_consenso;
set
{
_tag_consenso = value;
OnPropertyChanged(nameof(Tag_consenso));
}
}
public override float Left
{
get => _left;
set
{
_left = value;
CanvasSetLeftinMeter(value);
OnPropertyChanged(nameof(Left));
}
}
public override float Top
{
get => _top;
set
{
_top = value;
CanvasSetTopinMeter(value);
OnPropertyChanged(nameof(Top));
}
}
public float Ancho
{
get => _ancho;
set
{
_ancho = value;
OnPropertyChanged(nameof(Ancho));
}
}
public float Alto
{
get => _alto;
set
{
_alto = value;
OnPropertyChanged(nameof(Alto));
}
}
public float Angulo
{
get => _angulo;
set
{
_angulo = value;
OnPropertyChanged(nameof(Angulo));
}
}
public override string Nombre
{
get => _nombre;
set
{
if (_nombre != value)
{
_nombre = value;
OnPropertyChanged(nameof(Nombre));
}
}
}
public osFiller()
{
Ancho = 0.30f;
Alto = 0.30f;
Angulo = 0;
Velocidad_actual_percentual = 0;
Diametro_botella = 0.1f;
Botellas_hora = 10000;
}
public override void UpdateGeometryStart()
{
// Se llama antes de la simulacion
}
public override void UpdateGeometryStep()
{
}
public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds)
{
Consenso = LeerBitTag(plc, Tag_consenso);
}
public override void UpdateControl(int elapsedMilliseconds)
{
if (Consenso && Velocidad_actual_percentual>0)
{
TiempoRestante -= elapsedMilliseconds / 1000.0f;
if (TiempoRestante <= 0)
{
TiempoRestante = Botellas_hora * (Velocidad_actual_percentual / 100.0f) / 3600.0f;
var PosSalida = new Vector2(Left, Top);
var UltimaBotellla = GetLastElement<simCircle>(Botellas);
if (UltimaBotellla != null && UltimaBotellla.Center != PosSalida)
Botellas.Add(simulationManager.AddCircle(Diametro_botella, PosSalida, 1));
}
}
}
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
}
}
public partial class ucFiller : UserControl, IDataContainer
{
public osBase? Datos { get; set; }
public ucFiller()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
}
public void Resize(float width, float height)
{
if (Datos is osFiller datos)
{
datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width);
datos.Alto = PixelToMeter.Instance.calc.PixelsToMeters(width);
}
}
public void Move(float LeftPixels, float TopPixels)
{
if (Datos != null)
{
Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
}
}
public void Rotate(float Angle)
{
if (Datos != null)
if (Datos is osFiller datos)
datos.Angulo = Angle;
}
public void Highlight(bool State) { }
public int ZIndex()
{
return 10;
}
}
}

View File

@ -1,7 +1,6 @@
using CtrEditor.Convertidores; using CtrEditor.Convertidores;
using CtrEditor.Siemens; using CtrEditor.Siemens;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OpenCvSharp.Flann;
using Siemens.Simatic.Simulation.Runtime; using Siemens.Simatic.Simulation.Runtime;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -46,7 +45,6 @@ namespace CtrEditor.ObjetosSim
private bool _SalidaAbierta_Bool; private bool _SalidaAbierta_Bool;
private float _capacidadLitros; private float _capacidadLitros;
public float Capacidad_Litros public float Capacidad_Litros
{ {
get => _capacidadLitros; get => _capacidadLitros;

View File

@ -12,7 +12,7 @@
</UserControl.Resources> </UserControl.Resources>
<Grid> <Grid>
<Image Source="/imagenes/motor2.png" <Image Source="{Binding ImageSource}"
Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}" Width="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding Tamano, Converter={StaticResource MeterToPixelConverter}}"
Stretch="Uniform"/> Stretch="Uniform"/>

View File

@ -15,6 +15,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using CtrEditor.Simulacion; using CtrEditor.Simulacion;
using Newtonsoft.Json;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -22,25 +23,10 @@ namespace CtrEditor.ObjetosSim
/// Interaction logic for ucVMmotorSim.xaml /// Interaction logic for ucVMmotorSim.xaml
/// </summary> /// </summary>
/// ///
public class VMSimMotor
{
public bool _STATUS_VFD_Ready;
public float STATUS_VFD_ACT_Speed_Hz;
public bool Motor_Running;
public bool STATUS_VFD_Trip;
public bool STATUS_VFD_Warning;
public bool STATUS_VFD_Coasting;
public bool OUT_Run;
public bool OUT_Stop;
public bool OUT_Reversal;
public float OUT_OUT_VFD_REQ_Speed_Hz;
}
public class osVMmotorSim : osBase public class osVMmotorSim : osBase
{ {
// Otros datos y métodos relevantes para la simulación // Otros datos y métodos relevantes para la simulación
private string _nombre = "VetroMeccanica Motor"; private string _nombre = "VetroMeccanica Motor";
@ -53,9 +39,21 @@ namespace CtrEditor.ObjetosSim
private bool _encendido; private bool _encendido;
private float _rampaSegundos; private float _rampaSegundos;
private float _maxHz; private float _maxHz;
private ImageSource _imageSource;
public VMSimMotor motState = new VMSimMotor(); private VMSimMotor motState = new VMSimMotor();
[Hidden]
[JsonIgnore]
public ImageSource ImageSource
{
get { return _imageSource; }
set
{
_imageSource = value;
OnPropertyChanged(nameof(ImageSource));
}
}
public float Tamano public float Tamano
{ {
@ -89,7 +87,6 @@ namespace CtrEditor.ObjetosSim
} }
} }
public bool Encendido public bool Encendido
{ {
get => _encendido; get => _encendido;
@ -157,6 +154,11 @@ namespace CtrEditor.ObjetosSim
get => _velocidad; get => _velocidad;
set { set {
_velocidad = value; _velocidad = value;
if (value > 0)
ImageSource = ImageFromPath("/imagenes/motorVerde.png");
else
ImageSource = ImageFromPath("/imagenes/motorNegro.png");
OnPropertyChanged(nameof(Velocidad)); OnPropertyChanged(nameof(Velocidad));
} }
} }
@ -167,6 +169,7 @@ namespace CtrEditor.ObjetosSim
PLC_NumeroMotor = 31; PLC_NumeroMotor = 31;
MaxRatedHz = 100; MaxRatedHz = 100;
TiempoRampa = 3; TiempoRampa = 3;
ImageSource = ImageFromPath("/imagenes/motor2.png");
} }
public override void UpdateGeometryStart() public override void UpdateGeometryStart()
@ -178,68 +181,19 @@ namespace CtrEditor.ObjetosSim
{ {
} }
public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds) { public override void UpdatePLC(PLCModel plc, int elapsedMilliseconds) {
var index = 0;
switch (PLC_NumeroMotor)
{
case < 100:
index = (int)PLC_NumeroMotor-30+300;
break;
}
motState.OUT_Run = plc.LeerTagBool($"\"DB MotorSimulate\".Motors[{index}].OUT.Run"); motState.UpdatePLC(plc,PLC_NumeroMotor,Encendido, elapsedMilliseconds);
motState.OUT_Reversal = plc.LeerTagBool($"\"DB MotorSimulate\".Motors[{index}].OUT.\"Reversal Direction\""); Velocidad = motState.STATUS_VFD_ACT_Speed_Hz / 10;
motState.OUT_OUT_VFD_REQ_Speed_Hz = (float)plc.LeerTagInt16($"\"DB MotorSimulate\".Motors[{index}].OUT.OUT_VFD_REQ_Speed_Hz");
if (Encendido)
{
motState._STATUS_VFD_Ready = true;
motState.Motor_Running = true;
motState.STATUS_VFD_Trip = false;
motState.STATUS_VFD_Warning = false;
motState.STATUS_VFD_Coasting = false;
}
else
{
motState._STATUS_VFD_Ready = false;
motState.Motor_Running = false;
motState.STATUS_VFD_Trip = true;
motState.STATUS_VFD_Warning = false;
motState.STATUS_VFD_Coasting = false;
}
// Calculamos la velocidad
motState.STATUS_VFD_ACT_Speed_Hz += CalcSpeedRamp(motState.STATUS_VFD_ACT_Speed_Hz, motState.OUT_OUT_VFD_REQ_Speed_Hz, elapsedMilliseconds);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Ready", motState._STATUS_VFD_Ready);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].Motor_Running", motState.Motor_Running);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Trip", motState.STATUS_VFD_Trip);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Warning", motState.STATUS_VFD_Warning);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Coasting", motState.STATUS_VFD_Coasting);
plc.EscribirTagInt16($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_ACT_Speed_Hz",(int)motState.STATUS_VFD_ACT_Speed_Hz);
Velocidad = motState.STATUS_VFD_ACT_Speed_Hz/10;
}
private float CalcSpeedRamp(float actual, float expected, int elapsedMilliseconds)
{
float hzIncrementsRamp = (MaxRatedHz * 10) / (TiempoRampa * (1000.0f / elapsedMilliseconds));
float delta = expected - actual;
// Conrtolar si la diferencia no es mayor de lo que falta
if (Math.Abs(hzIncrementsRamp)>Math.Abs(delta))
hzIncrementsRamp = Math.Abs(delta);
if (delta < 0)
return -hzIncrementsRamp;
else
return hzIncrementsRamp;
} }
public override void UpdateControl(int elapsedMilliseconds) public override void UpdateControl(int elapsedMilliseconds)
{ {
// Calculamos la velocidad
motState.UpdateSpeed(MaxRatedHz,TiempoRampa, elapsedMilliseconds);
} }
public override void ucLoaded() public override void ucLoaded()
{ {
// El UserControl ya se ha cargado y podemos obtener las coordenadas para // El UserControl ya se ha cargado y podemos obtener las coordenadas para
@ -277,4 +231,82 @@ namespace CtrEditor.ObjetosSim
return 10; return 10;
} }
} }
public class VMSimMotor
{
public bool _STATUS_VFD_Ready;
public float STATUS_VFD_ACT_Speed_Hz;
public bool Motor_Running;
public bool STATUS_VFD_Trip;
public bool STATUS_VFD_Warning;
public bool STATUS_VFD_Coasting;
public bool OUT_Run;
public bool OUT_Stop;
public bool OUT_Reversal;
public float OUT_OUT_VFD_REQ_Speed_Hz;
public void UpdatePLC(PLCModel plc, int NumeroMotor, bool Encendido, int elapsedMilliseconds)
{
var index = 0;
switch (NumeroMotor)
{
case < 100:
index = (int)NumeroMotor - 30 + 300;
break;
}
OUT_Run = plc.LeerTagBool($"\"DB MotorSimulate\".Motors[{index}].OUT.Run");
OUT_Reversal = plc.LeerTagBool($"\"DB MotorSimulate\".Motors[{index}].OUT.\"Reversal Direction\"");
OUT_OUT_VFD_REQ_Speed_Hz = (float)plc.LeerTagInt16($"\"DB MotorSimulate\".Motors[{index}].OUT.OUT_VFD_REQ_Speed_Hz");
if (Encendido)
{
_STATUS_VFD_Ready = true;
Motor_Running = true;
STATUS_VFD_Trip = false;
STATUS_VFD_Warning = false;
STATUS_VFD_Coasting = false;
}
else
{
_STATUS_VFD_Ready = false;
Motor_Running = false;
STATUS_VFD_Trip = true;
STATUS_VFD_Warning = false;
STATUS_VFD_Coasting = false;
}
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Ready", _STATUS_VFD_Ready);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].Motor_Running", Motor_Running);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Trip", STATUS_VFD_Trip);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Warning", STATUS_VFD_Warning);
plc.EscribirTagBool($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_Coasting", STATUS_VFD_Coasting);
plc.EscribirTagInt16($"\"DB MotorSimulate\".Motors[{index}].STATUS_VFD_ACT_Speed_Hz", (int)STATUS_VFD_ACT_Speed_Hz);
}
private float CalcSpeedRamp(float MaxRatedHz, float TiempoRampa, float actual, float expected, int elapsedMilliseconds)
{
float hzIncrementsRamp = (MaxRatedHz * 10) / (TiempoRampa * (1000.0f / elapsedMilliseconds));
float delta = expected - actual;
// Conrtolar si la diferencia no es mayor de lo que falta
if (Math.Abs(hzIncrementsRamp) > Math.Abs(delta))
hzIncrementsRamp = Math.Abs(delta);
if (delta < 0)
return -hzIncrementsRamp;
else
return hzIncrementsRamp;
}
public void UpdateSpeed(float MaxRatedHz, float TiempoRampa, int elapsedMilliseconds)
{
// Calculamos la velocidad
STATUS_VFD_ACT_Speed_Hz += CalcSpeedRamp(MaxRatedHz, TiempoRampa, STATUS_VFD_ACT_Speed_Hz, OUT_OUT_VFD_REQ_Speed_Hz, elapsedMilliseconds);
}
}
} }

BIN
imagenes/filler.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

BIN
imagenes/motorVerde.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB