Implement remaining XBE-24 and stirrer keys
Test / Run tests (push) Successful in 35s

This commit is contained in:
lorenz.stechauner committed 2026-11-06 09:49:23 +01:00
1 parent ed4bbd09bd
commit 50f6174af1
14 files changed
+438 -78

No files matched your search

+6 -2
View File
@@ -1,8 +1,12 @@
[plc]
port = COM1
sensor_delay_open = 0 ; seconds
sensor_delay_close = 2 ; seconds
; sensor delay in seconds
sensor_delay_open = 0
sensor_delay_close = 2
sensor_delay_mw = 10
; from which filling level on does the stirrer start (or stop when below) automatically when pumping
auto_stirrer = Half
[update]
url = https://elwig.at/files/pamhagen-sysctrl/latest
+4
View File
@@ -11,6 +11,8 @@ namespace PamhagenSysCtrl.Helpers {
public string PlcPort = "COM1";
public int PlcSensorDelayOpen = 0;
public int PlcSensorDelayClose = 0;
public int PlcSensorDelayMW = 0;
public FillState PlcAutoStirrer = FillState.Half;
public string? UpdateUrl;
public bool UpdateAuto;
@@ -28,6 +30,8 @@ namespace PamhagenSysCtrl.Helpers {
PlcPort = config["plc:port"] ?? "COM1";
PlcSensorDelayOpen = int.Parse(config["plc:sensor_delay_open"] ?? "0");
PlcSensorDelayClose = int.Parse(config["plc:sensor_delay_close"] ?? "0");
PlcSensorDelayMW = int.Parse(config["plc:sensor_delay_mw"] ?? "0");
PlcAutoStirrer = Enum.Parse<FillState>(config["plc:auto_stirrer"] ?? "Half");
UpdateUrl = config["update:url"];
UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
var xbe24 = config.GetSection("xbe24");
+4
View File
@@ -3,6 +3,10 @@ using System.Drawing;
namespace PamhagenSysCtrl.Helpers {
public static class Extensions {
public static void SetBacklight(this Xbe24Keyboard k, PamhagenPlant.ShortcutKey key, (Color Color, bool Flashing) state) {
k.SetBacklight(key, state.Color, state.Flashing);
}
public static void SetBacklight(this Xbe24Keyboard k, PamhagenPlant.ShortcutKey key, Color color, bool flashing = false) {
if (App.Config.MapKey(key) is int n)
k.SetBacklight(n, color, flashing);
+1 -1
View File
@@ -1,3 +1,3 @@
namespace PamhagenSysCtrl.Helpers {
public enum FillState { Empty = 0, Filled = 1, Half = 2, Full = 3, Invalid = -1, Unknown = -2 }
public enum FillState { Unknown = 0, Empty = 1, Filled = 2, Quarter = 3, Half = 4, ThreeQuarter = 5, AlmostFull = 6, Full = 7, Invalid = -1 }
}
@@ -16,7 +16,10 @@ namespace PamhagenSysCtrl.Helpers {
return state switch {
FillState.Empty => GetEmpty(background),
FillState.Filled => GetFilled(background),
FillState.Quarter => GetQuarter(background),
FillState.Half => GetHalf(background),
FillState.ThreeQuarter => GetThreeQuarter(background),
FillState.AlmostFull => GetAlmostFull(background),
FillState.Full => GetFull(background),
_ => GetEmpty(background),
};
@@ -34,10 +37,22 @@ namespace PamhagenSysCtrl.Helpers {
return new LinearGradientBrush(background, Green.Color, new(0.5, 0.875 - TRANSITION), new(0.5, 0.875 + TRANSITION));
}
public static Brush GetQuarter(Color background) {
return new LinearGradientBrush(background, Green.Color, new(0.5, 0.75 - TRANSITION), new(0.5, 0.75 + TRANSITION));
}
public static Brush GetHalf(Color background) {
return new LinearGradientBrush(background, Green.Color, new(0.5, 0.5 - TRANSITION), new(0.5, 0.5 + TRANSITION));
}
public static Brush GetThreeQuarter(Color background) {
return new LinearGradientBrush(background, Green.Color, new(0.5, 0.25 - TRANSITION), new(0.5, 0.25 + TRANSITION));
}
public static Brush GetAlmostFull(Color background) {
return new LinearGradientBrush(background, Green.Color, new(0.5, 0.125 - TRANSITION), new(0.5, 0.125 + TRANSITION));
}
public static Brush GetFull(Color background) {
return new LinearGradientBrush(background, Red.Color, new(0.5, 0.0625 - TRANSITION), new(0.5, 0.0625 + TRANSITION));
}
+3 -3
View File
@@ -367,8 +367,8 @@ namespace PamhagenSysCtrl.Helpers {
var prX = (pr1X + pr2X) / 2;
var pr1cX = prX - 3;
var pr2cX = prX + 3;
Press1 = new Press("Presse 1", pr1X, prY, 20000, () => FillState.Unknown);
Press2 = new Press("Presse 2", pr2X, prY, 15000, () => FillState.Unknown);
Press1 = new Press("Presse 1", pr1X, prY, 20000, () => FillState.Unknown, () => App.Plant?.State.Press1_HasClearance ?? false);
Press2 = new Press("Presse 2", pr2X, prY, 15000, () => FillState.Unknown, () => App.Plant?.State.Press2_HasClearance ?? false);
var v50 = CreateValve(50, pr2cX + 6, ltg3Y, 1);
var v51 = CreateValve(51, pr1cX - 6, ltg3Y, 1);
var v52 = CreateValve(52, pr1cX - 6, ltg4Y, 3);
@@ -492,7 +492,7 @@ namespace PamhagenSysCtrl.Helpers {
}
protected static Tank CreateTank(int n, double x, double y, int capacity) {
return new($"Tank {n}", x, y, capacity, () => App.Plant?.State.Tanks_FillLevel[n - 1] ?? FillState.Unknown);
return new($"Tank {n}", x, y, capacity, () => App.Plant?.State.Tanks_FillLevel[n - 1] ?? FillState.Unknown, () => true);
}
private int PathCost(Path p) {
+324 -48
View File
@@ -16,8 +16,6 @@ namespace PamhagenSysCtrl.Helpers {
START_TROUGH_AUGER, STOP_TROUGH_AUGER, TOGGLE_TROUGH_AUGER, INDICATE_TROUGH_AUGER,
SELECT_MW1, INDICATE_MW1_SELECTED,
SELECT_MW2, INDICATE_MW2_SELECTED,
INDICATE_MW1, INDICATE_MW1_EMPTY, INDICATE_MW1_FILLED, INDICATE_MW1_HALF, INDICATE_MW1_FULL,
INDICATE_MW2, INDICATE_MW2_EMPTY, INDICATE_MW2_FILLED, INDICATE_MW2_HALF, INDICATE_MW2_FULL,
START_STIRRER_MW1, STOP_STIRRER_MW1, TOGGLE_STIRRER_MW1, INDICATE_STIRRER_MW1,
START_STIRRER_MW2, STOP_STIRRER_MW2, TOGGLE_STIRRER_MW2, INDICATE_STIRRER_MW2,
START_MP1, STOP_MP1, TOGGLE_MP1, INDICATE_MP1,
@@ -97,7 +95,7 @@ namespace PamhagenSysCtrl.Helpers {
PlcThread = null;
PamhagenPlc? tmp = null;
try {
tmp = new PamhagenPlc(PlcComPort, App.Config.PlcSensorDelayOpen * 1000, App.Config.PlcSensorDelayClose * 1000);
tmp = new PamhagenPlc(PlcComPort, App.Config.PlcSensorDelayOpen * 1000, App.Config.PlcSensorDelayClose * 1000, App.Config.PlcSensorDelayMW * 1000);
await tmp.Initialize();
Plc = tmp;
PlcConnectionError = null;
@@ -147,50 +145,179 @@ namespace PamhagenSysCtrl.Helpers {
App.MainDispatcher?.BeginInvoke(() => Update?.Invoke(this, evt));
}
private static void UpdatePumpKeys(Xbe24Keyboard k, ShortcutKey start, ShortcutKey stop, ShortcutKey toggle, ShortcutKey indicate, PamhagenState.PumpState state, bool highlightOff, bool directControl) {
var waiting = !state.HasPathClearance && state.HasDryRunClearance && state.WantsPathClearance;
k.SetBacklight(start,
state.State == MotorState.Forward ? (Xbe24Keyboard.Green, false) :
state.State == MotorState.Backward ? (Xbe24Keyboard.Lime, true) :
waiting && state.WantActive ? (Xbe24Keyboard.Green, true) :
waiting && !state.WantActive ? (Xbe24Keyboard.LightGreen, true) :
state.HasClearance ? (Xbe24Keyboard.LightGreen, false) :
k.IsKeyPressed(start) ? (Xbe24Keyboard.Orange, false) :
(Xbe24Keyboard.LightRed, false));
k.SetBacklight(stop,
highlightOff ? Xbe24Keyboard.Orange :
!state.IsActive ? Xbe24Keyboard.Red :
Xbe24Keyboard.LightRed);
k.SetBacklight(toggle,
highlightOff ? (Xbe24Keyboard.Orange, false) :
state.State == MotorState.Forward ? (Xbe24Keyboard.Green, false) :
state.State == MotorState.Backward ? (Xbe24Keyboard.Lime, true) :
waiting && state.WantActive ? (Xbe24Keyboard.Green, true) :
waiting && !state.WantActive ? (Xbe24Keyboard.Yellow, true) :
state.HasClearance ? (Xbe24Keyboard.Yellow, false) :
k.IsKeyPressed(toggle) ? (Xbe24Keyboard.Orange, false) :
(Xbe24Keyboard.Red, false));
k.SetBacklight(indicate,
state.State == MotorState.Forward ? (Xbe24Keyboard.Green, false) :
state.State == MotorState.Backward ? (Xbe24Keyboard.Lime, true) :
waiting && state.WantActive ? (Xbe24Keyboard.Green, true) :
waiting && !state.WantActive ? (Xbe24Keyboard.Yellow, true) :
state.HasClearance ? (Xbe24Keyboard.Yellow, false) :
(Xbe24Keyboard.Red, false));
}
private static void UpdateMotorKeys(Xbe24Keyboard k, ShortcutKey start, ShortcutKey stop, ShortcutKey toggle, ShortcutKey indicate, bool active, bool clearance, bool consistent = true) {
k.SetBacklight(start,
active && consistent ? Xbe24Keyboard.Green :
active ? Xbe24Keyboard.Yellow :
clearance ? Xbe24Keyboard.LightGreen :
k.IsKeyPressed(start) ? Xbe24Keyboard.Orange :
Xbe24Keyboard.LightRed);
k.SetBacklight(stop,
!active && consistent ? Xbe24Keyboard.Red :
Xbe24Keyboard.LightRed);
k.SetBacklight(toggle,
active && consistent ? Xbe24Keyboard.Green :
active ? Xbe24Keyboard.Yellow :
!clearance && k.IsKeyPressed(toggle) ? Xbe24Keyboard.Orange :
Xbe24Keyboard.Red);
k.SetBacklight(indicate,
active && consistent ? Xbe24Keyboard.Green :
active ? Xbe24Keyboard.Yellow :
Xbe24Keyboard.Red);
}
private static void UpdateMwSelectKeys(Xbe24Keyboard k, ShortcutKey select, ShortcutKey indicate, bool selected, bool wantSelected, bool clearance) {
k.SetBacklight(select,
selected && !clearance ? (Xbe24Keyboard.Red, true) :
selected ? (Xbe24Keyboard.Blue, false) :
!clearance && k.IsKeyPressed(select) ? (Xbe24Keyboard.Orange, false) :
wantSelected && !clearance ? (Xbe24Keyboard.Red, true) :
wantSelected ? (Xbe24Keyboard.Blue, true) :
clearance ? (Xbe24Keyboard.LightBlue, false) :
(Xbe24Keyboard.LightRed, false));
k.SetBacklight(indicate,
selected && !clearance ? (Xbe24Keyboard.Red, true) :
selected ? (Xbe24Keyboard.Blue, false) :
wantSelected && !clearance ? (Xbe24Keyboard.Red, true) :
wantSelected ? (Xbe24Keyboard.Blue, true) :
clearance ? (Xbe24Keyboard.LightBlue, false) :
(Xbe24Keyboard.LightRed, false));
}
private static void UpdateMwStirrerKeys(Xbe24Keyboard k, FillState auto, ShortcutKey start, ShortcutKey stop, ShortcutKey toggle, ShortcutKey indicate, bool active, bool pumping, FillState filling) {
k.SetBacklight(start,
active && pumping && filling >= auto ? (Xbe24Keyboard.Green, false) :
active ? (Xbe24Keyboard.Green, true) :
pumping && filling >= auto ? (Xbe24Keyboard.LightGreen, true) :
filling >= auto ? (Xbe24Keyboard.LightGreen, false) :
(Xbe24Keyboard.LightRed, false));
k.SetBacklight(stop,
active && pumping && filling >= auto ? (Xbe24Keyboard.LightRed, false) :
active ? (Xbe24Keyboard.LightRed, true) :
pumping && filling >= auto ? (Xbe24Keyboard.Red, true) :
(Xbe24Keyboard.Red, false));
k.SetBacklight(toggle,
active && pumping && filling >= auto ? (Xbe24Keyboard.Green, false) :
active ? (Xbe24Keyboard.Green, true) :
pumping && filling >= auto ? (Xbe24Keyboard.Red, true) :
filling >= auto ? (Xbe24Keyboard.Yellow, false) :
(Xbe24Keyboard.Red, false));
k.SetBacklight(indicate,
active && pumping && filling >= auto ? (Xbe24Keyboard.Green, false) :
active ? (Xbe24Keyboard.Green, true) :
pumping && filling >= auto ? (Xbe24Keyboard.Red, true) :
filling >= auto ? (Xbe24Keyboard.Yellow, false) :
(Xbe24Keyboard.Red, false));
}
protected void UpdateKeyboardBacklights(object? sender, PlantEventArgs evt) {
if (sender is not PamhagenPlant plant || plant.Keyboard is not Xbe24Keyboard k) return;
// TODO update all keys
k.SetBacklight(ShortcutKey.INDICATE_PRESS_CROSS_AUGER, State.PressCrossAuger_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.Red);
k.SetBacklight(ShortcutKey.INDICATE_PRESS1_CLEARANCE, State.Press1_HasClearance ? Xbe24Keyboard.Green : Xbe24Keyboard.Red);
k.SetBacklight(ShortcutKey.INDICATE_PRESS2_CLEARANCE, State.Press2_HasClearance ? Xbe24Keyboard.Green : Xbe24Keyboard.Red);
k.SetBacklight(ShortcutKey.START_REBLER, State.Rebler_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
k.SetBacklight(ShortcutKey.STOP_REBLER, !State.Rebler_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
UpdateMotorKeys(k, ShortcutKey.START_AUGER1, ShortcutKey.STOP_AUGER1, ShortcutKey.TOGGLE_AUGER1, ShortcutKey.INDICATE_AUGER1,
State.Auger1_IsActive, true);
UpdateMotorKeys(k, ShortcutKey.START_AUGER2, ShortcutKey.STOP_AUGER2, ShortcutKey.TOGGLE_AUGER2, ShortcutKey.INDICATE_AUGER2,
State.Auger2_IsActive, true);
UpdateMotorKeys(k, ShortcutKey.START_AUGER3, ShortcutKey.STOP_AUGER3, ShortcutKey.TOGGLE_AUGER3, ShortcutKey.INDICATE_AUGER3,
State.Auger3_IsActive, true);
UpdateMotorKeys(k, ShortcutKey.START_REBLER, ShortcutKey.STOP_REBLER, ShortcutKey.TOGGLE_REBLER, ShortcutKey.INDICATE_REBLER,
State.Rebler_IsActive, true);
UpdateMotorKeys(k, ShortcutKey.START_TROUGH_AUGER, ShortcutKey.STOP_TROUGH_AUGER, ShortcutKey.TOGGLE_TROUGH_AUGER, ShortcutKey.INDICATE_TROUGH_AUGER,
State.TroughAuger_IsActive, State.TroughAuger_HasClearance);
UpdateMotorKeys(k, ShortcutKey.START_WASTE_DISPOSAL, ShortcutKey.STOP_WASTE_DISPOSAL, ShortcutKey.TOGGLE_WASTE_DISPOSAL, ShortcutKey.INDICATE_WASTE_DISPOSAL,
true, State.WasteDisposal_IsActive, State.WasteDisposal_IsConsistent);
k.SetBacklight(ShortcutKey.START_TROUGH_AUGER, !State.TroughAuger_HasClearance ? k.IsKeyPressed(ShortcutKey.START_TROUGH_AUGER) ? Xbe24Keyboard.Orange : Xbe24Keyboard.LightRed : State.TroughAuger_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
k.SetBacklight(ShortcutKey.STOP_TROUGH_AUGER, !State.TroughAuger_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
UpdateMwSelectKeys(k, ShortcutKey.SELECT_MW1, ShortcutKey.INDICATE_MW1_SELECTED,
State.MW1_IsSelected, State.MW1_WantSelected, State.MW1_FillLevel != FillState.Full);
UpdateMwSelectKeys(k, ShortcutKey.SELECT_MW2, ShortcutKey.INDICATE_MW2_SELECTED,
State.MW2_IsSelected, State.MW2_WantSelected, State.MW2_FillLevel != FillState.Full);
k.SetBacklight(ShortcutKey.SELECT_MW2, State.MW2_WantSelected || State.MW2_IsSelected ? Xbe24Keyboard.Blue : Xbe24Keyboard.LightBlue, State.MW2_WantSelected && !State.MW2_IsSelected);
k.SetBacklight(ShortcutKey.SELECT_MW1, State.MW1_WantSelected || State.MW1_IsSelected ? Xbe24Keyboard.Blue : Xbe24Keyboard.LightBlue, State.MW1_WantSelected && !State.MW1_IsSelected);
UpdateMwStirrerKeys(k, Plc?.AutoStirrer ?? App.Config.PlcAutoStirrer,
ShortcutKey.START_STIRRER_MW1, ShortcutKey.STOP_STIRRER_MW1, ShortcutKey.TOGGLE_STIRRER_MW1, ShortcutKey.INDICATE_STIRRER_MW1,
State.MW1_Stirrer_IsActive, State.MP1_State == MotorState.Forward, State.MW1_FillLevel);
UpdateMwStirrerKeys(k, Plc?.AutoStirrer ?? App.Config.PlcAutoStirrer,
ShortcutKey.START_STIRRER_MW2, ShortcutKey.STOP_STIRRER_MW2, ShortcutKey.TOGGLE_STIRRER_MW2, ShortcutKey.INDICATE_STIRRER_MW2,
State.MW2_Stirrer_IsActive, State.MP2_State == MotorState.Forward, State.MW2_FillLevel);
Dictionary<Pump, bool> pumpHighlightOff = [];
foreach (var (key, d) in Graph.PathShortcuts) {
if (App.Config.MapKey(key) is not int idx)
continue;
var isActive = d.Pump.IsActive;
var hasClearnace = d.Sink.HasFillingClearance;
var paths = plant.Graph.SelectedPaths.Select(p => (Pipeline.Path?)p)
.Where(p => p?.Matches(d.Source, d.Intermediate, d.Sink) ?? false);
if (paths.FirstOrDefault() is Pipeline.Path path) {
var isReady = path.IsReady;
var isDefault = !path.Hops.SkipLast(1).Any(h => h.Node is not Valve && h.Node is not PipeJoin && h.Node is not Pump);
k.SetBacklight(idx, isActive ? isDefault ? Xbe24Keyboard.Cyan : Xbe24Keyboard.Purple : isDefault ? Xbe24Keyboard.Blue : Xbe24Keyboard.DarkPurple, !isReady);
k.SetBacklight(idx,
!hasClearnace && k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange :
!hasClearnace ? Xbe24Keyboard.Red :
isActive && isDefault ? Xbe24Keyboard.Cyan :
isActive ? Xbe24Keyboard.Purple :
isDefault ? Xbe24Keyboard.Blue :
Xbe24Keyboard.DarkPurple, !hasClearnace || !isReady);
} else {
var isFree = Graph.GetFreePath([d.Source, d.Sink], overrideStart: true) != null;
if (isActive && k.IsKeyPressed(idx)) pumpHighlightOff[d.Pump] = true;
k.SetBacklight(idx, isActive ? k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange : Xbe24Keyboard.Neutral : isFree ? Xbe24Keyboard.LightBlue : k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange : Xbe24Keyboard.Neutral);
k.SetBacklight(idx,
(!isFree || !hasClearnace) && k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange :
(!isFree || !hasClearnace) ? Xbe24Keyboard.LightRed :
isActive && k.IsKeyPressed(idx) ? Xbe24Keyboard.Orange :
isActive ? Xbe24Keyboard.Neutral :
Xbe24Keyboard.LightBlue);
}
}
if (!plant.State.MP2_HasPathClearance && plant.State.MP2_HasDryRunClearance && plant.State.MP2_WantsPathClearance) {
k.SetBacklight(ShortcutKey.START_MP2, plant.State.MP2_WantActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen, true);
} else {
k.SetBacklight(ShortcutKey.START_MP2, !State.MP2_HasClearance ? k.IsKeyPressed(ShortcutKey.START_MP2) ? Xbe24Keyboard.Orange : Xbe24Keyboard.LightRed : State.MP2_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
}
if (!plant.State.MP1_HasPathClearance && plant.State.MP1_HasDryRunClearance && plant.State.MP1_WantsPathClearance) {
k.SetBacklight(ShortcutKey.START_MP1, plant.State.MP1_WantActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen, true);
} else {
k.SetBacklight(ShortcutKey.START_MP1, !State.MP1_HasClearance ? k.IsKeyPressed(ShortcutKey.START_MP1) ? Xbe24Keyboard.Orange : Xbe24Keyboard.LightRed : State.MP1_IsActive ? Xbe24Keyboard.Green : Xbe24Keyboard.LightGreen);
}
k.SetBacklight(ShortcutKey.STOP_MP2, pumpHighlightOff.GetValueOrDefault(Graph.MP2) ? Xbe24Keyboard.Orange : !State.MP2_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
k.SetBacklight(ShortcutKey.STOP_MP1, pumpHighlightOff.GetValueOrDefault(Graph.MP1) ? Xbe24Keyboard.Orange : !State.MP1_IsActive ? Xbe24Keyboard.Red : Xbe24Keyboard.LightRed);
UpdatePumpKeys(k, ShortcutKey.START_MP1, ShortcutKey.STOP_MP1, ShortcutKey.TOGGLE_MP1, ShortcutKey.INDICATE_MP1,
plant.State.MP1, pumpHighlightOff.GetValueOrDefault(Graph.MP1), true);
UpdatePumpKeys(k, ShortcutKey.START_MP2, ShortcutKey.STOP_MP2, ShortcutKey.TOGGLE_MP2, ShortcutKey.INDICATE_MP2,
plant.State.MP2, pumpHighlightOff.GetValueOrDefault(Graph.MP2), true);
UpdatePumpKeys(k, ShortcutKey.ENABLE_P12, ShortcutKey.DISABLE_P12, ShortcutKey.TOGGLE_P12, ShortcutKey.INDICATE_P12,
plant.State.P12, pumpHighlightOff.GetValueOrDefault(Graph.P12), false);
UpdatePumpKeys(k, ShortcutKey.ENABLE_P3, ShortcutKey.DISABLE_P3, ShortcutKey.TOGGLE_P3, ShortcutKey.INDICATE_P3,
plant.State.P3, pumpHighlightOff.GetValueOrDefault(Graph.P3), false);
UpdatePumpKeys(k, ShortcutKey.ENABLE_P4, ShortcutKey.DISABLE_P4, ShortcutKey.TOGGLE_P4, ShortcutKey.INDICATE_P4,
plant.State.P4, pumpHighlightOff.GetValueOrDefault(Graph.P4), false);
UpdatePumpKeys(k, ShortcutKey.ENABLE_P5, ShortcutKey.DISABLE_P5, ShortcutKey.TOGGLE_P5, ShortcutKey.INDICATE_P5,
plant.State.P5, pumpHighlightOff.GetValueOrDefault(Graph.P5), false);
UpdatePumpKeys(k, ShortcutKey.ENABLE_P6, ShortcutKey.DISABLE_P6, ShortcutKey.TOGGLE_P6, ShortcutKey.INDICATE_P6,
plant.State.P6, pumpHighlightOff.GetValueOrDefault(Graph.P6), false);
}
public void Dispose() {
@@ -279,34 +406,61 @@ namespace PamhagenSysCtrl.Helpers {
private void Keyboard_KeyDown(object? sender, int keyIndex) {
if (Plc == null || App.Config.MapKey(keyIndex) is not ShortcutKey key) return;
try {
if (key == ShortcutKey.START_REBLER) {
Plc.StartRebler();
} else if (key == ShortcutKey.STOP_REBLER) {
Plc.StopRebler();
} else if (key == ShortcutKey.START_TROUGH_AUGER) {
Plc.StartTroughAuger();
} else if (key == ShortcutKey.STOP_TROUGH_AUGER) {
Plc.StopTroughAuger();
} else if (key == ShortcutKey.SELECT_MW2) {
Plc.SelectMW2();
} else if (key == ShortcutKey.SELECT_MW1) {
Plc.SelectMW1();
} else if (key == ShortcutKey.START_MP2) {
Plc.StartMP2Forward();
} else if (key == ShortcutKey.STOP_MP2) {
Plc.StopMP2();
} else if (key == ShortcutKey.START_MP1) {
Plc.StartMP1Forward();
} else if (key == ShortcutKey.STOP_MP1) {
Plc.StopMP1();
} else if (Graph.PathShortcuts.TryGetValue(key, out var path)) {
if (Graph.PathShortcuts.TryGetValue(key, out var path)) {
FastSelect(path.Source, path.Intermediate, path.Sink);
} else {
return;
switch (key) {
case ShortcutKey.START_REBLER: StartRebler(); break;
case ShortcutKey.STOP_REBLER: StopRebler(); break;
case ShortcutKey.TOGGLE_REBLER: ToggleRebler(); break;
case ShortcutKey.START_WASTE_DISPOSAL: StartWasteDisposal(); break;
case ShortcutKey.STOP_WASTE_DISPOSAL: StopWasteDisposal(); break;
case ShortcutKey.TOGGLE_WASTE_DISPOSAL: ToggleWasteDisposal(); break;
case ShortcutKey.START_AUGER1: StartAuger1(); break;
case ShortcutKey.STOP_AUGER1: StopAuger1(); break;
case ShortcutKey.TOGGLE_AUGER1: ToggleAuger1(); break;
case ShortcutKey.START_AUGER2: StartAuger2(); break;
case ShortcutKey.STOP_AUGER2: StopAuger2(); break;
case ShortcutKey.TOGGLE_AUGER2: ToggleAuger2(); break;
case ShortcutKey.START_AUGER3: StartAuger3(); break;
case ShortcutKey.STOP_AUGER3: StopAuger3(); break;
case ShortcutKey.TOGGLE_AUGER3: ToggleAuger3(); break;
case ShortcutKey.START_TROUGH_AUGER: StartTroughAuger(); break;
case ShortcutKey.STOP_TROUGH_AUGER: StopTroughAuger(); break;
case ShortcutKey.TOGGLE_TROUGH_AUGER: ToggleTroughAuger(); break;
case ShortcutKey.SELECT_MW1: SelectMW1(); break;
case ShortcutKey.SELECT_MW2: SelectMW2(); break;
case ShortcutKey.START_STIRRER_MW1: StartStirrerMW1(); break;
case ShortcutKey.STOP_STIRRER_MW1: StopStirrerMW1(); break;
case ShortcutKey.TOGGLE_STIRRER_MW1: ToggleStirrerMW1(); break;
case ShortcutKey.START_STIRRER_MW2: StartStirrerMW2(); break;
case ShortcutKey.STOP_STIRRER_MW2: StopStirrerMW2(); break;
case ShortcutKey.TOGGLE_STIRRER_MW2: ToggleStirrerMW2(); break;
case ShortcutKey.START_MP1: StartMP1Forward(); break;
case ShortcutKey.STOP_MP1: StopMP1(); break;
case ShortcutKey.TOGGLE_MP1: ToggleMP1(); break;
case ShortcutKey.START_MP2: StartMP2Forward(); break;
case ShortcutKey.STOP_MP2: StopMP2(); break;
case ShortcutKey.TOGGLE_MP2: ToggleMP2(); break;
case ShortcutKey.ENABLE_P12: EnableP12(); break;
case ShortcutKey.DISABLE_P12: DisableP12(); break;
case ShortcutKey.TOGGLE_P12: ToggleP12(); break;
case ShortcutKey.ENABLE_P3: EnableP3(); break;
case ShortcutKey.DISABLE_P3: DisableP3(); break;
case ShortcutKey.TOGGLE_P3: ToggleP3(); break;
case ShortcutKey.ENABLE_P4: EnableP4(); break;
case ShortcutKey.DISABLE_P4: DisableP4(); break;
case ShortcutKey.TOGGLE_P4: ToggleP4(); break;
case ShortcutKey.ENABLE_P5: EnableP5(); break;
case ShortcutKey.DISABLE_P5: DisableP5(); break;
case ShortcutKey.TOGGLE_P5: ToggleP5(); break;
case ShortcutKey.ENABLE_P6: EnableP6(); break;
case ShortcutKey.DISABLE_P6: DisableP6(); break;
case ShortcutKey.TOGGLE_P6: ToggleP6(); break;
default: return;
}
}
RaiseUpdateEvent(new());
} catch (NoClearanceException) {
// Keyboard?.SetBacklight(keyIndex, Color.FromRgb(255, 0, 0));
} catch (Exception) {
// ignore
}
@@ -334,6 +488,8 @@ namespace PamhagenSysCtrl.Helpers {
public void StopAuger2() => Plc?.StopAuger2();
public void StartAuger3() => Plc?.StartAuger3();
public void StopAuger3() => Plc?.StopAuger3();
public void StartWasteDisposal() => Plc?.StartWasteDisposal();
public void StopWasteDisposal() => Plc?.StopWasteDisposal();
public void StartMP1Forward() => Plc?.StartMP1Forward();
public void StartMP1Backward() => Plc?.StartMP1Backward();
public void StopMP1() => Plc?.StopMP1();
@@ -350,5 +506,125 @@ namespace PamhagenSysCtrl.Helpers {
public void DisableP5() => Plc?.DisableP5();
public void EnableP6() => Plc?.EnableP6();
public void DisableP6() => Plc?.DisableP6();
public void ToggleTroughAuger() {
if (State.TroughAuger_IsActive) {
StopTroughAuger();
} else {
StartTroughAuger();
}
}
public void ToggleRebler() {
if (State.Rebler_IsActive) {
StopRebler();
} else {
StartRebler();
}
}
public void ToggleAuger1() {
if (State.Auger1_IsActive) {
StopAuger1();
} else {
StartAuger1();
}
}
public void ToggleAuger2() {
if (State.Auger2_IsActive) {
StopAuger2();
} else {
StartAuger2();
}
}
public void ToggleAuger3() {
if (State.Auger3_IsActive) {
StopAuger3();
} else {
StartAuger3();
}
}
public void ToggleWasteDisposal() {
if (State.WasteDisposal_IsActive) {
StopWasteDisposal();
} else {
StartWasteDisposal();
}
}
public void ToggleStirrerMW1() {
if (State.MW1_Stirrer_IsActive) {
StopStirrerMW1();
} else {
StartStirrerMW1();
}
}
public void ToggleStirrerMW2() {
if (State.MW2_Stirrer_IsActive) {
StopStirrerMW2();
} else {
StartStirrerMW2();
}
}
public void ToggleMP1() {
if (State.MP1_IsActive || State.MP1_WantActive) {
StopMP1();
} else {
StartMP1Forward();
}
}
public void ToggleMP2() {
if (State.MP2_IsActive || State.MP2_WantActive) {
StopMP2();
} else {
StartMP2Forward();
}
}
public void ToggleP12() {
if (State.P12_IsActive || State.P12_WantActive) {
EnableP12();
} else {
DisableP12();
}
}
public void ToggleP3() {
if (State.P3_IsActive || State.P3_WantActive) {
EnableP3();
} else {
DisableP3();
}
}
public void ToggleP4() {
if (State.P4_IsActive || State.P4_WantActive) {
EnableP4();
} else {
DisableP4();
}
}
public void ToggleP5() {
if (State.P5_IsActive || State.P5_WantActive) {
EnableP5();
} else {
DisableP5();
}
}
public void ToggleP6() {
if (State.P6_IsActive || State.P6_WantActive) {
EnableP6();
} else {
DisableP6();
}
}
}
}
@@ -2,6 +2,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
public interface ISink : INode {
public double TopY { get; }
public bool IsFull { get; }
public bool HasFillingClearance { get; }
public int? CapacityLiters { get; }
}
}
+4 -1
View File
@@ -18,21 +18,24 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
public double TopY => CenterY - DIAMETER / 2;
public FillState FillState => CallbackFillState();
public bool IsFull => FillState == FillState.Full;
public bool HasFillingClearance => CallbackFillingClearance();
public int? CapacityLiters { get; set; }
protected Func<FillState> CallbackFillState;
protected Func<bool> CallbackFillingClearance;
private Polygon? _frame;
private Ellipse? _circle;
private TextBlock? _text;
public Press(string label, double x, double y, int capacityLiters, Func<FillState> cbFillState) {
public Press(string label, double x, double y, int capacityLiters, Func<FillState> cbFillState, Func<bool> cbFillingClearance) {
CenterX = x;
CenterY = y;
Label = label;
CapacityLiters = capacityLiters;
CallbackFillState = cbFillState;
CallbackFillingClearance = cbFillingClearance;
Inputs = new HashSet<IEdge>();
Outputs = new HashSet<IEdge>();
}
+4 -1
View File
@@ -17,6 +17,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
public FillState FillState => CallbackFillState();
public bool IsFull => FillState == FillState.Full;
public bool IsFilled => FillState != FillState.Empty;
public bool HasFillingClearance => CallbackFillingClearance();
public ISet<IEdge> Inputs { get; init; }
public ISet<IEdge> Outputs { get; init; }
@@ -24,16 +25,18 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
public int? CapacityLiters { get; set; }
protected Func<FillState> CallbackFillState;
protected Func<bool> CallbackFillingClearance;
private Shape? _rect;
private TextBlock? _text;
public Tank(string label, double x, double y, int capacityLiters, Func<FillState> cbFillState) {
public Tank(string label, double x, double y, int capacityLiters, Func<FillState> cbFillState, Func<bool> cbFillingClearance) {
CenterX = x;
CenterY = y;
Label = label;
CapacityLiters = capacityLiters;
CallbackFillState = cbFillState;
CallbackFillingClearance = cbFillingClearance;
Inputs = new HashSet<IEdge>();
Outputs = new HashSet<IEdge>();
}
@@ -49,7 +49,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
protected static FillState Int3ToFillState(int n, bool bigEndian = true) {
return
(bigEndian && (n & 0x4) != 0) || (!bigEndian && (n & 0x1) != 0) ? FillState.Full :
(bigEndian && (n & 0x4) != 0) || (!bigEndian && (n & 0x1) != 0) ? FillState.AlmostFull :
(bigEndian && (n & 0x2) != 0) || (!bigEndian && (n & 0x2) != 0) ? FillState.Half :
(bigEndian && (n & 0x1) != 0) || (!bigEndian && (n & 0x4) != 0) ? FillState.Filled :
n == 0 ? FillState.Empty :
+30 -12
View File
@@ -20,6 +20,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
protected LegacyPamhagenPlc Plc;
public PamhagenState State { get; private set; }
public PamhagenState LastState { get; private set; }
public string? ComPort => Plc?.ComPort;
public T1.Status? LastStatus => Plc?.LastStatus;
@@ -31,12 +32,16 @@ namespace PamhagenSysCtrl.Helpers.Plc {
internal readonly int ConsiderLastSensorsOpen;
internal readonly int ConsiderLastSensorsClose;
internal readonly int ConsiderLastSensorsMW;
internal readonly FillState AutoStirrer;
public PamhagenPlc(string comPort, int sensorDelayOpenMs, int sensorDelayCloseMs, Parity parity = Parity.Odd) {
public PamhagenPlc(string comPort, int sensorDelayOpenMs, int sensorDelayCloseMs, int sensorDelayMwMs, FillState autoStirrer = FillState.Half, Parity parity = Parity.Odd) {
Plc = new(comPort, parity);
ConsiderLastSensorsOpen = sensorDelayOpenMs / 125 + 1;
ConsiderLastSensorsClose = sensorDelayCloseMs / 125 + 1;
LastSensors = new LegacyPamhagenPlc.SensorStates[Math.Max(ConsiderLastSensorsOpen, ConsiderLastSensorsClose)];
ConsiderLastSensorsMW = sensorDelayMwMs / 125 + 1;
AutoStirrer = autoStirrer;
LastSensors = new LegacyPamhagenPlc.SensorStates[Math.Max(Math.Max(ConsiderLastSensorsOpen, ConsiderLastSensorsClose), ConsiderLastSensorsMW)];
}
public void Dispose() {
@@ -51,6 +56,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
var sensors = await Plc.ReadInputs();
LastSensors[0] = sensors;
State = new(LastSensors, this);
LastState = State;
}
public async Task Shutdown() {
@@ -67,7 +73,9 @@ namespace PamhagenSysCtrl.Helpers.Plc {
var sensors = await Plc.ReadInputs();
Array.Copy(LastSensors, 0, LastSensors, 1, LastSensors.Length - 1);
LastSensors[0] = sensors;
State = new(LastSensors, this);
var current = new PamhagenState(LastSensors, this);
LastState = State;
State = current;
UpdateInterlocks();
}
@@ -103,14 +111,10 @@ namespace PamhagenSysCtrl.Helpers.Plc {
if (P6_WantActive && State.P6_HasClearance) EnableP6();
if (!ManualControlMode) {
if (State.MP1_State == MotorState.Forward && State.MW1_FillLevel >= FillState.Half && !State.MW1_Stirrer_IsActive) {
StartStirrerMW1();
} else if (State.MW2_Stirrer_IsActive && (!State.MP1_IsActive || State.MW1_FillLevel < FillState.Half)) {
if (State.MW1_Stirrer_IsActive && (State.MW1_FillLevel == FillState.Empty || (LastState.MW1_FillLevel >= AutoStirrer && State.MW1_FillLevel < AutoStirrer))) {
StopStirrerMW1();
}
if (State.MP2_State == MotorState.Forward && State.MW2_FillLevel >= FillState.Half && !State.MW2_Stirrer_IsActive) {
StartStirrerMW2();
} else if (State.MW2_Stirrer_IsActive && (!State.MP2_IsActive || State.MW2_FillLevel < FillState.Half)) {
if (State.MW2_Stirrer_IsActive && (State.MW2_FillLevel == FillState.Empty || (LastState.MW2_FillLevel >= AutoStirrer && State.MW2_FillLevel < AutoStirrer))) {
StopStirrerMW2();
}
}
@@ -154,6 +158,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
}
public void StartStirrerMW1() {
if (!ManualControlMode && State.MW1_FillLevel == FillState.Empty) throw new NoClearanceException("MW1 ist leer");
Actuators.StirrerMW1 = true;
}
@@ -162,6 +167,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
}
public void StartStirrerMW2() {
if (!ManualControlMode && State.MW2_FillLevel == FillState.Empty) throw new NoClearanceException("MW2 ist leer");
Actuators.StirrerMW2 = true;
}
@@ -203,6 +209,18 @@ namespace PamhagenSysCtrl.Helpers.Plc {
Actuators.Auger3 = false;
}
public void StartWasteDisposal() {
StartAuger1();
StartAuger2();
StartAuger3();
}
public void StopWasteDisposal() {
StopAuger1();
StopAuger2();
StopAuger3();
}
public void StartGradationPump() {
Actuators.GradationPump = true;
}
@@ -221,7 +239,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
MP1_WantActive = false;
if (Actuators.MP1 == MotorState.Backward) throw new NoClearanceException("MP1 läuft bereits (zurück)");
Actuators.MP1 = MotorState.Forward;
if (State.MW1_FillLevel >= FillState.Half) StartStirrerMW1();
if (!ManualControlMode && State.MW1_FillLevel >= AutoStirrer) StartStirrerMW1();
}
public void StartMP1Backward() {
@@ -247,7 +265,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
MP2_WantActive = false;
if (Actuators.MP2 == MotorState.Backward) throw new NoClearanceException("MP2 läuft bereits (zurück)");
Actuators.MP2 = MotorState.Forward;
if (State.MW2_FillLevel >= FillState.Half) StartStirrerMW2();
if (!ManualControlMode && State.MW2_FillLevel >= AutoStirrer) StartStirrerMW2();
}
public void StartMP2Backward() {
@@ -260,7 +278,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
public void StopMP2() {
MP2_WantActive = false;
Actuators.MP2 = MotorState.Halt;
if (!ManualControlMode) StopStirrerMW1();
if (!ManualControlMode) StopStirrerMW2();
}
public void EnableP12() {
+39 -9
View File
@@ -1,6 +1,11 @@
namespace PamhagenSysCtrl.Helpers.Plc {
public readonly record struct PamhagenState {
public readonly record struct PumpState(
MotorState State, bool IsActive,
bool HasClearance, bool HasPathClearance, bool HasDryRunClearance,
bool WantsPathClearance, bool WantActive);
private readonly LegacyPamhagenPlc.SensorStates Sensors;
private readonly PamhagenPlc Plc;
private LegacyPamhagenPlc.ActuatorStates Actuators => Plc == null ? default : Plc.Actuators;
@@ -17,8 +22,9 @@ namespace PamhagenSysCtrl.Helpers.Plc {
public bool MW2_IsSelected => Sensors.TroughSelector == 2;
public bool MW1_WantSelected => Actuators.GetV(58);
public bool MW2_WantSelected => !Actuators.GetV(58);
public FillState MW1_FillLevel => Sensors.FillLevelMW1;
public FillState MW2_FillLevel => Sensors.FillLevelMW2;
public readonly FillState MW1_FillLevel { get; }
public readonly FillState MW2_FillLevel { get; }
public FillState[] Tanks_FillLevel => Sensors.FillLevelTanks ?? [FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown, FillState.Unknown];
public FillState T1_FillLevel => Sensors.FillLevelTanks[0];
@@ -42,6 +48,7 @@ namespace PamhagenSysCtrl.Helpers.Plc {
public bool Auger2_IsActive => Actuators.Auger2;
public bool Auger3_IsActive => Actuators.Auger3;
public bool WasteDisposal_IsActive => Auger1_IsActive || Auger2_IsActive || Auger3_IsActive;
public bool WasteDisposal_IsConsistent => (Auger1_IsActive && Auger2_IsActive && Auger3_IsActive) || (!Auger1_IsActive && !Auger2_IsActive && !Auger3_IsActive);
public MotorState MP1_State => Actuators.MP1;
public MotorState MP2_State => Actuators.MP2;
@@ -85,13 +92,13 @@ namespace PamhagenSysCtrl.Helpers.Plc {
public readonly bool P5_WantsPathClearance { get; }
public readonly bool P6_WantsPathClearance { get; }
public bool MP1_WantActive => Plc.MP1_WantActive;
public bool MP2_WantActive => Plc.MP2_WantActive;
public bool P12_WantActive => Plc.P12_WantActive;
public bool P3_WantActive => Plc.P3_WantActive;
public bool P4_WantActive => Plc.P4_WantActive;
public bool P5_WantActive => Plc.P5_WantActive;
public bool P6_WantActive => Plc.P6_WantActive;
public bool MP1_WantActive => Plc != null && Plc.MP1_WantActive;
public bool MP2_WantActive => Plc != null && Plc.MP2_WantActive;
public bool P12_WantActive => Plc != null && Plc.P12_WantActive;
public bool P3_WantActive => Plc != null && Plc.P3_WantActive;
public bool P4_WantActive => Plc != null && Plc.P4_WantActive;
public bool P5_WantActive => Plc != null && Plc.P5_WantActive;
public bool P6_WantActive => Plc != null && Plc.P6_WantActive;
public bool MP1_HasPathClearance => OverridePathClearances || MP1_PathClearance;
public bool MP2_HasPathClearance => OverridePathClearances || MP2_PathClearance;
@@ -115,6 +122,14 @@ namespace PamhagenSysCtrl.Helpers.Plc {
public bool P5_HasClearance => P4_HasDryRunClearance && P5_HasPathClearance;
public bool P6_HasClearance => P6_HasDryRunClearance && P6_HasPathClearance;
public PumpState MP1 => new(MP1_State, MP1_IsActive, MP1_HasClearance, MP1_HasPathClearance, MP1_HasDryRunClearance, MP1_WantsPathClearance, MP1_WantActive);
public PumpState MP2 => new(MP2_State, MP2_IsActive, MP2_HasClearance, MP2_HasPathClearance, MP2_HasDryRunClearance, MP2_WantsPathClearance, MP2_WantActive);
public PumpState P12 => new(P12_State, P12_IsActive, P12_HasClearance, P12_HasPathClearance, P12_HasDryRunClearance, P12_WantsPathClearance, P12_WantActive);
public PumpState P3 => new(P3_State, P3_IsActive, P3_HasClearance, P3_HasPathClearance, P3_HasDryRunClearance, P3_WantsPathClearance, P3_WantActive);
public PumpState P4 => new(P4_State, P4_IsActive, P4_HasClearance, P4_HasPathClearance, P4_HasDryRunClearance, P4_WantsPathClearance, P4_WantActive);
public PumpState P5 => new(P5_State, P5_IsActive, P5_HasClearance, P5_HasPathClearance, P5_HasDryRunClearance, P5_WantsPathClearance, P5_WantActive);
public PumpState P6 => new(P6_State, P6_IsActive, P6_HasClearance, P6_HasPathClearance, P6_HasDryRunClearance, P6_WantsPathClearance, P6_WantActive);
public PamhagenState(IEnumerable<LegacyPamhagenPlc.SensorStates> sensors, PamhagenPlc plc) {
Sensors = sensors.First();
Plc = plc;
@@ -122,6 +137,21 @@ namespace PamhagenSysCtrl.Helpers.Plc {
OpenValves = sensors.Take(Plc.ConsiderLastSensorsOpen).Aggregate(-1L, (m, s) => m & ~s.PressureSensors);
ClosedValves = sensors.Take(Plc.ConsiderLastSensorsClose).Aggregate(-1L, (m, s) => m & s.PressureSensors);
var mw1 = sensors.Take(Plc.ConsiderLastSensorsMW).Select(s => s.FillLevelMW1).Where(s => s != FillState.Unknown).Distinct().ToArray();
var mw2 = sensors.Take(Plc.ConsiderLastSensorsMW).Select(s => s.FillLevelMW2).Where(s => s != FillState.Unknown).Distinct().ToArray();
MW1_FillLevel =
mw1.Contains(FillState.Invalid) ? FillState.Invalid :
mw1.Length == 1 && mw1[0] == FillState.Empty ? mw1[0] :
mw1.Length == 1 ? mw1[0] + 1 :
mw1.Length >= 2 ? mw1[0] > mw1[1] ? mw1[0] : mw1[1] :
FillState.Unknown;
MW2_FillLevel =
mw2.Contains(FillState.Invalid) ? FillState.Invalid :
mw2.Length == 1 && mw2[0] == FillState.Empty ? mw2[0] :
mw2.Length == 1 ? mw2[0] + 1 :
mw2.Length >= 2 ? mw2[0] > mw2[1] ? mw2[0] : mw2[1] :
FillState.Unknown;
MP1_WantsPathClearance = WantsPathClearnace(this, Paths.MP1);
MP2_WantsPathClearance = WantsPathClearnace(this, Paths.MP2);
P12_WantsPathClearance = WantsPathClearnace(this, Paths.P12);
+2
View File
@@ -11,6 +11,7 @@ namespace PamhagenSysCtrl.Helpers {
public readonly bool GetKey(int n) => (Rows[n / 6] & (1 << (n % 6))) != 0;
}
public static readonly Color Off = Color.FromArgb(0, 0, 0);
public static readonly Color DefaltBacklight = Color.FromArgb(3, 3, 3);
public static readonly Color Neutral = Color.FromArgb(4, 4, 4);
public static readonly Color Red = Color.FromArgb(255, 0, 0);
@@ -22,6 +23,7 @@ namespace PamhagenSysCtrl.Helpers {
public static readonly Color Orange = Color.FromArgb(255, 32, 0);
public static readonly Color DarkPurple = Color.FromArgb(128, 0, 128);
public static readonly Color Purple = Color.FromArgb(255, 64, 255);
public static readonly Color Lime = Color.FromArgb(64, 255, 4);
public static readonly Color LightRed = Color.FromArgb(32, 4, 4);
public static readonly Color LightGreen = Color.FromArgb(4, 32, 4);
public static readonly Color LightBlue = Color.FromArgb(4, 4, 32);