From 8e9f2f4e90cb9f041b9e087f15c91a30da660573 Mon Sep 17 00:00:00 2001
From: Lorenz Stechauner <lorenz.stechauner@necronda.net>
Date: Wed, 24 Jul 2024 16:42:38 +0200
Subject: [PATCH] WeighingTests: Add Haugsdorf and Sitzendorf

---
 Tests/WeighingTests/MockScale.cs              |  16 +--
 Tests/WeighingTests/ScaleHandlers.cs          |  87 ++++++++++++-
 Tests/WeighingTests/ScaleTestHaugsdorf.cs     |   6 -
 .../WeighingTests/ScaleTestHaugsdorfDMA02.cs  | 115 ++++++++++++++++++
 Tests/WeighingTests/ScaleTestSitzendorf.cs    |   6 -
 .../ScaleTestSitzendorfDMA03Baby.cs           | 115 ++++++++++++++++++
 .../ScaleTestWolkersdorfIT6000E.cs            |  43 +------
 7 files changed, 323 insertions(+), 65 deletions(-)
 delete mode 100644 Tests/WeighingTests/ScaleTestHaugsdorf.cs
 create mode 100644 Tests/WeighingTests/ScaleTestHaugsdorfDMA02.cs
 delete mode 100644 Tests/WeighingTests/ScaleTestSitzendorf.cs
 create mode 100644 Tests/WeighingTests/ScaleTestSitzendorfDMA03Baby.cs

