Push Alpha Version

This commit is contained in:
2026-02-27 16:09:59 +01:00
parent a0ef457995
commit d2665d17fa
209 changed files with 13423 additions and 1034 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

View File

@@ -0,0 +1,17 @@
<Application x:Class="InfineonHMI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InfineonHMI">
<Application.Resources>
<!-- MahApps Metro style themes -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<!-- Theme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Dark.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,42 @@
using System.Windows;
using Heisig.HMI.AdsManager;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TcEventLoggerAdsProxyLib;
namespace InfineonHMI;
public partial class App : Application
{
public static IHost? AppHost { get; private set; }
public App()
{
AppHost = Host.CreateDefaultBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<MainWindow>();
services.AddSingleton<MainWindowVM>();
services.AddSingleton<IAdsManager, AdsManager>();
services.AddSingleton<TcEventLogger>();
})
.Build();
}
protected override async void OnStartup(StartupEventArgs e)
{
await AppHost!.StartAsync();
var startupForm = AppHost.Services.GetRequiredService<MainWindow>();
startupForm.Show();
base.OnStartup(e);
}
protected override async void OnExit(ExitEventArgs e)
{
await AppHost!.StopAsync();
base.OnExit(e);
}
}

View File

@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@@ -0,0 +1,127 @@
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace InfineonHMI.Common
{
public static class L4ItXmlSerializer
{
/// <summary>
/// Serializes an object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="serializableObject"></param>
/// <param name="fileName"></param>
/// <param name="encrypt"></param>
/// <param name="rootElementName"></param>
public static void SerializeObject<T>(T serializableObject, string fileName, bool encrypt = false, string rootElementName = null)
{
if (string.IsNullOrEmpty(fileName))
return;
if (serializableObject == null)
return;
XmlSerializer serializer;
if (rootElementName != null)
{
var xmlRoot = new XmlRootAttribute(rootElementName);
serializer = new XmlSerializer(serializableObject.GetType(), xmlRoot);
}
else
{
serializer = new XmlSerializer(serializableObject.GetType());
}
try
{
var dir = new FileInfo(fileName).DirectoryName;
if (dir != null && !Directory.Exists(dir)) // Überprüfen Sie, ob dir nicht null ist, bevor Sie es verwenden
Directory.CreateDirectory(dir);
var xmlDocument = new XmlDocument();
using var stream = new MemoryStream();
serializer.Serialize(stream, serializableObject);
stream.Position = 0;
xmlDocument.Load(stream);
if (encrypt && false)
{
//FileEncryption.SaveEncryptedToFile(fileName, xmlDocument.OuterXml);
return;
}
xmlDocument.Save(fileName);
}
catch (Exception ex)
{
Console.Write(ex);
}
}
/// <summary>
/// Deserializes an xml file into an object list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName"></param>
/// <param name="decrypt"></param>
/// <param name="rootElementName"></param>
/// <returns></returns>
///
///
public static T DeSerializeObject<T>(string fileName, bool decrypt = false, string rootElementName = null)
{
if (string.IsNullOrEmpty(fileName) || !File.Exists(fileName)) return default!;
T objectOut;
try
{
string xmlString;
if (decrypt && false)
{
//xmlString = FileEncryption.ReadDecryptedFromFile(fileName)!;
}
else
{
var xmlDocument = new XmlDocument();
xmlDocument.Load(fileName);
xmlString = xmlDocument.OuterXml;
}
if (string.IsNullOrEmpty(xmlString))
{
// Handle empty xmlString if necessary
return default!;
}
using var read = new StringReader(xmlString);
var outType = typeof(T);
XmlSerializer serializer;
if (rootElementName != null)
{
var root = new XmlRootAttribute(rootElementName);
serializer = new XmlSerializer(outType, root);
}
else
{
serializer = new XmlSerializer(outType);
}
using XmlReader reader = new XmlTextReader(read);
objectOut = (T)serializer.Deserialize(reader)!;
}
catch (Exception ex)
{
Console.Write(ex);
return default!;
}
return objectOut;
}
}
}

View File

@@ -0,0 +1,83 @@
<UserControl x:Class="Common.MediaContainer"
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:common="clr-namespace:Common"
xmlns:HMIToolkit="clr-namespace:HMIToolkit"
d:DataContext="{d:DesignInstance Type=common:MediaContainerVm, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Width="Auto"
Height="Auto"
MinWidth="200">
<UserControl.Resources>
<HMIToolkit:FeedbackToColorConverter x:Key="feedbackConverter" />
</UserControl.Resources>
<!-- :DataContext="{d:DesignInstance Type=local:AnalogValueVM, IsDesignTimeCreatable=True}" -->
<!-- Style to see things in the designer-->
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!-- Property="Background" Value="White" /> -->
<Setter Property="Height" Value="300" />
<Setter Property="Width" Value="100" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid Height="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="30*"/>
<RowDefinition Height="30*"/>
<RowDefinition Height="30*"/>
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" BorderBrush="White" BorderThickness="2"/>
<!-- <Label Grid.Column="0" Content="{Binding SName}" VerticalAlignment="Center" HorizontalAlignment="Left"/> -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{Binding SName, Mode=OneWay }" HorizontalAlignment="Center" FontSize="24"/>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderBrush="White" BorderThickness="1" />
<Border Grid.Row="1" BorderBrush="White" BorderThickness="1" />
<Label Grid.Row="0" VerticalAlignment="Center" Content="Übervoll" HorizontalAlignment="Center" FontSize="16"/>
<RadioButton Margin="5" Grid.Row="1" IsChecked="{Binding Overload}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<Grid Grid.Column="0" Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderBrush="White" BorderThickness="1" />
<Border Grid.Row="1" BorderBrush="White" BorderThickness="1" />
<Label Grid.Row="0" VerticalAlignment="Center" Content="Voll" HorizontalAlignment="Center" FontSize="16"/>
<RadioButton Grid.Row="1" Margin="5" IsChecked="{Binding Full}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<Grid Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderBrush="White" BorderThickness="1" />
<Border Grid.Row="1" BorderBrush="White" BorderThickness="1" />
<Label Grid.Row="0" VerticalAlignment="Center" Content="Leer" HorizontalAlignment="Center" FontSize="16"/>
<RadioButton Grid.Row="1" Margin="5" IsChecked="{Binding Empty}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<Border Grid.Column="1" Grid.Row="1" Grid.RowSpan="3" BorderBrush="White" BorderThickness="1"></Border>
<Grid Grid.Column="1" Grid.Row="1" Grid.RowSpan="3">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button x:Name="btnFill" DataContext="{Binding FillButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Background="{Binding IFeedback, Converter={StaticResource feedbackConverter}}" Grid.Row="0" Grid.Column="0" Content="Füllen" Margin="5" />
<Button x:Name="btnOpen" DataContext="{Binding EmptyButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Background="{Binding IFeedback, Converter={StaticResource feedbackConverter}}" Grid.Row="1" Grid.Column="0" Content="Leeren" Margin="5" />
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,32 @@
using System.Text.RegularExpressions;
using System.Windows.Controls;
using System.Windows.Input;
namespace Common
{
/// <summary>
/// Interaktionslogik für AnalogValue.xaml
/// </summary>
public partial class MediaContainer : UserControl
{
public bool IsReadonly { get; set; }
public MediaContainer()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
private void NumberValidation(object sender, TextCompositionEventArgs e)
{
Regex regex = new("^[-+]?[0-9]*,?[0-9]+$");
e.Handled = regex.IsMatch(e.Text);
}
}
}

View File

@@ -0,0 +1,76 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel.DataAnnotations;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
using HMIToolkit;
namespace Common;
public sealed partial class MediaContainerVm : ObservableValidator, IDisposable
{
private IAdsManager? _adsManager;
private string? _variableName;
[ObservableProperty] private string? sName = "No Name";
[ObservableProperty] private bool empty = false;
[ObservableProperty] private bool full = false;
[ObservableProperty] private bool overload = false;
[ObservableProperty] private HMIControlButtonVM? emptyButton;
[ObservableProperty] private HMIControlButtonVM? fillButton;
public MediaContainerVm()
{
sName = "No Name";
EmptyButton = new HMIControlButtonVM();
FillButton = new HMIControlButtonVM();
}
public MediaContainerVm(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
sName = "No Name";
EmptyButton = new HMIControlButtonVM(_adsManager, _variableName + ".stEmptyButton");
FillButton = new HMIControlButtonVM(_adsManager, _variableName + ".stFillButton");
_adsManager.Register(_variableName + ".xEmpty", EmptyChanged);
_adsManager.Register(_variableName + ".xFull", FullChanged);
_adsManager.Register(_variableName + ".xOverload", OverloadChanged);
}
private void EmptyChanged(object? sender, ValueChangedEventArgs e)
{
Empty = (bool)e.Value;
}
private void FullChanged(object? sender, ValueChangedEventArgs e)
{
Full = (bool)e.Value;
}
private void OverloadChanged(object? sender, ValueChangedEventArgs e)
{
Overload = (bool)e.Value;
}
public void Dispose()
{
EmptyButton?.Dispose();
EmptyButton = null;
FillButton?.Dispose();
FillButton = null;
_adsManager?.Deregister(_variableName + ".xEmpty", EmptyChanged);
_adsManager?.Deregister(_variableName + ".xFull", FullChanged);
_adsManager?.Deregister(_variableName + ".xOverload", OverloadChanged);
}
}

View File

@@ -0,0 +1,33 @@
<UserControl x:Class="Common.ParamControlFloat"
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:Common"
d:DataContext="{d:DesignInstance Type=local:ParamControlFloatVm, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Width="Auto"
Height="Auto">
<!-- :DataContext="{d:DesignInstance Type=local:AnalogValueVM, IsDesignTimeCreatable=True}" -->
<!-- Style to see things in the designer-->
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!-- Property="Background" Value="White" /> -->
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="280" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid Height="Auto">
<Grid.ColumnDefinitions>
<!-- <ColumnDefinition Width="Auto" /> -->
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- <Label Grid.Column="0" Content="{Binding SName}" VerticalAlignment="Center" HorizontalAlignment="Left"/> -->
<Label x:Name="tbName" Grid.Column="0" Content="{Binding SName, Mode=OneWay }" Width="200"/>
<TextBox x:Name="tbValue" Text="{Binding Value, Mode=TwoWay, StringFormat=N2}" Grid.Column="1" MaxLines="1" Width="80" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="{Binding Readonly}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,32 @@
using System.Text.RegularExpressions;
using System.Windows.Controls;
using System.Windows.Input;
namespace Common
{
/// <summary>
/// Interaktionslogik für AnalogValue.xaml
/// </summary>
public partial class ParamControlFloat : UserControl
{
public bool IsReadonly { get; set; }
public ParamControlFloat()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
private void NumberValidation(object sender, TextCompositionEventArgs e)
{
Regex regex = new("^[-+]?[0-9]*,?[0-9]+$");
e.Handled = regex.IsMatch(e.Text);
}
}
}

View File

@@ -0,0 +1,27 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel.DataAnnotations;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace Common;
public sealed partial class ParamControlFloatVm : ObservableValidator, IDisposable
{
[ObservableProperty]
private string sName;
[ObservableProperty]
private float value;
public ParamControlFloatVm()
{
SName = "No Name:";
Value = 0.0f;
}
public void Dispose()
{
}
}

View File

@@ -0,0 +1,33 @@
<UserControl x:Class="Common.ParamControlInt"
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:common="clr-namespace:Common"
d:DataContext="{d:DesignInstance Type=common:ParamControlIntVm, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Width="Auto"
Height="Auto">
<!-- :DataContext="{d:DesignInstance Type=local:AnalogValueVM, IsDesignTimeCreatable=True}" -->
<!-- Style to see things in the designer-->
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!-- Property="Background" Value="White" /> -->
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="280" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid Height="Auto">
<Grid.ColumnDefinitions>
<!-- <ColumnDefinition Width="Auto" /> -->
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- <Label Grid.Column="0" Content="{Binding SName}" VerticalAlignment="Center" HorizontalAlignment="Left"/> -->
<Label x:Name="tbName" Grid.Column="0" Content="{Binding SName, Mode=OneWay }" Width="200"/>
<TextBox x:Name="tbValue" Text="{Binding Value, Mode=TwoWay}" Grid.Column="1" MaxLines="1" Width="80" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsReadOnly="{Binding Readonly}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,32 @@
using System.Text.RegularExpressions;
using System.Windows.Controls;
using System.Windows.Input;
namespace Common
{
/// <summary>
/// Interaktionslogik für AnalogValue.xaml
/// </summary>
public partial class ParamControlInt : UserControl
{
public bool IsReadonly { get; set; }
public ParamControlInt()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
private void NumberValidation(object sender, TextCompositionEventArgs e)
{
Regex regex = new("^[-+]?[0-9]*,?[0-9]+$");
e.Handled = regex.IsMatch(e.Text);
}
}
}

View File

@@ -0,0 +1,28 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel.DataAnnotations;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace Common;
public sealed partial class ParamControlIntVm : ObservableValidator, IDisposable
{
[ObservableProperty]
private string sName;
[ObservableProperty]
private int value;
public ParamControlIntVm()
{
SName = "No Name:";
Value = 0;
}
public void Dispose()
{
}
}

View File

@@ -0,0 +1,33 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace InfineonHMI
{
public class DateTimeToEventTimeConverter : IValueConverter
{
// 599264352000000000 ticks is a date used by beckhoff for events that didnt happen up to this point
public const long NoTime = 599264352000000000;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DateTime dt)
{
if (dt.Ticks == NoTime)
return "";
else
{
CultureInfo cultureInfo = CultureInfo.CurrentCulture;
return dt.ToString("G", cultureInfo);
}
}
else
throw new InvalidOperationException("Target must be of type DateTime");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
}

View File

@@ -0,0 +1,12 @@
<Window x:Class="HMIToolkit.AnalogMotorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HMIToolkit"
mc:Ignorable="d"
Title="AnalogMotorWindow" SizeToContent="WidthAndHeight">
<Grid>
<local:AnalogMotorControl />
</Grid>
</Window>

View File

@@ -0,0 +1,14 @@
using System.Windows;
namespace HMIToolkit;
/// <summary>
/// Interaktionslogik für AnalogMotorWindow.xaml
/// </summary>
public partial class AnalogMotorWindow : Window
{
public AnalogMotorWindow()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,12 @@
<Window xmlns:HMIToolkit="clr-namespace:HMIToolkit" x:Class="InfineonHMI.BinaryValveWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HMIToolkit"
mc:Ignorable="d"
Title="BinaryValveWindow" SizeToContent="WidthAndHeight" ResizeMode="NoResize">
<Grid>
<HMIToolkit:BinaryValveControl />
</Grid>
</Window>

View File

@@ -0,0 +1,15 @@
using System.Windows;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für BinaryValveWindow.xaml
/// </summary>
public partial class BinaryValveWindow : Window
{
public BinaryValveWindow()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,46 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace HMIToolkit;
class FeedbackToColorConverter : IValueConverter
{
public Object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (targetType != typeof(System.Windows.Media.Brush))
throw new InvalidOperationException("The target must be a brush");
#pragma warning disable CS8604 // Mögliches Nullverweisargument.
int num = int.Parse(value.ToString());
#pragma warning restore CS8604 // Mögliches Nullverweisargument.
switch (num)
{
case 0:
return DependencyProperty.UnsetValue;
case 1:
return System.Windows.Media.Brushes.Green;
case 2:
return System.Windows.Media.Brushes.GreenYellow;
case 3:
return System.Windows.Media.Brushes.DarkOrange;
case 4:
return System.Windows.Media.Brushes.DarkRed;
default:
return DependencyProperty.UnsetValue;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}

View File

@@ -0,0 +1,91 @@
<UserControl x:Class="HMIToolkit.AnalogMotorControl"
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:HMIToolkit"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:AnalogMotorControlVM, IsDesignTimeCreatable=True}"
Width="Auto"
Height="Auto">
<UserControl.Resources>
<local:FeedbackToColorConverter x:Key="feedbackConverter" />
</UserControl.Resources>
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!-- Property="Background" Value="White" /> -->
<Setter Property="Height" Value="Auto" />
<Setter Property="Width" Value="Auto" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid>
<Grid Margin="5" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Row 0 -->
<Label Grid.Row="0" Content="{Binding SName}" HorizontalAlignment="Center" FontSize="24" FontWeight="Bold"/>
<!-- Row 1 -->
<Label Grid.Row="1" Content="Interlocks:" Margin="0,0,0,-3"/>
<!-- Row 2 -->
<Grid Grid.Row="2">
<local:IntlkButtonControl DataContext="{Binding Interlocks}"/>
</Grid>
<!-- Row 3 -->
<Label Grid.Row="3" Content="Setpoint:" Margin="0,0,0,-3"/>
<!-- Row 4 -->
<local:AnalogValue DataContext="{Binding Setpoint}" Grid.Row="4"/>
<!-- Row 5 -->
<Label Grid.Row="5" Content="Process value:" Margin="0,0,0,-3"/>
<!-- Row 6 -->
<local:AnalogValue DataContext="{Binding ProcessValue}" Grid.Row="6"/>
<!-- Row 7 -->
<Grid Grid.Row="7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="Control:" Margin="0,0,0,-3" />
<Button x:Name="btnOpen" DataContext="{Binding StartButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Background="{Binding IFeedback, Converter={StaticResource feedbackConverter}}" Grid.Row="1" Grid.Column="0" Content="Start" Height="80" Width="80" Margin="0,0,5,5" />
<Button x:Name="btnClose" DataContext="{Binding StopButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Background="{Binding IFeedback, Converter={StaticResource feedbackConverter}}" Grid.Row="1" Grid.Column="1" Content="Stop" Height="80" Width="80" Margin="0,-5,0,0"/>
</Grid>
<!-- Row 8 -->
<Grid Grid.Row="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="Mode:" Margin="0,0,0,-3" />
<Button x:Name="btnAuto" DataContext="{Binding AutomaticButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="0" Content="Auto" Height="80" Width="80" Margin="0,0,5,0"/>
<Button x:Name="btnManual" DataContext="{Binding ManualButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="1" Content="Man" Height="80" Width="80" Margin="0,-5,0,-5"/>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,23 @@
using System.Windows.Controls;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für AnalogMotorControl.xaml
/// </summary>
public partial class AnalogMotorControl : UserControl
{
public AnalogMotorControl()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,83 @@
using CommunityToolkit.Mvvm.ComponentModel;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace HMIToolkit
{
public sealed partial class AnalogMotorControlVM : ObservableObject
{
[ObservableProperty]
private string sName = "No Name";
public HMIControlButtonVM? AutomaticButton { get; private set; }
public HMIControlButtonVM? ManualButton { get; private set; }
public HMIControlButtonVM StartButton { get; private set; }
public HMIControlButtonVM StopButton { get; private set; }
public IntlkControlVM? Interlocks { get; private set; }
public AnalogValueVM? Setpoint { get; private set; }
public AnalogValueVM? ProcessValue { get; private set; }
private readonly string? _variableName;
private IAdsManager? _adsManager;
public AnalogMotorControlVM()
{
AutomaticButton = new HMIControlButtonVM();
ManualButton = new HMIControlButtonVM();
StartButton = new HMIControlButtonVM();
StopButton = new HMIControlButtonVM();
Interlocks = new IntlkControlVM();
Setpoint = new AnalogValueVM();
ProcessValue = new AnalogValueVM();
}
public AnalogMotorControlVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
AutomaticButton = new HMIControlButtonVM(_adsManager, _variableName + ".stAutomaticButton");
ManualButton = new HMIControlButtonVM(_adsManager, _variableName + ".stManualButton");
StartButton = new HMIControlButtonVM(_adsManager, _variableName + ".stStartButton");
StopButton = new HMIControlButtonVM(_adsManager, _variableName + ".stStopButton");
Interlocks = new IntlkControlVM(_adsManager, _variableName + ".stInterlock");
Setpoint = new AnalogValueVM(_adsManager, _variableName + ".stSetpoint", false);
ProcessValue = new AnalogValueVM(_adsManager, _variableName + ".stProcessValue", true);
_adsManager.Register(_variableName + ".sName", NameChanged);
}
public void Dispose()
{
_adsManager?.Deregister(_variableName + ".sName", NameChanged);
_adsManager = null;
AutomaticButton?.Dispose();
AutomaticButton = null;
ManualButton?.Dispose();
ManualButton = null;
StartButton?.Dispose();
StartButton = null;
StopButton?.Dispose();
StopButton = null;
Interlocks?.Dispose();
Interlocks = null;
Setpoint?.Dispose();
Setpoint = null;
ProcessValue?.Dispose();
ProcessValue = null;
}
private void NameChanged(object? sender, ValueChangedEventArgs e)
{
SName = (string)e.Value;
}
}
}

View File

@@ -0,0 +1,33 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.Globalization;
using System.Windows.Controls;
namespace HMIToolkit
{
public sealed partial class AnalogRangeValidator : ValidationRule
{
public float Min { get; set; }
public float Max { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
float analogValue = 0;
try
{
if (((string)value).Length > 0)
analogValue = float.Parse((string)value);
}
catch (Exception e)
{
return new ValidationResult(false, $"Illegal characters or {e.Message}");
}
if ((analogValue < Min) || (analogValue > Max))
return new ValidationResult(false, $"Please enter a value in the range: {Min}-{Max}.");
return ValidationResult.ValidResult;
}
}
}

View File

@@ -0,0 +1,33 @@
<UserControl x:Class="HMIToolkit.AnalogValue"
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:HMIToolkit"
d:DataContext="{d:DesignInstance Type=local:AnalogValueVM, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Width="Auto"
Height="Auto">
<!-- :DataContext="{d:DesignInstance Type=local:AnalogValueVM, IsDesignTimeCreatable=True}" -->
<!-- Style to see things in the designer-->
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!-- Property="Background" Value="White" /> -->
<Setter Property="Height" Value="Auto" />
<Setter Property="Width" Value="200" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid Height="Auto">
<Grid.ColumnDefinitions>
<!-- <ColumnDefinition Width="Auto" /> -->
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- <Label Grid.Column="0" Content="{Binding SName}" VerticalAlignment="Center" HorizontalAlignment="Left"/> -->
<TextBox x:Name="tbValue" Text="{Binding RValue, Mode=TwoWay, StringFormat=N2}" Grid.Column="0" MaxLines="1" FontSize="40" Width="150" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" IsReadOnly="{Binding Readonly}" />
<Label Grid.Column="1" Content="{Binding SUnit}" VerticalAlignment="Center" FontSize="35" HorizontalAlignment="Left"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,32 @@
using System.Text.RegularExpressions;
using System.Windows.Controls;
using System.Windows.Input;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für AnalogValue.xaml
/// </summary>
public partial class AnalogValue : UserControl
{
public bool IsReadonly { get; set; }
public AnalogValue()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
private void NumberValidation(object sender, TextCompositionEventArgs e)
{
Regex regex = new("^[-+]?[0-9]*,?[0-9]+$");
e.Handled = regex.IsMatch(e.Text);
}
}
}

View File

@@ -0,0 +1,144 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel.DataAnnotations;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace HMIToolkit;
public sealed class InRangeAttribute(string propMin, string propMax) : ValidationAttribute
{
public string PropMin { get; } = propMin;
public string PropMax { get; } = propMax;
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
object instance = validationContext.ObjectInstance;
float minValue = (float)(instance.GetType().GetProperty(PropMin)?.GetValue(instance) ?? 0.0f);
float maxValue = (float)(instance.GetType().GetProperty(PropMax)?.GetValue(instance) ?? 0.0f);
float tempValue = (float)(value ?? 0.0f);
if (tempValue <= maxValue && tempValue >= minValue)
return ValidationResult.Success;
return new($"Value has to be greater than {minValue} and smaller then {maxValue}");
}
}
public sealed partial class AnalogValueVM : ObservableValidator, IDisposable
{
[ObservableProperty]
private string sName;
// 1 = Ok; 2 = Error
[ObservableProperty]
private short iStatus;
private float rValue;
[InRangeAttribute(nameof(RMin), nameof(RMax))]
public float RValue
{
get => rValue;
set
{
SetProperty(ref rValue, value, true);
if (value >= RMin && value <= RMax)
{
if (!Readonly)
WriteValue(value);
}
}
}
private void WriteValue(float value)
{
_adsManager?.WriteValue(_variableName + ".rValue", value);
}
[ObservableProperty]
private string sUnit;
[ObservableProperty]
private float rMin;
[ObservableProperty]
private float rMax;
public bool Readonly { get; private set; }
private IAdsManager? _adsManager;
private readonly string? _variableName;
public AnalogValueVM()
{
sName = "No Name:";
iStatus = 2;
rValue = 0.0f;
sUnit = "";
Readonly = true;
rMin = 0.0f;
rMax = 100.0f;
}
public AnalogValueVM(IAdsManager adsManager, string variableName, bool isReadonly) : this()
{
_adsManager = adsManager;
_variableName = variableName;
Readonly = isReadonly;
_adsManager.Register(_variableName + ".sName", NameChanged);
_adsManager.Register(_variableName + ".iStatus", StatusChanged);
//if (isReadonly)
_adsManager.Register(_variableName + ".rValue", ValueChanged);
_adsManager.Register(_variableName + ".sUnit", UnitChanged);
_adsManager.Register(_variableName + ".rMin", MinChanged);
_adsManager.Register(_variableName + ".rMax", MaxChanged);
}
public void Dispose()
{
_adsManager?.Deregister(_variableName + ".sName", NameChanged);
_adsManager?.Deregister(_variableName + ".iStatus", StatusChanged);
_adsManager?.Deregister(_variableName + ".rValue", ValueChanged);
_adsManager?.Deregister(_variableName + ".sUnit", UnitChanged);
_adsManager?.Deregister(_variableName + ".rMin", MinChanged);
_adsManager?.Deregister(_variableName + ".rMax", MaxChanged);
_adsManager = null;
}
private void NameChanged(object? sender, ValueChangedEventArgs e)
{
string temp = (string)e.Value;
if (temp != String.Empty)
SName = temp + ":";
else
SName = "";
}
private void StatusChanged(object? sender, ValueChangedEventArgs e)
{
IStatus = (short)e.Value;
}
private void ValueChanged(object? sender, ValueChangedEventArgs e)
{
RValue = (float)e.Value;
}
private void UnitChanged(object? sender, ValueChangedEventArgs e)
{
SUnit = (string)e.Value;
}
private void MinChanged(object? sender, ValueChangedEventArgs e)
{
RMin = (float)e.Value;
}
private void MaxChanged(object? sender, ValueChangedEventArgs e)
{
RMax = (float)e.Value;
}
}

View File

@@ -0,0 +1,87 @@
<UserControl xmlns:AnalogValue="clr-namespace:HMIToolkit" x:Class="HMIToolkit.AnalogValveControl"
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:HMIToolkit"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:AnalogValveControlVM, IsDesignTimeCreatable=True}"
Width="Auto"
Height="Auto">
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!-- Property="Background" Value="White" /> -->
<Setter Property="Height" Value="Auto" />
<Setter Property="Width" Value="Auto" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid>
<Grid Margin="5" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Row 0 -->
<Label Grid.Row="0" Content="{Binding SName}" HorizontalAlignment="Center" FontSize="24" FontWeight="Bold"/>
<!-- Row 1 -->
<Label Grid.Row="1" Content="Interlocks:" Margin="0,0,0,-3"/>
<!-- Row 2 -->
<Grid Grid.Row="2">
<local:IntlkButtonControl DataContext="{Binding Interlocks}"/>
</Grid>
<!-- Row 3 -->
<Label Grid.Row="3" Content="Setpoint:" Margin="0,0,0,-3"/>
<!-- Row 4 -->
<AnalogValue:AnalogValue DataContext="{Binding Setpoint}" Grid.Row="4"/>
<!-- Row 5 -->
<Label Grid.Row="5" Content="Process value:" Margin="0,0,0,-3"/>
<!-- Row 6 -->
<AnalogValue:AnalogValue DataContext="{Binding ProcessValue}" Grid.Row="6"/>
<!-- Row 7 -->
<Grid Grid.Row="7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="Control:" Margin="0,0,0,-3" />
<Button x:Name="btnOpen" DataContext="{Binding OpenButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="0" Content="Open" Height="80" Width="80" Margin="0,0,5,5" />
<Button x:Name="btnClose" DataContext="{Binding CloseButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="1" Content="Close" Height="80" Width="80" Margin="0,-5,0,0"/>
</Grid>
<!-- Row 8 -->
<Grid Grid.Row="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="Mode:" Margin="0,0,0,-3" />
<Button x:Name="btnAuto" DataContext="{Binding AutomaticButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="0" Content="Auto" Height="80" Width="80" Margin="0,0,5,0"/>
<Button x:Name="btnManual" DataContext="{Binding ManualButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="1" Content="Man" Height="80" Width="80" Margin="0,-5,0,-5"/>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,35 @@
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;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für AnalogValveControl.xaml
/// </summary>
public partial class AnalogValveControl : UserControl
{
public AnalogValveControl()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,83 @@
using CommunityToolkit.Mvvm.ComponentModel;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace HMIToolkit
{
public sealed partial class AnalogValveControlVM : ObservableObject
{
[ObservableProperty]
private string sName = "No Name";
public HMIControlButtonVM? AutomaticButton { get; private set; }
public HMIControlButtonVM? ManualButton { get; private set; }
public HMIControlButtonVM? OpenButton { get; private set; }
public HMIControlButtonVM? CloseButton { get; private set; }
public IntlkControlVM? Interlocks { get; private set; }
public AnalogValueVM? Setpoint { get; private set; }
public AnalogValueVM? ProcessValue { get; private set; }
private readonly string? _variableName;
private IAdsManager? _adsManager;
public AnalogValveControlVM()
{
AutomaticButton = new HMIControlButtonVM();
ManualButton = new HMIControlButtonVM();
OpenButton = new HMIControlButtonVM();
CloseButton = new HMIControlButtonVM();
Interlocks = new IntlkControlVM();
Setpoint = new AnalogValueVM();
ProcessValue = new AnalogValueVM();
}
public AnalogValveControlVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
AutomaticButton = new HMIControlButtonVM(_adsManager, _variableName + ".stAutomaticButton");
ManualButton = new HMIControlButtonVM(_adsManager, _variableName + ".stManualButton");
OpenButton = new HMIControlButtonVM(_adsManager, _variableName + ".stOpenButton");
CloseButton = new HMIControlButtonVM(_adsManager, _variableName + ".stCloseButton");
Interlocks = new IntlkControlVM(_adsManager, _variableName + ".stInterlock");
Setpoint = new AnalogValueVM(_adsManager, _variableName + ".stSetpoint", false);
ProcessValue = new AnalogValueVM(_adsManager, _variableName + ".stProcessValue", true);
_adsManager.Register(_variableName + ".sName", NameChanged);
}
public void Dispose()
{
_adsManager?.Deregister(_variableName + ".sName", NameChanged);
_adsManager = null;
AutomaticButton?.Dispose();
AutomaticButton = null;
ManualButton?.Dispose();
ManualButton = null;
OpenButton?.Dispose();
OpenButton = null;
CloseButton?.Dispose();
CloseButton = null;
Interlocks?.Dispose();
Interlocks = null;
Setpoint?.Dispose();
Setpoint = null;
ProcessValue?.Dispose();
ProcessValue = null;
}
private void NameChanged(object? sender, ValueChangedEventArgs e)
{
SName = (string)e.Value;
}
}
}

View File

@@ -0,0 +1,76 @@
<UserControl x:Class="HMIToolkit.BinaryValveControl"
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:HMIToolkit"
d:DataContext="{d:DesignInstance Type=local:BinaryValveControlVM, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Height="Auto"
Width="Auto">
<UserControl.Resources>
<local:FeedbackToColorConverter x:Key="feedbackConverter" />
</UserControl.Resources>
<!-- Style to see things in the designer-->
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<!--Property="Background" Value="White" />-->
<Setter Property="Height" Value="Auto" />
<Setter Property="Width" Value="Auto" />
</Style>
</d:DesignerProperties.DesignStyle>
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="55" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Row 0 -->
<Label Grid.Row="0" Content="{Binding SName}" HorizontalAlignment="Center" FontSize="35" FontWeight="Bold"/>
<!-- Row 1 -->
<Label Grid.Row="1" Content="Interlocks:" FontSize="30"/>
<!-- Row 2 -->
<Grid Grid.Row="2">
<local:IntlkButtonControl DataContext="{Binding Interlocks}"/>
</Grid>
<!-- Row 3 -->
<Grid Grid.Row="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="30" Content="Control:"/>
<Button x:Name="btnOpen" DataContext="{Binding OpenButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Background="{Binding IFeedback, Converter={StaticResource feedbackConverter}}" Grid.Row="1" Grid.Column="0" Content="Open" FontSize="40" Height="100" Width="180" Margin="0,0,5,5" />
<Button x:Name="btnClose" DataContext="{Binding CloseButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Background="{Binding IFeedback, Converter={StaticResource feedbackConverter}}" Grid.Row="1" Grid.Column="1" Content="Close" FontSize="40" Height="100" Width="180" Margin="0,-5,0,0"/>
</Grid>
<!-- Row 4 -->
<Grid Grid.Row="4">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="30" Content="Mode:" />
<Button x:Name="btnAuto" DataContext="{Binding AutomaticButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="0" Content="Auto" FontSize="35" Height="100" Width="180" Margin="0,0,5,0"/>
<Button x:Name="btnManual" DataContext="{Binding ManualButton}" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding XRelease}" Grid.Row="1" Grid.Column="1" Content="Man" FontSize="35" Height="100" Width="180" Margin="0,-5,0,-5"/>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,35 @@
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;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für BinaryValveControl.xaml
/// </summary>
public partial class BinaryValveControl : UserControl
{
public BinaryValveControl()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,70 @@
using CommunityToolkit.Mvvm.ComponentModel;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
// {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.OpenButton}
namespace HMIToolkit
{
public sealed partial class BinaryValveControlVM : ObservableObject, IDisposable
{
[ObservableProperty]
private string sName = "No Name";
public HMIControlButtonVM? AutomaticButton { get; private set; }
public HMIControlButtonVM? ManualButton { get; private set; }
public HMIControlButtonVM OpenButton { get; private set; }
public HMIControlButtonVM CloseButton { get; private set; }
public IntlkControlVM? Interlocks { get; private set; }
private readonly string? _variableName;
private IAdsManager? _adsManager;
public BinaryValveControlVM()
{
AutomaticButton = new HMIControlButtonVM();
ManualButton = new HMIControlButtonVM();
OpenButton = new HMIControlButtonVM();
CloseButton = new HMIControlButtonVM();
Interlocks = new IntlkControlVM();
}
public BinaryValveControlVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
AutomaticButton = new HMIControlButtonVM(_adsManager, _variableName + ".stAutomaticButton");
ManualButton = new HMIControlButtonVM(_adsManager, _variableName + ".stManualButton");
OpenButton = new HMIControlButtonVM(_adsManager, _variableName + ".stOpenButton");
CloseButton = new HMIControlButtonVM(_adsManager, _variableName + ".stCloseButton");
Interlocks = new IntlkControlVM(_adsManager, _variableName + ".stInterlock");
_adsManager.Register(_variableName + ".sName", NameChanged);
}
public void Dispose()
{
_adsManager?.Deregister(_variableName + ".sName", NameChanged);
_adsManager = null;
AutomaticButton?.Dispose();
AutomaticButton = null;
ManualButton?.Dispose();
ManualButton = null;
OpenButton?.Dispose();
CloseButton?.Dispose();
Interlocks?.Dispose();
Interlocks = null;
}
private void NameChanged(object? sender, ValueChangedEventArgs e)
{
SName = (string)e.Value;
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace HMIToolkit
{
public class BoolToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(Brush))
throw new InvalidOperationException("The target must be a brush");
bool temp = bool.Parse(value.ToString()!);
return (temp ? Brushes.DarkGreen : Brushes.DarkRed);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
}

View File

@@ -0,0 +1,74 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace HMIToolkit
{
public sealed partial class HMIControlButtonVM : ObservableObject, IDisposable
{
private IAdsManager? _adsManager;
private readonly string _variableName;
// Action triggered when the button is about to be clicked
public event EventHandler? ButtonClickedStarted;
// Action triggered when the button is done being clicked
public event EventHandler? ButtonClickedEnded;
// Event when button feedback changed
public event EventHandler? FeedbackChanged;
// Event when release changed
public event EventHandler? ReleaseChanged;
[ObservableProperty]
private bool xRelease;
// 0 = none, 1 = active, 2 = pending, 3 = waring, 4 = error
[ObservableProperty]
private short iFeedback;
public HMIControlButtonVM()
{
_variableName = string.Empty;
XRelease = false;
IFeedback = 4;
}
public HMIControlButtonVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
_adsManager.Register(_variableName + ".xRelease", XReleaseCahnged);
_adsManager.Register(_variableName + ".iFeedback", IFeedbackChanged);
}
public void Dispose()
{
_adsManager?.Deregister(_variableName + ".xRelease", XReleaseCahnged);
_adsManager?.Deregister(_variableName + ".iFeedback", IFeedbackChanged);
}
[RelayCommand]
private void ButtonClicked()
{
ButtonClickedStarted?.Invoke(this, EventArgs.Empty);
_adsManager?.WriteValue(_variableName + ".xRequest", true);
ButtonClickedEnded?.Invoke(this, EventArgs.Empty);
}
private void XReleaseCahnged(object? sender, ValueChangedEventArgs e)
{
XRelease = (bool)e.Value;
ReleaseChanged?.Invoke(this, EventArgs.Empty);
}
private void IFeedbackChanged(object? sender, ValueChangedEventArgs e)
{
IFeedback = (short)e.Value;
FeedbackChanged?.Invoke(this, EventArgs.Empty);
}
}
}

View File

@@ -0,0 +1,33 @@
<UserControl x:Class="HMIToolkit.IntlkButtonControl"
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:HMIToolkit"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:IntlkControlVM, IsDesignTimeCreatable=True}"
d:DesignHeight="35" d:DesignWidth="175">
<UserControl.Resources>
<local:BoolToBrushConverter x:Key="myBoolConverter" />
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" FontSize="35" Height="80" Width="180" Padding="0" Command="{Binding ShowProcessIntlksCommand}">
<StackPanel Orientation="Horizontal">
<Label>Process</Label>
<Rectangle Width="10" Height="10" Fill="{Binding Path=XProcessIntlkOk, Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
</StackPanel>
</Button>
<Button Grid.Column="1" Padding="0" FontSize="35" Height="80" Width="180" Margin="5,0,0,0" Command="{Binding ShowSafetyIntlksCommand}">
<StackPanel Orientation="Horizontal">
<Label>Safety</Label>
<Rectangle Width="10" Height="10" Fill="{Binding Path=XSafetyIntlkOk, Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
</StackPanel>
</Button>
</Grid>
</UserControl>

View File

@@ -0,0 +1,35 @@
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;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für ProcessIntlkButtonControl.xaml
/// </summary>
public partial class IntlkButtonControl : UserControl
{
public IntlkButtonControl()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,109 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace HMIToolkit;
public sealed partial class IntlkControlVM : ObservableObject, IDisposable
{
[ObservableProperty]
private bool xProcessIntlkOk;
[ObservableProperty]
private bool xSafetyIntlkOk;
[ObservableProperty]
private IntlkDetailsVM safetyInterlocksVM;
[ObservableProperty]
private IntlkDetailsVM processInterlocksVM;
private IntlkDetailsWindow? processIntlksDetailsWindow;
private IntlkDetailsWindow? safetyIntlksDetailsWindow;
private readonly string _variableName;
private IAdsManager? _adsManager;
public IntlkControlVM()
{
XProcessIntlkOk = false;
XSafetyIntlkOk = false;
_variableName = string.Empty;
safetyInterlocksVM = new();
processInterlocksVM = new();
}
public IntlkControlVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
SafetyInterlocksVM = new IntlkDetailsVM(_adsManager, _variableName + ".wSafetyINTLKStatus", _variableName + ".asSafetyINTLKName", "Safety Interlock");
ProcessInterlocksVM = new IntlkDetailsVM(_adsManager, _variableName + ".wProcessINTLKStatus", _variableName + ".asProcessINTLKName", "Process Interlock");
_adsManager.Register(_variableName + ".xProcessINTLKOk", ProcessIntlkOkChanged);
_adsManager.Register(_variableName + ".xSafetyINTLKOk", SafetyIntlkOkChanged);
}
public void Dispose()
{
SafetyInterlocksVM.Dispose();
ProcessInterlocksVM.Dispose();
_adsManager?.Deregister(_variableName + ".xProcessINTLKOk", ProcessIntlkOkChanged);
_adsManager?.Deregister(_variableName + ".xSafetyINTLKOk", SafetyIntlkOkChanged);
processIntlksDetailsWindow?.Close();
safetyIntlksDetailsWindow?.Close();
_adsManager = null;
}
private void ProcessIntlkOkChanged(object? sender, ValueChangedEventArgs e)
{
XProcessIntlkOk = (bool)e.Value;
}
private void SafetyIntlkOkChanged(object? sender, ValueChangedEventArgs e)
{
XSafetyIntlkOk = (bool)e.Value;
}
[RelayCommand]
private void ShowProcessIntlks()
{
if (_adsManager != null && processIntlksDetailsWindow == null)
{
processIntlksDetailsWindow = new() { DataContext = ProcessInterlocksVM };
processIntlksDetailsWindow.Closed += ProcessIntlksDetailsWindow_Closed;
processIntlksDetailsWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
processIntlksDetailsWindow.Show();
}
}
private void ProcessIntlksDetailsWindow_Closed(object? sender, EventArgs e)
{
processIntlksDetailsWindow!.Close();
processIntlksDetailsWindow = null;
}
[RelayCommand]
private void ShowSafetyIntlks()
{
if (_adsManager != null && safetyIntlksDetailsWindow == null)
{
safetyIntlksDetailsWindow = new() { DataContext = SafetyInterlocksVM };
safetyIntlksDetailsWindow.Closed += SafetyIntlksDetailsWindow_Closed;
safetyIntlksDetailsWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
safetyIntlksDetailsWindow.Show();
}
}
private void SafetyIntlksDetailsWindow_Closed(object? sender, EventArgs e)
{
safetyIntlksDetailsWindow!.Close();
safetyIntlksDetailsWindow = null;
}
}

View File

@@ -0,0 +1,132 @@
<UserControl x:Class="HMIToolkit.IntlkDetails"
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:HMIToolkit"
d:DataContext="{d:DesignInstance Type=local:IntlkDetailsVM, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
MinWidth="500" MinHeight="300"
d:DesignHeight="300" d:DesignWidth="500"
>
<UserControl.Resources>
<local:BoolToBrushConverter x:Key="myBoolConverter" />
</UserControl.Resources>
<Grid Margin="5" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Row 0 -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{Binding InterlockName}" />
<!-- Row 1 -->
<!-- <ListBox Grid.Column="0" Grid.Row="1" ItemsSource="{Binding ListBoxItemsLeft}"/> -->
<!-- <ListBox Grid.Column="1" Grid.Row="1" ItemsSource="{Binding ListBoxItemsRight}" /> -->
<Grid Grid.Column="0" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Row 0 -->
<Rectangle Grid.Row="0" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[0], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="0" Grid.Column="1" Content="{Binding InterlockNames[0]}" />
<!-- Row 1 -->
<Rectangle Grid.Row="1" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[1], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="1" Grid.Column="1" Content="{Binding InterlockNames[1]}" />
<!-- Row 2 -->
<Rectangle Grid.Row="2" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[2], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding InterlockNames[2]}" />
<!-- Row 3 -->
<Rectangle Grid.Row="3" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[3], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="3" Grid.Column="1" Content="{Binding InterlockNames[3]}" />
<!-- Row 4 -->
<Rectangle Grid.Row="4" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[4], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="4" Grid.Column="1" Content="{Binding InterlockNames[4]}" />
<!-- Row 5 -->
<Rectangle Grid.Row="5" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[5], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="5" Grid.Column="1" Content="{Binding InterlockNames[5]}" />
<!-- Row 6 -->
<Rectangle Grid.Row="6" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[6], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="6" Grid.Column="1" Content="{Binding InterlockNames[6]}" />
<!-- Row 7 -->
<Rectangle Grid.Row="7" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[7], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="7" Grid.Column="1" Content="{Binding InterlockNames[7]}" />
</Grid>
<Grid Grid.Column="1" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Row 0 -->
<Rectangle Grid.Row="0" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[8], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="0" Grid.Column="1" Content="{Binding InterlockNames[8]}" />
<!-- Row 1 -->
<Rectangle Grid.Row="1" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[9], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="1" Grid.Column="1" Content="{Binding InterlockNames[9]}" />
<!-- Row 2 -->
<Rectangle Grid.Row="2" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[10], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="2" Grid.Column="1" Content="{Binding InterlockNames[10]}" />
<!-- Row 3 -->
<Rectangle Grid.Row="3" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[11], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="3" Grid.Column="1" Content="{Binding InterlockNames[11]}" />
<!-- Row 4 -->
<Rectangle Grid.Row="4" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[12], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="4" Grid.Column="1" Content="{Binding InterlockNames[12]}" />
<!-- Row 5 -->
<Rectangle Grid.Row="5" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[13], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="5" Grid.Column="1" Content="{Binding InterlockNames[13]}" />
<!-- Row 6 -->
<Rectangle Grid.Row="6" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[14], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="6" Grid.Column="1" Content="{Binding InterlockNames[14]}" />
<!-- Row 7 -->
<Rectangle Grid.Row="7" Grid.Column="0" Width="10" Height="10" Fill="{Binding Path=InterlockStatus[15], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
<Label Grid.Row="7" Grid.Column="1" Content="{Binding InterlockNames[15]}" />
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,35 @@
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;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für IntlkDetails.xaml
/// </summary>
public partial class IntlkDetails : UserControl
{
public IntlkDetails()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,151 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace HMIToolkit
{
public sealed partial class IntlkDetailsVM : ObservableObject, IDisposable
{
[ObservableProperty]
private string interlockName;
[ObservableProperty]
private BitArray interlockStatus;
[ObservableProperty]
private string[] interlockNames;
[ObservableProperty]
private ListBoxItem[] listBoxItemsLeft;
[ObservableProperty]
private ListBoxItem[] listBoxItemsRight;
[ObservableProperty]
private Visibility isVisible;
private readonly BoolToBrushConverter boolToBrushConverter = new();
private readonly int numIntlksLeftSide;
private readonly int numIntlksRightSide;
private readonly string _variableNameStatus;
private readonly string _variableNameNames;
private IAdsManager? _adsManager;
public IntlkDetailsVM()
{
interlockName = "Interlocks";
interlockStatus = new BitArray(HMIConstants.NumInterlocks);
interlockNames = new string[HMIConstants.NumInterlocks];
Array.Fill(interlockNames, "Not used");
// Split all interlocks into two parts
numIntlksLeftSide = (int)Math.Ceiling(HMIConstants.NumInterlocks * 0.5);
numIntlksRightSide = HMIConstants.NumInterlocks - numIntlksLeftSide;
listBoxItemsLeft = new ListBoxItem[numIntlksLeftSide];
listBoxItemsRight = new ListBoxItem[numIntlksRightSide];
_variableNameStatus = System.String.Empty;
_variableNameNames = System.String.Empty;
// CreateContent();
}
public IntlkDetailsVM(IAdsManager adsManager, string variableNameStatus, string variableNameNames, string intlkName) : this()
{
interlockName = intlkName;
_variableNameStatus = variableNameStatus;
_variableNameNames = variableNameNames;
_adsManager = adsManager;
interlockStatus = new BitArray(HMIConstants.NumInterlocks);
interlockNames = new string[HMIConstants.NumInterlocks];
_adsManager.Register(_variableNameStatus, InterlockStatusChanged);
_adsManager.Register(_variableNameNames, InterlockNamesChanged);
}
public void Dispose()
{
_adsManager?.Deregister(_variableNameStatus, InterlockStatusChanged);
_adsManager?.Deregister(_variableNameNames, InterlockNamesChanged);
_adsManager = null;
}
/*private void CreateContent()
{
// Create left side
for (int i = 0; i < HMIConstants.NumInterlocks; i++)
{
// Create the stack panel
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
// Create the box
// <Rectangle Width="10" Height="10" Fill="{Binding Path=InterlockStatus[10], Converter={StaticResource myBoolConverter}}" RadiusX="2" RadiusY="2" Margin="0,2,0,0"/>
Rectangle rectangle = new Rectangle
{
Width = 10,
Height = 10,
RadiusX = 2,
RadiusY = 2
};
// Create binding
Binding binding = new()
{
Source = this,
Path = new PropertyPath("InterlockStatus[" + i + "]"),
Converter = boolToBrushConverter,
};
// Set binding
rectangle.SetBinding(Rectangle.FillProperty, binding);
// Create label
Label label = new();
binding = new()
{
Source = this,
Path = new PropertyPath("InterlockNames[" + i + "]")
};
label.SetBinding(Label.ContentProperty, binding);
// Add items to stack panel
stackPanel.Children.Add(rectangle);
stackPanel.Children.Add(label);
// Add stack panel to listbox items
ListBoxItem tempListBoxItem = new()
{
Content = stackPanel
};
if (i < numIntlksLeftSide)
ListBoxItemsLeft[i] = tempListBoxItem;
else
ListBoxItemsRight[i - numIntlksLeftSide] = tempListBoxItem;
}
}*/
private void InterlockStatusChanged(object? sender, ValueChangedEventArgs e)
{
ushort temp = (ushort)e.Value;
InterlockStatus = new BitArray(BitConverter.GetBytes(temp));
}
private void InterlockNamesChanged(object? sender, ValueChangedEventArgs e)
{
InterlockNames = (string[])e.Value;
}
}
}

View File

@@ -0,0 +1,13 @@
<Window xmlns:AdsSessionTest="clr-namespace:HMIToolkit" x:Class="HMIToolkit.IntlkDetailsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HMIToolkit"
mc:Ignorable="d"
SizeToContent="WidthAndHeight"
Title="IntlkDetailsWindow" Height="450" Width="800">
<Grid>
<AdsSessionTest:IntlkDetails />
</Grid>
</Window>

View File

@@ -0,0 +1,27 @@
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.Shapes;
namespace HMIToolkit
{
/// <summary>
/// Interaktionslogik für IntlkDetailsWindow.xaml
/// </summary>
public partial class IntlkDetailsWindow : Window
{
public IntlkDetailsWindow()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,218 @@
using System.Runtime.InteropServices;
using System.Text;
namespace HMIToolkit
{
// PLC - C#
// --------
// int - short
// word - ushort
// Constants for interaction with data
public static class HMIConstants
{
public const int StringLength = 81;
public const int NumInterlocks = 16;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIAnalogValue
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HMIConstants.StringLength)]
public string sName;
// 1 = Ok, 2 = Error
public short iStatus;
public float rValue;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HMIConstants.StringLength)]
public string sUnit;
[MarshalAs(UnmanagedType.I1)]
public bool xUsed;
}
// TwinCAT2 Pack = 1, TwinCAT 3 Pack = 0
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIControlButton
{
[MarshalAs(UnmanagedType.I1)]
public bool xRequest;
[MarshalAs(UnmanagedType.I1)]
public bool xRelease;
public short iFeedback;
}
// TwinCAT2 Pack = 1, TwinCAT 3 Pack = 0
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIInterlock
{
public ushort wProcessINTLKStatus;
public ushort wSafeyINTLKStatus;
public ushort wProcessINTLKUsed;
public ushort wSafeyINTLKUsed;
// 16 * String(80) = 81 bytes a 16 indexes
// combined in one string because reading a two dimensional array is not possible
[MarshalAs(UnmanagedType.ByValArray, SizeConst = HMIConstants.StringLength * HMIConstants.NumInterlocks)]
public byte[] asProcessINTLKName;
// 16 * String(80) = 81 bytes a 16 indexes
// combined in one string because reading a two dimensional array is not possible
[MarshalAs(UnmanagedType.ByValArray, SizeConst = HMIConstants.StringLength * HMIConstants.NumInterlocks)]
public byte[] asSafetyINTLKName;
[MarshalAs(UnmanagedType.I1)]
public bool xProcessINTLKOk;
[MarshalAs(UnmanagedType.I1)]
public bool xSafetyINTLKOk;
}
// TwinCAT2 Pack = 1, TwinCAT 3 Pack = 0
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIValveData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HMIConstants.StringLength)]
public string sName;
public HMIControlButton stAutomaticButton;
public HMIControlButton stManualButton;
public HMIControlButton stOpenButton;
public HMIControlButton stCloseButton;
// 1 = Opened, 2 = Opening/Closing, 3 = Closed, 4 = Error
public short iStatus;
// 1 = Automatic mode, 2 = Manual mode
public short iCurrentMode;
public HMIInterlock stInterlock;
[MarshalAs(UnmanagedType.I1)]
public bool xUsed;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIAnalogValveData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HMIConstants.StringLength)]
public string sName;
public HMIControlButton stAutomaticButton;
public HMIControlButton stManualButton;
public HMIControlButton stOpenButton;
public HMIControlButton stCloseButton;
// 1 = Opened, 2 = Opening/Closing, 3 = Closed, 4 = Error
public short iStatus;
// 1 = Automatic mode, 2 = Manual mode
public short iCurrentMode;
public HMIInterlock stInterlock;
HMIAnalogValue stSetpoint;
HMIAnalogValue stProcessValue;
[MarshalAs(UnmanagedType.I1)]
public bool xUsed;
}
// TwinCAT2 Pack = 1, TwinCAT 3 Pack = 0
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIAnalogMotorData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HMIConstants.StringLength)]
public string sName;
public HMIControlButton stAutomaticButton;
public HMIControlButton stManualButton;
public HMIControlButton stStartButton;
public HMIControlButton stStopButton;
// 1 = Opened, 2 = Opening/Closing, 3 = Closed, 4 = Error
public short iStatus;
// 1 = Automatic mode, 2 = Manual mode
public short iCurrentMode;
public HMIAnalogValue stSetpoint;
public HMIAnalogValue stProcessValue;
public HMIInterlock stInterlock;
[MarshalAs(UnmanagedType.I1)]
public bool xUsed;
}
// TwinCAT2 Pack = 1, TwinCAT 3 Pack = 0
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct HMIOrpSensorData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = HMIConstants.StringLength)]
public string sName;
// 1 = Ok, 2 = Error
public short iStatus;
public float rValuePH;
public float rValueTemp;
public float rValueORP;
public float rValueDLI;
[MarshalAs(UnmanagedType.I1)]
public bool xUsed;
}
static class HMIUtilities
{
// Converts the interlock byte array into a string array
public static string[] GetInterlockStringArray(byte[] byteArray)
{
string[] temp = new string[HMIConstants.NumInterlocks];
int size;
// Check if byteArray is of correct size
if (byteArray.Length != (HMIConstants.StringLength * HMIConstants.NumInterlocks))
return temp;
for (int i = 0; i < HMIConstants.NumInterlocks; i++)
{
// Calculate length of string by finding the 0 terminator so the unused bytes get truncated
size = Array.IndexOf(byteArray, (byte)0, i * HMIConstants.StringLength) - (i * HMIConstants.StringLength);
// Check if we found a valid 0 terminator
if (size >= 0)
// Build string from byteArray with calculated size
temp[i] = Encoding.ASCII.GetString(byteArray, i * HMIConstants.StringLength, size);
else
// No valid 0 string terminator was found so return an empty string
temp[i] = "";
}
return temp;
}
}
}

View File

@@ -0,0 +1,79 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<AssemblyVersion>0.1.0</AssemblyVersion>
<FileVersion>0.1</FileVersion>
<Platforms>AnyCPU;x64</Platforms>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<None Remove="Anlagenuebersicht.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Beckhoff.TwinCAT.Ads" Version="6.1.197" />
<PackageReference Include="Beckhoff.TwinCAT.TcEventLoggerAdsProxy.Net" Version="2.7.11" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="MahApps.Metro" Version="2.4.10" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="AdsManager">
<HintPath>bin\x64\Debug\net8.0-windows8.0\AdsManager.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Resource Include="Anlagenuebersicht.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
<Compile Update="Common\MediaContainer.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Common\ParamControlInt.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Common\ParamControlFloat.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\AnalogMotorControl\AnalogMotorControl.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\AnalogValue\AnalogValue.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\AnalogValveControl\AnalogValveControl.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\BinaryValveControl\BinaryValveControl.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\InterlockControl\IntlkControl.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\InterlockDetailsControl\IntlkDetails.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="HMIToolkit\HMIObjects\InterlockDetailsControl\IntlkDetailsWindow.xaml.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,190 @@
<Window x:Class="InfineonHMI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:uniperHmi="clr-namespace:InfineonHMI"
mc:Ignorable="d"
x:Name="MainControlWindow"
d:DataContext="{d:DesignInstance Type=uniperHmi:MainWindowVM}"
WindowStartupLocation="CenterScreen"
Title="Infineon BiPolar" Height="2100" Width="3820" ResizeMode="NoResize">
<Viewbox Stretch="Fill">
<Grid Width="3840" Height="2100">
<Grid.RowDefinitions>
<RowDefinition Height="0.08*"/>
<RowDefinition Height="0.04*"/>
<RowDefinition Height="0.04*"/>
<RowDefinition Height="0.74*"/>
<RowDefinition Height="0.10*"/>
</Grid.RowDefinitions>
<!-- Header line -->
<Grid Grid.Row="0" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.Resources>
<!--Set x: share to get the latest every time-->
<system:DateTime x:Key="DateTime"
x:Shared="False" />
<Storyboard x:Key="Storyboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext"
Duration="0:0:1"
RepeatBehavior="Forever"
AutoReverse="False">
<DiscreteObjectKeyFrame KeyTime="50%"
Value="{StaticResource DateTime}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<TextBlock Text="{Binding RelativeSource={RelativeSource Self},Path=DataContext.Now,StringFormat={}{0:dd.MM.yyyy}}"
DataContext="{StaticResource DateTime}"
FontSize="48"
Foreground="White">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard}" />
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<TextBlock Text="{Binding RelativeSource={RelativeSource Self},Path=DataContext.Now,StringFormat={}{0:hh:mm:ss}}"
DataContext="{StaticResource DateTime}"
FontSize="48"
Margin="0,50,0,0"
Foreground="White">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard}" />
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Grid>
<Button Grid.Column="10"
Grid.ColumnSpan="2"
Margin="10"
FontSize="44"
Content="{Binding ActualUser}"
Command="{Binding ChangeUserClickedCommand}"/>
<Button Grid.Column="12"
Grid.ColumnSpan="2"
Margin="10"
FontSize="44"
Content="Auswahl&#xD;&#xA;Betriebsart"
Command="{Binding WorkingModeSelectionClickedCommand}"/>
<Label Grid.Column="1"
Grid.ColumnSpan="3"
Content="BiPolar Randätzer"
FontSize="60"
VerticalAlignment="Top"/>
<Label Grid.Column="1"
Grid.ColumnSpan="3"
Content="V 01.00"
FontSize="40"
VerticalAlignment="Bottom"/>
</Grid>
<!-- Latest event line -->
<Border Grid.Row="1" BorderBrush="White" BorderThickness="0,0,0,2">
<Label Content="{Binding EventsPageVM.CurrentEvent.Message}"
FontSize="28"
VerticalAlignment="Center"/>
</Border>
<!-- Breadcrumb line -->
<Label Grid.Row="2"
Content="{Binding Breadcrumb}"
FontSize="28"/>
<!-- Page frame -->
<Frame x:Name="MainFrame"
Grid.Row="3"
NavigationUIVisibility="Hidden"
Content="{Binding CurrentPage}"/>
<!-- Softkey grid -->
<Grid Grid.Row="4" Margin="20">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<UniformGrid Columns="7" Grid.ColumnSpan="7">
<!-- Softkey 1 -->
<Button Grid.Column="0" Content="Übersicht" FontSize="38" Margin="10"
Command="{Binding OverviewWindowClickedCommand}" />
<!-- Command="{Binding AutomaticModeCommand}" -->
<!-- Softkey 2 -->
<Button Grid.Column="0" Content="Stationen" FontSize="38" Margin="10"
Command="{Binding ProductionWindowClickedCommand}"/>
<!-- Command="{Binding ManualModeCommand}" -->
<!-- Softkey 3 -->
<Button Grid.Column="0" Content="Protokoll" FontSize="38" Margin="10"
Command="{Binding ProtocolWindowClickedCommand}" Visibility="Collapsed"/>
<!-- Softkey 4 -->
<Button Grid.Column="0" Content="Rezepte" FontSize="38" Margin="10"
Command="{Binding ReceipesWindowClickedCommand}" />
<!-- Command="{Binding SettingsWindowCommand}" -->
<!-- Softkey 5 -->
<Button Grid.Column="0" Content="Trend" FontSize="38" Margin="10"
Command="{Binding TrendWindowClickedCommand}" Visibility="Collapsed"/>
<!-- Softkey 6 -->
<Button Grid.Column="0" Content="Komponenten" FontSize="38" Margin="10"
Command="{Binding ComponentsWindowClickedCommand}" Visibility="Collapsed"/>
<!-- Softkey 7 -->
<!-- Softkey 8 -->
<Button Content="Einstellungen" FontSize="38" Margin="10"
Command="{Binding SettingsWindowClickedCommand}" Visibility="Collapsed"/>
</UniformGrid>
<Button Grid.Column="7" Content="Meldungen" FontSize="38" Margin="10"
Command="{Binding EventsListClickedCommand}"/>
<!-- Softkey 9 -->
<Button Grid.Column="8" Content="Ack Alarms" FontSize="38" Margin="10"
Command="{Binding AckAlarmsCommand}"/>
</Grid>
</Grid>
</Grid>
</Viewbox>
</Window>

View File

@@ -0,0 +1,26 @@
using HMIToolkit;
using MahApps.Metro.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow(MainWindowVM mainWindowVM)
{
this.DataContext = mainWindowVM;
InitializeComponent();
Closed += OnClosedEvent;
}
private void OnClosedEvent(object? sender, EventArgs e)
{
if (DataContext is IDisposable dataContext)
dataContext.Dispose();
}
}
}

View File

@@ -0,0 +1,298 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using System.Windows.Controls;
using TcEventLoggerAdsProxyLib;
using InfineonHMI.Pages.Views;
namespace InfineonHMI;
public sealed partial class MainWindowVM : ObservableObject, IRecipient<NavigateMessage>, IDisposable
{
[ObservableProperty] private StringControlButtonVM dummyStringVM;
[ObservableProperty] private Page currentPage;
[ObservableProperty] private Visibility statusBarVisible;
[ObservableProperty] private string breadcrumb;
[ObservableProperty] private string actualUser;
private const string _actualUserPrefix = "Aktueller Benutzer: \n";
private readonly IAdsManager _adsManager;
private readonly IConfiguration _config;
private readonly TcEventLogger _eventlogger;
// Last active event
[ObservableProperty] private string currentActiveEvent = "";
private readonly object _lock = new();
// Empty page
private readonly Page _emptyPage;
// Last navigate message
private readonly Stack<NavigateMessage> _messageStack = new();
NavigateMessage? _currentMessage;
// Events page view model
[ObservableProperty] EventsPageVM _eventsPageVM;
// Settings page viem model
SettingsPageVM? _settingsPageVM;
ProductionOverviewPageVM? _productionOverviewPageVM;
private MachineOverviewPageVM? _machineOverviewPageVM;
// Hot Coolplate page view model
HotCoolPlatePageVM? _hotCoolplatePageVM;
// Kuka Robot page view model
ReceipePageVM? _receipePageVM;
public MainWindowVM(IAdsManager adsManager, IConfiguration config, TcEventLogger eventLogger)
{
_adsManager = adsManager;
_config = config;
ActualUser = _actualUserPrefix + "---------";
// Create dummy string
DummyStringVM = new StringControlButtonVM();
// Create empty page
_emptyPage = new();
// Create events page viewmodel
_eventlogger = eventLogger;
_eventsPageVM = new(_eventlogger);
CurrentPage = _emptyPage;
_currentMessage = new NavigateMessage("", typeof(Page));
_messageStack.Push(_currentMessage);
WeakReferenceMessenger.Default.Register<NavigateMessage>(this);
breadcrumb = "";
}
public void NavigateFromOuterPage(NavigateMessage message, NavigateMessage nextMessage)
{
_currentMessage = message;
Navigate(message, nextMessage);
}
[RelayCommand]
private void SettingsWindow()
{
StatusBarVisible = Visibility.Visible;
_messageStack.Clear();
NavigateMessage message = new("", typeof(SettingsPage));
Receive(message);
}
[RelayCommand]
private void ChangeUserClicked()
{
}
[RelayCommand]
private void WorkingModeSelectionClicked()
{
}
[RelayCommand]
private void OverviewWindowClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config[""]!, typeof(MachineOverviewPage));
Receive(message);
}
[RelayCommand]
private void ProductionWindowClicked()
{
StatusBarVisible = Visibility.Visible;
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config[""]!, typeof(ProductionOverviewPage));
Receive(message);
}
[RelayCommand]
private void ProtocolWindowClicked()
{
}
[RelayCommand]
private void ReceipesWindowClicked()
{
StatusBarVisible = Visibility.Visible;
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config[""]!, typeof(ReceipePage));
Receive(message);
}
[RelayCommand]
private void TrendWindowClicked()
{
}
[RelayCommand]
private void ComponentsWindowClicked()
{
}
[RelayCommand]
private void SettingsWindowClicked()
{
_messageStack.Clear();
NavigateMessage message = new("", typeof(SettingsPage));
Receive(message);
}
[RelayCommand]
public void EventsListClicked()
{
StatusBarVisible = Visibility.Collapsed;
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new("", typeof(EventsPage));
Receive(message);
}
// Only use for forward traversal!
public void Receive(NavigateMessage message)
{
// Only change page if its a new page type
if (CurrentPage.GetType() == message.type)
return;
// Push current message
if (_currentMessage != null)
_messageStack.Push(_currentMessage);
// Save current message for later push
_currentMessage = message;
Navigate(message);
}
private void Navigate(NavigateMessage message, NavigateMessage? nextMessage = null)
{
// Dispose current pages viewmodel
if (CurrentPage.DataContext is IDisposable viewModel)
{
CurrentPage.DataContext = null;
viewModel.Dispose();
}
// Create new page
switch (message.type.Name)
{
case nameof(ProductionOverviewPage):
if (_productionOverviewPageVM == null || nextMessage != null)
_productionOverviewPageVM = new ProductionOverviewPageVM(_adsManager, _config, _eventlogger, nextMessage);
ProductionOverviewPage productionOverviewPage = new() { DataContext = _productionOverviewPageVM };
CurrentPage = productionOverviewPage;
break;
case nameof(MachineOverviewPage):
_machineOverviewPageVM?.Dispose();
_machineOverviewPageVM = new MachineOverviewPageVM(_adsManager, _config,this, new ProductionOverviewPageVM(_adsManager, _config, _eventlogger), _eventlogger);
MachineOverviewPage machineOverviewPage = new() { DataContext = _machineOverviewPageVM };
CurrentPage = machineOverviewPage;
break;
case nameof(EventsPage):
#pragma warning disable MVVMTK0034 // Direct field reference to [ObservableProperty] backing field
EventsPage eventsPage = new() { DataContext = _eventsPageVM };
#pragma warning restore MVVMTK0034 // Direct field reference to [ObservableProperty] backing field
CurrentPage = eventsPage;
Breadcrumb = " > Events";
break;
case nameof(SettingsPage):
// Create seetings page view model only once
if (_settingsPageVM == null)
_settingsPageVM = new(_adsManager, "GVL_CONFIG.stUnitConfig");
SettingsPage settingsPage = new() { DataContext = _settingsPageVM };
CurrentPage = settingsPage;
Breadcrumb = " > Settings";
break;
case nameof(ReceipePage):
if (_receipePageVM == null)
_receipePageVM = new();
ReceipePage receipePage = new() { DataContext = _receipePageVM };
CurrentPage = receipePage;
Breadcrumb = " > Kuka Roboter";
break;
case nameof(HotCoolPlatePage):
if (_hotCoolplatePageVM == null)
_hotCoolplatePageVM = new(_adsManager, "GVL_Config.stHotCoolplateConfig");
HotCoolPlatePage hotCoolPlatePage = new() {DataContext = _hotCoolplatePageVM };
CurrentPage = hotCoolPlatePage;
Breadcrumb = " > Heiz- /Kühlplatte";
break;
default:
CurrentPage = new Page();
break;
}
}
private void AppendBreadcrumb(string path)
{
if (Breadcrumb[^1] != ' ')
Breadcrumb += " > " + path;
else
Breadcrumb += "> " + path;
}
[RelayCommand]
private void AckAlarms()
{
_adsManager.WriteValue("GVL_SCADA.stConfirmAlarmsBtn.xRequest", true);
}
public void Dispose()
{
// Dispose current pages viewmodel
if (CurrentPage.DataContext is IDisposable viewModel)
{
CurrentPage.DataContext = null;
viewModel.Dispose();
}
DummyStringVM.Dispose();
}
}

View File

@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InfineonHMI.Model
{
public enum E_BMS_CONTROL_MODE : short
{
AUTO_REMOTE = 1,
AUTO_LOCAL = 2,
SAFETY_CHECK = 3,
CAPACITY_TEST = 4,
MANUAL = 5
}
public class BMSControlModeEntry(E_BMS_CONTROL_MODE mode, string name)
{
public E_BMS_CONTROL_MODE eMode = mode;
public string Name = name;
public override string ToString()
{
return Name;
}
}
public enum PLCJobenum : short
{
NONE = 0,
SCAN_QR_CODE = 10,
VACUUM_ON_ALIGNER = 15,
VACUUM_OFF_ALIGNER = 16,
VACUUM_ON_ETCHER_1 = 20,
VACUUM_ON_ETCHER_2 = 21,
VACUUM_OFF_ETCHER_1 = 22,
VACUUM_OFF_ETCHER_2 = 23,
CHUCK_OPEN_ETCHER_1 = 60,
CHUCK_OPEN_ETCHER_2 = 61,
CHUCK_CLOSE_ETCHER_1 = 62,
CHUCK_CLOSE_ETCHER_2 = 63,
}
public enum RobotJobenum : short
{
NONE = 0,
PICK_TRAYFEEDER = 10,
PLACE_TRAYFEEDER = 11,
PUT_ALIGNMENT = 15,
PICK_ALIGNMENT = 16,
PUT_ETCHER_1 = 20,
PUT_ETCHER_2 = 21,
PICK_ETCHER_1 = 22,
PICK_ETCHER_2 = 23,
SWITCH_ETCHER_1 = 24,
SWITCH_ETCHER_2 = 25,
PUT_HVTEST_HOT = 30,
PUT_HVTEST_COLD = 31,
PICK_HVTEST_HOT = 32,
PICK_HVTEST_COLD = 33,
PUT_HOTPLATE = 40,
PICK_HOTPLATE = 41,
PUT_COOLPLATE = 42,
PICK_COOLPLATE = 43,
PICK_GRIPPER = 50,
PICK_CHUCK_ETCHER_1 = 60,
PICK_CHUCK_ETCHER_2 = 61,
PUT_CHUCK_ETCHER_1 = 62,
PUT_CHUCK_ETCHER_2 = 63,
PUT_CHUCK_MAGAZIN = 64,
PICK_CHUCK_MAGAZIN = 65,
PUT_NIO_STATION = 70,
PICK_NIO_STATION = 71,
WARMUP = 80
}
public class PLCJobentry(PLCJobenum job, string name)
{
public PLCJobenum eJob = job;
public string Name = name;
public override string ToString()
{
return Name;
}
}
public class RobotJobentry(RobotJobenum job, string name)
{
public RobotJobenum eJob = job;
public string Name = name;
public override string ToString()
{
return Name;
}
}
public enum Stationenum : uint
{
EINGABE = 1,
QRCODE = 2,
AUSRICHTEN = 4,
AETZEN = 8,
HEIZPLATTE = 16,
KUEHLPLATTE = 32,
HOCHVOLTHEISS = 64,
HOCHVOLTKALT = 128,
AUSGABE = 256,
NIOSTATION = 512
}
public class StationEntry(Stationenum station, string name)
{
public Stationenum eStation = station;
public string sName = name;
public override string ToString()
{
return sName;
}
}
public class FlowReceipeEntry()
{
public int NodeId { get; set; }
public UInt16 Priority { get; set; }
public required StationEntry Station { get; set; }
public UInt16 MaxRetries { get; set; }
public int NextNodeSuccess { get; set; }
public int NextNodeRetry { get; set; }
public int NextNodeFail { get; set; }
}
}

View File

@@ -0,0 +1,225 @@
using System.IO;
using System.Reflection.PortableExecutable;
using System.Xml;
using System.Xml.Serialization;
using InfineonHMI.Common;
namespace InfineonHMI.Model;
public class ReceipeDto
{
public ReceipeDto()
{
ReceipeObject = new ReceipeObject();
}
public ReceipeObject ReceipeObject { get; set; }
public void Write(string filename)
{
L4ItXmlSerializer.SerializeObject(ReceipeObject, filename);
}
public void Read(string filename)
{
ReceipeObject = L4ItXmlSerializer.DeSerializeObject<ReceipeObject>(filename);
}
}
public class ReceipeObject
{
public MachineParameters MachineParameters { get; set; }
public ProductParameters ProductParameters { get; set; }
public ReceipeHotplate ReceipeHotplate { get; set; }
public ReceipeCoolplate ReceipeCoolplate { get; set; }
public ReceipeEtcher ReceipeEtcher { get; set; }
public ReceipeHighvoltageTester ReceipeHvTester { get; set; }
public FlowReceipe Flowreceipe { get; set; }
public ReceipeObject()
{
MachineParameters = new MachineParameters();
ProductParameters = new ProductParameters();
ReceipeHotplate = new ReceipeHotplate();
ReceipeCoolplate = new ReceipeCoolplate();
ReceipeEtcher = new ReceipeEtcher();
ReceipeHvTester = new ReceipeHighvoltageTester();
Flowreceipe = new FlowReceipe();
}
}
public class MachineParameters
{
public List<TrayPosition> TrayPositions { get; set; }
public int CameraPrograms { get; set; }
public int Chucks { get; set; }
public int Gripper { get; set; }
/// <summary>
/// Erlaubten Strahlparameter Abweichungen
/// </summary>
public float PermissibleBeamParameterDeviations { get; set; }
public MachineParameters()
{
TrayPositions = new List<TrayPosition>();
}
}
public class ProductParameters
{
public float Diameter { get; set; }
public float Thickness { get; set; }
public float TimeIntervallBeamCheck { get; set; }
}
public class ReceipeHotplate
{
public float RestingTime { get; set; }
public float TargetTemperature { get; set; }
}
public class ReceipeCoolplate
{
public float RestingTime { get; set; }
public float TargetTemperature { get; set; }
}
public class ReceipeHighvoltageTester
{
/// <summary>
/// Test voltage in V
/// </summary>
public float TestVoltage { get; set; }
/// <summary>
/// Maximum test Current
/// </summary>
public float MaximumTestCurrent { get; set; }
/// <summary>
/// Ramp Time in milliseconds
/// </summary>
public float RampTime { get; set; }
/// <summary>
/// Testfrequency in HZ
/// </summary>
public float TestFrequency { get; set; }
/// <summary>
/// Polarity 1=Positive, 2=Negative
/// </summary>
public UInt16 Polarity { get; set; }
/// <summary>
/// Overpressure N2 in mbar
/// </summary>
public float TestpressureN2 { get; set; }
/// <summary>
/// N2 pre purging time in seconds
/// </summary>
public float N2PrePurgetime { get; set; }
/// <summary>
/// Test retries
/// </summary>
public UInt16 NumRetries { get; set; }
/// <summary>
/// Temperature for testing (only used in heated HV station)
/// </summary>
public float TestTemperature { get; set; }
/// <summary>
/// Test OK Voltage
/// </summary>
public float TestOkVoltage { get; set; }
/// <summary>
/// Test OK Current
/// </summary>
public float TestOkCurrent { get; set; }
}
public class ReceipeEtcher
{
/// <summary>
/// Number of Robot positions
/// </summary>
public UInt16 NumberRobotPos { get; set; }
public float Rpm { get; set; }
/// <summary>
/// Roboter position and setting data
/// </summary>
public List<EtcherRobotStepData> RobotStepData { get; set; }
/// <summary>
/// Radial position of water jet under the blank in mm
/// </summary>
public float RadialPosLowerWaterJet { get; set; }
public ReceipeEtcher()
{
RobotStepData = new List<EtcherRobotStepData>();
}
}
public class EtcherRobotStepData
{
public float PosX { get; set; }
public float PosY { get; set; }
public float PosZ { get; set; }
public float AngleAlpha { get; set; }
public float MoveSpeed { get; set; }
public float Delay { get; set; }
public UInt16 Medium { get; set; }
public bool WaterFromBelow { get; set; }
public bool WaterFromAbove { get; set; }
}
public class FlowReceipe
{
public int NodeCount { get; set; }
public List<FlowReceipeNode> Nodes { get; set; }
public FlowReceipe()
{
Nodes = new List<FlowReceipeNode>();
}
}
public class FlowReceipeNode
{
public UInt16 Priority { get; set; }
public Int32 StationType { get; set; }
public UInt16 MaxRetries { get; set; }
public int NextNodeSuccess { get; set; }
public int NextNodeRetry { get; set; }
public int NextNodeFail { get; set; }
}
public class TrayPosition
{
public int PosId { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
}

View File

@@ -0,0 +1,3 @@
namespace InfineonHMI;
public record class NavigateMessage(string VariableName, Type type, string Header = "");

View File

@@ -0,0 +1,18 @@
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
namespace UniperHMI;
public sealed partial class ModuleControlButtonVM : SMUBaseVM, IDisposable
{
public ModuleControlButtonVM() : base() { }
public ModuleControlButtonVM(IAdsManager adsManager, string variableName) : base(adsManager, variableName) { }
[RelayCommand]
private void Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName, typeof(ModuleOverviewPage)));
}
}

View File

@@ -0,0 +1,60 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Heisig.HMI.AdsManager;
using TwinCAT.TypeSystem;
namespace InfineonHMI;
public enum E_COMPONENT_STATUS : short
{
OFF = 0,
ON = 1,
CHARGING = 2,
DISCHARGING = 3,
ERROR = 4
}
public partial class SMUBaseVM : ObservableObject, IDisposable
{
[ObservableProperty]
protected float voltage;
[ObservableProperty]
protected E_COMPONENT_STATUS status;
protected readonly string _variableName;
protected readonly IAdsManager? _adsManager;
public SMUBaseVM()
{
_variableName = string.Empty;
_adsManager = null;
voltage = 0.0f;
status = E_COMPONENT_STATUS.OFF;
}
public SMUBaseVM(IAdsManager adsManager, string variableName)
{
Status = E_COMPONENT_STATUS.OFF;
_adsManager = adsManager;
_variableName = variableName;
_adsManager!.Register(_variableName + ".rVoltage", VoltageChanged);
_adsManager.Register(_variableName + ".eStatus", StatusChanged);
}
protected void VoltageChanged(object? sender, ValueChangedEventArgs e)
{
Voltage = (float)e.Value;
}
protected void StatusChanged(object? sender, ValueChangedEventArgs e)
{
Status = (E_COMPONENT_STATUS)((short)e.Value);
}
public void Dispose()
{
_adsManager?.Deregister(_variableName + ".rVoltage", VoltageChanged);
_adsManager?.Deregister(_variableName + ".eStatus", StatusChanged);
}
}

View File

@@ -0,0 +1,16 @@
using Heisig.HMI.AdsManager;
namespace InfineonHMI;
public sealed partial class StringControlButtonVM : SMUBaseVM, IDisposable
{
public StringControlButtonVM() : base() { }
public StringControlButtonVM(IAdsManager adsManager, string variableName) : base(adsManager, variableName) { }
//[RelayCommand]
//private void Clicked()
//{
// WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName, typeof(StringOverviewPage)));
//}
}

View File

@@ -0,0 +1,19 @@
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
namespace InfineonHMI.OwnControls
{
public sealed partial class UnitControlButtonVM : SMUBaseVM
{
public UnitControlButtonVM() : base() { }
public UnitControlButtonVM(IAdsManager adsManager, string variableName) : base(adsManager, variableName) { }
[RelayCommand]
private void Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName, typeof(UnitDetailsControl)));
}
}
}

View File

