Files
laatzen/Common/OMNIPruefung/ViewModels/Content/EOLContentVM.cs
T

649 lines
18 KiB
C#

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.NotifyStopRef();
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.NotifyStartRef(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.NotifyStopRef();
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();
}
}
}
}