diff --git a/.gitignore b/.gitignore
index 11af5602f..7c7e759cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,8 @@ LabelPrinting/bin/
LabelPrinting/obj/
MergeResultsDBs/bin/
MergeResultsDBs/obj/
+NfcC7_Dll/bin/
+NfcC7_Dll/obj/
OrderManagement/bin/
OrderManagement/obj/
ProductionTracing/bin/
diff --git a/NfcC7_DLL/NfcC7_DLL.csproj b/NfcC7_DLL/NfcC7_DLL.csproj
new file mode 100644
index 000000000..9bb52f2b7
--- /dev/null
+++ b/NfcC7_DLL/NfcC7_DLL.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net8.0
+ enable
+ enable
+ Copyright © 2025
+ 1.1.0.0
+ 1.1.0.0
+
+
+
+ TRACE;
+ true
+
+
+
diff --git a/NfcC7_DLL/NfcHanler/Tools.cs b/NfcC7_DLL/NfcHanler/Tools.cs
new file mode 100644
index 000000000..3a7b1a564
--- /dev/null
+++ b/NfcC7_DLL/NfcHanler/Tools.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+//*****************************************************************************
+// Copyright 2020 Sensus GmbH Ludwigshafen. All rights reserved.
+// Author: Venkat, Rajeshwar
+//*****************************************************************************
+
+namespace Sensus.Poseidon.NfcHandler
+{
+ public static class Tools
+ {
+ public static bool ByteArrayCompare(byte[] a1, byte[] a2)
+ {
+ // thanks to https://stackoverflow.com/questions/43289/comparing-two-byte-arrays-in-net
+ if (a1.Length != a2.Length)
+ return false;
+
+ for (int i = 0; i < a1.Length; i++)
+ if (a1[i] != a2[i])
+ return false;
+
+ return true;
+ }
+ public static string SwapHex(string sHex)
+ {
+ string sResult = "";
+ int iPos = sHex.Length - 2;
+ while (iPos >= 0)
+ {
+ sResult += sHex.Substring(iPos, 2);
+ sHex = sHex.Remove(iPos, 2);
+ iPos = sHex.Length - 2;
+ }
+ return sResult;
+ }
+ public static string DecimalToHexString(string value, int size = 1)
+ {
+ try
+ {
+ long Lval = long.Parse(value);
+ if (size == 1) return Lval.ToString("X2");
+ if (size == 2) return Lval.ToString("X4");
+ if (size == 4) return Lval.ToString("X8");
+ }
+ catch (Exception)
+ {
+ if (size == 1) return "00";
+ if (size == 2) return "0000";
+ if (size == 4) return "00000000";
+ }
+ return "00";
+ }
+ public static string ByteToHexString(byte data)
+ {
+ List val = new List();
+ val.Add(data);
+ byte[] arr = val.ToArray();
+ return BytesToHex(arr);
+ }
+ public static string BytesToHex(byte[] data)
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (byte b in data)
+ sb.Append(b.ToString("X2"));
+
+ return sb.ToString();
+
+ }
+ public static byte[] HexStringToByteArray(String hexString)
+ {
+ int numberChars = hexString.Length;
+ byte[] bytes = new byte[numberChars / 2];
+ for (int i = 0; i < numberChars; i += 2)
+ {
+ bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
+ }
+ return bytes;
+ }
+ public enum InitialCrcValue
+ {
+ Zeros,
+ NonZero1 = 0xffff,
+ NonZero2 = 0x1D0F
+ }
+
+ public class Crc16Ccitt
+ {
+ private const ushort poly = 0x1021;
+ ushort[] table = new ushort[256];
+ ushort initialValue = 0;
+
+ public ushort ComputeChecksum(byte[] bytes)
+ {
+ ushort crc = this.initialValue;
+ for (int i = 0; i < bytes.Length; ++i)
+ {
+ crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
+ }
+ return crc;
+ }
+ public byte[] ComputeChecksumBytes(byte[] bytes)
+ {
+ ushort crc = ComputeChecksum(bytes);
+ return BitConverter.GetBytes(crc);
+ }
+ public Crc16Ccitt(InitialCrcValue initialValue)
+ {
+ this.initialValue = (ushort) initialValue;
+ ushort temp, a;
+ for (int i = 0; i < table.Length; ++i)
+ {
+ temp = 0;
+ a = (ushort) (i << 8);
+ for (int j = 0; j < 8; ++j)
+ {
+ if (((temp ^ a) & 0x8000) != 0)
+ {
+ temp = (ushort) ((temp << 1) ^ poly);
+ }
+ else
+ {
+ temp <<= 1;
+ }
+ a <<= 1;
+ }
+ table[i] = temp;
+ }
+ }
+ public byte[] calcCRCfromMessage(byte[] message)
+ {
+ // CRC calculation goes from MessageID to Password
+ // For Read this means MsgID (1) + Offset (2) + PayloadLength (1) + Password (2) = 6
+ // for write the length of the payload comes on top.
+ // STX(1), length(1), CRC(2) and ETX(1) are excluded, in total 5 bytes.
+ //
+ // the method works both for sending messages (where the CRC and ETX are not in message)
+ // and for receiving messages (where the CRC and ETX are included at the end)
+ byte[] crc_msg = new byte[message[1]]; // message length is 2nd byte
+ Array.Copy(message, 2, crc_msg, 0, crc_msg.Length);
+ return ComputeChecksumBytes(crc_msg);
+ }
+ public string commentCRC(byte[] crc_meter, byte[] crc_computed)
+ {
+ bool crc_do_match = Tools.ByteArrayCompare(crc_meter, crc_computed);
+ string crcComment = crc_do_match ? "ok." : "CRC DOESN'T MATCH!!";
+ return "CRC Meter: " + Tools.BytesToHex(crc_meter) + (crc_do_match ? " == " : " != ")
+ + "CRC Computed: " + Tools.BytesToHex(crc_computed) + ". " + crcComment;
+ }
+ public bool crc_do_match(byte[] a, byte[] b)
+ {
+ return ByteArrayCompare(a, b);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/NfcC7_DLL/Properties/AssemblyInfo.cs b/NfcC7_DLL/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..3e6ef37b3
--- /dev/null
+++ b/NfcC7_DLL/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NfcC7_DLL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("NfcC7_DLL")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("A27EE8F2-46F8-43B1-82C7-F49D5DE392EC")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.1.0.0")]
+[assembly: AssemblyFileVersion("1.1.0.0")]
diff --git a/TBF.sln b/TBF.sln
index 2dc522326..361019cc7 100644
--- a/TBF.sln
+++ b/TBF.sln
@@ -119,6 +119,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sensus.iPerl.TestConsole",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NfcS5_DLL", "..\NfcS5_DLL\NfcS5_DLL.csproj", "{5954D496-CAAB-4F7A-BDE2-BDC8F47DAB19}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NfcC7_DLL", "NfcC7_DLL\NfcC7_DLL.csproj", "{53E75979-B530-4805-8FC9-B314F14A62BE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -539,6 +541,18 @@ Global
{5954D496-CAAB-4F7A-BDE2-BDC8F47DAB19}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5954D496-CAAB-4F7A-BDE2-BDC8F47DAB19}.Release|x86.ActiveCfg = Release|Any CPU
{5954D496-CAAB-4F7A-BDE2-BDC8F47DAB19}.Release|x86.Build.0 = Release|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Debug|x86.Build.0 = Debug|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Release|x86.ActiveCfg = Release|Any CPU
+ {53E75979-B530-4805-8FC9-B314F14A62BE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE