diff --git a/Elwig/Helpers/Weighing/SchemberScale.cs b/Elwig/Helpers/Weighing/SchemberScale.cs index 52b1ce1..329e117 100644 --- a/Elwig/Helpers/Weighing/SchemberScale.cs +++ b/Elwig/Helpers/Weighing/SchemberScale.cs @@ -13,10 +13,7 @@ namespace Elwig.Helpers.Weighing { public string? LogPath => throw new NotImplementedException(); public void Dispose() { - throw new NotImplementedException(); + GC.SuppressFinalize(this); } - - - } } diff --git a/Elwig/Helpers/Weighing/WeighingResult.cs b/Elwig/Helpers/Weighing/WeighingResult.cs index 25d77e5..6cb4d77 100644 --- a/Elwig/Helpers/Weighing/WeighingResult.cs +++ b/Elwig/Helpers/Weighing/WeighingResult.cs @@ -4,36 +4,38 @@ namespace Elwig.Helpers.Weighing { /// /// Result of a weighing process on an industrial scale /// - public class WeighingResult { + public struct WeighingResult { /// /// Measured net weight in kg /// - public int? Weight = null; + public int? Weight; /// /// Weighing id (or IdentNr) provided by the scale /// - public string? WeighingId = null; + public string? WeighingId; /// /// Wheighing id (or IdentNr) provided by the scale optionally combined with the current date /// - public string? FullWeighingId = null; + public string? FullWeighingId; /// /// Date string provided by the scale /// - public DateOnly? Date = null; + public DateOnly? Date; /// /// Time string provided by the scale /// - public TimeOnly? Time = null; + public TimeOnly? Time; /// <Weight/WeighingId/Date/Time> - override public string ToString() { + public override readonly string ToString() { var w = Weight != null ? $"{Weight}kg" : ""; return $"<{w}/{WeighingId}/{Date:yyyy-MM-dd}/{Time:HH:mm}>"; } + + } } diff --git a/Tests/WeighingTests/MockScale.cs b/Tests/WeighingTests/MockScale.cs new file mode 100644 index 0000000..9da6698 --- /dev/null +++ b/Tests/WeighingTests/MockScale.cs @@ -0,0 +1,71 @@ +using System.Net.Sockets; +using System.Net; +using System.Text; + +namespace Tests.WeighingTests { + public abstract class MockScale : IDisposable { + + protected readonly TcpListener Server; + + public int IdentNr { get; set; } = 0; + public int Weight { get; set; } = 0; + public string? Error { get; set; } = null; + + protected MockScale(int port) { + Server = new TcpListener(IPAddress.Loopback, port); + Server.Start(4); + } + + public void Dispose() { + Server.Dispose(); + GC.SuppressFinalize(this); + } + } + + public class CommandMockScale : MockScale { + + private readonly Func Handler; + private readonly Thread ServerThread; + private bool IsRunning = true; + + public CommandMockScale(int port, Func handler) : + base(port) { + Handler = handler; + ServerThread = new Thread(new ParameterizedThreadStart(Serve)); + ServerThread.Start(); + } + + private async void Serve(object? parameters) { + byte[] buffer = new byte[16]; + while (IsRunning) { + try { + using var client = await Server.AcceptTcpClientAsync(); + if (client == null) continue; + using var stream = client.GetStream(); + while (true) { + int read = await stream.ReadAsync(buffer); + var (res, inc) = Handler(Encoding.ASCII.GetString(buffer, 0, read), Weight, Error, IdentNr + 1); + if (inc) IdentNr++; + await stream.WriteAsync(Encoding.ASCII.GetBytes(res)); + } + } catch (Exception) { + // ignore + } + } + } + + public new void Dispose() { + IsRunning = false; + ServerThread.Interrupt(); + ServerThread.Join(); + base.Dispose(); + } + } + + public class EventMockScale : MockScale { + public EventMockScale(int port, Func handler) : + base(port) { + // TODO + } + } +} diff --git a/Tests/WeighingTests/ScaleTestMatzen.cs b/Tests/WeighingTests/ScaleTestMatzen.cs new file mode 100644 index 0000000..5837883 --- /dev/null +++ b/Tests/WeighingTests/ScaleTestMatzen.cs @@ -0,0 +1,93 @@ +using Elwig.Helpers.Weighing; + +namespace Tests.WeighingTests { + [TestFixture] + class ScaleTestMatzen { + + private MockScale? Mock; + private SystecScale? Scale; + + private static (string, bool) ScaleHandler(string req, int weight, string? error, int identNr) { + bool incr = false; + if (!req.StartsWith('<') || !req.EndsWith('>')) + return ("<31>\r\n", incr); + req = req[1..^1]; + + if (req.Length > 3) { + return ("<32>\r\n", incr); + } else if (req.StartsWith("RN")) { + incr = true; + } else if (req.StartsWith("RM")) { + incr = false; + } else { + return ("<32>\r\n", incr); + } + + var modes = error?.Split(';') ?? []; + if (weight == 0) { + incr = false; + } + + bool moving = modes.Contains("moving"); + string data = $"00{(moving ? 1 : 0)}0{DateTime.Now:dd.MM.yyHH:mm}{(incr ? identNr : 0),4}1{weight,8}{0,8}{weight,8}kg {1,3}"; + return ($"<{data}{Elwig.Helpers.Utils.CalcCrc16Modbus(data),8}>\r\n", incr); + } + + [OneTimeSetUp] + public void SetupScale() { + Mock = new CommandMockScale(12345, ScaleHandler); + Scale = new("1", "IT3000A", "tcp://127.0.0.1:12345"); + } + + [OneTimeTearDown] + public void TeardownScale() { + Mock?.Dispose(); + Scale?.Dispose(); + } + + [SetUp] + public void ResetScale() { + Mock!.IdentNr = 0; + Mock!.Weight = 0; + Mock!.Error = null; + } + + [Test] + public async Task Test_01_CurrentWeight() { + Mock!.Weight = 1234; + Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult { + Weight = 1234, Date = Utils.Today, Time = Utils.Time, + })); + Mock!.Weight = 1235; + Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult { + Weight = 1235, Date = Utils.Today, Time = Utils.Time, + })); + Mock!.Weight = 1236; + Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult { + Weight = 1236, Date = Utils.Today, Time = Utils.Time, + })); + } + + [Test] + public async Task Test_02_Normal() { + Mock!.Weight = 1234; + Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult { + Weight = 1234, WeighingId = "1", + FullWeighingId = $"{DateTime.Today:yyyy-MM-dd}/1", + Date = Utils.Today, Time = Utils.Time, + })); + Mock!.Weight = 3333; + Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult { + Weight = 3333, WeighingId = "2", + FullWeighingId = $"{DateTime.Today:yyyy-MM-dd}/2", + Date = Utils.Today, Time = Utils.Time, + })); + Mock!.Weight = 4321; + Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult { + Weight = 4321, WeighingId = "3", + FullWeighingId = $"{DateTime.Today:yyyy-MM-dd}/3", + Date = Utils.Today, Time = Utils.Time, + })); + } + } +} diff --git a/Tests/WeighingTests/ScaleTestWolkersdorf.cs b/Tests/WeighingTests/ScaleTestWolkersdorf.cs new file mode 100644 index 0000000..1faa39e --- /dev/null +++ b/Tests/WeighingTests/ScaleTestWolkersdorf.cs @@ -0,0 +1,6 @@ +namespace Tests.WeighingTests { + [TestFixture] + public class ScaleTestWolkersdorf { + // TODO + } +} diff --git a/Tests/WeighingTests/Utils.cs b/Tests/WeighingTests/Utils.cs new file mode 100644 index 0000000..11e500f --- /dev/null +++ b/Tests/WeighingTests/Utils.cs @@ -0,0 +1,6 @@ +namespace Tests.WeighingTests { + public static class Utils { + public static DateOnly Today => DateOnly.FromDateTime(DateTime.Now); + public static TimeOnly Time => new(DateTime.Now.Hour, DateTime.Now.Minute); + } +}