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

395 lines
11 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.Collections.ObjectModel;
using System.IO.Ports;
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.Coms = new ObservableCollection<string>();
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.LoadComPorts = new Command(this.InitializeComPorts);
this.CancelInspection = new Command(this.CancelInspectionHandler);
this.StartInspection = new Command(this.StartInspectionHandler);
this.InitializeComPorts();
}
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; }
public ObservableCollection<string> Coms { get; }
private void InitializeComPorts()
{
this.Coms.Clear();
this.Nodes.Clear();
this.Option.Clear();
try
{
var existingComPorts = SerialPort.GetPortNames();
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.Exists = existingComPorts.Any(x => x.Equals(com, StringComparison.OrdinalIgnoreCase));
comVM.Header = comVM.Exists ? $"({com})" : $"({com} - nicht vorhanden)";
comVM.State = comVM.Header;
this.Coms.Add(com);
this.Nodes.Add(comVM);
this.Option.Add(comVM.Option);
}
}
catch (Exception e)
{
this.Error = e.ToString();
}
this.Option.SetIndentation(this.Option.Indent);
this.CanStart = true;
this.CanStop = false;
this.State = default(string);
this.Error = default(string);
}
private void CancelInspectionHandler()
{
this.Error = "Warte bis abbruch abgeschlossen ...";
this.State = default(string);
this.CanStop = false;
this.CanStart = true;
try
{
this.manualResetEventSlim?.Set();
this.cancellationTokenSource?.Cancel();
this.tasks.Clear();
this.Error = "Vorgang wurde abbgebrochen!";
}
catch (Exception e)
{
this.Error = e.ToString();
}
this.InitializeComPorts();
Task.Factory.StartNew(() =>
{
if (this.AvailableIn > 0)
{
this.CanStart = false;
this.manualResetEventSlim = new ManualResetEventSlim();
this.timer = new TimersTimer(1000)
{
AutoReset = true,
Enabled = true
};
this.WaitUntil(this.AvailableIn, true);
this.AvailableIn = 0;
this.CanStart = true;
}
this.Error = default(string);
});
}
private void StartInspectionHandler()
{
this.CanStop = true;
this.CanStart = false;
this.Error = string.Empty;
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
this.manualResetEventSlim = new ManualResetEventSlim();
this.timer = new TimersTimer(1000)
{
AutoReset = true,
Enabled = true
};
this.dbcontext.LoadOmniDefaults(6, "T2", this.OmniDefaults);
this.NotifyPropertyChanged(nameof(this.OmniDefaults));
this.signalR.Connect(this.hubsettings.ExchangeHubURL);
Task.Factory.StartNew(() =>
{
var coms = this.Nodes.Cast<COMContentVM>();
foreach (var comVM in coms)
{
this.tasks.Add(comVM.PrepareConnectionTask(this.cancellationToken));
}
this.ContinueWhenAll();
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)
{
var rotations = pp.Rotations;
var duration = pp.Duration;
foreach (var comVM in coms)
{
this.tasks.Add(comVM.StartPPCalibrationTask(pp, this.cancellationToken));
}
this.ContinueWhenAll();
this.signalR.NotifyStartRef(duration);
this.WaitUntil((int)(duration * 1.2), true, false);
if (this.manualResetEventSlim.IsSet)
{
break;
}
var referenceV = this.GetReferenceVolume();
foreach (var comVM in coms)
{
this.tasks.Add(comVM.StopPPCalibrationTask(pp, this.cancellationToken));
}
this.ContinueWhenAll();
foreach (var comVM in coms)
{
comVM.SetReferenceVolume(pp, referenceV);
}
}
foreach (var comVM in coms)
{
comVM.GetCorrectionFactor();
}
foreach (var comVM in coms)
{
comVM.Dispose();
}
this.CancelInspectionHandler();
this.signalR.Dispose();
}, this.cancellationToken);
}
private void WaitUntil(int duration, bool show = false, bool error = true)
{
this.AvailableIn = duration;
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";
}
}
};
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();
}
}
public override void Dispose()
{
foreach (var comVM in this.Nodes.Cast<COMContentVM>())
{
comVM.Dispose();
}
}
private double GetReferenceVolume()
{
var received = false;
var referenceV = 0D;
var timeout = 10; // seconds
void referenceVolumeReceived(double m3h)
{
received = true;
referenceV = m3h;
}
this.signalR.StopRef += referenceVolumeReceived;
this.signalR.NotifyStopRef();
while (!received && timeout > 0)
{
Thread.Sleep(1000);
timeout--;
}
return referenceV;
}
}
}