From 6571de7c32377b0ebfa30831eb4953a0dfb3a33a Mon Sep 17 00:00:00 2001 From: Michal Buzik Date: Mon, 29 Sep 2025 09:58:09 +0200 Subject: [PATCH] Add `NfcC7_DLL` project with initial implementation and solution integration --- .gitignore | 2 + NfcC7_DLL/NfcC7_DLL.csproj | 17 +++ NfcC7_DLL/NfcHanler/Tools.cs | 160 +++++++++++++++++++++++++++ NfcC7_DLL/Properties/AssemblyInfo.cs | 35 ++++++ TBF.sln | 14 +++ 5 files changed, 228 insertions(+) create mode 100644 NfcC7_DLL/NfcC7_DLL.csproj create mode 100644 NfcC7_DLL/NfcHanler/Tools.cs create mode 100644 NfcC7_DLL/Properties/AssemblyInfo.cs 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