Refactor PamhagenPlc
Test / Run tests (push) Successful in 36s

This commit is contained in:
2026-10-13 12:45:33 +02:00
parent 6f076919c7
commit 49bdd5d4c0
10 changed files with 754 additions and 727 deletions
+20 -20
View File
@@ -66,26 +66,26 @@ namespace PamhagenSysCtrl.Helpers {
var pr1X = -15; var pr1X = -15;
var pr2X = 23; var pr2X = 23;
var trough = new EntryTrough("Auffangwanne", mw1X + 14, rebY - 20, () => App.Plant?.IsTroughAugerActive ?? false); var trough = new EntryTrough("Auffangwanne", mw1X + 14, rebY - 20, () => App.Plant?.State.TroughAuger_IsActive ?? false);
Nodes.Add(trough); Nodes.Add(trough);
Auger1 = new EncasedAuger("", rebX - 19, rebY, () => App.Plant?.IsAuger1Active ?? false); Auger1 = new EncasedAuger("", rebX - 19, rebY, () => App.Plant?.State.Auger1_IsActive ?? false);
var auger0 = new EncasedAuger("Pressen-\nQuerschnecke", rebX - 39, rebY, () => App.Plant?.IsPresseQuerSchneckeActive ?? false, 180, clickable: false); var auger0 = new EncasedAuger("Pressen-\nQuerschnecke", rebX - 39, rebY, () => App.Plant?.State.PressCrossAuger_IsActive ?? false, 180, clickable: false);
Auger3 = new EncasedAuger("", rebX - 23, rebY - 24, () => App.Plant?.IsAuger3Active ?? false, 135); Auger3 = new EncasedAuger("", rebX - 23, rebY - 24, () => App.Plant?.State.Auger3_IsActive ?? false, 135);
var belt = new ConveyorBelt("", rebX - 29, rebY - 8, () => App.Plant?.IsAuger2Active ?? false); var belt = new ConveyorBelt("", rebX - 29, rebY - 8, () => App.Plant?.State.Auger2_IsActive ?? false);
Nodes.Add(belt); Nodes.Add(belt);
Nodes.Add(Auger1); Nodes.Add(Auger1);
Nodes.Add(auger0); Nodes.Add(auger0);
Nodes.Add(Auger3); Nodes.Add(Auger3);
var rebler = new Rebler("Rebler", rebX, rebY, () => App.Plant?.IsReblerActive ?? false); var rebler = new Rebler("Rebler", rebX, rebY, () => App.Plant?.State.Rebler_IsActive ?? false);
Nodes.Add(rebler); Nodes.Add(rebler);
var switcher = new Switcher("", rebX, rebY + 12, () => App.Plant?.TroughSelector ?? 0, () => App.Plant == null ? 0 : App.Plant.WantMW1Selected ? 1 : 2); var switcher = new Switcher("", rebX, rebY + 12, () => App.Plant?.State.MW1_IsSelected == true ? 1 : App.Plant?.State.MW2_IsSelected == true ? 2 : 0, () => App.Plant?.State.MW1_WantSelected == true ? 1 : App.Plant?.State.MW2_WantSelected == true ? 2 : 0);
Nodes.Add(switcher); Nodes.Add(switcher);
MW1 = new Trough("MW1", mw1X, mpY - 14, () => App.Plant?.FillLevelMW1 ?? FillState.Unknown); MW1 = new Trough("MW1", mw1X, mpY - 14, () => App.Plant?.State.MW1_FillLevel ?? FillState.Unknown);
MW2 = new Trough("MW2", mw2X, mpY - 14, () => App.Plant?.FillLevelMW2 ?? FillState.Unknown); MW2 = new Trough("MW2", mw2X, mpY - 14, () => App.Plant?.State.MW2_FillLevel ?? FillState.Unknown);
MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.MP1 ?? default, () => App.Plant?.MP1HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.State.MP1_State ?? default, () => App.Plant?.State.MP1_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.MP2 ?? default, () => App.Plant?.MP2HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.State.MP2_State ?? default, () => App.Plant?.State.MP2_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
var x1 = new PipeJoin(mw1X, mpY + 8); var x1 = new PipeJoin(mw1X, mpY + 8);
var x2 = new PipeJoin(mw2X, mpY + 8); var x2 = new PipeJoin(mw2X, mpY + 8);
@@ -309,14 +309,14 @@ namespace PamhagenSysCtrl.Helpers {
CreateInlet(v43, Tank9); CreateInlet(v43, Tank9);
var xp12 = new PipeJoin((t1X + t2X) / 2, tanksY + 16); var xp12 = new PipeJoin((t1X + t2X) / 2, tanksY + 16);
P12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 22, () => App.Plant?.P12 ?? default, () => App.Plant?.P12HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); P12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 22, () => App.Plant?.State.P12_State ?? default, () => App.Plant?.State.P12_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
CreateOutlet(Tank1, xp12); CreateOutlet(Tank1, xp12);
CreateOutlet(Tank2, xp12); CreateOutlet(Tank2, xp12);
CreatePipe(xp12, P12); CreatePipe(xp12, P12);
P3 = new Pump("P3", t3X, tanksY + 22, () => App.Plant?.P3 ?? default, () => App.Plant?.P3HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); P3 = new Pump("P3", t3X, tanksY + 22, () => App.Plant?.State.P3_State ?? default, () => App.Plant?.State.P3_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
P4 = new Pump("P4", t4X, tanksY + 22, () => App.Plant?.P4 ?? default, () => App.Plant?.P4HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); P4 = new Pump("P4", t4X, tanksY + 22, () => App.Plant?.State.P4_State ?? default, () => App.Plant?.State.P4_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
P5 = new Pump("P5", t5X, tanksY + 22, () => App.Plant?.P5 ?? default, () => App.Plant?.P5HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); P5 = new Pump("P5", t5X, tanksY + 22, () => App.Plant?.State.P5_State ?? default, () => App.Plant?.State.P5_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
CreateOutlet(Tank3, P3); CreateOutlet(Tank3, P3);
CreateOutlet(Tank4, P4); CreateOutlet(Tank4, P4);
CreateOutlet(Tank5, P5); CreateOutlet(Tank5, P5);
@@ -346,7 +346,7 @@ namespace PamhagenSysCtrl.Helpers {
var xt6 = new PipeJoin(t6X, tanksY + 22); var xt6 = new PipeJoin(t6X, tanksY + 22);
var xt7 = new PipeJoin(t7X, tanksY + 22); var xt7 = new PipeJoin(t7X, tanksY + 22);
var xt8 = new PipeJoin(t8X, tanksY + 22); var xt8 = new PipeJoin(t8X, tanksY + 22);
P6 = new Pump("P6", t6X, tanksY + 30, () => App.Plant?.P6 ?? default, () => App.Plant?.P6HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); P6 = new Pump("P6", t6X, tanksY + 30, () => App.Plant?.State.P6_State ?? default, () => App.Plant?.State.P6_HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
CreateOutlet(Tank6, xt6); CreateOutlet(Tank6, xt6);
CreateOutlet(Tank7, xt7); CreateOutlet(Tank7, xt7);
CreateOutlet(Tank8, xt8); CreateOutlet(Tank8, xt8);
@@ -404,8 +404,8 @@ namespace PamhagenSysCtrl.Helpers {
CreatePipe(xp5, xp6); CreatePipe(xp5, xp6);
CreatePipe(xp7, xp8); CreatePipe(xp7, xp8);
var zv1 = new ExternalValve("ZV1", pr1cX, prY - 8, 0, () => App.Plant?.Press1HasClearance ?? false); var zv1 = new ExternalValve("ZV1", pr1cX, prY - 8, 0, () => App.Plant?.State.Press1_HasClearance ?? false);
var zv2 = new ExternalValve("ZV2", pr2cX, prY - 8, 2, () => App.Plant?.Press2HasClearance ?? false); var zv2 = new ExternalValve("ZV2", pr2cX, prY - 8, 2, () => App.Plant?.State.Press2_HasClearance ?? false);
CreatePipe(xp6, zv1, true); CreatePipe(xp6, zv1, true);
CreatePipe(xp8, zv2, true); CreatePipe(xp8, zv2, true);
CreateInlet(zv1, Press1, true); CreateInlet(zv1, Press1, true);
@@ -413,11 +413,11 @@ namespace PamhagenSysCtrl.Helpers {
} }
protected ControlledValve CreateValve(int n, double x, double y, int o) { protected ControlledValve CreateValve(int n, double x, double y, int o) {
return new(n, x, y, o, () => App.Plant?.IsValveOpen(n) ?? false, (v) => App.Plant?.ManualControlMode ?? false ? App.Plant.WantValveOpen(n) : SelectedPaths.Any(p => p.Hops.Any(h => h.Node == v))); return new(n, x, y, o, () => App.Plant?.State.Valve_IsOpen(n) ?? false, (v) => App.Plant?.ManualControlMode ?? false ? App.Plant.State.Valve_WantOpen(n) : SelectedPaths.Any(p => p.Hops.Any(h => h.Node == v)));
} }
protected static Tank CreateTank(int n, double x, double y, int capacity) { protected static Tank CreateTank(int n, double x, double y, int capacity) {
return new($"Tank {n}", x, y, capacity, () => App.Plant?.TankFillLevels[n - 1] ?? FillState.Unknown); return new($"Tank {n}", x, y, capacity, () => App.Plant?.State.Tanks_FillLevel[n - 1] ?? FillState.Unknown);
} }
private int PathCost(Path p) { private int PathCost(Path p) {
+74 -576
View File
@@ -1,4 +1,5 @@
using PamhagenSysCtrl.Helpers.Pipeline; using PamhagenSysCtrl.Helpers.Pipeline;
using PamhagenSysCtrl.Helpers.Plc;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
@@ -34,73 +35,17 @@ namespace PamhagenSysCtrl.Helpers {
protected bool IsRunning = true; protected bool IsRunning = true;
protected Thread? BackgroundThread; protected Thread? BackgroundThread;
public bool ManualControlMode { get; set; }
public bool OverridePathClearances { get; set; }
public bool OverrideDryRunClearances { get; set; }
public event EventHandler<PlantEventArgs>? Update; public event EventHandler<PlantEventArgs>? Update;
protected bool ActuatorsChanged = false;
protected PamhagenPlc.ActuatorStates Actuators;
protected PamhagenPlc.SensorStates Sensors = new(default, default, default, default, default, default, default, [
FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown
], default);
public string? PlcPortName => Plc?.PortName; public string? PlcPortName => Plc?.PortName;
public T1.Status? LastPlcStatus => Plc?.LastPlcStatus; public T1.Status? LastPlcStatus => Plc?.LastStatus;
public T1Error? LastPlcError => Plc?.LastPlcError; public T1Error? LastPlcError => Plc?.LastError;
public long? LastRttNs { get; private set; } public long? LastRttNs { get; private set; }
public bool IsValveOpen(int n) => !IsValveClosed(n); public PamhagenState State => Plc?.State ?? default; // FIXME
public bool IsValveClosed(int n) => Sensors.GetDS(n); public bool ManualControlMode { get => Plc?.ManualControlMode ?? false; set => Plc?.ManualControlMode = value; }
public bool WantValveClosed(int n) => !WantValveOpen(n); public bool OverridePathClearances { get => Plc?.OverridePathClearances ?? false; set => Plc?.OverridePathClearances = value; }
public bool WantValveOpen(int n) => Actuators.GetV(n); public bool OverrideDryRunClearances { get => Plc?.OverrideDryRunClearances ?? false; set => Plc?.OverrideDryRunClearances = value; }
public bool AreValvesOpen(params int[] ns) => ns.All(IsValveOpen) && ns.All(WantValveOpen);
public bool AreValvesClosed(params int[] ns) => ns.All(IsValveClosed) && ns.All(WantValveClosed);
public int TroughSelector => Sensors.TroughSelector;
public bool IsMW1Selected => Sensors.TroughSelector == 1;
public bool IsMW2Selected => Sensors.TroughSelector == 2;
public FillState FillLevelMW1 => Sensors.FillingLevelMW1;
public FillState FillLevelMW2 => Sensors.FillingLevelMW2;
public bool Press1HasClearance => Sensors.ClearancePress1;
public bool Press2HasClearance => Sensors.ClearancePress2;
public FillState FillLevelT1 => Sensors.FillingLevelTanks[0];
public FillState FillLevelT2 => Sensors.FillingLevelTanks[1];
public FillState FillLevelT3 => Sensors.FillingLevelTanks[2];
public FillState FillLevelT4 => Sensors.FillingLevelTanks[3];
public FillState FillLevelT5 => Sensors.FillingLevelTanks[4];
public FillState FillLevelT6 => Sensors.FillingLevelTanks[5];
public FillState FillLevelT7 => Sensors.FillingLevelTanks[6];
public FillState FillLevelT8 => Sensors.FillingLevelTanks[7];
public FillState FillLevelT9 => Sensors.FillingLevelTanks[8];
public FillState[] TankFillLevels => Sensors.FillingLevelTanks;
public double GradationOe => Sensors.GradationOe;
public MotorState PresseQuerSchnecke => Sensors.PresseQuerSchnecke;
public bool IsPresseQuerSchneckeActive => PresseQuerSchnecke == MotorState.Forward;
public bool WantMW1Selected => Actuators.GetV(58);
public bool WantMW2Selected => !Actuators.GetV(58);
public bool IsTroughAugerActive => Actuators.TroughAuger;
public bool TroughAugerHasClearance => IsReblerActive && !(IsMW1Selected && FillLevelMW1 == FillState.Full) && !(IsMW2Selected && FillLevelMW2 == FillState.Full);
public bool IsReblerActive => Actuators.Rebler;
public bool IsStirrerMW1Active => Actuators.StirrerMW1;
public bool IsStirrerMW2Active => Actuators.StirrerMW2;
public bool IsAuger1Active => Actuators.Auger1;
public bool IsAuger2Active => Actuators.Auger2;
public bool IsAuger3Active => Actuators.Auger3;
public bool IsWasteDisposalActive => IsAuger1Active || IsAuger2Active || IsAuger3Active;
public bool IsGradationPumpActive => Actuators.GradationPump;
public bool IsMP1Active => Actuators.MP1 == MotorState.Forward || Actuators.MP1 == MotorState.Backward;
public bool IsMP2Active => Actuators.MP2 == MotorState.Forward || Actuators.MP2 == MotorState.Backward;
public bool IsP12Active => Actuators.P12 == MotorState.Forward;
public bool IsP3Active => Actuators.P3 == MotorState.Forward;
public bool IsP4Active => Actuators.P4 == MotorState.Forward;
public bool IsP5Active => Actuators.P5 == MotorState.Forward;
public bool IsP6Active => Actuators.P6 == MotorState.Forward;
public PamhagenPlant(string portName) { public PamhagenPlant(string portName) {
try { try {
@@ -120,7 +65,6 @@ namespace PamhagenSysCtrl.Helpers {
Keyboard.SetBacklight(Color.FromRgb(4, 4, 4)); Keyboard.SetBacklight(Color.FromRgb(4, 4, 4));
} catch { } } catch { }
Update += OnUpdate;
Update += UpdateKeyboardBacklights; Update += UpdateKeyboardBacklights;
} }
@@ -128,56 +72,17 @@ namespace PamhagenSysCtrl.Helpers {
App.MainDispatcher?.BeginInvoke(() => Update?.Invoke(this, evt)); App.MainDispatcher?.BeginInvoke(() => Update?.Invoke(this, evt));
} }
protected static void OnUpdate(object? sender, PlantEventArgs evt) {
if (sender is not PamhagenPlant p) return;
if (!p.ManualControlMode) {
if (p.IsPresseQuerSchneckeActive && !p.IsAuger2Active) p.StartAuger2();
if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1();
if (p.IsAuger1Active && !p.IsAuger2Active) p.StartAuger2();
if (p.IsAuger2Active && !p.IsAuger3Active) p.StartAuger3();
if (p.IsTroughAugerActive && !p.TroughAugerHasClearance)
p.StopTroughAuger();
if (!p.IsPresseQuerSchneckeActive && !p.IsAuger1Active) {
p.StopAuger2();
p.StopAuger3();
}
}
if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1();
if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2();
if (!p.ManualControlMode) {
if (p.MP1 == MotorState.Forward && p.FillLevelMW1 >= FillState.Half && !p.IsStirrerMW1Active) {
p.StartStirrerMW1();
} else if (p.IsStirrerMW1Active && (!p.IsMP1Active || p.FillLevelMW1 < FillState.Half)) {
p.StopStirrerMW1();
}
if (p.MP2 == MotorState.Forward && p.FillLevelMW2 >= FillState.Half && !p.IsStirrerMW2Active) {
p.StartStirrerMW2();
} else if (p.IsStirrerMW2Active && (!p.IsMP2Active || p.FillLevelMW2 < FillState.Half)) {
p.StopStirrerMW2();
}
}
if (p.IsP12Active && !p.P12HasClearance) p.StopP12();
if (p.IsP3Active && !p.P3HasClearance) p.StopP3();
if (p.IsP4Active && !p.P4HasClearance) p.StopP4();
if (p.IsP5Active && !p.P5HasClearance) p.StopP5();
if (p.IsP6Active && !p.P6HasClearance) p.StopP6();
}
protected void UpdateKeyboardBacklights(object? sender, PlantEventArgs evt) { protected void UpdateKeyboardBacklights(object? sender, PlantEventArgs evt) {
if (sender is not PamhagenPlant plant || plant.Keyboard is not Xbe24Keyboard k) return; if (sender is not PamhagenPlant plant || plant.Keyboard is not Xbe24Keyboard k) return;
k.SetBacklight((int)Xbe24Key.START_REBLER, plant.IsReblerActive ? Color.FromRgb(0, 255, 0) : plant.IsAuger1Active ? Color.FromRgb(255, 255, 0) : plant.IsAuger2Active || plant.IsAuger3Active ? Color.FromRgb(32, 32, 4) : Color.FromRgb(4, 32, 4)); k.SetBacklight((int)Xbe24Key.START_REBLER, State.Rebler_IsActive ? Color.FromRgb(0, 255, 0) : State.Auger1_IsActive ? Color.FromRgb(255, 255, 0) : State.WasteDisposal_IsActive ? Color.FromRgb(32, 32, 4) : Color.FromRgb(4, 32, 4));
k.SetBacklight((int)Xbe24Key.STOP_REBLER, !plant.IsReblerActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4)); k.SetBacklight((int)Xbe24Key.STOP_REBLER, !State.Rebler_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight((int)Xbe24Key.START_TROUGH_AUGER, !plant.TroughAugerHasClearance ? k.IsKeyPressed((int)Xbe24Key.START_TROUGH_AUGER) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : plant.IsTroughAugerActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4)); k.SetBacklight((int)Xbe24Key.START_TROUGH_AUGER, !State.TroughAuger_HasClearance ? k.IsKeyPressed((int)Xbe24Key.START_TROUGH_AUGER) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : State.TroughAuger_IsActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4));
k.SetBacklight((int)Xbe24Key.STOP_TROUGH_AUGER, !plant.IsTroughAugerActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4)); k.SetBacklight((int)Xbe24Key.STOP_TROUGH_AUGER, !State.TroughAuger_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight((int)Xbe24Key.SELECT_MW2, plant.WantMW2Selected || plant.IsMW2Selected ? Color.FromRgb(0, 0, 255) : Color.FromRgb(4, 4, 16), plant.WantMW2Selected && !plant.IsMW2Selected); k.SetBacklight((int)Xbe24Key.SELECT_MW2, State.MW2_WantSelected || State.MW2_IsSelected ? Color.FromRgb(0, 0, 255) : Color.FromRgb(4, 4, 16), State.MW2_WantSelected && !State.MW2_IsSelected);
k.SetBacklight((int)Xbe24Key.SELECT_MW1, plant.WantMW1Selected || plant.IsMW1Selected ? Color.FromRgb(0, 0, 255) : Color.FromRgb(4, 4, 16), plant.WantMW1Selected && !plant.IsMW1Selected); k.SetBacklight((int)Xbe24Key.SELECT_MW1, State.MW1_WantSelected || State.MW1_IsSelected ? Color.FromRgb(0, 0, 255) : Color.FromRgb(4, 4, 16), State.MW1_WantSelected && !State.MW1_IsSelected);
var buttons = new Dictionary<Xbe24Key, (ISource Source, Pump Pump, ISink Sink)> { var buttons = new Dictionary<Xbe24Key, (ISource Source, Pump Pump, ISink Sink)> {
[Xbe24Key.FAST_SELECT_MW1_1] = (Graph.MW1, Graph.MP1, Graph.Press1), [Xbe24Key.FAST_SELECT_MW1_1] = (Graph.MW1, Graph.MP1, Graph.Press1),
@@ -213,24 +118,23 @@ namespace PamhagenSysCtrl.Helpers {
} }
} }
if (!plant.MP2HasPathClearance && plant.MP2HasDryRunClearance && preparingMP2) { if (!plant.State.MP2_HasPathClearance && plant.State.MP2_HasDryRunClearance && preparingMP2) {
k.SetBacklight((int)Xbe24Key.START_MP2, Color.FromRgb(4, 32, 4), true); k.SetBacklight((int)Xbe24Key.START_MP2, Color.FromRgb(4, 32, 4), true);
} else { } else {
k.SetBacklight((int)Xbe24Key.START_MP2, !plant.MP2HasClearance ? k.IsKeyPressed((int)Xbe24Key.START_MP2) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : plant.IsMP2Active ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4)); k.SetBacklight((int)Xbe24Key.START_MP2, !State.MP2_HasClearance ? k.IsKeyPressed((int)Xbe24Key.START_MP2) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : State.MP2_IsActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4));
} }
if (!plant.MP1HasPathClearance && plant.MP1HasDryRunClearance && preparingMP1) { if (!plant.State.MP1_HasPathClearance && plant.State.MP1_HasDryRunClearance && preparingMP1) {
k.SetBacklight((int)Xbe24Key.START_MP1, Color.FromRgb(4, 32, 4), true); k.SetBacklight((int)Xbe24Key.START_MP1, Color.FromRgb(4, 32, 4), true);
} else { } else {
k.SetBacklight((int)Xbe24Key.START_MP1, !plant.MP1HasClearance ? k.IsKeyPressed((int)Xbe24Key.START_MP1) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : plant.IsMP1Active ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4)); k.SetBacklight((int)Xbe24Key.START_MP1, !State.MP1_HasClearance ? k.IsKeyPressed((int)Xbe24Key.START_MP1) ? Color.FromRgb(255, 32, 0) : Color.FromRgb(32, 4, 4) : State.MP1_IsActive ? Color.FromRgb(0, 255, 0) : Color.FromRgb(4, 32, 4));
} }
k.SetBacklight((int)Xbe24Key.STOP_MP2, highlightOffMP2 ? Color.FromRgb(255, 32, 0) : !plant.IsMP2Active ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4)); k.SetBacklight((int)Xbe24Key.STOP_MP2, highlightOffMP2 ? Color.FromRgb(255, 32, 0) : !State.MP2_IsActive ? Color.FromRgb(255, 0, 0) : Color.FromRgb(32, 4, 4));
k.SetBacklight((int)Xbe24Key.STOP_MP1, highlightOffMP1 ? Color.FromRgb(255, 32, 0) : !plant.IsMP1Active ? 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() { public async Task StartThread() {
if (Plc == null) throw new Exception(); if (Plc == null) throw new Exception();
await Plc.TestConnection(); await Plc.Initialize();
Actuators = await Plc.ReadOutputs();
BackgroundThread = new Thread(new ParameterizedThreadStart(BackgroundLoop)); BackgroundThread = new Thread(new ParameterizedThreadStart(BackgroundLoop));
BackgroundThread.Start(); BackgroundThread.Start();
} }
@@ -247,11 +151,7 @@ namespace PamhagenSysCtrl.Helpers {
while (IsRunning && Plc != null) { while (IsRunning && Plc != null) {
var start = DateTime.Now; var start = DateTime.Now;
try { try {
if (ActuatorsChanged) { await Plc.Update();
await Plc.WriteOutputs(Actuators);
ActuatorsChanged = false;
}
Sensors = await Plc.ReadInputs();
LastRttNs = (long)(DateTime.Now - start).TotalNanoseconds; LastRttNs = (long)(DateTime.Now - start).TotalNanoseconds;
RaiseUpdateEvent(new()); RaiseUpdateEvent(new());
} catch (Exception exc) { } catch (Exception exc) {
@@ -270,7 +170,7 @@ namespace PamhagenSysCtrl.Helpers {
} }
try { try {
if (Plc != null) if (Plc != null)
await Plc.WriteOutputs(new() { Valves = Actuators.Valves }); 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;
@@ -283,7 +183,7 @@ namespace PamhagenSysCtrl.Helpers {
var remove = Graph.SelectedPaths.ToList(); var remove = Graph.SelectedPaths.ToList();
foreach (var p in remove) Graph.RemovePath(p); foreach (var p in remove) Graph.RemovePath(p);
for (int i = 1; i <= 57; i++) { for (int i = 1; i <= 57; i++) {
App.Plant?.CloseV(i); App.Plant?.Plc?.CloseV(i);
} }
foreach (var p in add) { foreach (var p in add) {
if (p.Hops.Any(h => h.Node is ControlledValve v && v.IsLocked)) continue; if (p.Hops.Any(h => h.Node is ControlledValve v && v.IsLocked)) continue;
@@ -298,7 +198,7 @@ namespace PamhagenSysCtrl.Helpers {
foreach (var src in sources) { foreach (var src in sources) {
var paths = new List<Pipeline.Path>(); var paths = new List<Pipeline.Path>();
foreach (var sink in sinks) { foreach (var sink in sinks) {
paths.AddRange(Graph.GetPaths(src, sink, null, (n) => n is not ISink && (n is not ControlledValve v || p.WantValveOpen(v.Nr)))); paths.AddRange(Graph.GetPaths(src, sink, null, (n) => n is not ISink && (n is not ControlledValve v || State.Valve_WantOpen(v.Nr))));
} }
if (paths.Count == 1) if (paths.Count == 1)
yield return paths.First(); yield return paths.First();
@@ -321,35 +221,36 @@ namespace PamhagenSysCtrl.Helpers {
private void Keyboard_KeyDown(object? sender, int keyIndex) { private void Keyboard_KeyDown(object? sender, int keyIndex) {
var key = (Xbe24Key)keyIndex; var key = (Xbe24Key)keyIndex;
App.MainDispatcher?.BeginInvoke(() => { App.MainDispatcher?.BeginInvoke(() => {
if (Plc == null) return;
try { try {
if (key == Xbe24Key.START_REBLER) { if (key == Xbe24Key.START_REBLER) {
StartRebler(); Plc.StartRebler();
} else if (key == Xbe24Key.STOP_REBLER) { } else if (key == Xbe24Key.STOP_REBLER) {
if (IsReblerActive) { if (State.Rebler_IsActive) {
StopRebler(); Plc.StopRebler();
} else { } else {
StopAuger1(); Plc.StopAuger1();
if (!IsPresseQuerSchneckeActive) { if (!State.PressCrossAuger_IsActive) {
StopAuger2(); Plc.StopAuger2();
StopAuger3(); Plc.StopAuger3();
} }
} }
} else if (key == Xbe24Key.START_TROUGH_AUGER) { } else if (key == Xbe24Key.START_TROUGH_AUGER) {
StartTroughAuger(); Plc.StartTroughAuger();
} else if (key == Xbe24Key.STOP_TROUGH_AUGER) { } else if (key == Xbe24Key.STOP_TROUGH_AUGER) {
StopTroughAuger(); Plc.StopTroughAuger();
} else if (key == Xbe24Key.SELECT_MW2) { } else if (key == Xbe24Key.SELECT_MW2) {
SelectMW2(); Plc.SelectMW2();
} else if (key == Xbe24Key.SELECT_MW1) { } else if (key == Xbe24Key.SELECT_MW1) {
SelectMW1(); Plc.SelectMW1();
} else if (key == Xbe24Key.START_MP2) { } else if (key == Xbe24Key.START_MP2) {
StartMP2Forward(); Plc.StartMP2Forward();
} else if (key == Xbe24Key.STOP_MP2) { } else if (key == Xbe24Key.STOP_MP2) {
StopMP2(); Plc.StopMP2();
} else if (key == Xbe24Key.START_MP1) { } else if (key == Xbe24Key.START_MP1) {
StartMP1Forward(); Plc.StartMP1Forward();
} else if (key == Xbe24Key.STOP_MP1) { } else if (key == Xbe24Key.STOP_MP1) {
StopMP1(); Plc.StopMP1();
} else if (key == Xbe24Key.FAST_SELECT_MW1_1) { } else if (key == Xbe24Key.FAST_SELECT_MW1_1) {
FastSelect(Graph.MW1, Graph.Press1); FastSelect(Graph.MW1, Graph.Press1);
} else if (key == Xbe24Key.FAST_SELECT_MW1_2) { } else if (key == Xbe24Key.FAST_SELECT_MW1_2) {
@@ -387,442 +288,39 @@ namespace PamhagenSysCtrl.Helpers {
RaiseUpdateEvent(new()); RaiseUpdateEvent(new());
} }
protected bool HasWTClearanceAA => public void OpenV(int n) => Plc?.OpenV(n);
(AreValvesOpen(12) && AreValvesClosed(15, 16, 20)) || // bypass public void CloseV(int n) => Plc?.CloseV(n);
(AreValvesOpen(15, 18, 16) && AreValvesClosed(11, 12, 14, 17, 19, 20)) || // WT1 public void SelectMW1() => Plc?.SelectMW1();
(AreValvesOpen(15, 17, 20) && AreValvesClosed(11, 12, 18, 19, 21)) || // WT2 public void SelectMW2() => Plc?.SelectMW2();
(AreValvesOpen(15, 18, 19, 20) && AreValvesClosed(11, 12, 14, 16, 17, 21)) || // WT1+WT2 public void StartTroughAuger() => Plc?.StartTroughAuger();
false; public void StopTroughAuger() => Plc?.StopTroughAuger();
protected bool HasWTClearanceAB => public void StartRebler() => Plc?.StartRebler();
(AreValvesOpen(15, 18, 14) && AreValvesClosed(11, 12, 13, 16, 17, 19, 21)) || // WT1 public void StopRebler() => Plc?.StopRebler();
(AreValvesOpen(15, 17, 21) && AreValvesClosed(11, 12, 13, 18, 19, 20)) || // WT2 public void StartStirrerMW1() => Plc?.StartStirrerMW1();
(AreValvesOpen(15, 18, 19, 21) && AreValvesClosed(11, 12, 13, 14, 16, 17, 20)) || // WT1+WT2 public void StopStirrerMW1() => Plc?.StopStirrerMW1();
false; public void StartStirrerMW2() => Plc?.StartStirrerMW2();
protected bool HasWTClearanceBA => public void StopStirrerMW2() => Plc?.StopStirrerMW2();
(AreValvesOpen(11, 18, 16) && AreValvesClosed(15, 12, 13, 14, 17, 19, 20)) || // WT1 public void StartAuger1() => Plc?.StartAuger1();
(AreValvesOpen(11, 17, 20) && AreValvesClosed(15, 12, 13, 18, 19, 21)) || // WT2 public void StopAuger1() => Plc?.StopAuger1();
(AreValvesOpen(11, 18, 19, 20) && AreValvesClosed(15, 12, 13, 14, 16, 17, 21)) || // WT1+WT2 public void StartAuger2() => Plc?.StartAuger2();
false; public void StopAuger2() => Plc?.StopAuger2();
protected bool HasWTClearanceBB => public void StartAuger3() => Plc?.StartAuger3();
(AreValvesOpen(13) && AreValvesClosed(11, 14, 21)) || // bypass public void StopAuger3() => Plc?.StopAuger3();
(AreValvesOpen(11, 18, 14) && AreValvesClosed(15, 13, 16, 17, 19, 21)) || // WT1 public void StartMP1Forward() => Plc?.StartMP1Forward();
(AreValvesOpen(11, 17, 21) && AreValvesClosed(15, 13, 18, 19, 20)) || // WT2 public void StartMP1Backward() => Plc?.StartMP1Backward();
(AreValvesOpen(11, 18, 19, 21) && AreValvesClosed(15, 13, 14, 16, 17, 20)) || // WT1+WT2 public void StopMP1() => Plc?.StopMP1();
false; public void StartMP2Forward() => Plc?.StartMP2Forward();
public void StartMP2Backward() => Plc?.StartMP2Backward();
protected bool HasT1ClearanceA => AreValvesOpen(22) && AreValvesClosed(24, 26, 28); public void StopMP2() => Plc?.StopMP2();
protected bool HasT1ClearanceB => AreValvesOpen(23) && AreValvesClosed(25, 27, 29); public void EnableP12() => Plc?.EnableP12();
protected bool HasT2ClearanceA => AreValvesOpen(24) && AreValvesClosed(22, 26, 28); public void DisableP12() => Plc?.DisableP12();
protected bool HasT2ClearanceB => AreValvesOpen(25) && AreValvesClosed(23, 27, 29); public void EnableP3() => Plc?.EnableP3();
protected bool HasT3ClearanceA => AreValvesOpen(26) && AreValvesClosed(22, 24, 28); public void DisableP3() => Plc?.DisableP3();
protected bool HasT3ClearanceB => AreValvesOpen(27) && AreValvesClosed(23, 25, 29); public void EnableP4() => Plc?.EnableP4();
protected bool HasT4ClearanceA => AreValvesOpen(28, 30) && AreValvesClosed(22, 24, 26, 32, 34); public void DisableP4() => Plc?.DisableP4();
protected bool HasT4ClearanceB => AreValvesOpen(29, 31) && AreValvesClosed(23, 25, 27, 33, 35); public void EnableP5() => Plc?.EnableP5();
protected bool HasT5ClearanceA => AreValvesOpen(28, 32) && AreValvesClosed(22, 24, 26, 30, 34); public void DisableP5() => Plc?.DisableP5();
protected bool HasT5ClearanceB => AreValvesOpen(29, 33) && AreValvesClosed(23, 25, 27, 31, 35); public void EnableP6() => Plc?.EnableP6();
protected bool HasT6ClearanceA => AreValvesOpen(28, 34, 37) && AreValvesClosed(22, 24, 26, 30, 32, 39, 41, 43); public void DisableP6() => Plc?.DisableP6();
protected bool HasT6ClearanceB => AreValvesOpen(29, 35, 36) && AreValvesClosed(23, 25, 27, 31, 33, 38, 40, 42);
protected bool HasT7ClearanceA => AreValvesOpen(28, 34, 39) && AreValvesClosed(22, 24, 26, 30, 32, 37, 41, 43);
protected bool HasT7ClearanceB => AreValvesOpen(29, 35, 38) && AreValvesClosed(23, 25, 27, 31, 33, 36, 40, 42);
protected bool HasT8ClearanceA => AreValvesOpen(28, 34, 41) && AreValvesClosed(22, 24, 26, 30, 32, 37, 39, 43);
protected bool HasT8ClearanceB => AreValvesOpen(29, 35, 40) && AreValvesClosed(23, 25, 27, 31, 33, 36, 38, 42);
protected bool HasT9ClearanceA => AreValvesOpen(28, 34, 43) && AreValvesClosed(22, 24, 26, 30, 32, 37, 39, 41);
protected bool HasT9ClearanceB => AreValvesOpen(29, 35, 42) && AreValvesClosed(23, 25, 27, 31, 33, 36, 38, 40);
protected bool HasClearanceTank1(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT1ClearanceA) || (HasWTClearanceAB && HasT1ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT1ClearanceA) || (HasWTClearanceBB && HasT1ClearanceB)));
protected bool HasClearanceTank2(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT2ClearanceA) || (HasWTClearanceAB && HasT2ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT2ClearanceA) || (HasWTClearanceBB && HasT2ClearanceB)));
protected bool HasClearanceTank3(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT3ClearanceA) || (HasWTClearanceAB && HasT3ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT3ClearanceA) || (HasWTClearanceBB && HasT3ClearanceB)));
protected bool HasClearanceTank4(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT4ClearanceA) || (HasWTClearanceAB && HasT4ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT4ClearanceA) || (HasWTClearanceBB && HasT4ClearanceB)));
protected bool HasClearanceTank5(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT5ClearanceA) || (HasWTClearanceAB && HasT5ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT5ClearanceA) || (HasWTClearanceBB && HasT5ClearanceB)));
protected bool HasClearanceTank6(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT6ClearanceA) || (HasWTClearanceAB && HasT6ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT6ClearanceA) || (HasWTClearanceBB && HasT6ClearanceB)));
protected bool HasClearanceTank7(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT7ClearanceA) || (HasWTClearanceAB && HasT7ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT7ClearanceA) || (HasWTClearanceBB && HasT7ClearanceB)));
protected bool HasClearanceTank8(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT8ClearanceA) || (HasWTClearanceAB && HasT8ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT8ClearanceA) || (HasWTClearanceBB && HasT8ClearanceB)));
protected bool HasClearanceTank9(bool a, bool b) =>
(a && ((HasWTClearanceAA && HasT9ClearanceA) || (HasWTClearanceAB && HasT9ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT9ClearanceA) || (HasWTClearanceBB && HasT9ClearanceB)));
public bool MP1HasClearance => MP1HasDryRunClearance && MP1HasPathClearance;
public bool MP1HasDryRunClearance => (OverrideDryRunClearances || FillLevelMW1 != FillState.Empty);
public bool MP1HasPathClearance => (
OverridePathClearances ||
(MP1HasClearancePress1 && Press1HasClearance) ||
(MP1HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
(HasClearanceTank4(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT4 != FillState.Full) ||
(HasClearanceTank5(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT5 != FillState.Full) ||
(HasClearanceTank6(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT6 != FillState.Full) ||
(HasClearanceTank7(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT7 != FillState.Full) ||
(HasClearanceTank8(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT8 != FillState.Full) ||
(HasClearanceTank9(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT9 != FillState.Full) ||
false);
protected bool MP1HasClearancePress1 =>
(AreValvesOpen(1, 6, 51) && AreValvesClosed(3, 4, 5, 50, 52, 53, 55)) ||
(AreValvesOpen(4, 8, 52) && AreValvesClosed(1, 2, 7, 50, 51, 53, 56));
protected bool MP1HasClearancePress2 =>
(AreValvesOpen(1, 6, 55) && AreValvesClosed(3, 4, 5, 51, 54, 56, 57)) ||
(AreValvesOpen(4, 8, 56) && AreValvesClosed(1, 2, 7, 52, 54, 55, 57));
protected bool MP1HasClearanceTanksA => AreValvesOpen(1, 5) && AreValvesClosed(3, 4, 6);
protected bool MP1HasClearanceTanksB => AreValvesOpen(4, 7, 9) && AreValvesClosed(1, 2, 8, 10);
public MotorState MP1 {
get => Actuators.MP1;
set => Actuators.MP1 = (value != MotorState.Halt && value != MotorState.Forward && value != MotorState.Backward) ? throw new ArgumentException("Invalid state for MP1") : value;
}
public bool MP2HasClearance => MP2HasDryRunClearance && MP2HasPathClearance;
public bool MP2HasDryRunClearance => (OverrideDryRunClearances || FillLevelMW2 != FillState.Empty);
public bool MP2HasPathClearance => (
OverridePathClearances ||
(MP2HasClearancePress1 && Press1HasClearance) ||
(MP2HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
(HasClearanceTank4(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT4 != FillState.Full) ||
(HasClearanceTank5(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT5 != FillState.Full) ||
(HasClearanceTank6(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT6 != FillState.Full) ||
(HasClearanceTank7(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT7 != FillState.Full) ||
(HasClearanceTank8(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT8 != FillState.Full) ||
(HasClearanceTank9(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT9 != FillState.Full) ||
false);
protected bool MP2HasClearancePress1 =>
(AreValvesOpen(2, 8, 52) && AreValvesClosed(3, 4, 7, 50, 51, 53, 56)) ||
(AreValvesOpen(3, 6, 51) && AreValvesClosed(1, 2, 5, 50, 52, 53, 55));
protected bool MP2HasClearancePress2 =>
(AreValvesOpen(2, 8, 56) && AreValvesClosed(3, 4, 7, 52, 54, 55, 57)) ||
(AreValvesOpen(3, 6, 55) && AreValvesClosed(2, 1, 5, 51, 54, 56, 57));
protected bool MP2HasClearanceTanksA => AreValvesOpen(3, 5) && AreValvesClosed(1, 2, 6);
protected bool MP2HasClearanceTanksB => AreValvesOpen(2, 7, 9) && AreValvesClosed(3, 4, 8, 10);
public MotorState MP2 {
get => Actuators.MP2;
set => Actuators.MP2 = (value != MotorState.Halt && value != MotorState.Forward && value != MotorState.Backward) ? throw new ArgumentException("Invalid state for MP2") : value;
}
public bool P12HasClearance => (OverrideDryRunClearances || FillLevelT1 != FillState.Empty || FillLevelT2 != FillState.Empty) && (
OverridePathClearances ||
(P12HasClearancePress1 && Press1HasClearance) ||
(P12HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(false, P12HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(false, P12HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(false, P12HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
(HasClearanceTank4(false, P12HasClearanceTanksB) && FillLevelT4 != FillState.Full) ||
(HasClearanceTank5(false, P12HasClearanceTanksB) && FillLevelT5 != FillState.Full) ||
(HasClearanceTank6(false, P12HasClearanceTanksB) && FillLevelT6 != FillState.Full) ||
(HasClearanceTank7(false, P12HasClearanceTanksB) && FillLevelT7 != FillState.Full) ||
(HasClearanceTank8(false, P12HasClearanceTanksB) && FillLevelT8 != FillState.Full) ||
(HasClearanceTank9(false, P12HasClearanceTanksB) && FillLevelT9 != FillState.Full) ||
false);
protected bool P12HasClearancePress1 => AreValvesOpen(44, 46, 49, 50) && AreValvesClosed(10, 45, 47, 48, 54, 51, 52, 53);
protected bool P12HasClearancePress2 => AreValvesOpen(44, 46, 49, 54) && AreValvesClosed(10, 45, 47, 48, 50, 55, 56, 57);
protected bool P12HasClearanceTanksB => AreValvesOpen(44, 10) && AreValvesClosed(9, 45, 46);
public MotorState P12 {
get => Actuators.P12;
set => Actuators.P12 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P12") : value;
}
public bool P3HasClearance => (OverrideDryRunClearances || FillLevelT3 != FillState.Empty) && (
OverridePathClearances ||
(P3HasClearancePress1 && Press1HasClearance) ||
(P3HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(false, P3HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(false, P3HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(false, P3HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
(HasClearanceTank4(false, P3HasClearanceTanksB) && FillLevelT4 != FillState.Full) ||
(HasClearanceTank5(false, P3HasClearanceTanksB) && FillLevelT5 != FillState.Full) ||
(HasClearanceTank6(false, P3HasClearanceTanksB) && FillLevelT6 != FillState.Full) ||
(HasClearanceTank7(false, P3HasClearanceTanksB) && FillLevelT7 != FillState.Full) ||
(HasClearanceTank8(false, P3HasClearanceTanksB) && FillLevelT8 != FillState.Full) ||
(HasClearanceTank9(false, P3HasClearanceTanksB) && FillLevelT9 != FillState.Full) ||
false);
protected bool P3HasClearancePress1 => AreValvesOpen(45, 46, 49, 50) && AreValvesClosed(10, 44, 47, 48, 51, 52, 53, 54);
protected bool P3HasClearancePress2 => AreValvesOpen(45, 46, 49, 54) && AreValvesClosed(10, 44, 47, 48, 50, 55, 56, 57);
protected bool P3HasClearanceTanksB => AreValvesOpen(45, 10) && AreValvesClosed(9, 44, 46);
public MotorState P3 {
get => Actuators.P3;
set => Actuators.P3 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P3") : value;
}
public bool P4HasClearance => (OverrideDryRunClearances || FillLevelT4 != FillState.Empty) && (
OverridePathClearances ||
(P4HasClearancePress1 && Press1HasClearance) ||
(P4HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(false, P4HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(false, P4HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(false, P4HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
(HasClearanceTank4(false, P4HasClearanceTanksB) && FillLevelT4 != FillState.Full) ||
(HasClearanceTank5(false, P4HasClearanceTanksB) && FillLevelT5 != FillState.Full) ||
(HasClearanceTank6(false, P4HasClearanceTanksB) && FillLevelT6 != FillState.Full) ||
(HasClearanceTank7(false, P4HasClearanceTanksB) && FillLevelT7 != FillState.Full) ||
(HasClearanceTank8(false, P4HasClearanceTanksB) && FillLevelT8 != FillState.Full) ||
(HasClearanceTank9(false, P4HasClearanceTanksB) && FillLevelT9 != FillState.Full) ||
false);
protected bool P4HasClearancePress1 => AreValvesOpen(47, 49, 50) && AreValvesClosed(46, 48, 51, 52, 53, 54);
protected bool P4HasClearancePress2 => AreValvesOpen(47, 49, 54) && AreValvesClosed(46, 48, 50, 55, 56, 57);
protected bool P4HasClearanceTanksB => AreValvesOpen(47, 46, 10) && AreValvesClosed(9, 44, 45, 48, 49);
public MotorState P4 {
get => Actuators.P4;
set => Actuators.P4 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P4") : value;
}
public bool P5HasClearance => (OverrideDryRunClearances || FillLevelT5 != FillState.Empty) && (
OverridePathClearances ||
(P5HasClearancePress1 && Press1HasClearance) ||
(P5HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(false, P5HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(false, P5HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(false, P5HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
(HasClearanceTank4(false, P5HasClearanceTanksB) && FillLevelT4 != FillState.Full) ||
(HasClearanceTank5(false, P5HasClearanceTanksB) && FillLevelT5 != FillState.Full) ||
(HasClearanceTank6(false, P5HasClearanceTanksB) && FillLevelT6 != FillState.Full) ||
(HasClearanceTank7(false, P5HasClearanceTanksB) && FillLevelT7 != FillState.Full) ||
(HasClearanceTank8(false, P5HasClearanceTanksB) && FillLevelT8 != FillState.Full) ||
(HasClearanceTank9(false, P5HasClearanceTanksB) && FillLevelT9 != FillState.Full) ||
false);
protected bool P5HasClearancePress1 => AreValvesOpen(48, 49, 50) && AreValvesClosed(46, 47, 51, 52, 53, 54);
protected bool P5HasClearancePress2 => AreValvesOpen(48, 49, 54) && AreValvesClosed(46, 47, 50, 55, 56, 57);
protected bool P5HasClearanceTanksB => AreValvesOpen(48, 46, 10) && AreValvesClosed(9, 44, 45, 47, 49);
public MotorState P5 {
get => Actuators.P5;
set => Actuators.P5 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P5") : value;
}
public bool P6HasClearance => OverridePathClearances ||
(AreValvesOpen(53) && AreValvesClosed(50, 51, 52, 57) && Press1HasClearance) ||
(AreValvesOpen(57) && AreValvesClosed(53, 54, 55, 56) && Press2HasClearance);
public MotorState P6 {
get => Actuators.P6;
set => Actuators.P6 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P6") : value;
}
public void OpenV(int n) => SetV(n, true);
public void CloseV(int n) => SetV(n, false);
protected void SetV(int n, bool val) {
if (n < 1 || n > 57) throw new ArgumentException("Invalid value for n: 1 <= #V <= 57");
Actuators.SetV(n, val);
ActuatorsChanged = true;
}
public void SelectMW1() {
Actuators.SetV(58, true);
ActuatorsChanged = true;
}
public void SelectMW2() {
Actuators.SetV(58, false);
ActuatorsChanged = true;
}
public void StartTroughAuger() {
if (!ManualControlMode && !TroughAugerHasClearance)
throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe");
Actuators.TroughAuger = true;
ActuatorsChanged = true;
}
public void StopTroughAuger() {
Actuators.TroughAuger = false;
ActuatorsChanged = true;
}
public void StartRebler() {
Actuators.Rebler = true;
if (!ManualControlMode) StartAuger1();
ActuatorsChanged = true;
}
public void StopRebler() {
if (!ManualControlMode) StopTroughAuger();
Actuators.Rebler = false;
ActuatorsChanged = true;
}
public void StartStirrerMW1() {
Actuators.StirrerMW1 = true;
ActuatorsChanged = true;
}
public void StopStirrerMW1() {
Actuators.StirrerMW1 = false;
ActuatorsChanged = true;
}
public void StartStirrerMW2() {
Actuators.StirrerMW2 = true;
ActuatorsChanged = true;
}
public void StopStirrerMW2() {
Actuators.StirrerMW2 = false;
ActuatorsChanged = true;
}
public void StartAuger1() {
Actuators.Auger1 = true;
if (!ManualControlMode) StartAuger2();
ActuatorsChanged = true;
}
public void StopAuger1() {
if (!ManualControlMode && IsReblerActive) throw new NoClearanceException("Rebler aktiv");
Actuators.Auger1 = false;
ActuatorsChanged = true;
}
public void StartAuger2() {
Actuators.Auger2 = true;
if (!ManualControlMode) StartAuger3();
ActuatorsChanged = true;
}
public void StopAuger2() {
if (!ManualControlMode && IsPresseQuerSchneckeActive) throw new NoClearanceException("Presse-Querschnecke aktiv");
if (!ManualControlMode && IsAuger1Active) throw new NoClearanceException("Förderschnecke 1 aktiv");
Actuators.Auger2 = false;
ActuatorsChanged = true;
}
public void StartAuger3() {
Actuators.Auger3 = true;
ActuatorsChanged = true;
}
public void StopAuger3() {
if (!ManualControlMode && IsAuger2Active) throw new NoClearanceException("Förderschnecke 2 aktiv");
Actuators.Auger3 = false;
ActuatorsChanged = true;
}
public void StartGradationPump() {
Actuators.GradationPump = true;
ActuatorsChanged = true;
}
public void StopGradationPump() {
Actuators.GradationPump = false;
ActuatorsChanged = true;
}
public void StartMP1Forward() {
if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe");
if (Actuators.MP1 == MotorState.Backward) throw new NoClearanceException("MP1 läuft bereits (zurück)");
Actuators.MP1 = MotorState.Forward;
if (FillLevelMW1 >= FillState.Half) StartStirrerMW1();
ActuatorsChanged = true;
}
public void StartMP1Backward() {
if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe");
if (Actuators.MP1 == MotorState.Forward) throw new NoClearanceException("MP1 läuft bereits (vor)");
Actuators.MP1 = MotorState.Backward;
ActuatorsChanged = true;
}
public void StopMP1() {
Actuators.MP1 = MotorState.Halt;
if (!ManualControlMode) StopStirrerMW1();
ActuatorsChanged = true;
}
public void StartMP2Forward() {
if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe");
if (Actuators.MP2 == MotorState.Backward) throw new NoClearanceException("MP2 läuft bereits (zurück)");
Actuators.MP2 = MotorState.Forward;
if (FillLevelMW2 >= FillState.Half) StartStirrerMW2();
ActuatorsChanged = true;
}
public void StartMP2Backward() {
if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe");
if (Actuators.MP2 == MotorState.Forward) throw new NoClearanceException("MP2 läuft bereits (vor)");
Actuators.MP2 = MotorState.Backward;
ActuatorsChanged = true;
}
public void StopMP2() {
Actuators.MP2 = MotorState.Halt;
if (!ManualControlMode) StopStirrerMW1();
ActuatorsChanged = true;
}
public void StartP12() {
if (!P12HasClearance) throw new NoClearanceException("P1/2 hat keine Freigabe");
Actuators.P12 = MotorState.Forward;
ActuatorsChanged = true;
}
public void StopP12() {
Actuators.P12 = MotorState.Halt;
ActuatorsChanged = true;
}
public void StartP3() {
if (!P3HasClearance) throw new NoClearanceException("P3 hat keine Freigabe");
Actuators.P3 = MotorState.Forward;
ActuatorsChanged = true;
}
public void StopP3() {
Actuators.P3 = MotorState.Halt;
ActuatorsChanged = true;
}
public void StartP4() {
if (!P4HasClearance) throw new NoClearanceException("P4 hat keine Freigabe");
Actuators.P4 = MotorState.Forward;
ActuatorsChanged = true;
}
public void StopP4() {
Actuators.P4 = MotorState.Halt;
ActuatorsChanged = true;
}
public void StartP5() {
if (!P5HasClearance) throw new NoClearanceException("P5 hat keine Freigabe");
Actuators.P5 = MotorState.Forward;
ActuatorsChanged = true;
}
public void StopP5() {
Actuators.P5 = MotorState.Halt;
ActuatorsChanged = true;
}
public void StartP6() {
if (!P6HasClearance) throw new NoClearanceException("P6 hat keine Freigabe");
Actuators.P6 = MotorState.Forward;
ActuatorsChanged = true;
}
public void StopP6() {
Actuators.P6 = MotorState.Halt;
ActuatorsChanged = true;
}
} }
} }
@@ -1,18 +1,18 @@
using System.IO.Ports; using System.IO.Ports;
namespace PamhagenSysCtrl.Helpers { namespace PamhagenSysCtrl.Helpers.Plc {
public class PamhagenPlc : IDisposable { public class LegacyPamhagenPlc : IDisposable {
public record struct SensorStates( public record struct SensorStates(
long PressureSensors, long PressureSensors,
FillState FillingLevelMW1, FillState FillLevelMW1,
FillState FillingLevelMW2, FillState FillLevelMW2,
bool ClearancePress1, bool ClearancePress1,
bool ClearancePress2, bool ClearancePress2,
int TroughSelector, int TroughSelector,
double GradationOe, double GradationOe,
FillState[] FillingLevelTanks, FillState[] FillLevelTanks,
MotorState PresseQuerSchnecke MotorState PressCrossAuger
) { ) {
public readonly bool GetDS(int n) => (PressureSensors & (1L << (n - 1))) != 0; public readonly bool GetDS(int n) => (PressureSensors & (1L << (n - 1))) != 0;
} }
@@ -35,10 +35,10 @@ namespace PamhagenSysCtrl.Helpers {
protected readonly T1 Plc; protected readonly T1 Plc;
public string PortName => Plc.PortName; public string PortName => Plc.PortName;
public T1.Status LastPlcStatus => Plc.LastStatus; public T1.Status LastStatus => Plc.LastStatus;
public T1Error LastPlcError => Plc.LastError; public T1Error LastError => Plc.LastError;
public PamhagenPlc(string portName, Parity parity = Parity.Odd) { public LegacyPamhagenPlc(string portName, Parity parity = Parity.Odd) {
Plc = new T1(portName, parity); Plc = new T1(portName, parity);
} }
@@ -95,7 +95,7 @@ namespace PamhagenSysCtrl.Helpers {
throw new T1Exception($"Interner Fehler: {error} ({(int)error:0000})"); throw new T1Exception($"Interner Fehler: {error} ({(int)error:0000})");
} }
protected async Task<(ushort RW010, ushort RW011, ushort RW012, ushort RW013, ushort RW014, ushort RW015, ushort RW016)> ReadInputRegisters() { public async Task<(ushort RW010, ushort RW011, ushort RW012, ushort RW013, ushort RW014, ushort RW015, ushort RW016)> ReadInputRegisters() {
var d = await Plc.DataRead("RW010", 7); var d = await Plc.DataRead("RW010", 7);
// RW010, RW011, RW012, RW013 Drucksensoren // RW010, RW011, RW012, RW013 Drucksensoren
// RW014 Füllstände A1, A2, Presse1, Presse2, Wannenselekt // RW014 Füllstände A1, A2, Presse1, Presse2, Wannenselekt
+267
View File
@@ -0,0 +1,267 @@
using System.IO.Ports;
namespace PamhagenSysCtrl.Helpers.Plc {
public class PamhagenPlc : IDisposable {
private bool _manualControlMode = false;
private bool _overridePathClearnaces = false;
private bool _overrideDryRunClearances = false;
public bool ManualControlMode { get => _manualControlMode; set { _manualControlMode = value; UpdateInterlocks(); } }
public bool OverridePathClearances { get => _overridePathClearnaces; set { _overridePathClearnaces = value; UpdateInterlocks(); } }
public bool OverrideDryRunClearances { get => _overrideDryRunClearances; set { _overrideDryRunClearances = value; UpdateInterlocks(); } }
protected LegacyPamhagenPlc Plc;
public PamhagenState State { get; private set; }
public string? PortName => Plc?.PortName;
public T1.Status? LastStatus => Plc?.LastStatus;
public T1Error? LastError => Plc?.LastError;
protected LegacyPamhagenPlc.ActuatorStates Actuators;
protected LegacyPamhagenPlc.ActuatorStates LastActuators;
protected LegacyPamhagenPlc.SensorStates Sensors = new(default, default, default, default, default, default, default, [
FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown
], default);
public PamhagenPlc(string portName, Parity parity = Parity.Odd) {
Plc = new(portName, parity);
}
public void Dispose() {
GC.SuppressFinalize(this);
Plc.Dispose();
}
public async Task Initialize() {
await Plc.TestConnection();
Actuators = await Plc.ReadOutputs();
LastActuators = Actuators;
}
public async Task Shutdown() {
await Plc.WriteOutputs(new() { Valves = Actuators.Valves });
}
public async Task Update() {
UpdateInterlocks();
if (Actuators != LastActuators) {
// FIXME race condition!
await Plc.WriteOutputs(Actuators);
LastActuators = Actuators;
}
Sensors = await Plc.ReadInputs();
State = new(Sensors, () => Actuators, OverridePathClearances, OverrideDryRunClearances);
UpdateInterlocks();
}
protected void UpdateInterlocks() {
if (!ManualControlMode) {
if (State.PressCrossAuger_IsActive && !State.Auger2_IsActive) StartAuger2();
if (State.Rebler_IsActive && !State.Auger1_IsActive) StartAuger1();
if (State.Auger1_IsActive && !State.Auger2_IsActive) StartAuger2();
if (State.Auger2_IsActive && !State.Auger3_IsActive) StartAuger3();
if (State.TroughAuger_IsActive && !State.TroughAuger_HasClearance)
StopTroughAuger();
if (!State.PressCrossAuger_IsActive && !State.Auger1_IsActive) {
StopAuger2();
StopAuger3();
}
}
if (State.MP1_IsActive && !State.MP1_HasClearance) StopMP1();
if (State.MP2_IsActive && !State.MP2_HasClearance) StopMP2();
if (!ManualControlMode) {
if (State.MP1_State == MotorState.Forward && State.MW1_FillLevel >= FillState.Half && !State.MW1_Stirrer_IsActive) {
StartStirrerMW1();
} else if (State.MW2_Stirrer_IsActive && (!State.MP1_IsActive || State.MW1_FillLevel < FillState.Half)) {
StopStirrerMW1();
}
if (State.MP2_State == MotorState.Forward && State.MW2_FillLevel >= FillState.Half && !State.MW2_Stirrer_IsActive) {
StartStirrerMW2();
} else if (State.MW2_Stirrer_IsActive && (!State.MP2_IsActive || State.MW2_FillLevel < FillState.Half)) {
StopStirrerMW2();
}
}
if (State.P12_IsActive && !State.P12_HasClearance) DisableP12();
if (State.P3_IsActive && !State.P3_HasClearance) DisableP3();
if (State.P4_IsActive && !State.P4_HasClearance) DisableP4();
if (State.P5_IsActive && !State.P5_HasClearance) DisableP5();
if (State.P6_IsActive && !State.P6_HasClearance) DisableP6();
}
public void OpenV(int n) => SetV(n, true);
public void CloseV(int n) => SetV(n, false);
protected void SetV(int n, bool val) {
if (n < 1 || n > 57) throw new ArgumentException("Invalid value for n: 1 <= #V <= 57");
Actuators.SetV(n, val);
}
public void SelectMW1() {
Actuators.SetV(58, true);
}
public void SelectMW2() {
Actuators.SetV(58, false);
}
public void StartTroughAuger() {
if (!ManualControlMode && !State.TroughAuger_HasClearance)
throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe");
Actuators.TroughAuger = true;
}
public void StopTroughAuger() {
Actuators.TroughAuger = false;
}
public void StartRebler() {
Actuators.Rebler = true;
if (!ManualControlMode) StartAuger1();
}
public void StopRebler() {
if (!ManualControlMode) StopTroughAuger();
Actuators.Rebler = false;
}
public void StartStirrerMW1() {
Actuators.StirrerMW1 = true;
}
public void StopStirrerMW1() {
Actuators.StirrerMW1 = false;
}
public void StartStirrerMW2() {
Actuators.StirrerMW2 = true;
}
public void StopStirrerMW2() {
Actuators.StirrerMW2 = false;
}
public void StartAuger1() {
Actuators.Auger1 = true;
if (!ManualControlMode) StartAuger2();
}
public void StopAuger1() {
if (!ManualControlMode && State.Rebler_IsActive) throw new NoClearanceException("Rebler aktiv");
Actuators.Auger1 = false;
}
public void StartAuger2() {
Actuators.Auger2 = true;
if (!ManualControlMode) StartAuger3();
}
public void StopAuger2() {
if (!ManualControlMode && State.PressCrossAuger_IsActive) throw new NoClearanceException("Presse-Querschnecke aktiv");
if (!ManualControlMode && State.Auger1_IsActive) throw new NoClearanceException("Förderschnecke 1 aktiv");
Actuators.Auger2 = false;
}
public void StartAuger3() {
Actuators.Auger3 = true;
}
public void StopAuger3() {
if (!ManualControlMode && State.Auger2_IsActive) throw new NoClearanceException("Förderschnecke 2 aktiv");
Actuators.Auger3 = false;
}
public void StartGradationPump() {
Actuators.GradationPump = true;
}
public void StopGradationPump() {
Actuators.GradationPump = false;
}
public void StartMP1Forward() {
if (!State.MP1_HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe");
if (Actuators.MP1 == MotorState.Backward) throw new NoClearanceException("MP1 läuft bereits (zurück)");
Actuators.MP1 = MotorState.Forward;
if (State.MW1_FillLevel >= FillState.Half) StartStirrerMW1();
}
public void StartMP1Backward() {
if (!State.MP1_HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe");
if (Actuators.MP1 == MotorState.Forward) throw new NoClearanceException("MP1 läuft bereits (vor)");
Actuators.MP1 = MotorState.Backward;
}
public void StopMP1() {
Actuators.MP1 = MotorState.Halt;
if (!ManualControlMode) StopStirrerMW1();
}
public void StartMP2Forward() {
if (!State.MP2_HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe");
if (Actuators.MP2 == MotorState.Backward) throw new NoClearanceException("MP2 läuft bereits (zurück)");
Actuators.MP2 = MotorState.Forward;
if (State.MW2_FillLevel >= FillState.Half) StartStirrerMW2();
}
public void StartMP2Backward() {
if (!State.MP2_HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe");
if (Actuators.MP2 == MotorState.Forward) throw new NoClearanceException("MP2 läuft bereits (vor)");
Actuators.MP2 = MotorState.Backward;
}
public void StopMP2() {
Actuators.MP2 = MotorState.Halt;
if (!ManualControlMode) StopStirrerMW1();
}
public void EnableP12() {
if (!State.P12_HasClearance) throw new NoClearanceException("P1/2 hat keine Freigabe");
Actuators.P12 = MotorState.Forward;
}
public void DisableP12() {
Actuators.P12 = MotorState.Halt;
}
public void EnableP3() {
if (!State.P3_HasClearance) throw new NoClearanceException("P3 hat keine Freigabe");
Actuators.P3 = MotorState.Forward;
}
public void DisableP3() {
Actuators.P3 = MotorState.Halt;
}
public void EnableP4() {
if (!State.P4_HasClearance) throw new NoClearanceException("P4 hat keine Freigabe");
Actuators.P4 = MotorState.Forward;
}
public void DisableP4() {
Actuators.P4 = MotorState.Halt;
}
public void EnableP5() {
if (!State.P5_HasClearance) throw new NoClearanceException("P5 hat keine Freigabe");
Actuators.P5 = MotorState.Forward;
}
public void DisableP5() {
Actuators.P5 = MotorState.Halt;
}
public void EnableP6() {
if (!State.P6_HasClearance) throw new NoClearanceException("P6 hat keine Freigabe");
Actuators.P6 = MotorState.Forward;
}
public void DisableP6() {
Actuators.P6 = MotorState.Halt;
}
}
}
@@ -0,0 +1,262 @@
namespace PamhagenSysCtrl.Helpers.Plc {
public readonly record struct PamhagenState {
private readonly LegacyPamhagenPlc.SensorStates Sensors;
private readonly Func<LegacyPamhagenPlc.ActuatorStates> ActuatorsCb;
private LegacyPamhagenPlc.ActuatorStates Actuators { get => ActuatorsCb == null ? default : ActuatorsCb(); }
public long Valves => Actuators.Valves;
public long PressureSensors => Sensors.PressureSensors;
public bool MW1_IsSelected => Sensors.TroughSelector == 1;
public bool MW2_IsSelected => Sensors.TroughSelector == 2;
public bool MW1_WantSelected => Actuators.GetV(58);
public bool MW2_WantSelected => !Actuators.GetV(58);
public FillState MW1_FillLevel => Sensors.FillLevelMW1;
public FillState MW2_FillLevel => Sensors.FillLevelMW2;
public FillState[] Tanks_FillLevel => Sensors.FillLevelTanks;
public FillState T1_FillLevel => Sensors.FillLevelTanks[0];
public FillState T2_FillLevel => Sensors.FillLevelTanks[1];
public FillState T3_FillLevel => Sensors.FillLevelTanks[2];
public FillState T4_FillLevel => Sensors.FillLevelTanks[3];
public FillState T5_FillLevel => Sensors.FillLevelTanks[4];
public FillState T6_FillLevel => Sensors.FillLevelTanks[5];
public FillState T7_FillLevel => Sensors.FillLevelTanks[6];
public FillState T8_FillLevel => Sensors.FillLevelTanks[7];
public FillState T9_FillLevel => Sensors.FillLevelTanks[8];
public MotorState PressCrossAuger_State => Sensors.PressCrossAuger;
public bool PressCrossAuger_IsActive => PressCrossAuger_State == MotorState.Forward;
public bool TroughAuger_IsActive => Actuators.TroughAuger;
public bool Rebler_IsActive => Actuators.Rebler;
public bool MW1_Stirrer_IsActive => Actuators.StirrerMW1;
public bool MW2_Stirrer_IsActive => Actuators.StirrerMW2;
public bool Auger1_IsActive => Actuators.Auger1;
public bool Auger2_IsActive => Actuators.Auger2;
public bool Auger3_IsActive => Actuators.Auger3;
public bool WasteDisposal_IsActive => Auger1_IsActive || Auger2_IsActive || Auger3_IsActive;
public MotorState MP1_State => Actuators.MP1;
public MotorState MP2_State => Actuators.MP2;
public MotorState P12_State => Actuators.P12;
public MotorState P3_State => Actuators.P3;
public MotorState P4_State => Actuators.P4;
public MotorState P5_State => Actuators.P5;
public MotorState P6_State => Actuators.P6;
public bool MP1_IsActive => Actuators.MP1 == MotorState.Forward || Actuators.MP1 == MotorState.Backward;
public bool MP2_IsActive => Actuators.MP2 == MotorState.Forward || Actuators.MP2 == MotorState.Backward;
public bool P12_IsActive => Actuators.P12 == MotorState.Forward;
public bool P3_IsActive => Actuators.P3 == MotorState.Forward;
public bool P4_IsActive => Actuators.P4 == MotorState.Forward;
public bool P5_IsActive => Actuators.P5 == MotorState.Forward;
public bool P6_IsActive => Actuators.P6 == MotorState.Forward;
public bool Press1_HasClearance => Sensors.ClearancePress1;
public bool Press2_HasClearance => Sensors.ClearancePress2;
public bool TroughAuger_HasClearance => Rebler_IsActive && !(MW1_IsSelected && MW1_FillLevel == FillState.Full) && !(MW2_IsSelected && MW2_FillLevel == FillState.Full);
public readonly bool MP1_HasPathClearance { get; }
public readonly bool MP2_HasPathClearance { get; }
public readonly bool P12_HasPathClearance { get; }
public readonly bool P3_HasPathClearance { get; }
public readonly bool P4_HasPathClearance { get; }
public readonly bool P5_HasPathClearance { get; }
public readonly bool P6_HasPathClearance { get; }
public readonly bool MP1_HasDryRunClearance { get; }
public readonly bool MP2_HasDryRunClearance { get; }
public readonly bool P12_HasDryRunClearance { get; }
public readonly bool P3_HasDryRunClearance { get; }
public readonly bool P4_HasDryRunClearance { get; }
public readonly bool P5_HasDryRunClearance { get; }
public readonly bool P6_HasDryRunClearance { get; }
public bool MP1_HasClearance => MP1_HasDryRunClearance && MP1_HasPathClearance;
public bool MP2_HasClearance => MP2_HasDryRunClearance && MP2_HasPathClearance;
public bool P12_HasClearance => P12_HasDryRunClearance && P12_HasPathClearance;
public bool P3_HasClearance => P3_HasDryRunClearance && P3_HasPathClearance;
public bool P4_HasClearance => P4_HasDryRunClearance && P4_HasPathClearance;
public bool P5_HasClearance => P4_HasDryRunClearance && P5_HasPathClearance;
public bool P6_HasClearance => P6_HasDryRunClearance && P6_HasPathClearance;
public PamhagenState(LegacyPamhagenPlc.SensorStates sensors, Func<LegacyPamhagenPlc.ActuatorStates> actuatorsCb, bool overridePathClearances = false, bool overrideDryRunClearances = false) {
Sensors = sensors;
ActuatorsCb = actuatorsCb;
MP1_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.MP1);
MP2_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.MP2);
P12_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.P12);
P3_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.P3);
P4_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.P4);
P5_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.P5);
P6_HasPathClearance = overridePathClearances || HasPathClearance(this, Paths.P6);
MP1_HasDryRunClearance = overrideDryRunClearances || MW1_FillLevel != FillState.Empty;
MP2_HasDryRunClearance = overrideDryRunClearances || MW2_FillLevel != FillState.Empty;
P12_HasDryRunClearance = overrideDryRunClearances || T1_FillLevel != FillState.Empty || T2_FillLevel != FillState.Empty;
P3_HasDryRunClearance = overrideDryRunClearances || T3_FillLevel != FillState.Empty;
P4_HasDryRunClearance = overrideDryRunClearances || T4_FillLevel != FillState.Empty;
P5_HasDryRunClearance = overrideDryRunClearances || T5_FillLevel != FillState.Empty;
P6_HasDryRunClearance = true;
}
public bool Valve_IsClosed(int n) => Sensors.GetDS(n);
public bool Valve_IsOpen(int n) => !Valve_IsClosed(n);
public bool Valve_WantOpen(int n) => Actuators.GetV(n);
public bool Valve_WantClosed(int n) => !Valve_WantOpen(n);
private record struct ValveStates(int[] Open, int[] Closed) {
public readonly ValveStateMask ToMask() => new(Open.Aggregate(0L, (m, n) => m | (1L << (n - 1))), Open.Concat(Closed).Aggregate(0L, (m, n) => m | (1L << (n - 1))));
public static ValveStates operator +(ValveStates a, ValveStates b) {
return new([.. a.Open, .. b.Open], [.. a.Closed, .. b.Closed]);
}
}
private record struct ValveStateMask(long States, long Mask) {
public static ValveStateMask[] From(IEnumerable<ValveStates> states) => [.. states.Select(s => s.ToMask())];
public static bool operator ==(long a, ValveStateMask b) => (a & b.Mask) == b.States;
public static bool operator >=(long a, ValveStateMask b) => (a & b.States) == b.States;
public static bool operator !=(long a, ValveStateMask b) => !(a == b);
public static bool operator <=(long a, ValveStateMask b) => !(a >= b);
}
private static bool HasSinglePathClearance(PamhagenState state, IEnumerable<ValveStateMask> masks) {
return masks.Any(m => state.Valves == m && ~state.PressureSensors == m);
}
private static bool HasAnyClearance(PamhagenState state, IEnumerable<ValveStateMask> masks) {
return masks.Any(m => state.Valves >= m && ~state.PressureSensors >= m);
}
private static bool HasPathClearance(PamhagenState state, (ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) masks) {
return
(HasSinglePathClearance(state, masks.Press1) && state.Press1_HasClearance) ||
(HasSinglePathClearance(state, masks.Press2) && state.Press2_HasClearance) ||
(HasSinglePathClearance(state, masks.Tanks[0]) && state.T1_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[1]) && state.T2_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[2]) && state.T3_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[3]) && state.T4_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[4]) && state.T5_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[5]) && state.T6_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[6]) && state.T7_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[7]) && state.T8_FillLevel != FillState.Full) ||
(HasSinglePathClearance(state, masks.Tanks[8]) && state.T9_FillLevel != FillState.Full) ||
false;
}
private static bool HasPathClearance(PamhagenState state, (ValveStateMask[] Press1, ValveStateMask[] Press2) masks) {
return
(HasSinglePathClearance(state, masks.Press1) && state.Press1_HasClearance) ||
(HasSinglePathClearance(state, masks.Press2) && state.Press2_HasClearance) ||
false;
}
private static readonly (
(ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) MP1,
(ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) MP2,
(ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) P12,
(ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) P3,
(ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) P4,
(ValveStateMask[] Press1, ValveStateMask[] Press2, ValveStateMask[][] Tanks) P5,
(ValveStateMask[] Press1, ValveStateMask[] Press2) P6
) Paths;
static PamhagenState() {
ValveStates[] wt_aa = [
new([12], [15, 16, 20]), // bypass
new([15, 18, 16], [11, 12, 14, 17, 19, 20]), // WT1
new([15, 17, 20], [11, 12, 18, 19, 21]), // WT2
new([15, 18, 19, 20], [11, 12, 14, 16, 17, 21]), // WT1+WT2
];
ValveStates[] wt_ab = [
new([15, 18, 14], [11, 12, 13, 16, 17, 19, 21]), // WT1
new([15, 17, 21], [11, 12, 13, 18, 19, 20]), // WT2
new([15, 18, 19, 21], [11, 12, 13, 14, 16, 17, 20]), // WT1+WT2
];
ValveStates[] wt_ba = [
new([11, 18, 16], [15, 12, 13, 14, 17, 19, 20]), // WT1
new([11, 17, 20], [15, 12, 13, 18, 19, 21]), // WT2
new([11, 18, 19, 20], [15, 12, 13, 14, 16, 17, 21]), // WT1+WT2
];
ValveStates[] wt_bb = [
new([13], [11, 14, 21]), // bypass
new([11, 18, 14], [15, 13, 16, 17, 19, 21]), // WT1
new([11, 17, 21], [15, 13, 18, 19, 20]), // WT2
new([11, 18, 19, 21], [15, 13, 14, 16, 17, 20]), // WT1+WT2
];
ValveStates[][] tanks = [
[new([22], [24, 26, 28]), new([23], [25, 27, 29])],
[new([24], [22, 26, 28]), new([25], [23, 27, 29])],
[new([26], [22, 24, 28]), new([27], [23, 25, 29])],
[new([28, 30], [22, 24, 26, 32, 34]), new([29, 31], [23, 25, 27, 33, 35])],
[new([28, 32], [22, 24, 26, 30, 34]), new([29, 33], [23, 25, 27, 31, 35])],
[new([28, 34, 37], [22, 24, 26, 30, 32, 39, 41, 43]), new([29, 35, 36], [23, 25, 27, 31, 33, 38, 40, 42])],
[new([28, 34, 39], [22, 24, 26, 30, 32, 37, 41, 43]), new([29, 35, 38], [23, 25, 27, 31, 33, 36, 40, 42])],
[new([28, 34, 41], [22, 24, 26, 30, 32, 37, 39, 43]), new([29, 35, 40], [23, 25, 27, 31, 33, 36, 38, 42])],
[new([28, 34, 43], [22, 24, 26, 30, 32, 37, 39, 41]), new([29, 35, 42], [23, 25, 27, 31, 33, 36, 38, 40])],
];
ValveStates[] mp1_pr1 = [
new([1, 6, 51], [3, 4, 5, 50, 52, 53, 55]),
new([4, 8, 52], [1, 2, 7, 50, 51, 53, 56]),
];
ValveStates[] mp1_pr2 = [
new([1, 6, 55], [3, 4, 5, 51, 54, 56, 57]),
new([4, 8, 56], [1, 2, 7, 52, 54, 55, 57]),
];
ValveStates mp1_wt_a = new([1, 5], [3, 4, 6]);
ValveStates mp1_wt_b = new([4, 7, 9], [1, 2, 8, 10]);
ValveStates[] mp1_a = [.. wt_aa.Select(m => mp1_wt_a + m), .. wt_ba.Select(m => mp1_wt_b + m)];
ValveStates[] mp1_b = [.. wt_ab.Select(m => mp1_wt_a + m), .. wt_bb.Select(m => mp1_wt_b + m)];
ValveStates[][] mp1_t = [.. tanks.Select<ValveStates[], ValveStates[]>(t => [.. mp1_a.Select(m => m + t[0]), .. mp1_b.Select(m => m + t[1])])];
ValveStates[] mp2_pr1 = [
new([2, 8, 52], [3, 4, 7, 50, 51, 53, 56]),
new([3, 6, 51], [1, 2, 5, 50, 52, 53, 55]),
];
ValveStates[] mp2_pr2 = [
new([2, 8, 56], [3, 4, 7, 52, 54, 55, 57]),
new([3, 6, 55], [2, 1, 5, 51, 54, 56, 57]),
];
ValveStates mp2_wt_a = new([3, 5], [1, 2, 6]);
ValveStates mp2_wt_b = new([2, 7, 9], [3, 4, 8, 10]);
ValveStates[] mp2_a = [.. wt_aa.Select(m => mp2_wt_a + m), .. wt_ba.Select(m => mp2_wt_b + m)];
ValveStates[] mp2_b = [.. wt_ab.Select(m => mp2_wt_a + m), .. wt_bb.Select(m => mp2_wt_b + m)];
ValveStates[][] mp2_t = [.. tanks.Select<ValveStates[], ValveStates[]>(t => [.. mp2_a.Select(m => m + t[0]), .. mp2_b.Select(m => m + t[1])])];
ValveStates[] p12_pr1 = [new([44, 46, 49, 50], [10, 45, 47, 48, 54, 51, 52, 53])];
ValveStates[] p12_pr2 = [new([44, 46, 49, 54], [10, 45, 47, 48, 50, 55, 56, 57])];
ValveStates[] p12_b = [new([44, 10], [9, 45, 46])];
ValveStates[][] p12_t = [.. tanks.Select<ValveStates[], ValveStates[]>(t => [.. p12_b.Select(m => m + t[1])])];
ValveStates[] p3_pr1 = [new([45, 46, 49, 50], [10, 44, 47, 48, 51, 52, 53, 54])];
ValveStates[] p3_pr2 = [new([45, 46, 49, 54], [10, 44, 47, 48, 50, 55, 56, 57])];
ValveStates[] p3_b = [new([45, 10], [9, 44, 46])];
ValveStates[][] p3_t = [.. tanks.Select<ValveStates[], ValveStates[]>(t => [.. p3_b.Select(m => m + t[1])])];
ValveStates[] p4_pr1 = [new([47, 49, 50], [46, 48, 51, 52, 53, 54])];
ValveStates[] p4_pr2 = [new([47, 49, 54], [46, 48, 50, 55, 56, 57])];
ValveStates[] p4_b = [new([47, 46, 10], [9, 44, 45, 48, 49])];
ValveStates[][] p4_t = [.. tanks.Select<ValveStates[], ValveStates[]>(t => [.. p4_b.Select(m => m + t[1])])];
ValveStates[] p5_pr1 = [new([48, 49, 50], [46, 47, 51, 52, 53, 54])];
ValveStates[] p5_pr2 = [new([48, 49, 54], [46, 47, 50, 55, 56, 57])];
ValveStates[] p5_b = [new([48, 46, 10], [9, 44, 45, 47, 49])];
ValveStates[][] p5_t = [.. tanks.Select<ValveStates[], ValveStates[]>(t => [.. p5_b.Select(m => m + t[1])])];
ValveStates[] p6_pr1 = [new([53], [50, 51, 52, 57])];
ValveStates[] p6_pr2 = [new([57], [53, 54, 55, 56])];
Paths = (
(ValveStateMask.From(mp1_pr1), ValveStateMask.From(mp1_pr2), [.. mp1_t.Select(t => ValveStateMask.From(t))]),
(ValveStateMask.From(mp2_pr1), ValveStateMask.From(mp2_pr2), [.. mp2_t.Select(t => ValveStateMask.From(t))]),
(ValveStateMask.From(p12_pr1), ValveStateMask.From(p12_pr2), [.. p12_t.Select(t => ValveStateMask.From(t))]),
(ValveStateMask.From(p3_pr1), ValveStateMask.From(p3_pr2), [.. p3_t.Select(t => ValveStateMask.From(t))]),
(ValveStateMask.From(p4_pr1), ValveStateMask.From(p4_pr2), [.. p4_t.Select(t => ValveStateMask.From(t))]),
(ValveStateMask.From(p5_pr1), ValveStateMask.From(p5_pr2), [.. p5_t.Select(t => ValveStateMask.From(t))]),
(ValveStateMask.From(p6_pr1), ValveStateMask.From(p6_pr2))
);
}
}
}
@@ -2,7 +2,7 @@ using System.IO;
using System.IO.Ports; using System.IO.Ports;
using System.Text; using System.Text;
namespace PamhagenSysCtrl.Helpers { namespace PamhagenSysCtrl.Helpers.Plc {
public class T1 : IDisposable { public class T1 : IDisposable {
public enum Mode { HALT = 1, RUN = 2, RUN_F = 3, HOLD = 4, ERROR = 6 } public enum Mode { HALT = 1, RUN = 2, RUN_F = 3, HOLD = 4, ERROR = 6 }
@@ -51,7 +51,7 @@ namespace PamhagenSysCtrl.Helpers {
Serial.WriteLine(line.ToString()); Serial.WriteLine(line.ToString());
} }
protected async Task<(string, string)> ReceiveResponse(string? expectedCmd = null) { protected async Task<(string Command, string Data)> ReceiveResponse(string? expectedCmd = null) {
var line = Serial.ReadLine(); var line = Serial.ReadLine();
if (line.Length < 8 || !line.StartsWith("(A") || !line.EndsWith(')') || line[^4] != '&') { if (line.Length < 8 || !line.StartsWith("(A") || !line.EndsWith(')') || line[^4] != '&') {
throw new FormatException("Invalid response from PLC (T1)"); throw new FormatException("Invalid response from PLC (T1)");
@@ -1,4 +1,4 @@
namespace PamhagenSysCtrl.Helpers { namespace PamhagenSysCtrl.Helpers.Plc {
public enum T1Error { public enum T1Error {
UNKNOWN_ERROR = -1, UNKNOWN_ERROR = -1,
NO_ERROR = 0, NO_ERROR = 0,
@@ -1,4 +1,4 @@
namespace PamhagenSysCtrl.Helpers { namespace PamhagenSysCtrl.Helpers.Plc {
public class T1Exception(string msg) : Exception(msg) { public class T1Exception(string msg) : Exception(msg) {
} }
} }
@@ -29,14 +29,14 @@ namespace PamhagenSysCtrl {
if (App.Plant == null || sender is not Button b) return; if (App.Plant == null || sender is not Button b) return;
var i = int.Parse($"{b.Content}"[1..]); var i = int.Parse($"{b.Content}"[1..]);
if (i == 58) { if (i == 58) {
if (App.Plant.WantMW1Selected) { if (App.Plant.State.MW1_WantSelected) {
App.Plant.SelectMW2(); App.Plant.SelectMW2();
} else { } else {
App.Plant.SelectMW1(); App.Plant.SelectMW1();
} }
} else if (i > 57) { } else if (i > 57) {
return; return;
} else if (App.Plant.WantValveOpen(i)) { } else if (App.Plant.State.Valve_WantOpen(i)) {
App.Plant.CloseV(i); App.Plant.CloseV(i);
} else { } else {
App.Plant.OpenV(i); App.Plant.OpenV(i);
@@ -60,8 +60,8 @@ namespace PamhagenSysCtrl {
if (sender is not PamhagenPlant plant) return; if (sender is not PamhagenPlant plant) return;
for (int i = 1; i <= 58; i++) { for (int i = 1; i <= 58; i++) {
var target = plant.WantValveClosed(i); var target = plant.State.Valve_WantClosed(i);
var actual = plant.IsValveClosed(i); var actual = plant.State.Valve_IsClosed(i);
if (ValvePanel.Children[i - 1] is not Button b) if (ValvePanel.Children[i - 1] is not Button b)
continue; continue;
b.BorderBrush = target ? Brushes.DarkRed : Brushes.DarkGreen; b.BorderBrush = target ? Brushes.DarkRed : Brushes.DarkGreen;
@@ -69,98 +69,97 @@ namespace PamhagenSysCtrl {
b.Background = actual ? Brushes.MistyRose : Brushes.MintCream; b.Background = actual ? Brushes.MistyRose : Brushes.MintCream;
} }
ReblerButton.BorderBrush = plant.IsReblerActive ? Brushes.DarkGreen : Brushes.DarkRed; ReblerButton.BorderBrush = plant.State.Rebler_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
ReblerButton.Foreground = plant.IsReblerActive ? Brushes.DarkGreen : Brushes.DarkRed; ReblerButton.Foreground = plant.State.Rebler_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
ReblerButton.Background = plant.IsReblerActive ? Brushes.MintCream: Brushes.MistyRose; ReblerButton.Background = plant.State.Rebler_IsActive ? Brushes.MintCream: Brushes.MistyRose;
TroughAugerButton.BorderBrush = plant.IsTroughAugerActive ? Brushes.DarkGreen : Brushes.DarkRed; TroughAugerButton.BorderBrush = plant.State.TroughAuger_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
TroughAugerButton.Foreground = plant.IsTroughAugerActive ? Brushes.DarkGreen : Brushes.DarkRed; TroughAugerButton.Foreground = plant.State.TroughAuger_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
TroughAugerButton.Background = plant.IsTroughAugerActive ? Brushes.MintCream : Brushes.MistyRose; TroughAugerButton.Background = plant.State.TroughAuger_IsActive ? Brushes.MintCream : Brushes.MistyRose;
StirrerMW1Button.BorderBrush = plant.IsStirrerMW1Active ? Brushes.DarkGreen : Brushes.DarkRed; StirrerMW1Button.BorderBrush = plant.State.MW1_Stirrer_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW1Button.Foreground = plant.IsStirrerMW1Active ? Brushes.DarkGreen : Brushes.DarkRed; StirrerMW1Button.Foreground = plant.State.MW1_Stirrer_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW1Button.Background = plant.IsStirrerMW1Active ? Brushes.MintCream : Brushes.MistyRose; StirrerMW1Button.Background = plant.State.MW1_Stirrer_IsActive ? Brushes.MintCream : Brushes.MistyRose;
StirrerMW2Button.BorderBrush = plant.IsStirrerMW2Active ? Brushes.DarkGreen : Brushes.DarkRed; StirrerMW2Button.BorderBrush = plant.State.MW2_Stirrer_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW2Button.Foreground = plant.IsStirrerMW2Active ? Brushes.DarkGreen : Brushes.DarkRed; StirrerMW2Button.Foreground = plant.State.MW2_Stirrer_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW2Button.Background = plant.IsStirrerMW2Active ? Brushes.MintCream : Brushes.MistyRose; StirrerMW2Button.Background = plant.State.MW2_Stirrer_IsActive ? Brushes.MintCream : Brushes.MistyRose;
Auger1Button.BorderBrush = plant.IsAuger1Active ? Brushes.DarkGreen : Brushes.DarkRed; Auger1Button.BorderBrush = plant.State.Auger1_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
Auger1Button.Foreground = plant.IsAuger1Active ? Brushes.DarkGreen : Brushes.DarkRed; Auger1Button.Foreground = plant.State.Auger1_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
Auger1Button.Background = plant.IsAuger1Active ? Brushes.MintCream : Brushes.MistyRose; Auger1Button.Background = plant.State.Auger1_IsActive ? Brushes.MintCream : Brushes.MistyRose;
Auger2Button.BorderBrush = plant.IsAuger2Active ? Brushes.DarkGreen : Brushes.DarkRed; Auger2Button.BorderBrush = plant.State.Auger2_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
Auger2Button.Foreground = plant.IsAuger2Active ? Brushes.DarkGreen : Brushes.DarkRed; Auger2Button.Foreground = plant.State.Auger2_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
Auger2Button.Background = plant.IsAuger2Active ? Brushes.MintCream : Brushes.MistyRose; Auger2Button.Background = plant.State.Auger2_IsActive ? Brushes.MintCream : Brushes.MistyRose;
Auger3Button.BorderBrush = plant.IsAuger3Active ? Brushes.DarkGreen : Brushes.DarkRed; Auger3Button.BorderBrush = plant.State.Auger3_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
Auger3Button.Foreground = plant.IsAuger3Active ? Brushes.DarkGreen : Brushes.DarkRed; Auger3Button.Foreground = plant.State.Auger3_IsActive ? Brushes.DarkGreen : Brushes.DarkRed;
Auger3Button.Background = plant.IsAuger3Active ? Brushes.MintCream : Brushes.MistyRose; Auger3Button.Background = plant.State.Auger3_IsActive ? Brushes.MintCream : Brushes.MistyRose;
MP1BackwardButton.BorderBrush = plant.MP1 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray; MP1BackwardButton.BorderBrush = plant.State.MP1_State == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1BackwardButton.Foreground = plant.MP1 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray; MP1BackwardButton.Foreground = plant.State.MP1_State == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1BackwardButton.Background = plant.MP1 == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke; MP1BackwardButton.Background = plant.State.MP1_State == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke;
MP1HaltButton.BorderBrush = plant.MP1 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray; MP1HaltButton.BorderBrush = plant.State.MP1_State == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP1HaltButton.Foreground = plant.MP1 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray; MP1HaltButton.Foreground = plant.State.MP1_State == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP1HaltButton.Background = plant.MP1 == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke; MP1HaltButton.Background = plant.State.MP1_State == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke;
MP1ForwardButton.BorderBrush = plant.MP1 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray; MP1ForwardButton.BorderBrush = plant.State.MP1_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1ForwardButton.Foreground = plant.MP1 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray; MP1ForwardButton.Foreground = plant.State.MP1_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1ForwardButton.Background = plant.MP1 == MotorState.Forward ? Brushes.MintCream: Brushes.WhiteSmoke; MP1ForwardButton.Background = plant.State.MP1_State == MotorState.Forward ? Brushes.MintCream: Brushes.WhiteSmoke;
MP2BackwardButton.BorderBrush = plant.MP2 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray; MP2BackwardButton.BorderBrush = plant.State.MP2_State == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2BackwardButton.Foreground = plant.MP2 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray; MP2BackwardButton.Foreground = plant.State.MP2_State == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2BackwardButton.Background = plant.MP2 == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke; MP2BackwardButton.Background = plant.State.MP2_State == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke;
MP2HaltButton.BorderBrush = plant.MP2 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray; MP2HaltButton.BorderBrush = plant.State.MP2_State == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP2HaltButton.Foreground = plant.MP2 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray; MP2HaltButton.Foreground = plant.State.MP2_State == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP2HaltButton.Background = plant.MP2 == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke; MP2HaltButton.Background = plant.State.MP2_State == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke;
MP2ForwardButton.BorderBrush = plant.MP2 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray; MP2ForwardButton.BorderBrush = plant.State.MP2_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2ForwardButton.Foreground = plant.MP2 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray; MP2ForwardButton.Foreground = plant.State.MP2_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2ForwardButton.Background = plant.MP2 == MotorState.Forward ? Brushes.MintCream : Brushes.WhiteSmoke; MP2ForwardButton.Background = plant.State.MP2_State == MotorState.Forward ? Brushes.MintCream : Brushes.WhiteSmoke;
P12Button.BorderBrush = plant.P12 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P12Button.BorderBrush = plant.State.P12_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P12Button.Foreground = plant.P12 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P12Button.Foreground = plant.State.P12_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P12Button.Background = plant.P12 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose; P12Button.Background = plant.State.P12_State == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P3Button.BorderBrush = plant.P3 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P3Button.BorderBrush = plant.State.P3_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P3Button.Foreground = plant.P3 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P3Button.Foreground = plant.State.P3_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P3Button.Background = plant.P3 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose; P3Button.Background = plant.State.P3_State == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P4Button.BorderBrush = plant.P4 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P4Button.BorderBrush = plant.State.P4_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P4Button.Foreground = plant.P4 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P4Button.Foreground = plant.State.P4_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P4Button.Background = plant.P4 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose; P4Button.Background = plant.State.P4_State == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P5Button.BorderBrush = plant.P5 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P5Button.BorderBrush = plant.State.P5_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P5Button.Foreground = plant.P5 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P5Button.Foreground = plant.State.P5_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P5Button.Background = plant.P5 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose; P5Button.Background = plant.State.P5_State == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P6Button.BorderBrush = plant.P6 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P6Button.BorderBrush = plant.State.P6_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P6Button.Foreground = plant.P6 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed; P6Button.Foreground = plant.State.P6_State == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P6Button.Background = plant.P6 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose; P6Button.Background = plant.State.P6_State == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
Status.Text = $""" Status.Text = $"""
Gradation °Oe: {plant.GradationOe:N2} Presse Querschnecke: {plant.State.PressCrossAuger_State}
Presse Querschnecke: {plant.PresseQuerSchnecke}
Füllstände: Füllstände:
Maischewanne 1: {plant.FillLevelMW1} (ausgewählt: {plant.WantMW1Selected}, Status: {plant.IsMW1Selected}) Maischewanne 1: {plant.State.MW2_FillLevel} (ausgewählt: {plant.State.MW1_WantSelected}, Status: {plant.State.MW1_IsSelected})
Maischewanne 2: {plant.FillLevelMW2} (ausgewählt: {plant.WantMW2Selected}, Status: {plant.IsMW2Selected}) Maischewanne 2: {plant.State.MW2_FillLevel} (ausgewählt: {plant.State.MW2_WantSelected}, Status: {plant.State.MW2_IsSelected})
Presse 1: {plant.Press1HasClearance} Presse 1: {plant.State.Press1_HasClearance}
Presse 2: {plant.Press2HasClearance} Presse 2: {plant.State.Press2_HasClearance}
Tank 1: {plant.FillLevelT1} Tank 1: {plant.State.T1_FillLevel}
Tank 2: {plant.FillLevelT2} Tank 2: {plant.State.T2_FillLevel}
Tank 3: {plant.FillLevelT3} Tank 3: {plant.State.T3_FillLevel}
Tank 4: {plant.FillLevelT4} Tank 4: {plant.State.T4_FillLevel}
Tank 5: {plant.FillLevelT5} Tank 5: {plant.State.T5_FillLevel}
Tank 6: {plant.FillLevelT6} Tank 6: {plant.State.T6_FillLevel}
Tank 7: {plant.FillLevelT7} Tank 7: {plant.State.T7_FillLevel}
Tank 8: {plant.FillLevelT8} Tank 8: {plant.State.T8_FillLevel}
Tank 9: {plant.FillLevelT9} Tank 9: {plant.State.T9_FillLevel}
"""; """;
} }
private void TroughAugerButton_Click(object? sender, RoutedEventArgs? evt) { private void TroughAugerButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsTroughAugerActive) { if (App.Plant.State.TroughAuger_IsActive) {
App.Plant.StopTroughAuger(); App.Plant.StopTroughAuger();
} else { } else {
App.Plant.StartTroughAuger(); App.Plant.StartTroughAuger();
@@ -173,7 +172,7 @@ namespace PamhagenSysCtrl {
private void ReblerButton_Click(object? sender, RoutedEventArgs? evt) { private void ReblerButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsReblerActive) { if (App.Plant.State.Rebler_IsActive) {
App.Plant.StopRebler(); App.Plant.StopRebler();
} else { } else {
App.Plant.StartRebler(); App.Plant.StartRebler();
@@ -186,7 +185,7 @@ namespace PamhagenSysCtrl {
private void StirrerMW1Button_Click(object? sender, RoutedEventArgs? evt) { private void StirrerMW1Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsStirrerMW1Active) { if (App.Plant.State.MW1_Stirrer_IsActive) {
App.Plant.StopStirrerMW1(); App.Plant.StopStirrerMW1();
} else { } else {
App.Plant.StartStirrerMW1(); App.Plant.StartStirrerMW1();
@@ -199,7 +198,7 @@ namespace PamhagenSysCtrl {
private void StirrerMW2Button_Click(object? sender, RoutedEventArgs? evt) { private void StirrerMW2Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsStirrerMW2Active) { if (App.Plant.State.MW2_Stirrer_IsActive) {
App.Plant.StopStirrerMW2(); App.Plant.StopStirrerMW2();
} else { } else {
App.Plant.StartStirrerMW2(); App.Plant.StartStirrerMW2();
@@ -212,7 +211,7 @@ namespace PamhagenSysCtrl {
private void Auger1Button_Click(object? sender, RoutedEventArgs? evt) { private void Auger1Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsAuger1Active) { if (App.Plant.State.Auger1_IsActive) {
App.Plant.StopAuger1(); App.Plant.StopAuger1();
} else { } else {
App.Plant.StartAuger1(); App.Plant.StartAuger1();
@@ -225,7 +224,7 @@ namespace PamhagenSysCtrl {
private void Auger2Button_Click(object? sender, RoutedEventArgs? evt) { private void Auger2Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsAuger2Active) { if (App.Plant.State.Auger2_IsActive) {
App.Plant.StopAuger2(); App.Plant.StopAuger2();
} else { } else {
App.Plant.StartAuger2(); App.Plant.StartAuger2();
@@ -238,7 +237,7 @@ namespace PamhagenSysCtrl {
private void Auger3Button_Click(object? sender, RoutedEventArgs? evt) { private void Auger3Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.IsAuger3Active) { if (App.Plant.State.Auger3_IsActive) {
App.Plant.StopAuger3(); App.Plant.StopAuger3();
} else { } else {
App.Plant.StartAuger3(); App.Plant.StartAuger3();
@@ -306,10 +305,10 @@ namespace PamhagenSysCtrl {
private void P12Button_Click(object? sender, RoutedEventArgs? evt) { private void P12Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.P12 == MotorState.Forward) { if (App.Plant.State.P12_IsActive) {
App.Plant.StopP12(); App.Plant.DisableP12();
} else { } else {
App.Plant.StartP12(); App.Plant.EnableP12();
} }
} catch (NoClearanceException exc) { } catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -319,10 +318,10 @@ namespace PamhagenSysCtrl {
private void P3Button_Click(object? sender, RoutedEventArgs? evt) { private void P3Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.P3 == MotorState.Forward) { if (App.Plant.State.P3_IsActive) {
App.Plant.StopP3(); App.Plant.DisableP3();
} else { } else {
App.Plant.StartP3(); App.Plant.EnableP3();
} }
} catch (NoClearanceException exc) { } catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -332,10 +331,10 @@ namespace PamhagenSysCtrl {
private void P4Button_Click(object? sender, RoutedEventArgs? evt) { private void P4Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.P4 == MotorState.Forward) { if (App.Plant.State.P4_IsActive) {
App.Plant.StopP4(); App.Plant.DisableP4();
} else { } else {
App.Plant.StartP4(); App.Plant.EnableP4();
} }
} catch (NoClearanceException exc) { } catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -345,10 +344,10 @@ namespace PamhagenSysCtrl {
private void P5Button_Click(object? sender, RoutedEventArgs? evt) { private void P5Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.P5 == MotorState.Forward) { if (App.Plant.State.P5_IsActive) {
App.Plant.StopP5(); App.Plant.DisableP5();
} else { } else {
App.Plant.StartP5(); App.Plant.EnableP5();
} }
} catch (NoClearanceException exc) { } catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -358,10 +357,10 @@ namespace PamhagenSysCtrl {
private void P6Button_Click(object? sender, RoutedEventArgs? evt) { private void P6Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return; if (App.Plant == null) return;
try { try {
if (App.Plant.P6 == MotorState.Forward) { if (App.Plant.State.P6_IsActive) {
App.Plant.StopP6(); App.Plant.DisableP6();
} else { } else {
App.Plant.StartP6(); App.Plant.EnableP6();
} }
} catch (NoClearanceException exc) { } catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
@@ -1,5 +1,6 @@
using PamhagenSysCtrl.Helpers; using PamhagenSysCtrl.Helpers;
using PamhagenSysCtrl.Helpers.Pipeline; using PamhagenSysCtrl.Helpers.Pipeline;
using PamhagenSysCtrl.Helpers.Plc;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@@ -385,7 +386,7 @@ namespace PamhagenSysCtrl.Windows {
App.Plant?.StartRebler(); App.Plant?.StartRebler();
} }
} else if (c is Switcher switcher) { } else if (c is Switcher switcher) {
if (App.Plant?.WantMW1Selected ?? false) { if (App.Plant?.State.MW1_WantSelected ?? false) {
App.Plant?.SelectMW2(); App.Plant?.SelectMW2();
} else { } else {
App.Plant?.SelectMW1(); App.Plant?.SelectMW1();
@@ -425,33 +426,33 @@ namespace PamhagenSysCtrl.Windows {
} }
} else if (pump == Graph.P12) { } else if (pump == Graph.P12) {
if (pump.IsActive) { if (pump.IsActive) {
App.Plant?.StopP12(); App.Plant?.DisableP12();
} else { } else {
App.Plant?.StartP12(); App.Plant?.EnableP12();
} }
} else if (pump == Graph.P3) { } else if (pump == Graph.P3) {
if (pump.IsActive) { if (pump.IsActive) {
App.Plant?.StopP3(); App.Plant?.DisableP3();
} else { } else {
App.Plant?.StartP3(); App.Plant?.EnableP3();
} }
} else if (pump == Graph.P4) { } else if (pump == Graph.P4) {
if (pump.IsActive) { if (pump.IsActive) {
App.Plant?.StopP4(); App.Plant?.DisableP4();
} else { } else {
App.Plant?.StartP4(); App.Plant?.EnableP4();
} }
} else if (pump == Graph.P5) { } else if (pump == Graph.P5) {
if (pump.IsActive) { if (pump.IsActive) {
App.Plant?.StopP5(); App.Plant?.DisableP5();
} else { } else {
App.Plant?.StartP5(); App.Plant?.EnableP5();
} }
} else if (pump == Graph.P6) { } else if (pump == Graph.P6) {
if (pump.IsActive) { if (pump.IsActive) {
App.Plant?.StopP6(); App.Plant?.DisableP6();
} else { } else {
App.Plant?.StartP6(); App.Plant?.EnableP6();
} }
} }
} }
@@ -497,14 +498,14 @@ namespace PamhagenSysCtrl.Windows {
} }
} }
SetFastSelectButton(FastSelectButton_EntryTrough_Start, App.Plant?.IsTroughAugerActive ?? false ? 1 : 0, !(App.Plant?.TroughAugerHasClearance ?? false)); SetFastSelectButton(FastSelectButton_EntryTrough_Start, App.Plant?.State.TroughAuger_IsActive ?? false ? 1 : 0, !(App.Plant?.State.TroughAuger_HasClearance ?? false));
SetFastSelectButton(FastSelectButton_EntryTrough_Stop, App.Plant?.IsTroughAugerActive ?? false ? 0 : 2); SetFastSelectButton(FastSelectButton_EntryTrough_Stop, App.Plant?.State.TroughAuger_IsActive ?? false ? 0 : 2);
SetFastSelectButton(FastSelectButton_MW1, App.Plant?.IsMW1Selected ?? false ? 1 : 0); SetFastSelectButton(FastSelectButton_MW1, App.Plant?.State.MW1_IsSelected?? false ? 1 : 0);
SetFastSelectButton(FastSelectButton_MW2, App.Plant?.IsMW2Selected ?? false ? 1 : 0); SetFastSelectButton(FastSelectButton_MW2, App.Plant?.State.MW2_IsSelected ?? false ? 1 : 0);
SetFastSelectButton(FastSelectButton_MP1_Forward, App.Plant?.MP1 == MotorState.Forward ? 1 : 0, !(App.Plant?.MP1HasClearance ?? false)); SetFastSelectButton(FastSelectButton_MP1_Forward, App.Plant?.State.MP1_State == MotorState.Forward ? 1 : 0, !(App.Plant?.State.MP1_HasClearance ?? false));
SetFastSelectButton(FastSelectButton_MP1_Stop, App.Plant?.MP1 == MotorState.Halt ? 2 : 0); SetFastSelectButton(FastSelectButton_MP1_Stop, App.Plant?.State.MP1_State == MotorState.Halt ? 2 : 0);
SetFastSelectButton(FastSelectButton_MP2_Forward, App.Plant?.MP2 == MotorState.Forward ? 1 : 0, !(App.Plant?.MP2HasClearance ?? false)); SetFastSelectButton(FastSelectButton_MP2_Forward, App.Plant?.State.MP2_State == MotorState.Forward ? 1 : 0, !(App.Plant?.State.MP2_HasClearance ?? false));
SetFastSelectButton(FastSelectButton_MP2_Stop, App.Plant?.MP2 == MotorState.Halt ? 2 : 0); SetFastSelectButton(FastSelectButton_MP2_Stop, App.Plant?.State.MP2_State == MotorState.Halt ? 2 : 0);
_hover = Graph.GetHover(pos.X, pos.Y, RoundedScale); _hover = Graph.GetHover(pos.X, pos.Y, RoundedScale);
var hoverButtons = FastSelectPaths.Where(b => b.Key.IsMouseOver).ToDictionary(); var hoverButtons = FastSelectPaths.Where(b => b.Key.IsMouseOver).ToDictionary();
@@ -585,8 +586,8 @@ namespace PamhagenSysCtrl.Windows {
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" : "") + ")"; Status_Connection.Text = $"Ja ({p.PlcPortName}" + (p.LastRttNs != null ? $", {p.LastRttNs / 1000000.0:N0} ms" : "") + ")";
Status_Plc.Text = $"{p.LastPlcStatus?.Mode} ({p.LastPlcStatus?.Flags:X3}) / {p.LastPlcError?.GetName()} ({(int?)p.LastPlcError:0000})"; Status_Plc.Text = $"{p.LastPlcStatus?.Mode} ({p.LastPlcStatus?.Flags:X3}) / {p.LastPlcError?.GetName()} ({(int?)p.LastPlcError:0000})";
Status_CompressedAir.Text = Enumerable.Range(1, 57).Any(p.IsValveClosed) ? "Ein" : Enumerable.Range(1, 57).Any(p.WantValveClosed) ? "Aus" : "?"; 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.IsValveOpen) + " / " + Enumerable.Range(1, 57).Count(p.WantValveOpen) + " / 57"; Status_ValvesOpen.Text = Enumerable.Range(1, 57).Count(p.State.Valve_IsOpen) + " / " + Enumerable.Range(1, 57).Count(p.State.Valve_WantOpen) + " / 57";
} }
UpdateScheme(Mouse.GetPosition(SchemeCanvas), Mouse.LeftButton == MouseButtonState.Pressed); UpdateScheme(Mouse.GetPosition(SchemeCanvas), Mouse.LeftButton == MouseButtonState.Pressed);
} }
@@ -611,7 +612,7 @@ namespace PamhagenSysCtrl.Windows {
foreach (var src in sources) { foreach (var src in sources) {
var paths = new List<Path>(); var paths = new List<Path>();
foreach (var sink in sinks) { foreach (var sink in sinks) {
paths.AddRange(Graph.GetPaths(src, sink, null, (n) => n is not ISink && (n is not ControlledValve v || p.WantValveOpen(v.Nr)))); paths.AddRange(Graph.GetPaths(src, sink, null, (n) => n is not ISink && (n is not ControlledValve v || p.State.Valve_WantOpen(v.Nr))));
} }
if (paths.Count == 1) if (paths.Count == 1)
yield return paths.First(); yield return paths.First();