laatzen/Common/CordonelAssemblyLine/Model/MarriageViewModel.cs
2021-10-01 11:09:20 +02:00

625 lines
23 KiB
C#

using Logic.ProductionToProductMapper.Cordonel;
using NLog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
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.Hardware.WaterMeter.WaterMeterCore.Consts;
using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Utils.Logging;
namespace CordonelAssemblyLine.Model
{
internal class MarriageViewModel : INotifyPropertyChanged
{
public event EventHandler<string> OnMsgRaise;
public MarriageViewModel(string scannerPort, int slotNr)
{
_logger = NLogHelper.CreateOrGetLogger("ProductionUI");
ScannerPort = scannerPort;
SlotNr = slotNr;
}
private readonly ILogger _logger;
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 string Slot
{
get
{
return slot;
}
set
{
slot = value;
NotifyPropertyChanged(nameof(Slot));
}
}
public string SerialNr
{
get
{
return serialNr;
}
set
{
serialNr = value;
NotifyPropertyChanged(nameof(SerialNr));
}
}
public string Result
{
get
{
return result;
}
set
{
result = value;
NotifyPropertyChanged(nameof(Result));
}
}
public bool CanMarry
{
get
{
return canMarry;
}
set
{
canMarry = value;
NotifyPropertyChanged(nameof(CanMarry));
}
}
public string PcbId
{
get
{
return pcbId;
}
set
{
pcbId = value;
NotifyPropertyChanged(nameof(PcbId));
}
}
private string pcbId;
private bool canMarry = false;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void StartStore()
{
sm = PickingStateMachine.Store;
}
public void StartPicking(CancellationToken cancle)
{
var s = new Task(() => { PickingLoop(cancle); }, cancle);
s.Start();
}
public enum PickingStateMachine
{
Init,
WaitForScanning,
ScanningDone,
WaitForDetect,
GetMapping,
Store,
WaitForBuildingMeterReady,
MappingError,
Done
}
private PickingStateMachine sm = PickingStateMachine.Init;
private class BarScanner : IDisposable
{
public bool? IsRuning = null;
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.HasValue || !IsRuning.Value)
{
if (Port == null)
{
return;
}
WaitForScannerTask = new Task(() =>
{
try
{
using (var a = new SerialPort(Port))
{
a.Open();
a.NewLine = "\r";
while (true)
{
if (Cancellation.IsCancellationRequested)
{
IsRuning = false;
break;
}
else
{
IsRuning = true;
Input = a.ReadLine();
a.Close();
IsRuning = false;
break;
}
}
}
}
catch (Exception ex)
{
IsRuning = false;
}
}, Cancellation);
WaitForScannerTask.Start();
}
}
public void Dispose()
{
if (WaitForScannerTask.Status != TaskStatus.Faulted && WaitForScannerTask.Status != TaskStatus.RanToCompletion && WaitForScannerTask.Status != TaskStatus.Canceled)
{
WaitForScannerTask.Dispose();
}
}
}
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);
State = "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={serialNr}";
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)
{
State = $"Üperprüfe Parameter";
var FrequencyReadOut = RegisterConverter.ConvertTo<UInt32>(meter.ReadRegister("SENSUSRADIO_FrequencyIndicator"));
if (FrequencyReadOut != Frequency)
{
State = $"Falsche Frequenz! soll {Frequency}MHz ist {FrequencyReadOut}MHz";
return false;
}
var MeterSizeReadOut = RegisterConverter.ConvertTo<UInt32>(meter.ReadRegister("GENESISFLOW_MeterSize"));
if (MeterSizeReadOut != MeterSize)
{
State = $"Meter Dn falsch! soll {MeterSize}DN ist {MeterSizeReadOut}DN";
return false;
}
var PressureReadOut = RegisterConverter.ConvertTo<bool>(meter.ReadRegister("METROLOGYASST_PressurePresent"));
if (PressureReadOut != PressurePresent)
{
if (PressurePresent)
{
State = $"Pcb mit Drucksensor. Laut Auftrag keine verbaut";
}
else
{
State = $"Pcb ohne Drucksensor. Laut Auftrag soll eine verbaut werden";
}
//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)
{
State = $"Falsche FW, bitte Updaten";
return false;
}
}
catch (Exception)
{
State = $"Fehler beim auslesen der FW";
return false;
}
}
try
{
meter.WriteRegister("METROLOGYASST_StoreConfiguration", 1);
Thread.Sleep(100);
var storeRet = meter.ReadRegister("METROLOGYASST_StoreConfiguration");
if (!storeRet.All(a => a.Equals(0)))
{
State = $"Filesystem corrupt";
return false;
}
}
catch (Exception)
{
State = $"Fehler beim überprüfen des Filesystems";
return false;
}
return true;
}
private PickingCompareItem OrderDetails;
private BarScanner barScanner;
private string serialNr;
private readonly string ScannerPort;
private readonly int SlotNr;
//PickingState,PickingScanner,PickingSlot,PickingResult
private void PickingLoop(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
switch (sm)
{
case PickingStateMachine.Init:
CanMarry = false;
State = "Initialisierung";
Slot = $"Inaktiv EP {SlotNr}";
Scanner = $"Geschlossen {ScannerPort}";
//CheckAllPorts?
Scanner = $"Öfffne {ScannerPort}";
//CheckAllPorts?
barScanner = new BarScanner(ScannerPort, token);
barScanner.Start();
while (!barScanner.IsRuning.HasValue)
{
Thread.Sleep(50);
}
if (barScanner.IsRuning.HasValue && barScanner.IsRuning.Value)
{
Scanner = $"Offen {ScannerPort}";
sm = PickingStateMachine.WaitForScanning;
}
else
{
Scanner = $"Nicht geöffnet {ScannerPort}";
sm = PickingStateMachine.Init;
Thread.Sleep(5000);
}
break;
case PickingStateMachine.WaitForScanning:
OrderDetails = null;
State = $"Warte auf Scannereingabe({ScannerPort})";
if (barScanner != null && !String.IsNullOrEmpty(barScanner.Input))
{
SerialNr = barScanner.Input;
Scanner = $"Geschlossen {ScannerPort}";
barScanner = null;
sm = PickingStateMachine.WaitForDetect;
}
break;
case PickingStateMachine.WaitForDetect:
using (var Batch = new MeterBatch())
{
using (var tryMeter = new GenesisMeter())
{
try
{
State = $"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)
{
State = $"Pcb gefunden {PcbId}";
Log($"New PcbID detected {PcbId}");
sm = PickingStateMachine.GetMapping;
}
else
{
Slot = $"Keine Konnektivität EP {SlotNr}";
Log($"No Meter found");
}
}
catch (Exception e)
{
Log($"Error occur.{ Environment.NewLine} {e.Message}");
}
}
}
break;
case PickingStateMachine.GetMapping:
State = $"Lade Auftragsdaten {serialNr}";
var retCode = 0;
var str = LocalWebRequest.GetRequestWithError($"{ServiceUrls.MarriageServiceUrl()}GetPreMarriageState?SerialNumber={serialNr}&PcbId={PcbId}", out retCode, 15000);
var retInt = MarriagePossibleEnum.None;
if (retCode != 200 || !MarriagePossibleEnum.TryParse(str, out retInt))
{
OnMsgRaise?.Invoke(this, $"Technisches Problem beim abfragen der Verfügbarkeit. Code ({retCode})");
sm = PickingStateMachine.MappingError;
}
List<string> MappingText = new List<string>();
if (retInt.HasFlag(MarriagePossibleEnum.NotPossibleDueAlredayMatch))
{
MappingText.Add("Pcb ist schon mit dieser Seriennummer verbunden.");
}
if (retInt.HasFlag(MarriagePossibleEnum.NotPossibleDuePcblocked))
{
MappingText.Add("Pcb ist schon mit einer anderen Seriennummer verbunden.");
}
if (retInt.HasFlag(MarriagePossibleEnum.NotPossibleDueSerialNumberBlocked))
{
MappingText.Add("Seriennummer ist schon mit einer anderen Pcb verbunden.");
}
if (retInt.HasFlag(MarriagePossibleEnum.PcbNotMatchingOrder))
{
MappingText.Add("Die Pcb ist noch keinem Auftrag zugeordnet.");
}
if (retInt.HasFlag(MarriagePossibleEnum.Error))
{
MappingText.Add("Ein unbestimmter Fehler ist aufgetreten.");
}
if (MappingText.Any())
{
var MsgText = "";
foreach (var item in MappingText)
{
MsgText = MsgText + Environment.NewLine + item;
}
OnMsgRaise?.Invoke(this, $"Diese Kombination ist nicht möglich.{MsgText}");
sm = PickingStateMachine.MappingError;
Log($"No Meter found");
}
else
{
sm = PickingStateMachine.WaitForBuildingMeterReady;
}
break;
case PickingStateMachine.WaitForBuildingMeterReady:
CanMarry = true;
break;
case PickingStateMachine.MappingError:
State = $"Mapping nicht möglich, bitte erneut scannen";
Log($"Mapping nicht möglich, bitte erneut scannen");
Thread.Sleep(10000);
sm = PickingStateMachine.Init;
break;
case PickingStateMachine.Store:
CanMarry = false;
var url = $"{ServiceUrls.MarriageServiceUrl()}SetPcbToSerial?PcbId={PcbId}&Scan={serialNr}&returnMetroData=0";
try
{
string resp = "";
try
{
resp = LocalWebRequest.GetRequest(url, 18000);
}
catch (Exception ex)
{
if (!ex.Message.Contains("Mapping already exist. check your marriage request"))
{
throw;
}
else
{
resp = "already store";
}
}
if (resp.Trim().ToLower().Contains("store"))
{
using (var Batch = new MeterBatch())
{
using (var tryMeter = new GenesisMeter())
{
try
{
State = $"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)
{
tryMeter.Login();
State = $"Pcb gefunden {PcbId}";
Log($"New PcbID detected {PcbId}");
tryMeter.SetProcessState(DisplayCodes.Mounted);
tryMeter.PushProgress("AssemblyLine", Assembly.GetExecutingAssembly().GetName().Version.ToString());
sm = PickingStateMachine.Done;
}
else
{
Slot = $"Keine Konnektivität EP {SlotNr}";
Log($"No Meter found");
}
OnMsgRaise?.Invoke(this, $"Zähler verheiratet. Kann zur Prüfstation");
}
catch (Exception e)
{
Log($"Error occur.{ Environment.NewLine} {e.Message}");
}
}
}
}
else
{
OnMsgRaise?.Invoke(this, $"Fehler beim Speichern, bitte Support Kontaktieren.Response{resp}");
}
sm = PickingStateMachine.Init;
}
catch (Exception ex)
{
if (ex is WebException)
{
Log($"Error on Store {url}: {Environment.NewLine} {((WebException)ex).Message}");
}
else
{
Log(ex.Message);
}
}
break;
case PickingStateMachine.Done:
OnMsgRaise?.Invoke(this, $"Bitte Display überprüfen. {Environment.NewLine}Sollte etwas anderes als {DisplayCodes.Mounted} im Display erscheinen ist der Zähler nicht erfolgreich bearbeitet.");
sm = PickingStateMachine.Init;
break;
default:
break;
}
Thread.Sleep(1000);
}
}
public void Log(string txt)
{
_logger?.Info(txt);
}
}
}