OmniPlus DLL refactoring - build failed (missing extensions methods)

This commit is contained in:
Stoyan Zlatev
2024-01-03 15:22:37 +01:00
parent c34c93177f
commit 17fc381303
178 changed files with 897 additions and 3914 deletions
@@ -1,258 +0,0 @@
namespace OmniPlus.Connections
{
using OmniPlus.Enums;
using OmniPlus.Hanlers;
using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
internal class IrdaConnection : SerialPortConnection
{
protected event DataReceivedHandler MessageReceived;
public IrdaConnection(string portName)
{
this.Options.PortName = portName;
this.Options.BaudRate = BaudRate.K115200;
this.Options.DataBits = DataBits.X8;
this.Options.Parity = Parity.None;
this.Options.StopBits = StopBits.One;
this.Options.LogFile = $".\\IRDA\\[{portName}].txt";
}
public Byte[] Send(params Byte[] request)
{
if (!this.IsOpen)
{
this.OpenII();
}
var response = new Byte[] { };
if (!this.IsOpen || !this.Stream.CanWrite || !this.Stream.CanRead)
{
return response;
}
this.Stream.Write(new byte[] { 1, 1, 1, 1 }, 0, 4);
var asyncState = new IRDAAsyncState
{
Request = request,
Stream = this.Stream,
Logger = this.InvokeLogMessage
};
var lock_object = new object();
lock (lock_object)
{
asyncState.BeginWriteAsync(request);
}
return asyncState.Response;
}
public byte[] SendMessage(byte[] command)
{
var response = new byte[0];
var received = false;
if (command?.Length <= 0)
{
return response;
}
void MessageReceivedHandler(byte[] bytes)
{
response = bytes
.FromIrdaMessage()
.FromUI1236Message();
this.InvokeLogMessage($"RX: {BitConverter.ToString(response)}");
received = response.Length > 0 && response[0] > 0;
if (received)
{
this.MessageReceived -= MessageReceivedHandler;
}
}
this.MessageReceived += MessageReceivedHandler;
var request = command
.ToUI1236Message()
.ToIrdaMessage();
var sleep = 5000;
var delay = 500;
this.Write(1, 1, 1, 1);
Thread.Sleep(1);
this.Write(request);
this.InvokeLogMessage($"TX: {BitConverter.ToString(command)}");
while (!received && sleep >= 0)
{
sleep -= delay;
Thread.Sleep(delay);
}
this.MessageReceived -= MessageReceivedHandler;
return response;
}
protected override void SerialPortConnection_DataReceived(byte[] bytes)
{
var message = default(byte[]);
var length = bytes.Length;
var start = -1;
while (++start < bytes.Length)
{
if (bytes[start] == OmniPlusExtensions.IRDA_START)
{
try
{
if (bytes[start + 1] == OmniPlusExtensions.IRDA_PING)
{
continue;
}
var messageLength = bytes[start + 2] * 2;
messageLength += OmniPlusExtensions.IRDA_MIN_LENGTH;
message = new byte[messageLength];
Array.Copy(bytes, start, message, 0, messageLength);
}
catch (Exception e)
{
this.SerialPortConnection_LogMessage(e.ToString());
}
break;
}
}
this.MessageReceived?.Invoke(message);
}
}
public class IRDAAsyncState
{
private const int BUFFER_SIZE = 256;
private const int MAX_REPEATS = 10;
private readonly ManualResetEventSlim manualResetEventSlim;
private readonly CancellationTokenSource cancellationTokenSource;
private readonly CancellationToken cancellationToken;
private Task readerTask;
private int repeatsCount;
public IRDAAsyncState()
{
this.manualResetEventSlim = new ManualResetEventSlim();
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
this.InputBuffer = new Byte[BUFFER_SIZE];
}
public Byte[] InputBuffer { get; private set; }
public Byte[] Request { get; set; }
public Byte[] Response { get; set; }
public Stream Stream { get; set; }
public Action<String> Logger { get; set; }
internal void BeginReadAsync()
{
this.repeatsCount++;
this.Response = null;
var asyncResult = this.Stream.BeginRead(this.InputBuffer, 0, BUFFER_SIZE, this.EndReadAsync, this);
asyncResult.AsyncWaitHandle.WaitOne();
if (this.Response is null && this.repeatsCount <= MAX_REPEATS)
{
this.BeginReadAsync();
}
else
{
this.manualResetEventSlim.Set();
}
}
private void EndReadAsync(IAsyncResult asyncResult)
{
if (asyncResult.AsyncState is IRDAAsyncState asyncState)
{
var bytesLength = asyncState.Stream.EndRead(asyncResult);
var lock_object = new object();
lock (lock_object)
{
if (this.Response is null)
{
var response = new Byte[bytesLength];
Buffer.BlockCopy(this.InputBuffer, 0, response, 0, bytesLength);
this.Logger?.Invoke("<<< IRDA: " + BitConverter.ToString(response));
response = response.FromIrdaMessage();
this.Logger?.Invoke(" UI1236: " + BitConverter.ToString(response));
response = response.FromUI1236Message();
this.Logger?.Invoke(" OMNI: " + BitConverter.ToString(response));
if (response.Length != 0)
{
this.Response = response;
}
}
}
}
}
internal void BeginWriteAsync(Byte[] request)
{
this.Logger?.Invoke(">>> OMNI: " + BitConverter.ToString(request));
request = request.ToUI1236Message();
this.Logger?.Invoke(" UI1236: " + BitConverter.ToString(request));
request = request.ToIrdaMessage();
this.Logger?.Invoke(" IRDA: " + BitConverter.ToString(request));
this.readerTask = Task.Factory.StartNew(this.BeginReadAsync, this.cancellationToken);
var asyncResult = this.Stream.BeginWrite(request, 0, request.Length, this.EndWriteAsync, this);
asyncResult.AsyncWaitHandle.WaitOne();
this.manualResetEventSlim.Wait();
}
private void EndWriteAsync(IAsyncResult asyncResult)
{
if (asyncResult.AsyncState is IRDAAsyncState asyncState)
{
asyncState.Stream.EndWrite(asyncResult);
}
}
}
}
@@ -1,331 +0,0 @@
namespace OmniPlus.Connections
{
using OmniPlus.Enums;
using OmniPlus.Hanlers;
using OmniPlus.Options;
using System;
using System.IO;
using System.IO.Ports;
using System.Threading.Tasks;
internal abstract class SerialPortConnection : IDisposable
{
protected event StateChangedEventHandler StateChanged;
protected event DataReceivedHandler DataReceived;
protected event LogMessageEventHandler LogMessage;
private SerialPort serialPort;
private SerialPortState state;
protected SerialPortConnection()
=> this.Options = new SerialPortOptions();
protected SerialPortOptions Options { get; }
public bool Connected => this.state == SerialPortState.Open;
protected bool IsOpen => this.serialPort?.IsOpen ?? false;
protected Stream Stream => this.serialPort.BaseStream;
public virtual void Dispose()
{
try
{
if (this.serialPort != null)
{
this.serialPort.Disposed -= this.Port_Disposed;
this.serialPort.ErrorReceived -= this.Port_ErrorReceived;
this.serialPort.Close();
this.serialPort.Dispose();
this.serialPort = null;
}
}
catch (Exception e)
{
this.LogMessage?.Invoke(e.Message);
}
this.LogMessage?.Invoke($"Port {this.Options.PortName} disposed");
}
protected virtual void OpenII()
{
try
{
this.serialPort = new SerialPort
{
PortName = this.Options.PortName,
BaudRate = (int)this.Options.BaudRate,
DataBits = (int)this.Options.DataBits,
Parity = this.Options.Parity,
StopBits = this.Options.StopBits,
RtsEnable = this.Options.RtsEnabled,
DtrEnable = this.Options.DtrEnabled
};
this.serialPort.Disposed += this.Port_Disposed;
this.serialPort.ErrorReceived += this.Port_ErrorReceived;
this.serialPort.Open();
}
catch (Exception e)
{
this.LogMessage?.Invoke(e.Message);
}
}
public virtual void Close()
{
try
{
if (this.serialPort != null)
{
this.serialPort.Disposed -= this.SerialPort_Disposed;
this.serialPort.ErrorReceived -= this.SerialPort_ErrorReceived;
this.serialPort.PinChanged -= this.SerialPort_PinChanged;
}
this.serialPort?.Close();
this.serialPort?.Dispose();
}
catch (Exception e)
{
this.StateChanged?.Invoke(SerialPortState.ErrorReceived, e.ToString());
this.LogMessage?.Invoke(e.ToString());
}
this.serialPort = null;
this.state = SerialPortState.Closed;
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} closed.");
if (this.LogMessage != null)
{
foreach (var @delegate in this.LogMessage.GetInvocationList())
{
if (@delegate is LogMessageEventHandler eventHandler)
{
this.LogMessage -= eventHandler;
}
}
}
if (this.StateChanged != null)
{
foreach (var @delegate in this.StateChanged.GetInvocationList())
{
if (@delegate is StateChangedEventHandler eventHandler)
{
this.StateChanged -= eventHandler;
}
}
}
if (this.DataReceived != null)
{
foreach (var @delegate in this.DataReceived.GetInvocationList())
{
if (@delegate is DataReceivedHandler eventHandler)
{
this.DataReceived -= eventHandler;
}
}
}
}
private void Port_Disposed(Object sender, EventArgs args)
{
this.Dispose();
this.LogMessage?.Invoke("... Port disposed internal");
}
private void Port_ErrorReceived(Object sender, SerialErrorReceivedEventArgs args)
{
this.LogMessage?.Invoke("... Port error received");
this.LogMessage?.Invoke($"... {args.EventType}");
if (!this.serialPort.IsOpen)
{
this.Dispose();
}
}
public virtual void Open()
{
try
{
var fileInfo = new FileInfo(this.Options.LogFile);
fileInfo.Directory.Create();
File.AppendAllText(this.Options.LogFile, string.Empty);
this.LogMessage += this.SerialPortConnection_LogMessage;
}
catch (Exception e)
{
this.state = SerialPortState.ErrorReceived;
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName}: {e}");
this.LogMessage?.Invoke(e.ToString());
}
try
{
this.serialPort = new SerialPort
{
PortName = this.Options.PortName,
BaudRate = (int)this.Options.BaudRate,
DataBits = (int)this.Options.DataBits,
Parity = this.Options.Parity,
StopBits = this.Options.StopBits,
RtsEnable = this.Options.RtsEnabled,
DtrEnable = this.Options.DtrEnabled
};
this.serialPort.Disposed += this.SerialPort_Disposed;
this.serialPort.ErrorReceived += this.SerialPort_ErrorReceived;
this.serialPort.PinChanged += this.SerialPort_PinChanged;
this.DataReceived += this.SerialPortConnection_DataReceived;
this.StateChanged += this.SerialPortConnection_StateChanged;
this.serialPort.Open();
this.state = SerialPortState.Open;
this.StateChanged?.Invoke(this.state
, $"{this.Options.PortName} opened"
+ $", {this.Options.BaudRate}"
+ $", {this.Options.DataBits}"
+ $", {this.Options.Parity}"
+ $", {this.Options.StopBits}");
}
catch (Exception e)
{
this.state = SerialPortState.ErrorReceived;
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName}: {e}");
this.LogMessage?.Invoke(e.ToString());
this.Close();
}
}
protected void InvokeLogMessage(string message)
=> this.LogMessage?.Invoke(message);
protected void Write(params byte[] bytes)
{
if (this.BeginWaitingResponseAsync())
{
lock (this.serialPort)
{
this.serialPort.Write(bytes, 0, bytes.Length);
}
this.LogMessage?.Invoke($"TX: {BitConverter.ToString(bytes)}");
}
}
protected abstract void SerialPortConnection_DataReceived(byte[] bytes);
protected void SerialPortConnection_LogMessage(string message)
{
try
{
File.AppendAllText(this.Options.LogFile, $"{message}{Environment.NewLine}");
}
catch (Exception e)
{
this.LogMessage?.Invoke(e.ToString());
}
}
protected void SerialPortConnection_StateChanged(SerialPortState state, string message)
{
try
{
File.AppendAllText(this.Options.LogFile, $"[{state}] {message}{Environment.NewLine}");
}
catch (Exception e)
{
this.LogMessage?.Invoke(e.ToString());
}
}
private void SerialPort_PinChanged(object sender, SerialPinChangedEventArgs args)
{
this.state = SerialPortState.PinChanged;
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} {args.EventType}.");
this.Close();
}
private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs args)
{
this.state = SerialPortState.ErrorReceived;
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} {args.EventType}.");
this.Close();
}
private void SerialPort_Disposed(object sender, EventArgs args)
{
this.state = SerialPortState.Disposed;
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName} disposed.");
this.Close();
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs args)
{
var bytes = new byte[this.serialPort.BytesToRead];
this.serialPort.Read(bytes, 0, this.serialPort.BytesToRead);
this.DataReceived?.Invoke(bytes);
this.LogMessage?.Invoke($"RX: {BitConverter.ToString(bytes)}");
}
private bool BeginWaitingResponseAsync()
{
var buffer = new byte[1024];
var baseStream = this.serialPort.BaseStream;
var ar = baseStream.BeginRead(buffer, 0, buffer.Length, delegate(IAsyncResult asyncResult)
{
try
{
var actualLength = baseStream.EndRead(asyncResult);
if (actualLength <= 0)
{
return;
}
var received = new byte[actualLength];
Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
this.DataReceived?.Invoke(received);
this.LogMessage?.Invoke($"RX: {BitConverter.ToString(received)}");
}
catch (Exception e)
{
this.StateChanged?.Invoke(this.state, $"{this.Options.PortName}: {e}");
this.LogMessage?.Invoke(e.ToString());
}
}, null);
Task.Factory.StartNew(ar.AsyncWaitHandle.WaitOne);
return this.serialPort != null && this.serialPort.IsOpen;
}
}
}
@@ -1,48 +0,0 @@
namespace OmniPlus.Connections
{
using System;
internal class SerialTextStream : SerialPortStream
{
public SerialTextStream(SerialPortSettings settings) : base(settings)
{
}
public string ReadLine()
{
try
{
if (this.IsOpen)
{
return this.serialPort.ReadLine();
}
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
return default(string);
}
public void WriteLine(string line)
{
try
{
if (this.IsOpen)
{
var _lock = new object();
lock (_lock)
{
this.serialPort.WriteLine(line);
}
}
}
catch (Exception e)
{
this.NotifyStateChanged(e);
}
}
}
}
@@ -1,92 +0,0 @@
namespace OmniPlus.Connections
{
using OmniPlus.Enums;
using OmniPlus.Hanlers;
using System;
using System.IO.Ports;
using System.Threading;
internal class UniProConnection : SerialPortConnection
{
protected event DataReceivedHandler MessageReceived;
public UniProConnection(string portName)
{
this.Options.PortName = portName;
this.Options.BaudRate = BaudRate.K2400;
this.Options.DataBits = DataBits.X8;
this.Options.Parity = Parity.None;
this.Options.StopBits = StopBits.One;
this.Options.LogFile = $".\\UniPro\\[{portName}].txt";
}
public byte[] SendMessage(byte[] command)
{
var response = new byte[0];
var received = false;
if (command is null)
{
return response;
}
void MessageReceivedHandler(byte[] bytes)
{
response = bytes.FromUniProMessage();
received = true;
}
this.MessageReceived += MessageReceivedHandler;
var request = command.ToUniProMessage();
var sleep = 33000;
var delay = 1000;
this.Write(request);
while (!received && sleep >= 0)
{
sleep -= delay;
Thread.Sleep(delay);
}
this.MessageReceived -= MessageReceivedHandler;
return response;
}
protected override void SerialPortConnection_DataReceived(byte[] bytes)
{
var message = default(byte[]);
var length = bytes.Length;
var start = 0;
while (start < bytes.Length)
{
if (bytes[start] == OmniPlusExtensions.UNIPRO_START)
{
try
{
var messageLength = bytes[start + 2];
messageLength += OmniPlusExtensions.UNIPRO_MIN_LENGTH;
message = new byte[messageLength];
Array.Copy(bytes, start, message, 0, messageLength);
}
catch (Exception e)
{
this.SerialPortConnection_LogMessage(e.ToString());
}
break;
}
start++;
}
this.MessageReceived?.Invoke(message);
}
}
}
-19
View File
@@ -1,19 +0,0 @@
namespace OmniPlus.Enums
{
public enum BaudRate
{
K300 = 300,
K600 = 600,
K1200 = 1200,
K2400 = 2400,
K4800 = 4800,
K9600 = 9600,
K19200 = 19200,
K38400 = 38400,
K57600 = 57600,
K115200 = 115200,
K230400 = 230400,
K460800 = 460800,
K921600 = 921600
}
}
-10
View File
@@ -1,10 +0,0 @@
namespace OmniPlus.Enums
{
public enum DataBits
{
X5 = 5,
X6 = 6,
X7 = 7,
X8 = 8
}
}
-11
View File
@@ -1,11 +0,0 @@
namespace OmniPlus.Enums
{
public enum SerialPortState
{
Closed,
Disposed,
PinChanged,
ErrorReceived,
Open
}
}
@@ -1,4 +0,0 @@
namespace OmniPlus.Hanlers
{
internal delegate void DataReceivedHandler(byte[] bytes);
}
@@ -1,4 +0,0 @@
namespace OmniPlus.Hanlers
{
internal delegate void LogMessageEventHandler(string message);
}
@@ -1,4 +0,0 @@
namespace OmniPlus.Hanlers
{
internal delegate byte[] MessageHandler(params byte[] bytes);
}
@@ -1,6 +0,0 @@
using OmniPlus.Enums;
namespace OmniPlus.Hanlers
{
internal delegate void StateChangedEventHandler(SerialPortState state, string reason);
}
-84
View File
@@ -1,84 +0,0 @@
namespace OmniPlus
{
using System;
using System.Collections.Concurrent;
using System.IO.Ports;
using System.Linq;
public class OMNIPool
{
private readonly ConcurrentDictionary<OMNISlot, OMNIFeatures> features;
private readonly ConcurrentDictionary<OMNISlot, OMNIConnection> connections;
public OMNIPool()
{
this.connections = new ConcurrentDictionary<OMNISlot, OMNIConnection>();
}
public void AddConnection(String portNr)
{
var slot = new OMNISlot(this.connections.Count + 1, portNr);
_ = this.features.AddOrUpdate(slot, new OMNIFeatures(), (_slot, _) => new OMNIFeatures());
_ = this.connections.AddOrUpdate(slot, new OMNIConnection(slot), (_slot, _) => new OMNIConnection(_slot));
}
}
public class OMNIConnection
{
private readonly OMNISlot slot;
private readonly OMNIFeatures features;
public OMNIConnection(OMNISlot slot)
{
this.slot = slot;
this.features = new OMNIFeatures();
}
}
public class OMNIFeatures
{
}
public class OMNISlot : IComparable<OMNISlot>
{
public OMNISlot(Int32 nr, String port)
{
if (string.IsNullOrWhiteSpace(port))
{
throw new ArgumentNullException("COM port is required!");
}
else if (!SerialPort.GetPortNames().Any(x => x == port))
{
throw new ArgumentException("COM port dose not exists!");
}
this.Nr = nr;
this.Port = port;
}
public Int32 Nr { get; }
public String Port { get; }
public Int32 CompareTo(OMNISlot other)
{
return this.Port.CompareTo(other.Port);
}
public override Boolean Equals(Object other)
{
return this.Equals(other);
}
public override Int32 GetHashCode()
{
return this.Port.GetHashCode();
}
public override String ToString()
{
return $"{this.Nr}. {this.Port}";
}
}
}
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="PSNR" value="2015"/>
<add key="Type" value="T2" />
<add key="COMPorts" value="COM4" />
<add key="ExchangeHubURL" value="http://sla12iis01.emea.sensus.net/LaaProductionWeb" />
<add key="OmniDB" value="Server=SLASQL01.emea.sensus.net; Database=AuftragKopie; User ID=sa; Password=sqlserver;" />
</appSettings>
</configuration>
+151
View File
@@ -0,0 +1,151 @@
<Application x:Class="OMNIPruefung.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Helpers="clr-namespace:OMNIPruefung.Helpers"
xmlns:ContentV="clr-namespace:OMNIPruefung.Views.Content"
xmlns:OptionsV="clr-namespace:OMNIPruefung.Views.Options"
xmlns:ContentVM="clr-namespace:OMNIPruefung.ViewModels.Content"
xmlns:OptionsVM="clr-namespace:OMNIPruefung.ViewModels.Options"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="Label">
<Setter Property="FontFamily" Value="Consolas" />
<Setter Property="Padding" Value="0" />
</Style>
<Style TargetType="TextBox">
<Setter Property="Padding" Value="3, 5" />
<Setter Property="FontFamily" Value="Consolas" />
</Style>
<Style TargetType="Button">
<Setter Property="FontFamily" Value="Consolas" />
</Style>
<SolidColorBrush x:Key="LightBlue" Color="#ECF0F1" />
<SolidColorBrush x:Key="DarkBlue" Color="#003595" />
<SolidColorBrush x:Key="Blue" Color="#0072CE" />
<SolidColorBrush x:Key="HoverBlue" Color="#110072CE" />
<SolidColorBrush x:Key="Green" Color="#71D54C" />
<SolidColorBrush x:Key="HoverGreen" Color="#1171D54C" />
<SolidColorBrush x:Key="Red" Color="#CF2E2E" />
<SolidColorBrush x:Key="HoverRed" Color="#11F78DA7" />
<Style x:Key="SystemBtn" TargetType="{x:Type Button}">
<Setter Property="Background" Value="{x:Static SystemColors.ControlBrush}" />
<Setter Property="BorderBrush" Value="{x:Static SystemColors.ControlBrush}" />
<Setter Property="Foreground" Value="{x:Static SystemColors.ControlTextBrush}" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontFamily" Value="Consolas" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="13, 0, 0, 0" />
<Setter Property="Padding" Value="13, 8"/>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border"
CornerRadius="3.5"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="border" Value="{x:Static SystemColors.ControlLightBrush}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static SystemColors.ControlDarkBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="border" Value="{x:Static SystemColors.ControlLightBrush}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static SystemColors.ControlDarkBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="border" Value="{x:Static SystemColors.ControlLightBrush}"/>
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static SystemColors.ControlDarkBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Helpers:BooleanVisibilityConverter x:Key="BooleanVisibility" />
<Helpers:BooleanProgressBackgroundConverter x:Key="BooleanProgress" />
<Style x:Key="RadioNodeStyle" TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}">
<ContentPresenter SnapsToDevicePixels="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#55f0f0f0" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="AliceBlue" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsChecked" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="AliceBlue" />
</MultiTrigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type OptionsVM:MainOptionVM}">
<OptionsV:Option DataContext="{Binding .}" Icon="/Images/folder.png"/>
</DataTemplate>
<DataTemplate DataType="{x:Type OptionsVM:ExchangeHubOptionVM}">
<OptionsV:Option DataContext="{Binding .}" Icon="/Images/folder.png"/>
</DataTemplate>
<DataTemplate DataType="{x:Type OptionsVM:EOLOptionVM}">
<OptionsV:Option DataContext="{Binding .}" Icon="/Images/folder.png"/>
</DataTemplate>
<DataTemplate DataType="{x:Type OptionsVM:COMOptionVM}">
<OptionsV:COMOption DataContext="{Binding .}" ProgressIcon="/Images/meter.png"/>
</DataTemplate>
<DataTemplate DataType="{x:Type ContentVM:MainContentVM}">
<Label Content="{Binding Header}" />
</DataTemplate>
<DataTemplate DataType="{x:Type ContentVM:ExchangeHubContentVM}">
<ContentV:ExchangeHub DataContext="{Binding .}" />
</DataTemplate>
<DataTemplate DataType="{x:Type ContentVM:EOLContentVM}">
<ContentV:EOLContent DataContext="{Binding .}" />
</DataTemplate>
<DataTemplate DataType="{x:Type ContentVM:COMContentVM}">
<ContentV:COMContent DataContext="{Binding .}" />
</DataTemplate>
<!--<a href="https://www.flaticon.com/free-icons/folder" title="folder icons">Folder icons created by kmg design - Flaticon</a>-->
<!--<a href="https://www.flaticon.com/free-icons/water-meter" title="water meter icons">Water meter icons created by Umeicon - Flaticon</a>-->
<!--<a href="https://www.flaticon.com/free-icons/settings" title="settings icons">Settings icons created by Freepik - Flaticon</a>-->
</Application.Resources>
</Application>
+27
View File
@@ -0,0 +1,27 @@
namespace OMNIPruefung
{
using System;
using System.IO;
using System.Windows;
using System.Windows.Threading;
public partial class App : Application
{
public static readonly string ExePath = typeof(App).Assembly.Location;
public static readonly string Path = new FileInfo(ExePath).DirectoryName;
public static event Action Disposed;
public static void Invoke(Action action)
=> Current.Dispatcher.Invoke(action, DispatcherPriority.ApplicationIdle);
public static void BeginInvoke(Action action)
=> Current.Dispatcher.BeginInvoke(action, DispatcherPriority.ApplicationIdle);
public static void NotifyDisposed()
=> Disposed?.Invoke();
protected override void OnExit(ExitEventArgs _)
=> NotifyDisposed();
}
}
@@ -0,0 +1,44 @@
namespace OMNIPruefung.Helpers
{
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
public class BooleanProgressBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean)
{
if (boolean)
{
return Brushes.Green;
}
else
{
return Brushes.Red;
}
}
return Brushes.Gray;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Brush brush)
{
if (brush == Brushes.Green)
{
return true;
}
else if (brush == Brushes.Red)
{
return false;
}
}
return default(bool?);
}
}
}
@@ -0,0 +1,16 @@
namespace OMNIPruefung.Helpers
{
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
public class BooleanVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> value is bool visible && visible ? Visibility.Visible : Visibility.Collapsed;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value is Visibility visibility && visibility == Visibility.Visible;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

@@ -0,0 +1,48 @@
<Window x:Class="OMNIPruefung.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ContentVM="clr-namespace:OMNIPruefung.ViewModels.Content"
Icon="/Images/logo.png"
Background="LightGray"
Title="OMNI+ Pruefung"
Height="450"
Width="800">
<Window.DataContext>
<ContentVM:MainContentVM />
</Window.DataContext>
<Grid Margin="0, 3, 0, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="230" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0"
Background="White"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Options}" Margin="2, 0"/>
</ScrollViewer>
<GridSplitter Grid.Column="1"
ResizeDirection="Columns"
ResizeBehavior="PreviousAndNext"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="LightGray"
Width="3"/>
<DockPanel Grid.Column="2"
Background="White">
<ContentControl Content="{Binding Content}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="White"/>
</DockPanel>
</Grid>
</Window>
@@ -0,0 +1,12 @@
using System.Windows;
namespace OMNIPruefung
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
}
}
@@ -0,0 +1,86 @@
namespace OMNIPruefung.Models
{
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
public class Appsettings
{
private static readonly Configuration configuration
= ConfigurationManager.OpenExeConfiguration(App.ExePath);
private static readonly KeyValueConfigurationCollection appsettings
= configuration.AppSettings.Settings;
public event Action StateChanged;
public string this[string key]
{
get
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentNullException(nameof(key), "Should not be null or white space.");
}
var existingKey = appsettings.AllKeys.FirstOrDefault(x => x.Equals(key, StringComparison.OrdinalIgnoreCase));
if (string.IsNullOrWhiteSpace(existingKey))
{
appsettings.Add(key, string.Empty);
}
return appsettings[key].Value;
}
set
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentNullException(nameof(key), "Should not be null or white space.");
}
var existingKey = appsettings.AllKeys.FirstOrDefault(x => x.Equals(key, StringComparison.OrdinalIgnoreCase));
if (string.IsNullOrWhiteSpace(existingKey))
{
appsettings.Add(key, string.Empty);
}
appsettings[key].Value = value;
configuration.Save(ConfigurationSaveMode.Full, true);
this.StateChanged?.Invoke();
}
}
public string PSNR => this[nameof(PSNR)];
public IEnumerable<string> AllKeys => appsettings.AllKeys;
}
public class ExchangeHubSettings : Appsettings
{
public string ExchangeHubURL
{
get => base[nameof(this.ExchangeHubURL)];
set => base[nameof(this.ExchangeHubURL)] = value;
}
public string ExchangeHubOutputDir
{
get => base[nameof(this.ExchangeHubOutputDir)];
set => base[nameof(this.ExchangeHubOutputDir)] = value;
}
}
public class EOLSettings : Appsettings
{
public IEnumerable<string> COMPorts
=> this[nameof(COMPorts)]
?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?? new string[] { };
public string OmniDB => this[nameof(OmniDB)];
}
}
@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D766BA80-CCA1-4D05-96B9-AAE520F30595}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>OMNIPruefung</RootNamespace>
<AssemblyName>OMNIPruefung</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Helpers\BooleanProgressBackgroundConverter.cs" />
<Compile Include="Helpers\BooleanVisibilityConverter.cs" />
<Compile Include="Models\Appsettings.cs" />
<Compile Include="ViewModels\Content\SettingsContentVM.cs" />
<Compile Include="ViewModels\Features\OMNIPlusVM.cs" />
<Compile Include="ViewModels\Base\Command.cs" />
<Compile Include="ViewModels\Base\Command[T].cs" />
<Compile Include="ViewModels\Base\VM[T].cs" />
<Compile Include="ViewModels\ContentVM.cs" />
<Compile Include="ViewModels\Content\COMContentVM.cs" />
<Compile Include="ViewModels\Content\EOLContentVM.cs" />
<Compile Include="ViewModels\Content\ExchangeHubContentVM.cs" />
<Compile Include="ViewModels\Content\MainContentVM.cs" />
<Compile Include="ViewModels\Features\OMNISysParameters.cs" />
<Compile Include="ViewModels\NodeVM.cs" />
<Compile Include="ViewModels\Options\COMOptionVM.cs" />
<Compile Include="ViewModels\Options\EOLOptionVM.cs" />
<Compile Include="ViewModels\Options\ExchangeHubOptionVM.cs" />
<Compile Include="ViewModels\Options\MainOptionVM.cs" />
<Compile Include="ViewModels\Options\SettingsOptionVM.cs" />
<Compile Include="ViewModels\OptionVM.cs" />
<Compile Include="Views\Content\COMContent.xaml.cs">
<DependentUpon>COMContent.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Content\EOLContent.xaml.cs">
<DependentUpon>EOLContent.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Content\ExchangeHub.xaml.cs">
<DependentUpon>ExchangeHub.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Options\COMOption.xaml.cs">
<DependentUpon>COMOption.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Options\Option.xaml.cs">
<DependentUpon>Option.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Views\Content\COMContent.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Content\EOLContent.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Content\ExchangeHub.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Options\COMOption.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Options\Option.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ExchangeHub\ExchangeHub.csproj">
<Project>{6033FF0C-CF32-4BC5-8EFE-4774CCDC663D}</Project>
<Name>ExchangeHub</Name>
</ProjectReference>
<ProjectReference Include="..\OmniPlus\OmniPlus.csproj">
<Project>{F8D84B9A-0FCF-4083-B067-8C39B7314152}</Project>
<Name>OmniPlus</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Images\empty.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Images\folder.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Images\logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Images\meter.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Images\settings.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,54 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// C:\Users\SZLATEV\source\repos\laa_production\Common\OMNIPruefung\Properties\AssemblyInfo.cs
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OMNI+ Prüfung")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OMNI+ Prüfung")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[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)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OMNIPruefung.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PruefsoftwareUI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OMNIPruefung.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
@@ -0,0 +1,25 @@
namespace OMNIPruefung.ViewModels.Base
{
using System;
using System.Windows.Input;
public class Command : ICommand
{
private readonly Action commandHandler;
public Command(Action commandHandler)
=> this.commandHandler = commandHandler;
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
=> this.commandHandler != null;
public void Execute(object parameter)
=> this.commandHandler?.Invoke();
}
}
@@ -0,0 +1,25 @@
namespace OMNIPruefung.ViewModels.Base
{
using System;
using System.Windows.Input;
public class Command<T> : ICommand
{
private readonly Action<T> commandCallback;
public Command(Action<T> commandCallback)
=> this.commandCallback = commandCallback;
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
=> this.commandCallback != null;
public void Execute(object parameter)
=> this.commandCallback?.Invoke(parameter is T value ? value : default(T));
}
}
@@ -0,0 +1,12 @@
namespace OMNIPruefung.ViewModels.Base
{
using System.ComponentModel;
public abstract class VM<T> : INotifyPropertyChanged where T : VM<T>
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string property)
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
@@ -0,0 +1,437 @@
namespace OMNIPruefung.ViewModels.Content
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OmniPlus;
using OmniPlus.Features;
using OMNIPruefung.ViewModels.Base;
using OMNIPruefung.ViewModels.Features;
using OMNIPruefung.ViewModels.Options;
public class COMContentVM : ContentVM
{
private readonly Dictionary<OmniPlusTestPoint, OmniPlusTest> results
= new Dictionary<OmniPlusTestPoint, OmniPlusTest>();
private OmniPlusConnection connection;
public COMContentVM() : base()
{
this.Meter = new OMNIPlusVM();
this.Option = new COMOptionVM(this);
this.Option.OptionSelected += this.NotifyOptionSelected;
}
private int progress;
public int Progress
{
get => this.progress;
set
{
this.progress = value;
this.NotifyPropertyChanged(nameof(this.Progress));
}
}
private bool running;
public bool Running
{
get => this.running;
set
{
this.running = value;
this.NotifyPropertyChanged(nameof(this.Running));
}
}
private bool connected;
public bool Connected
{
get => this.connected;
set
{
this.connected = value;
this.NotifyPropertyChanged(nameof(this.Connected));
}
}
private bool visible;
public bool Visible
{
get => this.visible;
set
{
this.visible = value;
this.NotifyPropertyChanged(nameof(this.Visible));
}
}
private string state;
public string State
{
get => this.state;
set
{
this.state = value;
this.NotifyPropertyChanged(nameof(this.State));
}
}
private int nr;
public int Nr
{
get => this.nr;
set
{
this.nr = value;
this.NotifyPropertyChanged(nameof(this.Nr));
}
}
private string portName;
public string PortName
{
get => this.portName;
set
{
this.portName = value;
this.connection = new OmniPlusConnection(value);
this.NotifyPropertyChanged(nameof(this.PortName));
}
}
private string testResults;
public string TestResults
{
get => this.testResults;
set
{
this.testResults = value;
this.NotifyPropertyChanged(nameof(this.TestResults));
}
}
public int AvailableIn { get; set; }
public OMNIPlusVM Meter { get; }
internal void CancelExecution()
{
this.State = "Prüfung abgebrochen.";
this.Connected = false;
this.Running = false;
}
internal Task InitializeAsync(CancellationToken cancellationToken)
{
cancellationToken.Register(this.Dispose);
void Initialize()
{
this.results.Clear();
this.Header = $"{this.PortName}";
this.State = this.Header;
this.State = $"{this.Header} - wird ermittelt ...";
try
{
this.Connected = this.connection.Connected;
if (!this.Connected)
{
this.Connected = this.connection.ConnectIrda();
this.Running = this.Connected;
}
if (this.IsRunning())
{
this.State = "Mit IRDA verbunden";
}
else
{
this.connection.Disconnect();
this.Header = $"({this.PortName} - nicht verbunden!)";
this.State = this.Header;
}
}
catch (Exception e)
{
this.connection.Disconnect();
this.Header = $"({this.PortName} - nicht vorhanden!)";
this.State = this.Header;
}
}
return Task.Factory.StartNew(Initialize, cancellationToken);
}
internal Task ReadSystemParametersAsync(CancellationToken cancelationToken)
{
cancelationToken.Register(this.Dispose);
void ReadSystemParameters()
{
if (this.IsRunning())
{
var response = this.connection.ViewSystemParameters();
this.Meter.Add(response);
this.Header = response.BuildInfo.Value;
this.Running = response.IsValid;
if (this.Running)
{
this.State = "Systemeigenschaften gelesen und validiert";
}
else
{
this.State = "Systemeigenschaften konnten nicht gelesen werden";
}
this.Progress += 10;
}
else
{
this.State += $" (Verbindung unterbrochen)";
}
}
return Task.Factory.StartNew(ReadSystemParameters, cancelationToken);
}
internal Task SetInputVolumeAsync(OmniPlusType defaults, CancellationToken cancelationToken)
{
cancelationToken.Register(this.Dispose);
void SetInputVolume()
{
if (this.Connected)
{
var response = this.connection.Set(defaults.InputVolume);
this.Running = response.Succeeded;
if (this.Running)
{
this.State = "Flow-Eigenschaften konfiguriert";
}
else
{
this.State = $"Flow-Eigenschaften: ({(int)response.Status} - {response.Status})";
}
this.Progress += 10;
}
else
{
this.State += $" (Verbindung unterbrochen)";
}
}
return Task.Factory.StartNew(SetInputVolume, cancelationToken);
}
internal Task SetReferenceVolumeAsync(OmniPlusTestPoint pp, double referenceV, CancellationToken cancellationToken)
{
cancellationToken.Register(this.Dispose);
void SetReferenceVolume()
{
if (this.results.ContainsKey(pp))
{
this.results[pp].VolumeMessured = referenceV;
}
}
return Task.Factory.StartNew(SetReferenceVolume, cancellationToken);
}
internal Task SaveInspectionAsync(CancellationToken cancellationToken)
{
cancellationToken.Register(this.Dispose);
void SaveInspection()
{
if (!this.IsRunning())
{
return;
}
var resultsBuilder = new StringBuilder();
resultsBuilder.AppendLine($"GPM\t"
+ $"m³/h\t"
+ $"ml/R\t"
+ $"R(soll)\t"
+ $"R(ist)\t"
+ $"T(soll)\t"
+ $"T(ist)\t"
+ $"m³(ist)\t"
+ $"Diff %\t"
+ $"Factor %\t"
+ $"Min\t"
+ $"Max\t");
foreach (var kvp in this.results)
{
var pruefpunkt = kvp.Key;
var ergebnis = kvp.Value;
resultsBuilder.AppendLine($"{pruefpunkt.GalPerMin:0.00}\t"
+ $"{pruefpunkt.VolumeM3H:0.00}\t"
+ $"{pruefpunkt.MlPerRotation:0.00}\t"
+ $"{pruefpunkt.Rotations}\t"
+ $"{ergebnis.Rotations}\t"
+ $"{pruefpunkt.Duration}\t"
+ $"{ergebnis.Duration}\t"
+ $"{ergebnis.VolumeMessured}\t"
+ $"{ergebnis.DifferencePercentage:0.00}%\t"
+ $"{this.GetCorrectionFactor():0.00}%\t"
+ $"{pruefpunkt.MinDiff:0.00}\t"
+ $"{pruefpunkt.MaxDiff:0.00}\t");
}
this.TestResults = resultsBuilder.ToString();
try
{
File.WriteAllText($"{this.Header}_{DateTime.Now:yyyyMMddHHmmss}.csv", this.TestResults);
}
catch (Exception e)
{
this.State = e.ToString();
}
}
return Task.Factory.StartNew(SaveInspection, cancellationToken);
}
internal Task StartPPCalibrationAsync(OmniPlusTestPoint pp, CancellationToken cancellationToken)
{
cancellationToken.Register(this.Dispose);
void StartPPCalibration()
{
this.results[pp] = new OmniPlusTest();
//if (this.IsRunning())
//{
// var rotations = pp.Rotations;
// var duration = pp.Duration;
// var activationResponse = connection.StartChamberCalibration(pp.Rotations, pp.Duration);
// this.Running = activationResponse.Succeeded && activationResponse.Control == ChamberCalibrationResponse.TEST_ACTIVATED;
// if (this.Running)
// {
// this.State = $"PP {rotations}/{duration} (rotations/seconds) wurde gestarted.";
// }
// else
// {
// this.State = $"PP {rotations}/{duration} (rotations/seconds): {(int)activationResponse.Status} - {activationResponse.Status}";
// }
//}
this.Progress += 10;
}
return Task.Factory.StartNew(StartPPCalibration, cancellationToken);
}
internal Task StopPPCalibrationAsync(OmniPlusTestPoint pp, byte[] response, CancellationToken cancellationToken)
{
cancellationToken.Register(this.Dispose);
void StopPPCalibration()
{
if (this.IsRunning())
{
// var calibrationResult = connection.ViewChamberCalibration();
var calibrationResult = new ChamberCalibrationResponse(response);
this.results[pp].Rotations = calibrationResult.Rotations;
this.results[pp].Duration = calibrationResult.Duration;
this.results[pp].MeterVolume = pp.VolumeM3(this.results[pp]);
this.Running = calibrationResult.Succeeded && calibrationResult.Control == ChamberCalibrationResponse.TEST_COMPLETED;
if (this.Running)
{
this.State = $"PP {pp.Rotations}/{pp.Duration} (rotations/seconds) wurde durchgeführt.";
}
else
{
this.State = $"PP {pp.Rotations}/{pp.Duration} fehlgeschlagen: {(int)calibrationResult.Control} - {calibrationResult.Control}";
}
}
this.Progress += 10;
}
return Task.Factory.StartNew(StopPPCalibration, cancellationToken);
}
internal double GetCorrectionFactor()
{
var correction = this.results
.OrderBy(x => x.Key.GalPerMin)
.Select(x => x.Value.DifferencePercentage)
.ToArray()
.GetCorrectionFactor();
this.State = $"Korekturfaktor: {correction:0.00} %";
return correction;
}
public override void Dispose()
{
try
{
this.SaveInspectionAsync(CancellationToken.None).Wait();
this.connection?.Disconnect();
}
catch (Exception e)
{
this.State = e.Message;
}
try
{
this.results.Clear();
}
catch (Exception e)
{
this.State = e.Message;
}
}
private bool IsRunning()
{
if (!this.Running)
{
return false;
}
this.Connected = this.connection.Connected;
return this.Connected;
}
}
}
@@ -0,0 +1,648 @@
namespace OMNIPruefung.ViewModels.Content
{
using ExchangeHub;
using OmniPlus;
using OMNIPruefung.Models;
using OMNIPruefung.ViewModels.Base;
using OMNIPruefung.ViewModels.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using TimersTimer = System.Timers.Timer;
public class EOLContentVM : ContentVM
{
private static readonly string line = new string('=', 500);
private readonly EOLSettings omnisettings;
private readonly ExchangeHubSettings hubsettings;
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
private OmniPlusDatabase dbcontext;
private ExchangeConnection signalR;
private ManualResetEventSlim awaiter;
private ICollection<Task> tasks;
private TimersTimer timer;
private bool canceled;
public EOLContentVM() : base()
{
this.Header = "EOL";
this.CanStop = false;
this.CanStart = true;
this.Option = new EOLOptionVM(this);
this.Option.OptionSelected += this.NotifyOptionSelected;
this.omnisettings = new EOLSettings();
this.hubsettings = new ExchangeHubSettings();
this.OmniDefaults = new OmniPlusType();
this.tasks = new List<Task>();
this.dbcontext = new OmniPlusDatabase(this.omnisettings.OmniDB);
this.signalR = new ExchangeConnection();
this.signalR.OutputDir = this.hubsettings.ExchangeHubOutputDir;
this.signalR.Connect(this.hubsettings.ExchangeHubURL);
this.LoadComPorts = new Command(this.PrepareConnections);
this.CancelInspection = new Command(this.CancelInspectionHandler);
this.StartInspection = new Command(this.StartInspectionHandler);
this.PrepareConnections();
}
private int size;
public int Size
{
get => this.size;
set
{
this.size = value;
this.NotifyPropertyChanged(nameof(this.Type));
}
}
private string type;
public string Type
{
get => this.type;
set
{
this.type = value;
this.NotifyPropertyChanged(nameof(this.Type));
}
}
private string text;
public string Text
{
get => this.text;
set
{
this.text = value;
this.NotifyPropertyChanged(nameof(this.Text));
}
}
private string error;
public string Error
{
get => this.error;
set
{
this.error = value;
this.NotifyPropertyChanged(nameof(this.Error));
}
}
private string state;
public string State
{
get => this.state;
set
{
this.state = value;
this.NotifyPropertyChanged(nameof(this.State));
}
}
private bool canStart;
public bool CanStart
{
get => this.canStart;
set
{
this.canStart = value;
this.NotifyPropertyChanged(nameof(this.CanStart));
}
}
private bool canStop;
public bool CanStop
{
get => this.canStop;
set
{
this.canStop = value;
this.NotifyPropertyChanged(nameof(this.CanStop));
}
}
private int secondsLeft;
public int AvailableIn
{
get => this.secondsLeft;
set
{
this.secondsLeft = value;
this.NotifyPropertyChanged(nameof(this.AvailableIn));
}
}
private OmniPlusType omniDefaults;
public OmniPlusType OmniDefaults
{
get => this.omniDefaults;
set
{
this.omniDefaults = value;
this.NotifyPropertyChanged(nameof(this.OmniDefaults));
}
}
public String Line => line;
public ICommand LoadComPorts { get; }
public ICommand CancelInspection { get; }
public ICommand StartInspection { get; }
private void PrepareConnections()
{
if (this.Size == 0 || this.Type is null)
{
this.Error = "Size und Type auswählen!";
return;
}
this.Error = default(string);
if (this.Nodes.Any())
{
foreach (var disposable in this.Nodes.Cast<IDisposable>())
{
disposable.Dispose();
}
this.Nodes.Clear();
this.Option.Clear();
}
this.dbcontext.LoadOmniDefaults((byte)this.Size, this.Type, this.OmniDefaults);
this.NotifyPropertyChanged(nameof(this.OmniDefaults));
this.Text = $"ME OMNI 1.5-2\" {this.Type}";
try
{
var placeNr = 1;
foreach (var com in this.omnisettings.COMPorts)
{
var comVM = new COMContentVM();
comVM.ContentSelected += this.NotifyCotnentSelected;
comVM.PortName = com;
comVM.Nr = placeNr++;
comVM.Header = $"{com}";
comVM.State = $"{com}";
this.Nodes.Add(comVM);
this.Option.Add(comVM.Option);
}
this.Option.SetIndentation(this.Option.Indent);
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in this.Nodes.Cast<COMContentVM>())
{
tasks.Add(meterVM.InitializeAsync(cancellationToken));
}
});
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in this.Nodes.Cast<COMContentVM>())
{
tasks.Add(meterVM.ReadSystemParametersAsync(cancellationToken));
}
}, wait: false);
}
catch (Exception e)
{
this.Error = e.ToString();
}
this.CanStop = false;
this.CanStart = true;
this.Error = default(string);
this.State = default(string);
}
private void CancelInspectionHandler()
{
this.canceled = true;
this.CanStop = false;
this.CanStart = false;
this.Error = default(string);
this.State = "Warte bis abbruch abgeschlossen ...";
try
{
this.signalR.SendStopReferenceMessurement();
this.signalR.NotifyStopQ();
this.awaiter?.Set();
this.cancellationTokenSource?.Cancel();
this.tasks.Clear();
this.State = "Vorgang wurde abbgebrochen!";
}
catch (Exception e)
{
this.Error = e.ToString();
this.State = default(string);
}
this.InvokeAsync(() =>
{
this.WaitUntil(this.AvailableIn, show: true, error: true);
this.CanStart = true;
this.Error = default(string);
this.State = default(string);
}, wait: false);
}
private void StartInspectionHandler()
{
this.canceled = false;
this.CanStart = false;
this.CanStop = true;
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
var metersVM = this.Nodes.Cast<COMContentVM>();
this.InvokeAsync(() =>
{
//this.InvokeAsync((tasks, cancellationToken) =>
//{
// foreach (var meterVM in metersVM)
// {
// tasks.Add(meterVM.SetInputVolumeAsync(this.OmniDefaults, cancellationToken));
// }
//});
var results = new byte[][]
{
new byte[] { 0x01, 0x02, 0x04, 0x00, 0x6F, 0x85, 0x0D, 0x00, 0x01 },
new byte[] { 0x01, 0x02, 0x08, 0x00, 0x4F, 0xFA, 0x11, 0x00, 0x01 },
new byte[] { 0x01, 0x02, 0xE8, 0x03, 0xA1, 0xFB, 0x10, 0x00, 0x02 },
};
for (int i = 0; i < this.OmniDefaults.TestPoints.Count; i++)
{
var pp = this.OmniDefaults.TestPoints[i];
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.StartPPCalibrationAsync(pp, cancellationToken));
}
});
var result = results[i];
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.StopPPCalibrationAsync(pp, result, cancellationToken));
}
});
var referenceV = pp.VolumeM3H * 1;
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.SetReferenceVolumeAsync(pp, referenceV, cancellationToken));
}
});
}
//foreach (var pp in this.OmniDefaults.TestPoints)
//{
// if (this.cancellationTokenSource?.IsCancellationRequested == true)
// {
// break;
// }
// var rotations = pp.Rotations;
// var duration = pp.Duration;
// this.StartFlow(pp.VolumeM3H);
// this.InvokeAsync((tasks, cancellationToken) =>
// {
// foreach (var meterVM in metersVM)
// {
// tasks.Add(meterVM.StartPPCalibrationAsync(pp, cancellationToken));
// }
// });
// this.StartReferenceMessurement(duration);
// this.WaitUntil((int)(duration * 1.2), true, false);
// var referenceV = this.GetReferenceVolume();
// if (this.cancellationTokenSource?.IsCancellationRequested == true)
// {
// break;
// }
// this.InvokeAsync((tasks, cancellationToken) =>
// {
// foreach (var meterVM in metersVM)
// {
// tasks.Add(meterVM.StopPPCalibrationAsync(pp, cancellationToken));
// }
// });
// if (this.cancellationTokenSource?.IsCancellationRequested == true)
// {
// break;
// }
// this.InvokeAsync((tasks, cancellationToken) =>
// {
// foreach (var meterVM in metersVM)
// {
// tasks.Add(meterVM.SetReferenceVolumeAsync(pp, referenceV, cancellationToken));
// }
// });
//}
//this.signalR.NotifyStopQ();
//this.signalR.NotifyStopRef();
this.InvokeAsync((tasks, cancellationToken) =>
{
foreach (var meterVM in metersVM)
{
tasks.Add(meterVM.SaveInspectionAsync(cancellationToken));
}
});
foreach (var meterVM in metersVM)
{
meterVM.GetCorrectionFactor();
}
foreach (var meterVM in metersVM)
{
meterVM.Dispose();
}
this.InvokeAsync(() =>
{
this.WaitUntil(this.AvailableIn, show: true);
this.CanStart = true;
this.Error = default(string);
this.State = default(string);
});
}, wait: false);
}
private void WaitUntil(int duration, bool show = false, bool error = true)
{
if (duration <= 0)
{
this.AvailableIn = 0;
return;
}
this.CanStart = false;
this.awaiter = new ManualResetEventSlim();
this.timer = new TimersTimer(1000)
{
AutoReset = true,
Enabled = true
};
this.timer.Elapsed += (_1, _2) =>
{
this.AvailableIn -= 1;
if (show)
{
if (error)
{
this.State = null;
this.Error = $"Verfügbar in {this.AvailableIn} Sekunden";
}
else
{
this.Error = null;
this.State = $"Noch {this.AvailableIn} Sekunden verbleiben";
}
}
if (this.AvailableIn <= 0)
{
this.AvailableIn = 0;
this.awaiter.Set();
}
};
this.timer.Start();
this.awaiter.Wait(this.AvailableIn * 1000);
this.awaiter = null;
this.timer.Stop();
this.timer = null;
}
public override void Dispose()
{
foreach (var disposable in this.Nodes.Cast<IDisposable>())
{
disposable.Dispose();
}
this.signalR.Dispose();
}
private void StartFlow(double volumeM3H)
{
var received = false;
var volume = volumeM3H;
var timeout = 120; // seconds
void referenceVolumeReceived(double value)
{
timeout = -1;
received = true;
volume = value;
}
this.signalR.StartQ += referenceVolumeReceived;
this.signalR.NotifyStartQ(volumeM3H);
this.State = "Warten auf Q(soll) ...";
while (!received && timeout > 0)
{
if (this.canceled)
{
this.AvailableIn = timeout;
break;
}
Thread.Sleep(1000);
timeout--;
this.State = $"{timeout} Sekunden verbleiben bis Q(soll) erreicht";
}
if (!this.canceled)
{
this.State = $"Durchfluss {volume:0.0000} erreicht ...";
}
}
private void StartReferenceMessurement(int duration)
{
var received = false;
var reference = 0;
var timeout = 30; // seconds
void referenceVolumeReceived(int value)
{
timeout = -1;
received = true;
reference = value;
}
this.signalR.StartRef += referenceVolumeReceived;
this.signalR.SendStartReferenceMessurement(duration);
this.State = "Warten bis RZ gestarted ...";
while (!received && timeout > 0)
{
if (this.canceled)
{
this.AvailableIn = timeout;
break;
}
Thread.Sleep(1000);
timeout--;
this.State = $"{timeout} Sekunden verbleiben ...";
}
if (!this.canceled)
{
this.State = $"Referenzmessung gestartet ...";
}
}
private double GetReferenceVolume()
{
var received = false;
var referenceV = 0D;
var timeout = 30; // seconds
void referenceVolumeReceived(double value)
{
timeout = -1;
received = true;
referenceV = value;
}
this.signalR.StopRef += referenceVolumeReceived;
this.signalR.SendStopReferenceMessurement();
this.State = "Warten RZ Ergebnis ...";
while (!received && timeout > 0)
{
if (this.canceled)
{
this.AvailableIn = timeout;
break;
}
Thread.Sleep(1000);
timeout--;
this.State = $"{timeout} Sekunden verbleiben ...";
}
if (!this.canceled)
{
this.State = $"Referenzmessung bereit ...";
}
return referenceV;
}
private void InvokeAsync(Action<ICollection<Task>, CancellationToken> action, bool wait = true)
{
if (this.cancellationTokenSource?.IsCancellationRequested == true)
{
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
}
this.tasks = new List<Task>();
action?.Invoke(this.tasks, this.cancellationToken);
if (tasks.Any())
{
var handle = Task.Factory
.ContinueWhenAll(this.tasks.ToArray(), _ => { })
.ContinueWith(_ => this.tasks.Clear());
if (wait)
{
handle.Wait();
}
}
}
private void InvokeAsync(Action action, bool wait = true)
{
var handle = Task.Factory.StartNew(action);
if (wait)
{
handle.Wait();
}
}
}
}
@@ -0,0 +1,115 @@
namespace OMNIPruefung.ViewModels.Content
{
using ExchangeHub;
using OMNIPruefung.Models;
using OMNIPruefung.ViewModels.Base;
using OMNIPruefung.ViewModels.Options;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Input;
public class ExchangeHubContentVM : ContentVM
{
private readonly ExchangeHubSettings hubsettings;
private readonly ExchangeConnection connection;
public ExchangeHubContentVM() : base()
{
this.Header = "Exchange HUB";
this.Option = new ExchangeHubOptionVM(this);
this.Option.OptionSelected += this.NotifyOptionSelected;
this.Connect = new Command(this.ConnectHubHandler);
this.Disconnect = new Command(this.DisconnectHubHandler);
this.hubsettings = new ExchangeHubSettings();
this.connection = new ExchangeConnection();
this.connection.OutputDir = this.hubsettings.ExchangeHubOutputDir;
this.connection.StateChanged += this.Connection_StateChanged;
this.NotifyPropertyChanged(nameof(this.LogContent));
}
public string URL
{
get => this.hubsettings.ExchangeHubURL;
set
{
this.hubsettings.ExchangeHubURL = value;
this.NotifyPropertyChanged(nameof(this.URL));
}
}
public string OutputDir
{
get
{
if (string.IsNullOrWhiteSpace(this.hubsettings.ExchangeHubOutputDir))
{
this.hubsettings.ExchangeHubOutputDir = App.Path;
}
return this.hubsettings.ExchangeHubOutputDir;
}
set
{
this.hubsettings.ExchangeHubOutputDir = value;
this.connection.OutputDir = value;
this.NotifyPropertyChanged(nameof(this.OutputDir));
}
}
private bool connected;
public bool Connected
{
get => this.connected;
set
{
this.connected = value;
this.NotifyPropertyChanged(nameof(this.Connected));
this.NotifyPropertyChanged(nameof(this.Disconnected));
}
}
public bool Disconnected => !this.Connected;
public string LogContent { get; private set; }
public ICommand Connect { get; }
public ICommand Disconnect { get; }
private void ConnectHubHandler()
{
Task.Factory.StartNew(() =>
{
this.Connected = this.connection.Connect(this.URL);
});
}
private void Connection_StateChanged(string fileName)
{
try
{
this.LogContent = File.ReadAllText(fileName);
}
catch (Exception e)
{
this.LogContent = e.ToString();
}
this.NotifyPropertyChanged(nameof(this.LogContent));
}
private void DisconnectHubHandler()
{
this.connection.Dispose();
this.Connected = false;
}
}
}
@@ -0,0 +1,46 @@
namespace OMNIPruefung.ViewModels.Content
{
using OMNIPruefung.ViewModels.Base;
using System.Collections.ObjectModel;
public class MainContentVM : ContentVM
{
public MainContentVM() : base()
{
this.Content = this;
this.Header = "OMNI+ Prüfung";
this.ContentSelected += this.SetContentSelected;
this.Options = new ObservableCollection<OptionVM>();
var exchangeHubVM = new ExchangeHubContentVM();
exchangeHubVM.ContentSelected += this.SetContentSelected;
var contentEOL = new EOLContentVM();
contentEOL.ContentSelected += this.SetContentSelected;
this.Nodes.Add(exchangeHubVM);
this.Nodes.Add(contentEOL);
this.Options.Add(exchangeHubVM.Option);
this.Options.Add(contentEOL.Option);
}
private ContentVM content;
public ContentVM Content
{
get => this.content;
set
{
this.content = value;
this.NotifyPropertyChanged(nameof(this.Content));
}
}
public ObservableCollection<OptionVM> Options { get; }
private void SetContentSelected(ContentVM content)
=> this.Content = content;
}
}
@@ -0,0 +1,56 @@
namespace OMNIPruefung.ViewModels.Content
{
using OMNIPruefung.Models;
using OMNIPruefung.ViewModels.Base;
using OMNIPruefung.ViewModels.Options;
using System.Collections.ObjectModel;
using System.Linq;
public class SettingsContentVM : ContentVM
{
private readonly Appsettings appsettings;
public SettingsContentVM()
{
this.Header = "Einstellungen";
this.Option = new SettingsOptionVM(this);
this.Option.OptionSelected += this.NotifyOptionSelected;
this.appsettings = new Appsettings();
var settings = this.appsettings
.AllKeys
.Select(x => new SettingVM(x, this.appsettings));
this.Settings = new ObservableCollection<SettingVM>(settings);
}
public ObservableCollection<SettingVM> Settings { get; }
}
public class SettingVM : VM<SettingVM>
{
private readonly string key;
private readonly Appsettings appsettings;
public SettingVM(string key, Appsettings appsettings)
{
this.key = key;
this.appsettings = appsettings;
}
public string Key => this.key;
private string value;
public string Value
{
get => this.appsettings[this.key];
set
{
this.appsettings[this.key] = value;
this.NotifyPropertyChanged(nameof(this.Value));
}
}
}
}
@@ -0,0 +1,21 @@
namespace OMNIPruefung.ViewModels.Base
{
using System;
public class ContentVM : NodeVM
{
public ContentVM() : base()
{
}
public virtual event Action<ContentVM> ContentSelected;
public OptionVM Option { get; protected set; }
protected void NotifyOptionSelected()
=> this.ContentSelected?.Invoke(this);
protected void NotifyCotnentSelected(ContentVM content)
=> this.ContentSelected?.Invoke(content);
}
}
@@ -0,0 +1,39 @@
namespace OMNIPruefung.ViewModels.Features
{
using OmniPlus.Features;
using OMNIPruefung.ViewModels.Base;
using System.Collections.ObjectModel;
public class OMNIPlusVM : VM<OMNIPlusVM>
{
public ObservableCollection<Property> Values { get; }
= new ObservableCollection<Property>();
public ObservableCollection<Result> Results { get; }
= new ObservableCollection<Result>();
internal void Add(SystemParameters response)
{
if (response.Succeeded)
{
}
}
}
public class Result
{
}
public class Property
{
public string DbName { get; set; }
public string DisplayName { get; set; }
public string BinValue { get; set; }
public string StrValue { get; set; }
}
}
@@ -0,0 +1,161 @@
namespace OMNIPruefung.ViewModels.Features
{
using OmniPlus.Features;
using OMNIPruefung.ViewModels.Base;
using System;
using System.Collections.Generic;
public class OMNISysParameters : VM<OMNIPlusVM>
{
private SystemParameters parameters;
public OMNISysParameters(SystemParameters parameters)
{
this.parameters = parameters;
if (this.parameters is null)
{
this.parameters = new SystemParameters();
}
this.BuildInfo = this.parameters.BuildInfo.Value;
this.Manifactured = this.parameters.ManifacturingTime.DateTime;
this.Timedrift = this.parameters.SystemTime.DateTime;
this.Reboots = this.parameters.RebootsCount;
this.Version = this.parameters.VersionAndType.Value;
var voltage = Math.Max(this.parameters.BatteryVoltage.Volts, (ushort)1);
this.Voltage = voltage / 1000D;
this.ADCCounts = this.parameters.BatteryVoltage.ADCCount;
this.Sealed = this.parameters.FactorySealed;
this.IsValid = this.parameters.IsValid;
}
private string buildInfo;
public string BuildInfo
{
get => this.buildInfo;
set
{
this.buildInfo = value;
this.NotifyPropertyChanged(nameof(this.BuildInfo));
}
}
private DateTime manifactured;
public DateTime Manifactured
{
get => this.manifactured;
set
{
this.manifactured = value;
this.NotifyPropertyChanged(nameof(this.Manifactured));
}
}
private DateTime timedrift;
public DateTime Timedrift
{
get => this.timedrift;
set
{
this.timedrift = value;
this.NotifyPropertyChanged(nameof(this.Timedrift));
}
}
private byte reboots;
public byte Reboots
{
get => this.reboots;
set
{
this.reboots = value;
this.NotifyPropertyChanged(nameof(this.Reboots));
}
}
private string version;
public string Version
{
get => this.version;
set
{
this.version = value;
this.NotifyPropertyChanged(nameof(this.Version));
}
}
private double voltage;
public double Voltage
{
get => this.voltage;
set
{
this.voltage = value;
this.NotifyPropertyChanged(nameof(this.Voltage));
}
}
private uint adc;
public uint ADCCounts
{
get => this.adc;
set
{
this.adc = value;
this.NotifyPropertyChanged(nameof(this.ADCCounts));
}
}
private bool @sealed;
public bool Sealed
{
get => this.@sealed;
set
{
this.@sealed = value;
this.NotifyPropertyChanged(nameof(this.Sealed));
}
}
private bool isvalid;
public bool IsValid
{
get => this.isvalid;
set
{
this.isvalid = value;
this.NotifyPropertyChanged(nameof(this.IsValid));
}
}
public Dictionary<string, string> ToDictionary()
{
var dictionary = new Dictionary<string, string>();
dictionary["Version & Type: "] = this.Version;
dictionary["Build info: "] = this.BuildInfo;
dictionary["Manifactured: "] = $"{this.Manifactured:yyyy-MM-dd}";
dictionary["Last update: "] = $"{this.Timedrift:yyyy-MM-dd HH:mm:ss}";
dictionary["Battery voltage: "] = $"{this.Voltage:0.000}V";
dictionary["ADC counts: "] = $"{this.ADCCounts}";
dictionary["Reboots count: "] = $"{this.Reboots}";
dictionary["Factory sealed: "] = $"{this.Sealed}";
return dictionary;
}
public static implicit operator OMNISysParameters(SystemParameters parameters)
=> new OMNISysParameters(parameters);
}
}
@@ -0,0 +1,36 @@
namespace OMNIPruefung.ViewModels
{
using OMNIPruefung.ViewModels.Base;
using System;
using System.Collections.ObjectModel;
public abstract class NodeVM : VM<NodeVM>, IDisposable
{
protected NodeVM()
{
this.Nodes = new ObservableCollection<NodeVM>();
App.Disposed += this.Dispose;
}
private string header;
public virtual string Header
{
get => this.header;
set
{
this.header = value;
this.NotifyPropertyChanged( nameof(this.Header));
}
}
public ObservableCollection<NodeVM> Nodes { get; }
public virtual void Dispose()
{
}
}
}
@@ -0,0 +1,107 @@
namespace OMNIPruefung.ViewModels
{
using OMNIPruefung.ViewModels.Base;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
public class OptionVM : NodeVM
{
const int INDENT = 13;
private readonly NodeVM parent;
public OptionVM(NodeVM parent)
{
this.parent = parent;
this.parent.PropertyChanged += this.Parent_PropertyChanged;
}
public event Action OptionSelected;
private int indent = INDENT;
public int Indent
{
get => this.indent;
set
{
this.indent = value;
this.NotifyPropertyChanged(nameof(this.Indent));
}
}
public override string Header
{
get => this.parent?.Header;
set => this.NotifyPropertyChanged(this.Header);
}
private bool expanded;
public bool IsExpanded
{
get => this.expanded;
set
{
this.expanded = value;
this.NotifyPropertyChanged(nameof(this.IsExpanded));
}
}
private bool selected;
public bool IsSelected
{
get => this.selected;
set
{
if (!this.selected && value)
{
this.OptionSelected?.Invoke();
}
this.selected = value;
this.NotifyPropertyChanged(nameof(this.IsSelected));
}
}
public ICommand ToggleNodes => new Command(() =>
{
this.IsExpanded = !this.IsExpanded;
});
public ObservableCollection<OptionVM> Options { get; }
= new ObservableCollection<OptionVM>();
internal void Add(OptionVM option)
{
App.Invoke(() => this.Options.Add(option));
}
internal void Clear()
{
App.Invoke(() => this.Options.Clear());
}
internal void SetIndentation(int indent = INDENT)
{
this.indent = indent;
foreach (var option in this.Options)
{
option.SetIndentation(this.indent + INDENT);
}
}
protected virtual void Parent_PropertyChanged(object sender, PropertyChangedEventArgs args)
{
this.NotifyPropertyChanged(nameof(this.Header));
this.NotifyPropertyChanged(nameof(this.Indent));
this.NotifyPropertyChanged(nameof(this.IsExpanded));
this.NotifyPropertyChanged(nameof(this.IsSelected));
}
}
}
@@ -0,0 +1,63 @@
namespace OMNIPruefung.ViewModels.Options
{
using OMNIPruefung.ViewModels.Content;
using System.ComponentModel;
public class COMOptionVM : OptionVM
{
private readonly COMContentVM parent;
public COMOptionVM(COMContentVM parent) : base(parent)
{
this.parent = parent;
}
public int Nr
{
get => this.parent.Nr;
set => this.NotifyPropertyChanged(nameof(this.Nr));
}
public int Progress
{
get => this.parent.Progress;
set => this.NotifyPropertyChanged(nameof(this.Progress));
}
public bool Running
{
get => this.parent.Running;
set => this.NotifyPropertyChanged(nameof(this.Running));
}
public bool Connected
{
get => this.parent.Connected;
set => this.NotifyPropertyChanged(nameof(this.Connected));
}
public bool Visible
{
get => this.parent.Visible;
set => this.NotifyPropertyChanged(nameof(this.Visible));
}
public string State
{
get => this.parent.State;
set => this.NotifyPropertyChanged(nameof(this.State));
}
protected override void Parent_PropertyChanged(object sender, PropertyChangedEventArgs args)
{
base.Parent_PropertyChanged(sender, args);
this.NotifyPropertyChanged(nameof(this.Connected));
this.NotifyPropertyChanged(nameof(this.Running));
this.NotifyPropertyChanged(nameof(this.Nr));
this.NotifyPropertyChanged(nameof(this.Progress));
this.NotifyPropertyChanged(nameof(this.State));
this.NotifyPropertyChanged(nameof(this.Visible));
}
}
}
@@ -0,0 +1,12 @@
namespace OMNIPruefung.ViewModels.Options
{
using OMNIPruefung.ViewModels.Content;
public class EOLOptionVM : OptionVM
{
public EOLOptionVM(EOLContentVM parent) : base(parent)
{
}
}
}
@@ -0,0 +1,11 @@
namespace OMNIPruefung.ViewModels.Options
{
using OMNIPruefung.ViewModels.Content;
public class ExchangeHubOptionVM : OptionVM
{
public ExchangeHubOptionVM(ExchangeHubContentVM parent) : base(parent)
{
}
}
}
@@ -0,0 +1,11 @@
namespace OMNIPruefung.ViewModels.Options
{
using OMNIPruefung.ViewModels.Content;
public class MainOptionVM : OptionVM
{
public MainOptionVM(MainContentVM parent) : base(parent)
{
}
}
}
@@ -0,0 +1,11 @@
namespace OMNIPruefung.ViewModels.Options
{
using OMNIPruefung.ViewModels.Content;
public class SettingsOptionVM : OptionVM
{
public SettingsOptionVM(SettingsContentVM parent) : base(parent)
{
}
}
}
@@ -0,0 +1,50 @@
<ScrollViewer x:Class="OMNIPruefung.Views.Content.COMContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="White">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding Meter.Properties}" FontFamily="Consolas">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Content="{Binding Path=Key}" Padding="21, 3" FontWeight="Bold"/>
<ItemsControl ItemsSource="{Binding Path=Value}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Path=Key}" Padding="42, 3, 2, 3" Width="200" FontWeight="Bold"/>
<Label Content="{Binding Path=Value}" Padding="3"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Grid.Row="1"
Margin="13"
FontFamily="Consolas"
TextAlignment="Left"
Text="{Binding TestResults}" />
<TextBlock Grid.Row="2"
Margin="13"
FontFamily="Consolas"
TextAlignment="Left"
Text="{Binding Error}" />
<DataGrid Grid.Row="3" ItemsSource="{Binding Meter.Results}" />
</Grid>
</ScrollViewer>
@@ -0,0 +1,12 @@
namespace OMNIPruefung.Views.Content
{
using System.Windows.Controls;
public partial class COMContent : ScrollViewer
{
public COMContent()
{
this.InitializeComponent();
}
}
}
@@ -0,0 +1,187 @@
<Grid x:Class="OMNIPruefung.Views.Content.EOLContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:OptionsVM="clr-namespace:OMNIPruefung.ViewModels.Options"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="White">
<Grid Margin="13">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <!-- Auftrag:-->
<RowDefinition Height="Auto" /> <!--Kd.Auftrag:-->
<RowDefinition Height="Auto" /> <!-- PosNr:-->
<RowDefinition Height="Auto" /> <!-- IdentNr:-->
<RowDefinition Height="Auto" /> <!-- Kurztext:-->
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="Auftragskarte" Margin="0" Padding="0" FontWeight="Bold" FontSize="14" Grid.ColumnSpan="5" />
<Label Grid.Column="0" Grid.Row="1" Content="{Binding Line}" Margin="0" Padding="0" FontWeight="Bold" Grid.ColumnSpan="5" />
<Label Grid.Column="0" Grid.Row="2" Content="AuftragNr:" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="0" Grid.Row="3" Content="Kd.AuftragNr:" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="0" Grid.Row="4" Content="PosNr:" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="0" Grid.Row="5" Content="IdentNr:" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="0" Grid.Row="6" Content="Kurztext:" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="1" Grid.Row="2" Content="3221652" HorizontalContentAlignment="Left" Margin="0" Padding="21, 5, 0, 0" />
<Label Grid.Column="1" Grid.Row="3" Content="71156877" HorizontalContentAlignment="Left" Margin="0" Padding="21, 5, 0, 0" />
<Label Grid.Column="1" Grid.Row="4" Content="30" HorizontalContentAlignment="Left" Margin="0" Padding="21, 5, 0, 0" />
<Label Grid.Column="1" Grid.Row="5" Content="96011428" HorizontalContentAlignment="Left" Margin="0" Padding="21, 5, 0, 0" />
<Label Grid.Column="1" Grid.Row="6" Content="{Binding Text}" HorizontalContentAlignment="Left" Margin="0" Padding="21, 5, 0, 0" />
<Label Grid.Column="2" Grid.Row="2" Content="Prüfpunkte" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="3" Grid.Row="2" Content="Toleranzen" HorizontalContentAlignment="Right" Grid.ColumnSpan="2" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="2" Grid.Row="3" Content="Abweichung" HorizontalContentAlignment="Left" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0"/>
<Label Grid.Column="3" Grid.Row="3" Content="min %" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="4" Grid.Row="3" Content="max %" HorizontalContentAlignment="Right" Grid.ColumnSpan="2" FontWeight="Bold" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="2" Grid.Row="4" Content="{Binding OmniDefaults.TestPoints[0].VolumeM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="5" Content="{Binding OmniDefaults.TestPoints[1].VolumeM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="2" Grid.Row="6" Content="{Binding OmniDefaults.TestPoints[2].VolumeM3H}" ContentStringFormat="{}{0:0.0000} m³/h" HorizontalContentAlignment="Right" FontWeight="Bold" Margin="0" Padding="0, 5, 21, 0"/>
<Label Grid.Column="3" Grid.Row="4" Content="{Binding OmniDefaults.TestPoints[0].MinDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 21, 0" />
<Label Grid.Column="3" Grid.Row="5" Content="{Binding OmniDefaults.TestPoints[1].MinDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 21, 0" />
<Label Grid.Column="3" Grid.Row="6" Content="{Binding OmniDefaults.TestPoints[2].MinDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 21, 0" />
<Label Grid.Column="4" Grid.Row="4" Content="{Binding OmniDefaults.TestPoints[0].MaxDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="4" Grid.Row="5" Content="{Binding OmniDefaults.TestPoints[1].MaxDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="4" Grid.Row="6" Content="{Binding OmniDefaults.TestPoints[2].MaxDiff}" ContentStringFormat="{}{0:0.00} %" HorizontalContentAlignment="Right" Margin="0" Padding="0, 5, 0, 0" />
<Label Grid.Column="0" Grid.Row="7" Content="{Binding Line}" Margin="0" Padding="0" FontWeight="Bold" Grid.ColumnSpan="5" />
<Label Grid.Column="0" Grid.Row="8" Content="{Binding State}" Margin="0" Padding="0, 3" Grid.ColumnSpan="5" FontWeight="Bold" Background="Transparent"/>
<Label Grid.Column="0" Grid.Row="8" Content="{Binding Error}" Margin="0" Padding="0, 3" Grid.ColumnSpan="5" FontWeight="Bold" Background="Transparent" Foreground="{StaticResource Red}" />
<Grid Grid.Row="9" Grid.ColumnSpan="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Text="{Binding Size}" HorizontalAlignment="Stretch" Margin="0, 2, 2, 2">
<ComboBoxItem IsSelected="True" >5</ComboBoxItem>
<ComboBoxItem IsSelected="True">6</ComboBoxItem>
<ComboBoxItem IsSelected="True">7</ComboBoxItem>
<ComboBoxItem IsSelected="True">8</ComboBoxItem>
<ComboBoxItem IsSelected="True">9</ComboBoxItem>
<ComboBoxItem IsSelected="True">10</ComboBoxItem>
<ComboBoxItem IsSelected="True">11</ComboBoxItem>
</ComboBox>
<ComboBox Grid.Column="1" Text="{Binding Type}" HorizontalAlignment="Stretch" Margin="2, 2, 0, 2">
<ComboBoxItem IsSelected="True">C2</ComboBoxItem>
<ComboBoxItem >F2</ComboBoxItem>
<ComboBoxItem >R2</ComboBoxItem>
<ComboBoxItem >T2</ComboBoxItem>
</ComboBox>
</Grid>
<!--<Label Grid.Column="0" Grid.Row="9" Content="Type eingeben: " VerticalContentAlignment="Center" VerticalAlignment="Stretch"/>
<TextBox Grid.Column="1" Grid.Row="9" Text="{Binding Type}" />-->
</Grid>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Option.Options}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type OptionsVM:COMOptionVM}">
<Grid Margin="0, 3, 0, 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0"
Grid.Column="0"
Padding="0"
Margin="0"
FontSize="13"
FontWeight="Bold"
VerticalContentAlignment="Center"
ContentStringFormat="{}{0}. "
Content="{Binding Nr}" />
<Label Grid.Row="0"
Grid.Column="1"
Padding="0"
Margin="0"
FontSize="13"
VerticalContentAlignment="Center"
Content="{Binding State}" />
<Label Grid.Row="0"
Grid.Column="2"
Padding="0"
Margin="0"
FontSize="13"
Foreground="Gray"
VerticalContentAlignment="Center"
Content="{Binding Progress}"
ContentStringFormat="{}{0} %" />
<ProgressBar Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Foreground="{Binding Running, Converter={StaticResource BooleanProgress}}"
Value="{Binding Progress}"
Background="WhiteSmoke"
BorderBrush="WhiteSmoke"
BorderThickness="1"
Margin="0, 5"
Padding="0"
Height="8"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
Margin="0"
Content="Plätze aktualisieren"
Style="{DynamicResource SystemBtn}"
Visibility="{Binding CanStart, Converter={StaticResource BooleanVisibility}}"
Command="{Binding LoadComPorts}"/>
<Button Grid.Column="2"
Content="Abbruch"
Style="{DynamicResource SystemBtn}"
Visibility="{Binding CanStop, Converter={StaticResource BooleanVisibility}}"
Command="{Binding CancelInspection}"/>
<Button Grid.Column="3"
Content="Prüfung starten"
Style="{DynamicResource SystemBtn}"
Visibility="{Binding CanStart, Converter={StaticResource BooleanVisibility}}"
Command="{Binding StartInspection}"/>
</Grid>
</Grid>
</Grid>
@@ -0,0 +1,12 @@
namespace OMNIPruefung.Views.Content
{
using System.Windows.Controls;
public partial class EOLContent : Grid
{
public EOLContent()
{
this.InitializeComponent();
}
}
}
@@ -0,0 +1,95 @@
<Grid x:Class="OMNIPruefung.Views.Content.ExchangeHub"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="150"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="21, 21, 21, 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0"
Grid.Column="0"
Content="Hub URL:"
FontFamily="Consolas"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"/>
<TextBox Grid.Row="0"
Grid.Column="1"
Height="30"
FontFamily="Consolas"
Text="{Binding URL}"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"/>
<Line Grid.Row="1" Height="10" />
<Label Grid.Row="2"
Grid.Column="0"
FontFamily="Consolas"
Content="Output Directory:"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"/>
<TextBox Grid.Row="2"
Grid.Column="1"
Height="30"
FontFamily="Consolas"
Text="{Binding OutputDir}"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"/>
<StackPanel Grid.Row="3"
Grid.Column="1"
Orientation="Horizontal"
Margin="0, 10, 0, 0">
<Button VerticalAlignment="Stretch"
HorizontalAlignment="Left"
Style="{StaticResource SystemBtn}"
Content="Speichern"
Margin="0, 0, 10, 0"/>
<Button VerticalAlignment="Stretch"
HorizontalAlignment="Left"
Visibility="{Binding Disconnected, Converter={StaticResource BooleanVisibility}}"
Style="{StaticResource SystemBtn}"
Command="{Binding Connect}"
Content="Verbinden"
Margin="0, 0, 10, 0"/>
<Button VerticalAlignment="Stretch"
HorizontalAlignment="Left"
Visibility="{Binding Connected, Converter={StaticResource BooleanVisibility}}"
Style="{StaticResource SystemBtn}"
Command="{Binding Disconnect}"
Content="Trennen"
Margin="0, 0, 10, 0"/>
</StackPanel>
</Grid>
<GridSplitter Grid.Row="1"
Height="3"
ResizeBehavior="PreviousAndNext"
ResizeDirection="Rows"
Background="LightGray"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" />
<ScrollViewer Grid.Row="2"
Margin="0"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<TextBlock FontFamily="Consolas"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Text="{Binding LogContent}"
Padding="21, 21, 0, 0"/>
</ScrollViewer>
</Grid>
@@ -0,0 +1,12 @@
namespace OMNIPruefung.Views.Content
{
using System.Windows.Controls;
public partial class ExchangeHub : Grid
{
public ExchangeHub()
{
this.InitializeComponent();
}
}
}
@@ -0,0 +1,81 @@
<Grid x:Class="OMNIPruefung.Views.Options.COMOption"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ToggleButton Grid.Row="0"
IsChecked="{Binding IsExpanded}">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<ContentPresenter SnapsToDevicePixels="True" />
</ControlTemplate>
</ToggleButton.Template>
<RadioButton GroupName="sidebar_nodes"
Cursor="Hand"
Padding="0, 2"
Margin="0, 2, 0, 0"
Style="{StaticResource RadioNodeStyle}"
IsChecked="{Binding IsSelected}">
<RadioButton.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding ToggleNodes}" />
</RadioButton.InputBindings>
<Grid Margin="0, 0, 0, 1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Indent}" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ProgressBar Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Visibility="{Binding Connected, Converter={StaticResource BooleanVisibility}}"
Foreground="{Binding Running, Converter={StaticResource BooleanProgress}}"
Background="Transparent"
Value="{Binding Progress}"
BorderThickness="0"
Opacity="0.1"
Margin="5, 2"
Padding="0"/>
<Label Grid.Column="2"
Visibility="{Binding Connected, Converter={StaticResource BooleanVisibility}}"
Content="{Binding Progress}"
ContentStringFormat="{}{0}%"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Opacity="0.5" />
<Label Grid.Column="1"
FontSize="14"
Margin="0"
Padding="0"
FontWeight="Bold"
Foreground="Black"
Background="Transparent"
Content="{Binding Nr}"
ContentStringFormat="{}{0}."
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"/>
<Label Grid.Column="2"
Padding="0"
Margin="5"
Content="{Binding Header}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"/>
</Grid>
</RadioButton>
</ToggleButton>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Options}"
Visibility="{Binding IsExpanded, Converter={StaticResource BooleanVisibility}}"/>
</Grid>
@@ -0,0 +1,21 @@
namespace OMNIPruefung.Views.Options
{
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public partial class COMOption : Grid
{
public static readonly DependencyProperty ProgressIconProperty
= DependencyProperty.Register(nameof(ProgressIcon), typeof(ImageSource), typeof(Option));
public COMOption()
=> this.InitializeComponent();
public ImageSource ProgressIcon
{
get => this.GetValue(ProgressIconProperty) as ImageSource;
set => this.SetValue(ProgressIconProperty, value);
}
}
}
@@ -0,0 +1,58 @@
<Grid x:Class="OMNIPruefung.Views.Options.Option"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:OMNIPruefung.Views.Options">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ToggleButton Grid.Row="0"
IsChecked="{Binding IsExpanded}">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<ContentPresenter SnapsToDevicePixels="True" />
</ControlTemplate>
</ToggleButton.Template>
<RadioButton GroupName="sidebar_nodes"
Cursor="Hand"
Padding="0, 2"
Margin="0, 2, 0, 0"
Style="{StaticResource RadioNodeStyle}"
IsChecked="{Binding IsSelected}">
<RadioButton.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding ToggleNodes}" />
</RadioButton.InputBindings>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Indent}" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="1"
Source="{Binding Icon, RelativeSource={RelativeSource AncestorType=v:Option, Mode=FindAncestor}}"
Height="{Binding IconSize, RelativeSource={RelativeSource AncestorType=v:Option, Mode=FindAncestor}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
Width="16"/>
<Label Grid.Column="2"
Padding="0"
Margin="5"
Background="Transparent"
Content="{Binding Header}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"/>
</Grid>
</RadioButton>
</ToggleButton>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Options}"
Visibility="{Binding IsExpanded, Converter={StaticResource BooleanVisibility}}"/>
</Grid>
@@ -0,0 +1,31 @@
namespace OMNIPruefung.Views.Options
{
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public partial class Option : Grid
{
public static readonly DependencyProperty IconProperty
= DependencyProperty.Register(nameof(Icon), typeof(ImageSource), typeof(Option));
public static readonly DependencyProperty IconSizeProperty
= DependencyProperty.Register(nameof(IconSize), typeof(int), typeof(Option),
new FrameworkPropertyMetadata(16));
public Option()
=> this.InitializeComponent();
public ImageSource Icon
{
get => this.GetValue(IconProperty) as ImageSource;
set => this.SetValue(IconProperty, value);
}
public int IconSize
{
get => this.GetValue(IconSizeProperty) is int size ? size : 16;
set => this.SetValue(IconSizeProperty, value);
}
}
}
@@ -12,7 +12,7 @@
this.encoder = new IrdaEncoder();
}
public override void WriteBytes(params byte[] bytes)
protected override void WriteBytes(params byte[] bytes)
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
@@ -48,10 +48,9 @@
message[index++] = UI1236_START;
message[index++] = (byte)(bytesLength + UI1236_HED_LENGTH);
//OmniControlOptions control = OxOO;
//control.ReturnResponse = true;
//message[index++] = control;
message[index++] = 0x08;
UI1236Control control = OxOO;
control.ReturnResponse = true;
message[index++] = control;
bytes.CopyTo(message, index);
@@ -8,7 +8,7 @@
{
}
public virtual byte[] ReadBytes()
protected virtual byte[] ReadBytes()
{
var bytes = new byte[0];
@@ -34,7 +34,7 @@
return bytes;
}
public virtual void WriteBytes(params byte[] bytes)
protected virtual void WriteBytes(params byte[] bytes)
{
try
{
@@ -1,10 +1,10 @@
namespace OmniPlus.Options
namespace OmniPlus.Connections
{
internal class OmniControlOptions
internal class UI1236Control
{
private readonly byte[] bits;
private OmniControlOptions(byte[] bits)
private UI1236Control(byte[] bits)
=> this.bits = bits;
public bool E0Encryption => this.bits[0] == 1;
@@ -39,7 +39,7 @@
set => this.bits[7] = (byte)(value ? 1 : 0);
}
public static implicit operator OmniControlOptions(byte controlByte)
public static implicit operator UI1236Control(byte controlByte)
{
var bits = new byte[8];
@@ -48,10 +48,10 @@
bits[i] = (byte)((controlByte >> i) & 1);
}
return new OmniControlOptions(bits);
return new UI1236Control(bits);
}
public static implicit operator byte (OmniControlOptions control)
public static implicit operator byte (UI1236Control control)
{
var @byte = default(byte);
@@ -56,7 +56,7 @@
return response;
}
public override void WriteBytes(params byte[] bytes)
protected override void WriteBytes(params byte[] bytes)
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
@@ -57,7 +57,7 @@
return response;
}
public override void WriteBytes(params byte[] bytes)
protected override void WriteBytes(params byte[] bytes)
{
if (this.encoder.TryEncode(bytes, out byte[] message))
{
@@ -1,8 +1,7 @@
using System;
using static System.Text.Encoding;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using static System.Text.Encoding;
public class ASCIIString : FeatureRequest
{
protected const char NULL = '\0';
@@ -1,7 +1,7 @@
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using System;
public class AlarmSettings : FeatureRequest
{
const int LENGTH = 28;
@@ -1,7 +1,7 @@
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using System;
public class ChamberCalibrationRequest : FeatureRequest
{
public const byte ACTIVATE_TEST = 0x00;
@@ -1,4 +1,4 @@
namespace OmniPlus.Enums
namespace OmniPlus.Features.Enums
{
public enum MessurementUnits : byte
{
@@ -1,4 +1,4 @@
namespace OmniPlus.Enums
namespace OmniPlus.Features.Enums
{
public enum ReadingSettings : byte
{
@@ -1,4 +1,4 @@
namespace OmniPlus.Enums
namespace OmniPlus.Features.Enums
{
public enum Status : byte
{
@@ -1,4 +1,4 @@
namespace OmniPlus.Enums
namespace OmniPlus.Features.Enums
{
public enum TimeUnits : byte
{
@@ -0,0 +1,6 @@
namespace OmniPlus.Features
{
internal static class FeatureExtensions
{
}
}
@@ -1,7 +1,7 @@
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using System;
public class FeatureRequest : FeatureResponse
{
public FeatureRequest(int length)
@@ -1,9 +1,9 @@
using OmniPlus.Enums;
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using OmniPlus.Features.Enums;
using System;
public class FeatureResponse
{
protected int length;
@@ -1,8 +1,5 @@
namespace OmniPlus.Features
{
using System.Collections.Generic;
using System.Security.Cryptography;
internal class Features
{
/// <summary>
@@ -1,7 +1,7 @@
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using System;
public class InputVolume : FeatureRequest
{
const int LENGTH = 6;
@@ -1,7 +1,7 @@
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using System;
public class ManifacturingTime : Epoch20000101
{
public static implicit operator ManifacturingTime(DateTime dateTime)
@@ -1,7 +1,7 @@
using System;
namespace OmniPlus.Features
namespace OmniPlus.Features
{
using System;
public class ProgrammableID : ASCIIString
{
const int LENGTH = 20;

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