diff --git a/Elwig/App.xaml.cs b/Elwig/App.xaml.cs index 08d171b..c5f5095 100644 --- a/Elwig/App.xaml.cs +++ b/Elwig/App.xaml.cs @@ -50,6 +50,8 @@ namespace Elwig { int? limit = s[6] == null ? null : int.Parse(s[6]); if (type == "systec") { list.AddLast(new SystecScale(scaleNr, model, cnx, empty, filling, limit)); + } else { + throw new ArgumentException($"Invalid scale type: \"{type}\""); } } catch (Exception e) { MessageBox.Show($"Unable to create scale {s[0]}:\n\n{e.Message}", "Scale Error", MessageBoxButton.OK, MessageBoxImage.Error); diff --git a/Elwig/Helpers/Utils.cs b/Elwig/Helpers/Utils.cs index 3ae33f0..7e06ce6 100644 --- a/Elwig/Helpers/Utils.cs +++ b/Elwig/Helpers/Utils.cs @@ -7,12 +7,62 @@ using System.Windows; using System.Windows.Controls; using System.Diagnostics; using System.Windows.Controls.Primitives; +using System.Text.RegularExpressions; +using System.IO.Ports; +using PdfSharp.Charting; +using System.Net.Sockets; namespace Elwig.Helpers { - public static class Utils { + public static partial class Utils { public static int CurrentSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0); + public static readonly Regex SerialRegex = GeneratedSerialRegex(); + public static readonly Regex TcpRegex = GeneratedTcpRegex(); + + [GeneratedRegex("^serial://([A-Za-z0-9]+):([0-9]+)(,([5-9]),([NOEMSnoems]),(0|1|1\\.5|2|))?$", RegexOptions.Compiled)] + private static partial Regex GeneratedSerialRegex(); + + [GeneratedRegex("^tcp://[A-Za-z0-9:._-]+(:[0-9]+)?$", RegexOptions.Compiled)] + private static partial Regex GeneratedTcpRegex(); + + public static SerialPort OpenSerialConnection(string connection) { + var m = Utils.SerialRegex.Match(connection); + if (!m.Success) + throw new ArgumentException("Invalid connection string for scheme \"serial\""); + + var stop = m.Groups[6].Value; + var parity = m.Groups[5].Value.ToUpper(); + var data = m.Groups[4].Value; + var port = new SerialPort() { + PortName = m.Groups[1].Value, + BaudRate = int.Parse(m.Groups[2].Value), + Parity = parity == "E" ? Parity.Even : + parity == "O" ? Parity.Odd : + parity == "M" ? Parity.Mark : + parity == "S" ? Parity.Space : + Parity.None, + DataBits = data == "" ? 8 : int.Parse(data), + StopBits = (StopBits)(stop == "" ? 1 : stop == "1.5" ? 3 : stop[0] - '0'), + Handshake = Handshake.None, + }; + port.Open(); + return port; + } + + public static TcpClient OpenTcpConnection(string connection) { + var m = Utils.TcpRegex.Match(connection); + if (!m.Success) + throw new ArgumentException("Invalid connection string for scheme \"tcp\""); + + var client = new TcpClient() { + SendTimeout = 250, + ReceiveTimeout = 250, + }; + client.Connect(m.Groups[1].Value, int.Parse(m.Groups[2].Value)); + return client; + } + public static void SetInputChanged(Control input) { var brush = Brushes.Orange; if (input is ComboBox cb) { diff --git a/Elwig/Helpers/Weighing/GassnerScale.cs b/Elwig/Helpers/Weighing/GassnerScale.cs new file mode 100644 index 0000000..3c30f5c --- /dev/null +++ b/Elwig/Helpers/Weighing/GassnerScale.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.IO.Ports; +using System.Text; +using System.Threading.Tasks; + +namespace Elwig.Helpers.Weighing { + public class GassnerScale : IScale { + + protected SerialPort Serial = null; + protected StreamReader Reader; + protected StreamWriter Writer; + + public string Manufacturer => "Gassner"; + public int InternalScaleNr => 1; + public string Model { get; private set; } + public int ScaleNr { get; private set; } + public bool IsReady { get; private set; } + public bool HasFillingClearance { get; private set; } + public int? WeightLimit { get; private set; } + + public GassnerScale(int scaleNr, string model, string connection) { + ScaleNr = scaleNr; + Model = model; + IsReady = true; + HasFillingClearance = false; + + if (!connection.StartsWith("serial:")) + throw new ArgumentException("Unsupported scheme"); + + Serial = Utils.OpenSerialConnection(connection); + Writer = new(Serial.BaseStream, Encoding.ASCII, -1, true); + Reader = new(Serial.BaseStream, Encoding.ASCII, false, -1, true); + } + + public void Dispose() { + Writer.Close(); + Reader.Close(); + Serial.Close(); + GC.SuppressFinalize(this); + } + + public async Task Weigh(bool incIdentNr) { + await Writer.WriteAsync(incIdentNr ? "\x05" : "?"); + // TODO receive response + return new(); + } + + public async Task GetCurrentWeight() { + return await Weigh(false); + } + + public async Task Weigh() { + return await Weigh(true); + } + + public async Task Empty() { } + + public async Task GrantFillingClearance() { } + + public async Task RevokeFillingClearance() { } + } +} diff --git a/Elwig/Helpers/Weighing/SchemberScale.cs b/Elwig/Helpers/Weighing/SchemberScale.cs new file mode 100644 index 0000000..e1ffa69 --- /dev/null +++ b/Elwig/Helpers/Weighing/SchemberScale.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; + +namespace Elwig.Helpers.Weighing { + // TODO implement SchemberScale + public class SchemberScale : IScale { + + public string Manufacturer => "Schember"; + public string Model => throw new NotImplementedException(); + public int ScaleNr => throw new NotImplementedException(); + public int InternalScaleNr => throw new NotImplementedException(); + public bool IsReady => throw new NotImplementedException(); + public bool HasFillingClearance => throw new NotImplementedException(); + public int? WeightLimit => throw new NotImplementedException(); + + public void Dispose() { + throw new NotImplementedException(); + } + + public Task Empty() { + throw new NotImplementedException(); + } + + public Task GetCurrentWeight() { + throw new NotImplementedException(); + } + + public Task GrantFillingClearance() { + throw new NotImplementedException(); + } + + public Task RevokeFillingClearance() { + throw new NotImplementedException(); + } + + public Task Weigh() { + throw new NotImplementedException(); + } + } +} diff --git a/Elwig/Helpers/Weighing/SystecScale.cs b/Elwig/Helpers/Weighing/SystecScale.cs index b4fcb84..45451d3 100644 --- a/Elwig/Helpers/Weighing/SystecScale.cs +++ b/Elwig/Helpers/Weighing/SystecScale.cs @@ -3,7 +3,6 @@ using System.IO; using System.IO.Ports; using System.Net.Sockets; using System.Text; -using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Elwig.Helpers.Weighing { @@ -20,9 +19,6 @@ namespace Elwig.Helpers.Weighing { protected readonly Output? FillingClearanceMode = null; protected readonly int EmptyDelay; - protected static readonly Regex SerialRe = new(@"^serial://([A-Za-z0-9]+):([0-9]+)(,([5-9]),([NOEMSnoems]),(0|1|1\.5|2|))?$", RegexOptions.Compiled); - protected static readonly Regex TcpRe = new(@"^tcp://[A-Za-z0-9:._-]+(:[0-9]+)?$", RegexOptions.Compiled); - public string Manufacturer => "SysTec"; public int InternalScaleNr => 1; public string Model { get; private set; } @@ -38,39 +34,11 @@ namespace Elwig.Helpers.Weighing { HasFillingClearance = false; Stream stream; - if (connection.StartsWith("serial:")) { - var m = SerialRe.Match(connection); - if (!m.Success) - throw new ArgumentException("Invalid connection string for scheme \"serial\""); - - var stop = m.Groups[6].Value; - var parity = m.Groups[5].Value.ToUpper(); - var data = m.Groups[4].Value; - Serial = new() { - PortName = m.Groups[1].Value, - BaudRate = int.Parse(m.Groups[2].Value), - Parity = parity == "E" ? Parity.Even : - parity == "O" ? Parity.Odd : - parity == "M" ? Parity.Mark : - parity == "S" ? Parity.Space : - Parity.None, - DataBits = data == "" ? 8 : int.Parse(data), - StopBits = (StopBits)(stop == "" ? 1 : stop == "1.5" ? 3 : stop[0] - '0'), - Handshake = Handshake.None, - }; - Serial.Open(); + Serial = Utils.OpenSerialConnection(connection); stream = Serial.BaseStream; } else if (connection.StartsWith("tcp:")) { - var m = TcpRe.Match(connection); - if (!m.Success) - throw new ArgumentException("Invalid connection string for scheme \"tcp\""); - - Tcp = new() { - SendTimeout = 250, - ReceiveTimeout = 250, - }; - Tcp.Connect(m.Groups[1].Value, int.Parse(m.Groups[2].Value)); + Tcp = Utils.OpenTcpConnection(connection); stream = Tcp.GetStream(); } else { throw new ArgumentException("Unsupported scheme");