diff --git a/PamhagenSysCtrl/Helpers/PamhagenPlant.cs b/PamhagenSysCtrl/Helpers/PamhagenPlant.cs index 4e2419d..2f93968 100644 --- a/PamhagenSysCtrl/Helpers/PamhagenPlant.cs +++ b/PamhagenSysCtrl/Helpers/PamhagenPlant.cs @@ -1,9 +1,10 @@ -using System.Windows; +using System.IO; +using System.Windows; namespace PamhagenSysCtrl.Helpers { public class PamhagenPlant : IDisposable { - protected PamhagenPlc Plc; + protected PamhagenPlc? Plc; protected bool IsRunning = true; protected Thread? BackgroundThread; @@ -61,6 +62,7 @@ namespace PamhagenSysCtrl.Helpers { } public async Task StartThread() { + if (Plc == null) throw new Exception(); await Plc.TestConnection(); Actuators = await Plc.ReadOutputs(); BackgroundThread = new Thread(new ParameterizedThreadStart(BackgroundLoop)); @@ -71,12 +73,12 @@ namespace PamhagenSysCtrl.Helpers { IsRunning = false; BackgroundThread?.Interrupt(); BackgroundThread?.Join(); - Plc.Dispose(); + Plc?.Dispose(); GC.SuppressFinalize(this); } protected async void BackgroundLoop(object? parameters) { - while (IsRunning) { + while (IsRunning && Plc != null) { try { if (ActuatorsChanged) { await Plc.WriteOutputs(Actuators); @@ -90,10 +92,16 @@ namespace PamhagenSysCtrl.Helpers { var str = "Bei der SPS ist ein Fehler aufgetreten:\n\n" + exc.Message; if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; MessageBox.Show(str, "SPS-Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + if (exc is TimeoutException or IOException) { + Plc?.Dispose(); + Plc = null; + IsRunning = false; + } } } try { - await Plc.WriteOutputs(new()); + if (Plc != null) + await Plc.WriteOutputs(new()); } catch (Exception exc) { var str = "Beim Schließen der Verbindung zur SPS ist ein Fehler aufgetreten:\n\n" + exc.Message; if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message; diff --git a/PamhagenSysCtrl/Helpers/T1.cs b/PamhagenSysCtrl/Helpers/T1.cs index 61aa4e8..cfaa230 100644 --- a/PamhagenSysCtrl/Helpers/T1.cs +++ b/PamhagenSysCtrl/Helpers/T1.cs @@ -31,15 +31,15 @@ namespace PamhagenSysCtrl.Helpers { protected async Task SendCommand(string cmd, string? data = null, bool checksum = true) { // max 255 bytes byte[] d = new byte[255]; - int n = Encoding.ASCII.GetBytes($"(A{1:02}{cmd}", d); + int n = Encoding.ASCII.GetBytes($"(A{1:00}{cmd}", d); if (data != null) { if (data.Length > 244) throw new ArgumentException("T1 playload too long"); n += Encoding.ASCII.GetBytes(data, 0, data.Length, d, n); } if (checksum) { d[n++] = (byte)'&'; - byte chk = d.Take(n).Aggregate((s, c) => s = (byte)((s + c) & 0xFF)); - n += Encoding.ASCII.GetBytes($"{chk:02X}", 0, 2, d, n); + byte chk = d.Take(n).Aggregate((s, c) => (byte)((s + c) & 0xFF)); + n += Encoding.ASCII.GetBytes($"{chk:X2}", 0, 2, d, n); } d[n++] = (byte)')'; d[n++] = (byte)'\r'; @@ -55,13 +55,13 @@ namespace PamhagenSysCtrl.Helpers { } var chk1 = (byte)Convert.ToInt32(line[^4..^2], 16); - var chk2 = Encoding.ASCII.GetBytes(line).SkipLast(5).Aggregate((s, c) => (byte)((s + c) & 0xFF)); + var chk2 = Encoding.ASCII.GetBytes(line).SkipLast(4).Aggregate((s, c) => (byte)((s + c) & 0xFF)); if (chk1 != chk2) { - throw new IOException("Ungültige Prüfsumme von SPS (T1)"); + throw new IOException($"Ungültige Prüfsumme von SPS (T1)"); } - var (cmd, data) = (line[3..5], line[5..^5]); - if (cmd == "ST" && data[4] == '6') { + var (cmd, data) = (line[4..6], line[6..^5]); + if (cmd == "ST" && data[3] == '6') { // TODO check for other error bits? await SendCommand("ER"); var (_, res) = await ReceiveResponse("ER"); @@ -124,7 +124,7 @@ namespace PamhagenSysCtrl.Helpers { } public async Task DataWrite(params (string Register, ushort[] Values)[] registers) { - await SendCommand("DW", string.Join(',', registers.Select(r => $"{r.Register},{r.Values.Length}," + string.Join(',', r.Values.Select(v => $"{v:04X}"))))); + await SendCommand("DW", string.Join(',', registers.Select(r => $"{r.Register},{r.Values.Length}," + string.Join(',', r.Values.Select(v => $"{v:X4}"))))); var (_, res) = await ReceiveResponse("ST"); return new Status((Mode)(res[3] - '0'), ((res[0] - '0') << 4) | (res[1] - '0')); } diff --git a/PamhagenSysCtrl/Windows/MainWindow.xaml b/PamhagenSysCtrl/Windows/MainWindow.xaml index 4455a49..57138c9 100644 --- a/PamhagenSysCtrl/Windows/MainWindow.xaml +++ b/PamhagenSysCtrl/Windows/MainWindow.xaml @@ -15,5 +15,8 @@ + + diff --git a/PamhagenSysCtrl/Windows/MainWindow.xaml.cs b/PamhagenSysCtrl/Windows/MainWindow.xaml.cs index daeaf5e..11b982e 100644 --- a/PamhagenSysCtrl/Windows/MainWindow.xaml.cs +++ b/PamhagenSysCtrl/Windows/MainWindow.xaml.cs @@ -24,7 +24,8 @@ namespace PamhagenSysCtrl { borderStyle.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(5))); b.Resources.Add(typeof(Border), borderStyle); b.Click += (sender, evt) => { - if (App.Plant == null) return; + if (App.Plant == null || sender is not Button b) return; + var i = int.Parse($"{b.Content}"[1..]); if (App.Plant.WantValveOpen(i)) { App.Plant.CloseV(i); } else { @@ -62,6 +63,25 @@ namespace PamhagenSysCtrl { b.Foreground = target ? Brushes.DarkRed : Brushes.Black; b.Background = actual ? Brushes.MistyRose : Brushes.WhiteSmoke; } + + Status.Text = $""" + Gradation °Oe: {plant.GradationOe:N2} + Presse Querschnecke: {plant.PresseQuerSchnecke} + Füllstände: + Wanne A1: {plant.FillLevelA1} (ausgewählt: {plant.WantA1Selected}, Status: {plant.IsA1Selected}) + Wanne A2: {plant.FillLevelA2} (ausgewählt: {plant.WantA2Selected}, Status: {plant.IsA2Selected}) + Presse 1: {plant.FillLevelPress1} + Presse 2: {plant.FillLevelPress2} + Tank 1: {plant.FillLevelT1} + Tank 2: {plant.FillLevelT2} + Tank 3: {plant.FillLevelT3} + Tank 4: {plant.FillLevelT4} + Tank 5: {plant.FillLevelT5} + Tank 6: {plant.FillLevelT6} + Tank 7: {plant.FillLevelT7} + Tank 8: {plant.FillLevelT8} + Tank 9: {plant.FillLevelT9} + """; } } }