@@ -0,0 +1,494 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HMIToolkit;
using TwinCAT.TypeSystem;
using Heisig.HMI.AdsManager;
namespace InfineonHMI
{
public sealed partial class UnitDetailsControlVM : ObservableObject, IDisposable
{
[ObservableProperty]
private float rVoltage;
[ObservableProperty]
private E_COMPONENT_STATUS status;
[ObservableProperty]
private AnalogValueVM pressureNegolytSegmentInVM;
[ObservableProperty]
private AnalogValueVM pressureNegolytTankInVM;
[ObservableProperty]
private AnalogValueVM temperatureNegolytTankInVM;
[ObservableProperty]
private AnalogValueVM pressurePosolytSegmentInVM;
[ObservableProperty]
private AnalogValueVM pressurePosolytTankInVM;
[ObservableProperty]
private AnalogValueVM temperaturePosolytTankInVM;
[ObservableProperty]
private bool canOpenBothValves;
[ObservableProperty]
private bool canCloseBothValves;
[ObservableProperty]
private short feedbackOpenValves;
[ObservableProperty]
private short feedbackCloseValves;
[ObservableProperty]
private bool canStartBothPumps;
[ObservableProperty]
private bool canStopBothPumps;
[ObservableProperty]
private short feedbackStartPumps;
[ObservableProperty]
private short feedbackStopPumps;
private float _posolytPumpOnSpeed;
private float _negolytPumpOnSpeed;
private float valveWindowHorizontalPosition;
private readonly BinaryValveControlVM _valveNegolytVM;
private readonly BinaryValveControlVM _valvePosolytVM;
private readonly AnalogMotorControlVM _pumpNegolytVM;
private readonly AnalogMotorControlVM _pumpPosolytVM;
private BinaryValveWindow? _windowValveNegolyt;
private BinaryValveWindow? _windowValvePosolyt;
private AnalogMotorWindow? _windowPumpNegolyt;
private AnalogMotorWindow? _windowPumpPosolyt;
private readonly IAdsManager? _adsManager;
private readonly string _variableName;
public UnitDetailsControlVM()
{
Status = E_COMPONENT_STATUS.OFF;
rVoltage = 0.0f;
_variableName = "";
// Negolyt
PressureNegolytSegmentInVM = new AnalogValueVM();
PressureNegolytTankInVM = new AnalogValueVM();
TemperatureNegolytTankInVM = new AnalogValueVM();
_valveNegolytVM = new BinaryValveControlVM();
_pumpNegolytVM = new AnalogMotorControlVM();
_windowValveNegolyt = null;
// Posolyt
PressurePosolytSegmentInVM = new AnalogValueVM();
PressurePosolytTankInVM = new AnalogValueVM();
TemperaturePosolytTankInVM = new AnalogValueVM();
_valvePosolytVM = new BinaryValveControlVM();
_pumpPosolytVM = new AnalogMotorControlVM();
_windowValvePosolyt = null;
valveWindowHorizontalPosition = 10;
}
public UnitDetailsControlVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
Status = E_COMPONENT_STATUS.OFF;
rVoltage = 0.0f;
// Negolyt
PressureNegolytSegmentInVM = new AnalogValueVM(_adsManager, _variableName + ".stP21", true);
PressureNegolytTankInVM = new AnalogValueVM(_adsManager, _variableName + ".stP22", true);
TemperatureNegolytTankInVM = new AnalogValueVM(_adsManager, _variableName + ".stT21", true);
_valveNegolytVM = new BinaryValveControlVM(_adsManager, _variableName + ".stNS22");
_valveNegolytVM.OpenButton.FeedbackChanged += OnValveNegolytOpenFeedbackChanged;
_valveNegolytVM.CloseButton.FeedbackChanged += OnValveNegolytCloseFeedbackChanged;
_valveNegolytVM.OpenButton.ReleaseChanged += OnValveNegolytOpenReleaseChanged;
_valveNegolytVM.CloseButton.ReleaseChanged += OnValveNegolytCloseReleaseChanged;
_pumpNegolytVM = new AnalogMotorControlVM(_adsManager, _variableName + ".stNS21");
_pumpNegolytVM.StartButton.FeedbackChanged += OnPumpNegolytStartFeedbackChanged;
_pumpNegolytVM.StopButton.FeedbackChanged += OnPumpNegolytStopFeedbackChanged;
_pumpNegolytVM.StartButton.ReleaseChanged += OnPumpNegolytStartReleaseChanged;
_pumpNegolytVM.StopButton.ReleaseChanged += OnPumpNegolytStopReleaseChanged;
// Posolyt
PressurePosolytSegmentInVM = new AnalogValueVM(_adsManager, _variableName + ".stP11", true);
PressurePosolytTankInVM = new AnalogValueVM(_adsManager, _variableName + ".stP12", true);
TemperaturePosolytTankInVM = new AnalogValueVM(_adsManager, _variableName + ".stT11", true);
_valvePosolytVM = new BinaryValveControlVM(_adsManager, _variableName + ".stNS12");
_valvePosolytVM.OpenButton.FeedbackChanged += OnValvePosolytOpenFeedbackChanged;
_valvePosolytVM.CloseButton.FeedbackChanged += OnValvePosolytCloseFeedbackChanged;
_valvePosolytVM.OpenButton.ReleaseChanged += OnValvePosolytOpenReleaseChanged;
_valvePosolytVM.CloseButton.ReleaseChanged += OnValvePosolytCloseReleaseChanged;
_pumpPosolytVM = new AnalogMotorControlVM(_adsManager, _variableName + ".stNS11");
_pumpPosolytVM.StartButton.FeedbackChanged += OnPumpPosolytStartFeedbackChanged;
_pumpPosolytVM.StopButton.FeedbackChanged += OnPumpPosolytStopFeedbackChanged;
_pumpPosolytVM.StartButton.ReleaseChanged += OnPumpPosolytStartReleaseChanged;
_pumpPosolytVM.StopButton.ReleaseChanged += OnPumpPosolytStopReleaseChanged;
// Current status
_adsManager.Register(_variableName + ".eStatus", StatusChanged);
_adsManager.Register(_variableName + ".rVoltage", VoltageChanged);
// Configured pump speed for on
_adsManager.Register("GVL_CONFIG.rPumpNegolytOnPower", NegolytPumpOnSpeedChanged);
_adsManager.Register("GVL_CONFIG.rPumpPosolytOnPower", PosolytPumpOnSpeedChanged);
valveWindowHorizontalPosition = 10;
}
private void NegolytPumpOnSpeedChanged(object? sender, ValueChangedEventArgs e)
{
_negolytPumpOnSpeed = (float)e.Value;
}
private void PosolytPumpOnSpeedChanged(object? sender, ValueChangedEventArgs e)
{
_posolytPumpOnSpeed = (float)e.Value;
}
private void VoltageChanged(object? sender, ValueChangedEventArgs e)
{
RVoltage = (float)e.Value;
}
public void Dispose()
{
// Dispose all necessary view models
// Negolyt
PressureNegolytSegmentInVM.Dispose();
PressureNegolytTankInVM.Dispose();
TemperatureNegolytTankInVM.Dispose();
_valveNegolytVM.OpenButton.FeedbackChanged -= OnValveNegolytOpenFeedbackChanged;
_valveNegolytVM.CloseButton.FeedbackChanged -= OnValveNegolytCloseFeedbackChanged;
_valveNegolytVM.OpenButton.ReleaseChanged -= OnValveNegolytOpenReleaseChanged;
_valveNegolytVM.CloseButton.ReleaseChanged -= OnValveNegolytCloseReleaseChanged;
_valveNegolytVM.Dispose();
_pumpNegolytVM.Dispose();
// Posolyt
PressurePosolytSegmentInVM.Dispose();
PressurePosolytTankInVM.Dispose();
TemperaturePosolytTankInVM.Dispose();
_valvePosolytVM.OpenButton.FeedbackChanged -= OnValvePosolytOpenFeedbackChanged;
_valvePosolytVM.CloseButton.FeedbackChanged -= OnValvePosolytCloseFeedbackChanged;
_valvePosolytVM.OpenButton.ReleaseChanged -= OnValvePosolytOpenReleaseChanged;
_valvePosolytVM.CloseButton.ReleaseChanged -= OnValvePosolytCloseReleaseChanged;
_valvePosolytVM.Dispose();
_pumpPosolytVM.Dispose();
// Deregister variables
_adsManager?.Deregister(_variableName + ".eStatus", StatusChanged);
_adsManager?.Deregister(_variableName + ".rVoltage", VoltageChanged);
_adsManager?.Deregister("GVL_CONFIG.rPumpNegolytOnPower", NegolytPumpOnSpeedChanged);
_adsManager?.Deregister("GVL_CONFIG.rPumpPosolytOnPower", PosolytPumpOnSpeedChanged);
// Destroy windows
_windowValveNegolyt?.Close();
_windowValvePosolyt?.Close();
_windowPumpNegolyt?.Close();
_windowPumpPosolyt?.Close();
}
private void StatusChanged(object? sender, ValueChangedEventArgs e)
{
Status = (E_COMPONENT_STATUS)((short)e.Value);
}
[RelayCommand]
private void ShowValveNegolyt()
{
if (_adsManager != null && _windowValveNegolyt == null)
{
_windowValveNegolyt = new() { DataContext = _valveNegolytVM };
_windowValveNegolyt.Closed += WindowValveNegolyt_Closed;
_windowValveNegolyt.Show();
}
}
private void WindowValveNegolyt_Closed(object? sender, EventArgs e)
{
_windowValveNegolyt!.Close();
_windowValveNegolyt = null;
}
[RelayCommand]
private void ShowValvePosolyt()
{
if (_adsManager != null && _windowValvePosolyt == null)
{
_windowValvePosolyt = new() { DataContext = _valvePosolytVM };
_windowValvePosolyt.Closed += WindowValvePosolyt_Closed;
_windowValvePosolyt.Show();
}
}
private void WindowValvePosolyt_Closed(object? sender, EventArgs e)
{
_windowValvePosolyt!.Close();
_windowValvePosolyt = null;
}
[RelayCommand]
public void ShowPumpNegolyt()
{
if (_adsManager != null && _windowPumpNegolyt == null)
{
_windowPumpNegolyt = new() { DataContext = _pumpNegolytVM };
_windowPumpNegolyt.Closed += WindowPumpNegolyt_Closed;
_windowPumpNegolyt.Show();
}
}
private void WindowPumpNegolyt_Closed(object? sender, EventArgs e)
{
_windowPumpNegolyt!.Close();
_windowPumpNegolyt = null;
}
[RelayCommand]
public void ShowPumpPosolyt()
{
if (_adsManager != null && _windowPumpPosolyt == null)
{
_windowPumpPosolyt = new() { DataContext = _pumpPosolytVM };
_windowPumpPosolyt.Closed += WindowPumpPosolyt_Closed;
_windowPumpPosolyt.Show();
}
}
[RelayCommand]
private void OpenBothValves()
{
_valveNegolytVM.OpenButton?.ButtonClickedCommand.Execute(null);
_valvePosolytVM.OpenButton?.ButtonClickedCommand.Execute(null);
}
[RelayCommand]
private void CloseBothValves()
{
_valveNegolytVM.CloseButton?.ButtonClickedCommand.Execute(null);
_valvePosolytVM.CloseButton?.ButtonClickedCommand.Execute(null);
}
private void OnValveNegolytOpenFeedbackChanged(object? sender, EventArgs e)
{
CalculateOpenFeedback();
}
private void OnValvePosolytOpenFeedbackChanged(object? sender, EventArgs e)
{
CalculateOpenFeedback();
}
private void CalculateOpenFeedback()
{
if (_valveNegolytVM?.OpenButton.IFeedback == 1 && _valvePosolytVM?.OpenButton.IFeedback == 1)
FeedbackOpenValves = 1;
else if (_valveNegolytVM?.OpenButton.IFeedback == 0 && _valvePosolytVM?.OpenButton.IFeedback == 0)
FeedbackOpenValves = 0;
else
FeedbackOpenValves = 2;
}
private void OnValveNegolytCloseFeedbackChanged(object? sender, EventArgs e)
{
CalculateCloseFeedback();
}
private void OnValvePosolytCloseFeedbackChanged(object? sender, EventArgs e)
{
CalculateCloseFeedback();
}
private void CalculateCloseFeedback()
{
if (_valveNegolytVM?.CloseButton.IFeedback == 1 && _valvePosolytVM?.CloseButton.IFeedback == 1)
FeedbackCloseValves = 1;
else if (_valveNegolytVM?.CloseButton.IFeedback == 0 && _valvePosolytVM?.CloseButton.IFeedback == 0)
FeedbackCloseValves = 0;
else
FeedbackCloseValves = 2;
}
private void OnValveNegolytOpenReleaseChanged(object? sender, EventArgs e)
{
CalculateOpenRelease();
}
private void OnValvePosolytOpenReleaseChanged(object? sender, EventArgs e)
{
CalculateOpenRelease();
}
private void CalculateOpenRelease()
{
if (_valvePosolytVM == null || _valveNegolytVM == null)
return;
if (_valveNegolytVM.OpenButton.XRelease && _valvePosolytVM.OpenButton.XRelease)
CanOpenBothValves = true;
else
CanOpenBothValves = false;
}
private void OnValveNegolytCloseReleaseChanged(object? sender, EventArgs e)
{
CalculateCloseRelease();
}
private void OnValvePosolytCloseReleaseChanged(object? sender, EventArgs e)
{
CalculateCloseRelease();
}
private void CalculateCloseRelease()
{
if (_valvePosolytVM == null || _valveNegolytVM == null)
return;
if (_valveNegolytVM.CloseButton.XRelease && _valvePosolytVM.CloseButton.XRelease)
CanCloseBothValves = true;
else
CanCloseBothValves = false;
}
[RelayCommand]
private void StartBothPumps()
{
if (_adsManager == null || _pumpNegolytVM == null || _pumpPosolytVM == null)
return;
_pumpNegolytVM.Setpoint.RValue = _negolytPumpOnSpeed;
_pumpPosolytVM.Setpoint.RValue = _posolytPumpOnSpeed;
_pumpNegolytVM.StartButton?.ButtonClickedCommand.Execute(null);
_pumpPosolytVM.StartButton?.ButtonClickedCommand.Execute(null);
}
[RelayCommand]
private void StopBothPumps()
{
_pumpNegolytVM.StopButton?.ButtonClickedCommand.Execute(null);
_pumpPosolytVM.StopButton?.ButtonClickedCommand.Execute(null);
}
private void CalculateStartRelease()
{
if (_pumpNegolytVM == null || _pumpPosolytVM == null)
return;
if (_pumpNegolytVM.StartButton.XRelease && _pumpPosolytVM.StartButton.XRelease)
CanStartBothPumps = true;
else
CanStartBothPumps = false;
}
private void CalculatStopRelease()
{
if (_pumpNegolytVM == null || _pumpPosolytVM == null)
return;
if (_pumpNegolytVM.StopButton.XRelease && _pumpPosolytVM.StopButton.XRelease)
CanStopBothPumps = true;
else
CanStopBothPumps = false;
}
private void CalculateStartFeedback()
{
if (_pumpNegolytVM == null || _pumpPosolytVM == null)
return;
if (_pumpNegolytVM.StartButton.IFeedback == 1 && _pumpPosolytVM.StartButton.IFeedback == 1)
FeedbackStartPumps = 1;
else if (_pumpNegolytVM.StartButton.IFeedback == 0 && _pumpPosolytVM.StartButton.IFeedback == 0)
FeedbackStartPumps = 0;
else
FeedbackStartPumps = 2;
}
private void CalculateStopFeedback()
{
if (_pumpNegolytVM == null || _pumpPosolytVM == null)
return;
if (_pumpNegolytVM.StopButton.IFeedback == 1 && _pumpPosolytVM.StopButton.IFeedback == 1)
FeedbackStopPumps = 1;
else if (_pumpNegolytVM.StopButton.IFeedback == 0 && _pumpPosolytVM.StopButton.IFeedback == 0)
FeedbackStopPumps = 0;
else
FeedbackStopPumps = 2;
}
private void OnPumpPosolytStopReleaseChanged(object? sender, EventArgs e)
{
CalculatStopRelease();
}
private void OnPumpPosolytStartReleaseChanged(object? sender, EventArgs e)
{
CalculateStartRelease();
}
private void OnPumpPosolytStopFeedbackChanged(object? sender, EventArgs e)
{
CalculateStopFeedback();
}
private void OnPumpPosolytStartFeedbackChanged(object? sender, EventArgs e)
{
CalculateStartFeedback();
}
private void OnPumpNegolytStopReleaseChanged(object? sender, EventArgs e)
{
CalculatStopRelease();
}
private void OnPumpNegolytStartReleaseChanged(object? sender, EventArgs e)
{
CalculateStartRelease();
}
private void OnPumpNegolytStopFeedbackChanged(object? sender, EventArgs e)
{
CalculateStopFeedback();
}
private void OnPumpNegolytStartFeedbackChanged(object? sender, EventArgs e)
{
CalculateStartFeedback();
}
private void WindowPumpPosolyt_Closed(object? sender, EventArgs e)
{
_windowPumpPosolyt!.Close();
_windowPumpPosolyt = null;
}
}
}

View File

@@ -0,0 +1,42 @@
<Button x:Class="InfineonHMI.SMUControlButton"
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:InfineonHMI"
d:DataContext="{d:DesignInstance Type=local:StringControlButtonVM, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Style="{StaticResource MahApps.Styles.Button}"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
Width="Auto" Height="Auto"
x:Name="root">
<Grid x:Name="mainGrid" Width="Auto" Height="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Row 0 -->
<Label Content="{Binding SMUName, ElementName=root}" Grid.Row="0" Grid.ColumnSpan="3" FontSize="24" HorizontalAlignment="Center"/>
<!-- Row 1 -->
<Line Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" X1="0" X2="{Binding ElementName=mainGrid, Path=ActualWidth}" Stroke="White" Margin="0,5,0,10"/>
<!-- Row 2 -->
<Label Grid.Row="2" Grid.Column="0" Content="Spannung:" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Voltage, StringFormat=N2}" MaxLines="1" Width="70" TextAlignment="Right" IsReadOnly="True" />
<Label Grid.Row="2" Grid.Column="2" Content="V" />
<!-- Row 3 -->
<Label Content="Status:" Grid.Row="3" Grid.Column="0" />
<Label Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Content="{Binding Status}" HorizontalAlignment="Center"/>
</Grid>
</Button>

View File

@@ -0,0 +1,23 @@
using System.Windows;
using System.Windows.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für StringControlButton.xaml
/// </summary>
public partial class SMUControlButton : Button
{
public static readonly DependencyProperty SMUNameProperty = DependencyProperty.Register("SMUName", typeof(string), typeof(SMUControlButton));
public String SMUName
{
get { return (string)GetValue(SMUNameProperty); }
set { SetValue(SMUNameProperty, value); }
}
public SMUControlButton()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,138 @@
<UserControl xmlns:HMIToolkit="clr-namespace:HMIToolkit" x:Class="InfineonHMI.UnitDetailsControl"
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:InfineonHMI"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:UnitDetailsControlVM, IsDesignTimeCreatable=True}"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Width="Auto" Height="Auto"
x:Name="root">
<UserControl.Resources>
<HMIToolkit:FeedbackToColorConverter x:Key="feedbackConverter" />
</UserControl.Resources>
<Grid x:Name="mainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Row 0 -->
<Label Content="{Binding UnitName, ElementName=root}" Grid.Row="0" Grid.ColumnSpan="4" FontSize="24" HorizontalAlignment="Center"/>
<!-- Row 1 -->
<Line Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4" X1="0" X2="{Binding ElementName=mainGrid, Path=ActualWidth}" Stroke="White" Margin="0,5,0,10"/>
<!-- Row 2 -->
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" Width="Auto" HorizontalAlignment="Left">
<Label Content="Spannung:" />
<TextBox Text="{Binding RVoltage, StringFormat=N2}" MaxLines="1" Width="70" TextAlignment="Right" IsReadOnly="True" />
<Label Content="V" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Label Content="Status:" Margin="20,0,0,0"/>
<Label Grid.ColumnSpan="2" Content="{Binding Status}" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
<!-- Row 3 -->
<Line Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" X1="0" X2="{Binding ElementName=mainGrid, Path=ActualWidth}" Stroke="White" Margin="0,5,0,10"/>
<!-- Row 4 -->
<Grid Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Negolyt:" FontWeight="Bold" HorizontalAlignment="Center"/>
<Label Grid.Row="0" Grid.Column="2" Content="Posolyt:" FontWeight="Bold" HorizontalAlignment="Center"/>
<Button Grid.Row="1" Grid.Column="0" Content="Tankventil" Command="{Binding ShowValveNegolytCommand}" HorizontalAlignment="Center" Width="100" />
<Button Grid.Row="1" Grid.Column="2" Content="Tankventil" Command="{Binding ShowValvePosolytCommand}" HorizontalAlignment="Center" Width="100" />
<!-- Open Close both valves -->
<Label Grid.Row="0" Grid.Column="1" Content="Both:" FontWeight="Bold" HorizontalAlignment="Center"/>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Open" Width="50" Command="{Binding OpenBothValvesCommand}" IsEnabled="{Binding CanOpenBothValves}" Background="{Binding FeedbackOpenValves, Converter={StaticResource feedbackConverter}}"/>
<Button Grid.Column="1" Content="Close" Width="50" Command="{Binding CloseBothValvesCommand}" IsEnabled="{Binding CanCloseBothValves}" Background="{Binding FeedbackCloseValves, Converter={StaticResource feedbackConverter}}" Margin="5,0,0,0"/>
</Grid>
<!-- Start stop both pumps -->
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Start" Command="{Binding StartBothPumpsCommand}" IsEnabled="{Binding CanStartBothPumps}" Background="{Binding FeedbackStartPumps, Converter={StaticResource feedbackConverter}}" Width="50" Margin="0,5,0,0"/>
<Button Grid.Column="1" Content="Stop" Command="{Binding StopBothPumpsCommand}" IsEnabled="{Binding CanStopBothPumps}" Background="{Binding FeedbackStopPumps, Converter={StaticResource feedbackConverter}}" Width="50" Margin="5,5,0,0"/>
</Grid>
<Button Grid.Row="2" Grid.Column="0" Content="Pumpe" Command="{Binding ShowPumpNegolytCommand}" HorizontalAlignment="Center" Width="100" Margin="0,5,0,0"/>
<Button Grid.Row="2" Grid.Column="2" Content="Pumpe" Command="{Binding ShowPumpPosolytCommand}" HorizontalAlignment="Center" Width="100" Margin="0,5,0,0"/>
</Grid>
<!-- Row 5 -->
<Line Grid.Row="5" X1="0" X2="{Binding ElementName=mainGrid, Path=ActualWidth}" Stroke="White" Margin="0,5,0,10"/>
<!-- Row 6 -->
<Grid Grid.Row="6">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="1" Content="Negolyt:" FontWeight="Bold" />
<Label Grid.Row="0" Grid.Column="2" Content="Posolyt:" FontWeight="Bold" />
<Label Grid.Row="1" Grid.Column="0" Content="Druck Segment Inlet:" />
<HMIToolkit:AnalogValue Grid.Row="1" Grid.Column="1" DataContext="{Binding PressureNegolytSegmentInVM}" HorizontalAlignment="Left" />
<HMIToolkit:AnalogValue Grid.Row="1" Grid.Column="2" DataContext="{Binding PressurePosolytSegmentInVM}" HorizontalAlignment="Left" />
<Label Grid.Row="2" Grid.Column="0" Content="Druck Tank Inlet:" Margin="0,5,0,0"/>
<HMIToolkit:AnalogValue Grid.Row="2" Grid.Column="1" DataContext="{Binding PressureNegolytTankInVM}" HorizontalAlignment="Left" Margin="0,5,0,0"/>
<HMIToolkit:AnalogValue Grid.Row="2" Grid.Column="2" DataContext="{Binding PressurePosolytTankInVM}" HorizontalAlignment="Left" Margin="0,5,0,0"/>
<Label Grid.Row="3" Grid.Column="0" Content="Temperatur Tank Inlet:" Margin="0,5,0,5"/>
<HMIToolkit:AnalogValue Grid.Row="3" Grid.Column="1" DataContext="{Binding TemperatureNegolytTankInVM}" HorizontalAlignment="Left" Margin="0,5,0,5"/>
<HMIToolkit:AnalogValue Grid.Row="3" Grid.Column="2" DataContext="{Binding TemperaturePosolytTankInVM}" HorizontalAlignment="Left" Margin="0,5,0,5"/>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,22 @@
using System.Windows;
using System.Windows.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für UnitControl.xaml
/// </summary>
public partial class UnitDetailsControl : UserControl
{
public static readonly DependencyProperty UnitNameProperty = DependencyProperty.Register("UnitName", typeof(string), typeof(UnitDetailsControl));
public String UnitName
{
get { return (string)GetValue(UnitNameProperty); }
set { SetValue(UnitNameProperty, value); }
}
public UnitDetailsControl()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,43 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class AlignmentStationPageVM : ObservableValidator, IDisposable
{
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
[ObservableProperty]
private BinaryValveControlVM vacuumValveControlVm;
public AlignmentStationPageVM()
{
VacuumValveControlVm = new BinaryValveControlVM();
}
public AlignmentStationPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
VacuumValveControlVm = new BinaryValveControlVM(_adsManager, _variableName + ".stVacuumValve");
}
public void Dispose()
{
}
}
}

View File

@@ -0,0 +1,134 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using UniperHMI.Model;
namespace UniperHMI
{
public sealed partial class AutomaticModePageVM : ObservableValidator, IDisposable
{
private int _setpoint;
[Range(-40000, 40000)]
public int Setpoint
{
get => this._setpoint;
set => SetProperty(ref this._setpoint, value, true);
}
[ObservableProperty]
private int processValue;
[ObservableProperty]
public HMIControlButtonVM? startButton;
[ObservableProperty]
public HMIControlButtonVM? stopButton;
[ObservableProperty]
private E_BMS_CONTROL_MODE bmsControlMode;
[ObservableProperty]
public ObservableCollection<BMSControlModeEntry> reqBMSControlModes =
[
new BMSControlModeEntry(E_BMS_CONTROL_MODE.AUTO_REMOTE, "Auto Remote"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.AUTO_LOCAL, "Auto Local"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.SAFETY_CHECK, "Safety Check"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.CAPACITY_TEST, "Capacity Test"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.MANUAL, "Manual")
];
[ObservableProperty]
private BMSControlModeEntry selectedControlMode;
[ObservableProperty]
private bool canChangeControlMode;
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
public AutomaticModePageVM()
{
StartButton = new HMIControlButtonVM();
StopButton = new HMIControlButtonVM();
SelectedControlMode = ReqBMSControlModes[1];
canChangeControlMode = true;
}
public AutomaticModePageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
StartButton = new HMIControlButtonVM(_adsManager, _variableName + ".stStartAutoButton");
//StopButton = new HMIControlButtonVM(_adsManager, _variableName + ".stStopAutoButton");
SelectedControlMode = ReqBMSControlModes[1];
_adsManager.Register("GVL_SCADA.eCurrentControlMode", CurrentControlModeChanged);
_adsManager.Register("GVL_SCADA.xCanChangeControlMode", CCCMChanged);
_adsManager.Register(_variableName + ".diSetpointAutomatic", SetpointChanged);
}
private void SetpointChanged(object? sender, ValueChangedEventArgs e)
{
Setpoint = (int)e.Value;
}
private void CCCMChanged(object? sender, ValueChangedEventArgs e)
{
CanChangeControlMode = (bool)e.Value;
}
private void CurrentControlModeChanged(object? sender, ValueChangedEventArgs e)
{
BmsControlMode = (E_BMS_CONTROL_MODE)e.Value;
SelectedControlMode.eMode = BmsControlMode;
SelectedControlMode.Name = "Test";
}
public void Dispose()
{
StartButton?.Dispose();
StartButton = null;
StopButton?.Dispose();
StopButton = null;
_adsManager?.Deregister("GVL_SCADA.eCurrentControlMode", CurrentControlModeChanged);
_adsManager?.Deregister("GVL_SCADA.xCanChangeControlMode", CCCMChanged);
_adsManager?.Deregister(_variableName + ".diSetpointAutomatic", SetpointChanged);
}
[RelayCommand]
private void StartAutomatic()
{
_adsManager?.WriteValue(_variableName + ".diSetpointAutomatic", Setpoint);
}
[RelayCommand]
private void StopAutomatic()
{
_adsManager?.WriteValue(_variableName + ".diSetpointAutomatic", 0);
Setpoint = 0;
}
public static ValidationResult ValidatePower(int power, ValidationContext context)
{
if (power < -40000 || power > 40000)
return new("Must be between -40.000 and +40.000");
else
return ValidationResult.Success!;
}
}
}

View File

@@ -0,0 +1,55 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
namespace UniperHMI
{
public sealed partial class BatteryOverviewPageVM : ObservableObject, IDisposable
{
[ObservableProperty]
private StringControlButtonVM? string1VM;
[ObservableProperty]
private StringControlButtonVM? string2VM;
[ObservableProperty]
private StringControlButtonVM? dummyStringVM;
private readonly IAdsManager? _adsManager;
public BatteryOverviewPageVM()
{
string1VM = new StringControlButtonVM();
string2VM = new StringControlButtonVM();
}
public BatteryOverviewPageVM(IAdsManager adsManager)
{
_adsManager = adsManager;
string1VM = new StringControlButtonVM(adsManager, "GVL_SCADA.stHMIInterface[0]");
string2VM = new StringControlButtonVM(adsManager, "GVL_SCADA.stHMIInterface[1]");
}
public void Dispose()
{
String1VM?.Dispose();
String1VM = null;
String2VM?.Dispose();
String2VM = null;
}
[RelayCommand]
private void String1Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage("GVL_SCADA.stHMIInterface[0]", typeof(StringOverviewPage), "String 1"));
}
[RelayCommand]
private void String2Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage("GVL_SCADA.stHMIInterface[1]", typeof(StringOverviewPage), "String 2"));
}
}
}

View File

@@ -0,0 +1,140 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Heisig.HMI.AdsManager;
using HMIToolkit;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Windows;
using TwinCAT.TypeSystem;
using UniperHMI.Model;
namespace UniperHMI
{
public sealed partial class ChuckMagazinPageVM : ObservableValidator, IDisposable
{
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
private const string sChuckOnPlace1 = "_adsVariable_MagazinPlace1";
private const string sChuckOnPlace2 = "_adsVariable_MagazinPlace2";
private const string sChuckOnPlace3 = "_adsVariable_MagazinPlace3";
private const string sChuckOnPlace4 = "_adsVariable_MagazinPlace4";
private const string sChuckOnPlace5 = "_adsVariable_MagazinPlace5";
private const string sChuckOnPlace6 = "_adsVariable_MagazinPlace6";
[ObservableProperty]
private Visibility magazinPlace1;
[ObservableProperty]
private Visibility magazinPlace2;
[ObservableProperty]
private Visibility magazinPlace3;
[ObservableProperty]
private Visibility magazinPlace4;
[ObservableProperty]
private Visibility magazinPlace5;
[ObservableProperty]
private Visibility magazinPlace6;
public ChuckMagazinPageVM()
{
}
public ChuckMagazinPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
_adsManager.Register(sChuckOnPlace1, ChuckOnPlace1Changed);
_adsManager.Register(sChuckOnPlace2, ChuckOnPlace2Changed);
_adsManager.Register(sChuckOnPlace3, ChuckOnPlace3Changed);
_adsManager.Register(sChuckOnPlace4, ChuckOnPlace4Changed);
_adsManager.Register(sChuckOnPlace5, ChuckOnPlace5Changed);
_adsManager.Register(sChuckOnPlace6, ChuckOnPlace6Changed);
}
private void ChuckOnPlace1Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace1 = Visibility.Visible;
}
else
{
MagazinPlace1 = Visibility.Hidden;
}
}
private void ChuckOnPlace2Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace2 = Visibility.Visible;
}
else
{
MagazinPlace2 = Visibility.Hidden;
}
}
private void ChuckOnPlace3Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace3 = Visibility.Visible;
}
else
{
MagazinPlace3 = Visibility.Hidden;
}
}
private void ChuckOnPlace4Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace4 = Visibility.Visible;
}
else
{
MagazinPlace4 = Visibility.Hidden;
}
}
private void ChuckOnPlace5Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace5 = Visibility.Visible;
}
else
{
MagazinPlace5 = Visibility.Hidden;
}
}
private void ChuckOnPlace6Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace6 = Visibility.Visible;
}
else
{
MagazinPlace6 = Visibility.Hidden;
}
}
public void Dispose()
{
_adsManager?.Deregister(sChuckOnPlace1, ChuckOnPlace1Changed);
_adsManager?.Deregister(sChuckOnPlace2, ChuckOnPlace2Changed);
_adsManager?.Deregister(sChuckOnPlace3, ChuckOnPlace3Changed);
_adsManager?.Deregister(sChuckOnPlace4, ChuckOnPlace4Changed);
_adsManager?.Deregister(sChuckOnPlace5, ChuckOnPlace5Changed);
_adsManager?.Deregister(sChuckOnPlace6, ChuckOnPlace6Changed);
}
}
}

View File

@@ -0,0 +1,94 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class EtchingStation1PageVM : ObservableValidator, IDisposable
{
[ObservableProperty] private BinaryValveControlVM vacuumValveControlEtching1Vm;
[ObservableProperty] private BinaryValveControlVM doorValveControlEtching1Vm;
[ObservableProperty] private BinaryValveControlVM chuckUnlockValveLeftEtching1Vm;
[ObservableProperty] private BinaryValveControlVM chuckUnlockValveRightEtching1Vm;
[ObservableProperty] private BinaryValveControlVM chuckEjectValveFrontEtching1Vm;
[ObservableProperty] private BinaryValveControlVM chuckEjectValveBackEtching1Vm;
[ObservableProperty] private HMIControlButtonVM? chuckUnlockCmdButtonEtching1Vm;
[ObservableProperty] private HMIControlButtonVM? chuckLockCmdButtonEtching1Vm;
[ObservableProperty] private HMIControlButtonVM? chuckEjectCmdButtonEtching1Vm;
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
public EtchingStation1PageVM()
{
VacuumValveControlEtching1Vm = new BinaryValveControlVM();
DoorValveControlEtching1Vm = new BinaryValveControlVM();
ChuckUnlockValveLeftEtching1Vm = new BinaryValveControlVM();
ChuckUnlockValveRightEtching1Vm = new BinaryValveControlVM();
ChuckEjectValveFrontEtching1Vm = new BinaryValveControlVM();
ChuckEjectValveBackEtching1Vm = new BinaryValveControlVM();
ChuckUnlockCmdButtonEtching1Vm = new HMIControlButtonVM();
ChuckLockCmdButtonEtching1Vm = new HMIControlButtonVM();
ChuckEjectCmdButtonEtching1Vm = new HMIControlButtonVM();
}
public EtchingStation1PageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
VacuumValveControlEtching1Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stVacuumValve");
DoorValveControlEtching1Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stDoorValve");
ChuckUnlockValveLeftEtching1Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckUnlockLeft");
ChuckUnlockValveRightEtching1Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckUnlockRight");
ChuckEjectValveFrontEtching1Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckEjectFront");
ChuckEjectValveBackEtching1Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckEjectBack");
ChuckUnlockCmdButtonEtching1Vm = new HMIControlButtonVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckUnlockCmd");
ChuckLockCmdButtonEtching1Vm = new HMIControlButtonVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckLockCmd");
ChuckEjectCmdButtonEtching1Vm = new HMIControlButtonVM(_adsManager, "GVL_SCADA.stMachine.stEtcher1.stChuckEjectCmd");
}
public void Dispose()
{
VacuumValveControlEtching1Vm.Dispose();
DoorValveControlEtching1Vm.Dispose();
ChuckUnlockValveLeftEtching1Vm.Dispose();
ChuckUnlockValveRightEtching1Vm.Dispose();
ChuckEjectValveFrontEtching1Vm.Dispose();
ChuckEjectValveBackEtching1Vm.Dispose();
ChuckUnlockCmdButtonEtching1Vm?.Dispose();
ChuckUnlockCmdButtonEtching1Vm = null;
ChuckLockCmdButtonEtching1Vm?.Dispose();
ChuckLockCmdButtonEtching1Vm = null;
ChuckLockCmdButtonEtching1Vm?.Dispose();
ChuckEjectCmdButtonEtching1Vm = null;
}
}
}

View File

@@ -0,0 +1,92 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class EtchingStation2PageVM : ObservableValidator, IDisposable
{
[ObservableProperty] private BinaryValveControlVM vacuumValveControlEtching2Vm;
[ObservableProperty] private BinaryValveControlVM doorValveControlEtching2Vm;
[ObservableProperty] private BinaryValveControlVM chuckUnlockValveLeftEtching2Vm;
[ObservableProperty] private BinaryValveControlVM chuckUnlockValveRightEtching2Vm;
[ObservableProperty] private BinaryValveControlVM chuckEjectValveFrontEtching2Vm;
[ObservableProperty] private BinaryValveControlVM chuckEjectValveBackEtching2Vm;
[ObservableProperty] private HMIControlButtonVM? chuckUnlockCmdButtonEtching2Vm;
[ObservableProperty] private HMIControlButtonVM? chuckLockCmdButtonEtching2Vm;
[ObservableProperty] private HMIControlButtonVM? chuckEjectCmdButtonEtching2Vm;
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
public EtchingStation2PageVM()
{
VacuumValveControlEtching2Vm = new BinaryValveControlVM();
DoorValveControlEtching2Vm = new BinaryValveControlVM();
ChuckUnlockValveLeftEtching2Vm = new BinaryValveControlVM();
ChuckUnlockValveRightEtching2Vm = new BinaryValveControlVM();
ChuckEjectValveFrontEtching2Vm = new BinaryValveControlVM();
ChuckEjectValveBackEtching2Vm = new BinaryValveControlVM();
ChuckUnlockCmdButtonEtching2Vm = new HMIControlButtonVM();
ChuckLockCmdButtonEtching2Vm = new HMIControlButtonVM();
ChuckEjectCmdButtonEtching2Vm = new HMIControlButtonVM();
}
public EtchingStation2PageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
VacuumValveControlEtching2Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stVacuumValve");
DoorValveControlEtching2Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stDoorValve");
ChuckUnlockValveLeftEtching2Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckUnlockLeft");
ChuckUnlockValveRightEtching2Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckUnlockRight");
ChuckEjectValveFrontEtching2Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckEjectFront");
ChuckEjectValveBackEtching2Vm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckEjectBack");
ChuckUnlockCmdButtonEtching2Vm = new HMIControlButtonVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckUnlockCmd");
ChuckLockCmdButtonEtching2Vm = new HMIControlButtonVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckLockCmd");
ChuckEjectCmdButtonEtching2Vm = new HMIControlButtonVM(_adsManager, "GVL_SCADA.stMachine.stEtcher2.stChuckEjectCmd");
}
public void Dispose()
{
VacuumValveControlEtching2Vm.Dispose();
DoorValveControlEtching2Vm.Dispose();
ChuckUnlockValveLeftEtching2Vm.Dispose();
ChuckUnlockValveRightEtching2Vm.Dispose();
ChuckEjectValveFrontEtching2Vm.Dispose();
ChuckEjectValveBackEtching2Vm.Dispose();
ChuckUnlockCmdButtonEtching2Vm?.Dispose();
ChuckUnlockCmdButtonEtching2Vm = null;
ChuckLockCmdButtonEtching2Vm?.Dispose();
ChuckLockCmdButtonEtching2Vm = null;
ChuckLockCmdButtonEtching2Vm?.Dispose();
ChuckEjectCmdButtonEtching2Vm = null;
}
}
}

