2 Commits
Author SHA1 Message Date
lorenz.stechauner e45c398c68 Update manual control invocation
Test / Run tests (push) Successful in 13s
2026-08-07 12:58:55 +02:00
lorenz.stechauner d3dea3e9a0 Add ability to override clearances 2026-08-07 12:48:51 +02:00
7 changed files with 85 additions and 43 deletions

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@ namespace PamhagenSysCtrl.Helpers {
PlcPort = config["plc:port"] ?? "COM1";
} catch (Exception exc) {
MessageBox.Show($"Die Konfigurationsdatei konnte nicht gelesen werden:\n\n{exc.Message}", "Konfigurationsdatei lesen", MessageBoxButton.OK, MessageBoxImage.Error);
App.Current.Shutdown();
Application.Current.Shutdown();
}
}
}
+2 -2
View File
@@ -386,8 +386,8 @@ namespace PamhagenSysCtrl.Helpers {
CreatePipe(xp5, xp6);
CreatePipe(xp7, xp8);
var zv1 = new CenterValve("ZV1", pr1cX, prY - 40, () => App.Plant?.Press1HasClerance ?? false);
var zv2 = new CenterValve("ZV2", pr2cX, prY - 40, () => App.Plant?.Press2HasClerance ?? false);
var zv1 = new CenterValve("ZV1", pr1cX, prY - 40, () => App.Plant?.Press1HasClearance ?? false);
var zv2 = new CenterValve("ZV2", pr2cX, prY - 40, () => App.Plant?.Press2HasClearance ?? false);
CreatePipe(xp6, zv1, true);
CreatePipe(xp8, zv2, true);
CreateInlet(zv1, press1, true);
+42 -33
View File
@@ -9,6 +9,9 @@ namespace PamhagenSysCtrl.Helpers {
protected bool IsRunning = true;
protected Thread? BackgroundThread;
public bool OverridePathClearances { get; set; }
public bool OverrideDryRunClearances { get; set; }
public event EventHandler<PlantEventArgs>? Update;
protected bool ActuatorsChanged = false;
@@ -30,8 +33,8 @@ namespace PamhagenSysCtrl.Helpers {
public bool IsMW2Selected => Sensors.TroughSelector == 2;
public FillState FillLevelMW1 => Sensors.FillingLevelMW1;
public FillState FillLevelMW2 => Sensors.FillingLevelMW2;
public bool Press1HasClerance => Sensors.ClearancePress1;
public bool Press2HasClerance => Sensors.ClearancePress2;
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];
@@ -210,19 +213,20 @@ namespace PamhagenSysCtrl.Helpers {
(a && ((HasWTClearanceAA && HasT9ClearanceA) || (HasWTClearanceAB && HasT9ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT9ClearanceA) || (HasWTClearanceBB && HasT9ClearanceB)));
public bool MP1HasClearance => FillLevelMW1 != FillState.Empty && (
(MP1HasClearancePress1 && Press1HasClerance) ||
(MP1HasClearancePress2 && Press2HasClerance) ||
(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);
public bool MP1HasClearance => (OverrideDryRunClearances || FillLevelMW1 != FillState.Empty) && (
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));
@@ -237,9 +241,10 @@ namespace PamhagenSysCtrl.Helpers {
set => Actuators.MP1 = (value != MotorState.Halt && value != MotorState.Forward && value != MotorState.Backward) ? throw new ArgumentException("Invalid state for MP1") : value;
}
public bool MP2HasClearance => FillLevelMW2 != FillState.Empty && (
(MP2HasClearancePress1 && Press1HasClerance) ||
(MP2HasClearancePress2 && Press2HasClerance) ||
public bool MP2HasClearance => (OverrideDryRunClearances || FillLevelMW2 != FillState.Empty) && (
OverridePathClearances ||
(MP2HasClearancePress1 && Press1HasClearance) ||
(MP2HasClearancePress2 && Press2HasClearance) ||
(HasClearanceTank1(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
(HasClearanceTank2(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT2 != FillState.Full) ||
(HasClearanceTank3(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT3 != FillState.Full) ||
@@ -264,9 +269,10 @@ namespace PamhagenSysCtrl.Helpers {
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 && Press1HasClerance) ||
(P12HasClearancePress2 && Press2HasClerance) ||
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) ||
@@ -286,9 +292,10 @@ namespace PamhagenSysCtrl.Helpers {
set => Actuators.P12 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P12") : value;
}
public bool P3HasClearance => FillLevelT3 != FillState.Empty && (
(P3HasClearancePress1 && Press1HasClerance) ||
(P3HasClearancePress2 && Press2HasClerance) ||
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) ||
@@ -308,9 +315,10 @@ namespace PamhagenSysCtrl.Helpers {
set => Actuators.P3 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P3") : value;
}
public bool P4HasClearance => FillLevelT4 != FillState.Empty && (
(P4HasClearancePress1 && Press1HasClerance) ||
(P4HasClearancePress2 && Press2HasClerance) ||
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) ||
@@ -330,9 +338,10 @@ namespace PamhagenSysCtrl.Helpers {
set => Actuators.P4 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P4") : value;
}
public bool P5HasClearance => FillLevelT5 != FillState.Empty && (
(P5HasClearancePress1 && Press1HasClerance) ||
(P5HasClearancePress2 && Press2HasClerance) ||
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) ||
@@ -352,9 +361,9 @@ namespace PamhagenSysCtrl.Helpers {
set => Actuators.P5 = (value != MotorState.Halt && value != MotorState.Forward) ? throw new ArgumentException("Invalid state for P5") : value;
}
public bool P6HasClearance =>
(AreValvesOpen(53) && AreValvesClosed(50, 51, 52, 57) && Press1HasClerance) ||
(AreValvesOpen(57) && AreValvesClosed(53, 54, 55, 56) && Press2HasClerance);
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;
@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PamhagenSysCtrl"
mc:Ignorable="d"
Title="Manuelle Steuerung - Anlagensteuerung Pamhagen" Height="550" Width="860">
Title="Handbetrieb - Anlagensteuerung Pamhagen" Height="550" Width="860">
<Grid>
<Grid x:Name="ValvePanel" Margin="5,5,5,5">
</Grid>
@@ -134,8 +134,8 @@ namespace PamhagenSysCtrl {
Füllstände:
Maischewanne 1: {plant.FillLevelMW1} (ausgewählt: {plant.WantMW1Selected}, Status: {plant.IsMWSelected})
Maischewanne 2: {plant.FillLevelMW2} (ausgewählt: {plant.WantMW2Selected}, Status: {plant.IsMW2Selected})
Presse 1: {plant.Press1HasClerance}
Presse 2: {plant.Press2HasClerance}
Presse 1: {plant.Press1HasClearance}
Presse 2: {plant.Press2HasClearance}
Tank 1: {plant.FillLevelT1}
Tank 2: {plant.FillLevelT2}
Tank 3: {plant.FillLevelT3}
+10 -1
View File
@@ -14,11 +14,20 @@
<Menu Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
<MenuItem Header="Einstellungen">
<MenuItem x:Name="Menu_Settings_ManualControl" Header="Manuelle Steuerung" Click="Menu_Settings_ManualControl_Click">
<MenuItem x:Name="Menu_Settings_ManualControl" Header="Handbetrieb"
Click="Menu_Settings_ManualControl_Click" IsCheckable="True">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xF271;"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_Settings_OverridePathClearances" Header="Pfad-Freigaben überbrücken"
Click="Menu_Settings_OverridePathClearances_Click" IsCheckable="True">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE785;"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_Settings_OverrideDryRunClearances" Header="Trockenlauf-Freigaben überbrücken"
Click="Menu_Settings_OverrideDryRunClearances_Click" IsCheckable="True"/>
<Separator/>
<MenuItem x:Name="Menu_Settings_Config" Header="Konfigurationsdatei öffnen..." Click="Menu_Settings_Config_Click">
<MenuItem.Icon>
@@ -22,8 +22,32 @@ namespace PamhagenSysCtrl.Windows {
}
private void Menu_Settings_ManualControl_Click(object sender, RoutedEventArgs evt) {
var w = new ManualControlWindow();
w.Show();
if (Menu_Settings_ManualControl.IsChecked) {
foreach (var win in Application.Current.Windows) {
if (win is ManualControlWindow w) {
w.Focus();
return;
}
}
var ctrl = new ManualControlWindow();
ctrl.Show();
} else {
foreach (var win in Application.Current.Windows) {
if (win is ManualControlWindow w) {
w.Close();
}
}
}
}
private void Menu_Settings_OverridePathClearances_Click(object sender, RoutedEventArgs evt) {
App.Plant?.OverridePathClearances = Menu_Settings_OverridePathClearances.IsChecked;
OnUpdate(null, null);
}
private void Menu_Settings_OverrideDryRunClearances_Click(object sender, RoutedEventArgs evt) {
App.Plant?.OverrideDryRunClearances = Menu_Settings_OverrideDryRunClearances.IsChecked;
OnUpdate(null, null);
}
private void Menu_Settings_Directory_Click(object sender, RoutedEventArgs evt) {
@@ -219,7 +243,7 @@ namespace PamhagenSysCtrl.Windows {
return _hover;
}
public void OnUpdate(object? sender, PlantEventArgs evt) {
public void OnUpdate(object? sender, PlantEventArgs? evt) {
if (sender is not PamhagenPlant plant) return;
UpdateScheme(Mouse.GetPosition(SchemeCanvas), Mouse.LeftButton == MouseButtonState.Pressed);
}