Compare commits
5
Commits
e45c398c68
..
v0.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3983393e10 | ||
|
|
c82adcc054 | ||
|
|
28aaa6b1f3 | ||
|
|
0ceab368ce | ||
|
|
7c3233361f |
No files matched your search
@@ -5,10 +5,12 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
public const double TRANSITION = 1.0 / 4096;
|
||||
|
||||
public static readonly SolidColorBrush Green = new SolidColorBrush(Color.FromRgb(0x20, 0xE0, 0x20));
|
||||
public static readonly SolidColorBrush DimOrange = new SolidColorBrush(Color.FromRgb(0xFF, 0xC0, 0x80));
|
||||
public static readonly SolidColorBrush Yellow = new SolidColorBrush(Color.FromRgb(0xFF, 0xE0, 0x10));
|
||||
public static readonly SolidColorBrush Red = new SolidColorBrush(Color.FromRgb(0xFF, 0x20, 0x20));
|
||||
public static readonly SolidColorBrush Green = new(Color.FromRgb(0x20, 0xE0, 0x20));
|
||||
public static readonly SolidColorBrush DimGreen = new(Color.FromRgb(0xC0, 0xE0, 0xC0));
|
||||
public static readonly SolidColorBrush DimOrange = new(Color.FromRgb(0xFF, 0xC0, 0x80));
|
||||
public static readonly SolidColorBrush Yellow = new(Color.FromRgb(0xFF, 0xE0, 0x10));
|
||||
public static readonly SolidColorBrush Red = new(Color.FromRgb(0xFF, 0x20, 0x20));
|
||||
public static readonly SolidColorBrush DimRed = new(Color.FromRgb(0xFF, 0xC0, 0xC0));
|
||||
|
||||
public static Brush ForFillState(FillState state, Color background) {
|
||||
return state switch {
|
||||
|
||||
@@ -66,8 +66,8 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
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)));
|
||||
MP1 = new Pump("MP1", mw1X, mpY, () => App.Plant?.MP1 ?? default, () => App.Plant?.MP1HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
MP2 = new Pump("MP2", mw2X, mpY, () => App.Plant?.MP2 ?? default, () => App.Plant?.MP2HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
var x1 = new PipeJoin(mw1X, mpY + 40);
|
||||
var x2 = new PipeJoin(mw2X, mpY + 40);
|
||||
|
||||
@@ -291,14 +291,14 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
CreateInlet(v43, t9);
|
||||
|
||||
var xp12 = new PipeJoin((t1X + t2X) / 2, tanksY + 80);
|
||||
P12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 110, () => App.Plant?.IsP12Active ?? false, () => App.Plant?.P12HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P12 = new Pump("P1/2", (t1X + t2X) / 2, tanksY + 110, () => App.Plant?.P12 ?? default, () => App.Plant?.P12HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
CreateOutlet(t1, xp12);
|
||||
CreateOutlet(t2, xp12);
|
||||
CreatePipe(xp12, P12);
|
||||
|
||||
P3 = new Pump("P3", t3X, tanksY + 110, () => App.Plant?.IsP3Active ?? false, () => App.Plant?.P3HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P4 = new Pump("P4", t4X, tanksY + 110, () => App.Plant?.IsP4Active ?? false, () => App.Plant?.P4HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P5 = new Pump("P5", t5X, tanksY + 110, () => App.Plant?.IsP5Active ?? false, () => App.Plant?.P5HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P3 = new Pump("P3", t3X, tanksY + 110, () => App.Plant?.P3 ?? default, () => App.Plant?.P3HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P4 = new Pump("P4", t4X, tanksY + 110, () => App.Plant?.P4 ?? default, () => App.Plant?.P4HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P5 = new Pump("P5", t5X, tanksY + 110, () => App.Plant?.P5 ?? default, () => App.Plant?.P5HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
CreateOutlet(t3, P3);
|
||||
CreateOutlet(t4, P4);
|
||||
CreateOutlet(t5, P5);
|
||||
@@ -328,7 +328,7 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
var xt6 = new PipeJoin(t6X, tanksY + 110);
|
||||
var xt7 = new PipeJoin(t7X, tanksY + 110);
|
||||
var xt8 = new PipeJoin(t8X, tanksY + 110);
|
||||
P6 = new Pump("P6", t6X, tanksY + 150, () => App.Plant?.IsP6Active ?? false, () => App.Plant?.P6HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
P6 = new Pump("P6", t6X, tanksY + 150, () => App.Plant?.P6 ?? default, () => App.Plant?.P6HasClearance ?? false, (x) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == x)));
|
||||
CreateOutlet(t6, xt6);
|
||||
CreateOutlet(t7, xt7);
|
||||
CreateOutlet(t8, xt8);
|
||||
@@ -395,34 +395,35 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
}
|
||||
|
||||
protected Valve CreateValve(int n, double x, double y) {
|
||||
return new(n, x, y, () => App.Plant?.IsValveOpen(n) ?? false, (v) => SelectedPaths.Any(p => p.Hops.Any(h => h.Node == v)));
|
||||
return new(n, x, y, () => App.Plant?.IsValveOpen(n) ?? false, (v) => App.Plant?.ManualControlMode ?? false ? App.Plant.WantValveOpen(n) : SelectedPaths.Any(p => p.Hops.Any(h => h.Node == v)));
|
||||
}
|
||||
|
||||
protected static Tank CreateTank(int n, double x, double y, int capacity) {
|
||||
return new($"Tank {n}", x, y, capacity, () => App.Plant?.TankFillLevels[n - 1] ?? FillState.Unknown);
|
||||
}
|
||||
|
||||
public void TraverseSubgraph(INode start, HashSet<IEdge>? visited = null, Action<IEdge>? edgeAction = null, Action<Valve>? valveAction = null) {
|
||||
visited ??= [];
|
||||
public void TraverseSubgraph(INode start, Func<INode, bool> invalid, HashSet<IEdge>? _visited = null, Action<INode, bool, IEdge>? edgeAction = null, Action<Valve>? valveAction = null, bool reverse = false) {
|
||||
var visited = _visited ?? [];
|
||||
if (start is Valve v) {
|
||||
valveAction?.Invoke(v);
|
||||
return;
|
||||
} else if (start is ISink || start is Pump) {
|
||||
}
|
||||
if (invalid(start)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var edge in start.Inputs) {
|
||||
if (visited.Contains(edge)) continue;
|
||||
var o = edge.IsTwoWay && edge.Start == start ? edge.End : edge.Start;
|
||||
edgeAction?.Invoke(edge);
|
||||
edgeAction?.Invoke(start, reverse || _visited == null, edge);
|
||||
visited.Add(edge);
|
||||
TraverseSubgraph(o, visited, edgeAction, valveAction);
|
||||
TraverseSubgraph(o, invalid, visited, edgeAction, valveAction, reverse || _visited == null);
|
||||
}
|
||||
foreach (var edge in start.Outputs) {
|
||||
if (visited.Contains(edge)) continue;
|
||||
var o = edge.IsTwoWay && edge.End == start ? edge.Start : edge.End;
|
||||
edgeAction?.Invoke(edge);
|
||||
edgeAction?.Invoke(start, reverse, edge);
|
||||
visited.Add(edge);
|
||||
TraverseSubgraph(o, visited, edgeAction, valveAction);
|
||||
TraverseSubgraph(o, invalid, visited, edgeAction, valveAction, reverse);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,7 +454,7 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
private void UpdateValvesAdjacientToPath(Path path, bool locked, bool? wantOpen = null) {
|
||||
foreach (var (edge, node) in path.Hops) {
|
||||
TraverseSubgraph(node, valveAction: (v) => {
|
||||
TraverseSubgraph(node, (n) => n is Valve || n is ISink || n is Pump, valveAction: (v) => {
|
||||
v.IsLocked = locked;
|
||||
if (wantOpen.HasValue) {
|
||||
if (wantOpen.Value) {
|
||||
@@ -466,18 +467,41 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
}
|
||||
}
|
||||
|
||||
public void ColorPipesAdjacientToPath(Path path, Brush? color1, bool flowArrows, Brush? color2) {
|
||||
public void ColorPipesAdjacientToPath(Path path, Brush? color1, MotorState flowArrows, Brush? color2) {
|
||||
var color = color1;
|
||||
var flowPathOffset = 0.0;
|
||||
HashSet<IEdge> visited = [];
|
||||
foreach (var (edge, node) in path.Hops) {
|
||||
edge.Highlight = color1;
|
||||
edge.Flow = flowArrows ? (edge.End == node, flowPathOffset) : null;
|
||||
if (edge.Flow != null) flowPathOffset += edge.FlowLength;
|
||||
if (flowArrows > MotorState.Halt) {
|
||||
var dir = edge.End == node;
|
||||
if (flowArrows == MotorState.Backward) dir = !dir;
|
||||
edge.Flow = (dir, flowPathOffset);
|
||||
flowPathOffset += edge.FlowLength;
|
||||
}
|
||||
visited.Add(edge);
|
||||
if (node is Pump) color = color2;
|
||||
TraverseSubgraph(node, visited, edgeAction: (e) => e.Highlight = color);
|
||||
TraverseSubgraph(node, (n) => n is Valve || n is ISink || n is Pump, visited, edgeAction: (s, r, e) => e.Highlight = color);
|
||||
}
|
||||
}
|
||||
|
||||
public void ColorPipesByValves(INode start, Brush? color1, MotorState flowArrows, Brush? color2) {
|
||||
var flowPathOffset = 0.0;
|
||||
TraverseSubgraph(start, (n) => n is ISink || n is Outlet || !((n as Valve)?.IsOpen ?? (n as CenterValve)?.IsOpen ?? true), null,
|
||||
edgeAction: (s, r, e) => {
|
||||
if (((e.Start as Valve)?.IsOpen ?? true) && ((e.End as Valve)?.IsOpen ?? true)) {
|
||||
e.Highlight = color1;
|
||||
if (flowArrows == MotorState.Forward || flowArrows == MotorState.Backward) {
|
||||
var dir = e.Start == s;
|
||||
if (r) dir = !dir;
|
||||
if (flowArrows == MotorState.Backward) dir = !dir;
|
||||
e.Flow = (dir, flowPathOffset);
|
||||
flowPathOffset += e.FlowLength;
|
||||
}
|
||||
} else {
|
||||
e.Highlight = color2;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
protected bool IsRunning = true;
|
||||
protected Thread? BackgroundThread;
|
||||
|
||||
public bool ManualControlMode { get; set; }
|
||||
public bool OverridePathClearances { get; set; }
|
||||
public bool OverrideDryRunClearances { get; set; }
|
||||
|
||||
@@ -81,14 +82,32 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
protected static void OnUpdate(object? sender, PlantEventArgs evt) {
|
||||
if (sender is not PamhagenPlant p) return;
|
||||
if (p.IsPresseQuerSchneckeActive && !p.IsAuger2Active) p.StartAuger2();
|
||||
if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1();
|
||||
if (p.IsAuger1Active && !p.IsAuger2Active) p.StartAuger2();
|
||||
if (p.IsAuger2Active && !p.IsAuger3Active) p.StartAuger3();
|
||||
if (p.IsTroughAugerActive && (!p.IsReblerActive || (p.IsMWSelected && p.FillLevelMW1 == FillState.Full) || (p.IsMW2Selected && p.FillLevelMW2 == FillState.Full)))
|
||||
p.StopTroughAuger();
|
||||
|
||||
if (!p.ManualControlMode) {
|
||||
if (p.IsPresseQuerSchneckeActive && !p.IsAuger2Active) p.StartAuger2();
|
||||
if (p.IsReblerActive && !p.IsAuger1Active) p.StartAuger1();
|
||||
if (p.IsAuger1Active && !p.IsAuger2Active) p.StartAuger2();
|
||||
if (p.IsAuger2Active && !p.IsAuger3Active) p.StartAuger3();
|
||||
if (p.IsTroughAugerActive && (!p.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();
|
||||
|
||||
if (!p.ManualControlMode) {
|
||||
if (p.MP1 == MotorState.Forward && p.FillLevelMW1 >= FillState.Half && !p.IsStirrerMW1Active) {
|
||||
p.StartStirrerMW1();
|
||||
} else if (p.IsStirrerMW1Active && (!p.IsMP1Active || p.FillLevelMW1 < FillState.Half)) {
|
||||
p.StopStirrerMW1();
|
||||
}
|
||||
if (p.MP2 == MotorState.Forward && p.FillLevelMW2 >= FillState.Half && !p.IsStirrerMW2Active) {
|
||||
p.StartStirrerMW2();
|
||||
} else if (p.IsStirrerMW2Active && (!p.IsMP2Active || p.FillLevelMW2 < FillState.Half)) {
|
||||
p.StopStirrerMW2();
|
||||
}
|
||||
}
|
||||
|
||||
if (p.IsP12Active && !p.P12HasClearance) p.StopP12();
|
||||
if (p.IsP3Active && !p.P3HasClearance) p.StopP3();
|
||||
if (p.IsP4Active && !p.P4HasClearance) p.StopP4();
|
||||
@@ -382,18 +401,16 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
public void SelectMW1() {
|
||||
Actuators.SetV(58, true);
|
||||
//if (IsReblerActive) Actuators.StirrerMW1 = true;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void SelectMW2() {
|
||||
Actuators.SetV(58, false);
|
||||
//if (IsReblerActive) Actuators.StirrerMW2 = true;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StartTroughAuger() {
|
||||
if (!IsReblerActive || (IsMWSelected && FillLevelMW1 == FillState.Full) || (IsMW2Selected && FillLevelMW2 == FillState.Full))
|
||||
if (!ManualControlMode && (!IsReblerActive || (IsMWSelected && FillLevelMW1 == FillState.Full) || (IsMW2Selected && FillLevelMW2 == FillState.Full)))
|
||||
throw new NoClearanceException("Schnecke Auffangwanne hat keine Freigabe");
|
||||
Actuators.TroughAuger = true;
|
||||
ActuatorsChanged = true;
|
||||
@@ -406,12 +423,12 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
public void StartRebler() {
|
||||
Actuators.Rebler = true;
|
||||
StartAuger1();
|
||||
if (!ManualControlMode) StartAuger1();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StopRebler() {
|
||||
StopTroughAuger();
|
||||
if (!ManualControlMode) StopTroughAuger();
|
||||
Actuators.Rebler = false;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
@@ -438,25 +455,25 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
public void StartAuger1() {
|
||||
Actuators.Auger1 = true;
|
||||
StartAuger2();
|
||||
if (!ManualControlMode) StartAuger2();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StopAuger1() {
|
||||
if (IsReblerActive) throw new NoClearanceException("Rebler aktiv");
|
||||
if (!ManualControlMode && IsReblerActive) throw new NoClearanceException("Rebler aktiv");
|
||||
Actuators.Auger1 = false;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StartAuger2() {
|
||||
Actuators.Auger2 = true;
|
||||
StartAuger3();
|
||||
if (!ManualControlMode) StartAuger3();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StopAuger2() {
|
||||
if (IsPresseQuerSchneckeActive) throw new NoClearanceException("Presse-Querschnecke aktiv");
|
||||
if (IsAuger1Active) throw new NoClearanceException("Förderschnecke 1 aktiv");
|
||||
if (!ManualControlMode && IsPresseQuerSchneckeActive) throw new NoClearanceException("Presse-Querschnecke aktiv");
|
||||
if (!ManualControlMode && IsAuger1Active) throw new NoClearanceException("Förderschnecke 1 aktiv");
|
||||
Actuators.Auger2 = false;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
@@ -467,7 +484,7 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
}
|
||||
|
||||
public void StopAuger3() {
|
||||
if (IsAuger2Active) throw new NoClearanceException("Förderschnecke 2 aktiv");
|
||||
if (!ManualControlMode && IsAuger2Active) throw new NoClearanceException("Förderschnecke 2 aktiv");
|
||||
Actuators.Auger3 = false;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
@@ -484,35 +501,43 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
|
||||
public void StartMP1Forward() {
|
||||
if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe");
|
||||
if (Actuators.MP1 == MotorState.Backward) throw new NoClearanceException("MP1 läuft bereits (zurück)");
|
||||
Actuators.MP1 = MotorState.Forward;
|
||||
if (FillLevelMW1 >= FillState.Half) StartStirrerMW1();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StartMP1Backward() {
|
||||
if (!MP1HasClearance) throw new NoClearanceException("MP1 hat keine Freigabe");
|
||||
if (Actuators.MP1 == MotorState.Forward) throw new NoClearanceException("MP1 läuft bereits (vor)");
|
||||
Actuators.MP1 = MotorState.Backward;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StopMP1() {
|
||||
Actuators.MP1 = MotorState.Halt;
|
||||
if (!ManualControlMode) StopStirrerMW1();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StartMP2Forward() {
|
||||
if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe");
|
||||
if (Actuators.MP2 == MotorState.Backward) throw new NoClearanceException("MP2 läuft bereits (zurück)");
|
||||
Actuators.MP2 = MotorState.Forward;
|
||||
if (FillLevelMW2 >= FillState.Half) StartStirrerMW2();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StartMP2Backward() {
|
||||
if (!MP2HasClearance) throw new NoClearanceException("MP2 hat keine Freigabe");
|
||||
if (Actuators.MP2 == MotorState.Forward) throw new NoClearanceException("MP2 läuft bereits (vor)");
|
||||
Actuators.MP2 = MotorState.Backward;
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
public void StopMP2() {
|
||||
Actuators.MP2 = MotorState.Halt;
|
||||
if (!ManualControlMode) StopStirrerMW1();
|
||||
ActuatorsChanged = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
public ISet<IEdge> Outputs { get; init; }
|
||||
|
||||
public Brush? Highlight { get; set; }
|
||||
public bool IsActive => CallbackActive();
|
||||
public bool IsActive => State == MotorState.Forward || State == MotorState.Backward;
|
||||
public MotorState State => CallbackState();
|
||||
public bool HasClearance => CallbackClearance();
|
||||
public bool IsSelected => CallbackSelected(this);
|
||||
|
||||
protected Func<bool> CallbackActive;
|
||||
protected Func<MotorState> CallbackState;
|
||||
protected Func<bool> CallbackClearance;
|
||||
protected Func<Pump, bool> CallbackSelected;
|
||||
|
||||
@@ -28,11 +29,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
private Shape? _triangle;
|
||||
private TextBlock? _text;
|
||||
|
||||
public Pump(string label, double x, double y, Func<bool> cbActive, Func<bool> cbClearance, Func<Pump, bool> cbSelected) {
|
||||
public Pump(string label, double x, double y, Func<MotorState> cbState, Func<bool> cbClearance, Func<Pump, bool> cbSelected) {
|
||||
CenterX = x;
|
||||
CenterY = y;
|
||||
Label = label;
|
||||
CallbackActive = cbActive;
|
||||
CallbackState = cbState;
|
||||
CallbackClearance = cbClearance;
|
||||
CallbackSelected = cbSelected;
|
||||
Inputs = new HashSet<IEdge>();
|
||||
@@ -75,13 +76,22 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
public void Update(bool isHovering, bool isPresed) {
|
||||
_circle?.Fill = Highlight ?? (
|
||||
IsActive && isHovering ? PamhagenBrushes.Red :
|
||||
IsActive ? PamhagenBrushes.Green :
|
||||
HasClearance && IsSelected && isHovering ? PamhagenBrushes.Green :
|
||||
HasClearance && IsSelected ? PamhagenBrushes.Yellow :
|
||||
IsSelected ? PamhagenBrushes.Red :
|
||||
isHovering ? Brushes.LightGray : Brushes.WhiteSmoke);
|
||||
if (App.Plant?.ManualControlMode ?? false) {
|
||||
_circle?.Fill = Highlight ?? (
|
||||
IsActive && isHovering ? PamhagenBrushes.Red :
|
||||
IsActive ? PamhagenBrushes.Green :
|
||||
HasClearance && isHovering ? PamhagenBrushes.Green :
|
||||
HasClearance ? PamhagenBrushes.Yellow :
|
||||
PamhagenBrushes.Red);
|
||||
} else {
|
||||
_circle?.Fill = Highlight ?? (
|
||||
IsActive && isHovering ? PamhagenBrushes.Red :
|
||||
IsActive ? PamhagenBrushes.Green :
|
||||
HasClearance && IsSelected && isHovering ? PamhagenBrushes.Green :
|
||||
HasClearance && IsSelected ? PamhagenBrushes.Yellow :
|
||||
IsSelected ? PamhagenBrushes.Red :
|
||||
isHovering ? Brushes.LightGray : Brushes.WhiteSmoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,12 +66,23 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
public void Update(bool isHovering, bool isPressed) {
|
||||
_circle?.Fill =
|
||||
IsLocked && !WantOpen && !IsOpen ? PamhagenBrushes.DimOrange :
|
||||
IsLocked && !WantOpen && IsOpen ? PamhagenBrushes.Red :
|
||||
IsLocked && WantOpen && !IsOpen ? PamhagenBrushes.Yellow :
|
||||
IsLocked && WantOpen && IsOpen ? PamhagenBrushes.Green :
|
||||
Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray);
|
||||
if (App.Plant?.ManualControlMode ?? false) {
|
||||
_circle?.Fill =
|
||||
!WantOpen && !IsOpen && !isHovering ? PamhagenBrushes.Red :
|
||||
!WantOpen && !IsOpen ? PamhagenBrushes.Green :
|
||||
!WantOpen && IsOpen ? PamhagenBrushes.DimRed :
|
||||
WantOpen && !IsOpen ? PamhagenBrushes.DimGreen :
|
||||
WantOpen && IsOpen && !isHovering ? PamhagenBrushes.Green :
|
||||
WantOpen && IsOpen ? PamhagenBrushes.Red :
|
||||
Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray);
|
||||
} else {
|
||||
_circle?.Fill =
|
||||
IsLocked && !WantOpen && !IsOpen ? PamhagenBrushes.DimOrange :
|
||||
IsLocked && !WantOpen && IsOpen ? PamhagenBrushes.Red :
|
||||
IsLocked && WantOpen && !IsOpen ? PamhagenBrushes.Yellow :
|
||||
IsLocked && WantOpen && IsOpen ? PamhagenBrushes.Green :
|
||||
Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<Version>0.0.1</Version>
|
||||
<Version>0.0.2</Version>
|
||||
<Product>Anlagensteuerung Pamhagen</Product>
|
||||
<AssemblyTitle>Anlagensteuerung Pamhagen</AssemblyTitle>
|
||||
<AssemblyName>PamhagenSysCtrl</AssemblyName>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:PamhagenSysCtrl"
|
||||
mc:Ignorable="d"
|
||||
Closed="OnClosed"
|
||||
Title="Handbetrieb - Anlagensteuerung Pamhagen" Height="550" Width="860">
|
||||
<Grid>
|
||||
<Grid x:Name="ValvePanel" Margin="5,5,5,5">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using PamhagenSysCtrl.Helpers;
|
||||
using PamhagenSysCtrl.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
@@ -47,6 +48,14 @@ namespace PamhagenSysCtrl {
|
||||
App.Plant?.Update += OnUpdate;
|
||||
}
|
||||
|
||||
private void OnClosed(object sender, EventArgs evt) {
|
||||
foreach (var win in Application.Current.Windows) {
|
||||
if (win is PlantSchemeWindow w) {
|
||||
w.Menu_Settings_ManualControl.IsChecked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnUpdate(object? sender, PlantEventArgs evt) {
|
||||
if (sender is not PamhagenPlant plant) return;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:PamhagenSysCtrl.Windows"
|
||||
Closed="OnClosed"
|
||||
Title="Anlagensteuerung Pamhagen" Height="950" Width="1600" MinWidth="1500" MinHeight="950">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -14,20 +15,23 @@
|
||||
|
||||
<Menu Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
|
||||
<MenuItem Header="Einstellungen">
|
||||
<MenuItem x:Name="Menu_Settings_ManualControl" Header="Handbetrieb"
|
||||
Click="Menu_Settings_ManualControl_Click" IsCheckable="True">
|
||||
<MenuItem x:Name="Menu_Settings_ManualControl" Header="Handbetrieb" IsCheckable="True"
|
||||
Checked="Menu_Settings_ManualControl_Changed"
|
||||
Unchecked="Menu_Settings_ManualControl_Changed">
|
||||
<MenuItem.Icon>
|
||||
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem x:Name="Menu_Settings_OverridePathClearances" Header="Pfad-Freigaben überbrücken"
|
||||
Click="Menu_Settings_OverridePathClearances_Click" IsCheckable="True">
|
||||
<MenuItem x:Name="Menu_Settings_OverridePathClearances" Header="Pfad-Freigaben überbrücken" IsCheckable="True"
|
||||
Checked="Menu_Settings_OverridePathClearances_Changed"
|
||||
Unchecked="Menu_Settings_OverridePathClearances_Changed">
|
||||
<MenuItem.Icon>
|
||||
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem x:Name="Menu_Settings_OverrideDryRunClearances" Header="Trockenlauf-Freigaben überbrücken"
|
||||
Click="Menu_Settings_OverrideDryRunClearances_Click" IsCheckable="True"/>
|
||||
<MenuItem x:Name="Menu_Settings_OverrideDryRunClearances" Header="Trockenlauf-Freigaben überbrücken" IsCheckable="True"
|
||||
Checked="Menu_Settings_OverrideDryRunClearances_Changed"
|
||||
Unchecked="Menu_Settings_OverrideDryRunClearances_Changed"/>
|
||||
<Separator/>
|
||||
<MenuItem x:Name="Menu_Settings_Config" Header="Konfigurationsdatei öffnen..." Click="Menu_Settings_Config_Click">
|
||||
<MenuItem.Icon>
|
||||
|
||||
@@ -21,7 +21,12 @@ namespace PamhagenSysCtrl.Windows {
|
||||
Graph.Draw(SchemeCanvas);
|
||||
}
|
||||
|
||||
private void Menu_Settings_ManualControl_Click(object sender, RoutedEventArgs evt) {
|
||||
private void OnClosed(object sender, EventArgs evt) {
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
private void Menu_Settings_ManualControl_Changed(object sender, RoutedEventArgs evt) {
|
||||
App.Plant?.ManualControlMode = Menu_Settings_ManualControl.IsChecked;
|
||||
if (Menu_Settings_ManualControl.IsChecked) {
|
||||
foreach (var win in Application.Current.Windows) {
|
||||
if (win is ManualControlWindow w) {
|
||||
@@ -37,15 +42,18 @@ namespace PamhagenSysCtrl.Windows {
|
||||
w.Close();
|
||||
}
|
||||
}
|
||||
Menu_Settings_OverridePathClearances.IsChecked = false;
|
||||
Menu_Settings_OverrideDryRunClearances.IsChecked = false;
|
||||
}
|
||||
OnUpdate(null, null);
|
||||
}
|
||||
|
||||
private void Menu_Settings_OverridePathClearances_Click(object sender, RoutedEventArgs evt) {
|
||||
private void Menu_Settings_OverridePathClearances_Changed(object sender, RoutedEventArgs evt) {
|
||||
App.Plant?.OverridePathClearances = Menu_Settings_OverridePathClearances.IsChecked;
|
||||
OnUpdate(null, null);
|
||||
}
|
||||
|
||||
private void Menu_Settings_OverrideDryRunClearances_Click(object sender, RoutedEventArgs evt) {
|
||||
private void Menu_Settings_OverrideDryRunClearances_Changed(object sender, RoutedEventArgs evt) {
|
||||
App.Plant?.OverrideDryRunClearances = Menu_Settings_OverrideDryRunClearances.IsChecked;
|
||||
OnUpdate(null, null);
|
||||
}
|
||||
@@ -85,27 +93,37 @@ namespace PamhagenSysCtrl.Windows {
|
||||
_lastSource = null;
|
||||
}
|
||||
foreach (var c in clicked) {
|
||||
if (_lastSource == null && Graph.SelectedPaths.Any(p => p.Start == c)) {
|
||||
var path = Graph.SelectedPaths.First(p => p.Start == c);
|
||||
if (!path.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false)) {
|
||||
Graph.RemovePath(path);
|
||||
if (App.Plant?.ManualControlMode ?? false) {
|
||||
if (c is Valve v) {
|
||||
if (v.WantOpen) {
|
||||
App.Plant.CloseV(v.Nr);
|
||||
} else {
|
||||
App.Plant.OpenV(v.Nr);
|
||||
}
|
||||
}
|
||||
} else if (_lastSource != null && c is ISink sink) {
|
||||
var res = Graph.GetPath([_lastSource, .._path, sink], (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||
if (res is Path path) {
|
||||
Graph.AddPath(path);
|
||||
} else {
|
||||
if (_lastSource == null && Graph.SelectedPaths.Any(p => p.Start == c)) {
|
||||
var path = Graph.SelectedPaths.First(p => p.Start == c);
|
||||
if (!path.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false)) {
|
||||
Graph.RemovePath(path);
|
||||
}
|
||||
} else if (_lastSource != null && c is ISink sink) {
|
||||
var res = Graph.GetPath([_lastSource, .. _path, sink], (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||
if (res is Path path) {
|
||||
Graph.AddPath(path);
|
||||
_lastSource = null;
|
||||
}
|
||||
} else if (_lastSource != null) {
|
||||
var path = Graph.GetPath([_lastSource, .. _path, c], (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||
if (path != null) {
|
||||
_path.Add(c);
|
||||
}
|
||||
} else if (c is ISource source) {
|
||||
_lastSource = source;
|
||||
_path = [];
|
||||
} else {
|
||||
_lastSource = null;
|
||||
}
|
||||
} else if (_lastSource != null) {
|
||||
var path = Graph.GetPath([_lastSource, .. _path, c], (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||
if (path != null) {
|
||||
_path.Add(c);
|
||||
}
|
||||
} else if (c is ISource source) {
|
||||
_lastSource = source;
|
||||
_path = [];
|
||||
} else {
|
||||
_lastSource = null;
|
||||
}
|
||||
try {
|
||||
if (c is EntryTrough trough) {
|
||||
@@ -208,35 +226,42 @@ namespace PamhagenSysCtrl.Windows {
|
||||
p.Highlight = null;
|
||||
}
|
||||
}
|
||||
foreach (var p in Graph.SelectedPaths) {
|
||||
Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, p.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false), PamhagenBrushes.DimOrange);
|
||||
}
|
||||
|
||||
_hover = Graph.GetHover(pos.X, pos.Y);
|
||||
if (_lastSource != null && (_hover.Count > 0 || _path.Count > 0)) {
|
||||
List<INode> points = [_lastSource, .. _path];
|
||||
if (_hover.Count > 0 && !points.Contains(_hover.First())) {
|
||||
points.Add(_hover.First());
|
||||
if (App.Plant?.ManualControlMode ?? false) {
|
||||
foreach (var src in Graph.Nodes.Where(n => n is Pump)) {
|
||||
Graph.ColorPipesByValves(src, PamhagenBrushes.Green, (src as Pump)?.State ?? default, PamhagenBrushes.DimOrange);
|
||||
}
|
||||
if (points.Count >= 2) {
|
||||
var res = Graph.GetPath(points, (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||
if (res is Path path) {
|
||||
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Green, false, PamhagenBrushes.DimOrange);
|
||||
} else {
|
||||
foreach (var p in Graph.SelectedPaths) {
|
||||
Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, p.Hops.Select(h => (h.Node as Pump)?.State ?? default).FirstOrDefault(n => n != MotorState.Halt), PamhagenBrushes.DimOrange);
|
||||
}
|
||||
if (_lastSource != null && (_hover.Count > 0 || _path.Count > 0)) {
|
||||
List<INode> points = [_lastSource, .. _path];
|
||||
if (_hover.Count > 0 && !points.Contains(_hover.First())) {
|
||||
points.Add(_hover.First());
|
||||
}
|
||||
if (points.Count >= 2) {
|
||||
var res = Graph.GetPath(points, (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||
if (res is Path path) {
|
||||
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Green, default, PamhagenBrushes.DimOrange);
|
||||
}
|
||||
}
|
||||
} else if (_lastSource == null && _hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == _hover.First())) {
|
||||
var path = Graph.SelectedPaths.First(p => p.Start == _hover.First());
|
||||
var pumpActive = path.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false);
|
||||
if (pumpActive) {
|
||||
foreach (var pump in path.Hops.Select(h => h.Node as Pump).Where(p => p != null)) {
|
||||
pump?.Highlight = PamhagenBrushes.Red;
|
||||
}
|
||||
} else {
|
||||
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, default, null);
|
||||
}
|
||||
}
|
||||
} else if (_lastSource == null && _hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == _hover.First())) {
|
||||
var path = Graph.SelectedPaths.First(p => p.Start == _hover.First());
|
||||
var pumpActive = path.Hops.Any(h => (h.Node as Pump)?.IsActive ?? false);
|
||||
if (pumpActive) {
|
||||
foreach (var pump in path.Hops.Select(h => h.Node as Pump).Where(p => p != null)) {
|
||||
pump?.Highlight = PamhagenBrushes.Red;
|
||||
if (_lastSource != null) {
|
||||
foreach (var edge in _lastSource.Outputs) {
|
||||
edge.Highlight = PamhagenBrushes.Green;
|
||||
}
|
||||
} else {
|
||||
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, false, null);
|
||||
}
|
||||
}
|
||||
if (_lastSource != null) {
|
||||
foreach (var edge in _lastSource.Outputs) {
|
||||
edge.Highlight = PamhagenBrushes.Green;
|
||||
}
|
||||
}
|
||||
Graph.Update(_hover, down);
|
||||
|
||||
Reference in new issue
Block a user