View File

@@ -0,0 +1,123 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using UniperHMI.Model;
namespace UniperHMI
{
public sealed partial class EtchingStationPageVM : ObservableValidator, IDisposable
{
private int _setpoint;
[Range(-40000, 40000)]
public int Setpoint
{
get => this._setpoint;
set => SetProperty(ref this._setpoint, value, true);
}
[ObservableProperty]
private int processValue;
[ObservableProperty]
public HMIControlButtonVM? startButton;
[ObservableProperty]
public HMIControlButtonVM? stopButton;
[ObservableProperty]
private E_BMS_CONTROL_MODE bmsControlMode;
[ObservableProperty]
public ObservableCollection<BMSControlModeEntry> reqBMSControlModes =
[
new BMSControlModeEntry(E_BMS_CONTROL_MODE.AUTO_REMOTE, "Auto Remote"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.AUTO_LOCAL, "Auto Local"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.SAFETY_CHECK, "Safety Check"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.CAPACITY_TEST, "Capacity Test"),
new BMSControlModeEntry(E_BMS_CONTROL_MODE.MANUAL, "Manual")
];
[ObservableProperty]
private BMSControlModeEntry selectedControlMode;
[ObservableProperty]
private bool canChangeControlMode;
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
public EtchingStationPageVM()
{
StartButton = new HMIControlButtonVM();
StopButton = new HMIControlButtonVM();
SelectedControlMode = ReqBMSControlModes[1];
canChangeControlMode = true;
}
public EtchingStationPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
//StartButton = new HMIControlButtonVM(_adsManager, _variableName + ".stStartAutoButton");
//StopButton = new HMIControlButtonVM(_adsManager, _variableName + ".stStopAutoButton");
SelectedControlMode = ReqBMSControlModes[1];
_adsManager.Register("GVL_SCADA.xCanChangeControlMode", CCCMChanged);
_adsManager.Register(_variableName + ".diSetpointAutomatic", SetpointChanged);
}
private void SetpointChanged(object? sender, ValueChangedEventArgs e)
{
Setpoint = (int)e.Value;
}
private void CCCMChanged(object? sender, ValueChangedEventArgs e)
{
CanChangeControlMode = (bool)e.Value;
}
public void Dispose()
{
StartButton?.Dispose();
StartButton = null;
StopButton?.Dispose();
StopButton = null;
_adsManager?.Deregister("GVL_SCADA.xCanChangeControlMode", CCCMChanged);
_adsManager?.Deregister(_variableName + ".diSetpointAutomatic", SetpointChanged);
}
[RelayCommand]
private void StartAutomatic()
{
_adsManager?.WriteValue(_variableName + ".diSetpointAutomatic", Setpoint);
}
[RelayCommand]
private void StopAutomatic()
{
_adsManager?.WriteValue(_variableName + ".diSetpointAutomatic", 0);
Setpoint = 0;
}
public static ValidationResult ValidatePower(int power, ValidationContext context)
{
if (power < -40000 || power > 40000)
return new("Must be between -40.000 and +40.000");
else
return ValidationResult.Success!;
}
}
}

View File

@@ -0,0 +1,114 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows;
using TcEventLoggerAdsProxyLib;
namespace InfineonHMI
{
public partial class EventData : ObservableObject
{
[ObservableProperty]
public uint id;
[ObservableProperty]
public string? message;
[ObservableProperty]
public DateTime raised;
[ObservableProperty]
public DateTime cleared;
[ObservableProperty]
public DateTime confirmed;
};
public sealed partial class EventsPageVM : ObservableObject
{
public ObservableCollection<EventData> CurrentEvents { get; private set; } = [];
private readonly object _lock = new();
private readonly TcEventLogger _logger;
[ObservableProperty]
private EventData? currentEvent;
// 599264352000000000 ticks is a date used by beckhoff for events that didnt happen up to this point
private const long NoTime = 599264352000000000;
public EventsPageVM(TcEventLogger logger)
{
_logger = logger;
_logger.AlarmRaised += SimpleAlarmRaisedEvent;
_logger.AlarmCleared += SimpleAlarmClearedEvent;
_logger.AlarmConfirmed += SimpleConfirmedAlarmEvent;
#if DEBUG
#else
_logger.Connect("10.103.32.50.1.1");
#endif
GetAllActiveEvents();
}
private void RebuildCurrentEventsList()
{
lock (_lock)
{
CurrentEvents.Clear();
}
GetAllActiveEvents();
}
private void SimpleConfirmedAlarmEvent(TcAlarm alarm, bool remove)
{
Application.Current.Dispatcher.BeginInvoke(RebuildCurrentEventsList);
}
private void SimpleAlarmClearedEvent(TcAlarm alarm, bool remove)
{
Application.Current.Dispatcher.BeginInvoke(RebuildCurrentEventsList);
}
private void SimpleAlarmRaisedEvent(TcAlarm alarm)
{
Application.Current.Dispatcher.BeginInvoke(RebuildCurrentEventsList);
}
private void GetAllActiveEvents()
{
EventData eventData;
List<EventData> tempEventList = [];
lock (_lock)
{
foreach (var alarm in _logger.ActiveAlarms)
{
eventData = new()
{
Id = alarm.EventId,
Message = alarm.GetText(1033),
Raised = alarm.TimeRaised,
Cleared = alarm.TimeCleared,
Confirmed = alarm.TimeConfirmed
};
tempEventList.Add(eventData);
}
IEnumerable<EventData> _eventQuery =
from data in tempEventList
orderby data.Raised descending
select data;
CurrentEvent = _eventQuery.FirstOrDefault();
CurrentEvents = new ObservableCollection<EventData>(_eventQuery);
}
}
}
}

View File

@@ -0,0 +1,72 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class HighVoltageStationPageVM : ObservableValidator, IDisposable
{
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
[ObservableProperty]
private BinaryValveControlVM doorValveHotControlVm;
[ObservableProperty]
private BinaryValveControlVM testChamberHotValveVm;
[ObservableProperty]
private AnalogValueVM tempSPHotVm;
[ObservableProperty]
private BinaryValveControlVM doorValveColdControlVm;
[ObservableProperty]
private BinaryValveControlVM testChamberColdValveVm;
[ObservableProperty]
private AnalogValueVM tempSPColdVm;
public HighVoltageStationPageVM()
{
DoorValveHotControlVm = new BinaryValveControlVM();
TestChamberHotValveVm = new BinaryValveControlVM();
TempSPHotVm = new AnalogValueVM();
DoorValveColdControlVm = new BinaryValveControlVM();
TestChamberColdValveVm = new BinaryValveControlVM();
TempSPColdVm = new AnalogValueVM();
}
public HighVoltageStationPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
DoorValveHotControlVm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stHVTesterHot.stDoorValve");
TestChamberHotValveVm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stHVTesterHot.stTestChamberValve");
TempSPHotVm = new AnalogValueVM(_adsManager, "GVL_SCADA.stMachine.stHVTesterHot.stTempSP", false);
DoorValveColdControlVm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stHVTesterCold.stDoorValve");
TestChamberColdValveVm = new BinaryValveControlVM(_adsManager, "GVL_SCADA.stMachine.stHVTesterCold.stTestChamberValve");
TempSPColdVm = new AnalogValueVM(_adsManager, "GVL_SCADA.stMachine.stHVTesterCold.stTempSP", false);
}
public void Dispose()
{
DoorValveHotControlVm.Dispose();
TestChamberHotValveVm.Dispose();
TempSPHotVm.Dispose();
DoorValveColdControlVm.Dispose();
TestChamberColdValveVm.Dispose();
TempSPColdVm.Dispose();
}
}
}

View File

@@ -0,0 +1,408 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
using System.Windows;
namespace InfineonHMI
{
public sealed partial class HotCoolPlatePageVM : ObservableValidator, IDisposable
{
private const string sPieceOnHotplate1 = ".stHotplate.stPiece1";
private const string sPieceOnHotplate2 = ".stHotplate.stPiece2";
private const string sPieceOnHotplate3 = ".stHotplate.stPiece3";
private const string sPieceOnHotplate4 = ".stHotplate.stPiece4";
private const string sPieceOnHotplate5 = ".stHotplate.stPiece5";
private const string sPieceOnHotplate6 = ".stHotplate.stPiece6";
private const string sPieceOnHotplate7 = ".stHotplate.stPiece7";
private const string sPieceOnHotplate8 = ".stHotplate.stPiece8";
private const string sPieceOnHotplate9 = ".stHotplate.stPiece9";
private const string sPieceOnCoolplate1 = ".stCoolplate.stPiece1";
private const string sPieceOnCoolplate2 = ".stCoolplate.stPiece2";
private const string sPieceOnCoolplate3 = ".stCoolplate.stPiece3";
private const string sPieceOnCoolplate4 = ".stCoolplate.stPiece4";
private const string sPieceOnCoolplate5 = ".stCoolplate.stPiece5";
private const string sPieceOnCoolplate6 = ".stCoolplate.stPiece6";
private const string sPieceOnCoolplate7 = ".stCoolplate.stPiece7";
private const string sPieceOnCoolplate8 = ".stCoolplate.stPiece8";
private const string sPieceOnCoolplate9 = ".stCoolplate.stPiece9";
private readonly IAdsManager? _adsManager;
private readonly string? _variableName;
[ObservableProperty]
private AnalogValueVM hotPlateTargetTemperature;
[ObservableProperty]
private AnalogValueVM hotPlateActualTemperature;
[ObservableProperty] private HMIControlButtonVM? enableHotPlateButtonVm;
[ObservableProperty] private HMIControlButtonVM? disableHotPlateButtonVm;
[ObservableProperty]
private AnalogValueVM coolPlateTargetTemperature;
[ObservableProperty]
private AnalogValueVM coolPlateActualTemperature;
[ObservableProperty] private HMIControlButtonVM? enableCoolPlateButtonVm;
[ObservableProperty] private HMIControlButtonVM? disableCoolPlateButtonVm;
[ObservableProperty]
private Visibility hotPlateVisibility1;
[ObservableProperty]
private Visibility hotPlateVisibility2;
[ObservableProperty]
private Visibility hotPlateVisibility3;
[ObservableProperty]
private Visibility hotPlateVisibility4;
[ObservableProperty]
private Visibility hotPlateVisibility5;
[ObservableProperty]
private Visibility hotPlateVisibility6;
[ObservableProperty]
private Visibility hotPlateVisibility7;
[ObservableProperty]
private Visibility hotPlateVisibility8;
[ObservableProperty]
private Visibility hotPlateVisibility9;
[ObservableProperty]
private Visibility coolPlateVisibility1;
[ObservableProperty]
private Visibility coolPlateVisibility2;
[ObservableProperty]
private Visibility coolPlateVisibility3;
[ObservableProperty]
private Visibility coolPlateVisibility4;
[ObservableProperty]
private Visibility coolPlateVisibility5;
[ObservableProperty]
private Visibility coolPlateVisibility6;
[ObservableProperty]
private Visibility coolPlateVisibility7;
[ObservableProperty]
private Visibility coolPlateVisibility8;
[ObservableProperty]
private Visibility coolPlateVisibility9;
public HotCoolPlatePageVM()
{
EnableHotPlateButtonVm = new HMIControlButtonVM();
DisableHotPlateButtonVm = new HMIControlButtonVM();
EnableCoolPlateButtonVm = new HMIControlButtonVM();
DisableCoolPlateButtonVm = new HMIControlButtonVM();
HotPlateActualTemperature = new AnalogValueVM();
HotPlateTargetTemperature = new AnalogValueVM();
CoolPlateActualTemperature = new AnalogValueVM();
CoolPlateTargetTemperature = new AnalogValueVM();
}
public HotCoolPlatePageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
EnableHotPlateButtonVm = new HMIControlButtonVM(_adsManager, _variableName + ".stHotplate.stEnableBtn");
DisableHotPlateButtonVm = new HMIControlButtonVM(_adsManager, _variableName + ".stHotplate.stDisableBtn");
EnableCoolPlateButtonVm = new HMIControlButtonVM(_adsManager, _variableName + ".stCoolplate.stEnableBtn");
DisableCoolPlateButtonVm = new HMIControlButtonVM(_adsManager, _variableName + ".stCoolplate.stDisableBtn");
HotPlateActualTemperature = new AnalogValueVM(_adsManager, "GVL_SCADA.stMachine.stHotplate.stPV", true);
CoolPlateActualTemperature = new AnalogValueVM(_adsManager, "GVL_SCADA.stMachine.stCoolplate.stPV", true);
HotPlateTargetTemperature = new AnalogValueVM(_adsManager, "GVL_SCADA.stMachine.stHotplate.stSetpoint", false);
CoolPlateTargetTemperature = new AnalogValueVM(_adsManager, "GVL_SCADA.stMachine.stCoolplate.stSetpoint", false);
_adsManager.Register(sPieceOnHotplate1, HotplatePiece1Changed);
_adsManager.Register(sPieceOnHotplate2, HotplatePiece2Changed);
_adsManager.Register(sPieceOnHotplate3, HotplatePiece3Changed);
_adsManager.Register(sPieceOnHotplate4, HotplatePiece4Changed);
_adsManager.Register(sPieceOnHotplate5, HotplatePiece5Changed);
_adsManager.Register(sPieceOnHotplate6, HotplatePiece6Changed);
_adsManager.Register(sPieceOnHotplate7, HotplatePiece7Changed);
_adsManager.Register(sPieceOnHotplate8, HotplatePiece8Changed);
_adsManager.Register(sPieceOnHotplate9, HotplatePiece9Changed);
_adsManager.Register(sPieceOnCoolplate1, CoolplatePiece1Changed);
_adsManager.Register(sPieceOnCoolplate2, CoolplatePiece2Changed);
_adsManager.Register(sPieceOnCoolplate3, CoolplatePiece3Changed);
_adsManager.Register(sPieceOnCoolplate4, CoolplatePiece4Changed);
_adsManager.Register(sPieceOnCoolplate5, CoolplatePiece5Changed);
_adsManager.Register(sPieceOnCoolplate6, CoolplatePiece6Changed);
_adsManager.Register(sPieceOnCoolplate7, CoolplatePiece7Changed);
_adsManager.Register(sPieceOnCoolplate8, CoolplatePiece8Changed);
_adsManager.Register(sPieceOnCoolplate9, CoolplatePiece9Changed);
}
private void HotplatePiece1Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility1 = Visibility.Visible;
}
else
{
HotPlateVisibility1 = Visibility.Hidden;
}
}
private void HotplatePiece2Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility2 = Visibility.Visible;
}
else
{
HotPlateVisibility2 = Visibility.Hidden;
}
}
private void HotplatePiece3Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility3 = Visibility.Visible;
}
else
{
HotPlateVisibility3 = Visibility.Hidden;
}
}
private void HotplatePiece4Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility4 = Visibility.Visible;
}
else
{
HotPlateVisibility4 = Visibility.Hidden;
}
}
private void HotplatePiece5Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility5 = Visibility.Visible;
}
else
{
HotPlateVisibility5 = Visibility.Hidden;
}
}
private void HotplatePiece6Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility6 = Visibility.Visible;
}
else
{
HotPlateVisibility6 = Visibility.Hidden;
}
}
private void HotplatePiece7Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility7 = Visibility.Visible;
}
else
{
HotPlateVisibility7 = Visibility.Hidden;
}
}
private void HotplatePiece8Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility8 = Visibility.Visible;
}
else
{
HotPlateVisibility8 = Visibility.Hidden;
}
}
private void HotplatePiece9Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
HotPlateVisibility9 = Visibility.Visible;
}
else
{
HotPlateVisibility9 = Visibility.Hidden;
}
}
private void CoolplatePiece1Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility1 = Visibility.Visible;
}
else
{
CoolPlateVisibility1 = Visibility.Hidden;
}
}
private void CoolplatePiece2Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility2 = Visibility.Visible;
}
else
{
CoolPlateVisibility2 = Visibility.Hidden;
}
}
private void CoolplatePiece3Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility3 = Visibility.Visible;
}
else
{
CoolPlateVisibility3 = Visibility.Hidden;
}
}
private void CoolplatePiece4Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility4 = Visibility.Visible;
}
else
{
CoolPlateVisibility4 = Visibility.Hidden;
}
}
private void CoolplatePiece5Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility5 = Visibility.Visible;
}
else
{
CoolPlateVisibility5 = Visibility.Hidden;
}
}
private void CoolplatePiece6Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility6 = Visibility.Visible;
}
else
{
CoolPlateVisibility6 = Visibility.Hidden;
}
}
private void CoolplatePiece7Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility7 = Visibility.Visible;
}
else
{
CoolPlateVisibility7 = Visibility.Hidden;
}
}
private void CoolplatePiece8Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility8 = Visibility.Visible;
}
else
{
CoolPlateVisibility8 = Visibility.Hidden;
}
}
private void CoolplatePiece9Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
CoolPlateVisibility9 = Visibility.Visible;
}
else
{
CoolPlateVisibility9 = Visibility.Hidden;
}
}
public void Dispose()
{
HotPlateActualTemperature.Dispose();
HotPlateTargetTemperature.Dispose();
CoolPlateActualTemperature.Dispose();
CoolPlateTargetTemperature.Dispose();
EnableCoolPlateButtonVm?.Dispose();
EnableCoolPlateButtonVm = null;
EnableHotPlateButtonVm?.Dispose();
EnableHotPlateButtonVm = null;
DisableCoolPlateButtonVm?.Dispose();
DisableCoolPlateButtonVm = null;
DisableHotPlateButtonVm?.Dispose();
DisableHotPlateButtonVm = null;
_adsManager?.Deregister(sPieceOnHotplate1, HotplatePiece1Changed);
_adsManager?.Deregister(sPieceOnHotplate2, HotplatePiece2Changed);
_adsManager?.Deregister(sPieceOnHotplate3, HotplatePiece3Changed);
_adsManager?.Deregister(sPieceOnHotplate4, HotplatePiece4Changed);
_adsManager?.Deregister(sPieceOnHotplate5, HotplatePiece5Changed);
_adsManager?.Deregister(sPieceOnHotplate6, HotplatePiece6Changed);
_adsManager?.Deregister(sPieceOnHotplate7, HotplatePiece7Changed);
_adsManager?.Deregister(sPieceOnHotplate8, HotplatePiece8Changed);
_adsManager?.Deregister(sPieceOnHotplate9, HotplatePiece9Changed);
_adsManager?.Deregister(sPieceOnCoolplate1, CoolplatePiece1Changed);
_adsManager?.Deregister(sPieceOnCoolplate2, CoolplatePiece2Changed);
_adsManager?.Deregister(sPieceOnCoolplate3, CoolplatePiece3Changed);
_adsManager?.Deregister(sPieceOnCoolplate4, CoolplatePiece4Changed);
_adsManager?.Deregister(sPieceOnCoolplate5, CoolplatePiece5Changed);
_adsManager?.Deregister(sPieceOnCoolplate6, CoolplatePiece6Changed);
_adsManager?.Deregister(sPieceOnCoolplate7, CoolplatePiece7Changed);
_adsManager?.Deregister(sPieceOnCoolplate8, CoolplatePiece8Changed);
_adsManager?.Deregister(sPieceOnCoolplate9, CoolplatePiece9Changed);
}
}
}

View File

