This commit is contained in:
1 parent
ed4bbd09bd
commit
50f6174af1
14 files changed
+438
-78
No files matched your search
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,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));
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
@@ -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 :
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user