using PamhagenSysCtrl.Helpers.Pipeline; using System.IO; using System.Windows; namespace PamhagenSysCtrl.Helpers { public class PamhagenPlant : IDisposable { protected PamhagenPlc? Plc; protected bool IsRunning = true; protected Thread? BackgroundThread; public event EventHandler? Update; protected bool ActuatorsChanged = false; protected PamhagenPlc.ActuatorStates Actuators; protected PamhagenPlc.SensorStates Sensors = new(default, default, default, default, [ FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown ], default); public bool IsValveOpen(int n) => !IsValveClosed(n); public bool IsValveClosed(int n) => Sensors.GetDS(n); public bool WantValveClosed(int n) => !WantValveOpen(n); public bool WantValveOpen(int n) => Actuators.GetV(n); public bool AreValvesOpen(params int[] ns) => ns.All(IsValveOpen); public bool AreValvesClosed(params int[] ns) => ns.All(IsValveClosed); public bool IsA1Selected => Sensors.TroughSelector == 1; public bool IsA2Selected => Sensors.TroughSelector == 2; public FillState FillLevelA1 => Sensors.FillingLevels.A1; public FillState FillLevelA2 => Sensors.FillingLevels.A2; public FillState FillLevelPress1 => Sensors.FillingLevels.Press1; public FillState FillLevelPress2 => Sensors.FillingLevels.Press2; 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 WantA1Selected => Actuators.GetV(58); public bool WantA2Selected => !Actuators.GetV(58); public bool IsTroughAugerActive => Actuators.TroughAuger; public bool IsReblerActive => Actuators.Rebler; public bool IsStirrerA1Active => Actuators.StirrerA1; public bool IsStirrerA2Active => Actuators.StirrerA2; public bool IsBeltActive => Actuators.Belt; public bool IsAuger1Active => Actuators.Auger1; public bool IsAuger2Active => Actuators.Auger2; public bool IsWasteDisposalActive => IsBeltActive || IsAuger1Active || IsAuger2Active; 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) { Plc = new(portName); Update += OnUpdate; } protected virtual void RaiseUpdateEvent(PlantEventArgs 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.IsPresseQuerSchneckeActive && !p.IsBeltActive) p.StartBelt(); if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1(); if (p.IsAuger1Active && !p.IsBeltActive) p.StartBelt(); if (p.IsBeltActive && !p.IsAuger2Active) p.StartAuger2(); if (p.IsTroughAugerActive && (!p.IsReblerActive || (p.IsA1Selected && p.FillLevelA1 == FillState.Full) || (p.IsA2Selected && p.FillLevelA2 == FillState.Full))) p.StopTroughAuger(); if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1(); if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2(); 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(); } public async Task StartThread() { if (Plc == null) throw new Exception(); await Plc.TestConnection(); Actuators = await Plc.ReadOutputs(); BackgroundThread = new Thread(new ParameterizedThreadStart(BackgroundLoop)); BackgroundThread.Start(); } public void Dispose() { IsRunning = false; BackgroundThread?.Join(); Plc?.Dispose(); GC.SuppressFinalize(this); } protected async void BackgroundLoop(object? parameters) { while (IsRunning && Plc != null) { try { if (ActuatorsChanged) { await Plc.WriteOutputs(Actuators); ActuatorsChanged = false; } Sensors = await Plc.ReadInputs(); RaiseUpdateEvent(new()); } catch (Exception exc) { var str = "Bei der SPS ist ein Fehler aufgetreten:\n\n" + exc.Message; if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error); if (exc is TimeoutException or IOException) { Plc?.Dispose(); Plc = null; IsRunning = false; } else { await Task.Delay(1000); } } } try { if (Plc != null) await Plc.WriteOutputs(new() { Valves = Actuators.Valves }); } catch (Exception exc) { 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; MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } } public void CommitChanges() { ActuatorsChanged = true; } protected bool HasWTClearanceAA => (AreValvesOpen(12) && AreValvesClosed(15, 16, 20)) || // bypass (AreValvesOpen(15, 18, 16) && AreValvesClosed(11, 12, 14, 17, 19, 20)) || // WT1 (AreValvesOpen(15, 17, 20) && AreValvesClosed(11, 12, 18, 19, 21)) || // WT2 (AreValvesOpen(15, 18, 19, 20) && AreValvesClosed(11, 12, 14, 16, 17, 21)) || // WT1+WT2 false; protected bool HasWTClearanceAB => (AreValvesOpen(15, 18, 14) && AreValvesClosed(11, 12, 13, 16, 17, 19, 21)) || // WT1 (AreValvesOpen(15, 17, 21) && AreValvesClosed(11, 12, 13, 18, 19, 20)) || // WT2 (AreValvesOpen(15, 18, 19, 21) && AreValvesClosed(11, 12, 13, 14, 16, 17, 20)) || // WT1+WT2 false; protected bool HasWTClearanceBA => (AreValvesOpen(11, 18, 16) && AreValvesClosed(15, 12, 13, 14, 17, 19, 20)) || // WT1 (AreValvesOpen(11, 17, 20) && AreValvesClosed(15, 12, 13, 18, 19, 21)) || // WT2 (AreValvesOpen(11, 18, 19, 20) && AreValvesClosed(15, 12, 13, 14, 16, 17, 21)) || // WT1+WT2 false; protected bool HasWTClearanceBB => (AreValvesOpen(13) && AreValvesClosed(11, 14, 21)) || // bypass (AreValvesOpen(11, 18, 14) && AreValvesClosed(15, 13, 16, 17, 19, 21)) || // WT1 (AreValvesOpen(11, 17, 21) && AreValvesClosed(15, 13, 18, 19, 20)) || // WT2 (AreValvesOpen(11, 18, 19, 21) && AreValvesClosed(15, 13, 14, 16, 17, 20)) || // WT1+WT2 false; protected bool HasT1ClearanceA => AreValvesOpen(22) && AreValvesClosed(24, 26, 28); protected bool HasT1ClearanceB => AreValvesOpen(23) && AreValvesClosed(25, 27, 29); protected bool HasT2ClearanceA => AreValvesOpen(24) && AreValvesClosed(22, 26, 28); protected bool HasT2ClearanceB => AreValvesOpen(25) && AreValvesClosed(23, 27, 29); protected bool HasT3ClearanceA => AreValvesOpen(26) && AreValvesClosed(22, 24, 28); protected bool HasT3ClearanceB => AreValvesOpen(27) && AreValvesClosed(23, 25, 29); protected bool HasT4ClearanceA => AreValvesOpen(28, 30) && AreValvesClosed(22, 24, 26, 32, 34); protected bool HasT4ClearanceB => AreValvesOpen(29, 31) && AreValvesClosed(23, 25, 27, 33, 35); protected bool HasT5ClearanceA => AreValvesOpen(28, 32) && AreValvesClosed(22, 24, 26, 30, 34); protected bool HasT5ClearanceB => AreValvesOpen(29, 33) && AreValvesClosed(23, 25, 27, 31, 35); protected bool HasT6ClearanceA => AreValvesOpen(28, 34, 37) && AreValvesClosed(22, 24, 26, 30, 32, 39, 41, 43); 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 => FillLevelA1 != FillState.Empty && ( (MP1HasClearancePress1 && FillLevelPress1 != FillState.Full) || (MP1HasClearancePress2 && FillLevelPress2 != FillState.Full) || (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, 55)) || (AreValvesOpen(4, 8, 52) && AreValvesClosed(1, 2, 7, 56)); protected bool MP1HasClearancePress2 => (AreValvesOpen(1, 6, 55) && AreValvesClosed(3, 4, 5, 51)) || (AreValvesOpen(4, 8, 56) && AreValvesClosed(1, 2, 7, 52)); 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 => FillLevelA2 != FillState.Empty && ( (MP2HasClearancePress1 && FillLevelPress1 != FillState.Full) || (MP2HasClearancePress2 && FillLevelPress2 != FillState.Full) || (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, 56)) || (AreValvesOpen(3, 6, 51) && AreValvesClosed(1, 2, 5, 55)); protected bool MP2HasClearancePress2 => (AreValvesOpen(2, 8, 56) && AreValvesClosed(3, 4, 7, 52)) || (AreValvesOpen(3, 6, 55) && AreValvesClosed(2, 1, 5, 51)); 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 => (FillLevelT1 != FillState.Empty || FillLevelT2 != FillState.Empty) && ( (P12HasClearancePress1 && FillLevelPress1 != FillState.Full) || (P12HasClearancePress2 && FillLevelPress2 != FillState.Full) || (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); protected bool P12HasClearancePress2 => AreValvesOpen(44, 46, 49, 54) && AreValvesClosed(10, 45, 47, 48, 50); 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 => FillLevelT3 != FillState.Empty && ( (P3HasClearancePress1 && FillLevelPress1 != FillState.Full) || (P3HasClearancePress2 && FillLevelPress2 != FillState.Full) || (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, 54); protected bool P3HasClearancePress2 => AreValvesOpen(45, 46, 49, 54) && AreValvesClosed(10, 44, 47, 48, 50); 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 => FillLevelT4 != FillState.Empty && ( (P4HasClearancePress1 && FillLevelPress1 != FillState.Full) || (P4HasClearancePress2 && FillLevelPress2 != FillState.Full) || (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, 54); protected bool P4HasClearancePress2 => AreValvesOpen(47, 49, 54) && AreValvesClosed(46, 48, 50); 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 => FillLevelT4 != FillState.Empty && ( (P5HasClearancePress1 && FillLevelPress1 != FillState.Full) || (P5HasClearancePress2 && FillLevelPress2 != FillState.Full) || (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, 54); protected bool P5HasClearancePress2 => AreValvesOpen(48, 49, 54) && AreValvesClosed(46, 47, 50); 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 => (IsValveOpen(53) && IsValveClosed(57) && FillLevelPress1 != FillState.Full) || (IsValveOpen(57) && IsValveClosed(53) && FillLevelPress2 != FillState.Full); 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); } public void SelectA1() { Actuators.SetV(58, true); //if (IsReblerActive) Actuators.StirrerA1 = true; } public void SelectA2() { Actuators.SetV(58, false); //if (IsReblerActive) Actuators.StirrerA2 = true; } public void StartTroughAuger() { if (!IsReblerActive || !((IsA1Selected && FillLevelA1 != FillState.Full) || (IsA2Selected && FillLevelA2 != FillState.Full))) throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe"); Actuators.TroughAuger = true; } public void StopTroughAuger() { Actuators.TroughAuger = false; } public void StartRebler() { Actuators.Rebler = true; } public void StopRebler() { StopTroughAuger(); Actuators.Rebler = false; } public void StartStirrerA1() { Actuators.StirrerA1 = true; } public void StopStirrerA1() { Actuators.StirrerA1 = false; } public void StartStirrerA2() { Actuators.StirrerA2 = true; } public void StopStirrerA2() { Actuators.StirrerA2 = false; } public void StartBelt() { Actuators.Belt = true; } public void StopBelt() { Actuators.Belt = false; } public void StartAuger1() { Actuators.Auger1 = true; } public void StopAuger1() { Actuators.Auger1 = false; } public void StartAuger2() { Actuators.Auger2 = true; } public void StopAuger2() { Actuators.Auger2 = false; } public void StartWasteDisposal() { StartBelt(); StartAuger1(); StartAuger2(); } public void StopWasteDisposal() { StopBelt(); StopAuger1(); StopAuger2(); } public void StartGradationPump() { Actuators.GradationPump = true; } public void StopGradationPump() { Actuators.GradationPump = false; } public void StartMP1Forward() { if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe"); Actuators.MP1 = MotorState.Forward; } public void StartMP1Backward() { if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe"); Actuators.MP1 = MotorState.Backward; } public void StopMP1() { Actuators.MP1 = MotorState.Halt; } public void StartMP2Forward() { if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe"); Actuators.MP2 = MotorState.Forward; } public void StartMP2Backward() { if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe"); Actuators.MP2 = MotorState.Backward; } public void StopMP2() { Actuators.MP2 = MotorState.Halt; } public void StartP12() { if (!P12HasClearance) throw new NoClearanceException("P1/2 hat keine Freigabe"); Actuators.P12 = MotorState.Forward; } public void StopP12() { Actuators.P12 = MotorState.Halt; } public void StartP3() { if (!P3HasClearance) throw new NoClearanceException("P3 hat keine Freigabe"); Actuators.P3 = MotorState.Forward; } public void StopP3() { Actuators.P3 = MotorState.Halt; } public void StartP4() { if (!P4HasClearance) throw new NoClearanceException("P4 hat keine Freigabe"); Actuators.P4 = MotorState.Forward; } public void StopP4() { Actuators.P4 = MotorState.Halt; } public void StartP5() { if (!P5HasClearance) throw new NoClearanceException("P5 hat keine Freigabe"); Actuators.P5 = MotorState.Forward; } public void StopP5() { Actuators.P5 = MotorState.Halt; } public void StartP6() { if (!P6HasClearance) throw new NoClearanceException("P6 hat keine Freigabe"); Actuators.P6 = MotorState.Forward; } public void StopP6() { Actuators.P6 = MotorState.Halt; } } }