@@ -0,0 +1,677 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using System.Security.Policy;
using System.Printing;
using System.Windows;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class KukaRobotPageVM : ObservableValidator, IDisposable
{
private readonly string? _variableName = "_adsVariable_";
private const string sStartRobotJob = "_adsVariable_kukaStartRobotJob";
private const string sAbortRobotJob = "_adsVariable_kukaAbortRobotJob";
private const string sResetState = "_adsVariable_kukaResetState";
private const string sClearState = "_adsVariable_kukaClearState";
private const string sAcknPLCJob = "_adsVariable_kukaAcknPLCJob";
private const string sCoolplateIndex = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.byPlaceOnCoolPlate";
private const string sHotplateIndex = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.byPlaceOnHotPlate";
private const string sPieceThickness = "_adsVariable_kukaPieceThickness";
private const string sJobGrippSide = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.byGripperNumber";
private const string sJobGrippType = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.byGripperNumber";
private const string sChuckMagazinPlace = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.byChuckNumber";
private const string sSelectedRobotJob = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.eJob";
private const string sActiveRobotJob = "_adsVariable_kukaActiveRobotJob";
private const string sFinishedRobotJob = "_adsVariable_kukaFinishedRobotJob";
private const string sSelectedPLCJob = "_adsVariable_kukaPLCJob";
private const string sOffsetPick_X = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosX";
private const string sOffsetPick_Y = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosY";
private const string sOffsetPlace_X = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosX";
private const string sOffsetPlace_Y = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosY";
private const string sOffsetNIOPick_X = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosX";
private const string sOffsetNIOPick_Y = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosY";
private const string sOffsetNIOPlace_X = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosX";
private const string sOffsetNIOPlace_Y = "GVL_SCADA.stMachine.stKukaRobot.stJobParams.rPosY";
private BMSControlModeEntry currentControlMode;
public BMSControlModeEntry CurrentControlMode
{
get { return currentControlMode; }
set
{
currentControlMode = value;
ccmChanged();
}
}
private E_BMS_CONTROL_MODE bmsControlMode;
[ObservableProperty]
private bool canChangeRobotJob;
[ObservableProperty]
private RobotJobentry robotJobActiveValue;
[ObservableProperty]
private RobotJobentry robotJobFinishedValue;
[ObservableProperty]
private bool canStartRobotJob;
[ObservableProperty]
private HMIControlButtonVM? startButton;
[ObservableProperty]
private bool canAbortRobotJob;
[ObservableProperty]
private HMIControlButtonVM? abortButton;
private const string sChuckOnPlace1 = "_adsVariable_MagazinPlace1";
private const string sChuckOnPlace2 = "_adsVariable_MagazinPlace2";
private const string sChuckOnPlace3 = "_adsVariable_MagazinPlace3";
private const string sChuckOnPlace4 = "_adsVariable_MagazinPlace4";
private const string sChuckOnPlace5 = "_adsVariable_MagazinPlace5";
private const string sChuckOnPlace6 = "_adsVariable_MagazinPlace6";
[ObservableProperty]
private Visibility magazinPlace1;
[ObservableProperty]
private Visibility magazinPlace2;
[ObservableProperty]
private Visibility magazinPlace3;
[ObservableProperty]
private Visibility magazinPlace4;
[ObservableProperty]
private Visibility magazinPlace5;
[ObservableProperty]
private Visibility magazinPlace6;
private int jobGrippSide;
public int JobGrippSide
{
get { return jobGrippSide; }
set
{
SetProperty(ref jobGrippSide, value);
_adsManager?.WriteValue(sJobGrippSide, value);
}
}
[ObservableProperty]
private bool canChangeJobGrippSide;
private int jobGrippType;
public int JobGrippType
{
get { return jobGrippType; }
set
{
SetProperty(ref jobGrippType, value);
_adsManager?.WriteValue(sJobGrippType, value);
}
}
[ObservableProperty]
private bool canChangeJobGrippType;
private int chuckMagazinPlace;
public int ChuckMagazinPlace
{
get { return chuckMagazinPlace; }
set
{
SetProperty(ref chuckMagazinPlace, value);
_adsManager?.WriteValue(sChuckMagazinPlace, value);
}
}
[ObservableProperty]
private bool canChangeChuckMagazinPlace;
private double pieceThickness;
public double PieceThickness
{
get { return pieceThickness; }
set
{
SetProperty(ref pieceThickness, value);
_adsManager?.WriteValue(sPieceThickness, value);
}
}
[ObservableProperty]
private bool canChangePieceThickness;
private double offsetPick_X;
public double OffsetPick_X
{
get { return offsetPick_X; }
set
{
SetProperty(ref offsetPick_X, value);
_adsManager?.WriteValue(sOffsetPick_X, value);
}
}
private double offsetPick_Y;
public double OffsetPick_Y
{
get { return offsetPick_Y; }
set
{
SetProperty(ref offsetPick_Y, value);
_adsManager?.WriteValue(sOffsetPick_Y, value);
}
}
[ObservableProperty]
private bool canChangeOffsetPick;
private double offsetPlace_X;
public double OffsetPlace_X
{
get { return offsetPlace_X; }
set
{
SetProperty(ref offsetPlace_X, value);
_adsManager?.WriteValue(sOffsetPlace_X, value);
}
}
private double offsetPlace_Y;
public double OffsetPlace_Y
{
get { return offsetPlace_Y; }
set
{
SetProperty(ref offsetPlace_Y, value);
_adsManager?.WriteValue(sOffsetPlace_Y, value);
}
}
[ObservableProperty]
private bool canChangeOffsetPlace;
private double offsetNIOPick_X;
public double OffsetNIOPick_X
{
get { return offsetNIOPick_X; }
set
{
SetProperty(ref offsetNIOPick_X, value);
_adsManager?.WriteValue(sOffsetNIOPick_X, value);
}
}
private double offsetNIOPick_Y;
public double OffsetNIOPick_Y
{
get { return offsetNIOPick_Y; }
set
{
SetProperty(ref offsetNIOPick_Y, value);
_adsManager?.WriteValue(sOffsetNIOPick_Y, value);
}
}
[ObservableProperty]
private bool canChangeOffsetNIOPick;
private double offsetNIOPlace_X;
public double OffsetNIOPlace_X
{
get { return offsetNIOPlace_X; }
set
{
SetProperty(ref offsetNIOPlace_X, value);
_adsManager?.WriteValue(sOffsetNIOPlace_X, value);
}
}
private double offsetNIOPlace_Y;
public double OffsetNIOPlace_Y
{
get { return offsetNIOPlace_Y; }
set
{
SetProperty(ref offsetNIOPlace_Y, value);
_adsManager?.WriteValue(sOffsetNIOPlace_Y, value);
}
}
[ObservableProperty]
private bool canChangeOffsetNIOPlace;
private int hotplateIndex;
public int HotplateIndex
{
get { return hotplateIndex; }
set
{
SetProperty(ref hotplateIndex, value);
_adsManager?.WriteValue(sHotplateIndex, value);
}
}
[ObservableProperty]
private bool canChangeHotPlateIndex;
private int coolplateIndex;
public int CoolplateIndex
{
get { return coolplateIndex; }
set
{
SetProperty(ref coolplateIndex, value);
_adsManager?.WriteValue(sCoolplateIndex, value);
}
}
[ObservableProperty]
private bool canChangeCoolPlateIndex;
[ObservableProperty]
private RobotJobenum robotJob;
[ObservableProperty]
private ObservableCollection<RobotJobentry> robotJobs =
[
new RobotJobentry(RobotJobenum.NONE, " ------- "),
new RobotJobentry(RobotJobenum.PICK_TRAYFEEDER, "10 - Hole Teil von Trayfeeder 'Eingabe' "),
new RobotJobentry(RobotJobenum.PLACE_TRAYFEEDER, "11 - Lege Teil in Trayfeeder 'Ausgabe' "),
new RobotJobentry(RobotJobenum.PUT_ALIGNMENT, "15 - Lege Teil auf Ausrichtstation"),
new RobotJobentry(RobotJobenum.PICK_ALIGNMENT, "16 - Hole Teil von Ausrichtstation"),
new RobotJobentry(RobotJobenum.PUT_ETCHER_1, "20 - Lege Teil in Ätzer 1"),
new RobotJobentry(RobotJobenum.PUT_ETCHER_2, "21 - Lege Teil in Ätzer 2"),
new RobotJobentry(RobotJobenum.PICK_ETCHER_1, "22 - Hole Teil aus Ätzer 1"),
new RobotJobentry(RobotJobenum.PICK_ETCHER_2, "23 - Hole Teil aus Ätzer 2"),
new RobotJobentry(RobotJobenum.SWITCH_ETCHER_1, "24 - Tausche Teile in Ätzer 1"),
new RobotJobentry(RobotJobenum.SWITCH_ETCHER_2, "25 - Tausche Teile in Ätzer 2"),
new RobotJobentry(RobotJobenum.PUT_HVTEST_HOT, "30 - Lege Teil in HV-Teststation Warm"),
new RobotJobentry(RobotJobenum.PUT_HVTEST_COLD, "31 - Lege Teil in HV-Teststation Kalt"),
new RobotJobentry(RobotJobenum.PICK_HVTEST_HOT, "32 - Hole Teil aus HV-Teststation Warm"),
new RobotJobentry(RobotJobenum.PICK_HVTEST_COLD, "33 - Hole Teil aus HV-Teststation Kalt"),
new RobotJobentry(RobotJobenum.PUT_HOTPLATE, "40 - Lege Teil auf Heizplatte"),
new RobotJobentry(RobotJobenum.PICK_HOTPLATE, "41 - Hole Teil von Heizplatte"),
new RobotJobentry(RobotJobenum.PUT_COOLPLATE, "42 - Lege Teil auf Kühlplatte"),
new RobotJobentry(RobotJobenum.PICK_COOLPLATE, "43 - Hole Teil von Kühlplatte"),
new RobotJobentry(RobotJobenum.PICK_GRIPPER, "50 - Hole anderen Greifertyp"),
new RobotJobentry(RobotJobenum.PICK_CHUCK_ETCHER_1, "60 - Hole Drehteller aus Ätzer 1"),
new RobotJobentry(RobotJobenum.PICK_CHUCK_ETCHER_2, "61 - Hole Drehteller aus Ätzer 2"),
new RobotJobentry(RobotJobenum.PUT_CHUCK_ETCHER_1, "62 - Lege Drehteller in Ätzer 1"),
new RobotJobentry(RobotJobenum.PUT_CHUCK_ETCHER_2, "63 - Lege Drehteller in Ätzer 2"),
new RobotJobentry(RobotJobenum.PUT_CHUCK_MAGAZIN, "64 - Lege Drehteller in Magazin"),
new RobotJobentry(RobotJobenum.PICK_CHUCK_MAGAZIN, "65 - Hole Drehteller von Magazin"),
new RobotJobentry(RobotJobenum.PUT_NIO_STATION, "70 - Lege Teil auf NIO-TRAY"),
new RobotJobentry(RobotJobenum.PICK_NIO_STATION, "71 - Hole Teil von NIO-TRAY"),
new RobotJobentry(RobotJobenum.WARMUP, "80 - Aufwärmprogramm")
];
[ObservableProperty]
private ObservableCollection<PLCJobentry> pLCJobs =
[
new PLCJobentry(PLCJobenum.NONE, " ------- "),
new PLCJobentry(PLCJobenum.SCAN_QR_CODE, "10 - QR Code Scannen"),
new PLCJobentry(PLCJobenum.VACUUM_ON_ALIGNER, "15 - Vakuum Ausrichtstation einschalten"),
new PLCJobentry(PLCJobenum.VACUUM_OFF_ALIGNER, "16 - Vakuum Ausrichtstation ausschalten"),
new PLCJobentry(PLCJobenum.VACUUM_ON_ETCHER_1, "20 - Vakuum Ätzer 1 einschalten"),
new PLCJobentry(PLCJobenum.VACUUM_ON_ETCHER_2, "21 - Vakuum Ätzer 2 einschalten"),
new PLCJobentry(PLCJobenum.VACUUM_OFF_ETCHER_1, "22 - Vakuum Ätzer 1 ausschalten"),
new PLCJobentry(PLCJobenum.VACUUM_OFF_ETCHER_2, "23 - Vakuum Ätzer 2 ausschalten"),
new PLCJobentry(PLCJobenum.CHUCK_OPEN_ETCHER_1, "60 - Drehteller Ätzer 1 entriegeln"),
new PLCJobentry(PLCJobenum.CHUCK_OPEN_ETCHER_2, "61 - Drehteller Ätzer 2 entriegeln"),
new PLCJobentry(PLCJobenum.CHUCK_CLOSE_ETCHER_1, "62 - Drehteller Ätzer 1 verriegeln"),
new PLCJobentry(PLCJobenum.CHUCK_CLOSE_ETCHER_2, "63 - Drehteller Ätzer 2 verriegeln"),
];
private RobotJobentry selectedRobotJob;
public RobotJobentry SelectedRobotJob
{
get { return selectedRobotJob; }
set
{
SetProperty(ref selectedRobotJob, value);
CanChangeChuckMagazinPlace = (value == RobotJobs.First(i => i.eJob == RobotJobenum.PICK_CHUCK_MAGAZIN))
|| (value == RobotJobs.First(i => i.eJob == RobotJobenum.PUT_CHUCK_MAGAZIN));
CanChangeJobGrippType = value == RobotJobs.First(i => i.eJob == RobotJobenum.PICK_GRIPPER);
_adsManager?.WriteValue(sSelectedRobotJob, SelectedRobotJob.eJob);
}
}
[ObservableProperty]
private PLCJobentry selectedPLCJob;
private readonly IAdsManager? _adsManager;
public KukaRobotPageVM()
{
StartButton = new HMIControlButtonVM();
AbortButton = new HMIControlButtonVM();
selectedRobotJob = RobotJobs.First(i => i.eJob == RobotJobenum.WARMUP);
robotJobActiveValue = RobotJobs.First(i => i.eJob == RobotJobenum.PUT_HVTEST_COLD);
robotJobFinishedValue = RobotJobs.First(i => i.eJob == RobotJobenum.PICK_HOTPLATE);
selectedPLCJob = PLCJobs.First(i => i.eJob == PLCJobenum.NONE);
canChangeRobotJob = true;currentControlMode = new BMSControlModeEntry(E_BMS_CONTROL_MODE.MANUAL, "Manual");
}
public KukaRobotPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
StartButton = new HMIControlButtonVM(_adsManager, sStartRobotJob);
AbortButton = new HMIControlButtonVM(_adsManager, sAbortRobotJob);
currentControlMode = new BMSControlModeEntry(E_BMS_CONTROL_MODE.MANUAL, "Manual");
CurrentControlMode = new BMSControlModeEntry(E_BMS_CONTROL_MODE.MANUAL, "Manual");
selectedRobotJob = RobotJobs.First(i => i.eJob == RobotJobenum.NONE);
robotJobActiveValue = RobotJobs.First(i => i.eJob == RobotJobenum.NONE);
robotJobFinishedValue = RobotJobs.First(i => i.eJob == RobotJobenum.NONE);
selectedPLCJob = PLCJobs.First(i => i.eJob == PLCJobenum.NONE);
_adsManager.Register(sJobGrippSide, OnJobGrippSideValueChanged);
_adsManager.Register(sJobGrippType, OnJobGrippTypeValueChanged);
_adsManager.Register(sChuckMagazinPlace, OnChuckMagazinPlaceValueChanged);
_adsManager.Register(sPieceThickness, OnPieceThicknessValueChanged);
_adsManager.Register(sSelectedPLCJob, OnSelectedPLCJobValueChanged);
_adsManager.Register(sSelectedRobotJob, OnSelectedRobotJobValueChanged);
_adsManager.Register(sActiveRobotJob, OnActiveRobotJobValueChanged);
_adsManager.Register(sFinishedRobotJob, OnFinishedRobotJobValueChanged);
_adsManager.Register(sOffsetPick_X, OnOffsetPickXValueChanged);
_adsManager.Register(sOffsetPick_Y, OnOffsetPickYValueChanged);
_adsManager.Register(sCoolplateIndex, OnCoolPlateIndexValueChanged);
_adsManager.Register(sHotplateIndex, OnHotPlateIndexValueChanged);
_adsManager.Register(sOffsetNIOPlace_Y, OnOffsetNIOPlaceYValueChanged);
_adsManager.Register(sOffsetNIOPlace_X, OnOffsetNIOPlaceXValueChanged);
_adsManager.Register(sOffsetNIOPick_Y, OnOffsetNIOPickYValueChanged);
_adsManager.Register(sOffsetNIOPick_X, OnOffsetNIOPickXValueChanged);
_adsManager.Register(sOffsetPlace_Y, OnOffsetPlaceYValueChanged);
_adsManager.Register(sOffsetPlace_X, OnOffsetPlaceXValueChanged);
_adsManager.Register(sChuckOnPlace1, ChuckOnPlace1Changed);
_adsManager.Register(sChuckOnPlace2, ChuckOnPlace2Changed);
_adsManager.Register(sChuckOnPlace3, ChuckOnPlace3Changed);
_adsManager.Register(sChuckOnPlace4, ChuckOnPlace4Changed);
_adsManager.Register(sChuckOnPlace5, ChuckOnPlace5Changed);
_adsManager.Register(sChuckOnPlace6, ChuckOnPlace6Changed);
canChangeRobotJob = true;
canChangeJobGrippType = false;
canChangeChuckMagazinPlace = false;
canChangeJobGrippType = false;
_adsManager.Register("GVL_SCADA.eCurrentControlMode", CurrentControlModeChanged);
}
private void OnJobGrippSideValueChanged(object sender, ValueChangedEventArgs e)
{
JobGrippSide = (byte)e.Value;
}
private void OnJobGrippTypeValueChanged(object sender, ValueChangedEventArgs e)
{
JobGrippType = (byte)e.Value;
}
private void OnChuckMagazinPlaceValueChanged(object sender, ValueChangedEventArgs e)
{
ChuckMagazinPlace = (byte)e.Value;
}
private void OnPieceThicknessValueChanged(object sender, ValueChangedEventArgs e)
{
PieceThickness = (int)e.Value;
}
private void OnSelectedPLCJobValueChanged(object sender, ValueChangedEventArgs e)
{
SelectedPLCJob = PLCJobs.First(i => (ushort)i.eJob == (ushort)e.Value);
}
private void OnSelectedRobotJobValueChanged(object sender, ValueChangedEventArgs e)
{
SelectedRobotJob = RobotJobs.First(i => (ushort)i.eJob == (ushort)e.Value);
}
private void OnActiveRobotJobValueChanged(object sender, ValueChangedEventArgs e)
{
RobotJobActiveValue = RobotJobs.First(i => (ushort)i.eJob == (ushort)e.Value);
}
private void OnFinishedRobotJobValueChanged(object sender, ValueChangedEventArgs e)
{
RobotJobFinishedValue = RobotJobs.First(i => (ushort)i.eJob == (ushort)e.Value);
}
private void OnHotPlateIndexValueChanged(object sender, ValueChangedEventArgs e)
{
HotplateIndex = (byte)e.Value;
}
private void OnCoolPlateIndexValueChanged(object sender, ValueChangedEventArgs e)
{
CoolplateIndex = (byte)e.Value;
}
private void OnOffsetPickXValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetPick_X = (float)e.Value;
}
private void OnOffsetPickYValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetPick_Y = (float)e.Value;
}
private void OnOffsetPlaceXValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetPlace_X = (float)e.Value;
}
private void OnOffsetPlaceYValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetPlace_Y = (float)e.Value;
}
private void OnOffsetNIOPickXValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetNIOPick_X = (float)e.Value;
}
private void OnOffsetNIOPickYValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetNIOPick_Y = (float)e.Value;
}
private void OnOffsetNIOPlaceXValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetNIOPlace_X = (float)e.Value;
}
private void OnOffsetNIOPlaceYValueChanged(object sender, ValueChangedEventArgs e)
{
OffsetNIOPlace_Y = (float)e.Value;
}
private void ChuckOnPlace1Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace1 = Visibility.Visible;
}
else
{
MagazinPlace1 = Visibility.Hidden;
}
}
private void ChuckOnPlace2Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace2 = Visibility.Visible;
}
else
{
MagazinPlace2 = Visibility.Hidden;
}
}
private void ChuckOnPlace3Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace3 = Visibility.Visible;
}
else
{
MagazinPlace3 = Visibility.Hidden;
}
}
private void ChuckOnPlace4Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace4 = Visibility.Visible;
}
else
{
MagazinPlace4 = Visibility.Hidden;
}
}
private void ChuckOnPlace5Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace5 = Visibility.Visible;
}
else
{
MagazinPlace5 = Visibility.Hidden;
}
}
private void ChuckOnPlace6Changed(object? sender, ValueChangedEventArgs e)
{
if ((bool)e.Value)
{
MagazinPlace6 = Visibility.Visible;
}
else
{
MagazinPlace6 = Visibility.Hidden;
}
}
public void Dispose()
{
StartButton?.Dispose();
StartButton = null;
AbortButton?.Dispose();
AbortButton = null;
_adsManager?.Deregister(sJobGrippSide, OnJobGrippSideValueChanged);
_adsManager?.Deregister(sJobGrippType, OnJobGrippTypeValueChanged);
_adsManager?.Deregister(sChuckMagazinPlace, OnChuckMagazinPlaceValueChanged);
_adsManager?.Deregister(sPieceThickness, OnPieceThicknessValueChanged);
_adsManager?.Deregister(sSelectedPLCJob, OnSelectedPLCJobValueChanged);
_adsManager?.Deregister(sSelectedRobotJob, OnSelectedRobotJobValueChanged);
_adsManager?.Deregister(sActiveRobotJob, OnActiveRobotJobValueChanged);
_adsManager?.Deregister(sFinishedRobotJob, OnFinishedRobotJobValueChanged);
_adsManager?.Deregister(sOffsetPick_X, OnOffsetPickXValueChanged);
_adsManager?.Deregister(sOffsetPick_Y, OnOffsetPickYValueChanged);
_adsManager?.Deregister(sCoolplateIndex, OnCoolPlateIndexValueChanged);
_adsManager?.Deregister(sHotplateIndex, OnHotPlateIndexValueChanged);
_adsManager?.Deregister(sOffsetNIOPlace_Y, OnOffsetNIOPlaceYValueChanged);
_adsManager?.Deregister(sOffsetNIOPlace_X, OnOffsetNIOPlaceXValueChanged);
_adsManager?.Deregister(sOffsetNIOPick_Y, OnOffsetNIOPickYValueChanged);
_adsManager?.Deregister(sOffsetNIOPick_X, OnOffsetNIOPickXValueChanged);
_adsManager?.Deregister(sOffsetPlace_Y, OnOffsetPlaceYValueChanged);
_adsManager?.Deregister(sOffsetPlace_X, OnOffsetPlaceXValueChanged);
_adsManager?.Deregister(sChuckOnPlace1, ChuckOnPlace1Changed);
_adsManager?.Deregister(sChuckOnPlace2, ChuckOnPlace2Changed);
_adsManager?.Deregister(sChuckOnPlace3, ChuckOnPlace3Changed);
_adsManager?.Deregister(sChuckOnPlace4, ChuckOnPlace4Changed);
_adsManager?.Deregister(sChuckOnPlace5, ChuckOnPlace5Changed);
_adsManager?.Deregister(sChuckOnPlace6, ChuckOnPlace6Changed);
_adsManager?.Deregister("GVL_SCADA.eCurrentControlMode", CurrentControlModeChanged);
}
private void CurrentControlModeChanged(object? sender, ValueChangedEventArgs e)
{
bmsControlMode = (E_BMS_CONTROL_MODE)e.Value;
currentControlMode.eMode = bmsControlMode;
currentControlMode.Name = "Test";
ccmChanged();
}
private void ccmChanged()
{
if (currentControlMode.eMode == E_BMS_CONTROL_MODE.MANUAL)
{
CanChangeCoolPlateIndex = true;
CanChangeHotPlateIndex = true;
CanChangeOffsetNIOPick = true;
CanChangeOffsetNIOPlace = true;
CanChangeOffsetPick = true;
CanChangeOffsetPlace = true;
CanChangePieceThickness = true;
CanChangeRobotJob = true;
CanChangeJobGrippSide = true;
}
else
{
CanChangeCoolPlateIndex = false;
CanChangeHotPlateIndex = false;
CanChangeOffsetNIOPick = false;
CanChangeOffsetNIOPlace = false;
CanChangeOffsetPick = false;
CanChangeOffsetPlace = false;
CanChangePieceThickness = false;
CanChangeRobotJob = false;
CanChangeJobGrippSide = false;
}
}
[RelayCommand]
private void ClearState()
{
_adsManager?.WriteValue(sClearState, true);
}
[RelayCommand]
private void ResetState()
{
_adsManager?.WriteValue(sResetState, true);
}
[RelayCommand]
private void StartRobotJob()
{
_adsManager?.WriteValue(sStartRobotJob, true);
}
[RelayCommand]
private void AbortRobotJob()
{
_adsManager?.WriteValue(sAbortRobotJob, true);
}
}
}

View File

@@ -0,0 +1,300 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using System.Windows.Controls;
using TcEventLoggerAdsProxyLib;
namespace InfineonHMI;
public sealed partial class MachineOverviewPageVM : ObservableObject, IRecipient<NavigateMessage>, IDisposable
{
[ObservableProperty] private StringControlButtonVM dummyStringVM;
[ObservableProperty] private Page currentDetailPage;
private readonly IAdsManager _adsManager;
private readonly IConfiguration _config;
// Last active event
[ObservableProperty] private string currentActiveEvent = "";
// Empty page
private readonly Page _emptyPage;
// Last navigate message
private readonly Stack<NavigateMessage> _messageStack = new();
NavigateMessage? _currentMessage;
// Hot Coolplate page view model
HotCoolPlatePageVM? _hotCoolplatePageVM;
AlignmentStationPageVM? _alignmentStationPageVM;
EtchingStation1PageVM? _etchingStation1PageVm;
EtchingStation2PageVM? _etchingStation2PageVm;
HighVoltageStationPageVM? _highVoltageStationPageVm;
MediaCabinetPageVM? _mediaCabinetPageVM;
NIOStationPageVM? _nioStationPageVm;
TrayFeederPageVM? _trayFeederPageVm;
private ProductionOverviewPageVM? _prodVM;
private MainWindowVM _mainVm;
// Kuka Robot page view model
KukaRobotPageVM? _kukaRobotPageVM;
public MachineOverviewPageVM()
{
// default ctor
}
public MachineOverviewPageVM(IAdsManager adsManager, IConfiguration config,MainWindowVM mainVm, ProductionOverviewPageVM prodVm, TcEventLogger eventLogger)
{
_adsManager = adsManager;
_config = config;
_prodVM = prodVm;
_mainVm = mainVm;
// Create dummy string
DummyStringVM = new StringControlButtonVM();
// Create empty page
_emptyPage = new();
CurrentDetailPage = _emptyPage;
_currentMessage = new NavigateMessage("", typeof(Page));
_messageStack.Push(_currentMessage);
WeakReferenceMessenger.Default.Register<NavigateMessage>(this);
}
[RelayCommand]
public void TrayfeederPageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(TrayFeederPage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void AlignerPageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(AlignmentStationPage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void Etching1PageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(EtchingStation1Page));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void Etching2PageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(EtchingStation2Page));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void HVTestPageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(HighVoltageStationPage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void HotCoolplatePageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(HotCoolPlatePage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void NIOStationPageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(NIOStationPage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void KukaPageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(KukaRobotPage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
[RelayCommand]
public void MediaCabinetPageClicked()
{
NavigateMessage message = new("", typeof(ProductionOverviewPage));
NavigateMessage nextMessage = new("", typeof(MediaCabinetPage));
this.Dispose();
_mainVm?.NavigateFromOuterPage(message, nextMessage);
}
// Only use for forward traversal!
public void Receive(NavigateMessage message)
{
// Only change page if its a new page type
if (CurrentDetailPage.GetType() == message.type)
return;
// Push current message
if (_currentMessage != null)
_messageStack.Push(_currentMessage);
// Save current message for later push
_currentMessage = message;
// Set can navigate back
Navigate(message);
}
private void Navigate(NavigateMessage message)
{
// Dispose current pages viewmodel
if (CurrentDetailPage.DataContext is IDisposable viewModel)
{
CurrentDetailPage.DataContext = null;
viewModel.Dispose();
}
// Create new page
switch (message.type.Name)
{
case nameof(TrayFeederPage):
if (_trayFeederPageVm == null)
_trayFeederPageVm = new(_adsManager, "GVL_CONFIG.stMachine");
TrayFeederPage trayFeederPage = new() { DataContext = _trayFeederPageVm };
CurrentDetailPage = trayFeederPage;
break;
case nameof(AlignmentStationPage):
// Create seetings page view model only once
if (_alignmentStationPageVM == null)
_alignmentStationPageVM = new(_adsManager, "GVL_CONFIG.stMachine.stAligner");
AlignmentStationPage settingsPage = new() { DataContext = _alignmentStationPageVM };
CurrentDetailPage = settingsPage;
break;
case nameof(EtchingStation1Page):
if (_etchingStation1PageVm == null)
_etchingStation1PageVm = new(_adsManager, "GVL_CONFIG.stMachine.stEtcher1");
EtchingStation1Page etchingStation1Page = new() { DataContext = _etchingStation1PageVm };
CurrentDetailPage = etchingStation1Page;
break;
case nameof(EtchingStation2Page):
if (_etchingStation2PageVm == null)
_etchingStation2PageVm = new(_adsManager, "GVL_CONFIG.stMachine.stEtcher2");
EtchingStation2Page etchingStation2Page = new() { DataContext = _etchingStation2PageVm };
CurrentDetailPage = etchingStation2Page;
break;
case nameof(HighVoltageStationPage):
if (_highVoltageStationPageVm == null)
_highVoltageStationPageVm = new(_adsManager, "GVL_CONFIG.stMachine");
HighVoltageStationPage highVoltageStationPage = new() { DataContext = _highVoltageStationPageVm };
CurrentDetailPage = highVoltageStationPage;
break;
case nameof(HotCoolPlatePage):
if (_hotCoolplatePageVM == null)
_hotCoolplatePageVM = new(_adsManager, "GVL_Config.stMachine");
HotCoolPlatePage hotCoolPlatePage = new() {DataContext = _hotCoolplatePageVM };
CurrentDetailPage = hotCoolPlatePage;
break;
case nameof(NIOStationPage):
if (_nioStationPageVm == null)
_nioStationPageVm = new(_adsManager, "GVL_Config.stMachine.stNOK");
NIOStationPage nIOStationPage = new() { DataContext = _nioStationPageVm };
CurrentDetailPage = nIOStationPage;
break;
case nameof(KukaRobotPage):
// Create page view model only once
if (_kukaRobotPageVM == null)
_kukaRobotPageVM = new(_adsManager, "GVL_CONFIG.stMachine.stKukaRobot");
KukaRobotPage kukaRobotPage = new() { DataContext = _kukaRobotPageVM };
CurrentDetailPage = kukaRobotPage;
break;
case nameof(MediaCabinetPage):
if (_mediaCabinetPageVM == null)
_mediaCabinetPageVM = new(_adsManager, "GVL_Config.stMachine");
MediaCabinetPage mediaCabinetPage = new() { DataContext= _mediaCabinetPageVM };
CurrentDetailPage = mediaCabinetPage;
break;
default:
CurrentDetailPage = new Page();
break;
}
}
[RelayCommand]
private void AckAlarms()
{
_adsManager.WriteValue("GVL_SCADA.stConfirmAlarmsBtn.xRequest", true);
}
public void Dispose()
{
// Dispose current pages viewmodel
if (CurrentDetailPage.DataContext is IDisposable viewModel)
{
CurrentDetailPage.DataContext = null;
viewModel.Dispose();
}
DummyStringVM.Dispose();
}
}

View File

@@ -0,0 +1,108 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using Common;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class MediaCabinetPageVM : ObservableValidator, IDisposable
{
private IAdsManager _adsManager;
private string? _variableName;
[ObservableProperty] private MediaContainerVm container1Vm;
[ObservableProperty] private MediaContainerVm container2Vm;
[ObservableProperty] private MediaContainerVm container3Vm;
[ObservableProperty] private MediaContainerVm container4Vm;
[ObservableProperty] private MediaContainerVm container5Vm;
[ObservableProperty] private MediaContainerVm container6Vm;
[ObservableProperty] private MediaContainerVm container7Vm;
[ObservableProperty] private MediaContainerVm container8Vm;
[ObservableProperty] private MediaContainerVm container9Vm;
public MediaCabinetPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
Container1Vm = new MediaContainerVm(adsManager, variableName + ".stContainer1");
Container2Vm = new MediaContainerVm(adsManager, variableName + ".stContainer2");
Container3Vm = new MediaContainerVm(adsManager, variableName + ".stContainer3");
Container4Vm = new MediaContainerVm(adsManager, variableName + ".stContainer4");
Container5Vm = new MediaContainerVm(adsManager, variableName + ".stContainer5");
Container6Vm = new MediaContainerVm(adsManager, variableName + ".stContainer6");
Container7Vm = new MediaContainerVm(adsManager, variableName + ".stContainer7");
Container8Vm = new MediaContainerVm(adsManager, variableName + ".stContainer8");
Container9Vm = new MediaContainerVm(adsManager, variableName + ".stContainer9");
Container1Vm.SName = "Container1";
Container2Vm.SName = "Container2";
Container3Vm.SName = "Container3";
Container4Vm.SName = "Container4";
Container5Vm.SName = "Container5";
Container6Vm.SName = "Container6";
Container7Vm.SName = "Container7";
Container8Vm.SName = "Container8";
Container9Vm.SName = "Container9";
}
public MediaCabinetPageVM()
{
Container1Vm = new MediaContainerVm();
Container2Vm = new MediaContainerVm();
Container3Vm = new MediaContainerVm();
Container4Vm = new MediaContainerVm();
Container5Vm = new MediaContainerVm();
Container6Vm = new MediaContainerVm();
Container7Vm = new MediaContainerVm();
Container8Vm = new MediaContainerVm();
Container9Vm = new MediaContainerVm();
Container1Vm.SName = "Container1";
Container2Vm.SName = "Container2";
Container3Vm.SName = "Container3";
Container4Vm.SName = "Container4";
Container5Vm.SName = "Container5";
Container6Vm.SName = "Container6";
Container7Vm.SName = "Container7";
Container8Vm.SName = "Container8";
Container9Vm.SName = "Container9";
}
public void Dispose()
{
Container1Vm.Dispose();
Container2Vm.Dispose();
Container3Vm.Dispose();
Container4Vm.Dispose();
Container5Vm.Dispose();
Container6Vm.Dispose();
Container7Vm.Dispose();
Container8Vm.Dispose();
Container9Vm.Dispose();
}
}
}

View File

@@ -0,0 +1,69 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
using UniperHMI.OwnControls;
namespace UniperHMI
{
public sealed partial class ModuleOverviewPageVM : ObservableObject, IDisposable
{
[ObservableProperty]
private UnitControlButtonVM unit1;
[ObservableProperty]
private UnitControlButtonVM unit2;
[ObservableProperty]
private UnitControlButtonVM unit3;
[ObservableProperty]
private UnitControlButtonVM unit4;
private readonly IAdsManager? _adsManager;
private readonly string? _variableName;
public ModuleOverviewPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
unit1 = new(_adsManager, _variableName + ".stHMIInterfaceUnit1");
unit2 = new(_adsManager, _variableName + ".stHMIInterfaceUnit2");
unit3 = new(_adsManager, _variableName + ".stHMIInterfaceUnit3");
unit4 = new(_adsManager, _variableName + ".stHMIInterfaceUnit4");
}
public void Dispose()
{
Unit1?.Dispose();
Unit2?.Dispose();
Unit3?.Dispose();
Unit4?.Dispose();
}
[RelayCommand]
public void Unit1Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceUnit1", typeof(UnitOverviewPage), "Unit 1"));
}
[RelayCommand]
public void Unit2Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceUnit2", typeof(UnitOverviewPage), "Unit 2"));
}
[RelayCommand]
public void Unit3Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceUnit3", typeof(UnitOverviewPage), "Unit 3"));
}
[RelayCommand]
public void Unit4Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceUnit4", typeof(UnitOverviewPage), "Unit 4"));
}
}
}

View File

@@ -0,0 +1,59 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class NIOStationPageVM : ObservableValidator, IDisposable
{
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
[ObservableProperty] private BinaryValveControlVM clampDiagValveVm;
[ObservableProperty] private BinaryValveControlVM clampAcrossValveVm;
[ObservableProperty] private HMIControlButtonVM clampCmdButtonVm;
[ObservableProperty] private HMIControlButtonVM unclampCmdButtonVm;
public NIOStationPageVM()
{
ClampDiagValveVm = new BinaryValveControlVM();
ClampAcrossValveVm = new BinaryValveControlVM();
ClampCmdButtonVm = new HMIControlButtonVM();
UnclampCmdButtonVm = new HMIControlButtonVM();
}
public NIOStationPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
ClampDiagValveVm = new BinaryValveControlVM(_adsManager, _variableName + ".stClampDiagValve");
ClampAcrossValveVm = new BinaryValveControlVM(_adsManager, _variableName + ".stClampAcrossValve");
ClampCmdButtonVm = new HMIControlButtonVM(_adsManager, _variableName + ".stClampCmd");
UnclampCmdButtonVm = new HMIControlButtonVM(_adsManager, _variableName + "stUnclampCmd");
}
public void Dispose()
{
ClampDiagValveVm.Dispose();
ClampAcrossValveVm.Dispose();
ClampCmdButtonVm.Dispose();
UnclampCmdButtonVm.Dispose();
}
}
}

View File

