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
+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);
var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 200, () => App.Plant?.IsReblerActive ?? false);
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);
MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelA1 ?? FillState.Unknown);
MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelA2 ?? FillState.Unknown);
MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelMW1 ?? 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)));
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);
+27 -27
View File
@@ -22,14 +22,14 @@ namespace PamhagenSysCtrl.Helpers {
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 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 IsA1Selected => Sensors.TroughSelector == 1;
public bool IsA2Selected => Sensors.TroughSelector == 2;
public FillState FillLevelA1 => Sensors.FillingLevels.A1;
public FillState FillLevelA2 => Sensors.FillingLevels.A2;
public bool IsMWSelected => Sensors.TroughSelector == 1;
public bool IsMW2Selected => Sensors.TroughSelector == 2;
public FillState FillLevelMW1 => Sensors.FillingLevels.MW1;
public FillState FillLevelMW2 => Sensors.FillingLevels.MW2;
public FillState FillLevelPress1 => Sensors.FillingLevels.Press1;
public FillState FillLevelPress2 => Sensors.FillingLevels.Press2;
public FillState FillLevelT1 => Sensors.FillingLevelTanks[0];
@@ -46,13 +46,13 @@ namespace PamhagenSysCtrl.Helpers {
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 WantMW1Selected => Actuators.GetV(58);
public bool WantMW2Selected => !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 IsStirrerMW1Active => Actuators.StirrerMW1;
public bool IsStirrerMW2Active => Actuators.StirrerMW2;
public bool IsBeltActive => Actuators.Belt;
public bool IsAuger1Active => Actuators.Auger1;
public bool IsAuger2Active => Actuators.Auger2;
@@ -73,7 +73,7 @@ namespace PamhagenSysCtrl.Helpers {
}
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) {
@@ -82,7 +82,7 @@ namespace PamhagenSysCtrl.Helpers {
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)))
if (p.IsTroughAugerActive && (!p.IsReblerActive || (p.IsMWSelected && p.FillLevelMW1 == FillState.Full) || (p.IsMW2Selected && p.FillLevelMW2 == FillState.Full)))
p.StopTroughAuger();
if (p.IsMP1Active && !p.MP1HasClearance) p.StopMP1();
if (p.IsMP2Active && !p.MP2HasClearance) p.StopMP2();
@@ -210,7 +210,7 @@ namespace PamhagenSysCtrl.Helpers {
(a && ((HasWTClearanceAA && HasT9ClearanceA) || (HasWTClearanceAB && HasT9ClearanceB))) ||
(b && ((HasWTClearanceBA && HasT9ClearanceA) || (HasWTClearanceBB && HasT9ClearanceB)));
public bool MP1HasClearance => FillLevelA1 != FillState.Empty && (
public bool MP1HasClearance => FillLevelMW1 != FillState.Empty && (
(MP1HasClearancePress1 && FillLevelPress1 != FillState.Full) ||
(MP1HasClearancePress2 && FillLevelPress2 != 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;
}
public bool MP2HasClearance => FillLevelA2 != FillState.Empty && (
public bool MP2HasClearance => FillLevelMW2 != FillState.Empty && (
(MP2HasClearancePress1 && FillLevelPress1 != FillState.Full) ||
(MP2HasClearancePress2 && FillLevelPress2 != FillState.Full) ||
(HasClearanceTank1(MP2HasClearanceTanksA, MP2HasClearanceTanksB) && FillLevelT1 != FillState.Full) ||
@@ -371,20 +371,20 @@ namespace PamhagenSysCtrl.Helpers {
ActuatorsChanged = true;
}
public void SelectA1() {
public void SelectMW1() {
Actuators.SetV(58, true);
//if (IsReblerActive) Actuators.StirrerA1 = true;
//if (IsReblerActive) Actuators.StirrerMW1 = true;
ActuatorsChanged = true;
}
public void SelectA2() {
public void SelectMW2() {
Actuators.SetV(58, false);
//if (IsReblerActive) Actuators.StirrerA2 = true;
//if (IsReblerActive) Actuators.StirrerMW2 = true;
ActuatorsChanged = true;
}
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");
Actuators.TroughAuger = true;
ActuatorsChanged = true;
@@ -407,23 +407,23 @@ namespace PamhagenSysCtrl.Helpers {
ActuatorsChanged = true;
}
public void StartStirrerA1() {
Actuators.StirrerA1 = true;
public void StartStirrerMW1() {
Actuators.StirrerMW1 = true;
ActuatorsChanged = true;
}
public void StopStirrerA1() {
Actuators.StirrerA1 = false;
public void StopStirrerMW1() {
Actuators.StirrerMW1 = false;
ActuatorsChanged = true;
}
public void StartStirrerA2() {
Actuators.StirrerA2 = true;
public void StartStirrerMW2() {
Actuators.StirrerMW2 = true;
ActuatorsChanged = true;
}
public void StopStirrerA2() {
Actuators.StirrerA2 = false;
public void StopStirrerMW2() {
Actuators.StirrerMW2 = false;
ActuatorsChanged = true;
}
+10 -10
View File
@@ -5,7 +5,7 @@ namespace PamhagenSysCtrl.Helpers {
public record struct SensorStates(
long PressureSensors,
(FillState A1, FillState A2, FillState Press1, FillState Press2) FillingLevels,
(FillState MW1, FillState MW2, FillState Press1, FillState Press2) FillingLevels,
int TroughSelector,
double GradationOe,
FillState[] FillingLevelTanks,
@@ -17,7 +17,7 @@ namespace PamhagenSysCtrl.Helpers {
public record struct ActuatorStates(
long Valves,
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 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);
pressure = (pressure & 0x01FFFFFFFFFFFFFF) | ((pressure & 0x0600000000000000) << 1);
var a1 = Int3ToFillState((f1 ) & 0x7); // 111 011 001 000
var a2 = Int3ToFillState((f1 >> 3) & 0x7); // 111 011 001 000
var p1 = Int1ToFillState((f1 >> 6) & 0x1); // 1 0
var p2 = Int1ToFillState((f1 >> 7) & 0x1); // 1 0
var wp = ((f1 >> 8) & 0x3); // 10 01
var mw1 = Int3ToFillState((f1 ) & 0x7); // 111 011 001 000
var mw2 = Int3ToFillState((f1 >> 3) & 0x7); // 111 011 001 000
var p1 = Int1ToFillState((f1 >> 6) & 0x1); // 1 0
var p2 = Int1ToFillState((f1 >> 7) & 0x1); // 1 0
var wp = ((f1 >> 8) & 0x3); // 10 01
// Masseligerät : 4mA => 50 Oe
// 20mA => 150 Oe
@@ -137,7 +137,7 @@ namespace PamhagenSysCtrl.Helpers {
var t9 = Int1ToFillState((f2 >> 13) & 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() {
@@ -210,8 +210,8 @@ namespace PamhagenSysCtrl.Helpers {
(state.TroughAuger ? 0x01 : 0x00) |
(state.Rebler ? 0x02 : 0x00) |
(state.GetV(58) ? 0x04 : 0x00) |
(state.StirrerA1 ? 0x08 : 0x00) |
(state.StirrerA2 ? 0x10 : 0x00) |
(state.StirrerMW1 ? 0x08 : 0x00) |
(state.StirrerMW2 ? 0x10 : 0x00) |
(state.Belt ? 0x20 : 0x00) |
(state.Auger1 ? 0x40 : 0x00) |
(state.Auger2 ? 0x80 : 0x00);