[#71] Weighing: Fix reconnection behaviour when COM port is connected/disconnected
Some checks failed
Test / Run tests (push) Failing after 2m47s
Some checks failed
Test / Run tests (push) Failing after 2m47s
This commit is contained in:
@@ -15,15 +15,17 @@ namespace Elwig.Helpers.Weighing {
|
||||
public bool IsReady { get; private set; }
|
||||
public bool HasFillingClearance { get; private set; }
|
||||
|
||||
public event IEventScale.EventHandler<WeighingEventArgs> WeighingEvent;
|
||||
public event IEventScale.EventHandler<WeighingEventArgs>? WeighingEvent;
|
||||
|
||||
private bool IsRunning = true;
|
||||
private readonly Thread BackgroundThread;
|
||||
private readonly string Connection;
|
||||
|
||||
public AveryEventScale(string id, string model, string cnx, string? empty = null, string? filling = null, int? limit = null, string? log = null) :
|
||||
base(cnx, empty, filling, limit, log) {
|
||||
public AveryEventScale(string id, string model, string cnx, string? log = null, bool required = true) :
|
||||
base(cnx, null, null, null, log, true, !required) {
|
||||
ScaleId = id;
|
||||
Model = model;
|
||||
Connection = cnx;
|
||||
IsReady = true;
|
||||
HasFillingClearance = false;
|
||||
Stream.WriteTimeout = -1;
|
||||
@@ -50,19 +52,49 @@ namespace Elwig.Helpers.Weighing {
|
||||
var data = await Receive();
|
||||
if (data != null)
|
||||
RaiseWeighingEvent(new WeighingEventArgs(data.Value));
|
||||
} catch (ThreadInterruptedException) {
|
||||
// ignore
|
||||
} catch (IOException) {
|
||||
await Task.Delay(500);
|
||||
await Reconnect();
|
||||
} catch (TimeoutException) {
|
||||
await Task.Delay(500);
|
||||
await Reconnect();
|
||||
} catch (Exception ex) {
|
||||
MessageBox.Show($"Beim Wiegen ist ein Fehler Aufgetreten:\n\n{ex.Message}", "Waagenfehler",
|
||||
MessageBox.Show($"Beim Wiegen ist ein Fehler Aufgetreten:\n\n{ex.Message} ({ex.GetType().Name})", "Waagenfehler",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task Reconnect() {
|
||||
try { Reader.Close(); } catch { }
|
||||
try { Stream.Close(); } catch { }
|
||||
try { Serial?.Close(); } catch { }
|
||||
while (IsRunning) {
|
||||
try {
|
||||
if (Connection.StartsWith("serial:")) {
|
||||
Serial = Utils.OpenSerialConnection(Connection);
|
||||
Stream = Serial.BaseStream;
|
||||
} else if (Connection.StartsWith("tcp:")) {
|
||||
Tcp = Utils.OpenTcpConnection(Connection);
|
||||
Stream = Tcp.GetStream();
|
||||
}
|
||||
Reader = new(Stream, Encoding.ASCII, false, 512);
|
||||
break;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<WeighingResult?> Receive() {
|
||||
var line = "";
|
||||
while (line.Length < 33) {
|
||||
var ch = Reader.Read();
|
||||
if (ch == -1) {
|
||||
return null;
|
||||
throw new IOException("Connection closed");
|
||||
} else if (line.Length > 0 || ch == ' ') {
|
||||
line += char.ToString((char)ch);
|
||||
}
|
||||
@@ -71,7 +103,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
if (line == null || line == "") {
|
||||
return null;
|
||||
} else if (line.Length != 33 || line[0] != ' ' || line[9] != ' ' || line[15] != ' ' || line[20] != ' ' || line[32] != ' ') {
|
||||
throw new IOException($"Invalid event from scale: '{line}'");
|
||||
throw new FormatException($"Invalid event from scale: '{line}'");
|
||||
}
|
||||
|
||||
var date = line[ 1.. 9];
|
||||
@@ -81,7 +113,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
var unit = line[30..32];
|
||||
|
||||
if (unit != "kg") {
|
||||
throw new IOException($"Unsupported unit in weighing event: '{unit}'");
|
||||
throw new WeighingException($"Unsupported unit in weighing event: '{unit}'");
|
||||
}
|
||||
|
||||
identNr = identNr.Length > 0 && identNr != "0" ? identNr : null;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
var line = await Reader.ReadUntilAsync('\x03');
|
||||
if (LogPath != null) await File.AppendAllTextAsync(LogPath, $"{line}\r\n");
|
||||
if (line == null || line.Length < 4 || !line.StartsWith('\x02')) {
|
||||
throw new IOException("Invalid response from scale");
|
||||
throw new FormatException("Invalid response from scale");
|
||||
}
|
||||
|
||||
var status = line[1..3];
|
||||
@@ -45,9 +45,9 @@ namespace Elwig.Helpers.Weighing {
|
||||
switch (status[1]) {
|
||||
case 'M': msg = "Waage in Bewegung"; break;
|
||||
}
|
||||
throw new IOException($"Waagenfehler {status}: {msg}");
|
||||
throw new WeighingException($"Waagenfehler {status}: {msg}");
|
||||
} else if (status[0] != ' ') {
|
||||
throw new IOException($"Invalid response from scale (error code {status})");
|
||||
throw new WeighingException($"Invalid response from scale (error code {status})");
|
||||
}
|
||||
|
||||
return line[1..^1];
|
||||
@@ -57,7 +57,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
await SendCommand(incIdentNr ? '\x05' : '?');
|
||||
string record = await ReceiveResponse();
|
||||
if (record.Length != 45)
|
||||
throw new IOException("Invalid response from scale: Received record has invalid size");
|
||||
throw new FormatException("Invalid response from scale: Received record has invalid size");
|
||||
var line = record[2..];
|
||||
|
||||
var brutto = line[ 0.. 7].Trim();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.IO.Ports;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Elwig.Helpers.Weighing {
|
||||
public abstract class Scale : IDisposable {
|
||||
@@ -27,7 +28,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
if (config.Type == "SysTec-IT") {
|
||||
return new SysTecITScale(config.Id, config.Model!, config.Connection!, config.Empty, config.Filling, limit, config.Log);
|
||||
} else if (config.Type == "Avery-Async") {
|
||||
return new AveryEventScale(config.Id, config.Model!, config.Connection!, config.Empty, config.Filling, limit, config.Log);
|
||||
return new AveryEventScale(config.Id, config.Model!, config.Connection!, config.Log, config.Required);
|
||||
} else if (config.Type == "Gassner") {
|
||||
return new GassnerScale(config.Id, config.Model!, config.Connection!, config.Empty, config.Filling, limit, config.Log);
|
||||
} else {
|
||||
@@ -35,10 +36,17 @@ namespace Elwig.Helpers.Weighing {
|
||||
}
|
||||
}
|
||||
|
||||
protected Scale(string cnx, string? empty, string? filling, int? limit, string? log) {
|
||||
protected Scale(string cnx, string? empty, string? filling, int? limit, string? log, bool softFail = false, bool failSilent = false) {
|
||||
if (cnx.StartsWith("serial:")) {
|
||||
Serial = Utils.OpenSerialConnection(cnx);
|
||||
Stream = Serial.BaseStream;
|
||||
try {
|
||||
Serial = Utils.OpenSerialConnection(cnx);
|
||||
} catch (Exception e) {
|
||||
if (!softFail) throw;
|
||||
if (!failSilent)
|
||||
MessageBox.Show($"Verbindung zu Waage konnte nicht hergestellt werden:\n\n{e.Message}", "Waagenfehler",
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
Stream = Serial?.BaseStream ?? Stream.Null;
|
||||
} else if (cnx.StartsWith("tcp:")) {
|
||||
Tcp = Utils.OpenTcpConnection(cnx);
|
||||
Stream = Tcp.GetStream();
|
||||
|
||||
@@ -34,14 +34,14 @@ namespace Elwig.Helpers.Weighing {
|
||||
var line = await Reader.ReadUntilAsync("\r\n");
|
||||
if (LogPath != null) await File.AppendAllTextAsync(LogPath, line);
|
||||
if (line == null || line.Length < 4 || !line.StartsWith('<') || !line.EndsWith(">\r\n")) {
|
||||
throw new IOException("Invalid response from scale");
|
||||
throw new FormatException("Invalid response from scale");
|
||||
}
|
||||
|
||||
var error = line[1..3];
|
||||
string msg = $"Unbekannter Fehler (Fehler code {error})";
|
||||
if (error[0] == '0') {
|
||||
if (error[1] != '0') {
|
||||
throw new IOException($"Invalid response from scale (error code {error})");
|
||||
throw new WeighingException($"Invalid response from scale (error code {error})");
|
||||
}
|
||||
} else if (error[0] == '1') {
|
||||
switch (error[1]) {
|
||||
@@ -52,21 +52,21 @@ namespace Elwig.Helpers.Weighing {
|
||||
case '6': msg = "Drucker nicht bereit"; break;
|
||||
case '7': msg = "Druckmuster enthält ungültiges Kommando"; break;
|
||||
}
|
||||
throw new IOException($"Waagenfehler {error}: {msg}");
|
||||
throw new WeighingException($"Waagenfehler {error}: {msg}");
|
||||
} else if (error[0] == '2') {
|
||||
switch (error[1]) {
|
||||
case '0': msg = "Brutto negativ"; break;
|
||||
}
|
||||
throw new IOException($"Fehler {error}: {msg}");
|
||||
throw new WeighingException($"Fehler {error}: {msg}");
|
||||
} else if (error[0] == '3') {
|
||||
switch (error[1]) {
|
||||
case '1': msg = "Übertragunsfehler"; break;
|
||||
case '2': msg = "Ungültiger Befehl"; break;
|
||||
case '3': msg = "Ungültiger Parameter"; break;
|
||||
}
|
||||
throw new IOException($"Kommunikationsfehler {error}: {msg}");
|
||||
throw new WeighingException($"Kommunikationsfehler {error}: {msg}");
|
||||
} else {
|
||||
throw new IOException($"Invalid response from scale (error code {error})");
|
||||
throw new WeighingException($"Invalid response from scale (error code {error})");
|
||||
}
|
||||
|
||||
return line[1..^3];
|
||||
@@ -76,7 +76,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
await SendCommand(incIdentNr ? $"RN{InternalScaleNr}" : $"RM{InternalScaleNr}");
|
||||
string record = await ReceiveResponse();
|
||||
if (record.Length != 62)
|
||||
throw new IOException("Invalid response from scale: Received record has invalid size");
|
||||
throw new FormatException("Invalid response from scale: Received record has invalid size");
|
||||
var line = record[2..];
|
||||
|
||||
var status = line[ 0.. 2];
|
||||
@@ -94,9 +94,9 @@ namespace Elwig.Helpers.Weighing {
|
||||
var crc16 = line[52..60].Trim();
|
||||
|
||||
if (Utils.CalcCrc16Modbus(record[..54]) != ushort.Parse(crc16)) {
|
||||
throw new IOException($"Invalid response from scale: Invalid CRC16 checksum ({crc16} != {Utils.CalcCrc16Modbus(record[..54])})");
|
||||
throw new WeighingException($"Invalid response from scale: Invalid CRC16 checksum ({crc16} != {Utils.CalcCrc16Modbus(record[..54])})");
|
||||
} else if (unit != "kg") {
|
||||
throw new IOException($"Unsupported unit in weighing response: '{unit}'");
|
||||
throw new WeighingException($"Unsupported unit in weighing response: '{unit}'");
|
||||
}
|
||||
|
||||
identNr = identNr.Length > 0 && identNr != "0" ? identNr : null;
|
||||
|
||||
6
Elwig/Helpers/Weighing/WeighingException.cs
Normal file
6
Elwig/Helpers/Weighing/WeighingException.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Elwig.Helpers.Weighing {
|
||||
class WeighingException(string? message = null) : Exception(message) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user