@@ -0,0 +1,307 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using System.Windows.Controls;
using TcEventLoggerAdsProxyLib;
namespace InfineonHMI;
public sealed partial class ProductionOverviewPageVM : ObservableObject, IRecipient<NavigateMessage>, IDisposable
{
[ObservableProperty] private StringControlButtonVM dummyStringVM;
[ObservableProperty] private Page currentDetailPage;
[ObservableProperty] private bool canNavigateBack;
private readonly IAdsManager _adsManager;
private readonly IConfiguration _config;
private readonly TcEventLogger _eventlogger;
// Last active event
[ObservableProperty] private string currentActiveEvent = "";
private readonly object _lock = new();
// Empty page
private readonly Page _emptyPage;
// Last navigate message
private readonly Stack<NavigateMessage> _messageStack = new();
NavigateMessage? _currentMessage;
// Hot Coolplate page view model
HotCoolPlatePageVM? _hotCoolplatePageVM;
AlignmentStationPageVM? _alignmentStationPageVM;
EtchingStation1PageVM? _etchingStation1PageVm;
EtchingStation2PageVM? _etchingStation2PageVm;
HighVoltageStationPageVM? _highVoltageStationPageVm;
MediaCabinetPageVM? _mediaCabinetPageVM;
NIOStationPageVM? _nioStationPageVm;
TrayFeederPageVM? _trayFeederPageVm;
// Kuka Robot page view model
KukaRobotPageVM? _kukaRobotPageVM;
public ProductionOverviewPageVM()
{
// default ctor
}
public ProductionOverviewPageVM(IAdsManager adsManager, IConfiguration config, TcEventLogger eventLogger, NavigateMessage? message = null)
{
_adsManager = adsManager;
_config = config;
// Create dummy string
DummyStringVM = new StringControlButtonVM();
// Create empty page
_emptyPage = new();
CurrentDetailPage = _emptyPage;
_currentMessage = new NavigateMessage("", typeof(Page));
_messageStack.Push(_currentMessage);
if (message != null)
{
Receive(message);
}
WeakReferenceMessenger.Default.Register<NavigateMessage>(this);
}
[RelayCommand]
public void TrayfeederPageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["TrayFeederVarName"]!, typeof(TrayFeederPage));
Receive(message);
}
[RelayCommand]
public void AlignerPageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["AlignerVarName"]!, typeof(AlignmentStationPage));
Receive(message);
}
[RelayCommand]
public void Etching1PageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["Etching1VarName"]!, typeof(EtchingStation1Page));
Receive(message);
}
[RelayCommand]
public void Etching2PageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["Etching2VarName"]!, typeof(EtchingStation2Page));
Receive(message);
}
[RelayCommand]
public void HVTestPageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["HVTestVarName"]!, typeof(HighVoltageStationPage));
Receive(message);
}
[RelayCommand]
public void HotCoolplatePageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["HotCoolplateVarName"]!, typeof(HotCoolPlatePage));
Receive(message);
}
[RelayCommand]
public void NIOStationPageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["NIOStationVarName"]!, typeof(NIOStationPage));
Receive(message);
}
[RelayCommand]
public void KukaPageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["KukaRobotVarName"]!, typeof(KukaRobotPage));
Receive(message);
}
[RelayCommand]
public void MediaCabinetPageClicked()
{
_messageStack.Clear();
_currentMessage = new NavigateMessage("", typeof(Page));
NavigateMessage message = new(_config["MediaCabinetVarName"]!, typeof(MediaCabinetPage));
Receive(message);
}
// Only use for forward traversal!
public void Receive(NavigateMessage message)
{
// Only change page if its a new page type
if (CurrentDetailPage.GetType() == message.type)
return;
// Push current message
if (_currentMessage != null)
_messageStack.Push(_currentMessage);
// Save current message for later push
_currentMessage = message;
// Set can navigate back
CanNavigateBack = true;
Navigate(message);
}
public void NavigateFromOuterPage(NavigateMessage message)
{
_currentMessage = message;
CanNavigateBack = true;
Navigate(message);
}
private void Navigate(NavigateMessage message)
{
// Dispose current pages viewmodel
if (CurrentDetailPage.DataContext is IDisposable viewModel)
{
CurrentDetailPage.DataContext = null;
viewModel.Dispose();
}
// Create new page
switch (message.type.Name)
{
case nameof(TrayFeederPage):
if (_trayFeederPageVm == null)
_trayFeederPageVm = new(_adsManager, "GVL_CONFIG.stMachine");
TrayFeederPage trayFeederPage = new() { DataContext = _trayFeederPageVm };
CurrentDetailPage = trayFeederPage;
break;
case nameof(AlignmentStationPage):
// Create seetings page view model only once
if (_alignmentStationPageVM == null)
_alignmentStationPageVM = new(_adsManager, "GVL_CONFIG.stMachine.stAligner");
AlignmentStationPage settingsPage = new() { DataContext = _alignmentStationPageVM };
CurrentDetailPage = settingsPage;
break;
case nameof(EtchingStation1Page):
if (_etchingStation1PageVm == null)
_etchingStation1PageVm = new(_adsManager, "GVL_CONFIG.stMachine.stEtcher1");
EtchingStation1Page etchingStation1Page = new() { DataContext = _etchingStation1PageVm };
CurrentDetailPage = etchingStation1Page;
break;
case nameof(EtchingStation2Page):
if (_etchingStation2PageVm == null)
_etchingStation2PageVm = new(_adsManager, "GVL_CONFIG.stMachine.stEtcher2");
EtchingStation2Page etchingStation2Page = new() { DataContext = _etchingStation2PageVm };
CurrentDetailPage = etchingStation2Page;
break;
case nameof(HighVoltageStationPage):
if (_highVoltageStationPageVm == null)
_highVoltageStationPageVm = new(_adsManager, "GVL_CONFIG.stMachine");
HighVoltageStationPage highVoltageStationPage = new() { DataContext = _highVoltageStationPageVm };
CurrentDetailPage = highVoltageStationPage;
break;
case nameof(HotCoolPlatePage):
if (_hotCoolplatePageVM == null)
_hotCoolplatePageVM = new(_adsManager, "GVL_Config.stMachine");
HotCoolPlatePage hotCoolPlatePage = new() {DataContext = _hotCoolplatePageVM };
CurrentDetailPage = hotCoolPlatePage;
break;
case nameof(NIOStationPage):
if (_nioStationPageVm == null)
_nioStationPageVm = new(_adsManager, "GVL_Config.stMachine.stNOK");
NIOStationPage nIOStationPage = new() { DataContext = _nioStationPageVm };
CurrentDetailPage = nIOStationPage;
break;
case nameof(KukaRobotPage):
// Create page view model only once
if (_kukaRobotPageVM == null)
_kukaRobotPageVM = new(_adsManager, "GVL_CONFIG.stMachine.stKukaRobot");
KukaRobotPage kukaRobotPage = new() { DataContext = _kukaRobotPageVM };
CurrentDetailPage = kukaRobotPage;
break;
case nameof(MediaCabinetPage):
if (_mediaCabinetPageVM == null)
_mediaCabinetPageVM = new(_adsManager, "GVL_Config.stMachine");
MediaCabinetPage mediaCabinetPage = new() { DataContext= _mediaCabinetPageVM };
CurrentDetailPage = mediaCabinetPage;
break;
default:
CurrentDetailPage = new Page();
break;
}
}
[RelayCommand]
private void AckAlarms()
{
_adsManager.WriteValue("GVL_SCADA.stConfirmAlarmsBtn.xRequest", true);
}
public void Dispose()
{
// Dispose current pages viewmodel
if (CurrentDetailPage.DataContext is IDisposable viewModel)
{
CurrentDetailPage.DataContext = null;
viewModel.Dispose();
}
DummyStringVM.Dispose();
}
}

View File

@@ -0,0 +1,746 @@
using System.Collections.ObjectModel;
using System.Printing;
using System.Runtime.InteropServices.JavaScript;
using System.Windows.Automation;
using System.Windows.Input;
using Common;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Heisig.HMI.AdsManager;
using InfineonHMI.Model;
using Microsoft.Win32;
using InfineonHMI.Common;
using TwinCAT.PlcOpen;
namespace InfineonHMI;
public sealed partial class ReceipePageVM : ObservableValidator, IDisposable
{
#region Properties
private AdsManager _adsManager;
private int maxFlowNodes = 10;
private int maxTrayPositions = 20;
private int maxEtcherRobotPositions = 20;
[ObservableProperty] private ObservableCollection<TrayPosition> trayPositions;
[ObservableProperty] private ParamControlIntVm cameraProgramsVm = new ();
[ObservableProperty] private ParamControlIntVm chucksVm = new ();
[ObservableProperty] private ParamControlIntVm gripperVm = new ();
[ObservableProperty] private ParamControlFloatVm permissibleBeamParamDeviationsVm = new ();
[ObservableProperty] private ParamControlFloatVm diameterVm = new ();
[ObservableProperty] private ParamControlFloatVm thicknessVm = new ();
[ObservableProperty] private ParamControlFloatVm timeIntervallBeamCheckVm = new ();
[ObservableProperty] private ParamControlFloatVm restingTimeHotplateVm = new ();
[ObservableProperty] private ParamControlFloatVm targetTemperatureHotplateVm = new ();
[ObservableProperty] private ParamControlFloatVm restingTimeCoolplateVm = new ();
[ObservableProperty] private ParamControlFloatVm targetTemperatureCoolplateVm = new ();
[ObservableProperty] private ParamControlFloatVm hvtestVoltageVm = new ();
[ObservableProperty] private ParamControlFloatVm hvmaxTestCurrentVm = new ();
[ObservableProperty] private ParamControlFloatVm hvrampTimeVm = new ();
[ObservableProperty] private ParamControlFloatVm hvtestFrequencyVm = new ();
[ObservableProperty] private ParamControlIntVm hvpolarityVm = new ();
[ObservableProperty] private ParamControlFloatVm hvtestPressureN2Vm = new ();
[ObservableProperty] private ParamControlFloatVm hvn2PrePurgeTimeVm = new ();
[ObservableProperty] private ParamControlIntVm hvnumRetriesVm = new ();
[ObservableProperty] private ParamControlFloatVm hvtestTemperatureVm = new ();
[ObservableProperty] private ParamControlFloatVm hvTestOkVoltageVm = new ();
[ObservableProperty] private ParamControlFloatVm hvTestOkCurrentVm = new ();
[ObservableProperty] private ParamControlIntVm numberRobotPositionsVm = new ();
[ObservableProperty] private ParamControlFloatVm chuckRpmVm = new ();
[ObservableProperty] private ObservableCollection<EtcherRobotStepData> etcherRobotSteps;
[ObservableProperty] private ParamControlFloatVm radialPosLowerWaterJetVm = new ();
[ObservableProperty] private ParamControlIntVm flowNodeCountVm = new ();
#endregion Properties
#region FlowReceipe
[ObservableProperty]
private ObservableCollection<StationEntry> flowStationsVm =
[
new StationEntry(Stationenum.EINGABE, "Eingabetray"),
new StationEntry(Stationenum.QRCODE, "QR Code Scan"),
new StationEntry(Stationenum.AUSRICHTEN, "Ausrichten"),
new StationEntry(Stationenum.AETZEN, "Ätzstation 1/2"),
new StationEntry(Stationenum.HEIZPLATTE, "Heizplatte"),
new StationEntry(Stationenum.KUEHLPLATTE, "Kühlplatte"),
new StationEntry(Stationenum.HOCHVOLTHEISS, "Hochvolt Heiss"),
new StationEntry(Stationenum.HOCHVOLTKALT, "Hochvolt Kalt"),
new StationEntry(Stationenum.AUSGABE, "Ausgabetray"),
new StationEntry(Stationenum.NIOSTATION, "NIO Station")
];
[ObservableProperty] private ObservableCollection<FlowReceipeEntry> flowReceipeEntries;
[RelayCommand]
public void AddFlowReceipeEntry()
{
var nodeid = FlowReceipeEntries.Count;
FlowReceipeEntries.Add(new FlowReceipeEntry
{
NodeId = nodeid,
MaxRetries = 0,
NextNodeFail = -1,
NextNodeSuccess = -1,
NextNodeRetry = -1,
Priority = 100,
Station = FlowStationsVm[0]
});
if (FlowReceipeEntries.Count >= maxFlowNodes)
{
CanAddFlowReceipeEntry = false;
}
if (FlowReceipeEntries.Count > 0)
{
CanRemoveFlowReceipeEntry = true;
}
}
private void addFlowReceipeEntry(FlowReceipeEntry fre)
{
var nodeid = FlowReceipeEntries.Count;
FlowReceipeEntries.Add(new FlowReceipeEntry
{
NodeId = nodeid,
MaxRetries = fre.MaxRetries,
NextNodeFail = fre.NextNodeFail,
NextNodeSuccess = fre.NextNodeSuccess,
NextNodeRetry = fre.NextNodeRetry,
Priority = fre.Priority,
Station = new StationEntry(fre.Station.eStation, fre.Station.sName)
});
}
[RelayCommand]
public void RemoveFlowReceipeEntry()
{
FlowReceipeEntries.Remove(SelectedFlowReceipeEntry);
var receipes = new ObservableCollection<FlowReceipeEntry>(FlowReceipeEntries);
FlowReceipeEntries.Clear();
foreach (var receipe in receipes)
addFlowReceipeEntry(receipe);
if (FlowReceipeEntries.Count < maxFlowNodes)
{
CanAddFlowReceipeEntry = true;
}
if (FlowReceipeEntries.Count > 0)
{
CanRemoveFlowReceipeEntry = true;
}
else
{
CanRemoveFlowReceipeEntry = false;
}
}
[RelayCommand]
public void FlowReceipeEntryUp()
{
var selectedIndex = FlowReceipeEntries.IndexOf(SelectedFlowReceipeEntry);
if (selectedIndex == 0)
return;
FlowReceipeEntries.Move(selectedIndex, selectedIndex - 1);
var receipes = new ObservableCollection<FlowReceipeEntry>(FlowReceipeEntries);
FlowReceipeEntries.Clear();
foreach (var receipe in receipes)
addFlowReceipeEntry(receipe);
}
[RelayCommand]
public void FlowReceipeEntryDown()
{
var selectedIndex = FlowReceipeEntries.IndexOf(SelectedFlowReceipeEntry);
if (selectedIndex >= FlowReceipeEntries.Count)
return;
FlowReceipeEntries.Move(selectedIndex, selectedIndex + 1);
var receipes = new ObservableCollection<FlowReceipeEntry>(FlowReceipeEntries);
FlowReceipeEntries.Clear();
foreach (var receipe in receipes)
addFlowReceipeEntry(receipe);
}
[ObservableProperty] private bool canAddFlowReceipeEntry;
[ObservableProperty] private bool canRemoveFlowReceipeEntry;
[ObservableProperty] private FlowReceipeEntry selectedFlowReceipeEntry;
#endregion Flowreceipe
#region Traypositions
[ObservableProperty] private TrayPosition selectedTrayPosition;
[ObservableProperty] private bool canAddTrayPosition;
[ObservableProperty] private bool canRemoveTrayPosition;
[RelayCommand]
public void AddTrayPosition()
{
var posId = TrayPositions.Count;
TrayPositions.Add(new TrayPosition
{
PosId = posId,
PosX = 0.0f,
PosY = 0.0f,
});
if (TrayPositions.Count >= maxTrayPositions)
{
CanAddTrayPosition = false;
}
if (TrayPositions.Count > 0)
{
CanRemoveTrayPosition = true;
}
}
private void addTrayPosition(TrayPosition trayPos)
{
var posId = TrayPositions.Count;
TrayPositions.Add(new TrayPosition
{
PosId = posId,
PosX = trayPos.PosX,
PosY = trayPos.PosY
});
}
[RelayCommand]
public void RemoveTrayPosition()
{
TrayPositions.Remove(SelectedTrayPosition);
var positions = new ObservableCollection<TrayPosition>(TrayPositions);
TrayPositions.Clear();
foreach (var position in positions)
addTrayPosition(position);
if (TrayPositions.Count < maxTrayPositions)
{
CanAddTrayPosition = true;
}
if (TrayPositions.Count > 0)
{
CanRemoveTrayPosition = true;
}
else
{
CanRemoveTrayPosition = false;
}
}
[RelayCommand]
public void TrayPositionUp()
{
var selectedIndex = TrayPositions.IndexOf(SelectedTrayPosition);
if (selectedIndex == 0)
return;
TrayPositions.Move(selectedIndex, selectedIndex - 1);
var positions = new ObservableCollection<TrayPosition>(TrayPositions);
TrayPositions.Clear();
foreach (var pos in positions)
addTrayPosition(pos);
}
[RelayCommand]
public void TrayPositionDown()
{
var selectedIndex = TrayPositions.IndexOf(SelectedTrayPosition);
if (selectedIndex >= TrayPositions.Count)
return;
TrayPositions.Move(selectedIndex, selectedIndex + 1);
var positions = new ObservableCollection<TrayPosition>(TrayPositions);
TrayPositions.Clear();
foreach (var pos in positions)
addTrayPosition(pos);
}
#endregion Traypositions
#region EtcherRobotPositions
[ObservableProperty] private EtcherRobotStepData selectedEtchRobotStep;
[ObservableProperty] private bool canAddEtchRobotStep;
[ObservableProperty] private bool canRemoveEtchRobotStep;
[RelayCommand]
public void AddEtchRobotStep()
{
EtcherRobotSteps.Add(new EtcherRobotStepData()
{
PosX = 0.0f,
PosY = 0.0f,
PosZ = 0.0f,
MoveSpeed = 0.0f,
AngleAlpha = 0.0f,
WaterFromAbove = false,
WaterFromBelow = false,
Medium = 0,
Delay = 0.0f
});
if (EtcherRobotSteps.Count >= maxEtcherRobotPositions)
{
CanAddEtchRobotStep = false;
}
if (EtcherRobotSteps.Count > 0)
{
CanRemoveEtchRobotStep = true;
}
}
private void addEtchRobotStep(EtcherRobotStepData etchStep)
{
var posId = EtcherRobotSteps.Count;
EtcherRobotSteps.Add(new EtcherRobotStepData()
{
PosX = etchStep.PosX,
PosY = etchStep.PosY,
PosZ = etchStep.PosZ,
MoveSpeed = etchStep.MoveSpeed,
AngleAlpha = etchStep.AngleAlpha,
WaterFromAbove = etchStep.WaterFromAbove,
WaterFromBelow = etchStep.WaterFromBelow,
Medium = etchStep.Medium,
Delay = etchStep.Delay
});
}
[RelayCommand]
public void RemoveEtchRobotStep()
{
EtcherRobotSteps.Remove(SelectedEtchRobotStep);
var steps = new ObservableCollection<EtcherRobotStepData>(EtcherRobotSteps);
EtcherRobotSteps.Clear();
foreach (var step in steps)
addEtchRobotStep(step);
if (EtcherRobotSteps.Count < maxEtcherRobotPositions)
{
CanAddEtchRobotStep = true;
}
if (EtcherRobotSteps.Count > 0)
{
CanRemoveEtchRobotStep = true;
}
else
{
CanRemoveEtchRobotStep = false;
}
}
[RelayCommand]
public void EtchRobotStepUp()
{
var selectedIndex = EtcherRobotSteps.IndexOf(SelectedEtchRobotStep);
if (selectedIndex == 0)
return;
EtcherRobotSteps.Move(selectedIndex, selectedIndex - 1);
var steps = new ObservableCollection<EtcherRobotStepData>(EtcherRobotSteps);
EtcherRobotSteps.Clear();
foreach (var step in steps)
addEtchRobotStep(step);
}
[RelayCommand]
public void EtchRobotStepDown()
{
var selectedIndex = EtcherRobotSteps.IndexOf(SelectedEtchRobotStep);
if (selectedIndex >= EtcherRobotSteps.Count)
return;
EtcherRobotSteps.Move(selectedIndex, selectedIndex + 1);
var steps = new ObservableCollection<EtcherRobotStepData>(EtcherRobotSteps);
EtcherRobotSteps.Clear();
foreach (var step in steps)
addEtchRobotStep(step);
}
#endregion
#region Commands
[RelayCommand]
public void WriteToPlc()
{
SendDataToPLC();
}
[RelayCommand]
public void ReadReceipeFile()
{
var dlg = new OpenFileDialog();
if (dlg.ShowDialog() != true)
return ;
var dto = new ReceipeDto();
dto.Read(dlg.FileName);
GetDto(dto);
}
[RelayCommand]
public void WriteReceipeFile()
{
var dlg = new SaveFileDialog();
if (dlg.ShowDialog() != true)
return;
var dto = SetDto();
dto.Write(dlg.FileName);
}
#endregion Commands
#region ctor
public ReceipePageVM()
{
maxFlowNodes = 10;
maxEtcherRobotPositions = 10;
maxTrayPositions = 10;
TrayPositions = new ();
EtcherRobotSteps = new ();
FlowReceipeEntries = new ();
CameraProgramsVm.SName = "Kameraprogramme: ";
ChucksVm.SName = "Drehteller: ";
GripperVm.SName = "Greifertyp: ";
PermissibleBeamParamDeviationsVm.SName = "Max. Strahlabweichung: ";
DiameterVm.SName = "Teiledurchmesser: ";
ThicknessVm.SName = "Teiledicke: ";
TimeIntervallBeamCheckVm.SName = "Intervall Strahlvermessung: ";
RestingTimeHotplateVm.SName = "Verweilzeit Heizplatte: ";
TargetTemperatureHotplateVm.SName = "Zieltemperatur Heizplatte: ";
RestingTimeCoolplateVm.SName = "Verweilzeit Kühlplatte: ";
TargetTemperatureCoolplateVm.SName = "Zieltemperatur Kühlplatte";
RadialPosLowerWaterJetVm.SName = "Radial Position Unterwasserstrahl: ";
ChuckRpmVm.SName = "Drehzahl: ";
HvmaxTestCurrentVm.SName = "HV: Max. Teststrom: ";
Hvn2PrePurgeTimeVm.SName = "HV: Vorreinigungszeit: ";
HvnumRetriesVm.SName = "HV: Anzahl Wiederholversuche: ";
HvpolarityVm.SName = "HV: Polarität (1=Pos, 2=Neg): ";
HvrampTimeVm.SName = "HV: Rampenzeit: ";
HvtestFrequencyVm.SName = "HV: Testfrequenz: ";
HvTestOkCurrentVm.SName = "HV: Teststrom Teil OK";
HvTestOkVoltageVm.SName = "HV: Testspannung Teil OK";
HvtestTemperatureVm.SName = "HV: Testtemperatur: ";
HvtestVoltageVm.SName = "HV: Testspannung: ";
HvtestPressureN2Vm.SName = "HV: DruckN2: ";
FlowReceipeEntries = new();
FlowReceipeEntries.Add(new FlowReceipeEntry
{
Priority = 100,
Station = FlowStationsVm[0],
MaxRetries = 0,
NextNodeSuccess = 1,
NextNodeRetry = -1,
NextNodeFail = -1
});
CanAddTrayPosition = true;
CanRemoveTrayPosition = false;
CanAddFlowReceipeEntry = true;
CanRemoveFlowReceipeEntry = false;
CanAddEtchRobotStep = true;
CanRemoveEtchRobotStep = false;
}
public ReceipePageVM(AdsManager adsManager)
{
_adsManager = adsManager;
var val = _adsManager.ReadValue("GVL_Scheduler.MAX_RECIPE_NODES");
maxFlowNodes = (val == null) ? 10 : (int)val; ;
val = _adsManager.ReadValue("GVL_ETCHER.MAX_ROBOT_POS");
maxEtcherRobotPositions = (val == null) ? 10 : (int)val;
val = _adsManager.ReadValue("GVL_ETCHER.MAX_ROBOT_POS");
maxTrayPositions = (val == null) ? 10 : (int)val;
TrayPositions = new ();
EtcherRobotSteps = new ();
FlowReceipeEntries = new ();
CameraProgramsVm.SName = "Kameraprogramme: ";
ChucksVm.SName = "Drehteller: ";
GripperVm.SName = "Greifertyp: ";
PermissibleBeamParamDeviationsVm.SName = "Max. Strahlabweichung: ";
DiameterVm.SName = "Teiledurchmesser: ";
ThicknessVm.SName = "Teiledicke: ";
TimeIntervallBeamCheckVm.SName = "Intervall Strahlvermessung: ";
RestingTimeHotplateVm.SName = "Verweilzeit Heizplatte: ";
TargetTemperatureHotplateVm.SName = "Zieltemperatur Heizplatte: ";
RestingTimeCoolplateVm.SName = "Verweilzeit Kühlplatte: ";
TargetTemperatureCoolplateVm.SName = "Zieltemperatur Kühlplatte";
RadialPosLowerWaterJetVm.SName = "Radial Position Unterwasserstrahl: ";
ChuckRpmVm.SName = "Drehzahl: ";
HvmaxTestCurrentVm.SName = "HV: Max. Teststrom: ";
Hvn2PrePurgeTimeVm.SName = "HV: Vorreinigungszeit: ";
HvnumRetriesVm.SName = "HV: Anzahl Wiederholversuche: ";
HvpolarityVm.SName = "HV: Polarität (1=Pos, 2=Neg): ";
HvrampTimeVm.SName = "HV: Rampenzeit: ";
HvtestFrequencyVm.SName = "HV: Testfrequenz: ";
HvTestOkCurrentVm.SName = "HV: Teststrom Teil OK";
HvTestOkVoltageVm.SName = "HV: Testspannung Teil OK";
HvtestTemperatureVm.SName = "HV: Testtemperatur: ";
HvtestVoltageVm.SName = "HV: Testspannung: ";
HvtestPressureN2Vm.SName = "HV: DruckN2: ";
}
#endregion ctor
private ReceipeDto SetDto()
{
var receipe = new ReceipeDto();
receipe.ReceipeObject.MachineParameters.TrayPositions = new List<TrayPosition>(TrayPositions);
receipe.ReceipeObject.MachineParameters.CameraPrograms = CameraProgramsVm.Value;
receipe.ReceipeObject.MachineParameters.Chucks = ChucksVm.Value;
receipe.ReceipeObject.MachineParameters.Gripper = GripperVm.Value;
receipe.ReceipeObject.MachineParameters.PermissibleBeamParameterDeviations = PermissibleBeamParamDeviationsVm.Value;
receipe.ReceipeObject.ProductParameters.Diameter = DiameterVm.Value;
receipe.ReceipeObject.ProductParameters.Thickness = ThicknessVm.Value;
receipe.ReceipeObject.ProductParameters.TimeIntervallBeamCheck = TimeIntervallBeamCheckVm.Value;
receipe.ReceipeObject.ReceipeHotplate.RestingTime = RestingTimeHotplateVm.Value;
receipe.ReceipeObject.ReceipeHotplate.TargetTemperature = TargetTemperatureHotplateVm.Value;
receipe.ReceipeObject.ReceipeCoolplate.RestingTime = RestingTimeCoolplateVm.Value;
receipe.ReceipeObject.ReceipeCoolplate.TargetTemperature = TargetTemperatureCoolplateVm.Value;
receipe.ReceipeObject.ReceipeEtcher.NumberRobotPos = (ushort)NumberRobotPositionsVm.Value;
receipe.ReceipeObject.ReceipeEtcher.RadialPosLowerWaterJet = RadialPosLowerWaterJetVm.Value;
receipe.ReceipeObject.ReceipeEtcher.Rpm = ChuckRpmVm.Value;
receipe.ReceipeObject.ReceipeEtcher.RobotStepData = new List<EtcherRobotStepData>(EtcherRobotSteps);
receipe.ReceipeObject.ReceipeHvTester.MaximumTestCurrent = HvmaxTestCurrentVm.Value;
receipe.ReceipeObject.ReceipeHvTester.N2PrePurgetime = Hvn2PrePurgeTimeVm.Value;
receipe.ReceipeObject.ReceipeHvTester.NumRetries = (ushort)HvnumRetriesVm.Value;
receipe.ReceipeObject.ReceipeHvTester.Polarity = (ushort)HvpolarityVm.Value;
receipe.ReceipeObject.ReceipeHvTester.RampTime = HvrampTimeVm.Value;
receipe.ReceipeObject.ReceipeHvTester.TestFrequency = HvtestFrequencyVm.Value;
receipe.ReceipeObject.ReceipeHvTester.TestOkCurrent = HvTestOkCurrentVm.Value;
receipe.ReceipeObject.ReceipeHvTester.TestOkVoltage = HvTestOkVoltageVm.Value;
receipe.ReceipeObject.ReceipeHvTester.TestTemperature = HvtestTemperatureVm.Value;
receipe.ReceipeObject.ReceipeHvTester.TestVoltage = HvtestVoltageVm.Value;
receipe.ReceipeObject.ReceipeHvTester.TestpressureN2 = HvtestPressureN2Vm.Value;
receipe.ReceipeObject.Flowreceipe.Nodes = new List<FlowReceipeNode>();
foreach (var entry in FlowReceipeEntries)
{
var node = new FlowReceipeNode();
node.StationType = (ushort)entry.Station.eStation;
node.Priority = entry.Priority;
node.NextNodeSuccess = entry.NextNodeSuccess;
node.NextNodeRetry = entry.NextNodeRetry;
node.NextNodeFail = entry.NextNodeFail;
node.MaxRetries = entry.MaxRetries;
receipe.ReceipeObject.Flowreceipe.Nodes.Add(node);
}
receipe.ReceipeObject.Flowreceipe.NodeCount = receipe.ReceipeObject.Flowreceipe.Nodes.Count;
return receipe;
}
private void GetDto(ReceipeDto receipe)
{
TrayPositions = new (receipe.ReceipeObject.MachineParameters.TrayPositions);
CameraProgramsVm.Value = receipe.ReceipeObject.MachineParameters.CameraPrograms;
ChucksVm.Value = receipe.ReceipeObject.MachineParameters.Chucks;
GripperVm.Value = receipe.ReceipeObject.MachineParameters.Gripper;
PermissibleBeamParamDeviationsVm.Value = receipe.ReceipeObject.MachineParameters.PermissibleBeamParameterDeviations;
DiameterVm.Value = receipe.ReceipeObject.ProductParameters.Diameter;
ThicknessVm.Value = receipe.ReceipeObject.ProductParameters.Thickness;
TimeIntervallBeamCheckVm.Value = receipe.ReceipeObject.ProductParameters.TimeIntervallBeamCheck;
RestingTimeHotplateVm.Value = receipe.ReceipeObject.ReceipeHotplate.RestingTime;
TargetTemperatureHotplateVm.Value = receipe.ReceipeObject.ReceipeHotplate.TargetTemperature;
RestingTimeCoolplateVm.Value = receipe.ReceipeObject.ReceipeCoolplate.RestingTime;
TargetTemperatureCoolplateVm.Value = receipe.ReceipeObject.ReceipeCoolplate.TargetTemperature;
NumberRobotPositionsVm.Value = receipe.ReceipeObject.ReceipeEtcher.NumberRobotPos;
RadialPosLowerWaterJetVm.Value = receipe.ReceipeObject.ReceipeEtcher.RadialPosLowerWaterJet;
ChuckRpmVm.Value = receipe.ReceipeObject.ReceipeEtcher.Rpm;
EtcherRobotSteps = new (receipe.ReceipeObject.ReceipeEtcher.RobotStepData);
HvmaxTestCurrentVm.Value = receipe.ReceipeObject.ReceipeHvTester.MaximumTestCurrent;
Hvn2PrePurgeTimeVm.Value = receipe.ReceipeObject.ReceipeHvTester.N2PrePurgetime;
HvnumRetriesVm.Value = receipe.ReceipeObject.ReceipeHvTester.NumRetries;
HvpolarityVm.Value = receipe.ReceipeObject.ReceipeHvTester.Polarity;
HvrampTimeVm.Value = receipe.ReceipeObject.ReceipeHvTester.RampTime;
HvtestFrequencyVm.Value = receipe.ReceipeObject.ReceipeHvTester.TestFrequency;
HvTestOkCurrentVm.Value = receipe.ReceipeObject.ReceipeHvTester.TestOkCurrent;
HvTestOkVoltageVm.Value = receipe.ReceipeObject.ReceipeHvTester.TestOkVoltage;
HvtestTemperatureVm.Value = receipe.ReceipeObject.ReceipeHvTester.TestTemperature;
HvtestVoltageVm.Value = receipe.ReceipeObject.ReceipeHvTester.TestVoltage;
HvtestPressureN2Vm.Value = receipe.ReceipeObject.ReceipeHvTester.TestpressureN2;
FlowReceipeEntries.Clear();
foreach (var node in receipe.ReceipeObject.Flowreceipe.Nodes)
{
var station = FlowStationsVm.First(i => (uint)i.eStation == (uint)node.StationType);
AddFlowReceipeEntry();
FlowReceipeEntries.Last().MaxRetries = node.MaxRetries;
FlowReceipeEntries.Last().NextNodeRetry = node.NextNodeRetry;
FlowReceipeEntries.Last().NextNodeFail = node.NextNodeFail;
FlowReceipeEntries.Last().NextNodeSuccess = node.NextNodeSuccess;
FlowReceipeEntries.Last().Priority = node.Priority;
FlowReceipeEntries.Last().Station = station;
}
FlowNodeCountVm.Value = receipe.ReceipeObject.Flowreceipe.NodeCount;
}
private void SendDataToPLC()
{
var val = _adsManager.ReadValue("GVL_Scheduler.MAX_RECIPE_NODES");
maxFlowNodes = (val == null) ? 10 : (int)val; ;
val = _adsManager.ReadValue("GVL_ETCHER.MAX_ROBOT_POS");
maxEtcherRobotPositions = (val == null) ? 10:(int)val;
val = _adsManager.ReadValue("GVL_ETCHER.MAX_ROBOT_POS");
maxTrayPositions = (val == null) ? 20 : (int)val;
for (var i = 0; i < maxTrayPositions && i < TrayPositions.Count; i++)
{
_adsManager.WriteValue("GVL_SCADA.stMachine.stTray.arPosX[" + i + "]", TrayPositions[i].PosX);
_adsManager.WriteValue("GVL_SCADA.stMachine.stTray.arPosY[" + i + "]", TrayPositions[i].PosY);
}
var trayPosCountToPlc = TrayPositions.Count < maxTrayPositions ? TrayPositions.Count : maxTrayPositions;
_adsManager.WriteValue("GVL_SCADA.stMachine.stTray.iPosCnt", trayPosCountToPlc);
for (var i = 0; i < maxEtcherRobotPositions && i < EtcherRobotSteps.Count; i++)
{
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].rPosX", EtcherRobotSteps[i].PosX);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].rPosY", EtcherRobotSteps[i].PosY);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].rPosZ", EtcherRobotSteps[i].PosZ);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].rAngleAlpha", EtcherRobotSteps[i].AngleAlpha);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].rMoveSpeed", EtcherRobotSteps[i].MoveSpeed);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].rDelay", EtcherRobotSteps[i].Delay);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].uiMedium", EtcherRobotSteps[i].Medium);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].xWaterFromBelow", EtcherRobotSteps[i].WaterFromBelow);
_adsManager.WriteValue("GVL_SCADA.stRecipeEtcher.stRobotStepData[" + i + "].xWaterFromAbove", EtcherRobotSteps[i].WaterFromAbove);
}
for (var i = 0; (i < maxFlowNodes && i < FlowReceipeEntries.Count); i++)
{
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.astNodes[" + i + "].uiPriority", FlowReceipeEntries[i].Priority);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.astNodes[" + i + "].uiPriority", FlowReceipeEntries[i].Station.eStation);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.astNodes[" + i + "].uiPriority", FlowReceipeEntries[i].MaxRetries);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.astNodes[" + i + "].uiPriority", FlowReceipeEntries[i].NextNodeSuccess);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.astNodes[" + i + "].uiPriority", FlowReceipeEntries[i].NextNodeRetry);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.astNodes[" + i + "].uiPriority", FlowReceipeEntries[i].NextNodeFail);
}
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterFlowRecipe.uiNodeCnt", FlowNodeCountVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", CameraProgramsVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", ChucksVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", GripperVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", PermissibleBeamParamDeviationsVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", DiameterVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", ThicknessVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine", TimeIntervallBeamCheckVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHotplate.rRestingTime", RestingTimeHotplateVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHotplate.rTemp", TargetTemperatureHotplateVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeCoolplate.rRestingTime", RestingTimeCoolplateVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeCoolplate.rTemp", TargetTemperatureCoolplateVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stRecipeEtcher.uiNumRobotPos", NumberRobotPositionsVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stRecipeEtcher.rRadialPosLowerWaterJet", RadialPosLowerWaterJetVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stRecipeEtcher.rChuckRPM", ChuckRpmVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rTestVoltage", HvtestVoltageVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rMaxTestCurrent", HvmaxTestCurrentVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rRampTime", HvrampTimeVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rTestFrequency", HvtestFrequencyVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.uiPolarity", HvpolarityVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rTestPresN2", HvtestPressureN2Vm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rN2PrePurgeTime", Hvn2PrePurgeTimeVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.uiNumRetries", HvnumRetriesVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rTestTemp", HvtestTemperatureVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rTestOkVoltage", HvTestOkVoltageVm.Value);
_adsManager.WriteValue("GVL_SCADA.stMachine.stMasterRecipeHVTest.rTestOkCurrent", HvTestOkCurrentVm.Value);
}
public void Dispose()
{
}
}

