Files
laatzen/Common/OMNIPruefung/ViewModels/Content/EOLContentVM.cs
T
2023-12-14 16:18:51 +01:00

501 lines
14 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 ICollection<Task> tasks;
private ManualResetEventSlim manualResetEventSlim;
private TimersTimer timer;
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.InitializeComPorts);
this.CancelInspection = new Command(this.CancelInspectionHandler);
this.StartInspection = new Command(this.StartInspectionHandler);
this.InitializeComPorts();
}
public string Type
{
get => this.hubsettings[nameof(this.Type)];
set
{
this.hubsettings[nameof(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 InitializeComPorts()
{
foreach (var disposable in this.Nodes.Cast<IDisposable>())
{
disposable.Dispose();
}
this.Nodes.Clear();
this.Option.Clear();
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}";
comVM.InitializeAsync();
this.Nodes.Add(comVM);
this.Option.Add(comVM.Option);
}
this.Text = $"ME OMNI 1.5-2\" {this.Type}";
this.Option.SetIndentation(this.Option.Indent);
this.dbcontext.LoadOmniDefaults(6, this.Type, this.OmniDefaults);
this.NotifyPropertyChanged(nameof(this.OmniDefaults));
this.NotifyPropertyChanged(nameof(this.Nodes));
}
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.CanStop = false;
this.CanStart = false;
this.Error = default(string);
this.State = "Warte bis abbruch abgeschlossen ...";
try
{
this.manualResetEventSlim?.Set();
this.cancellationTokenSource?.Cancel();
this.tasks.Clear();
this.Dispose();
this.State = "Vorgang wurde abbgebrochen!";
}
catch (Exception e)
{
this.Error = e.ToString();
this.State = default(string);
}
Task.Factory.StartNew(() =>
{
this.CanStart = false;
if (this.AvailableIn > 0)
{
this.WaitUntil(this.AvailableIn, true);
}
this.CanStart = true;
this.Error = default(string);
});
}
private void StartInspectionHandler()
{
this.CanStop = true;
this.CanStart = false;
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
Task.Factory.StartNew(() =>
{
var coms = this.Nodes.Cast<COMContentVM>();
//foreach (var comVM in coms)
//{
// this.tasks.Add(comVM.ReadSystemParametersTask(this.cancellationToken));
//}
//this.ContinueWhenAll();
foreach (var comVM in coms)
{
this.tasks.Add(comVM.SetInputVolumeTask(this.OmniDefaults, this.cancellationToken));
}
this.ContinueWhenAll();
var results = this.OmniDefaults
.TestPoints
.ToDictionary(x => x, x => new List<OmniPlusTest>());
foreach (var pp in this.OmniDefaults.TestPoints)
{
if (coms.All(x => !x.Running))
{
break;
}
var rotations = pp.Rotations;
var duration = pp.Duration;
this.SetFlow(pp.VolumeM3H);
foreach (var comVM in coms)
{
this.tasks.Add(comVM.StartPPCalibrationTask(pp, this.cancellationToken));
}
this.ContinueWhenAll();
this.StartRZ(duration);
this.WaitUntil((int)(duration * 1.2), true, false);
if (this.manualResetEventSlim.IsSet)
{
break;
}
var referenceV = this.GetRZVolume();
foreach (var comVM in coms)
{
this.tasks.Add(comVM.StopPPCalibrationTask(pp, this.cancellationToken));
}
this.ContinueWhenAll();
if (coms.All(x => !x.Running))
{
break;
}
foreach (var comVM in coms)
{
comVM.SetReferenceVolume(pp, referenceV);
}
}
foreach (var comVM in coms)
{
comVM.SaveInspection();
}
if (coms.All(x => x.Running))
{
foreach (var comVM in coms)
{
comVM.GetCorrectionFactor();
}
foreach (var comVM in coms)
{
comVM.Dispose();
}
}
this.CancelInspectionHandler();
this.signalR.NotifyStopRef();
this.signalR.NotifyStopQ();
this.signalR.Dispose();
}, this.cancellationToken);
}
private void WaitUntil(int duration, bool show = false, bool error = true)
{
this.AvailableIn = duration;
if (this.manualResetEventSlim != null)
{
this.manualResetEventSlim.Set();
this.manualResetEventSlim.Dispose();
}
this.manualResetEventSlim = new ManualResetEventSlim();
if (this.timer != null)
{
this.timer.Stop();
this.timer.Dispose();
}
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.manualResetEventSlim.Set();
}
};
this.timer.Start();
this.manualResetEventSlim.Wait(this.AvailableIn * 1000);
this.timer.Stop();
}
private void ContinueWhenAll()
{
if (this.tasks.Any())
{
Task.Factory
.ContinueWhenAll(this.tasks.ToArray(), _ => { })
.Wait();
this.tasks.Clear();
}
Thread.Sleep(1000);
}
public override void Dispose()
{
foreach (var disposable in this.Nodes.Cast<IDisposable>())
{
disposable.Dispose();
}
}
private void SetFlow(double volumeM3H)
{
var received = false;
var volume = volumeM3H;
var timeout = 120; // seconds
void referenceVolumeReceived(double value)
{
received = true;
volume = value;
}
this.signalR.StartQ += referenceVolumeReceived;
this.signalR.NotifyStartQ(volumeM3H);
this.State = "Warten auf Q(soll) ...";
while (!received && timeout > 0)
{
Thread.Sleep(1000);
timeout--;
}
}
private void StartRZ(int duration)
{
var received = false;
var reference = 0;
var timeout = 30; // seconds
void referenceVolumeReceived(int value)
{
received = true;
reference = value;
}
this.signalR.StartRef += referenceVolumeReceived;
this.signalR.NotifyStartRef(duration);
this.State = "Warten bis RZ gestarted ...";
while (!received && timeout > 0)
{
Thread.Sleep(1000);
timeout--;
}
}
private double GetRZVolume()
{
var received = false;
var referenceV = 0D;
var timeout = 30; // seconds
void referenceVolumeReceived(double value)
{
received = true;
referenceV = value;
}
this.signalR.StopRef += referenceVolumeReceived;
this.signalR.NotifyStopRef();
this.State = "Warten RZ Ergebnis ...";
while (!received && timeout > 0)
{
Thread.Sleep(1000);
timeout--;
}
return referenceV;
}
}
}