Add config file and refactor windows

This commit is contained in:
2026-08-05 14:16:01 +02:00
parent d9c1b79563
commit db5702c0a7
12 changed files with 562 additions and 344 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PamhagenSysCtrl" xmlns:local="clr-namespace:PamhagenSysCtrl"
StartupUri="Windows/MainWindow.xaml" StartupUri="Windows/PlantSchemeWindow.xaml"
Exit="Application_Exit"> Exit="Application_Exit">
<Application.Resources> <Application.Resources>
</Application.Resources> </Application.Resources>
+31 -1
View File
@@ -1,4 +1,6 @@
using PamhagenSysCtrl.Helpers; using PamhagenSysCtrl.Helpers;
using System.IO;
using System.Reflection;
using System.Windows; using System.Windows;
using System.Windows.Threading; using System.Windows.Threading;
@@ -6,14 +8,42 @@ namespace PamhagenSysCtrl {
public partial class App : Application { public partial class App : Application {
public static PamhagenPlant? Plant; public static PamhagenPlant? Plant;
public static Dispatcher MainDispatcher; public static Dispatcher? MainDispatcher;
public static readonly string DataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Anlagensteuerung Pamhagen");
public static readonly string ConfigPath = Path.Combine(DataPath, "config.ini");
public static readonly string InstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Anlagensteuerung Pamhagen");
public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Anlagensteuerung Pamhagen");
public static Config Config { get; private set; } = new(ConfigPath);
public static Version Version { get; private set; } = new();
public App() : public App() :
base() { base() {
Directory.CreateDirectory(TempPath);
Directory.CreateDirectory(DataPath);
MainDispatcher = Dispatcher; MainDispatcher = Dispatcher;
var args = Environment.GetCommandLineArgs();
if (args.Length >= 2) {
Config = new(Path.GetFullPath(args[1]));
}
} }
protected override async void OnStartup(StartupEventArgs evt) { protected override async void OnStartup(StartupEventArgs evt) {
Version = new Version(typeof(App).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion.Split('+')[0] ?? "0.0.0");
try {
Plant = new(Config.PlcPort);
await Plant.StartThread();
} catch (Exception exc) {
Plant?.Dispose();
Plant = null;
var str = $"Beim Aufbauen einer Verbindung zur SPS ist ein Fehler aufgetreten:\n\n{exc.GetType().Name}: {exc.Message}";
if (exc.InnerException != null) str += $"\n\n{exc.InnerException.GetType().Name}: {exc.InnerException.Message}";
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
base.OnStartup(evt); base.OnStartup(evt);
} }
+28
View File
@@ -0,0 +1,28 @@
using Microsoft.Extensions.Configuration;
using System.Windows;
namespace PamhagenSysCtrl.Helpers {
public class Config {
private static readonly string[] TrueValues = ["1", "true", "yes", "on"];
private readonly string FileName;
public string PlcPort = "COM1";
public Config(string filename) {
FileName = filename;
Read();
}
public void Read() {
try {
var config = new ConfigurationBuilder().AddIniFile(FileName).Build();
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();
}
}
}
}
+3 -3
View File
@@ -60,11 +60,11 @@ namespace PamhagenSysCtrl.Helpers {
Nodes.Add(Auger2); Nodes.Add(Auger2);
var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 200, () => App.Plant?.IsReblerActive ?? false); var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 200, () => App.Plant?.IsReblerActive ?? false);
Nodes.Add(rebler); Nodes.Add(rebler);
var switcher = new Switcher("", (mw1X + mw2X) / 2, 260, () => App.Plant?.TroughSelector ?? 0, () => App.Plant == null ? 0 : App.Plant.WantA1Selected ? 1 : 2); var switcher = new Switcher("", (mw1X + mw2X) / 2, 260, () => App.Plant?.TroughSelector ?? 0, () => App.Plant == null ? 0 : App.Plant.WantMW1Selected ? 1 : 2);
Nodes.Add(switcher); Nodes.Add(switcher);
MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelA1 ?? FillState.Unknown); MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelMW1 ?? FillState.Unknown);
MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelA2 ?? FillState.Unknown); MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelMW2 ?? FillState.Unknown);
MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.IsMP1Active ?? false, () => App.Plant?.MP1HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.IsMP1Active ?? false, () => App.Plant?.MP1HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.IsMP2Active ?? false, () => App.Plant?.MP2HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x))); MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.IsMP2Active ?? false, () => App.Plant?.MP2HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
var x1 = new PipeJoin(mw1X, mpY + 40); var x1 = new PipeJoin(mw1X, mpY + 40);
+27 -27
View File
@@ -22,14 +22,14 @@ namespace PamhagenSysCtrl.Helpers {
public bool WantValveClosed(int n) => !WantValveOpen(n); public bool WantValveClosed(int n) => !WantValveOpen(n);
public bool WantValveOpen(int n) => Actuators.GetV(n); public bool WantValveOpen(int n) => Actuators.GetV(n);
public bool AreValvesOpen(params int[] ns) => ns.All(IsValveOpen); public bool AreValvesOpen(params int[] ns) => ns.All(IsValveOpen) && ns.All(WantValveOpen);
public bool AreValvesClosed(params int[] ns) => ns.All(IsValveClosed); public bool AreValvesClosed(params int[] ns) => ns.All(IsValveClosed) && ns.All(WantValveClosed);
public int TroughSelector => Sensors.TroughSelector; public int TroughSelector => Sensors.TroughSelector;
public bool IsA1Selected => Sensors.TroughSelector == 1; public bool IsMWSelected => Sensors.TroughSelector == 1;
public bool IsA2Selected => Sensors.TroughSelector == 2; public bool IsMW2Selected => Sensors.TroughSelector == 2;
public FillState FillLevelA1 => Sensors.FillingLevels.A1; public FillState FillLevelMW1 => Sensors.FillingLevels.MW1;
public FillState FillLevelA2 => Sensors.FillingLevels.A2; public FillState FillLevelMW2 => Sensors.FillingLevels.MW2;
public FillState FillLevelPress1 => Sensors.FillingLevels.Press1; public FillState FillLevelPress1 => Sensors.FillingLevels.Press1;
public FillState FillLevelPress2 => Sensors.FillingLevels.Press2; public FillState FillLevelPress2 => Sensors.FillingLevels.Press2;
public FillState FillLevelT1 => Sensors.FillingLevelTanks[0]; public FillState FillLevelT1 => Sensors.FillingLevelTanks[0];
@@ -46,13 +46,13 @@ namespace PamhagenSysCtrl.Helpers {
public MotorState PresseQuerSchnecke => Sensors.PresseQuerSchnecke; public MotorState PresseQuerSchnecke => Sensors.PresseQuerSchnecke;
public bool IsPresseQuerSchneckeActive => PresseQuerSchnecke == MotorState.Forward; public bool IsPresseQuerSchneckeActive => PresseQuerSchnecke == MotorState.Forward;
public bool WantA1Selected => Actuators.GetV(58); public bool WantMW1Selected => Actuators.GetV(58);
public bool WantA2Selected => !Actuators.GetV(58); public bool WantMW2Selected => !Actuators.GetV(58);
public bool IsTroughAugerActive => Actuators.TroughAuger; public bool IsTroughAugerActive => Actuators.TroughAuger;
public bool IsReblerActive => Actuators.Rebler; public bool IsReblerActive => Actuators.Rebler;
public bool IsStirrerA1Active => Actuators.StirrerA1; public bool IsStirrerMW1Active => Actuators.StirrerMW1;
public bool IsStirrerA2Active => Actuators.StirrerA2; public bool IsStirrerMW2Active => Actuators.StirrerMW2;
public bool IsBeltActive => Actuators.Belt; public bool IsBeltActive => Actuators.Belt;
public bool IsAuger1Active => Actuators.Auger1; public bool IsAuger1Active => Actuators.Auger1;
public bool IsAuger2Active => Actuators.Auger2; public bool IsAuger2Active => Actuators.Auger2;
@@ -73,7 +73,7 @@ namespace PamhagenSysCtrl.Helpers {
} }
protected virtual void RaiseUpdateEvent(PlantEventArgs evt) { protected virtual void RaiseUpdateEvent(PlantEventArgs evt) {
App.MainDispatcher.BeginInvoke(() => Update?.Invoke(this, evt)); App.MainDispatcher?.BeginInvoke(() => Update?.Invoke(this, evt));
} }
protected static void OnUpdate(object? sender, PlantEventArgs evt) { protected static void OnUpdate(object? sender, PlantEventArgs evt) {
@@ -82,7 +82,7 @@ namespace PamhagenSysCtrl.Helpers {
if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1(); if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1();
if (p.IsAuger1Active && !p.IsBeltActive) p.StartBelt(); if (p.IsAuger1Active && !p.IsBeltActive) p.StartBelt();
if (p.IsBeltActive && !p.IsAuger2Active) p.StartAuger2(); if (p.IsBeltActive && !p.IsAuger2Active) p.StartAuger2();
if (p.IsTroughAugerActive && (!p.IsReblerActive || (p.IsA1Selected && p.FillLevelA1 == FillState.Full) || (p.IsA2Selected && p.FillLevelA2 == FillState.Full))) if (p.IsTroughAugerActive && (!p.IsReblerActive || (p.IsMWSelected && p.FillLevelMW1 == FillState.Full) || (p.IsMW2Selected && p.FillLevelMW2 == FillState.Full)))
p.StopTroughAuger(); p.StopTroughAuger();
if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1(); if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1();
if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2(); if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2();
@@ -210,7 +210,7 @@ namespace PamhagenSysCtrl.Helpers {
(a && ((HasWTClearanceAA && HasT9ClearanceA) || (HasWTClearanceAB && HasT9ClearanceB))) || (a && ((HasWTClearanceAA && HasT9ClearanceA) || (HasWTClearanceAB && HasT9ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT9ClearanceA) || (HasWTClearanceBB && HasT9ClearanceB))); (b && ((HasWTClearanceBA && HasT9ClearanceA) || (HasWTClearanceBB && HasT9ClearanceB)));
public bool MP1HasClearance => FillLevelA1 != FillState.Empty && ( public bool MP1HasClearance => FillLevelMW1 != FillState.Empty && (
(MP1HasClearancePress1 && FillLevelPress1 != FillState.Full) || (MP1HasClearancePress1 && FillLevelPress1 != FillState.Full) ||
(MP1HasClearancePress2 && FillLevelPress2 != FillState.Full) || (MP1HasClearancePress2 && FillLevelPress2 != FillState.Full) ||
(HasClearanceTank1(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT1 != FillState.Full) || (HasClearanceTank1(MP1HasClearanceTanksA, MP1HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
@@ -237,7 +237,7 @@ namespace PamhagenSysCtrl.Helpers {
set => Actuators.MP1 = (value != MotorState.Halt && value != MotorState.Forward && value != MotorState.Backward) ? throw new ArgumentException("Invalid state for MP1") : value; 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 && ( public bool MP2HasClearance => FillLevelMW2 != FillState.Empty && (
(MP2HasClearancePress1 && FillLevelPress1 != FillState.Full) || (MP2HasClearancePress1 && FillLevelPress1 != FillState.Full) ||
(MP2HasClearancePress2 && FillLevelPress2 != FillState.Full) || (MP2HasClearancePress2 && FillLevelPress2 != FillState.Full) ||
(HasClearanceTank1(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT1 != FillState.Full) || (HasClearanceTank1(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
@@ -371,20 +371,20 @@ namespace PamhagenSysCtrl.Helpers {
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void SelectA1() { public void SelectMW1() {
Actuators.SetV(58, true); Actuators.SetV(58, true);
//if (IsReblerActive) Actuators.StirrerA1 = true; //if (IsReblerActive) Actuators.StirrerMW1 = true;
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void SelectA2() { public void SelectMW2() {
Actuators.SetV(58, false); Actuators.SetV(58, false);
//if (IsReblerActive) Actuators.StirrerA2 = true; //if (IsReblerActive) Actuators.StirrerMW2 = true;
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void StartTroughAuger() { public void StartTroughAuger() {
if (!IsReblerActive || (IsA1Selected && FillLevelA1 == FillState.Full) || (IsA2Selected && FillLevelA2 == FillState.Full)) if (!IsReblerActive || (IsMWSelected && FillLevelMW1 == FillState.Full) || (IsMW2Selected && FillLevelMW2 == FillState.Full))
throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe"); throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe");
Actuators.TroughAuger = true; Actuators.TroughAuger = true;
ActuatorsChanged = true; ActuatorsChanged = true;
@@ -407,23 +407,23 @@ namespace PamhagenSysCtrl.Helpers {
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void StartStirrerA1() { public void StartStirrerMW1() {
Actuators.StirrerA1 = true; Actuators.StirrerMW1 = true;
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void StopStirrerA1() { public void StopStirrerMW1() {
Actuators.StirrerA1 = false; Actuators.StirrerMW1 = false;
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void StartStirrerA2() { public void StartStirrerMW2() {
Actuators.StirrerA2 = true; Actuators.StirrerMW2 = true;
ActuatorsChanged = true; ActuatorsChanged = true;
} }
public void StopStirrerA2() { public void StopStirrerMW2() {
Actuators.StirrerA2 = false; Actuators.StirrerMW2 = false;
ActuatorsChanged = true; ActuatorsChanged = true;
} }
+10 -10
View File
@@ -5,7 +5,7 @@ namespace PamhagenSysCtrl.Helpers {
public record struct SensorStates( public record struct SensorStates(
long PressureSensors, long PressureSensors,
(FillState A1, FillState A2, FillState Press1, FillState Press2) FillingLevels, (FillState MW1, FillState MW2, FillState Press1, FillState Press2) FillingLevels,
int TroughSelector, int TroughSelector,
double GradationOe, double GradationOe,
FillState[] FillingLevelTanks, FillState[] FillingLevelTanks,
@@ -17,7 +17,7 @@ namespace PamhagenSysCtrl.Helpers {
public record struct ActuatorStates( public record struct ActuatorStates(
long Valves, long Valves,
MotorState MP1, MotorState MP2, MotorState P12, MotorState P3, MotorState P4, MotorState P5, MotorState P6, MotorState MP1, MotorState MP2, MotorState P12, MotorState P3, MotorState P4, MotorState P5, MotorState P6,
bool TroughAuger, bool Rebler, bool StirrerA1, bool StirrerA2, bool Belt, bool Auger1, bool Auger2, bool GradationPump bool TroughAuger, bool Rebler, bool StirrerMW1, bool StirrerMW2, bool Belt, bool Auger1, bool Auger2, bool GradationPump
) { ) {
public readonly bool GetV(int n) => (Valves & (1L << (n - 1))) != 0; public readonly bool GetV(int n) => (Valves & (1L << (n - 1))) != 0;
public void SetV(int n, bool val) { public void SetV(int n, bool val) {
@@ -107,11 +107,11 @@ namespace PamhagenSysCtrl.Helpers {
long pressure = (long)r1 | ((long)r2 << 16) | ((long)r3 << 32) | ((long)r4 << 48); long pressure = (long)r1 | ((long)r2 << 16) | ((long)r3 << 32) | ((long)r4 << 48);
pressure = (pressure & 0x01FFFFFFFFFFFFFF) | ((pressure & 0x0600000000000000) << 1); pressure = (pressure & 0x01FFFFFFFFFFFFFF) | ((pressure & 0x0600000000000000) << 1);
var a1 = Int3ToFillState((f1 ) & 0x7); // 111 011 001 000 var mw1 = Int3ToFillState((f1 ) & 0x7); // 111 011 001 000
var a2 = Int3ToFillState((f1 >> 3) & 0x7); // 111 011 001 000 var mw2 = Int3ToFillState((f1 >> 3) & 0x7); // 111 011 001 000
var p1 = Int1ToFillState((f1 >> 6) & 0x1); // 1 0 var p1 = Int1ToFillState((f1 >> 6) & 0x1); // 1 0
var p2 = Int1ToFillState((f1 >> 7) & 0x1); // 1 0 var p2 = Int1ToFillState((f1 >> 7) & 0x1); // 1 0
var wp = ((f1 >> 8) & 0x3); // 10 01 var wp = ((f1 >> 8) & 0x3); // 10 01
// Masseligerät : 4mA => 50 Oe // Masseligerät : 4mA => 50 Oe
// 20mA => 150 Oe // 20mA => 150 Oe
@@ -137,7 +137,7 @@ namespace PamhagenSysCtrl.Helpers {
var t9 = Int1ToFillState((f2 >> 13) & 0x1); // 1 0 var t9 = Int1ToFillState((f2 >> 13) & 0x1); // 1 0
var q1 = Int1ToPumpState((f2 >> 15) & 0x1); // 1 0 var q1 = Int1ToPumpState((f2 >> 15) & 0x1); // 1 0
return new SensorStates(pressure, (a1, a2, p1, p2), wp == 3 ? -1 : wp == 1 ? 2 : wp == 2 ? 1 : 0, oe, [t1, t2, t3, t4, t5, t6, t7, t8, t9], q1); return new SensorStates(pressure, (mw1, mw2, p1, p2), wp == 3 ? -1 : wp == 1 ? 2 : wp == 2 ? 1 : 0, oe, [t1, t2, t3, t4, t5, t6, t7, t8, t9], q1);
} }
protected async Task<(ushort RW000, ushort RW001, ushort RW002, ushort RW003, ushort RW004, ushort RW005, ushort RW006)> ReadOutputRegisters() { protected async Task<(ushort RW000, ushort RW001, ushort RW002, ushort RW003, ushort RW004, ushort RW005, ushort RW006)> ReadOutputRegisters() {
@@ -210,8 +210,8 @@ namespace PamhagenSysCtrl.Helpers {
(state.TroughAuger ? 0x01 : 0x00) | (state.TroughAuger ? 0x01 : 0x00) |
(state.Rebler ? 0x02 : 0x00) | (state.Rebler ? 0x02 : 0x00) |
(state.GetV(58) ? 0x04 : 0x00) | (state.GetV(58) ? 0x04 : 0x00) |
(state.StirrerA1 ? 0x08 : 0x00) | (state.StirrerMW1 ? 0x08 : 0x00) |
(state.StirrerA2 ? 0x10 : 0x00) | (state.StirrerMW2 ? 0x10 : 0x00) |
(state.Belt ? 0x20 : 0x00) | (state.Belt ? 0x20 : 0x00) |
(state.Auger1 ? 0x40 : 0x00) | (state.Auger1 ? 0x40 : 0x00) |
(state.Auger2 ? 0x80 : 0x00); (state.Auger2 ? 0x80 : 0x00);
+2 -1
View File
@@ -11,7 +11,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.IO.Ports" Version="10.0.9" /> <PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.10" />
<PackageReference Include="System.IO.Ports" Version="10.0.10" />
</ItemGroup> </ItemGroup>
</Project> </Project>
-268
View File
@@ -1,268 +0,0 @@
using PamhagenSysCtrl.Helpers;
using PamhagenSysCtrl.Windows;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace PamhagenSysCtrl {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
for (int i = 1; i <= 60; i++) {
var b = new Button() {
Content = $"V{i}",
Margin = new(10 + ((i - 1) / 10) * 50, 10 + ((i - 1) % 10) * 40, 10, 10),
BorderThickness = new(2),
FontWeight = FontWeights.Bold,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Height = 30,
Width = 40,
FontSize = 14,
};
var borderStyle = new Style(typeof(Border));
borderStyle.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(5)));
b.Resources.Add(typeof(Border), borderStyle);
b.Click += (sender, evt) => {
if (App.Plant == null || sender is not Button b) return;
var i = int.Parse($"{b.Content}"[1..]);
if (i == 58) {
if (App.Plant.WantA1Selected) {
App.Plant.SelectA2();
} else {
App.Plant.SelectA1();
}
} else if (i > 57) {
return;
} else if (App.Plant.WantValveOpen(i)) {
App.Plant.CloseV(i);
} else {
App.Plant.OpenV(i);
}
};
ValvePanel.Children.Add(b);
}
var w = new PlantSchemeWindow();
w.Show();
}
public async void ConnectButton_Click(object? sender, RoutedEventArgs evt) {
try {
App.Plant = new(PortInput.Text);
App.Plant.Update += OnUpdate;
await App.Plant.StartThread();
} catch (Exception exc) {
App.Plant?.Dispose();
App.Plant = null;
var str = $"Beim Aufbauen einer Verbindung zur SPS ist ein Fehler aufgetreten:\n\n{exc.GetType().Name}: {exc.Message}";
if (exc.InnerException != null) str += $"\n\n{exc.InnerException.GetType().Name}: {exc.InnerException.Message}";
MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
public void OnUpdate(object? sender, PlantEventArgs evt) {
if (sender is not PamhagenPlant plant) return;
for (int i = 1; i <= 60; i++) {
var target = plant.WantValveClosed(i);
var actual = plant.IsValveClosed(i);
if (ValvePanel.Children[i - 1] is not Button b)
continue;
b.BorderBrush = target ? Brushes.DarkRed : Brushes.SlateGray;
b.Foreground = target ? Brushes.DarkRed : Brushes.Black;
b.Background = actual ? Brushes.MistyRose : Brushes.WhiteSmoke;
}
ReblerButton.BorderBrush = plant.IsReblerActive ? Brushes.DarkGreen : Brushes.DarkRed;
ReblerButton.Foreground = plant.IsReblerActive ? Brushes.DarkGreen : Brushes.DarkRed;
ReblerButton.Background = plant.IsReblerActive ? Brushes.MintCream: Brushes.MistyRose;
TroughAugerButton.BorderBrush = plant.IsTroughAugerActive ? Brushes.DarkGreen : Brushes.DarkRed;
TroughAugerButton.Foreground = plant.IsTroughAugerActive ? Brushes.DarkGreen : Brushes.DarkRed;
TroughAugerButton.Background = plant.IsTroughAugerActive ? Brushes.MintCream : Brushes.MistyRose;
StirrerA1Button.BorderBrush = plant.IsStirrerA1Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerA1Button.Foreground = plant.IsStirrerA1Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerA1Button.Background = plant.IsStirrerA1Active ? Brushes.MintCream : Brushes.MistyRose;
StirrerA2Button.BorderBrush = plant.IsStirrerA2Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerA2Button.Foreground = plant.IsStirrerA2Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerA2Button.Background = plant.IsStirrerA2Active ? Brushes.MintCream : Brushes.MistyRose;
BeltButton.BorderBrush = plant.IsBeltActive ? Brushes.DarkGreen : Brushes.DarkRed;
BeltButton.Foreground = plant.IsBeltActive ? Brushes.DarkGreen : Brushes.DarkRed;
BeltButton.Background = plant.IsBeltActive ? Brushes.MintCream : Brushes.MistyRose;
Auger1Button.BorderBrush = plant.IsAuger1Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger1Button.Foreground = plant.IsAuger1Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger1Button.Background = plant.IsAuger1Active ? Brushes.MintCream : Brushes.MistyRose;
Auger2Button.BorderBrush = plant.IsAuger2Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger2Button.Foreground = plant.IsAuger2Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger2Button.Background = plant.IsAuger2Active ? Brushes.MintCream : Brushes.MistyRose;
GradationPumpButton.BorderBrush = plant.IsGradationPumpActive ? Brushes.DarkGreen : Brushes.DarkRed;
GradationPumpButton.Foreground = plant.IsGradationPumpActive ? Brushes.DarkGreen : Brushes.DarkRed;
GradationPumpButton.Background = plant.IsGradationPumpActive ? Brushes.MintCream : Brushes.MistyRose;
MP1BackwardButton.BorderBrush = plant.MP1 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1BackwardButton.Foreground = plant.MP1 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1BackwardButton.Background = plant.MP1 == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke;
MP1HaltButton.BorderBrush = plant.MP1 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP1HaltButton.Foreground = plant.MP1 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP1HaltButton.Background = plant.MP1 == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke;
MP1ForwardButton.BorderBrush = plant.MP1 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1ForwardButton.Foreground = plant.MP1 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1ForwardButton.Background = plant.MP1 == MotorState.Forward ? Brushes.MintCream: Brushes.WhiteSmoke;
MP2BackwardButton.BorderBrush = plant.MP2 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2BackwardButton.Foreground = plant.MP2 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2BackwardButton.Background = plant.MP2 == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke;
MP2HaltButton.BorderBrush = plant.MP2 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP2HaltButton.Foreground = plant.MP2 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP2HaltButton.Background = plant.MP2 == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke;
MP2ForwardButton.BorderBrush = plant.MP2 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2ForwardButton.Foreground = plant.MP2 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2ForwardButton.Background = plant.MP2 == MotorState.Forward ? Brushes.MintCream : Brushes.WhiteSmoke;
P12Button.BorderBrush = plant.P12 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P12Button.Foreground = plant.P12 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P12Button.Background = plant.P12 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
Status.Text = $"""
Gradation °Oe: {plant.GradationOe:N2}
Presse Querschnecke: {plant.PresseQuerSchnecke}
Füllstände:
Wanne A1: {plant.FillLevelA1} (ausgewählt: {plant.WantA1Selected}, Status: {plant.IsA1Selected})
Wanne A2: {plant.FillLevelA2} (ausgewählt: {plant.WantA2Selected}, Status: {plant.IsA2Selected})
Presse 1: {plant.FillLevelPress1}
Presse 2: {plant.FillLevelPress2}
Tank 1: {plant.FillLevelT1}
Tank 2: {plant.FillLevelT2}
Tank 3: {plant.FillLevelT3}
Tank 4: {plant.FillLevelT4}
Tank 5: {plant.FillLevelT5}
Tank 6: {plant.FillLevelT6}
Tank 7: {plant.FillLevelT7}
Tank 8: {plant.FillLevelT8}
Tank 9: {plant.FillLevelT9}
""";
}
private void TroughAugerButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsTroughAugerActive) {
App.Plant.StopTroughAuger();
} else {
App.Plant.StartTroughAuger();
}
}
private void ReblerButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsReblerActive) {
App.Plant.StopRebler();
} else {
App.Plant.StartRebler();
}
}
private void StirrerA1Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsStirrerA1Active) {
App.Plant.StopStirrerA1();
} else {
App.Plant.StartStirrerA1();
}
}
private void StirrerA2Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsStirrerA2Active) {
App.Plant.StopStirrerA2();
} else {
App.Plant.StartStirrerA2();
}
}
private void BeltButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsBeltActive) {
App.Plant.StopBelt();
} else {
App.Plant.StartBelt();
}
}
private void Auger1Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsAuger1Active) {
App.Plant.StopAuger1();
} else {
App.Plant.StartAuger1();
}
}
private void Auger2Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsAuger2Active) {
App.Plant.StopAuger2();
} else {
App.Plant.StartAuger2();
}
}
private void GradationPumpButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.IsGradationPumpActive) {
App.Plant.StopGradationPump();
} else {
App.Plant.StartGradationPump();
}
}
private void MP1BackwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
App.Plant.StartMP1Backward();
}
private void MP1HaltButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
App.Plant.StopMP1();
}
private void MP1ForwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
App.Plant.StartMP1Forward();
}
private void MP2BackwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
App.Plant.StartMP2Backward();
}
private void MP2HaltButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
App.Plant.StopMP2();
}
private void MP2ForwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
App.Plant.StartMP2Forward();
}
private void P12Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
if (App.Plant.P12 == MotorState.Forward) {
App.Plant.StopP12();
} else {
App.Plant.StartP12();
}
}
}
}
@@ -1,19 +1,13 @@
<Window x:Class="PamhagenSysCtrl.MainWindow" <Window x:Class="PamhagenSysCtrl.ManualControlWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PamhagenSysCtrl" xmlns:local="clr-namespace:PamhagenSysCtrl"
mc:Ignorable="d" mc:Ignorable="d"
Title="MainWindow" Height="550" Width="860"> Title="Manuelle Steuerung - Anlagensteuerung Pamhagen" Height="550" Width="860">
<Grid> <Grid>
<TextBox x:Name="PortInput" Text="COM1" <Grid x:Name="ValvePanel" Margin="5,5,5,5">
Margin="10,10,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Height="25" Width="80" FontSize="14" Padding="2,2,2,2"/>
<Button x:Name="ConnectButton" Content="Verbinden"
Margin="100,10,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Height="25" Width="80" FontSize="14"
Click="ConnectButton_Click"/>
<Grid x:Name="ValvePanel" Margin="5,50,5,5">
</Grid> </Grid>
<TextBlock x:Name="Status" FontSize="14" <TextBlock x:Name="Status" FontSize="14"
@@ -31,36 +25,33 @@
Margin="10,45,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,45,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="ReblerButton_Click"/> Click="ReblerButton_Click"/>
<Button x:Name="StirrerA1Button" Content="Rührer A1" Padding="2" Height="30" Width="120" <Button x:Name="StirrerMW1Button" Content="Rührer MW1" Padding="2" Height="30" Width="120"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="10,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="StirrerA1Button_Click"/> Click="StirrerMW1Button_Click"/>
<Button x:Name="StirrerA2Button" Content="Rührer A2" Padding="2" Height="30" Width="120" <Button x:Name="StirrerMW2Button" Content="Rührer MW2" Padding="2" Height="30" Width="120"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="10,115,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,115,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="StirrerA2Button_Click"/> Click="StirrerMW2Button_Click"/>
<Button x:Name="BeltButton" Content="Förderband" Padding="2" Height="30" Width="150"
FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="135,10,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="BeltButton_Click"/>
<Button x:Name="Auger1Button" Content="Förderschnecke 1" Padding="2" Height="30" Width="150" <Button x:Name="Auger1Button" Content="Förderschnecke 1" Padding="2" Height="30" Width="150"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="135,45,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="135,10,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="Auger1Button_Click"/> Click="Auger1Button_Click"/>
<Button x:Name="BeltButton" Content="Förderband" Padding="2" Height="30" Width="150"
FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="135,45,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="BeltButton_Click"/>
<Button x:Name="Auger2Button" Content="Förderschnecke 2" Padding="2" Height="30" Width="150" <Button x:Name="Auger2Button" Content="Förderschnecke 2" Padding="2" Height="30" Width="150"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="135,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="135,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="Auger2Button_Click"/> Click="Auger2Button_Click"/>
<Button x:Name="GradationPumpButton" Content="Gradationspumpe" Padding="2" Height="30" Width="150" <Button x:Name="P6Button" Content="Pumpe 6" Padding="2" Height="30" Width="150"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="135,115,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="135,115,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="GradationPumpButton_Click"/> Click="P6Button_Click"/>
<Button x:Name="MP1BackwardButton" Content="Zurück" Padding="2" Height="30" Width="60" <Button x:Name="MP1BackwardButton" Content="Zurück" Padding="2" Height="30" Width="60"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="290,10,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="290,10,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
@@ -87,10 +78,22 @@
Margin="410,45,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="410,45,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="MP2ForwardButton_Click"/> Click="MP2ForwardButton_Click"/>
<Button x:Name="P12Button" Content="Pumpe 1/2" Padding="2" Height="30" Width="180" <Button x:Name="P12Button" Content="Pumpe 1/2" Padding="2" Height="30" Width="87.5"
FontSize="14" BorderThickness="2" FontWeight="Bold" FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="290,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="290,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="P12Button_Click"/> Click="P12Button_Click"/>
<Button x:Name="P3Button" Content="Pumpe 3" Padding="2" Height="30" Width="87.5"
FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="382.5,80,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="P3Button_Click"/>
<Button x:Name="P4Button" Content="Pumpe 4" Padding="2" Height="30" Width="87.5"
FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="290,115,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="P4Button_Click"/>
<Button x:Name="P5Button" Content="Pumpe 5" Padding="2" Height="30" Width="87.5"
FontSize="14" BorderThickness="2" FontWeight="Bold"
Margin="382.5,115,10,10" VerticalAlignment="Top" HorizontalAlignment="Left"
Click="P5Button_Click"/>
</Grid> </Grid>
</Grid> </Grid>
</Window> </Window>
@@ -0,0 +1,362 @@
using PamhagenSysCtrl.Helpers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace PamhagenSysCtrl {
public partial class ManualControlWindow : Window {
public ManualControlWindow() {
InitializeComponent();
for (int i = 1; i <= 58; i++) {
var b = new Button() {
Content = $"V{i}",
Margin = new(10 + ((i - 1) / 10) * 50, 10 + ((i - 1) % 10) * 40, 10, 10),
BorderThickness = new(2),
FontWeight = FontWeights.Bold,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Height = 30,
Width = 40,
FontSize = 14,
};
var borderStyle = new Style(typeof(Border));
borderStyle.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(5)));
b.Resources.Add(typeof(Border), borderStyle);
b.Click += (sender, evt) => {
if (App.Plant == null || sender is not Button b) return;
var i = int.Parse($"{b.Content}"[1..]);
if (i == 58) {
if (App.Plant.WantMW1Selected) {
App.Plant.SelectMW2();
} else {
App.Plant.SelectMW1();
}
} else if (i > 57) {
return;
} else if (App.Plant.WantValveOpen(i)) {
App.Plant.CloseV(i);
} else {
App.Plant.OpenV(i);
}
};
ValvePanel.Children.Add(b);
}
App.Plant?.Update += OnUpdate;
}
public void OnUpdate(object? sender, PlantEventArgs evt) {
if (sender is not PamhagenPlant plant) return;
for (int i = 1; i <= 58; i++) {
var target = plant.WantValveClosed(i);
var actual = plant.IsValveClosed(i);
if (ValvePanel.Children[i - 1] is not Button b)
continue;
b.BorderBrush = target ? Brushes.DarkRed : Brushes.DarkGreen;
b.Foreground = target ? Brushes.DarkRed : Brushes.DarkGreen;
b.Background = actual ? Brushes.MistyRose : Brushes.MintCream;
}
ReblerButton.BorderBrush = plant.IsReblerActive ? Brushes.DarkGreen : Brushes.DarkRed;
ReblerButton.Foreground = plant.IsReblerActive ? Brushes.DarkGreen : Brushes.DarkRed;
ReblerButton.Background = plant.IsReblerActive ? Brushes.MintCream: Brushes.MistyRose;
TroughAugerButton.BorderBrush = plant.IsTroughAugerActive ? Brushes.DarkGreen : Brushes.DarkRed;
TroughAugerButton.Foreground = plant.IsTroughAugerActive ? Brushes.DarkGreen : Brushes.DarkRed;
TroughAugerButton.Background = plant.IsTroughAugerActive ? Brushes.MintCream : Brushes.MistyRose;
StirrerMW1Button.BorderBrush = plant.IsStirrerMW1Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW1Button.Foreground = plant.IsStirrerMW1Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW1Button.Background = plant.IsStirrerMW1Active ? Brushes.MintCream : Brushes.MistyRose;
StirrerMW2Button.BorderBrush = plant.IsStirrerMW2Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW2Button.Foreground = plant.IsStirrerMW2Active ? Brushes.DarkGreen : Brushes.DarkRed;
StirrerMW2Button.Background = plant.IsStirrerMW2Active ? Brushes.MintCream : Brushes.MistyRose;
BeltButton.BorderBrush = plant.IsBeltActive ? Brushes.DarkGreen : Brushes.DarkRed;
BeltButton.Foreground = plant.IsBeltActive ? Brushes.DarkGreen : Brushes.DarkRed;
BeltButton.Background = plant.IsBeltActive ? Brushes.MintCream : Brushes.MistyRose;
Auger1Button.BorderBrush = plant.IsAuger1Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger1Button.Foreground = plant.IsAuger1Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger1Button.Background = plant.IsAuger1Active ? Brushes.MintCream : Brushes.MistyRose;
Auger2Button.BorderBrush = plant.IsAuger2Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger2Button.Foreground = plant.IsAuger2Active ? Brushes.DarkGreen : Brushes.DarkRed;
Auger2Button.Background = plant.IsAuger2Active ? Brushes.MintCream : Brushes.MistyRose;
MP1BackwardButton.BorderBrush = plant.MP1 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1BackwardButton.Foreground = plant.MP1 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1BackwardButton.Background = plant.MP1 == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke;
MP1HaltButton.BorderBrush = plant.MP1 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP1HaltButton.Foreground = plant.MP1 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP1HaltButton.Background = plant.MP1 == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke;
MP1ForwardButton.BorderBrush = plant.MP1 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1ForwardButton.Foreground = plant.MP1 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP1ForwardButton.Background = plant.MP1 == MotorState.Forward ? Brushes.MintCream: Brushes.WhiteSmoke;
MP2BackwardButton.BorderBrush = plant.MP2 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2BackwardButton.Foreground = plant.MP2 == MotorState.Backward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2BackwardButton.Background = plant.MP2 == MotorState.Backward ? Brushes.MintCream : Brushes.WhiteSmoke;
MP2HaltButton.BorderBrush = plant.MP2 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP2HaltButton.Foreground = plant.MP2 == MotorState.Halt ? Brushes.DarkRed : Brushes.SlateGray;
MP2HaltButton.Background = plant.MP2 == MotorState.Halt ? Brushes.MistyRose : Brushes.WhiteSmoke;
MP2ForwardButton.BorderBrush = plant.MP2 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2ForwardButton.Foreground = plant.MP2 == MotorState.Forward ? Brushes.DarkGreen : Brushes.SlateGray;
MP2ForwardButton.Background = plant.MP2 == MotorState.Forward ? Brushes.MintCream : Brushes.WhiteSmoke;
P12Button.BorderBrush = plant.P12 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P12Button.Foreground = plant.P12 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P12Button.Background = plant.P12 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P3Button.BorderBrush = plant.P3 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P3Button.Foreground = plant.P3 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P3Button.Background = plant.P3 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P4Button.BorderBrush = plant.P4 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P4Button.Foreground = plant.P4 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P4Button.Background = plant.P4 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P5Button.BorderBrush = plant.P5 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P5Button.Foreground = plant.P5 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P5Button.Background = plant.P5 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
P6Button.BorderBrush = plant.P6 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P6Button.Foreground = plant.P6 == MotorState.Forward ? Brushes.DarkGreen : Brushes.DarkRed;
P6Button.Background = plant.P6 == MotorState.Forward ? Brushes.MintCream : Brushes.MistyRose;
Status.Text = $"""
Gradation °Oe: {plant.GradationOe:N2}
Presse Querschnecke: {plant.PresseQuerSchnecke}
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.FillLevelPress1}
Presse 2: {plant.FillLevelPress2}
Tank 1: {plant.FillLevelT1}
Tank 2: {plant.FillLevelT2}
Tank 3: {plant.FillLevelT3}
Tank 4: {plant.FillLevelT4}
Tank 5: {plant.FillLevelT5}
Tank 6: {plant.FillLevelT6}
Tank 7: {plant.FillLevelT7}
Tank 8: {plant.FillLevelT8}
Tank 9: {plant.FillLevelT9}
""";
}
private void TroughAugerButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsTroughAugerActive) {
App.Plant.StopTroughAuger();
} else {
App.Plant.StartTroughAuger();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void ReblerButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsReblerActive) {
App.Plant.StopRebler();
} else {
App.Plant.StartRebler();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void StirrerMW1Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsStirrerMW1Active) {
App.Plant.StopStirrerMW1();
} else {
App.Plant.StartStirrerMW1();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void StirrerMW2Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsStirrerMW2Active) {
App.Plant.StopStirrerMW2();
} else {
App.Plant.StartStirrerMW2();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BeltButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsBeltActive) {
App.Plant.StopBelt();
} else {
App.Plant.StartBelt();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void Auger1Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsAuger1Active) {
App.Plant.StopAuger1();
} else {
App.Plant.StartAuger1();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void Auger2Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.IsAuger2Active) {
App.Plant.StopAuger2();
} else {
App.Plant.StartAuger2();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MP1BackwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
App.Plant.StartMP1Backward();
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MP1HaltButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
App.Plant.StopMP1();
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MP1ForwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
App.Plant.StartMP1Forward();
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MP2BackwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
App.Plant.StartMP2Backward();
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MP2HaltButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
App.Plant.StopMP2();
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MP2ForwardButton_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
App.Plant.StartMP2Forward();
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void P12Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.P12 == MotorState.Forward) {
App.Plant.StopP12();
} else {
App.Plant.StartP12();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void P3Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.P3 == MotorState.Forward) {
App.Plant.StopP3();
} else {
App.Plant.StartP3();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void P4Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.P4 == MotorState.Forward) {
App.Plant.StopP4();
} else {
App.Plant.StartP4();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void P5Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.P5 == MotorState.Forward) {
App.Plant.StopP5();
} else {
App.Plant.StartP5();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void P6Button_Click(object? sender, RoutedEventArgs? evt) {
if (App.Plant == null) return;
try {
if (App.Plant.P6 == MotorState.Forward) {
App.Plant.StopP6();
} else {
App.Plant.StartP6();
}
} catch (NoClearanceException exc) {
MessageBox.Show($"{exc.Message}", "Keine Freigabe", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
+45 -4
View File
@@ -4,10 +4,51 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PamhagenSysCtrl.Windows" xmlns:local="clr-namespace:PamhagenSysCtrl.Windows"
Title="Schema - Anlagensteuerung Pamhagen" Height="900" Width="1600" MinWidth="1500" MinHeight="900"> Title="Anlagensteuerung Pamhagen" Height="950" Width="1600" MinWidth="1500" MinHeight="950">
<Grid> <Grid>
<Canvas x:Name="SchemeCanvas" Width="1550" Height="900" VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="True" <Grid.RowDefinitions>
MouseMove="SchemeCanvas_MouseMove" MouseLeftButtonDown="SchemeCanvas_MouseLeftButtonDown" MouseLeftButtonUp="SchemeCanvas_MouseLeftButtonUp"> <RowDefinition Height="19"/>
</Canvas> <RowDefinition Height="*"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<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.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xF271;"/>
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem x:Name="Menu_Settings_Config" Header="Konfigurationsdatei öffnen..." Click="Menu_Settings_Config_Click">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xEC7A;"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_Settings_Directory" Header="Konfigurationsspeicherort öffnen..." Click="Menu_Settings_Directory_Click">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xED25;"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="Hilfe">
<MenuItem Header="Über">
<MenuItem.Icon>
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text="&#xE946;"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
<Grid Grid.Row="1" ClipToBounds="True">
<Canvas x:Name="SchemeCanvas" Width="1550" Height="900" VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="True"
MouseMove="SchemeCanvas_MouseMove" MouseLeftButtonDown="SchemeCanvas_MouseLeftButtonDown" MouseLeftButtonUp="SchemeCanvas_MouseLeftButtonUp" Grid.ColumnSpan="2" Margin="25,0,0,0">
</Canvas>
</Grid>
<StatusBar Grid.Row="2" BorderThickness="0,1,0,0" BorderBrush="Gray">
</StatusBar>
</Grid> </Grid>
</Window> </Window>
@@ -1,5 +1,6 @@
using PamhagenSysCtrl.Helpers; using PamhagenSysCtrl.Helpers;
using PamhagenSysCtrl.Helpers.Pipeline; using PamhagenSysCtrl.Helpers.Pipeline;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
@@ -12,7 +13,6 @@ namespace PamhagenSysCtrl.Windows {
private List<INode> _path = []; private List<INode> _path = [];
private ISet<INode>? _lastSelected; private ISet<INode>? _lastSelected;
private ISet<INode>? _hover; private ISet<INode>? _hover;
private bool _mouseDown;
public PlantSchemeWindow() { public PlantSchemeWindow() {
InitializeComponent(); InitializeComponent();
@@ -21,6 +21,28 @@ namespace PamhagenSysCtrl.Windows {
Graph.Draw(SchemeCanvas); Graph.Draw(SchemeCanvas);
} }
private void Menu_Settings_ManualControl_Click(object sender, RoutedEventArgs evt) {
var w = new ManualControlWindow();
w.Show();
}
private void Menu_Settings_Directory_Click(object sender, RoutedEventArgs evt) {
try {
Process.Start("explorer.exe", App.DataPath);
} catch { }
}
private void Menu_Settings_Config_Click(object sender, RoutedEventArgs evt) {
try {
Process.Start(new ProcessStartInfo {
FileName = "notepad.exe",
Arguments = App.ConfigPath,
Verb = "runas",
UseShellExecute = true,
});
} catch { }
}
private void SchemeCanvas_MouseMove(object sender, MouseEventArgs evt) { private void SchemeCanvas_MouseMove(object sender, MouseEventArgs evt) {
var p = evt.GetPosition(SchemeCanvas); var p = evt.GetPosition(SchemeCanvas);
UpdateScheme(evt.GetPosition(SchemeCanvas), evt.LeftButton == MouseButtonState.Pressed); UpdateScheme(evt.GetPosition(SchemeCanvas), evt.LeftButton == MouseButtonState.Pressed);
@@ -75,10 +97,10 @@ namespace PamhagenSysCtrl.Windows {
App.Plant?.StartRebler(); App.Plant?.StartRebler();
} }
} else if (c is Switcher switcher) { } else if (c is Switcher switcher) {
if (App.Plant?.WantA1Selected ?? false) { if (App.Plant?.WantMW1Selected ?? false) {
App.Plant?.SelectA2(); App.Plant?.SelectMW2();
} else { } else {
App.Plant?.SelectA1(); App.Plant?.SelectMW1();
} }
} else if (c is EncasedAuger auger) { } else if (c is EncasedAuger auger) {
if (auger == Graph.Auger1) { if (auger == Graph.Auger1) {
@@ -166,7 +188,6 @@ namespace PamhagenSysCtrl.Windows {
Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, p.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false), PamhagenBrushes.DimOrange); Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, p.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false), PamhagenBrushes.DimOrange);
} }
_hover = Graph.GetHover(pos.X, pos.Y); _hover = Graph.GetHover(pos.X, pos.Y);
_mouseDown = down;
if (_lastSource != null && (_hover.Count > 0 || _path.Count > 0)) { if (_lastSource != null && (_hover.Count > 0 || _path.Count > 0)) {
List<INode> points = [_lastSource, .. _path]; List<INode> points = [_lastSource, .. _path];
if (_hover.Count > 0 && !points.Contains(_hover.First())) { if (_hover.Count > 0 && !points.Contains(_hover.First())) {