View File

@@ -0,0 +1,56 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Heisig.HMI.AdsManager;
namespace UniperHMI;
public sealed partial class StringOverviewPageVM : ObservableObject, IDisposable
{
[ObservableProperty]
private ModuleControlButtonVM module1;
[ObservableProperty]
private ModuleControlButtonVM module2;
[ObservableProperty]
private ModuleControlButtonVM module3;
private readonly IAdsManager? _adsManager;
private readonly string? _variableName;
public StringOverviewPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
module1 = new(_adsManager, _variableName + ".stHMIInterfaceModule1");
module2 = new(_adsManager, _variableName + ".stHMIInterfaceModule2");
module3 = new(_adsManager, _variableName + ".stHMIInterfaceModule3");
}
public void Dispose()
{
Module1?.Dispose();
Module2?.Dispose();
Module3?.Dispose();
}
[RelayCommand]
private void Module1Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceModule1", typeof(ModuleOverviewPage), "Module 1"));
}
[RelayCommand]
private void Module2Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceModule2", typeof(ModuleOverviewPage), "Module 2"));
}
[RelayCommand]
private void Module3Clicked()
{
WeakReferenceMessenger.Default.Send(new NavigateMessage(_variableName + ".stHMIInterfaceModule3", typeof(ModuleOverviewPage), "Module 3"));
}
}

View File

@@ -0,0 +1,42 @@
using CommunityToolkit.Mvvm.ComponentModel;
using HMIToolkit;
using System.ComponentModel.DataAnnotations;
using Heisig.HMI.AdsManager;
using CommunityToolkit.Mvvm.Input;
using TwinCAT.TypeSystem;
using System.Collections.ObjectModel;
using InfineonHMI.Model;
namespace InfineonHMI
{
public sealed partial class TrayFeederPageVM : ObservableValidator, IDisposable
{
private readonly string? _variableName;
private readonly IAdsManager? _adsManager;
public TrayFeederPageVM()
{
}
public TrayFeederPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
}
public void Dispose()
{
}
}
}

View File

@@ -0,0 +1,31 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Heisig.HMI.AdsManager;
namespace UniperHMI;
public sealed partial class UnitOverviewPageVM : ObservableObject, IDisposable
{
[ObservableProperty]
private string unitName;
[ObservableProperty]
private UnitDetailsControlVM unitControlVM;
private readonly IAdsManager? _adsManager;
private readonly string? _variableName;
public UnitOverviewPageVM(IAdsManager adsManager, string variableName)
{
_adsManager = adsManager;
_variableName = variableName;
unitControlVM = new(_adsManager, _variableName);
unitName = "Unit X";
}
public void Dispose()
{
UnitControlVM?.Dispose();
}
}

View File

@@ -0,0 +1,36 @@
<Page
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:InfineonHMI"
xmlns:HMIToolkit="clr-namespace:HMIToolkit" x:Class="InfineonHMI.AlignmentStationPage"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type local:AlignmentStationPageVM}}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="AlignmentStationPage" FontSize="40">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Alignment Station" VerticalAlignment="Top" HorizontalAlignment="Left" />
<HMIToolkit:BinaryValveControl Grid.Column="0" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="center" VerticalAlignment="Center" DataContext="{Binding Path=VacuumValveControlVm}"/>
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class AlignmentStationPage : Page
{
public AlignmentStationPage()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,49 @@
<Page x:Class="UniperHMI.AutomaticModePage"
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:UniperHMI"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:AutomaticModePageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="AutomaticModePage">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="1" Grid.Column="1" Content="Requested Control Mode:" VerticalAlignment="Center" HorizontalAlignment="Left" />
<ComboBox Grid.Row="1" Grid.Column="2" IsEnabled="{Binding CanChangeControlMode}" ItemsSource="{Binding ReqBMSControlModes}" SelectedItem="{Binding SelectedControlMode}"/>
<Label Grid.Row="2" Grid.Column="1" Content="Current Control Mode:" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox Grid.Row="2" Grid.Column="2" Text="{Binding BmsControlMode}" MaxLines="1" IsReadOnly="True" TextAlignment="Right"/>
<Label Grid.Row="3" Grid.Column="1" Content="Status:" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox Grid.Row="3" Width="125" Grid.Column="2" Text="Charging" MaxLines="1" IsReadOnly="True" TextAlignment="Right"/>
<Label Grid.Row="4" Grid.Column="1" Content="Target Power (W):" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox Grid.Row="4" Width="125" Grid.Column="2" Text="{Binding Setpoint}" MaxLines="1" Margin="0,5,0,0" TextAlignment="Right" />
<Label Grid.Row="5" Grid.Column="1" Content="Actual Power (W):" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox Grid.Row="5" Width="125" Grid.Column="2" Text="{Binding ProcessValue}" MaxLines="1" Margin="0,5,0,0" IsReadOnly="True" TextAlignment="Right" />
<Button Grid.Row="6" Grid.Column="1" Command="{Binding StartAutomaticCommand}" Content="Start" Margin="0,5,5,0" />
<Button Grid.Row="6" Grid.Column="2" Command="{Binding StopAutomaticCommand}" Content="Stop" Margin="5,5,0,0" />
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace UniperHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class AutomaticModePage : Page
{
public AutomaticModePage()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,39 @@
<Page x:Class="UniperHMI.BatteryOverviewPage"
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:UniperHMI"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
x:Name="root"
d:DataContext="{d:DesignInstance Type=local:BatteryOverviewPageVM, IsDesignTimeCreatable=False}"
Title="ManualModePage" Height="Auto" Width="Auto" VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid Margin="10" Width="Auto" Height="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<local:SMUControlButton Grid.Row="0" Grid.Column="0" DataContext="{Binding String1VM}" Command="{Binding ElementName=root, Path=DataContext.String1ClickedCommand}" SMUName="String 1" Margin="0,0,5,0" />
<local:SMUControlButton Grid.Row="0" Grid.Column="1" DataContext="{Binding String2VM}" Command="{Binding ElementName=root, Path=DataContext.String2ClickedCommand}" SMUName="String 2" Margin="0,0,5,0" />
<local:SMUControlButton Grid.Row="0" Grid.Column="2" DataContext="{Binding DummyStringVM}" SMUName="String 3" Margin="0,0,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="0" Grid.Column="3" DataContext="{Binding DummyStringVM}" SMUName="String 4" Margin="0,0,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="0" Grid.Column="4" DataContext="{Binding DummyStringVM}" SMUName="String 5" Margin="0,0,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="0" Grid.Column="5" DataContext="{Binding DummyStringVM}" SMUName="String 6" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="1" Grid.Column="0" DataContext="{Binding DummyStringVM}" SMUName="String 7" Margin="0,5,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="1" Grid.Column="1" DataContext="{Binding DummyStringVM}" SMUName="String 8" Margin="0,5,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="1" Grid.Column="2" DataContext="{Binding DummyStringVM}" SMUName="String 9" Margin="0,5,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="1" Grid.Column="3" DataContext="{Binding DummyStringVM}" SMUName="String 10" Margin="0,5,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="1" Grid.Column="4" DataContext="{Binding DummyStringVM}" SMUName="String 11" Margin="0,5,5,0" IsEnabled="False"/>
<local:SMUControlButton Grid.Row="1" Grid.Column="5" DataContext="{Binding DummyStringVM}" SMUName="String 12" Margin="0,5,0,0" IsEnabled="False"/>
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace UniperHMI
{
/// <summary>
/// Interaktionslogik für ManualModePage.xaml
/// </summary>
public partial class BatteryOverviewPage : Page
{
public BatteryOverviewPage()
{
InitializeComponent();
//Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,64 @@
<Page x:Class="UniperHMI.ChuckMagazinPage"
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:UniperHMI"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:AutomaticModePageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="Blablubb">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Magazinbelegung: " VerticalAlignment="Center" HorizontalAlignment="Center" />
<Label Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Content="Tellerplatz 1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" />
<Label Grid.Row="1" Grid.Column="4" Grid.ColumnSpan="2" Content="Tellerplatz 2" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" />
<Label Grid.Row="1" Grid.Column="7" Grid.ColumnSpan="2" Content="Tellerplatz 3" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" />
<Label Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Content="Tellerplatz 4" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" />
<Label Grid.Row="5" Grid.Column="4" Grid.ColumnSpan="2" Content="Tellerplatz 5" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" />
<Label Grid.Row="5" Grid.Column="7" Grid.ColumnSpan="2" Content="Tellerplatz 6" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" />
<Ellipse Grid.Column="1" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="230" Margin="0" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="230"/>
<Ellipse Grid.Column="4" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="230" Margin="0" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="230"/>
<Ellipse Grid.Column="7" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="230" Margin="0" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="230"/>
<Ellipse Grid.Column="1" Grid.Row="6" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="230" Margin="0" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="230"/>
<Ellipse Grid.Column="4" Grid.Row="6" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="230" Margin="0" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="230"/>
<Ellipse Grid.Column="7" Grid.Row="6" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="230" Margin="0" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="230"/>
<Ellipse Grid.Column="1" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="210" Margin="0" Stroke="WhiteSmoke" Fill="DarkCyan" Visibility="{Binding MagazinPlace1}" VerticalAlignment="Center" Width="210"/>
<Ellipse Grid.Column="4" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="210" Margin="0" Stroke="WhiteSmoke" Fill="DarkCyan" Visibility="{Binding MagazinPlace2}" VerticalAlignment="Center" Width="210"/>
<Ellipse Grid.Column="7" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="210" Margin="0" Stroke="WhiteSmoke" Fill="DarkCyan" Visibility="{Binding MagazinPlace3}" VerticalAlignment="Center" Width="210"/>
<Ellipse Grid.Column="1" Grid.Row="6" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="210" Margin="0" Stroke="WhiteSmoke" Fill="DarkCyan" Visibility="{Binding MagazinPlace4}" VerticalAlignment="Center" Width="210"/>
<Ellipse Grid.Column="4" Grid.Row="6" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="210" Margin="0" Stroke="WhiteSmoke" Fill="DarkCyan" Visibility="{Binding MagazinPlace5}" VerticalAlignment="Center" Width="210"/>
<Ellipse Grid.Column="7" Grid.Row="6" Grid.RowSpan="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="210" Margin="0" Stroke="WhiteSmoke" Fill="DarkCyan" Visibility="{Binding MagazinPlace6}" VerticalAlignment="Center" Width="210"/>
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace UniperHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class ChuckMagazinPage : Page
{
public ChuckMagazinPage()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,49 @@
<Page x:Class="InfineonHMI.EtchingStation1Page"
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:InfineonHMI"
xmlns:hmiToolkit="clr-namespace:HMIToolkit"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:EtchingStation1PageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="EtchingStationPage">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Etching Station 1" VerticalAlignment="Top" HorizontalAlignment="Left" FontSize="35" />
<hmiToolkit:BinaryValveControl Grid.Column="0" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding VacuumValveControlEtching1Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding DoorValveControlEtching1Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="2" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckUnlockValveLeftEtching1Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="0" Grid.Row="3" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckUnlockValveRightEtching1Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="1" Grid.Row="3" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckEjectValveFrontEtching1Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="2" Grid.Row="3" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckEjectValveBackEtching1Vm}"/>
<Button Grid.Row="1" Grid.Column="3" Content="Teller Entriegeln" DataContext="{Binding ChuckUnlockCmdButtonEtching1Vm}" HorizontalAlignment="Center" Width="320" Height="140" FontSize="30" />
<Button Grid.Row="2" Grid.Column="3" Content="Teller Verriegeln" DataContext="{Binding ChuckLockCmdButtonEtching1Vm}" HorizontalAlignment="Center" Width="320" Height="140" FontSize="30"/>
<Button Grid.Row="3" Grid.Column="3" Content="Teller Auswerfen" DataContext="{Binding ChuckEjectCmdButtonEtching1Vm}" HorizontalAlignment="Center" Width="320" Height="140" FontSize="30"/>
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class EtchingStation1Page : Page
{
public EtchingStation1Page()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,48 @@
<Page x:Class="InfineonHMI.EtchingStation2Page"
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:InfineonHMI"
xmlns:hmiToolkit="clr-namespace:HMIToolkit"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:EtchingStation2PageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="EtchingStationPage">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Etching Station 2" VerticalAlignment="Top" HorizontalAlignment="Left" FontSize="35" />
<hmiToolkit:BinaryValveControl Grid.Column="0" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding VacuumValveControlEtching2Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="1" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding DoorValveControlEtching2Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="2" Grid.Row="0" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckUnlockValveLeftEtching2Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="0" Grid.Row="3" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckUnlockValveRightEtching2Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="1" Grid.Row="3" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckEjectValveFrontEtching2Vm}"/>
<hmiToolkit:BinaryValveControl Grid.Column="2" Grid.Row="3" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding ChuckEjectValveBackEtching2Vm}"/>
<Button Grid.Row="1" Grid.Column="3" Content="Teller Entriegeln" DataContext="{Binding ChuckUnlockCmdButtonEtching2Vm}" HorizontalAlignment="Center" Width="320" Height="140" FontSize="30"/>
<Button Grid.Row="2" Grid.Column="3" Content="Teller Verriegeln" DataContext="{Binding ChuckLockCmdButtonEtching2Vm}" HorizontalAlignment="Center" Width="320" Height="140" FontSize="30"/>
<Button Grid.Row="3" Grid.Column="3" Content="Teller Auswerfen" DataContext="{Binding ChuckEjectCmdButtonEtching2Vm}" HorizontalAlignment="Center" Width="320" Height="140" FontSize="30"/>
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class EtchingStation2Page : Page
{
public EtchingStation2Page()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,49 @@
<Page x:Class="UniperHMI.EtchingStationPage"
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:UniperHMI"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:AutomaticModePageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="Blablubb">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="1" Grid.Column="1" Content="Requested Control Mode:" VerticalAlignment="Center" HorizontalAlignment="Left" />
<ComboBox Grid.Row="1" Grid.Column="2" IsEnabled="{Binding CanChangeControlMode}" ItemsSource="{Binding ReqBMSControlModes}" SelectedItem="{Binding SelectedControlMode}"/>
<Label Grid.Row="2" Grid.Column="1" Content="Current Control Mode:" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox Grid.Row="2" Grid.Column="2" Text="{Binding BmsControlMode}" MaxLines="1" IsReadOnly="True" TextAlignment="Right"/>
<Label Grid.Row="3" Grid.Column="1" Content="Status:" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox Grid.Row="3" Width="125" Grid.Column="2" Text="Charging" MaxLines="1" IsReadOnly="True" TextAlignment="Right"/>
<Label Grid.Row="4" Grid.Column="1" Content="Target Power (W):" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox Grid.Row="4" Width="125" Grid.Column="2" Text="{Binding Setpoint}" MaxLines="1" Margin="0,5,0,0" TextAlignment="Right" />
<Label Grid.Row="5" Grid.Column="1" Content="Actual Power (W):" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox Grid.Row="5" Width="125" Grid.Column="2" Text="{Binding ProcessValue}" MaxLines="1" Margin="0,5,0,0" IsReadOnly="True" TextAlignment="Right" />
<Button Grid.Row="6" Grid.Column="1" Command="{Binding StartAutomaticCommand}" Content="Start" Margin="0,5,5,0" />
<Button Grid.Row="6" Grid.Column="2" Command="{Binding StopAutomaticCommand}" Content="Stop" Margin="5,5,0,0" />
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace UniperHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class EtchingStationPage : Page
{
public EtchingStationPage()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,25 @@
<Page x:Class="InfineonHMI.EventsPage"
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:InfineonHMI"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:EventsPageVM, IsDesignTimeCreatable=False}"
d:DesignHeight="450" d:DesignWidth="800"
Title="EventsPage">
<Page.Resources>
<local:DateTimeToEventTimeConverter x:Key="dtConverter" />
</Page.Resources>
<Grid>
<DataGrid ItemsSource="{Binding CurrentEvents}" AutoGenerateColumns="False" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="400"/>
<DataGridTextColumn Header="Raised" Binding="{Binding Raised, Converter={StaticResource dtConverter}}" Width="*" SortDirection="Descending"/>
<DataGridTextColumn Header="Cleared" Binding="{Binding Cleared, Converter={StaticResource dtConverter}}" Width="*"/>
<DataGridTextColumn Header="Confirmed" Binding="{Binding Confirmed, Converter={StaticResource dtConverter}}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Page>

View File

@@ -0,0 +1,14 @@
using System.Windows.Controls;
namespace InfineonHMI;
/// <summary>
/// Interaktionslogik für EventsPage.xaml
/// </summary>
public partial class EventsPage : Page
{
public EventsPage()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,52 @@
<Page x:Class="InfineonHMI.HighVoltageStationPage"
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:InfineonHMI"
xmlns:hmiToolkit="clr-namespace:HMIToolkit"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:HighVoltageStationPageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="High Voltage Test Station">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Hochvolt Test Station Heiß" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="35"/>
<Label Grid.Row="0" Grid.Column="3" Content="Hochvolt Test Station Kalt" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="35"/>
<Border Grid.Row="0" Grid.Column="2" Grid.RowSpan="9" BorderBrush="White" BorderThickness="0,0,1,0"></Border>
<Border Grid.Row="0" Grid.Column="3" Grid.RowSpan="9" BorderBrush="White" BorderThickness="1,0,0,0"></Border>
<hmiToolkit:BinaryValveControl Grid.Column="0" Grid.Row="1" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding DoorValveHotControlVm }"/>
<hmiToolkit:BinaryValveControl Grid.Column="3" Grid.Row="1" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding DoorValveColdControlVm }"/>
<hmiToolkit:BinaryValveControl Grid.Column="1" Grid.Row="1" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding TestChamberHotValveVm }"/>
<hmiToolkit:BinaryValveControl Grid.Column="4" Grid.Row="1" Grid.RowSpan="4" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding TestChamberColdValveVm }"/>
<Label Grid.Column="2" Grid.Row="1" FontSize="40" Content="Solltemperatur" HorizontalAlignment="left" Margin="5"/>
<hmiToolkit:AnalogValue Grid.Column="2" Grid.Row="1" Height="60" Width="260" HorizontalAlignment="Left" Margin="60" VerticalAlignment="Center" DataContext="{Binding TempSPHotVm}"/>
<Label Grid.Column="5" Grid.Row="1" FontSize="40" Content="Solltemperatur" Margin="5"/>
<hmiToolkit:AnalogValue Grid.Column="5" Grid.Row="1" Height="60" Width="260" Margin="60" HorizontalAlignment="Left" VerticalAlignment="Center" DataContext="{Binding TempSPColdVm}"/>
</Grid>
</Page>

View File

@@ -0,0 +1,22 @@
using System.Windows.Controls;
namespace InfineonHMI
{
/// <summary>
/// Interaktionslogik für AutomaticModePage.xaml
/// </summary>
public partial class HighVoltageStationPage : Page
{
public HighVoltageStationPage()
{
InitializeComponent();
// Unloaded += OnUnloaded;
}
private void OnUnloaded(object? sender, EventArgs e)
{
var disposable = DataContext as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,100 @@
<Page xmlns:HMIToolkit="clr-namespace:HMIToolkit" x:Class="InfineonHMI.HotCoolPlatePage"
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:InfineonHMI"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:HotCoolPlatePageVM, IsDesignTimeCreatable=True}"
d:DesignHeight="800" d:DesignWidth="1850"
Title="HotCoolPlatePage">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" Grid.RowSpan="9" Grid.Column="4" BorderBrush="WhiteSmoke" BorderThickness="2,0,0,0" />
<Border Grid.Row="0" Grid.RowSpan="9" Grid.Column="3" BorderBrush="WhiteSmoke" BorderThickness="0,0,2,0" />
<Label Grid.Row="0" Grid.Column="0" FontSize="35" Content="Heizplatte" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10"/>
<Label Grid.Row="0" Grid.Column="4" FontSize="35" Content="Kühlplatte" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10"/>
<Button Grid.Row="0" Grid.Column="1" Content="Einschalten" DataContext="{Binding EnableHotPlateButtonVm}" HorizontalAlignment="Center" Width="280" Height="100" FontSize="35" />
<Button Grid.Row="0" Grid.Column="2" Content="Ausschalten" DataContext="{Binding DisableHotPlateButtonVm}" HorizontalAlignment="Center" Width="280" Height="100" FontSize="35" />
<Button Grid.Row="0" Grid.Column="5" Content="Einschalten" DataContext="{Binding EnableCoolPlateButtonVm}" HorizontalAlignment="Center" Width="280" Height="100" FontSize="35" />
<Button Grid.Row="0" Grid.Column="6" Content="Ausschalten" DataContext="{Binding DisableCoolPlateButtonVm}" HorizontalAlignment="Center" Width="280" Height="100" FontSize="35" />
<Label Grid.Row="2" Grid.Column="0" FontSize="35" Content="Belegung:" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10" />
<Label Grid.Row="2" Grid.Column="4" FontSize="35" Content="Belegung:" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10" />
<Label Grid.Row="1" Grid.Column="1" FontSize="40" Content="Temperatur Soll" VerticalAlignment="Top" HorizontalAlignment="Center"/>
<HMIToolkit:AnalogValue Grid.Column="1" Grid.Row="1" Height="80" Width="160" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding HotPlateTargetTemperature}"/>
<Label Grid.Row="1" Grid.Column="2" Content="Temperatur Ist" VerticalAlignment="Top" HorizontalAlignment="Center" FontSize="40" />
<HMIToolkit:AnalogValue Grid.Column="2" Grid.Row="1" Height="80" Width="160" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding HotPlateActualTemperature}"/>
<Label Grid.Row="1" Grid.Column="5" Content="Temperatur Soll" VerticalAlignment="Top" HorizontalAlignment="Center" FontSize="40"/>
<HMIToolkit:AnalogValue Grid.Column="5" Grid.Row="1" Height="80" Width="160" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding CoolPlateTargetTemperature}"/>
<Label Grid.Row="1" Grid.Column="6" Content="Temperatur Ist" VerticalAlignment="Top" HorizontalAlignment="Center" FontSize="40"/>
<HMIToolkit:AnalogValue Grid.Column="6" Grid.Row="1" Height="80" Width="160" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding CoolPlateActualTemperature}"/>
<Ellipse Grid.Column="0" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="1" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="2" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="0" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="1" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="2" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="0" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="1" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="2" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="0" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility1}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="1" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility2}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="2" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility3}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="0" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility4}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="1" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility5}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="2" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility6}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="0" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility7}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="1" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility8}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="2" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding HotPlateVisibility9}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="4" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="5" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="6" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="4" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="5" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="6" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="4" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="5" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="6" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="150" Margin="10" Stroke="WhiteSmoke" Fill="WhiteSmoke" VerticalAlignment="Center" Width="150"/>
<Ellipse Grid.Column="4" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility1}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="5" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility2}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="6" Grid.Row="2" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility3}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="4" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility4}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="5" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility5}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="6" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility6}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="4" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility7}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="5" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility8}" VerticalAlignment="Center" Width="120"/>
<Ellipse Grid.Column="6" Grid.Row="6" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="120" Margin="10" Stroke="WhiteSmoke" Fill="Gray" Visibility="{Binding CoolPlateVisibility9}" VerticalAlignment="Center" Width="120"/>
</Grid>
</Page>

Some files were not shown because too many files have changed in this diff Show More