Add ReconnectThread to reconnect to PLC and Keyboard on the fly
Test / Run tests (push) Successful in 26s
Test / Run tests (push) Successful in 26s
This commit is contained in:
@@ -37,12 +37,6 @@ namespace PamhagenSysCtrl {
|
|||||||
Version = new Version(typeof(App).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion.Split('+')[0] ?? "0.0.0");
|
Version = new Version(typeof(App).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion.Split('+')[0] ?? "0.0.0");
|
||||||
|
|
||||||
Plant = new(Config.PlcPort);
|
Plant = new(Config.PlcPort);
|
||||||
try {
|
|
||||||
await Plant.StartThread();
|
|
||||||
} catch (Exception exc) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
base.OnStartup(evt);
|
base.OnStartup(evt);
|
||||||
|
|
||||||
if (Config.UpdateUrl != null && Config.UpdateAuto) {
|
if (Config.UpdateUrl != null && Config.UpdateAuto) {
|
||||||
|
|||||||
@@ -32,40 +32,79 @@ namespace PamhagenSysCtrl.Helpers {
|
|||||||
protected Xbe24Keyboard? Keyboard;
|
protected Xbe24Keyboard? Keyboard;
|
||||||
public PamhagenGraph Graph;
|
public PamhagenGraph Graph;
|
||||||
|
|
||||||
|
public bool IsPlcConnected => Plc != null;
|
||||||
|
public bool IsKeyboardConnected => Keyboard != null;
|
||||||
|
|
||||||
protected bool IsRunning = true;
|
protected bool IsRunning = true;
|
||||||
protected Thread? BackgroundThread;
|
protected Thread? ReconnectThread;
|
||||||
|
protected Thread? PlcThread;
|
||||||
|
|
||||||
public event EventHandler<PlantEventArgs>? Update;
|
public event EventHandler<PlantEventArgs>? Update;
|
||||||
|
|
||||||
public string? PlcPortName => Plc?.PortName;
|
public readonly string PlcComPort;
|
||||||
|
public string? PlcConnectionError { get; private set; }
|
||||||
public T1.Status? LastPlcStatus => Plc?.LastStatus;
|
public T1.Status? LastPlcStatus => Plc?.LastStatus;
|
||||||
public T1Error? LastPlcError => Plc?.LastError;
|
public T1Error? LastPlcError => Plc?.LastError;
|
||||||
public long? LastRttNs { get; private set; }
|
public long? LastRttNs { get; private set; }
|
||||||
|
|
||||||
public PamhagenState State => Plc?.State ?? default; // FIXME
|
public PamhagenState State => Plc?.State ?? default;
|
||||||
public bool ManualControlMode { get => Plc?.ManualControlMode ?? false; set => Plc?.ManualControlMode = value; }
|
public bool ManualControlMode { get => Plc?.ManualControlMode ?? false; set => Plc?.ManualControlMode = value; }
|
||||||
public bool OverridePathClearances { get => Plc?.OverridePathClearances ?? false; set => Plc?.OverridePathClearances = value; }
|
public bool OverridePathClearances { get => Plc?.OverridePathClearances ?? false; set => Plc?.OverridePathClearances = value; }
|
||||||
public bool OverrideDryRunClearances { get => Plc?.OverrideDryRunClearances ?? false; set => Plc?.OverrideDryRunClearances = value; }
|
public bool OverrideDryRunClearances { get => Plc?.OverrideDryRunClearances ?? false; set => Plc?.OverrideDryRunClearances = value; }
|
||||||
|
|
||||||
public PamhagenPlant(string portName) {
|
public PamhagenPlant(string comPort) {
|
||||||
try {
|
PlcComPort = comPort;
|
||||||
Plc = new(portName);
|
|
||||||
} catch (Exception exc) {
|
|
||||||
var str = $"Beim Aufbauen einer Verbindung zur SPS ist ein Fehler aufgetreten:\n\n{exc.GetType().Name}: {exc.Message}";
|
|
||||||
if (exc.InnerException != null) str += $"\n\n{exc.InnerException.GetType().Name}: {exc.InnerException.Message}";
|
|
||||||
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
Graph = new();
|
Graph = new();
|
||||||
|
|
||||||
try {
|
|
||||||
Keyboard = new();
|
|
||||||
Keyboard.KeyDown += Keyboard_KeyDown;
|
|
||||||
Keyboard.KeysChanged += Keyboard_KeysChanged;
|
|
||||||
Keyboard.SetFashFrequency(250);
|
|
||||||
Keyboard.SetBacklight(Color.FromRgb(4, 4, 4));
|
|
||||||
} catch { }
|
|
||||||
|
|
||||||
Update += UpdateKeyboardBacklights;
|
Update += UpdateKeyboardBacklights;
|
||||||
|
ReconnectThread = new Thread(new ParameterizedThreadStart(ReconnectLoop));
|
||||||
|
ReconnectThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async void ReconnectLoop(object? parameters) {
|
||||||
|
while (IsRunning) {
|
||||||
|
if (Plc == null) {
|
||||||
|
PlcThread?.Join();
|
||||||
|
PlcThread = null;
|
||||||
|
PamhagenPlc? tmp = null;
|
||||||
|
try {
|
||||||
|
tmp = new PamhagenPlc(PlcComPort);
|
||||||
|
await tmp.Initialize();
|
||||||
|
Plc = tmp;
|
||||||
|
PlcConnectionError = null;
|
||||||
|
PlcThread = new Thread(new ParameterizedThreadStart(PlcLoop));
|
||||||
|
PlcThread.Start();
|
||||||
|
} catch (Exception exc) {
|
||||||
|
tmp?.Dispose();
|
||||||
|
PlcConnectionError = $"{exc.GetType().Name}: {exc.Message}";
|
||||||
|
if (exc is FileNotFoundException) {
|
||||||
|
// COM port does not exist - ignore
|
||||||
|
PlcConnectionError = "Port existiert nicht";
|
||||||
|
} else if (exc is UnauthorizedAccessException) {
|
||||||
|
// COM port exists, but is used by other process - ignore
|
||||||
|
PlcConnectionError = "Port wird bereits verwendet";
|
||||||
|
} else if (exc is TimeoutException) {
|
||||||
|
// COM port exists, but PLC not responding - ignore
|
||||||
|
PlcConnectionError = "Keine Rückmeldung von SPS";
|
||||||
|
} else {
|
||||||
|
var str = $"Beim Aufbauen einer Verbindung zur SPS ist ein Fehler aufgetreten:\n\n{exc.GetType().Name}: {exc.Message}";
|
||||||
|
if (exc.InnerException != null) str += $"\n\n{exc.InnerException.GetType().Name}: {exc.InnerException.Message}";
|
||||||
|
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RaiseUpdateEvent(new());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Keyboard == null) {
|
||||||
|
try {
|
||||||
|
Keyboard = new();
|
||||||
|
Keyboard.KeyDown += Keyboard_KeyDown;
|
||||||
|
Keyboard.KeysChanged += Keyboard_KeysChanged;
|
||||||
|
Keyboard.SetFashFrequency(250);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RaiseUpdateEvent(PlantEventArgs evt) {
|
protected virtual void RaiseUpdateEvent(PlantEventArgs evt) {
|
||||||
@@ -132,22 +171,17 @@ namespace PamhagenSysCtrl.Helpers {
|
|||||||
k.SetBacklight((int)Xbe24Key.STOP_MP1, highlightOffMP1 ? Color.FromRgb(255, 32, 0) : !State.MP1_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
|
k.SetBacklight((int)Xbe24Key.STOP_MP1, highlightOffMP1 ? Color.FromRgb(255, 32, 0) : !State.MP1_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartThread() {
|
|
||||||
if (Plc == null) throw new Exception();
|
|
||||||
await Plc.Initialize();
|
|
||||||
BackgroundThread = new Thread(new ParameterizedThreadStart(BackgroundLoop));
|
|
||||||
BackgroundThread.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
BackgroundThread?.Join();
|
ReconnectThread?.Join();
|
||||||
|
PlcThread?.Join();
|
||||||
Plc?.Dispose();
|
Plc?.Dispose();
|
||||||
Keyboard?.Dispose();
|
Keyboard?.Dispose();
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async void BackgroundLoop(object? parameters) {
|
protected async void PlcLoop(object? parameters) {
|
||||||
|
App.MainDispatcher?.Invoke(InitializePaths);
|
||||||
while (IsRunning && Plc != null) {
|
while (IsRunning && Plc != null) {
|
||||||
var start = DateTime.Now;
|
var start = DateTime.Now;
|
||||||
try {
|
try {
|
||||||
@@ -160,22 +194,24 @@ namespace PamhagenSysCtrl.Helpers {
|
|||||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||||
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
if (exc is TimeoutException or IOException) {
|
if (exc is TimeoutException or IOException) {
|
||||||
|
PlcConnectionError = $"{exc.GetType().Name}: {exc.Message}";
|
||||||
Plc?.Dispose();
|
Plc?.Dispose();
|
||||||
Plc = null;
|
Plc = null;
|
||||||
IsRunning = false;
|
|
||||||
} else {
|
} else {
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
if (Plc != null) {
|
||||||
if (Plc != null)
|
try {
|
||||||
await Plc.Shutdown();
|
await Plc.Shutdown();
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
var str = "Beim Schließen der Verbindung zur SPS ist ein Fehler aufgetreten:\n\n" + exc.Message;
|
var str = "Beim Schließen der Verbindung zur SPS ist ein Fehler aufgetreten:\n\n" + exc.Message;
|
||||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||||
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
RaiseUpdateEvent(new());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitializePaths() {
|
public void InitializePaths() {
|
||||||
@@ -219,69 +255,67 @@ namespace PamhagenSysCtrl.Helpers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void Keyboard_KeyDown(object? sender, int keyIndex) {
|
private void Keyboard_KeyDown(object? sender, int keyIndex) {
|
||||||
|
if (Plc == null) return;
|
||||||
var key = (Xbe24Key)keyIndex;
|
var key = (Xbe24Key)keyIndex;
|
||||||
App.MainDispatcher?.BeginInvoke(() => {
|
try {
|
||||||
if (Plc == null) return;
|
if (key == Xbe24Key.START_REBLER) {
|
||||||
try {
|
Plc.StartRebler();
|
||||||
if (key == Xbe24Key.START_REBLER) {
|
} else if (key == Xbe24Key.STOP_REBLER) {
|
||||||
Plc.StartRebler();
|
if (State.Rebler_IsActive) {
|
||||||
} else if (key == Xbe24Key.STOP_REBLER) {
|
Plc.StopRebler();
|
||||||
if (State.Rebler_IsActive) {
|
} else {
|
||||||
Plc.StopRebler();
|
Plc.StopAuger1();
|
||||||
} else {
|
if (!State.PressCrossAuger_IsActive) {
|
||||||
Plc.StopAuger1();
|
Plc.StopAuger2();
|
||||||
if (!State.PressCrossAuger_IsActive) {
|
Plc.StopAuger3();
|
||||||
Plc.StopAuger2();
|
|
||||||
Plc.StopAuger3();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (key == Xbe24Key.START_TROUGH_AUGER) {
|
|
||||||
Plc.StartTroughAuger();
|
|
||||||
} else if (key == Xbe24Key.STOP_TROUGH_AUGER) {
|
|
||||||
Plc.StopTroughAuger();
|
|
||||||
} else if (key == Xbe24Key.SELECT_MW2) {
|
|
||||||
Plc.SelectMW2();
|
|
||||||
} else if (key == Xbe24Key.SELECT_MW1) {
|
|
||||||
Plc.SelectMW1();
|
|
||||||
} else if (key == Xbe24Key.START_MP2) {
|
|
||||||
Plc.StartMP2Forward();
|
|
||||||
} else if (key == Xbe24Key.STOP_MP2) {
|
|
||||||
Plc.StopMP2();
|
|
||||||
} else if (key == Xbe24Key.START_MP1) {
|
|
||||||
Plc.StartMP1Forward();
|
|
||||||
} else if (key == Xbe24Key.STOP_MP1) {
|
|
||||||
Plc.StopMP1();
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW1_1) {
|
|
||||||
FastSelect(Graph.MW1, Graph.Press1);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW1_2) {
|
|
||||||
FastSelect(Graph.MW1, Graph.Press2);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW1_3) {
|
|
||||||
FastSelect(Graph.MW1, Graph.Tank1);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW1_4) {
|
|
||||||
FastSelect(Graph.MW1, Graph.Tank2);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW1_5) {
|
|
||||||
FastSelect(Graph.MW1, Graph.Tank3);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW1_6) {
|
|
||||||
FastSelect(Graph.MW1, Graph.Tank4);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW2_1) {
|
|
||||||
FastSelect(Graph.MW2, Graph.Press1);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW2_2) {
|
|
||||||
FastSelect(Graph.MW2, Graph.Press2);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW2_3) {
|
|
||||||
FastSelect(Graph.MW2, Graph.Tank1);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW2_4) {
|
|
||||||
FastSelect(Graph.MW2, Graph.Tank2);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW2_5) {
|
|
||||||
FastSelect(Graph.MW2, Graph.Tank3);
|
|
||||||
} else if (key == Xbe24Key.FAST_SELECT_MW2_6) {
|
|
||||||
FastSelect(Graph.MW2, Graph.Tank4);
|
|
||||||
}
|
}
|
||||||
} catch (NoClearanceException) {
|
} else if (key == Xbe24Key.START_TROUGH_AUGER) {
|
||||||
// Keyboard?.SetBacklight(keyIndex, Color.FromRgb(255, 0, 0));
|
Plc.StartTroughAuger();
|
||||||
} catch (Exception) {
|
} else if (key == Xbe24Key.STOP_TROUGH_AUGER) {
|
||||||
// ignore
|
Plc.StopTroughAuger();
|
||||||
|
} else if (key == Xbe24Key.SELECT_MW2) {
|
||||||
|
Plc.SelectMW2();
|
||||||
|
} else if (key == Xbe24Key.SELECT_MW1) {
|
||||||
|
Plc.SelectMW1();
|
||||||
|
} else if (key == Xbe24Key.START_MP2) {
|
||||||
|
Plc.StartMP2Forward();
|
||||||
|
} else if (key == Xbe24Key.STOP_MP2) {
|
||||||
|
Plc.StopMP2();
|
||||||
|
} else if (key == Xbe24Key.START_MP1) {
|
||||||
|
Plc.StartMP1Forward();
|
||||||
|
} else if (key == Xbe24Key.STOP_MP1) {
|
||||||
|
Plc.StopMP1();
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW1_1) {
|
||||||
|
FastSelect(Graph.MW1, Graph.Press1);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW1_2) {
|
||||||
|
FastSelect(Graph.MW1, Graph.Press2);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW1_3) {
|
||||||
|
FastSelect(Graph.MW1, Graph.Tank1);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW1_4) {
|
||||||
|
FastSelect(Graph.MW1, Graph.Tank2);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW1_5) {
|
||||||
|
FastSelect(Graph.MW1, Graph.Tank3);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW1_6) {
|
||||||
|
FastSelect(Graph.MW1, Graph.Tank4);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW2_1) {
|
||||||
|
FastSelect(Graph.MW2, Graph.Press1);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW2_2) {
|
||||||
|
FastSelect(Graph.MW2, Graph.Press2);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW2_3) {
|
||||||
|
FastSelect(Graph.MW2, Graph.Tank1);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW2_4) {
|
||||||
|
FastSelect(Graph.MW2, Graph.Tank2);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW2_5) {
|
||||||
|
FastSelect(Graph.MW2, Graph.Tank3);
|
||||||
|
} else if (key == Xbe24Key.FAST_SELECT_MW2_6) {
|
||||||
|
FastSelect(Graph.MW2, Graph.Tank4);
|
||||||
}
|
}
|
||||||
});
|
} catch (NoClearanceException) {
|
||||||
|
// Keyboard?.SetBacklight(keyIndex, Color.FromRgb(255, 0, 0));
|
||||||
|
} catch (Exception) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Keyboard_KeysChanged(object? sender, Xbe24Keyboard.KeyState state) {
|
private void Keyboard_KeysChanged(object? sender, Xbe24Keyboard.KeyState state) {
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ namespace PamhagenSysCtrl.Helpers.Plc {
|
|||||||
|
|
||||||
protected readonly T1 Plc;
|
protected readonly T1 Plc;
|
||||||
|
|
||||||
public string PortName => Plc.PortName;
|
public string ComPort => Plc.PortName;
|
||||||
public T1.Status LastStatus => Plc.LastStatus;
|
public T1.Status LastStatus => Plc.LastStatus;
|
||||||
public T1Error LastError => Plc.LastError;
|
public T1Error LastError => Plc.LastError;
|
||||||
|
|
||||||
public LegacyPamhagenPlc(string portName, Parity parity = Parity.Odd) {
|
public LegacyPamhagenPlc(string comPort, Parity parity = Parity.Odd) {
|
||||||
Plc = new T1(portName, parity);
|
Plc = new T1(comPort, parity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
|
|||||||
protected LegacyPamhagenPlc Plc;
|
protected LegacyPamhagenPlc Plc;
|
||||||
public PamhagenState State { get; private set; }
|
public PamhagenState State { get; private set; }
|
||||||
|
|
||||||
public string? PortName => Plc?.PortName;
|
public string? ComPort => Plc?.ComPort;
|
||||||
public T1.Status? LastStatus => Plc?.LastStatus;
|
public T1.Status? LastStatus => Plc?.LastStatus;
|
||||||
public T1Error? LastError => Plc?.LastError;
|
public T1Error? LastError => Plc?.LastError;
|
||||||
|
|
||||||
@@ -23,8 +23,8 @@ namespace PamhagenSysCtrl.Helpers.Plc {
|
|||||||
FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown
|
FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown
|
||||||
], default);
|
], default);
|
||||||
|
|
||||||
public PamhagenPlc(string portName, Parity parity = Parity.Odd) {
|
public PamhagenPlc(string comPort, Parity parity = Parity.Odd) {
|
||||||
Plc = new(portName, parity);
|
Plc = new(comPort, parity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
@@ -36,6 +36,8 @@ namespace PamhagenSysCtrl.Helpers.Plc {
|
|||||||
await Plc.TestConnection();
|
await Plc.TestConnection();
|
||||||
Actuators = await Plc.ReadOutputs();
|
Actuators = await Plc.ReadOutputs();
|
||||||
LastActuators = Actuators;
|
LastActuators = Actuators;
|
||||||
|
Sensors = await Plc.ReadInputs();
|
||||||
|
State = new(Sensors, () => Actuators, OverridePathClearances, OverrideDryRunClearances);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Shutdown() {
|
public async Task Shutdown() {
|
||||||
@@ -46,9 +48,8 @@ namespace PamhagenSysCtrl.Helpers.Plc {
|
|||||||
UpdateInterlocks();
|
UpdateInterlocks();
|
||||||
|
|
||||||
if (Actuators != LastActuators) {
|
if (Actuators != LastActuators) {
|
||||||
// FIXME race condition!
|
|
||||||
await Plc.WriteOutputs(Actuators);
|
|
||||||
LastActuators = Actuators;
|
LastActuators = Actuators;
|
||||||
|
await Plc.WriteOutputs(LastActuators);
|
||||||
}
|
}
|
||||||
Sensors = await Plc.ReadInputs();
|
Sensors = await Plc.ReadInputs();
|
||||||
State = new(Sensors, () => Actuators, OverridePathClearances, OverrideDryRunClearances);
|
State = new(Sensors, () => Actuators, OverridePathClearances, OverrideDryRunClearances);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
|
|||||||
public FillState MW1_FillLevel => Sensors.FillLevelMW1;
|
public FillState MW1_FillLevel => Sensors.FillLevelMW1;
|
||||||
public FillState MW2_FillLevel => Sensors.FillLevelMW2;
|
public FillState MW2_FillLevel => Sensors.FillLevelMW2;
|
||||||
|
|
||||||
public FillState[] Tanks_FillLevel => Sensors.FillLevelTanks;
|
public FillState[] Tanks_FillLevel => Sensors.FillLevelTanks ?? [FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown];
|
||||||
public FillState T1_FillLevel => Sensors.FillLevelTanks[0];
|
public FillState T1_FillLevel => Sensors.FillLevelTanks[0];
|
||||||
public FillState T2_FillLevel => Sensors.FillLevelTanks[1];
|
public FillState T2_FillLevel => Sensors.FillLevelTanks[1];
|
||||||
public FillState T3_FillLevel => Sensors.FillLevelTanks[2];
|
public FillState T3_FillLevel => Sensors.FillLevelTanks[2];
|
||||||
|
|||||||
@@ -39,9 +39,13 @@ namespace PamhagenSysCtrl.Helpers {
|
|||||||
throw new IOException($"Unable to SetDataCallback for XBE keyboard: {res}");
|
throw new IOException($"Unable to SetDataCallback for XBE keyboard: {res}");
|
||||||
if ((res = XbeDevice.SetErrorCallback(this)) != 0)
|
if ((res = XbeDevice.SetErrorCallback(this)) != 0)
|
||||||
throw new IOException($"Unable to SetErrorCallback for XBE keyboard: {res}");
|
throw new IOException($"Unable to SetErrorCallback for XBE keyboard: {res}");
|
||||||
|
|
||||||
|
SetBacklight(Color.FromRgb(1, 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
SetBacklight(Color.FromRgb(1, 1, 1));
|
||||||
XbeDevice?.CloseInterface();
|
XbeDevice?.CloseInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,10 @@ namespace PamhagenSysCtrl.Windows {
|
|||||||
[FastSelectButton_MW1_Tank5] = (Graph.MW1, Graph.MP1, Graph.Tank5),
|
[FastSelectButton_MW1_Tank5] = (Graph.MW1, Graph.MP1, Graph.Tank5),
|
||||||
[FastSelectButton_MW2_Tank5] = (Graph.MW2, Graph.MP2, Graph.Tank5),
|
[FastSelectButton_MW2_Tank5] = (Graph.MW2, Graph.MP2, Graph.Tank5),
|
||||||
};
|
};
|
||||||
App.Plant?.Update += OnUpdate;
|
if (App.Plant != null) {
|
||||||
App.Plant?.InitializePaths();
|
Status_Connection.Text = $"Nein ({App.Plant.PlcComPort})";
|
||||||
|
App.Plant.Update += OnUpdate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClosed(object sender, EventArgs evt) {
|
private void OnClosed(object sender, EventArgs evt) {
|
||||||
@@ -584,27 +586,21 @@ namespace PamhagenSysCtrl.Windows {
|
|||||||
|
|
||||||
public void OnUpdate(object? sender, PlantEventArgs? evt) {
|
public void OnUpdate(object? sender, PlantEventArgs? evt) {
|
||||||
if (App.Plant is PamhagenPlant p) {
|
if (App.Plant is PamhagenPlant p) {
|
||||||
Status_Connection.Text = $"Ja ({p.PlcPortName}" + (p.LastRttNs != null ? $", {p.LastRttNs / 1000000.0:N0} ms" : "") + ")";
|
if (p.IsPlcConnected) {
|
||||||
Status_Plc.Text = $"{p.LastPlcStatus?.Mode} ({p.LastPlcStatus?.Flags:X3}) / {p.LastPlcError?.GetName()} ({(int?)p.LastPlcError:0000})";
|
Status_Connection.Text = $"Ja ({p.PlcComPort}" + (p.LastRttNs != null ? $", {p.LastRttNs / 1000000.0:N0} ms" : "") + ")";
|
||||||
Status_CompressedAir.Text = Enumerable.Range(1, 57).Any(p.State.Valve_IsClosed) ? "Ein" : Enumerable.Range(1, 57).Any(p.State.Valve_WantClosed) ? "Aus" : "?";
|
Status_Plc.Text = $"{p.LastPlcStatus?.Mode} ({p.LastPlcStatus?.Flags:X3}) / {p.LastPlcError?.GetName()} ({(int?)p.LastPlcError:0000})";
|
||||||
Status_ValvesOpen.Text = Enumerable.Range(1, 57).Count(p.State.Valve_IsOpen) + " / " + Enumerable.Range(1, 57).Count(p.State.Valve_WantOpen) + " / 57";
|
Status_CompressedAir.Text = Enumerable.Range(1, 57).Any(p.State.Valve_IsClosed) ? "Ein" : Enumerable.Range(1, 57).Any(p.State.Valve_WantClosed) ? "Aus" : "?";
|
||||||
|
Status_ValvesOpen.Text = Enumerable.Range(1, 57).Count(p.State.Valve_IsOpen) + " / " + Enumerable.Range(1, 57).Count(p.State.Valve_WantOpen) + " / 57";
|
||||||
|
} else {
|
||||||
|
Status_Connection.Text = p.PlcConnectionError is string err ? $"Nein ({p.PlcComPort}, {err})" : $"Nein ({p.PlcComPort})";
|
||||||
|
Status_Plc.Text = "-";
|
||||||
|
Status_CompressedAir.Text = "-";
|
||||||
|
Status_ValvesOpen.Text = "-";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UpdateScheme(Mouse.GetPosition(SchemeCanvas), Mouse.LeftButton == MouseButtonState.Pressed);
|
UpdateScheme(Mouse.GetPosition(SchemeCanvas), Mouse.LeftButton == MouseButtonState.Pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitializePaths() {
|
|
||||||
var add = ReconstructSelectedPaths().ToList();
|
|
||||||
var remove = Graph.SelectedPaths.ToList();
|
|
||||||
foreach (var p in remove) Graph.RemovePath(p);
|
|
||||||
for (int i = 1; i <= 57; i++) {
|
|
||||||
App.Plant?.CloseV(i);
|
|
||||||
}
|
|
||||||
foreach (var p in add) {
|
|
||||||
if (p.Hops.Any(h => h.Node is ControlledValve v && v.IsLocked)) continue;
|
|
||||||
Graph.AddPath(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Path> ReconstructSelectedPaths() {
|
public IEnumerable<Path> ReconstructSelectedPaths() {
|
||||||
if (App.Plant is not PamhagenPlant p) yield break;
|
if (App.Plant is not PamhagenPlant p) yield break;
|
||||||
var sources = Graph.Nodes.Where(n => n is ISource).ToList();
|
var sources = Graph.Nodes.Where(n => n is ISource).ToList();
|
||||||
|
|||||||
Reference in New Issue
Block a user