diff --git a/Tests/WeighingTests/MockScale.cs b/Tests/WeighingTests/MockScale.cs
index 5d058b7..b48d264 100644
--- a/Tests/WeighingTests/MockScale.cs
+++ b/Tests/WeighingTests/MockScale.cs
@@ -8,6 +8,7 @@ namespace Tests.WeighingTests {
         protected readonly TcpListener Server;
 
         public int IdentNr { get; set; } = 0;
+        public int Tare { get; set; } = 0;
         public int Weight { get; set; } = 0;
         public string? Error { get; set; } = null;
 
@@ -24,11 +25,11 @@ namespace Tests.WeighingTests {
 
     public class CommandMockScale : MockScale {
 
-        private readonly Func<string, int, string?, int, (string, bool)> Handler;
+        private readonly Func<string, int, int, string?, int, (string, bool)> Handler;
         private readonly Thread ServerThread;
         private bool IsRunning = true;
 
-        public CommandMockScale(int port, Func<string, int, string?, int, (string, bool)> handler) :
+        public CommandMockScale(int port, Func<string, int, int, string?, int, (string, bool)> handler) :
             base(port) {
             Handler = handler;
             ServerThread = new Thread(new ParameterizedThreadStart(Serve));
@@ -44,7 +45,7 @@ namespace Tests.WeighingTests {
                     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);
+                        var (res, inc) = Handler(Encoding.ASCII.GetString(buffer, 0, read), Weight, Tare, Error, IdentNr + 1);
                         if (inc) IdentNr++;
                         await stream.WriteAsync(Encoding.ASCII.GetBytes(res));
                     }
@@ -64,12 +65,12 @@ namespace Tests.WeighingTests {
 
     public class EventMockScale : MockScale {
 
-        private readonly Func<int, string?, int, (string, bool)> Handler;
+        private readonly Func<int, int, string?, int, (string, bool)> Handler;
         private readonly Thread ServerThread;
         private TcpClient? Client;
         private bool IsRunning = true;
 
-        public EventMockScale(int port, Func<int, string?, int, (string, bool)> handler) :
+        public EventMockScale(int port, Func<int, int, string?, int, (string, bool)> handler) :
             base(port) {
             Handler = handler;
             ServerThread = new Thread(new ParameterizedThreadStart(Serve));
@@ -86,13 +87,14 @@ namespace Tests.WeighingTests {
             }
         }
 
-        public async Task Weigh(int weight) {
+        public async Task Weigh(int weight, int tare = 0) {
             Weight = weight;
+            Tare = tare;
             await Weigh();
         }
 
         public async Task Weigh() {
-            var (res, inc) = Handler(Weight, Error, IdentNr + 1);
+            var (res, inc) = Handler(Weight, Tare, Error, IdentNr + 1);
             if (inc) IdentNr++;
             await Client!.GetStream().WriteAsync(Encoding.ASCII.GetBytes(res));
         }
diff --git a/Tests/WeighingTests/ScaleHandlers.cs b/Tests/WeighingTests/ScaleHandlers.cs
index 1c3d855..c0d440a 100644
--- a/Tests/WeighingTests/ScaleHandlers.cs
+++ b/Tests/WeighingTests/ScaleHandlers.cs
@@ -1,7 +1,7 @@
 namespace Tests.WeighingTests {
     public static class ScaleHandlers {
 
-        public static (string, bool) Handle_IT3000A(string req, int weight, string? error, int identNr) {
+        public static (string, bool) Handle_IT3000A(string req, int weight, int tare, string? error, int identNr) {
             var modes = error?.Split(';') ?? [];
             var overloaded = modes.Contains("overloaded");
             var moving = modes.Contains("moving");
@@ -39,13 +39,52 @@
                 return ("<13>\r\n", false);
 
             string data = $"00{(moving ? 1 : 0)}0{new DateTime(2020, 10, 15, 12, 34, 0):dd.MM.yyHH:mm}{(incr ? identNr : 0),4}1" +
-                $"{weight,8}{0,8}{weight,8}{(unit ? "lb" : "kg")}   {"1",3}";
+                $"{weight + tare,8}{tare,8}{weight,8}{(unit ? "lb" : "kg")}   {"1",3}";
             ushort checksum = Elwig.Helpers.Utils.CalcCrc16Modbus(data);
             if (crc) checksum += 10;
             return ($"<{data}{checksum,8}>\r\n", incr);
         }
 
-        public static (string, bool) Handle_L246(string req, int weight, string? error, int identNr) {
+        public static (string, bool) Handle_IT6000E(string req, int weight, int tare, string? error, int identNr, string terminalNr) {
+            var modes = error?.Split(';') ?? [];
+            var overloaded = modes.Contains("overloaded");
+            var moving = modes.Contains("moving");
+            var invalid = modes.Contains("invalid");
+            var crc = modes.Contains("crc");
+            var unit = modes.Contains("unit");
+
+            if (invalid) {
+                return ("abcd\r\n", false);
+            } else if (!req.StartsWith('<') || !req.EndsWith('>')) {
+                return ("<31>\r\n", false);
+            }
+            req = req[1..^1];
+
+            bool incr;
+            if (req.Length > 3) {
+                return ("<32>\r\n", false);
+            } else if (req.StartsWith("RN")) {
+                incr = true;
+            } else if (req.StartsWith("RM")) {
+                incr = false;
+            } else {
+                return ("<32>\r\n", false);
+            }
+
+            if (overloaded)
+                return ("<12>\r\n", false);
+
+            if (moving && incr)
+                return ("<13>\r\n", false);
+
+            string data = $"00{(moving ? 1 : 0)}0{new DateTime(2020, 10, 8, 8, 47, 0):dd.MM.yyHH:mm}{(incr ? identNr : 0),4}1" +
+                $"{weight + tare,8}{tare,8}{weight,8}{(unit ? "lb" : "kg")}   {terminalNr,3}";
+            ushort checksum = Elwig.Helpers.Utils.CalcCrc16Modbus(data);
+            if (crc) checksum += 10;
+            return ($"<{data}{checksum,8}>\r\n", incr);
+        }
+
+        public static (string, bool) Handle_L246(string req, int weight, int tare, string? error, int identNr) {
             var modes = error?.Split(';') ?? [];
             var overloaded = modes.Contains("overloaded");
             var moving = modes.Contains("moving");
@@ -80,13 +119,51 @@
                 return ("<13>\r\n", false);
 
             string data = $"00{(moving ? 1 : 0)}0{new DateTime(2020, 10, 17, 14, 23, 0):dd.MM.yyHH:mm}{(incr ? identNr : 0),4}1" +
-                $"{weight,8}{0,8}{weight,8}{(unit ? "lb" : "kg")}   {"001",3}";
+                $"{weight + tare,8}{tare,8}{weight,8}{(unit ? "lb" : "kg")}   {"001",3}";
             ushort checksum = Elwig.Helpers.Utils.CalcCrc16Modbus(data);
             if (crc) checksum += 10;
             return ($"<{data}{checksum,8}>\r\n", incr);
         }
 
-        public static (string, bool) Handle_L320(int weight, string? error, int identNr) {
+        public static (string, bool) HandleDMA02(string req, int weight, int tare, string? error, int identNr) {
+            var modes = error?.Split(';') ?? [];
+            var overloaded = modes.Contains("overloaded");
+            var moving = modes.Contains("moving");
+            var invalid = modes.Contains("invalid");
+
+            Thread.Sleep(100);
+
+            if (invalid) {
+                return ("abcd\x03", false);
+            } else if (req != "\x05" && req != "?") {
+                return ("\x0002ES\x03", false);
+            }
+
+            bool incr;
+            if (req == "?") {
+                incr = false;
+            } else {
+                incr = true;
+            }
+
+            if (overloaded) {
+                return ("\x0002ES\x03", false);
+            } else if (weight == 0) {
+                incr = false;
+            }
+
+            if (moving && incr)
+                return ("\x0002EM\x03", false);
+
+            string data = $" {(moving ? "M" : "S")}{weight + tare,7}{tare,7}{weight,7} 1{(incr ? identNr : 0),6}{new DateTime(2020, 10, 15, 12, 34, 0):yyyyMMddHHmmss}";
+            return ($"\x0002{data}\x03", incr);
+        }
+
+        public static (string, bool) HandleDMA03Baby(string req, int weight, int tare, string? error, int identNr) {
+            return HandleDMA02(req, weight, tare, error, identNr);
+        }
+
+        public static (string, bool) Handle_L320(int weight, int tare, string? error, int identNr) {
             var modes = error?.Split(';') ?? [];
             var invalid = modes.Contains("invalid");
             var unit = modes.Contains("unit");
diff --git a/Tests/WeighingTests/ScaleTestHaugsdorf.cs b/Tests/WeighingTests/ScaleTestHaugsdorf.cs
deleted file mode 100644
index d898724..0000000
--- a/Tests/WeighingTests/ScaleTestHaugsdorf.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Tests.WeighingTests {
-    [TestFixture]
-    public class ScaleTestHaugsdorf {
-        // TODO
-    }
-}
diff --git a/Tests/WeighingTests/ScaleTestHaugsdorfDMA02.cs b/Tests/WeighingTests/ScaleTestHaugsdorfDMA02.cs
new file mode 100644
index 0000000..9d61651
--- /dev/null
+++ b/Tests/WeighingTests/ScaleTestHaugsdorfDMA02.cs
@@ -0,0 +1,115 @@
+using Elwig.Helpers.Weighing;
+
+namespace Tests.WeighingTests {
+    [TestFixture]
+    public class ScaleTestHaugsdorfDMA02 {
+
+        private MockScale Mock;
+        private GassnerScale Scale;
+
+        [OneTimeSetUp]
+        public void SetupScale() {
+            Mock = new CommandMockScale(12345, ScaleHandlers.HandleDMA02);
+            Scale = new("1", "DMA02", "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.Tare = 0;
+            Mock.Error = null;
+        }
+
+        [Test]
+        public async Task Test_01_CurrentWeight() {
+            Mock.Weight = 1234;
+            Mock.Tare = 0;
+            Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1234,
+                TareWeight = 0,
+                NetWeight = 1234,
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 1235;
+            Mock.Tare = 46;
+            Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1281,
+                TareWeight = 46,
+                NetWeight = 1235,
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 1236;
+            Mock.Tare = 92;
+            Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1328,
+                TareWeight = 92,
+                NetWeight = 1236,
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+        }
+
+        [Test]
+        public async Task Test_02_Normal() {
+            Mock.Weight = 1234;
+            Mock.Tare = 92;
+            Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1326,
+                TareWeight = 92,
+                NetWeight = 1234,
+                WeighingId = "1",
+                FullWeighingId = "1",
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 3333;
+            Mock.Tare = 41;
+            Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 3374,
+                TareWeight = 41,
+                NetWeight = 3333,
+                WeighingId = "2",
+                FullWeighingId = "2",
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 4321;
+            Mock.Tare = 0;
+            Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 4321,
+                TareWeight = 0,
+                NetWeight = 4321,
+                WeighingId = "3",
+                FullWeighingId = "3",
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+        }
+
+        [Test]
+        public void Test_03_Moving() {
+            Mock.Weight = 1_000;
+            Mock.Tare = 41;
+            Mock.Error = "moving";
+            IOException ex = Assert.ThrowsAsync<IOException>(async () => await Scale!.Weigh());
+            Assert.That(ex.Message, Contains.Substring("Waage in Bewegung"));
+        }
+
+        [Test]
+        public void Test_04_InvalidResponse() {
+            Mock.Weight = 1_000;
+            Mock.Tare = 41;
+            Mock.Error = "invalid";
+            Assert.ThrowsAsync<IOException>(async () => await Scale!.Weigh());
+        }
+    }
+}
diff --git a/Tests/WeighingTests/ScaleTestSitzendorf.cs b/Tests/WeighingTests/ScaleTestSitzendorf.cs
deleted file mode 100644
index 513ac1d..0000000
--- a/Tests/WeighingTests/ScaleTestSitzendorf.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Tests.WeighingTests {
-    [TestFixture]
-    public class ScaleTestSitzendorf {
-        // TODO
-    }
-}
diff --git a/Tests/WeighingTests/ScaleTestSitzendorfDMA03Baby.cs b/Tests/WeighingTests/ScaleTestSitzendorfDMA03Baby.cs
new file mode 100644
index 0000000..83739f1
--- /dev/null
+++ b/Tests/WeighingTests/ScaleTestSitzendorfDMA03Baby.cs
@@ -0,0 +1,115 @@
+using Elwig.Helpers.Weighing;
+
+namespace Tests.WeighingTests {
+    [TestFixture]
+    public class ScaleTestSitzendorfDMA03Baby {
+
+        private MockScale Mock;
+        private GassnerScale Scale;
+
+        [OneTimeSetUp]
+        public void SetupScale() {
+            Mock = new CommandMockScale(12345, ScaleHandlers.HandleDMA03Baby);
+            Scale = new("1", "DMA03-baby", "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.Tare = 0;
+            Mock.Error = null;
+        }
+
+        [Test]
+        public async Task Test_01_CurrentWeight() {
+            Mock.Weight = 1234;
+            Mock.Tare = 0;
+            Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1234,
+                TareWeight = 0,
+                NetWeight = 1234,
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 1235;
+            Mock.Tare = 46;
+            Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1281,
+                TareWeight = 46,
+                NetWeight = 1235,
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 1236;
+            Mock.Tare = 92;
+            Assert.That(await Scale!.GetCurrentWeight(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1328,
+                TareWeight = 92,
+                NetWeight = 1236,
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+        }
+
+        [Test]
+        public async Task Test_02_Normal() {
+            Mock.Weight = 1234;
+            Mock.Tare = 92;
+            Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 1326,
+                TareWeight = 92,
+                NetWeight = 1234,
+                WeighingId = "1",
+                FullWeighingId = "1",
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 3333;
+            Mock.Tare = 41;
+            Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 3374,
+                TareWeight = 41,
+                NetWeight = 3333,
+                WeighingId = "2",
+                FullWeighingId = "2",
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+            Mock.Weight = 4321;
+            Mock.Tare = 0;
+            Assert.That(await Scale!.Weigh(), Is.EqualTo(new WeighingResult {
+                GrossWeight = 4321,
+                TareWeight = 0,
+                NetWeight = 4321,
+                WeighingId = "3",
+                FullWeighingId = "3",
+                Date = new DateOnly(2020, 10, 15),
+                Time = new TimeOnly(12, 34),
+            }));
+        }
+
+        [Test]
+        public void Test_03_Moving() {
+            Mock.Weight = 1_000;
+            Mock.Tare = 41;
+            Mock.Error = "moving";
+            IOException ex = Assert.ThrowsAsync<IOException>(async () => await Scale!.Weigh());
+            Assert.That(ex.Message, Contains.Substring("Waage in Bewegung"));
+        }
+
+        [Test]
+        public void Test_04_InvalidResponse() {
+            Mock.Weight = 1_000;
+            Mock.Tare = 41;
+            Mock.Error = "invalid";
+            Assert.ThrowsAsync<IOException>(async () => await Scale!.Weigh());
+        }
+    }
+}
diff --git a/Tests/WeighingTests/ScaleTestWolkersdorfIT6000E.cs b/Tests/WeighingTests/ScaleTestWolkersdorfIT6000E.cs
index 2944a4d..a7a92ff 100644
--- a/Tests/WeighingTests/ScaleTestWolkersdorfIT6000E.cs
+++ b/Tests/WeighingTests/ScaleTestWolkersdorfIT6000E.cs
@@ -9,49 +9,10 @@ namespace Tests.WeighingTests {
         private SysTecITScale ScaleA;
         private SysTecITScale ScaleB;
 
-        private static (string, bool) ScaleHandler(string req, int weight, string? error, int identNr, string terminalNr) {
-            var modes = error?.Split(';') ?? [];
-            var overloaded = modes.Contains("overloaded");
-            var moving = modes.Contains("moving");
-            var invalid = modes.Contains("invalid");
-            var crc = modes.Contains("crc");
-            var unit = modes.Contains("unit");
-
-            if (invalid) {
-                return ("abcd\r\n", false);
-            } else if (!req.StartsWith('<') || !req.EndsWith('>')) {
-                return ("<31>\r\n", false);
-            }
-            req = req[1..^1];
-
-            bool incr;
-            if (req.Length > 3) {
-                return ("<32>\r\n", false);
-            } else if (req.StartsWith("RN")) {
-                incr = true;
-            } else if (req.StartsWith("RM")) {
-                incr = false;
-            } else {
-                return ("<32>\r\n", false);
-            }
-
-            if (overloaded)
-                return ("<12>\r\n", false);
-
-            if (moving && incr)
-                return ("<13>\r\n", false);
-
-            string data = $"00{(moving ? 1 : 0)}0{new DateTime(2020, 10, 8, 8, 47, 0):dd.MM.yyHH:mm}{(incr ? identNr : 0),4}1" +
-                $"{weight,8}{0,8}{weight,8}{(unit ? "lb" : "kg")}   {terminalNr,3}";
-            ushort checksum = Elwig.Helpers.Utils.CalcCrc16Modbus(data);
-            if (crc) checksum += 10;
-            return ($"<{data}{checksum,8}>\r\n", incr);
-        }
-
         [OneTimeSetUp]
         public void SetupScale() {
-            MockA = new CommandMockScale(12345, (req, weight, error, identNr) => ScaleHandler(req, weight, error, identNr, "A"));
-            MockB = new CommandMockScale(12346, (req, weight, error, identNr) => ScaleHandler(req, weight, error, identNr, "B"));
+            MockA = new CommandMockScale(12345, (req, weight, tare, error, identNr) => ScaleHandlers.Handle_IT6000E(req, weight, tare, error, identNr, "A"));
+            MockB = new CommandMockScale(12346, (req, weight, tare, error, identNr) => ScaleHandlers.Handle_IT6000E(req, weight, tare, error, identNr, "B"));
             ScaleA = new("A", "IT3000E", "tcp://127.0.0.1:12345");
             ScaleB = new("B", "IT3000E", "tcp://127.0.0.1:12346");
         }