laatzen/Common/CordonelAssemblyLine/Model/PickingModel.cs
2022-05-10 15:34:48 +02:00

710 lines
28 KiB
C#

using Logic.ProductionToProductMapper.Cordonel;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Ui.ProductionControls;
using Xylem.Common.CommonCore.Configuration;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Logic.SoftwareAccessHelper;
using static Ui.ProductionControls.ctlPictureProgressBar;
namespace CordonelAssemblyLine.Model
{
internal class PickingViewModel : INotifyPropertyChanged
{
private string state = "Warte auf Scanner";
private string scanner = "keine Verbindung";
private string slot = "-";
private string result = "-";
private System.Windows.Media.Brush resultColor;
public System.Windows.Media.Brush ResultColor
{
get
{
return resultColor;
}
set
{
resultColor = value;
NotifyPropertyChanged(nameof(ResultColor));
}
}
public string State
{
get
{
return state;
}
set
{
state = value;
NotifyPropertyChanged(nameof(State));
}
}
public string Scanner
{
get
{
return scanner;
}
set
{
scanner = value;
NotifyPropertyChanged(nameof(Scanner));
}
}
public void UpdateLogText(string text, bool forceGuiUpdate = true)
{
logText = $"{text}{Environment.NewLine}{logText}";
if (logText.Length > 2503)
{
logText = $"{logText.Substring(0, 2500)}...";
}
if (forceGuiUpdate)
{
LogText = logText;
}
}
private string historyText = "-";
public string HistoryText
{
get
{
return historyText;
}
set
{
historyText = value;
NotifyPropertyChanged(nameof(HistoryText));
}
}
private string logText = "Start";
public string LogText
{
get
{
return logText;
}
set
{
logText = value;
NotifyPropertyChanged(nameof(LogText));
}
}
public string Slot
{
get
{
return slot;
}
set
{
slot = value;
NotifyPropertyChanged(nameof(Slot));
}
}
public string Result
{
get
{
return result;
}
set
{
result = value;
NotifyPropertyChanged(nameof(Result));
}
}
public PickingViewModel()
{
InitProgressBar();
}
private void InitProgressBar()
{
ProgressBar = new List<ImageElement>();
ProgressBar.Add(new ImageElement() { Name = "Init", Image = Ui.ProductionControls.Enums.Img.Waiting });
ProgressBar.Add(new ImageElement() { Name = "Scan", Image = Ui.ProductionControls.Enums.Img.BarcodeScanner });
ProgressBar.Add(new ImageElement() { Name = "Connect", Image = Ui.ProductionControls.Enums.Img.Plugin });
ProgressBar.Add(new ImageElement() { Name = "Order data", Image = Ui.ProductionControls.Enums.Img.Cloud });
ProgressBar.Add(new ImageElement() { Name = "Compare", Image = Ui.ProductionControls.Enums.Img.Compare });
ProgressBar.Add(new ImageElement() { Name = "Compare Result", Image = Ui.ProductionControls.Enums.Img.Default });
ProgressBar.Add(new ImageElement() { Name = "Scan Build", Image = Ui.ProductionControls.Enums.Img.BarcodeScanner });
ProgressBar.Add(new ImageElement() { Name = "Scan Build Pressure", Image = Ui.ProductionControls.Enums.Img.BarcodeScanner });
}
public List<ImageElement> ProgressBar { get; internal set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void StartPicking(CancellationToken cancle, string scannerPort, int slotNr)
{
ScannerPort = scannerPort;
SlotNr = slotNr;
var s = new Task(() => { PickingLoop(cancle); }, cancle);
s.Start();
}
public enum PickingStateMachine
{
Init,
WaitForScanning,
ScanningDone,
WaitForDetect,
GetOrderDetails,
Compare,
MeterDone,
MeterError,
StartCom,
WaitForBuildingMeterReady,
WaitForBuildingPressureReady,
}
private PickingStateMachine sm = PickingStateMachine.Init;
private class BarScanner : IDisposable
{
private bool isRuning = false;
public String Input = "";
private String Port;
private CancellationToken Cancellation;
private Task WaitForScannerTask;
public BarScanner(string port, CancellationToken cancellation)
{
Port = port;
Cancellation = cancellation;
}
public void Start()
{
if (!isRuning)
{
if (Port == null)
{
return;
}
WaitForScannerTask = new Task(() =>
{
using (var a = new SerialPort(Port))
{
try
{
a.Open();
a.NewLine = "\r";
while (true)
{
if (Cancellation.IsCancellationRequested)
{
isRuning = false;
break;
}
else
{
Input = a.ReadLine();
a.Close();
isRuning = false;
break;
}
}
}
catch (Exception ex)
{
Input = ex.Message;
isRuning = false;
}
}
}, Cancellation);
WaitForScannerTask.Start();
}
}
public void Dispose()
{
if (WaitForScannerTask.Status != TaskStatus.Faulted && WaitForScannerTask.Status != TaskStatus.RanToCompletion && WaitForScannerTask.Status != TaskStatus.Canceled)
{
WaitForScannerTask.Dispose();
}
}
}
public void setState(string state)
{
State = state;
UpdateLogText($"Status:{State}");
}
public bool Compare(Dictionary<UInt32, UInt32> checkAppsIdVersion, uint Frequency, uint MeterSize, bool PressurePresent)
{
using (var Batch = new MeterBatch())
{
using (var meter = new GenesisMeter())
{
meter.SetupFromConfigFile(SlotNr);
Batch.AddMeter(meter);
setState("Am Zähler anmelden");
if ((bool)meter.Login())
{
meter.SetProcessState(Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts.DisplayCodes.PickingStarted);
var ret = RunCheck(checkAppsIdVersion, Frequency, MeterSize, PressurePresent, meter);
if (ret)
{
meter.SetProcessState(Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts.DisplayCodes.PickingTested);
var url = $"{ServiceUrls.MeterProcessStateUrl()}SetPickingState?PcbID={meter.PcbId}&FertigungsauftragsNr={Order}";
var RetString = LocalWebRequest.PostRequestAsyncAndGetContent(url);
var result = false;
if (bool.TryParse(RetString, out result))
{
return result;
}
}
else
{
meter.SetProcessState(Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts.DisplayCodes.PickingFailed);
}
}
}
}
return false;
}
private bool RunCheck(Dictionary<uint, uint> checkAppsIdVersion, uint Frequency, uint MeterSize, bool PressurePresent, GenesisMeter meter)
{
setState($"Üperprüfe Parameter");
var FrequencyReadOut = RegisterConverter.ConvertTo<UInt32>(meter.ReadRegister("SENSUSRADIO_FrequencyIndicator"));
if (FrequencyReadOut != Frequency)
{
setState($"Falsche Frequenz! soll {Frequency}MHz ist {FrequencyReadOut}MHz");
meter.WriteLog(State);
return false;
}
//TODO: metersize check for bigger dn sizes!!!
//var MeterSizeReadOut = RegisterConverter.ConvertTo<UInt32>(meter.ReadRegister("GENESISFLOW_MeterSize"));
//if (MeterSizeReadOut != MeterSize)
//{
// setState($"Meter Dn falsch! soll {MeterSize}DN ist {MeterSizeReadOut}DN");
// meter.WriteLog(State);
// return false;
//}
var PressureReadOut = RegisterConverter.ConvertTo<bool>(meter.ReadRegister("METROLOGYASST_PressurePresent"));
if (PressureReadOut)
{
meter.WriteRegister("METROLOGYASST_PressureMeasure", 1, true);
var pressure = RegisterConverter.ConvertTo<Int32>(meter.ReadRegister("METROLOGYASST_PressureMeasure"));
setState($"Prüfe Drucksensor. {pressure}");
meter.WriteRegister("METROLOGYASST_PressureMeasure", 1, true);
var pressureS = RegisterConverter.ConvertTo<Int32>(meter.ReadRegister("METROLOGYASST_PressureMeasure"));
if (pressure - pressureS == 0)
{
PressureReadOut = false;
meter.WriteRegister("METROLOGYASST_PressurePresent", 0, true);
}
else
{
setState($"Pcb mit Drucksensor. Registerwert überschrieben");
PressureReadOut = true;
}
}
if (PressureReadOut != PressurePresent)
{
if (!PressurePresent)
{
setState($"Pcb mit Drucksensor. Laut Auftrag keine verbaut");
meter.WriteLog(State);
}
else
{
setState($"Pcb ohne Drucksensor. Laut Auftrag soll eine verbaut werden");
meter.WriteLog(State);
}
//todo raus
return false;
}
foreach (var item in checkAppsIdVersion)
{
try
{
var MeterFWApp = meter.MeterAppListVersion.First(a => item.Key == a.AppId);
if (MeterFWApp == null || MeterFWApp.Version != item.Value)
{
setState($"Falsche FW, bitte Updaten AppId:{item.Key} sollte {item.Value} haben, hat aber {MeterFWApp.Version}");
meter.WriteLog(State);
return false;
}
}
catch (Exception)
{
setState($"Fehler beim auslesen der FW");
meter.WriteLog(State);
return false;
}
}
try
{
meter.WriteRegister("METROLOGYASST_StoreConfiguration", 1);
Thread.Sleep(2500);
meter.Logout();
Thread.Sleep(2500);
meter.ReLogin();
var storeRet = meter.ReadRegister("METROLOGYASST_StoreConfiguration");
if (meter.PcbId != "18440026" && meter.PcbId != "193300058" && meter.PcbId != "194800276" && meter.PcbId != "201420255" && !storeRet.All(a => a.Equals(0)))
{
setState($"Filesystem corrupt");
meter.WriteLog(State);
return false;
}
}
catch (Exception)
{
setState($"Fehler beim überprüfen des Filesystems");
meter.WriteLog(State);
return false;
}
return true;
}
private PickingCompareItem OrderDetails;
private OrderOverViewCordonelWithPicking OrderOverview;
private BarScanner barScanner;
private string Order;
private string PcbId;
private string ScannerPort = "COM20";
private int SlotNr = 1;
//PickingState,PickingScanner,PickingSlot,PickingResult
private void PickingLoop(CancellationToken token)
{
var converter = new System.Windows.Media.BrushConverter();
while (!token.IsCancellationRequested)
{
switch (sm)
{
case PickingStateMachine.Init:
setState("Initialisierung");
Slot = $"Inaktiv EP {SlotNr}";
Scanner = $"Geschlossen {ScannerPort}";
//CheckAllPorts?
sm = PickingStateMachine.StartCom;
InitProgressBar();
break;
case PickingStateMachine.StartCom:
OrderDetails = null;
OrderOverview = null;
Scanner = $"Öfffne {ScannerPort}";
//CheckAllPorts?
barScanner = new BarScanner(ScannerPort, token);
barScanner.Start();
sm = PickingStateMachine.WaitForScanning;
var c = (System.Windows.Media.Brush)converter.ConvertFromString("Aquamarine");
c.Freeze();
ResultColor = c;
ProgressBar.Where(n => n.Name == "Init").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
ProgressBar.Where(n => n.Name == "Scan").First().State = Ui.ProductionControls.Enums.ImgStatus.InProgress;
break;
case PickingStateMachine.WaitForScanning:
Scanner = $"Offen {ScannerPort}";
setState($"Warte auf Scannereingabe({ScannerPort})");
if (barScanner != null && !String.IsNullOrEmpty(barScanner.Input))
{
Order = barScanner.Input;
Scanner = $"Geschlossen {ScannerPort}";
barScanner = null;
sm = PickingStateMachine.WaitForDetect;
ProgressBar.Where(n => n.Name == "Scan").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
ProgressBar.Where(n => n.Name == "Connect").First().State = Ui.ProductionControls.Enums.ImgStatus.InProgress;
}
break;
case PickingStateMachine.WaitForDetect:
using (var Batch = new MeterBatch())
{
using (var tryMeter = new GenesisMeter())
{
try
{
setState($"Warte auf Pcb");
Slot = $"Öffne EP {SlotNr}";
tryMeter.SetupFromConfigFile(SlotNr);
Batch.AddMeter(tryMeter);
tryMeter.Logout();
Log("Try to get PcbID");
PcbId = tryMeter.GetPcbId();
var hasDetect = !string.IsNullOrEmpty(PcbId);
if (hasDetect)
{
setState( $"Pcb gefunden {PcbId}");
Log($"New PcbID detected {PcbId}");
sm = PickingStateMachine.GetOrderDetails;
ProgressBar.Where(n => n.Name == "Connect").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
ProgressBar.Where(n => n.Name == "Order data").First().State = Ui.ProductionControls.Enums.ImgStatus.InProgress;
}
else
{
Slot = $"Keine Konnektivität EP {SlotNr}";
Log($"No Meter found");
}
}
catch (Exception e)
{
Log($"Error occur.{ Environment.NewLine} {e.Message}");
}
}
}
break;
case PickingStateMachine.GetOrderDetails:
setState($"Lade Auftragsdaten {Order}");
var retCode = 0;
var str = LocalWebRequest.GetRequestWithError($"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetOrderOverview?ProductionOrderNumber={Order}&CheckPcbId={PcbId}", out retCode, 35000);
if (retCode == 417)
{
sm = PickingStateMachine.MeterError;
Result = "Keine Radio Parameter";
UpdateLogText(Result, true);
ProgressBar.Where(n => n.Name == "Compare Result").First().State = Ui.ProductionControls.Enums.ImgStatus.Error;
ProgressBar.Where(n => n.Name == "Order data").First().State = Ui.ProductionControls.Enums.ImgStatus.Error;
}
else
{
OrderOverview = JsonConvert.DeserializeObject<OrderOverViewCordonelWithPicking>(str);
OrderDetails = OrderOverview.PickingCompareItem;
if (OrderOverview.OrderOverViewCordonel.Count == OrderOverview.OrderOverViewCordonel.AssignedPicking)
{
Result = "Auftrag schon komplett";
UpdateLogText(Result, true);
sm = PickingStateMachine.MeterError;
ProgressBar.Where(n => n.Name == "Compare Result").First().State = Ui.ProductionControls.Enums.ImgStatus.Error;
ProgressBar.Where(n => n.Name == "Order data").First().State = Ui.ProductionControls.Enums.ImgStatus.Error;
}
else
{
setState($"Auftragsdaten geladen {Order}");
sm = PickingStateMachine.Compare;
ProgressBar.Where(n => n.Name == "Order data").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
ProgressBar.Where(n => n.Name == "Compare").First().State = Ui.ProductionControls.Enums.ImgStatus.InProgress;
}
}
break;
case PickingStateMachine.Compare:
//Compare
setState($"Vergleiche Auftragsdaten {Order} mit Pcb Eigenschaften");
var minDate = DateTime.Now;
minDate = minDate.AddMonths(OrderOverview.OrderOverViewCordonel.Count < 5 ? -9 : -3);
setState($"Register wurde am {OrderOverview.KitronProductionDate } hergestellt, für diesen Auftrag ist muss das Register vor {minDate} hergestellt worden sein");
if (OrderOverview.KitronProductionDate <= minDate)
{
setState($"Fehlgeschlagen Register ist zu alt! Bitte QS informieren. KitronProductionDate:{OrderOverview.KitronProductionDate }");
// sm = PickingStateMachine.MeterError;
var b = (System.Windows.Media.Brush)converter.ConvertFromString("#FFFF00");
b.Freeze();
ResultColor = b;
//break;
}
if (Compare(OrderDetails.CheckAppsIdVersion, OrderDetails.FrequencyIndicator, OrderDetails.MeterSize, OrderDetails.PressurePresent))
{
//erfolg anzeigen und weiter
ProgressBar.Where(n => n.Name == "Compare Result").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
ProgressBar.Where(n => n.Name == "Compare").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
sm = PickingStateMachine.MeterDone;
}
else
{
sm = PickingStateMachine.MeterError;
ProgressBar.Where(n => n.Name == "Compare Result").First().State = Ui.ProductionControls.Enums.ImgStatus.Error;
ProgressBar.Where(n => n.Name == "Compare").First().State = Ui.ProductionControls.Enums.ImgStatus.Error;
var b = (System.Windows.Media.Brush)converter.ConvertFromString("#FF8000");
b.Freeze();
ResultColor = b;
}
break;
case PickingStateMachine.MeterError:
OrderDetails = null;
OrderOverview = null;
setState($"Vergleich abgeschlossen:{State}");
Result = $"Vergleich fertig fehlgeschlagen";
Thread.Sleep(10000);
sm = PickingStateMachine.StartCom;
break;
case PickingStateMachine.MeterDone:
setState($"Vergleich abgeschlossen warten auf Montage Rückmeldung");
Result = $"Pcb {PcbId} wurde dem Auftrag {Order} hinzugefügt";
Scanner = $"Öfffne {ScannerPort}";
barScanner = new BarScanner(ScannerPort, token);
HistoryText = $"{HistoryText} {Environment.NewLine}{Order}({OrderOverview.OrderOverViewCordonel.AssignedPicking + 1 }/{ OrderOverview.OrderOverViewCordonel.Count})";
barScanner.Start();
sm = PickingStateMachine.WaitForBuildingMeterReady;
Thread.Sleep(10000);
//CheckAllPorts?
ProgressBar.Where(n => n.Name == "Scan Build").First().State = Ui.ProductionControls.Enums.ImgStatus.InProgress;
break;
case PickingStateMachine.WaitForBuildingMeterReady:
if (barScanner != null && !String.IsNullOrEmpty(barScanner.Input))
{
if (barScanner.Input == "%Cordonel_SAP_100%")
{
ProgressBar.Where(n => n.Name == "Scan Build").First().State = Ui.ProductionControls.Enums.ImgStatus.Success;
var url = ServiceUrls.MeterProcessStateUrl();
url = url + $"setSapState?PcbID={PcbId}&code=100&version=1";
try
{
LocalWebRequest.PostRequestAsync(url);
}
catch (Exception ex)
{
}
if (OrderDetails.PressurePresent)
{
barScanner = new BarScanner(ScannerPort, token);
barScanner.Start();
setState($"Montage Rückmeldung erhalten, Montage des Drucksensors bestätigen");
sm = PickingStateMachine.WaitForBuildingPressureReady;
ProgressBar.Where(n => n.Name == "Scan Build Pressure").First().State = Ui.ProductionControls.Enums.ImgStatus.InProgress;
}
else
{
setState($"Montage Rückmeldung erhalten, auftrag Scannen");
sm = PickingStateMachine.StartCom;
Thread.Sleep(5000);
var b = (System.Windows.Media.Brush)converter.ConvertFromString("#419C14");
b.Freeze();
ResultColor = b;
}
}
}
break;
case PickingStateMachine.WaitForBuildingPressureReady:
if (barScanner != null && !String.IsNullOrEmpty(barScanner.Input))
{
if (barScanner.Input == "%Cordonel_SAP_101%")
{
var url = ServiceUrls.MeterProcessStateUrl();
url = url + $"setSapState?PcbID={PcbId}&code=101&version=1";
try
{
LocalWebRequest.PostRequestAsync(url);
}
catch (Exception ex)
{
}
var b = (System.Windows.Media.Brush)converter.ConvertFromString("#419C14");
b.Freeze();
ResultColor = b;
Thread.Sleep(5000);
setState($"Montage Rückmeldung erhalten, auftrag Scannen");
sm = PickingStateMachine.StartCom;
}
}
break;
default:
break;
}
Thread.Sleep(1000);
}
}
private void Log(string v)
{
//throw new NotImplementedException();
}
}
}