diff --git a/.gitignore b/.gitignore index 1c9a181..c0239a5 100644 --- a/.gitignore +++ b/.gitignore @@ -240,3 +240,4 @@ ModelManifest.xml # FAKE - F# Make .fake/ +/测试用模拟工具 diff --git a/ConsoleAppStd/ConsoleAppStd.csproj b/ConsoleAppStd/ConsoleAppStd.csproj index 820f23d..a076d6e 100644 --- a/ConsoleAppStd/ConsoleAppStd.csproj +++ b/ConsoleAppStd/ConsoleAppStd.csproj @@ -2,11 +2,11 @@ Exe - net5.0 + net6.0 - + diff --git a/ConsoleAppStd/Program.cs b/ConsoleAppStd/Program.cs index 423e386..9da83e9 100644 --- a/ConsoleAppStd/Program.cs +++ b/ConsoleAppStd/Program.cs @@ -1,4 +1,5 @@ -using System; +using EasyModbus; +using System; namespace ConsoleAppStd { @@ -7,16 +8,174 @@ class Program static void Main(string[] args) { - Console.WriteLine("Hello World!"); - + //EasyModbus.ModbusClient modbusClient = new EasyModbus.ModbusClient("COM3"); + //modbusClient.UnitIdentifier = 254; + //modbusClient.Connect(); EasyModbus.ModbusClient modbusClient = new EasyModbus.ModbusClient(); modbusClient.Connect("127.0.0.1", 502); - bool[] response = modbusClient.ReadDiscreteInputs(0, 2); + ushort startingAddress = 0; + int maxQuantity = 10; + // DOTest(startingAddress, maxQuantity, modbusClient); + // DITest(startingAddress,maxQuantity,modbusClient); + + //AOTest(startingAddress,maxQuantity,modbusClient); + //AIReadTest(startingAddress, maxQuantity, modbusClient); + AIWriteTest(startingAddress, maxQuantity, modbusClient); modbusClient.Disconnect(); - Console.WriteLine("Value of Discrete Input #1: " + response[0].ToString()); - Console.WriteLine("Value of Discrete Input #2: " + response[1].ToString()); Console.ReadKey(); } + + private static void AIWriteTest(ushort startingAddress, int _, ModbusClient modbusClient) + { + modbusClient.WriteMultipleRegisters(startingAddress, new byte[] { 0, 99, 0, 77, 0, 55, 0, 33, 0, 11 }); + modbusClient.WriteMultipleRegisters(startingAddress, new short[] { 1010, 99, 88, 77, 66, 55, 44, 33, 22, 11 }); + modbusClient.WriteMultipleRegisters(startingAddress, new ushort[] { 11, 22, 33, 44, 55 }); + modbusClient.WriteMultipleRegisters(startingAddress, new int[] { 11, 22, 33, 44, 55 }); + modbusClient.WriteMultipleRegisters(startingAddress, new long[] { 11, 22 }); + + modbusClient.WriteSingleRegister(startingAddress, (byte)11); + modbusClient.WriteSingleRegister(startingAddress, (short)22); + var ret = modbusClient.ReadWriteMultipleRegisters(startingAddress, 2, 5, new int[] { 32, 34 }); + } + + private static void AIReadTest(ushort startingAddress, int maxQuantity, ModbusClient modbusClient) + { + { + Console.WriteLine($"Start AIReadTest Byte"); + var response = modbusClient.ReadInputRegisters(startingAddress, maxQuantity * 2); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Byte Value of InputRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"--------------------------------------"); + } + + { + Console.WriteLine($"Start AIReadTest Int16"); + var response = modbusClient.ReadInputRegisters(startingAddress, maxQuantity); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Int16 Value of InputRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"--------------------------------------"); + } + + { + Console.WriteLine($"Start AIReadTest Int32"); + var response = modbusClient.ReadInputRegisters(startingAddress, maxQuantity / 2); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Int32 Value of InputRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"--------------------------------------"); + } + + { + Console.WriteLine($"Start AIReadTest Int64"); + var response = modbusClient.ReadInputRegisters(startingAddress, maxQuantity / 4); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Int64 Value of InputRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"Finish AIReadTest"); + Console.WriteLine($"--------------------------------------"); + } + } + + private static void AOTest(ushort startingAddress, int maxQuantity, ModbusClient modbusClient) + { + { + Console.WriteLine($"Start AOTest Byte"); + var response = modbusClient.ReadHoldingRegisters(startingAddress, maxQuantity * 2); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Byte Value of HoldingRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"--------------------------------------"); + } + + { + Console.WriteLine($"Start AOTest Int16"); + var response = modbusClient.ReadHoldingRegisters(startingAddress, maxQuantity); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Int16 Value of HoldingRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"--------------------------------------"); + } + + { + Console.WriteLine($"Start AOTest Int32"); + var response = modbusClient.ReadHoldingRegisters(startingAddress, maxQuantity / 2); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Int32 Value of HoldingRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"--------------------------------------"); + } + + { + Console.WriteLine($"Start AOTest Int64"); + var response = modbusClient.ReadHoldingRegisters(startingAddress, maxQuantity / 4); + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Int64 Value of HoldingRegisters #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"Finish AOTest"); + Console.WriteLine($"--------------------------------------"); + } + } + + private static void DITest(ushort startingAddress, int maxQuantity, ModbusClient modbusClient) + { + { + Console.WriteLine($"Start DITest"); + var response = modbusClient.ReadDiscreteInputs(startingAddress, maxQuantity); + + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Value of Discrete Input #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"Finish DITest"); + Console.WriteLine($"--------------------------------------"); + } + } + + /// + /// + /// + /// + /// 最大读取寄存器数量 + /// + private static void DOTest(ushort startingAddress, int maxQuantity, ModbusClient modbusClient) + { + { + Console.WriteLine($"Start DOTest"); + var response = modbusClient.ReadCoils(startingAddress, maxQuantity); + + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Value of Discrete Output #{i + 1:00}: {response[i]}"); + response[i] = !response[i]; + } + + Console.WriteLine($"--------------------------------------"); + Console.WriteLine($"取反"); + Console.WriteLine($"--------------------------------------"); + + modbusClient.WriteMultipleCoils(0, response); + + response = modbusClient.ReadCoils(startingAddress, maxQuantity); + + for (int i = 0; i < response.Length; i++) + { + Console.WriteLine($"Value of Discrete Output #{i + 1:00}: {response[i]}"); + } + Console.WriteLine($"Finish DOTest"); + Console.WriteLine($"--------------------------------------"); + } + } } + } diff --git a/EasyModbus.sln b/EasyModbus.sln index f19c59c..07165dc 100644 --- a/EasyModbus.sln +++ b/EasyModbus.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32811.315 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyModbus_Net40", "EasyModbus\EasyModbus_Net40.csproj", "{7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyModbusServerSimulator", "EasyModbusServerSimulator\EasyModbusServerSimulator.csproj", "{871BD4C1-69F0-45B9-8807-1620E6A896A9}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyModbusClientExample", "EasyModbusClientExample\EasyModbusClientExample.csproj", "{9412077F-7DFF-45D0-AFF9-7D5303118EA7}" @@ -13,9 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyModbusAdvancedClient", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleAppStd", "ConsoleAppStd\ConsoleAppStd.csproj", "{62AFCA11-8005-4D14-9F29-89DED1076335}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyModbus_V5.0", "EasyModbus_NET5\EasyModbus_V5.0.csproj", "{83AFFC60-BC95-46B1-861F-B1F80270FBFA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyModbus_Net60", "EasyModbus_Net60\EasyModbus_Net60.csproj", "{6BD5A885-D0A3-44C0-BF73-E2118519EAFE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyModbus", "EasyModbus\EasyModbus.csproj", "{16573E74-5836-4792-8935-92CDCEBBEB84}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -45,54 +41,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|ARM.ActiveCfg = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|ARM.Build.0 = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|x64.ActiveCfg = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|x64.Build.0 = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|x86.ActiveCfg = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Debug|x86.Build.0 = Debug|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|Any CPU.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|Any CPU.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|ARM.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|ARM.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|x64.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|x64.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|x86.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial|x86.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|Any CPU.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|Any CPU.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|ARM.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|ARM.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|x64.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|x64.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|x86.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial1|x86.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|Any CPU.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|Any CPU.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|ARM.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|ARM.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|x64.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|x64.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|x86.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial2|x86.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|Any CPU.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|Any CPU.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|ARM.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|ARM.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|x64.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|x64.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|x86.ActiveCfg = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.DebugCommercial3|x86.Build.0 = DebugCommercial|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|Any CPU.Build.0 = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|ARM.ActiveCfg = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|ARM.Build.0 = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|x64.ActiveCfg = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|x64.Build.0 = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|x86.ActiveCfg = Release|Any CPU - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B}.Release|x86.Build.0 = Release|Any CPU {871BD4C1-69F0-45B9-8807-1620E6A896A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {871BD4C1-69F0-45B9-8807-1620E6A896A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {871BD4C1-69F0-45B9-8807-1620E6A896A9}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -285,108 +233,60 @@ Global {62AFCA11-8005-4D14-9F29-89DED1076335}.Release|x64.Build.0 = Release|Any CPU {62AFCA11-8005-4D14-9F29-89DED1076335}.Release|x86.ActiveCfg = Release|Any CPU {62AFCA11-8005-4D14-9F29-89DED1076335}.Release|x86.Build.0 = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|ARM.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|ARM.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|x64.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|x64.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|x86.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Debug|x86.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|Any CPU.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|Any CPU.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|ARM.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|ARM.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|x64.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|x64.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|x86.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial|x86.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|Any CPU.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|Any CPU.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|ARM.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|ARM.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|x64.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|x64.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|x86.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial1|x86.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|Any CPU.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|Any CPU.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|ARM.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|ARM.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|x64.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|x64.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|x86.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial2|x86.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|Any CPU.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|Any CPU.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|ARM.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|ARM.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|x64.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|x64.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|x86.ActiveCfg = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.DebugCommercial3|x86.Build.0 = Debug|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|Any CPU.Build.0 = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|ARM.ActiveCfg = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|ARM.Build.0 = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|x64.ActiveCfg = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|x64.Build.0 = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|x86.ActiveCfg = Release|Any CPU - {83AFFC60-BC95-46B1-861F-B1F80270FBFA}.Release|x86.Build.0 = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|ARM.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|ARM.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|x64.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|x64.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|x86.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Debug|x86.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|Any CPU.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|Any CPU.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|ARM.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|ARM.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|x64.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|x64.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|x86.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial|x86.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|Any CPU.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|Any CPU.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|ARM.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|ARM.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|x64.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|x64.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|x86.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial1|x86.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|Any CPU.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|Any CPU.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|ARM.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|ARM.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|x64.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|x64.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|x86.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial2|x86.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|Any CPU.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|Any CPU.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|ARM.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|ARM.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|x64.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|x64.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|x86.ActiveCfg = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.DebugCommercial3|x86.Build.0 = Debug|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|Any CPU.Build.0 = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|ARM.ActiveCfg = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|ARM.Build.0 = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|x64.ActiveCfg = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|x64.Build.0 = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|x86.ActiveCfg = Release|Any CPU - {6BD5A885-D0A3-44C0-BF73-E2118519EAFE}.Release|x86.Build.0 = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|ARM.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|ARM.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|x64.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|x64.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|x86.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Debug|x86.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|Any CPU.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|Any CPU.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|ARM.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|ARM.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|x64.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|x64.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|x86.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial|x86.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|Any CPU.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|Any CPU.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|ARM.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|ARM.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|x64.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|x64.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|x86.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial1|x86.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|Any CPU.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|Any CPU.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|ARM.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|ARM.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|x64.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|x64.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|x86.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial2|x86.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|Any CPU.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|Any CPU.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|ARM.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|ARM.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|x64.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|x64.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|x86.ActiveCfg = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.DebugCommercial3|x86.Build.0 = Debug|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|Any CPU.Build.0 = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|ARM.ActiveCfg = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|ARM.Build.0 = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|x64.ActiveCfg = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|x64.Build.0 = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|x86.ActiveCfg = Release|Any CPU + {16573E74-5836-4792-8935-92CDCEBBEB84}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - VisualSVNWorkingCopyRoot = . SolutionGuid = {7628B1C9-8DDB-4DBD-A71D-D369A4A166DE} + VisualSVNWorkingCopyRoot = . EndGlobalSection EndGlobal diff --git a/EasyModbus/AdvancedModbusClient.cs b/EasyModbus/AdvancedModbusClient.cs index 2c322f0..e5ef069 100644 --- a/EasyModbus/AdvancedModbusClient.cs +++ b/EasyModbus/AdvancedModbusClient.cs @@ -1,32 +1,606 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace EasyModbus { public partial class ModbusClient { - /* - public enum DataType { Short = 0, UShort = 1, Long = 2, ULong = 3, Float = 4, Double = 5 }; - public object[] ReadHoldingRegisters(int startingAddress, int quantity, DataType dataType, RegisterOrder registerOrder) + /// + /// Read Holding Registers from Master device (FC3). + /// 读取AO + /// + /// only byte short ushort int uint float long ulong double + /// 从第几个寄存器开始读取 一个寄存器 2 byte + /// 要读取多少数据 + /// 接收到的原始数据 是高位在前还是地位在前 高低位关系理解可能有误 还未测试 如错误 取相反值即可 + /// + public T[] ReadHoldingRegisters(ushort startingAddress, int quantity, RegisterOrder registerOrder = RegisterOrder.HighLow) where T : struct { - int quantityToRead = quantity; - if (dataType == DataType.Long | dataType == DataType.ULong | dataType == DataType.Float) + var quantityToRead = GetQuanityToRead(quantity); + + var data = this.ReadHoldingRegistersBuffer(startingAddress, quantityToRead); + + return SetRegistersResult(quantity, registerOrder, data); + } + + /// + /// Read Input Registers from Master device (FC4). + /// 读取AI + /// + /// only byte short ushort int uint float long ulong double + /// 从第几个寄存器开始读取 一个寄存器 2 byte + /// 要读取多少数据 + /// 接收到的原始数据 是高位在前还是地位在前 高低位关系理解可能有误 还未测试 如错误 取相反值即可 + /// + public T[] ReadInputRegisters(ushort startingAddress, int quantity, RegisterOrder registerOrder = RegisterOrder.HighLow) where T : struct + { + var quantityToRead = GetQuanityToRead(quantity); + + var data = this.ReadInputRegistersBuffer(startingAddress, quantityToRead); + + return SetRegistersResult(quantity, registerOrder, data); + } + + /// + /// Write multiple registers to Master device (FC16). + /// 写AO + /// + /// only byte short ushort int uint float long ulong double + /// 从第几个寄存器开始读取 一个寄存器 2 byte + /// + /// 接收到的原始数据 是高位在前还是地位在前 高低位关系理解可能有误 还未测试 如错误 取相反值即可 + public void WriteMultipleRegisters(ushort startingAddress, T[] values, RegisterOrder registerOrder = RegisterOrder.HighLow) where T : struct + { + if (debug) + { + StringBuilder debugString = new StringBuilder(); + for (int i = 0; i < values.Length; i++) + { + debugString.Append(values[i]); + debugString.Append(" "); + } + StoreLogData.Instance.Store("FC16 (Write multiple Registers to Server device), StartingAddress: " + startingAddress + ", Values: " + debugString, System.DateTime.Now); + } + + WriteMultipleRegistersBuffer(startingAddress, SetRegistersWriteData(values, registerOrder)); + } + + /// + /// Write single Register to Master device (FC6). + /// 写AO + /// + /// only byte short ushort + /// 从第几个寄存器开始写 一个寄存器 2 byte + /// + /// 接收到的原始数据 是高位在前还是地位在前 高低位关系理解可能有误 还未测试 如错误 取相反值即可 + public void WriteSingleRegister(ushort startingAddress, T value, RegisterOrder registerOrder = RegisterOrder.HighLow) where T : struct + { + if (debug) + { + StoreLogData.Instance.Store("FC6 (Write single register to Master device), StartingAddress: " + startingAddress + ", Value: " + value, System.DateTime.Now); + } + + byte[] data; + if (typeof(T) == typeof(byte)) + { + data = new byte[2]; + data[0] = Convert.ToByte(value); + } + else if (typeof(T) == typeof(short)) + { + data = BitConverter.GetBytes(Convert.ToInt16(value)); + } + else if (typeof(T) == typeof(ushort)) + { + data = BitConverter.GetBytes(Convert.ToUInt16(value)); + } + else + { + throw new Exception("只支持 byte short ushort "); + } + + if (registerOrder == RegisterOrder.LowHigh) + { + byte temp = data[0]; + data[0] = data[1]; + data[1] = temp; + } + + WriteSingleRegisterBuffer(startingAddress, data); + } + + /// + /// Read/Write Multiple Registers (FC23). + /// 读写AO + /// + /// 从第几个寄存器开始读取 一个寄存器 2 byte < + /// 要读取多少数据 + /// 从第几个寄存器开始写 一个寄存器 2 byte + /// Values to write + /// Int Array which contains the Holding registers + public T[] ReadWriteMultipleRegisters(ushort startingAddressRead, int quantityRead, ushort startingAddressWrite, T[] values + , RegisterOrder registerOrder = RegisterOrder.HighLow) where T : struct + { + if (debug) + { + var debugString = new StringBuilder(); + for (int i = 0; i < values.Length; i++) + { + debugString.Append(values[i]); + debugString.Append(" "); + } + StoreLogData.Instance.Store("FC23 (Read and Write multiple Registers to Server device), StartingAddress Read: " + startingAddressRead + ", Quantity Read: " + quantityRead + ", startingAddressWrite: " + startingAddressWrite + ", Values: " + debugString, System.DateTime.Now); + } + + var quantityToRead = GetQuanityToRead(quantityRead); + + var data = this.ReadWriteMultipleRegistersBuffer(startingAddressRead, quantityToRead, startingAddressWrite, SetRegistersWriteData(values, registerOrder)); + + return SetRegistersResult(quantityRead, registerOrder, data); + } + + /// + /// 设置AO 写数据 + /// + /// only byte short ushort int uint float long ulong double + /// + /// + /// + /// + private static byte[] SetRegistersWriteData(T[] values, RegisterOrder registerOrder) where T : struct + { + byte[] data; + if (typeof(T) == typeof(byte)) + { + if (values.Length % 2 == 0) + { + data = values.Cast().ToArray(); + } + else + { + data = new byte[values.Length + 1]; + + Array.Copy(values, data, values.Length); + } + } + else if (typeof(T) == typeof(short)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 2]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(ushort)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 2]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(int)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 4]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(uint)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 4]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(float)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 4]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(double)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 8]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(long)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 8]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else if (typeof(T) == typeof(ulong)) + { + var valueRets = values.Cast().ToArray(); + data = new byte[valueRets.Length * 8]; + + for (int i = 0; i < valueRets.Length; i++) + { + var tempBytes = BitConverter.GetBytes(valueRets[i]); + + for (int j = 0; j < tempBytes.Length; j++) + { + if (registerOrder == RegisterOrder.HighLow) + { + data[i * tempBytes.Length + j] = tempBytes[tempBytes.Length - j - 1]; + } + else + { + data[i * tempBytes.Length + j] = tempBytes[j]; + } + } + } + } + else + { + throw new Exception("只支持 byte short ushort int uint float long ulong double "); + } + + return data; + } + + /// + /// 获取实际读取几个寄存器 + /// + /// only byte short ushort int uint float long ulong double + /// + /// + /// 数据类型不符合要求 + private static int GetQuanityToRead(int quantity) where T : struct + { + int quantityToRead; + if (typeof(T) == typeof(byte)) + { + quantityToRead = quantity / 2; + if (quantity % 2 != 0) + { + quantityToRead = quantityToRead + 1; + } + } + else if (typeof(T) == typeof(short) + || typeof(T) == typeof(ushort)) + { + quantityToRead = quantity; + } + else if (typeof(T) == typeof(int) + || typeof(T) == typeof(uint) + || typeof(T) == typeof(float)) + { quantityToRead = quantity * 2; - if (dataType == DataType.Float) + } + else if (typeof(T) == typeof(double) + || typeof(T) == typeof(long) + || typeof(T) == typeof(ulong)) + { quantityToRead = quantity * 4; - int[] response = this.ReadHoldingRegisters(startingAddress, quantityToRead); - switch (dataType) + } + else + { + throw new Exception("只支持 byte short ushort int uint float long ulong double "); + } + + return quantityToRead; + } + + /// + /// 设置AI/AO实际返回值 + /// + /// only byte short ushort int uint float long ulong double + /// + /// + /// + /// + private static T[] SetRegistersResult(int quantity, RegisterOrder registerOrder, byte[] data) where T : struct + { + T[] result = new T[quantity]; + if (typeof(T) == typeof(byte)) + { + Array.Copy(data.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(short)) + { + var ret = new short[quantity]; + byte[] temp = new byte[2]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToInt16(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(ushort)) + { + var ret = new ushort[quantity]; + byte[] temp = new byte[2]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToUInt16(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(int)) + { + var ret = new int[quantity]; + byte[] temp = new byte[4]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToInt32(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(uint)) + { + var ret = new uint[quantity]; + byte[] temp = new byte[4]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToUInt32(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(float)) + { + var ret = new float[quantity]; + byte[] temp = new byte[4]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToSingle(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(double)) { - case DataType.Short: return response.Cast().ToArray(); - break; - default: return response.Cast().ToArray(); - break; + var ret = new double[quantity]; + byte[] temp = new byte[8]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToDouble(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); } - - + else if (typeof(T) == typeof(long)) + { + var ret = new long[quantity]; + byte[] temp = new byte[8]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToInt64(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + else if (typeof(T) == typeof(ulong)) + { + var ret = new ulong[quantity]; + byte[] temp = new byte[8]; + + for (int i = 0; i < quantity; i++) + { + if (registerOrder == RegisterOrder.HighLow) + { + for (int j = 0; j < temp.Length; j++) + { + temp[j] = data[i * temp.Length + j]; + } + + for (int j = 0; j < temp.Length; j++) + { + data[i * temp.Length + j] = temp[temp.Length - j - 1]; + } + } + + ret[i] = BitConverter.ToUInt64(data, i * temp.Length); + } + Array.Copy(ret.Cast().ToArray(), result, result.Length); + } + return result; } - */ } + } diff --git a/EasyModbus/EasyModbus.csproj b/EasyModbus/EasyModbus.csproj new file mode 100644 index 0000000..da075a1 --- /dev/null +++ b/EasyModbus/EasyModbus.csproj @@ -0,0 +1,36 @@ + + + + EasyModbusTCP + net4.0;net6.0 + disable + disable + EasyModbus + EasyModbus + Stefan Roßmann + Stefan Roßmann + 5.7.0 + Rossmann Engineering 2018-2020 + Modbus TCP, Modbus UDP and Modbus RTU client library for .NET implementations + 1701;1702;0618;NU1803;IDE1006 + 8.0 + + + + $(DefineConstants);COMMERCIAL + + + + + + + + + ModbusClient.cs + + + + + + + diff --git a/EasyModbus/EasyModbus_Net40.csproj b/EasyModbus/EasyModbus_Net40.csproj deleted file mode 100644 index 41db91d..0000000 --- a/EasyModbus/EasyModbus_Net40.csproj +++ /dev/null @@ -1,81 +0,0 @@ - - - - {7657FC4A-AEDF-4F17-B3E9-0D0DFB1CE23B} - Debug - AnyCPU - Library - EasyModbus - EasyModbus - v4.0 - - - Properties - - - - - 3.5 - - - AnyCPU - - - bin\Debug\ - True - Full - False - True - DEBUG;TRACE - - - bin\Release\ - False - None - True - False - TRACE - - - true - bin\DebugCommercial\ - TRACE;DEBUG;COMMERCIAL - true - Full - AnyCPU - MinimumRecommendedRules.ruleset - false - - - TRACE;DEBUG;SSL - false - 0 - bin\Debug\EasyModbus.xml - - - false - - - - - - 3.5 - - - - 3.5 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/EasyModbus/EasyModbus_Net40.nuspec b/EasyModbus/EasyModbus_Net40.nuspec deleted file mode 100644 index 2e96d5a..0000000 --- a/EasyModbus/EasyModbus_Net40.nuspec +++ /dev/null @@ -1,20 +0,0 @@ - - - - EasyModbusTCP - 5.6 - EasyModbusTCP - Stefan Roßmann - false - MIT - http://www.EasyModbusTCP.net - http://easymodbustcp.net/wp-content/uploads/2020/06/medium-e1592036520465.png - Modbus TCP, Modbus UDP and Modbus RTU client/server library for .NET implementations - Update to version 5.6 - Rossmann Engineering 2018-2020 - Modbus TCP RTU EasyModbusTCP - - - - - \ No newline at end of file diff --git a/EasyModbus/ModbusClient.cs b/EasyModbus/ModbusClient.cs index b9e0285..92637c9 100644 --- a/EasyModbus/ModbusClient.cs +++ b/EasyModbus/ModbusClient.cs @@ -1264,6 +1264,25 @@ public bool[] ReadCoils(int startingAddress, int quantity) /// Int Array which contains the holding registers public int[] ReadHoldingRegisters(int startingAddress, int quantity) { + var data = ReadHoldingRegisters((ushort)startingAddress, quantity); + var response = new int[quantity]; + for (int i = 0; i < quantity; i++) + { + response[i] = Convert.ToInt32(data[i]); + } + return (response); + } + + + /// + /// Read Holding Registers from Master device (FC3). + /// 读取AO + /// + /// First holding register to be read 从第几个寄存器开始读取 + /// Number of holding registers to be read 需要读取的寄存器数量 一个寄存器2个byte + /// Int Array which contains the holding registers + private byte[] ReadHoldingRegistersBuffer(ushort startingAddress, int quantity) + { if (debug) StoreLogData.Instance.Store("FC3 (Read Holding Registers from Master device), StartingAddress: "+ startingAddress+", Quantity: " +quantity, System.DateTime.Now); transactionIdentifierInternal++; if (serialport != null) @@ -1332,11 +1351,17 @@ public int[] ReadHoldingRegisters(int startingAddress, int quantity) DateTime dateTimeSend = DateTime.Now; byte receivedUnitIdentifier = 0xFF; +#if NETFRAMEWORK SpinWait sw_delay = new SpinWait(); +#endif while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) { while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) +#if NETFRAMEWORK sw_delay.SpinOnce(); +#else + System.Threading.Thread.Sleep(1); +#endif data = new byte[2100]; Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); @@ -1421,7 +1446,7 @@ public int[] ReadHoldingRegisters(int startingAddress, int quantity) else { countRetries++; - return ReadHoldingRegisters(startingAddress, quantity); + return ReadHoldingRegistersBuffer(startingAddress, quantity); } } else if (!dataReceived) @@ -1435,38 +1460,48 @@ public int[] ReadHoldingRegisters(int startingAddress, int quantity) else { countRetries++; - return ReadHoldingRegisters(startingAddress, quantity); + return ReadHoldingRegistersBuffer(startingAddress, quantity); } - } } - response = new int[quantity]; + + var array4 = new byte[quantity * 2]; + Array.Copy(data, 9, array4, 0, array4.Length); + return array4; + } + + + + /// + /// Read Input Registers from Master device (FC4). + /// + /// First input register to be read + /// Number of input registers to be read + /// Int Array which contains the input registers + public int[] ReadInputRegisters(int startingAddress, int quantity) + { + var data = ReadInputRegisters((ushort)startingAddress, quantity); + + var response = new int[quantity]; for (int i = 0; i < quantity; i++) { - byte lowByte; - byte highByte; - highByte = data[9+i*2]; - lowByte = data[9+i*2+1]; - - data[9+i*2] = lowByte; - data[9+i*2+1] = highByte; - - response[i] = BitConverter.ToInt16(data,(9+i*2)); - } - return (response); + response[i] = Convert.ToInt32(data[i]); + } + return response; } /// /// Read Input Registers from Master device (FC4). + /// 读取AI /// /// First input register to be read /// Number of input registers to be read /// Int Array which contains the input registers - public int[] ReadInputRegisters(int startingAddress, int quantity) - { + private byte[] ReadInputRegistersBuffer(ushort startingAddress, int quantity) + { if (debug) StoreLogData.Instance.Store("FC4 (Read Input Registers from Master device), StartingAddress: "+ startingAddress+", Quantity: " +quantity, System.DateTime.Now); transactionIdentifierInternal++; @@ -1486,7 +1521,7 @@ public int[] ReadInputRegisters(int startingAddress, int quantity) if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 125"); } - int[] response; + //int[] response; this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000); this.length = BitConverter.GetBytes((int)0x0006); @@ -1537,11 +1572,17 @@ public int[] ReadInputRegisters(int startingAddress, int quantity) DateTime dateTimeSend = DateTime.Now; byte receivedUnitIdentifier = 0xFF; +#if NETFRAMEWORK SpinWait sw_delay = new SpinWait(); +#endif while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) { while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) +#if NETFRAMEWORK sw_delay.SpinOnce(); +#else + System.Threading.Thread.Sleep(1); +#endif data = new byte[2100]; Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); @@ -1626,7 +1667,7 @@ public int[] ReadInputRegisters(int startingAddress, int quantity) else { countRetries++; - return ReadInputRegisters(startingAddress, quantity); + return ReadInputRegistersBuffer(startingAddress, quantity); } } else if (!dataReceived) @@ -1641,31 +1682,22 @@ public int[] ReadInputRegisters(int startingAddress, int quantity) else { countRetries++; - return ReadInputRegisters(startingAddress, quantity); + return ReadInputRegistersBuffer(startingAddress, quantity); } } } - response = new int[quantity]; - for (int i = 0; i < quantity; i++) - { - byte lowByte; - byte highByte; - highByte = data[9+i*2]; - lowByte = data[9+i*2+1]; - - data[9+i*2] = lowByte; - data[9+i*2+1] = highByte; - - response[i] = BitConverter.ToInt16(data,(9+i*2)); - } - return (response); - } - - - /// - /// Write single Coil to Master device (FC5). - /// + var array4 = new byte[quantity * 2]; + + Array.Copy(data, 9, array4, 0, array4.Length); + + return array4; + } + + + /// + /// Write single Coil to Master device (FC5). + /// /// Coil to be written /// Coil Value to be written public void WriteSingleCoil(int startingAddress, bool value) @@ -1859,7 +1891,22 @@ public void WriteSingleCoil(int startingAddress, bool value) /// Register Value to be written public void WriteSingleRegister(int startingAddress, int value) { - if (debug) StoreLogData.Instance.Store("FC6 (Write single register to Master device), StartingAddress: "+ startingAddress+", Value: " + value, System.DateTime.Now); + WriteSingleRegister((ushort)startingAddress, Convert.ToInt16(value)); + } + + /// + /// Write single Register to Master device (FC6). + /// 写单个AO + /// + /// Register to be written + /// Register Value to be written + private void WriteSingleRegisterBuffer(ushort startingAddress, byte[] value) + { + if (debug) StoreLogData.Instance.Store("FC6 (Write single register to Master device), StartingAddress: " + startingAddress + ", Value: " + value, System.DateTime.Now); + if (value.Length != 2) + { + throw new EasyModbus.Exceptions.SerialPortNotOpenedException("value length must be 2"); + } transactionIdentifierInternal++; if (serialport != null) if (!serialport.IsOpen) @@ -1872,13 +1919,12 @@ public void WriteSingleRegister(int startingAddress, int value) if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); throw new EasyModbus.Exceptions.ConnectionException("connection error"); } - byte[] registerValue = new byte[2]; + var registerValue = value; this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); this.length = BitConverter.GetBytes((int)0x0006); this.functionCode = 0x06; this.startingAddress = BitConverter.GetBytes(startingAddress); - registerValue = BitConverter.GetBytes((int)value); Byte[] data = new byte[]{ this.transactionIdentifier[1], this.transactionIdentifier[0], @@ -1922,11 +1968,17 @@ public void WriteSingleRegister(int startingAddress, int value) DateTime dateTimeSend = DateTime.Now; byte receivedUnitIdentifier = 0xFF; +#if NETFRAMEWORK SpinWait sw_delay = new SpinWait(); +#endif while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) { while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) +#if NETFRAMEWORK sw_delay.SpinOnce(); +#else + System.Threading.Thread.Sleep(1); +#endif data = new byte[2100]; Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); @@ -2010,7 +2062,7 @@ public void WriteSingleRegister(int startingAddress, int value) else { countRetries++; - WriteSingleRegister(startingAddress, value); + WriteSingleRegisterBuffer(startingAddress, value); } } else if (!dataReceived) @@ -2025,7 +2077,7 @@ public void WriteSingleRegister(int startingAddress, int value) else { countRetries++; - WriteSingleRegister(startingAddress, value); + WriteSingleRegisterBuffer(startingAddress, value); } } } @@ -2237,13 +2289,25 @@ public void WriteMultipleCoils(int startingAddress, bool[] values) /// register Values to be written public void WriteMultipleRegisters(int startingAddress, int[] values) { - string debugString = ""; - for (int i = 0; i < values.Length;i++) - debugString = debugString + values[i] + " "; - if (debug) StoreLogData.Instance.Store("FC16 (Write multiple Registers to Server device), StartingAddress: "+ startingAddress+", Values: " + debugString, System.DateTime.Now); + short[] data = new short[values.Length]; + for (int i = 0; i < values.Length; i++) + { + data[i] = Convert.ToInt16( values[i]); + } + WriteMultipleRegisters((ushort)startingAddress, data); + } + + /// + /// Write multiple registers to Master device (FC16). + /// 写AO + /// + /// First register to be written + /// register Values to be written + private void WriteMultipleRegistersBuffer(ushort startingAddress, byte[] values) + { transactionIdentifierInternal++; - byte byteCount = (byte)(values.Length * 2); - byte[] quantityOfOutputs = BitConverter.GetBytes((int)values.Length); + byte byteCount = (byte)(values.Length); + byte[] quantityOfOutputs = BitConverter.GetBytes(values.Length / 2); if (serialport != null) if (!serialport.IsOpen) { @@ -2257,11 +2321,11 @@ public void WriteMultipleRegisters(int startingAddress, int[] values) } this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)(7+values.Length*2)); + this.length = BitConverter.GetBytes((int)(7 + byteCount)); this.functionCode = 0x10; this.startingAddress = BitConverter.GetBytes(startingAddress); - Byte[] data = new byte[13+2 + values.Length*2]; + Byte[] data = new byte[13 + 2 + byteCount]; data[0] = this.transactionIdentifier[1]; data[1] = this.transactionIdentifier[0]; data[2] = this.protocolIdentifier[1]; @@ -2275,12 +2339,7 @@ public void WriteMultipleRegisters(int startingAddress, int[] values) data[10] = quantityOfOutputs[1]; data[11] = quantityOfOutputs[0]; data[12] = byteCount; - for (int i = 0; i < values.Length; i++) - { - byte[] singleRegisterValue = BitConverter.GetBytes((int)values[i]); - data[13 + i*2] = singleRegisterValue[1]; - data[14 + i*2] = singleRegisterValue[0]; - } + Array.Copy(values, 0, data, 13, values.Length); crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data.Length - 8), 6)); data[data.Length - 2] = crc[0]; data[data.Length - 1] = crc[1]; @@ -2309,11 +2368,17 @@ public void WriteMultipleRegisters(int startingAddress, int[] values) DateTime dateTimeSend = DateTime.Now; byte receivedUnitIdentifier = 0xFF; +#if NETFRAMEWORK SpinWait sw_delay = new SpinWait(); +#endif while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) { while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) +#if NETFRAMEWORK sw_delay.SpinOnce(); +#else + System.Threading.Thread.Sleep(1); +#endif data = new byte[2100]; Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); @@ -2427,11 +2492,32 @@ public void WriteMultipleRegisters(int startingAddress, int[] values) /// Int Array which contains the Holding registers public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRead, int startingAddressWrite, int[] values) { + short[] data = new short[values.Length]; + for (int i = 0; i < values.Length; i++) + { + data[i] = Convert.ToInt16(values[i]); + } - string debugString = ""; - for (int i = 0; i < values.Length;i++) - debugString = debugString + values[i] + " "; - if (debug) StoreLogData.Instance.Store("FC23 (Read and Write multiple Registers to Server device), StartingAddress Read: "+ startingAddressRead+ ", Quantity Read: "+quantityRead+", startingAddressWrite: " + startingAddressWrite +", Values: " + debugString, System.DateTime.Now); + data = ReadWriteMultipleRegisters((ushort)startingAddressRead, quantityRead, (ushort)startingAddressWrite, data); + var response = new int[quantityRead]; + for (int i = 0; i < quantityRead; i++) + { + response[i] = data[i]; + } + return (response); + } + + /// + /// Read/Write Multiple Registers (FC23). + /// 读写AO + /// + /// First input register to read + /// Number of input registers to read + /// First input register to write + /// Values to write + /// Int Array which contains the Holding registers + private byte[] ReadWriteMultipleRegistersBuffer(ushort startingAddressRead, int quantityRead, ushort startingAddressWrite, byte[] values) + { transactionIdentifierInternal++; byte [] startingAddressReadLocal = new byte[2]; byte [] quantityReadLocal = new byte[2]; @@ -2449,22 +2535,21 @@ public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRea if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); throw new EasyModbus.Exceptions.ConnectionException("connection error"); } - if (startingAddressRead > 65535 | quantityRead > 125 | startingAddressWrite > 65535 | values.Length > 121) + if (startingAddressRead > 65535 | quantityRead > 125 | startingAddressWrite > 65535 | values.Length > 241) { if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000"); } - int[] response; this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)11 + values.Length * 2); + this.length = BitConverter.GetBytes((int)11 + values.Length); this.functionCode = 0x17; startingAddressReadLocal = BitConverter.GetBytes(startingAddressRead); quantityReadLocal = BitConverter.GetBytes(quantityRead); startingAddressWriteLocal = BitConverter.GetBytes(startingAddressWrite); - quantityWriteLocal = BitConverter.GetBytes(values.Length); - writeByteCountLocal = Convert.ToByte(values.Length * 2); - Byte[] data = new byte[17 +2+ values.Length*2]; + quantityWriteLocal = BitConverter.GetBytes(values.Length / 2); + writeByteCountLocal = Convert.ToByte(values.Length); + Byte[] data = new byte[17 + 2 + values.Length]; data[0] = this.transactionIdentifier[1]; data[1] = this.transactionIdentifier[0]; data[2] = this.protocolIdentifier[1]; @@ -2483,12 +2568,7 @@ public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRea data[15] = quantityWriteLocal[0]; data[16] = writeByteCountLocal; - for (int i = 0; i < values.Length; i++) - { - byte[] singleRegisterValue = BitConverter.GetBytes((int)values[i]); - data[17 + i*2] = singleRegisterValue[1]; - data[18 + i*2] = singleRegisterValue[0]; - } + Array.Copy(values, 0, data, 17, values.Length); crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data.Length - 8), 6)); data[data.Length - 2] = crc[0]; data[data.Length - 1] = crc[1]; @@ -2515,11 +2595,17 @@ public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRea DateTime dateTimeSend = DateTime.Now; byte receivedUnitIdentifier = 0xFF; +#if NETFRAMEWORK SpinWait sw_delay = new SpinWait(); +#endif while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) { while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) +#if NETFRAMEWORK sw_delay.SpinOnce(); +#else + System.Threading.Thread.Sleep(1); +#endif data = new byte[2100]; Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); @@ -2589,20 +2675,10 @@ public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRea if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); throw new EasyModbus.Exceptions.ModbusException("error reading"); } - response = new int[quantityRead]; - for (int i = 0; i < quantityRead; i++) - { - byte lowByte; - byte highByte; - highByte = data[9 + i * 2]; - lowByte = data[9 + i * 2 + 1]; + var array4 = new byte[quantityRead * 2]; - data[9 + i * 2] = lowByte; - data[9 + i * 2 + 1] = highByte; - - response[i] = BitConverter.ToInt16(data, (9 + i * 2)); - } - return (response); + Array.Copy(data, 9, array4, 0, array4.Length); + return array4; } /// @@ -2667,7 +2743,7 @@ public bool Connected return false; else { - return connected; + return connected && tcpClient.Connected; } diff --git a/EasyModbus/Properties/AssemblyInfo.cs b/EasyModbus/Properties/AssemblyInfo.cs deleted file mode 100644 index 87e63ce..0000000 --- a/EasyModbus/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -#region Using directives - -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -#endregion - -// 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("EasyModbus")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Stefan Rossmann Engineering Solutions")] -[assembly: AssemblyProduct("EasyModbus")] -[assembly: AssemblyCopyright("Copyright 2017-2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. -[assembly: ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all the values or you can use the default the Revision and -// Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("5.6.0")] diff --git a/EasyModbus/nuget.exe b/EasyModbus/nuget.exe deleted file mode 100644 index ad35fa4..0000000 Binary files a/EasyModbus/nuget.exe and /dev/null differ diff --git a/EasyModbusAdvancedClient/EasyModbusAdvancedClient.csproj b/EasyModbusAdvancedClient/EasyModbusAdvancedClient.csproj index 77592b0..50bc255 100644 --- a/EasyModbusAdvancedClient/EasyModbusAdvancedClient.csproj +++ b/EasyModbusAdvancedClient/EasyModbusAdvancedClient.csproj @@ -65,6 +65,9 @@ + + AdvancedModbusClient.cs + Exceptions\Exceptions.cs diff --git a/EasyModbusClientExample/EasyModbusClientExample.csproj b/EasyModbusClientExample/EasyModbusClientExample.csproj index c228c5b..5e4a554 100644 --- a/EasyModbusClientExample/EasyModbusClientExample.csproj +++ b/EasyModbusClientExample/EasyModbusClientExample.csproj @@ -68,6 +68,9 @@ + + AdvancedModbusClient.cs + Exceptions\Exceptions.cs diff --git a/EasyModbusServerSimulator/EasyModbusServerSimulator.csproj b/EasyModbusServerSimulator/EasyModbusServerSimulator.csproj index 7bd300a..16ee3fd 100644 --- a/EasyModbusServerSimulator/EasyModbusServerSimulator.csproj +++ b/EasyModbusServerSimulator/EasyModbusServerSimulator.csproj @@ -90,6 +90,9 @@ + + AdvancedModbusClient.cs + Exceptions\Exceptions.cs diff --git a/EasyModbus_NET5/EasyModbus.StoreLogData.cs b/EasyModbus_NET5/EasyModbus.StoreLogData.cs deleted file mode 100644 index 3345038..0000000 --- a/EasyModbus_NET5/EasyModbus.StoreLogData.cs +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace EasyModbus -{ - /// - /// Store Log-Data in a File - /// - public sealed class StoreLogData - { - private String filename = null; - private static volatile StoreLogData instance; - private static object syncObject = new Object(); - - /// - /// Private constructor; Ensures the access of the class only via "instance" - /// - private StoreLogData() - { - } - - /// - /// Returns the instance of the class (singleton) - /// - /// instance (Singleton) - public static StoreLogData Instance - { - get - { - if (instance == null) - { - lock (syncObject) - { - if (instance == null) - instance = new StoreLogData(); - } - } - - return instance; - } - } - - /// - /// Store message in Log-File - /// - /// Message to append to the Log-File - public void Store(String message) - { - if (this.filename == null) - return; - - using (System.IO.StreamWriter file = - new System.IO.StreamWriter(Filename, true)) - { - file.WriteLine(message); - } - } - - /// - /// Store message in Log-File including Timestamp - /// - /// Message to append to the Log-File - /// Timestamp to add to the same Row - public void Store(String message, DateTime timestamp) - { - try - { - using (System.IO.StreamWriter file = - new System.IO.StreamWriter(Filename, true)) - { - file.WriteLine(timestamp.ToString("dd.MM.yyyy H:mm:ss.ff ") + message); - } - } - catch (Exception e) - { - - } - } - - /// - /// Gets or Sets the Filename to Store Strings in a File - /// - public string Filename - { - get - { - return filename; - } - set - { - filename = value; - } - } - } -} diff --git a/EasyModbus_NET5/EasyModbus_V5.0.csproj b/EasyModbus_NET5/EasyModbus_V5.0.csproj deleted file mode 100644 index 9c1ace3..0000000 --- a/EasyModbus_NET5/EasyModbus_V5.0.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net5.0 - EasyModbus - EasyModbus - false - - - - - - - - - - - - - diff --git a/EasyModbus_NET5/Exceptions/Exceptions.cs b/EasyModbus_NET5/Exceptions/Exceptions.cs deleted file mode 100644 index 8d1db4f..0000000 --- a/EasyModbus_NET5/Exceptions/Exceptions.cs +++ /dev/null @@ -1,211 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -using System; -using System.Runtime.Serialization; - -namespace EasyModbus.Exceptions -{ - /// - /// Exception to be thrown if serial port is not opened - /// - public class SerialPortNotOpenedException : ModbusException - { - public SerialPortNotOpenedException() - : base() - { - } - - public SerialPortNotOpenedException(string message) - : base(message) - { - } - - public SerialPortNotOpenedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected SerialPortNotOpenedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Connection to Modbus device failed - /// - public class ConnectionException : ModbusException - { - public ConnectionException() - : base() - { - } - - public ConnectionException(string message) - : base(message) - { - } - - public ConnectionException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected ConnectionException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "Function code not supported" - /// - public class FunctionCodeNotSupportedException : ModbusException - { - public FunctionCodeNotSupportedException() - : base() - { - } - - public FunctionCodeNotSupportedException(string message) - : base(message) - { - } - - public FunctionCodeNotSupportedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected FunctionCodeNotSupportedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "quantity invalid" - /// - public class QuantityInvalidException : ModbusException - { - public QuantityInvalidException() - : base() - { - } - - public QuantityInvalidException(string message) - : base(message) - { - } - - public QuantityInvalidException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected QuantityInvalidException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "starting adddress and quantity invalid" - /// - public class StartingAddressInvalidException : ModbusException - { - public StartingAddressInvalidException() - : base() - { - } - - public StartingAddressInvalidException(string message) - : base(message) - { - } - - public StartingAddressInvalidException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected StartingAddressInvalidException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "Function Code not executed (0x04)" - /// - public class ModbusException : Exception - { - public ModbusException() - : base() - { - } - - public ModbusException(string message) - : base(message) - { - } - - public ModbusException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected ModbusException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if CRC Check failed - /// - public class CRCCheckFailedException : ModbusException - { - public CRCCheckFailedException() - : base() - { - } - - public CRCCheckFailedException(string message) - : base(message) - { - } - - public CRCCheckFailedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected CRCCheckFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - -} diff --git a/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Core.cs b/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Core.cs deleted file mode 100644 index 16b6cb4..0000000 --- a/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Core.cs +++ /dev/null @@ -1,328 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Net.Sockets; -using System.IO.Ports; - - - - - -namespace EasyModbus -{ - - public partial class ModbusClient - { - - - #region Class Variables - private bool debug = false; - private TcpClient tcpClient; - private bool udpFlag = false; - private string ipAddress = "127.0.0.1"; - private int port = 502; - private int baudRate = 9600; - private int connectTimeout = 1000; - private bool connected; - - private byte[] protocolIdentifier = new byte[2]; - private byte[] crc = new byte[2]; - private byte[] length = new byte[2]; - private byte unitIdentifier = 0x01; - private byte functionCode; - private byte[] startingAddress = new byte[2]; - private byte[] quantity = new byte[2]; - - private bool dataReceived = false; - private int bytesToRead = 0; - public byte[] sendData; - public byte[] receiveData; - private byte[] readBuffer = new byte[256]; - private int portOut; - - public int NumberOfRetries { get; set; } = 3; - private int countRetries = 0; - - private uint transactionIdentifierInternal = 0; - private byte[] transactionIdentifier = new byte[2]; - - private SerialPort serialport; - private bool receiveActive = false; - - public delegate void ConnectedChangedHandler(object sender); - public event ConnectedChangedHandler ConnectedChanged; - - public delegate void ReceiveDataChangedHandler(object sender); - public event ReceiveDataChangedHandler ReceiveDataChanged; - - public delegate void SendDataChangedHandler(object sender); - public event SendDataChangedHandler SendDataChanged; - - NetworkStream stream; - #endregion - - - /// - /// Establish connection to Master device in case of Modbus TCP. - /// - public void Connect(string ipAddress, int port) - { - if (!udpFlag) - { - if (debug) StoreLogData.Instance.Store("Open TCP-Socket, IP-Address: " + ipAddress + ", Port: " + port, System.DateTime.Now); - tcpClient = new TcpClient(); - var result = tcpClient.BeginConnect(ipAddress, port, null, null); - var success = result.AsyncWaitHandle.WaitOne(connectTimeout); - if (!success) - { - throw new EasyModbus.Exceptions.ConnectionException("connection timed out"); - } - tcpClient.EndConnect(result); - - //tcpClient = new TcpClient(ipAddress, port); - stream = tcpClient.GetStream(); - stream.ReadTimeout = connectTimeout; - connected = true; - } - else - { - tcpClient = new TcpClient(); - connected = true; - } - - if (ConnectedChanged != null) - ConnectedChanged(this); - } - - - /// - /// Close connection to Master Device. - /// - public void Disconnect() - { - if (debug) StoreLogData.Instance.Store("Disconnect", System.DateTime.Now); - if (serialport != null) - { - if (serialport.IsOpen & !receiveActive) - serialport.Close(); - if (ConnectedChanged != null) - ConnectedChanged(this); - return; - } - if (stream != null) - stream.Close(); - if (tcpClient != null) - tcpClient.Close(); - connected = false; - if (ConnectedChanged != null) - ConnectedChanged(this); - - } - - - - /// - /// Read Discrete Inputs from Server device (FC2). - /// - /// First discrete input to read - /// Number of discrete Inputs to read - /// Boolean Array which contains the discrete Inputs - public bool[] ReadDiscreteInputs(int startingAddress, int quantity) - { - if (debug) StoreLogData.Instance.Store("FC2 (Read Discrete Inputs from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity, System.DateTime.Now); - transactionIdentifierInternal++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - if (startingAddress > 65535 | quantity > 2000) - { - if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); - throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000"); - } - - // Create Request - ApplicationDataUnit request = new ApplicationDataUnit(2); - request.QuantityRead = (ushort)quantity; - request.StartingAddressRead = (ushort)startingAddress; - request.TransactionIdentifier = (ushort)transactionIdentifierInternal; - - - ApplicationDataUnit response = new ApplicationDataUnit(2); - response.QuantityRead = (ushort)quantity; - - byte[] data = new byte[255]; - if (serialport != null) - { - dataReceived = false; - if (quantity % 8 == 0) - bytesToRead = 5 + quantity / 8; - else - bytesToRead = 6 + quantity / 8; - - serialport.Write(request.Payload, 6, 8); - if (debug) - { - byte[] debugData = new byte[8]; - Array.Copy(request.Payload, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(request.Payload, 6, sendData, 0, 8); - SendDataChanged(this); - - } - - - - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.UtcNow; - - response.UnitIdentifier = 0xFF; - - while (response.UnitIdentifier != unitIdentifier & !((DateTime.UtcNow.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * connectTimeout)) - { - while (dataReceived == false & !((DateTime.UtcNow.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[255]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - - } - if (response.UnitIdentifier != unitIdentifier) - data = new byte[255]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - System.Net.IPEndPoint endPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length - 2, endPoint); - portOut = ((System.Net.IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(request.Payload, 0, request.Payload.Length - 2); - if (debug) - { - byte[] debugData = new byte[data.Length - 2]; - Array.Copy(data, 0, debugData, 0, data.Length - 2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length - 2]; - Array.Copy(data, 0, sendData, 0, data.Length - 2); - SendDataChanged(this); - } - data = new Byte[255]; - int NumberOfBytes = stream.Read(response.Payload, 0, response.Payload.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x82 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x82 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x82 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x82 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data[8] + 3), 6)); - if ((crc[0] != data[data[8] + 9] | crc[1] != data[data[8] + 10]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - return ReadDiscreteInputs(startingAddress, quantity); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - } - else - { - countRetries++; - return ReadDiscreteInputs(startingAddress, quantity); - } - } - } - - return response.RegisterDataBool; - } - - - - - } -} diff --git a/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Helpers.cs b/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Helpers.cs deleted file mode 100644 index e9340b8..0000000 --- a/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Helpers.cs +++ /dev/null @@ -1,508 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EasyModbus -{ - public partial class ModbusClient - { - - public enum RegisterOrder { LowHigh = 0, HighLow = 1 }; - - /// - /// Calculates the CRC16 for Modbus-RTU - /// - /// Byte buffer to send - /// Number of bytes to calculate CRC - /// First byte in buffer to start calculating CRC - internal static UInt16 calculateCRC(byte[] data, UInt16 numberOfBytes, int startByte) - { - byte[] auchCRCHi = { - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, - 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, - 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, - 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, - 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, - 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40 - }; - - byte[] auchCRCLo = { - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, - 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, - 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, - 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, - 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, - 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, - 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, - 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, - 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, - 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, - 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, - 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, - 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, - 0x40 - }; - UInt16 usDataLen = numberOfBytes; - byte uchCRCHi = 0xFF; - byte uchCRCLo = 0xFF; - int i = 0; - int uIndex; - while (usDataLen > 0) - { - usDataLen--; - if ((i + startByte) < data.Length) - { - uIndex = uchCRCLo ^ data[i + startByte]; - uchCRCLo = (byte)(uchCRCHi ^ auchCRCHi[uIndex]); - uchCRCHi = auchCRCLo[uIndex]; - } - i++; - } - return (UInt16)((UInt16)uchCRCHi << 8 | uchCRCLo); - } - - /// - /// Converts two ModbusRegisters to Float - Example: EasyModbus.ModbusClient.ConvertRegistersToFloat(modbusClient.ReadHoldingRegisters(19,2)) - /// - /// Two Register values received from Modbus - /// Connected float value - public static float ConvertRegistersToFloat(int[] registers) - { - if (registers.Length != 2) - throw new ArgumentException("Input Array length invalid - Array langth must be '2'"); - int highRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] floatBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToSingle(floatBytes, 0); - } - - - /// - /// Converts two ModbusRegisters to Float, Registers can by swapped - /// - /// Two Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connected float value - public static float ConvertRegistersToFloat(int[] registers, RegisterOrder registerOrder) - { - int[] swappedRegisters = { registers[0], registers[1] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[1], registers[0] }; - return ConvertRegistersToFloat(swappedRegisters); - } - - /// - /// Converts two ModbusRegisters to 32 Bit Integer value - /// - /// Two Register values received from Modbus - /// Connected 32 Bit Integer value - public static Int32 ConvertRegistersToInt(int[] registers) - { - if (registers.Length != 2) - throw new ArgumentException("Input Array length invalid - Array langth must be '2'"); - int highRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] doubleBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToInt32(doubleBytes, 0); - } - - /// - /// Converts two ModbusRegisters to 32 Bit Integer Value - Registers can be swapped - /// - /// Two Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connecteds 32 Bit Integer value - public static Int32 ConvertRegistersToInt(int[] registers, RegisterOrder registerOrder) - { - int[] swappedRegisters = { registers[0], registers[1] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[1], registers[0] }; - return ConvertRegistersToInt(swappedRegisters); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit Integer value Register Order "LowHigh": Reg0: Low Word.....Reg3: High Word, "HighLow": Reg0: High Word.....Reg3: Low Word - /// - /// four Register values received from Modbus - /// 64 bit value - - public static Int64 ConvertRegistersToLong(int[] registers) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int highRegister = registers[3]; - int highLowRegister = registers[2]; - int lowHighRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister); - byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] longBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - lowHighRegisterBytes[0], - lowHighRegisterBytes[1], - highLowRegisterBytes[0], - highLowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToInt64(longBytes, 0); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit Integer value - Registers can be swapped - /// - /// four Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connected 64 Bit Integer value - public static Int64 ConvertRegistersToLong(int[] registers, RegisterOrder registerOrder) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int[] swappedRegisters = { registers[0], registers[1], registers[2], registers[3] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[3], registers[2], registers[1], registers[0] }; - return ConvertRegistersToLong(swappedRegisters); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit double prec. value Register Order "LowHigh": Reg0: Low Word.....Reg3: High Word, "HighLow": Reg0: High Word.....Reg3: Low Word - /// - /// four Register values received from Modbus - /// 64 bit value - public static double ConvertRegistersToDouble(int[] registers) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int highRegister = registers[3]; - int highLowRegister = registers[2]; - int lowHighRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister); - byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] longBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - lowHighRegisterBytes[0], - lowHighRegisterBytes[1], - highLowRegisterBytes[0], - highLowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToDouble(longBytes, 0); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit double prec. value - Registers can be swapped - /// - /// four Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connected double prec. float value - public static double ConvertRegistersToDouble(int[] registers, RegisterOrder registerOrder) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int[] swappedRegisters = { registers[0], registers[1], registers[2], registers[3] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[3], registers[2], registers[1], registers[0] }; - return ConvertRegistersToDouble(swappedRegisters); - } - - /// - /// Converts float to two ModbusRegisters - Example: modbusClient.WriteMultipleRegisters(24, EasyModbus.ModbusClient.ConvertFloatToTwoRegisters((float)1.22)); - /// - /// Float value which has to be converted into two registers - /// Register values - public static int[] ConvertFloatToRegisters(float floatValue) - { - byte[] floatBytes = BitConverter.GetBytes(floatValue); - byte[] highRegisterBytes = - { - floatBytes[2], - floatBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - floatBytes[0], - floatBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts float to two ModbusRegisters Registers - Registers can be swapped - /// - /// Float value which has to be converted into two registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertFloatToRegisters(float floatValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertFloatToRegisters(floatValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new Int32[] { registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 32 Bit Value to two ModbusRegisters - /// - /// Int value which has to be converted into two registers - /// Register values - public static int[] ConvertIntToRegisters(Int32 intValue) - { - byte[] doubleBytes = BitConverter.GetBytes(intValue); - byte[] highRegisterBytes = - { - doubleBytes[2], - doubleBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - doubleBytes[0], - doubleBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts 32 Bit Value to two ModbusRegisters Registers - Registers can be swapped - /// - /// Double value which has to be converted into two registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertIntToRegisters(Int32 intValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertIntToRegisters(intValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new Int32[] { registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 64 Bit Value to four ModbusRegisters - /// - /// long value which has to be converted into four registers - /// Register values - public static int[] ConvertLongToRegisters(Int64 longValue) - { - byte[] longBytes = BitConverter.GetBytes(longValue); - byte[] highRegisterBytes = - { - longBytes[6], - longBytes[7], - 0, - 0 - }; - byte[] highLowRegisterBytes = - { - longBytes[4], - longBytes[5], - 0, - 0 - }; - byte[] lowHighRegisterBytes = - { - longBytes[2], - longBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - longBytes[0], - longBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(lowHighRegisterBytes,0), - BitConverter.ToInt32(highLowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts 64 Bit Value to four ModbusRegisters - Registers can be swapped - /// - /// long value which has to be converted into four registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertLongToRegisters(Int64 longValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertLongToRegisters(longValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new int[] { registerValues[3], registerValues[2], registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 64 Bit double prec Value to four ModbusRegisters - /// - /// double value which has to be converted into four registers - /// Register values - public static int[] ConvertDoubleToRegisters(double doubleValue) - { - byte[] doubleBytes = BitConverter.GetBytes(doubleValue); - byte[] highRegisterBytes = - { - doubleBytes[6], - doubleBytes[7], - 0, - 0 - }; - byte[] highLowRegisterBytes = - { - doubleBytes[4], - doubleBytes[5], - 0, - 0 - }; - byte[] lowHighRegisterBytes = - { - doubleBytes[2], - doubleBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - doubleBytes[0], - doubleBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(lowHighRegisterBytes,0), - BitConverter.ToInt32(highLowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts 64 Bit double prec. Value to four ModbusRegisters - Registers can be swapped - /// - /// double value which has to be converted into four registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertDoubleToRegisters(double doubleValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertDoubleToRegisters(doubleValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new int[] { registerValues[3], registerValues[2], registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 16 - Bit Register values to String - /// - /// Register array received via Modbus - /// First Register containing the String to convert - /// number of characters in String (must be even) - /// Converted String - public static string ConvertRegistersToString(int[] registers, int offset, int stringLength) - { - byte[] result = new byte[stringLength]; - byte[] registerResult = new byte[2]; - - for (int i = 0; i < stringLength / 2; i++) - { - registerResult = BitConverter.GetBytes(registers[offset + i]); - result[i * 2] = registerResult[0]; - result[i * 2 + 1] = registerResult[1]; - } - return System.Text.Encoding.Default.GetString(result); - } - - /// - /// Converts a String to 16 - Bit Registers - /// - /// Register array received via Modbus - /// Converted String - public static int[] ConvertStringToRegisters(string stringToConvert) - { - byte[] array = System.Text.Encoding.ASCII.GetBytes(stringToConvert); - int[] returnarray = new int[stringToConvert.Length / 2 + stringToConvert.Length % 2]; - for (int i = 0; i < returnarray.Length; i++) - { - returnarray[i] = array[i * 2]; - if (i * 2 + 1 < array.Length) - { - returnarray[i] = returnarray[i] | ((int)array[i * 2 + 1] << 8); - } - } - return returnarray; - } - - - - } -} diff --git a/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Protocol.cs b/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Protocol.cs deleted file mode 100644 index 161ffba..0000000 --- a/EasyModbus_NET5/ModbusClient/EasyModbus.ModbusClient.Protocol.cs +++ /dev/null @@ -1,189 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EasyModbus -{ - - - - /// - /// Protocol Data Unit (PDU) - As Specified in the Modbus Appliction Protocol specification V1.1b3 Page 3 - /// The PDU consists of: - /// Function code - 1 byte - /// Data - x bytes - /// The "Data" section is described in the Documentation of the Function code and will be created according to the given Function code - /// - class ProtocolDataUnit - { - public byte FunctionCode { get; set; } - private byte[] data; - public ushort StartingAddressRead { get; set; } - public ushort StartingAddressWrite { get; set; } - public ushort QuantityRead { get; set; } - public ushort QuantityWrite { get; set; } - public byte ByteCount { get; } - public byte ErroCode { get; } - public byte ExceptionCode { get; } - public int[] RegisterDataInt { get; set; } - - public bool[] RegisterDataBool { get; set; } - - - - public byte[] Data - { - //return the data in case of a request - get - { - Byte[] returnvalue = null; - switch (FunctionCode) - { - - // FC01 (0x01) "Read Coils" Page 11 - case 1: - returnvalue = new byte[] - { - BitConverter.GetBytes((ushort)StartingAddressRead)[1], - BitConverter.GetBytes((ushort)StartingAddressRead)[0], - BitConverter.GetBytes((ushort)QuantityRead)[1], - BitConverter.GetBytes((ushort)QuantityRead)[0], - - }; - break; - // FC02 (0x02) "Read Discrete Inputs" Page 12 - case 2: - returnvalue = new byte[] - { - BitConverter.GetBytes((ushort)StartingAddressRead)[1], - BitConverter.GetBytes((ushort)StartingAddressRead)[0], - BitConverter.GetBytes((ushort)QuantityRead)[1], - BitConverter.GetBytes((ushort)QuantityRead)[0], - - }; - break; - } - return returnvalue; - } - //set the data in case of a response - set - { - switch (FunctionCode) - { - // FC 01: Read Coils and 02 Read Discrete Inputs provide the same response - case 1: case 2: - byte byteCount = value[1]; - RegisterDataBool = new bool[QuantityRead]; - for (int i = 0; i < QuantityRead; i++) - { - int intData = data[i / 8]; - int mask = Convert.ToInt32(Math.Pow(2, (i % 8))); - RegisterDataBool[i] = (Convert.ToBoolean((intData & mask) / mask)); - } - break; - - } - } - - - } - - } - - /// - /// Application Data Unit (ADU) - As Specified in the Modbus Appliction Protocol specification V1.1b3 Page 3 (or Modbus Messaging on TCP/IP Implementation Guide Page 4) - /// The ADU consists of: - /// - /// MBAP Header (only for Modbus TCP) - /// Transaction Identifier - 2 Bytes - /// Protocol Identiifier - 2 Bytes - /// Length - 2 Bytes - /// - /// Additional Address - 1 byte - /// PDU - x Byte - /// CRC - 2 byte (not used for Modbus TCP) - /// The "Data" section is described in the Documentation of the Function code and will be created according to the given Function code - /// - class ApplicationDataUnit : ProtocolDataUnit - { - - public ushort TransactionIdentifier { get; set; } - private ushort protocolIdentifier = 0; - - public byte UnitIdentifier { get; set; } - /// - /// Constructor, the Function code has to be handed over at instantiation - /// - /// - public ApplicationDataUnit(byte functionCode) - { - this.FunctionCode = functionCode; - } - - public byte[] Mbap_Header - { - get - { - ushort length = 0x0006; - if (FunctionCode == 15) - { - byte byteCount = (byte)((RegisterDataBool.Length % 8 != 0 ? RegisterDataBool.Length / 8 + 1 : (RegisterDataBool.Length / 8))); - length = (ushort)(7 + byteCount); - } - if (FunctionCode == 16) - length = (ushort)(7 + RegisterDataInt.Length * 2); - if (FunctionCode == 23) - length = (ushort)(11 + RegisterDataInt.Length * 2); - - Byte[] returnvalue = new byte[] - { - BitConverter.GetBytes((ushort)TransactionIdentifier)[1], - BitConverter.GetBytes((ushort)TransactionIdentifier)[0], - BitConverter.GetBytes((ushort)protocolIdentifier)[1], - BitConverter.GetBytes((ushort)protocolIdentifier)[0], - BitConverter.GetBytes((ushort)length)[1], - BitConverter.GetBytes((ushort)length)[0], - UnitIdentifier - }; - - return returnvalue; - } - } - - - - public byte[] Payload { - // Return the Payload in case of a request - get - { - List returnvalue = new List(); - - returnvalue.AddRange(this.Mbap_Header); - returnvalue.Add(FunctionCode); - returnvalue.AddRange(Data); - - byte [] crc = BitConverter.GetBytes(ModbusClient.calculateCRC(returnvalue.ToArray(), (ushort)(returnvalue.Count - 8), 6)); - returnvalue.AddRange(crc); - return returnvalue.ToArray(); - } - // Set the Payload in case of a resonse - set - { - - TransactionIdentifier = BitConverter.ToUInt16(value, 0); - UnitIdentifier = value[6]; - - } - - - } - - - } - - - - - } diff --git a/EasyModbus_Net60/AdvancedModbusClient.cs b/EasyModbus_Net60/AdvancedModbusClient.cs deleted file mode 100644 index 2c322f0..0000000 --- a/EasyModbus_Net60/AdvancedModbusClient.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace EasyModbus -{ - public partial class ModbusClient - { - /* - public enum DataType { Short = 0, UShort = 1, Long = 2, ULong = 3, Float = 4, Double = 5 }; - public object[] ReadHoldingRegisters(int startingAddress, int quantity, DataType dataType, RegisterOrder registerOrder) - { - int quantityToRead = quantity; - if (dataType == DataType.Long | dataType == DataType.ULong | dataType == DataType.Float) - quantityToRead = quantity * 2; - if (dataType == DataType.Float) - quantityToRead = quantity * 4; - int[] response = this.ReadHoldingRegisters(startingAddress, quantityToRead); - switch (dataType) - { - case DataType.Short: return response.Cast().ToArray(); - break; - default: return response.Cast().ToArray(); - break; - - } - - - } - */ - } -} diff --git a/EasyModbus_Net60/EasyModbus_Net60.csproj b/EasyModbus_Net60/EasyModbus_Net60.csproj deleted file mode 100644 index 27f1e16..0000000 --- a/EasyModbus_Net60/EasyModbus_Net60.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net6.0 - enable - enable - EasyModbus - EasyModbus - - - - - - - diff --git a/EasyModbus_Net60/Exceptions/Exceptions.cs b/EasyModbus_Net60/Exceptions/Exceptions.cs deleted file mode 100644 index 8d1db4f..0000000 --- a/EasyModbus_Net60/Exceptions/Exceptions.cs +++ /dev/null @@ -1,211 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -using System; -using System.Runtime.Serialization; - -namespace EasyModbus.Exceptions -{ - /// - /// Exception to be thrown if serial port is not opened - /// - public class SerialPortNotOpenedException : ModbusException - { - public SerialPortNotOpenedException() - : base() - { - } - - public SerialPortNotOpenedException(string message) - : base(message) - { - } - - public SerialPortNotOpenedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected SerialPortNotOpenedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Connection to Modbus device failed - /// - public class ConnectionException : ModbusException - { - public ConnectionException() - : base() - { - } - - public ConnectionException(string message) - : base(message) - { - } - - public ConnectionException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected ConnectionException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "Function code not supported" - /// - public class FunctionCodeNotSupportedException : ModbusException - { - public FunctionCodeNotSupportedException() - : base() - { - } - - public FunctionCodeNotSupportedException(string message) - : base(message) - { - } - - public FunctionCodeNotSupportedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected FunctionCodeNotSupportedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "quantity invalid" - /// - public class QuantityInvalidException : ModbusException - { - public QuantityInvalidException() - : base() - { - } - - public QuantityInvalidException(string message) - : base(message) - { - } - - public QuantityInvalidException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected QuantityInvalidException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "starting adddress and quantity invalid" - /// - public class StartingAddressInvalidException : ModbusException - { - public StartingAddressInvalidException() - : base() - { - } - - public StartingAddressInvalidException(string message) - : base(message) - { - } - - public StartingAddressInvalidException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected StartingAddressInvalidException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if Modbus Server returns error code "Function Code not executed (0x04)" - /// - public class ModbusException : Exception - { - public ModbusException() - : base() - { - } - - public ModbusException(string message) - : base(message) - { - } - - public ModbusException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected ModbusException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Exception to be thrown if CRC Check failed - /// - public class CRCCheckFailedException : ModbusException - { - public CRCCheckFailedException() - : base() - { - } - - public CRCCheckFailedException(string message) - : base(message) - { - } - - public CRCCheckFailedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected CRCCheckFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - -} diff --git a/EasyModbus_Net60/ModbusClient.cs b/EasyModbus_Net60/ModbusClient.cs deleted file mode 100644 index c1e8f38..0000000 --- a/EasyModbus_Net60/ModbusClient.cs +++ /dev/null @@ -1,2851 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -using System; -using System.Net.Sockets; -using System.Net; -using System.IO.Ports; -using System.Reflection; -using System.Text; -using System.Collections.Generic; - -namespace EasyModbus -{ - /// - /// Implements a ModbusClient. - /// - public partial class ModbusClient - { - public enum RegisterOrder { LowHigh = 0, HighLow = 1 }; - private bool debug=false; - private TcpClient tcpClient; - private string ipAddress = "127.0.0.1"; - private int port = 502; - private uint transactionIdentifierInternal = 0; - private byte [] transactionIdentifier = new byte[2]; - private byte [] protocolIdentifier = new byte[2]; - private byte[] crc = new byte[2]; - private byte [] length = new byte[2]; - private byte unitIdentifier = 0x01; - private byte functionCode; - private byte [] startingAddress = new byte[2]; - private byte [] quantity = new byte[2]; - private bool udpFlag = false; - private int portOut; - private int baudRate = 9600; - private int connectTimeout = 1000; - public byte[] receiveData; - public byte[] sendData; - private SerialPort serialport; - private Parity parity = Parity.Even; - private StopBits stopBits = StopBits.One; - private bool connected = false; - public int NumberOfRetries { get; set; } = 3; - private int countRetries = 0; - - public delegate void ReceiveDataChangedHandler(object sender); - public event ReceiveDataChangedHandler ReceiveDataChanged; - - public delegate void SendDataChangedHandler(object sender); - public event SendDataChangedHandler SendDataChanged; - - public delegate void ConnectedChangedHandler(object sender); - public event ConnectedChangedHandler ConnectedChanged; - - NetworkStream stream; - - /// - /// Constructor which determines the Master ip-address and the Master Port. - /// - /// IP-Address of the Master device - /// Listening port of the Master device (should be 502) - public ModbusClient(string ipAddress, int port) - { - if (debug) StoreLogData.Instance.Store("EasyModbus library initialized for Modbus-TCP, IPAddress: " + ipAddress + ", Port: "+port ,System.DateTime.Now); -#if (!COMMERCIAL) - Console.WriteLine("EasyModbus Client Library Version: " + Assembly.GetExecutingAssembly().GetName().Version.ToString()); - Console.WriteLine("Copyright (c) Stefan Rossmann Engineering Solutions"); - Console.WriteLine(); -#endif - this.ipAddress = ipAddress; - this.port = port; - } - - /// - /// Constructor which determines the Serial-Port - /// - /// Serial-Port Name e.G. "COM1" - public ModbusClient(string serialPort) - { - if (debug) StoreLogData.Instance.Store("EasyModbus library initialized for Modbus-RTU, COM-Port: " + serialPort ,System.DateTime.Now); -#if (!COMMERCIAL) - Console.WriteLine("EasyModbus Client Library Version: " + Assembly.GetExecutingAssembly().GetName().Version.ToString()); - Console.WriteLine("Copyright (c) Stefan Rossmann Engineering Solutions"); - Console.WriteLine(); -#endif - this.serialport = new SerialPort(); - serialport.PortName = serialPort; - serialport.BaudRate = baudRate; - serialport.Parity = parity; - serialport.StopBits = stopBits; - serialport.WriteTimeout = 10000; - serialport.ReadTimeout = connectTimeout; - - serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); - } - - /// - /// Parameterless constructor - /// - public ModbusClient() - { - if (debug) StoreLogData.Instance.Store("EasyModbus library initialized for Modbus-TCP" ,System.DateTime.Now); -#if (!COMMERCIAL) - Console.WriteLine("EasyModbus Client Library Version: " + Assembly.GetExecutingAssembly().GetName().Version.ToString()); - Console.WriteLine("Copyright (c) Stefan Rossmann Engineering Solutions"); - Console.WriteLine(); -#endif - } - - /// - /// Establish connection to Master device in case of Modbus TCP. Opens COM-Port in case of Modbus RTU - /// - public void Connect() - { - if (serialport != null) - { - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("Open Serial port " + serialport.PortName,System.DateTime.Now); - serialport.BaudRate = baudRate; - serialport.Parity = parity; - serialport.StopBits = stopBits; - serialport.WriteTimeout = 10000; - serialport.ReadTimeout = connectTimeout; - serialport.Open(); - connected = true; - - - } - if (ConnectedChanged != null) - try - { - ConnectedChanged(this); - } - catch - { - - } - return; - } - if (!udpFlag) - { - if (debug) StoreLogData.Instance.Store("Open TCP-Socket, IP-Address: " + ipAddress + ", Port: " + port, System.DateTime.Now); - tcpClient = new TcpClient(); - var result = tcpClient.BeginConnect(ipAddress, port, null, null); - var success = result.AsyncWaitHandle.WaitOne(connectTimeout); - if (!success) - { - throw new EasyModbus.Exceptions.ConnectionException("connection timed out"); - } - tcpClient.EndConnect(result); - - //tcpClient = new TcpClient(ipAddress, port); - stream = tcpClient.GetStream(); - stream.ReadTimeout = connectTimeout; - connected = true; - } - else - { - tcpClient = new TcpClient(); - connected = true; - } - if (ConnectedChanged != null) - try - { - ConnectedChanged(this); - } - catch - { - - } - } - - /// - /// Establish connection to Master device in case of Modbus TCP. - /// - public void Connect(string ipAddress, int port) - { - if (!udpFlag) - { - if (debug) StoreLogData.Instance.Store("Open TCP-Socket, IP-Address: " + ipAddress + ", Port: " + port, System.DateTime.Now); - tcpClient = new TcpClient(); - var result = tcpClient.BeginConnect(ipAddress, port, null, null); - var success = result.AsyncWaitHandle.WaitOne(connectTimeout); - if (!success) - { - throw new EasyModbus.Exceptions.ConnectionException("connection timed out"); - } - tcpClient.EndConnect(result); - - //tcpClient = new TcpClient(ipAddress, port); - stream = tcpClient.GetStream(); - stream.ReadTimeout = connectTimeout; - connected = true; - } - else - { - tcpClient = new TcpClient(); - connected = true; - } - - if (ConnectedChanged != null) - ConnectedChanged(this); - } - - /// - /// Converts two ModbusRegisters to Float - Example: EasyModbus.ModbusClient.ConvertRegistersToFloat(modbusClient.ReadHoldingRegisters(19,2)) - /// - /// Two Register values received from Modbus - /// Connected float value - public static float ConvertRegistersToFloat(int[] registers) - { - if (registers.Length != 2) - throw new ArgumentException("Input Array length invalid - Array langth must be '2'"); - int highRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] floatBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToSingle(floatBytes, 0); - } - - /// - /// Converts two ModbusRegisters to Float, Registers can by swapped - /// - /// Two Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connected float value - public static float ConvertRegistersToFloat(int[] registers, RegisterOrder registerOrder) - { - int [] swappedRegisters = {registers[0],registers[1]}; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] {registers[1],registers[0]}; - return ConvertRegistersToFloat(swappedRegisters); - } - - /// - /// Converts two ModbusRegisters to 32 Bit Integer value - /// - /// Two Register values received from Modbus - /// Connected 32 Bit Integer value - public static Int32 ConvertRegistersToInt(int[] registers) - { - if (registers.Length != 2) - throw new ArgumentException("Input Array length invalid - Array langth must be '2'"); - int highRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] doubleBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToInt32(doubleBytes, 0); - } - - /// - /// Converts two ModbusRegisters to 32 Bit Integer Value - Registers can be swapped - /// - /// Two Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connecteds 32 Bit Integer value - public static Int32 ConvertRegistersToInt(int[] registers, RegisterOrder registerOrder) - { - int[] swappedRegisters = { registers[0], registers[1] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[1], registers[0] }; - return ConvertRegistersToInt(swappedRegisters); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit Integer value Register Order "LowHigh": Reg0: Low Word.....Reg3: High Word, "HighLow": Reg0: High Word.....Reg3: Low Word - /// - /// four Register values received from Modbus - /// 64 bit value - public static Int64 ConvertRegistersToLong(int[] registers) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int highRegister = registers[3]; - int highLowRegister = registers[2]; - int lowHighRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister); - byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] longBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - lowHighRegisterBytes[0], - lowHighRegisterBytes[1], - highLowRegisterBytes[0], - highLowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToInt64(longBytes, 0); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit Integer value - Registers can be swapped - /// - /// four Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connected 64 Bit Integer value - public static Int64 ConvertRegistersToLong(int[] registers, RegisterOrder registerOrder) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int[] swappedRegisters = { registers[0], registers[1], registers[2], registers[3] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[3], registers[2], registers[1], registers[0] }; - return ConvertRegistersToLong(swappedRegisters); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit double prec. value Register Order "LowHigh": Reg0: Low Word.....Reg3: High Word, "HighLow": Reg0: High Word.....Reg3: Low Word - /// - /// four Register values received from Modbus - /// 64 bit value - public static double ConvertRegistersToDouble(int[] registers) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int highRegister = registers[3]; - int highLowRegister = registers[2]; - int lowHighRegister = registers[1]; - int lowRegister = registers[0]; - byte[] highRegisterBytes = BitConverter.GetBytes(highRegister); - byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister); - byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister); - byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister); - byte[] longBytes = { - lowRegisterBytes[0], - lowRegisterBytes[1], - lowHighRegisterBytes[0], - lowHighRegisterBytes[1], - highLowRegisterBytes[0], - highLowRegisterBytes[1], - highRegisterBytes[0], - highRegisterBytes[1] - }; - return BitConverter.ToDouble(longBytes, 0); - } - - /// - /// Convert four 16 Bit Registers to 64 Bit double prec. value - Registers can be swapped - /// - /// four Register values received from Modbus - /// Desired Word Order (Low Register first or High Register first - /// Connected double prec. float value - public static double ConvertRegistersToDouble(int[] registers, RegisterOrder registerOrder) - { - if (registers.Length != 4) - throw new ArgumentException("Input Array length invalid - Array langth must be '4'"); - int[] swappedRegisters = { registers[0], registers[1], registers[2], registers[3] }; - if (registerOrder == RegisterOrder.HighLow) - swappedRegisters = new int[] { registers[3], registers[2], registers[1], registers[0] }; - return ConvertRegistersToDouble(swappedRegisters); - } - - /// - /// Converts float to two ModbusRegisters - Example: modbusClient.WriteMultipleRegisters(24, EasyModbus.ModbusClient.ConvertFloatToTwoRegisters((float)1.22)); - /// - /// Float value which has to be converted into two registers - /// Register values - public static int[] ConvertFloatToRegisters(float floatValue) - { - byte[] floatBytes = BitConverter.GetBytes(floatValue); - byte[] highRegisterBytes = - { - floatBytes[2], - floatBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - floatBytes[0], - floatBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts float to two ModbusRegisters Registers - Registers can be swapped - /// - /// Float value which has to be converted into two registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertFloatToRegisters(float floatValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertFloatToRegisters(floatValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new Int32[] { registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 32 Bit Value to two ModbusRegisters - /// - /// Int value which has to be converted into two registers - /// Register values - public static int[] ConvertIntToRegisters(Int32 intValue) - { - byte[] doubleBytes = BitConverter.GetBytes(intValue); - byte[] highRegisterBytes = - { - doubleBytes[2], - doubleBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - doubleBytes[0], - doubleBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts 32 Bit Value to two ModbusRegisters Registers - Registers can be swapped - /// - /// Double value which has to be converted into two registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertIntToRegisters(Int32 intValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertIntToRegisters(intValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new Int32[] { registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 64 Bit Value to four ModbusRegisters - /// - /// long value which has to be converted into four registers - /// Register values - public static int[] ConvertLongToRegisters(Int64 longValue) - { - byte[] longBytes = BitConverter.GetBytes(longValue); - byte[] highRegisterBytes = - { - longBytes[6], - longBytes[7], - 0, - 0 - }; - byte[] highLowRegisterBytes = - { - longBytes[4], - longBytes[5], - 0, - 0 - }; - byte[] lowHighRegisterBytes = - { - longBytes[2], - longBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - longBytes[0], - longBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(lowHighRegisterBytes,0), - BitConverter.ToInt32(highLowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts 64 Bit Value to four ModbusRegisters - Registers can be swapped - /// - /// long value which has to be converted into four registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertLongToRegisters(Int64 longValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertLongToRegisters(longValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new int[] { registerValues[3], registerValues[2], registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 64 Bit double prec Value to four ModbusRegisters - /// - /// double value which has to be converted into four registers - /// Register values - public static int[] ConvertDoubleToRegisters(double doubleValue) - { - byte[] doubleBytes = BitConverter.GetBytes(doubleValue); - byte[] highRegisterBytes = - { - doubleBytes[6], - doubleBytes[7], - 0, - 0 - }; - byte[] highLowRegisterBytes = - { - doubleBytes[4], - doubleBytes[5], - 0, - 0 - }; - byte[] lowHighRegisterBytes = - { - doubleBytes[2], - doubleBytes[3], - 0, - 0 - }; - byte[] lowRegisterBytes = - { - - doubleBytes[0], - doubleBytes[1], - 0, - 0 - }; - int[] returnValue = - { - BitConverter.ToInt32(lowRegisterBytes,0), - BitConverter.ToInt32(lowHighRegisterBytes,0), - BitConverter.ToInt32(highLowRegisterBytes,0), - BitConverter.ToInt32(highRegisterBytes,0) - }; - return returnValue; - } - - /// - /// Converts 64 Bit double prec. Value to four ModbusRegisters - Registers can be swapped - /// - /// double value which has to be converted into four registers - /// Desired Word Order (Low Register first or High Register first - /// Register values - public static int[] ConvertDoubleToRegisters(double doubleValue, RegisterOrder registerOrder) - { - int[] registerValues = ConvertDoubleToRegisters(doubleValue); - int[] returnValue = registerValues; - if (registerOrder == RegisterOrder.HighLow) - returnValue = new int[] { registerValues[3], registerValues[2], registerValues[1], registerValues[0] }; - return returnValue; - } - - /// - /// Converts 16 - Bit Register values to String - /// - /// Register array received via Modbus - /// First Register containing the String to convert - /// number of characters in String (must be even) - /// Converted String - public static string ConvertRegistersToString(int[] registers, int offset, int stringLength) - { - byte[] result = new byte[stringLength]; - byte[] registerResult = new byte[2]; - - for (int i = 0; i < stringLength/2; i++) - { - registerResult = BitConverter.GetBytes(registers[offset + i]); - result[i * 2] = registerResult[0]; - result[i * 2 + 1] = registerResult[1]; - } - return System.Text.Encoding.Default.GetString(result); - } - - /// - /// Converts a String to 16 - Bit Registers - /// - /// Register array received via Modbus - /// Converted String - public static int[] ConvertStringToRegisters(string stringToConvert) - { - byte[] array = System.Text.Encoding.ASCII.GetBytes(stringToConvert); - int[] returnarray = new int[stringToConvert.Length / 2 + stringToConvert.Length % 2]; - for (int i = 0; i < returnarray.Length; i++) - { - returnarray[i] = array[i * 2]; - if (i*2 +1< array.Length) - { - returnarray[i] = returnarray[i] | ((int)array[i * 2 + 1] << 8); - } - } - return returnarray; - } - - - /// - /// Calculates the CRC16 for Modbus-RTU - /// - /// Byte buffer to send - /// Number of bytes to calculate CRC - /// First byte in buffer to start calculating CRC - public static UInt16 calculateCRC(byte[] data, UInt16 numberOfBytes, int startByte) - { - byte[] auchCRCHi = { - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, - 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, - 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, - 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, - 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, - 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, - 0x40 - }; - - byte[] auchCRCLo = { - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, - 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, - 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, - 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, - 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, - 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, - 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, - 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, - 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, - 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, - 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, - 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, - 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, - 0x40 - }; - UInt16 usDataLen = numberOfBytes; - byte uchCRCHi = 0xFF ; - byte uchCRCLo = 0xFF ; - int i = 0; - int uIndex ; - while (usDataLen>0) - { - usDataLen--; - if ((i + startByte) < data.Length) - { - uIndex = uchCRCLo ^ data[i + startByte]; - uchCRCLo = (byte)(uchCRCHi ^ auchCRCHi[uIndex]); - uchCRCHi = auchCRCLo[uIndex]; - } - i++; - } - return (UInt16)((UInt16)uchCRCHi << 8 | uchCRCLo); - } - - private bool dataReceived = false; - private bool receiveActive = false; - private byte[] readBuffer = new byte[256]; - private int bytesToRead = 0; - private int akjjjctualPositionToRead = 0; - DateTime dateTimeLastRead; -/* - private void DataReceivedHandler(object sender, - SerialDataReceivedEventArgs e) - { - long ticksWait = TimeSpan.TicksPerMillisecond * 2000; - SerialPort sp = (SerialPort)sender; - - if (bytesToRead == 0 || sp.BytesToRead == 0) - { - actualPositionToRead = 0; - sp.DiscardInBuffer(); - dataReceived = false; - receiveActive = false; - return; - } - - if (actualPositionToRead == 0 && !dataReceived) - readBuffer = new byte[256]; - - //if ((DateTime.Now.Ticks - dateTimeLastRead.Ticks) > ticksWait) - //{ - // readBuffer = new byte[256]; - // actualPositionToRead = 0; - //} - int numberOfBytesInBuffer = sp.BytesToRead; - sp.Read(readBuffer, actualPositionToRead, ((numberOfBytesInBuffer + actualPositionToRead) > readBuffer.Length) ? 0 : numberOfBytesInBuffer); - actualPositionToRead = actualPositionToRead + numberOfBytesInBuffer; - //sp.DiscardInBuffer(); - //if (DetectValidModbusFrame(readBuffer, (actualPositionToRead < readBuffer.Length) ? actualPositionToRead : readBuffer.Length) | bytesToRead <= actualPositionToRead) - if (actualPositionToRead >= bytesToRead) - { - - dataReceived = true; - bytesToRead = 0; - actualPositionToRead = 0; - if (debug) StoreLogData.Instance.Store("Received Serial-Data: " + BitConverter.ToString(readBuffer), System.DateTime.Now); - - } - - - //dateTimeLastRead = DateTime.Now; - } - */ - - - private void DataReceivedHandler(object sender, - SerialDataReceivedEventArgs e) - { - serialport.DataReceived -= DataReceivedHandler; - - //while (receiveActive | dataReceived) - // System.Threading.Thread.Sleep(10); - receiveActive = true; - - const long ticksWait = TimeSpan.TicksPerMillisecond * 2000;//((40*10000000) / this.baudRate); - - - SerialPort sp = (SerialPort)sender; - if (bytesToRead == 0) - { - sp.DiscardInBuffer(); - receiveActive = false; - serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); - return; - } - readBuffer = new byte[256]; - int numbytes=0; - int actualPositionToRead = 0; - DateTime dateTimeLastRead = DateTime.Now; - do{ - try { - dateTimeLastRead = DateTime.Now; - while ((sp.BytesToRead) == 0) - { - System.Threading.Thread.Sleep(10); - if ((DateTime.Now.Ticks - dateTimeLastRead.Ticks) > ticksWait) - break; - } - numbytes=sp.BytesToRead; - - - byte[] rxbytearray = new byte[numbytes]; - sp.Read(rxbytearray, 0, numbytes); - Array.Copy(rxbytearray,0, readBuffer,actualPositionToRead, (actualPositionToRead + rxbytearray.Length) <= bytesToRead ? rxbytearray.Length : bytesToRead - actualPositionToRead); - - actualPositionToRead = actualPositionToRead + rxbytearray.Length; - - } - catch (Exception){ - - } - - if (bytesToRead <= actualPositionToRead) - break; - - if (DetectValidModbusFrame(readBuffer, (actualPositionToRead < readBuffer.Length) ? actualPositionToRead : readBuffer.Length) | bytesToRead <= actualPositionToRead) - break; - } - while ((DateTime.Now.Ticks - dateTimeLastRead.Ticks) < ticksWait) ; - - //10.000 Ticks in 1 ms - - receiveData = new byte[actualPositionToRead]; - Array.Copy(readBuffer, 0, receiveData, 0, (actualPositionToRead < readBuffer.Length) ? actualPositionToRead: readBuffer.Length); - if (debug) StoreLogData.Instance.Store("Received Serial-Data: "+BitConverter.ToString(readBuffer) ,System.DateTime.Now); - bytesToRead = 0; - - - - - dataReceived = true; - receiveActive = false; - serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); - if (ReceiveDataChanged != null) - { - - ReceiveDataChanged(this); - - } - - //sp.DiscardInBuffer(); - } - - public static bool DetectValidModbusFrame(byte[] readBuffer, int length) - { - // minimum length 6 bytes - if (length < 6) - return false; - //SlaveID correct - if ((readBuffer[0] < 1) | (readBuffer[0] > 247)) - return false; - //CRC correct? - byte[] crc = new byte[2]; - crc = BitConverter.GetBytes(calculateCRC(readBuffer, (ushort)(length-2), 0)); - if (crc[0] != readBuffer[length-2] | crc[1] != readBuffer[length-1]) - return false; - return true; - } - - - - /// - /// Read Discrete Inputs from Server device (FC2). - /// - /// First discrete input to read - /// Number of discrete Inputs to read - /// Boolean Array which contains the discrete Inputs - public bool[] ReadDiscreteInputs(int startingAddress, int quantity) - { - if (debug) StoreLogData.Instance.Store("FC2 (Read Discrete Inputs from Master device), StartingAddress: "+ startingAddress+", Quantity: " +quantity, System.DateTime.Now); - transactionIdentifierInternal ++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport==null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - if (startingAddress > 65535 | quantity >2000) - { - if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); - throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000"); - } - bool[] response; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000); - this.length = BitConverter.GetBytes((int)0x0006); - this.functionCode = 0x02; - this.startingAddress = BitConverter.GetBytes(startingAddress); - this.quantity = BitConverter.GetBytes(quantity); - Byte[] data = new byte[] - { - this.transactionIdentifier[1], - this.transactionIdentifier[0], - this.protocolIdentifier[1], - this.protocolIdentifier[0], - this.length[1], - this.length[0], - this.unitIdentifier, - this.functionCode, - this.startingAddress[1], - this.startingAddress[0], - this.quantity[1], - this.quantity[0], - this.crc[0], - this.crc[1] - }; - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - data[12] = crc[0]; - data[13] = crc[1]; - - if (serialport != null) - { - dataReceived = false; - if (quantity % 8 == 0) - bytesToRead = 5 + quantity / 8; - else - bytesToRead = 6 + quantity / 8; - // serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, 8); - if (debug) - { - byte [] debugData = new byte[8]; - Array.Copy(data, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(data, 6, sendData, 0, 8); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - - - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x82 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x82 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x82 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x82 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data[8]+3), 6)); - if ((crc[0] != data[data[8] + 9] | crc[1] != data[data[8] + 10]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - return ReadDiscreteInputs(startingAddress, quantity); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - } - else - { - countRetries++; - return ReadDiscreteInputs(startingAddress, quantity); - } - } - } - response = new bool[quantity]; - for (int i = 0; i < quantity; i++) - { - int intData = data[9+i/8]; - int mask = Convert.ToInt32(Math.Pow(2, (i%8))); - response[i] = Convert.ToBoolean((intData & mask)/mask); - } - return (response); - } - - - /// - /// Read Coils from Server device (FC1). - /// - /// First coil to read - /// Numer of coils to read - /// Boolean Array which contains the coils - public bool[] ReadCoils(int startingAddress, int quantity) - { - if (debug) StoreLogData.Instance.Store("FC1 (Read Coils from Master device), StartingAddress: "+ startingAddress+", Quantity: " +quantity, System.DateTime.Now); - transactionIdentifierInternal++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - if (startingAddress > 65535 | quantity >2000) - { - if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); - throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000"); - } - bool[] response; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000); - this.length = BitConverter.GetBytes((int)0x0006); - this.functionCode = 0x01; - this.startingAddress = BitConverter.GetBytes(startingAddress); - this.quantity = BitConverter.GetBytes(quantity); - Byte[] data = new byte[]{ - this.transactionIdentifier[1], - this.transactionIdentifier[0], - this.protocolIdentifier[1], - this.protocolIdentifier[0], - this.length[1], - this.length[0], - this.unitIdentifier, - this.functionCode, - this.startingAddress[1], - this.startingAddress[0], - this.quantity[1], - this.quantity[0], - this.crc[0], - this.crc[1] - }; - - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - data[12] = crc[0]; - data[13] = crc[1]; - if (serialport != null) - { - dataReceived = false; - if (quantity % 8 == 0) - bytesToRead = 5 + quantity/8; - else - bytesToRead = 6 + quantity/8; - // serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, 8); - if (debug) - { - byte [] debugData = new byte[8]; - Array.Copy(data, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(data, 6, sendData, 0, 8); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send MocbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x81 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x81 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x81 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x81 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data[8]+3), 6)); - if ((crc[0] != data[data[8]+9] | crc[1] != data[data[8]+10]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - return ReadCoils(startingAddress, quantity); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - } - else - { - countRetries++; - return ReadCoils(startingAddress, quantity); - } - } - } - response = new bool[quantity]; - for (int i = 0; i < quantity; i++) - { - int intData = data[9+i/8]; - int mask = Convert.ToInt32(Math.Pow(2, (i%8))); - response[i] = Convert.ToBoolean((intData & mask)/mask); - } - return (response); - } - - - /// - /// Read Holding Registers from Master device (FC3). - /// - /// First holding register to be read - /// Number of holding registers to be read - /// Int Array which contains the holding registers - public int[] ReadHoldingRegisters(int startingAddress, int quantity) - { - if (debug) StoreLogData.Instance.Store("FC3 (Read Holding Registers from Master device), StartingAddress: "+ startingAddress+", Quantity: " +quantity, System.DateTime.Now); - transactionIdentifierInternal++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - if (startingAddress > 65535 | quantity >125) - { - if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); - throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 125"); - } - int[] response; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000); - this.length = BitConverter.GetBytes((int)0x0006); - this.functionCode = 0x03; - this.startingAddress = BitConverter.GetBytes(startingAddress); - this.quantity = BitConverter.GetBytes(quantity); - Byte[] data = new byte[]{ this.transactionIdentifier[1], - this.transactionIdentifier[0], - this.protocolIdentifier[1], - this.protocolIdentifier[0], - this.length[1], - this.length[0], - this.unitIdentifier, - this.functionCode, - this.startingAddress[1], - this.startingAddress[0], - this.quantity[1], - this.quantity[0], - this.crc[0], - this.crc[1] - }; - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - data[12] = crc[0]; - data[13] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 5 + 2 * quantity; -// serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, 8); - if (debug) - { - byte [] debugData = new byte[8]; - Array.Copy(data, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(data, 6, sendData, 0, 8); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - - } - data = new Byte[256]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x83 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x83 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x83 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x83 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data[8]+3), 6)); - if ((crc[0] != data[data[8]+9] | crc[1] != data[data[8]+10])& dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - return ReadHoldingRegisters(startingAddress, quantity); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - } - else - { - countRetries++; - return ReadHoldingRegisters(startingAddress, quantity); - } - - - } - } - response = new int[quantity]; - for (int i = 0; i < quantity; i++) - { - byte lowByte; - byte highByte; - highByte = data[9+i*2]; - lowByte = data[9+i*2+1]; - - data[9+i*2] = lowByte; - data[9+i*2+1] = highByte; - - response[i] = BitConverter.ToInt16(data,(9+i*2)); - } - return (response); - } - - - - /// - /// Read Input Registers from Master device (FC4). - /// - /// First input register to be read - /// Number of input registers to be read - /// Int Array which contains the input registers - public int[] ReadInputRegisters(int startingAddress, int quantity) - { - - if (debug) StoreLogData.Instance.Store("FC4 (Read Input Registers from Master device), StartingAddress: "+ startingAddress+", Quantity: " +quantity, System.DateTime.Now); - transactionIdentifierInternal++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - if (startingAddress > 65535 | quantity >125) - { - if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); - throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 125"); - } - int[] response; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000); - this.length = BitConverter.GetBytes((int)0x0006); - this.functionCode = 0x04; - this.startingAddress = BitConverter.GetBytes(startingAddress); - this.quantity = BitConverter.GetBytes(quantity); - Byte[] data = new byte[]{ this.transactionIdentifier[1], - this.transactionIdentifier[0], - this.protocolIdentifier[1], - this.protocolIdentifier[0], - this.length[1], - this.length[0], - this.unitIdentifier, - this.functionCode, - this.startingAddress[1], - this.startingAddress[0], - this.quantity[1], - this.quantity[0], - this.crc[0], - this.crc[1] - }; - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - data[12] = crc[0]; - data[13] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 5 + 2 * quantity; - - - // serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, 8); - if (debug) - { - byte [] debugData = new byte[8]; - Array.Copy(data, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(data, 6, sendData, 0, 8); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - - } - } - if (data[7] == 0x84 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x84 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x84 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x84 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data[8]+3), 6)); - if ((crc[0] != data[data[8]+9] | crc[1] != data[data[8]+10]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - return ReadInputRegisters(startingAddress, quantity); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - - } - else - { - countRetries++; - return ReadInputRegisters(startingAddress, quantity); - } - - } - } - response = new int[quantity]; - for (int i = 0; i < quantity; i++) - { - byte lowByte; - byte highByte; - highByte = data[9+i*2]; - lowByte = data[9+i*2+1]; - - data[9+i*2] = lowByte; - data[9+i*2+1] = highByte; - - response[i] = BitConverter.ToInt16(data,(9+i*2)); - } - return (response); - } - - - /// - /// Write single Coil to Master device (FC5). - /// - /// Coil to be written - /// Coil Value to be written - public void WriteSingleCoil(int startingAddress, bool value) - { - - if (debug) StoreLogData.Instance.Store("FC5 (Write single coil to Master device), StartingAddress: "+ startingAddress+", Value: " + value, System.DateTime.Now); - transactionIdentifierInternal++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - byte[] coilValue = new byte[2]; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)0x0006); - this.functionCode = 0x05; - this.startingAddress = BitConverter.GetBytes(startingAddress); - if (value == true) - { - coilValue = BitConverter.GetBytes((int)0xFF00); - } - else - { - coilValue = BitConverter.GetBytes((int)0x0000); - } - Byte[] data = new byte[]{ this.transactionIdentifier[1], - this.transactionIdentifier[0], - this.protocolIdentifier[1], - this.protocolIdentifier[0], - this.length[1], - this.length[0], - this.unitIdentifier, - this.functionCode, - this.startingAddress[1], - this.startingAddress[0], - coilValue[1], - coilValue[0], - this.crc[0], - this.crc[1] - }; - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - data[12] = crc[0]; - data[13] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 8; - // serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, 8); - if (debug) - { - byte [] debugData = new byte[8]; - Array.Copy(data, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(data, 6, sendData, 0, 8); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length - 2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length - 2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x85 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x85 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x85 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x85 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - WriteSingleCoil(startingAddress, value); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - - } - else - { - countRetries++; - WriteSingleCoil(startingAddress, value); - } - } - } - } - - - /// - /// Write single Register to Master device (FC6). - /// - /// Register to be written - /// Register Value to be written - public void WriteSingleRegister(int startingAddress, int value) - { - if (debug) StoreLogData.Instance.Store("FC6 (Write single register to Master device), StartingAddress: "+ startingAddress+", Value: " + value, System.DateTime.Now); - transactionIdentifierInternal++; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - byte[] registerValue = new byte[2]; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)0x0006); - this.functionCode = 0x06; - this.startingAddress = BitConverter.GetBytes(startingAddress); - registerValue = BitConverter.GetBytes((int)value); - - Byte[] data = new byte[]{ this.transactionIdentifier[1], - this.transactionIdentifier[0], - this.protocolIdentifier[1], - this.protocolIdentifier[0], - this.length[1], - this.length[0], - this.unitIdentifier, - this.functionCode, - this.startingAddress[1], - this.startingAddress[0], - registerValue[1], - registerValue[0], - this.crc[0], - this.crc[1] - }; - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - data[12] = crc[0]; - data[13] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 8; -// serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, 8); - if (debug) - { - byte [] debugData = new byte[8]; - Array.Copy(data, 6, debugData, 0, 8); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[8]; - Array.Copy(data, 6, sendData, 0, 8); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length - 2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length - 2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x86 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x86 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x86 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x86 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - WriteSingleRegister(startingAddress, value); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - - } - else - { - countRetries++; - WriteSingleRegister(startingAddress, value); - } - } - } - } - - /// - /// Write multiple coils to Master device (FC15). - /// - /// First coil to be written - /// Coil Values to be written - public void WriteMultipleCoils(int startingAddress, bool[] values) - { - string debugString = ""; - for (int i = 0; i < values.Length;i++) - debugString = debugString + values[i] + " "; - if (debug) StoreLogData.Instance.Store("FC15 (Write multiple coils to Master device), StartingAddress: "+ startingAddress+", Values: " + debugString, System.DateTime.Now); - transactionIdentifierInternal++; - byte byteCount = (byte)((values.Length % 8 != 0 ? values.Length / 8 + 1: (values.Length / 8))); - byte[] quantityOfOutputs = BitConverter.GetBytes((int)values.Length); - byte singleCoilValue = 0; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)(7+(byteCount))); - this.functionCode = 0x0F; - this.startingAddress = BitConverter.GetBytes(startingAddress); - - - - Byte[] data = new byte[14 +2 + (values.Length % 8 != 0 ? values.Length/8 : (values.Length / 8)-1)]; - data[0] = this.transactionIdentifier[1]; - data[1] = this.transactionIdentifier[0]; - data[2] = this.protocolIdentifier[1]; - data[3] = this.protocolIdentifier[0]; - data[4] = this.length[1]; - data[5] = this.length[0]; - data[6] = this.unitIdentifier; - data[7] = this.functionCode; - data[8] = this.startingAddress[1]; - data[9] = this.startingAddress[0]; - data[10] = quantityOfOutputs[1]; - data[11] = quantityOfOutputs[0]; - data[12] = byteCount; - for (int i = 0; i < values.Length; i++) - { - if ((i % 8) == 0) - singleCoilValue = 0; - byte CoilValue; - if (values[i] == true) - CoilValue = 1; - else - CoilValue = 0; - - - singleCoilValue = (byte)((int)CoilValue<<(i%8) | (int)singleCoilValue); - - data[13 + (i / 8)] = singleCoilValue; - } - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data.Length - 8), 6)); - data[data.Length - 2] = crc[0]; - data[data.Length - 1] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 8; - // serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte [] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length - 6]; - Array.Copy(data, 6, sendData, 0, data.Length - 6); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x8F & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x8F & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x8F & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x8F & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - WriteMultipleCoils(startingAddress, values); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - - } - else - { - countRetries++; - WriteMultipleCoils(startingAddress, values); - } - } - } - } - - /// - /// Write multiple registers to Master device (FC16). - /// - /// First register to be written - /// register Values to be written - public void WriteMultipleRegisters(int startingAddress, int[] values) - { - string debugString = ""; - for (int i = 0; i < values.Length;i++) - debugString = debugString + values[i] + " "; - if (debug) StoreLogData.Instance.Store("FC16 (Write multiple Registers to Server device), StartingAddress: "+ startingAddress+", Values: " + debugString, System.DateTime.Now); - transactionIdentifierInternal++; - byte byteCount = (byte)(values.Length * 2); - byte[] quantityOfOutputs = BitConverter.GetBytes((int)values.Length); - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)(7+values.Length*2)); - this.functionCode = 0x10; - this.startingAddress = BitConverter.GetBytes(startingAddress); - - Byte[] data = new byte[13+2 + values.Length*2]; - data[0] = this.transactionIdentifier[1]; - data[1] = this.transactionIdentifier[0]; - data[2] = this.protocolIdentifier[1]; - data[3] = this.protocolIdentifier[0]; - data[4] = this.length[1]; - data[5] = this.length[0]; - data[6] = this.unitIdentifier; - data[7] = this.functionCode; - data[8] = this.startingAddress[1]; - data[9] = this.startingAddress[0]; - data[10] = quantityOfOutputs[1]; - data[11] = quantityOfOutputs[0]; - data[12] = byteCount; - for (int i = 0; i < values.Length; i++) - { - byte[] singleRegisterValue = BitConverter.GetBytes((int)values[i]); - data[13 + i*2] = singleRegisterValue[1]; - data[14 + i*2] = singleRegisterValue[0]; - } - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data.Length - 8), 6)); - data[data.Length - 2] = crc[0]; - data[data.Length - 1] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 8; -// serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, data.Length - 6); - - if (debug) - { - byte [] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length - 6]; - Array.Copy(data, 6, sendData, 0, data.Length - 6); - SendDataChanged(this); - - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x90 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x90 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x90 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x90 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - if (serialport != null) - { - crc = BitConverter.GetBytes(calculateCRC(data, 6, 6)); - if ((crc[0] != data[12] | crc[1] != data[13]) &dataReceived) - { - if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed"); - } - else - { - countRetries++; - WriteMultipleRegisters(startingAddress, values); - } - } - else if (!dataReceived) - { - if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now); - if (NumberOfRetries <= countRetries) - { - countRetries = 0; - throw new TimeoutException("No Response from Modbus Slave"); - - } - else - { - countRetries++; - WriteMultipleRegisters(startingAddress, values); - } - } - } - } - - /// - /// Read/Write Multiple Registers (FC23). - /// - /// First input register to read - /// Number of input registers to read - /// First input register to write - /// Values to write - /// Int Array which contains the Holding registers - public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRead, int startingAddressWrite, int[] values) - { - - string debugString = ""; - for (int i = 0; i < values.Length;i++) - debugString = debugString + values[i] + " "; - if (debug) StoreLogData.Instance.Store("FC23 (Read and Write multiple Registers to Server device), StartingAddress Read: "+ startingAddressRead+ ", Quantity Read: "+quantityRead+", startingAddressWrite: " + startingAddressWrite +", Values: " + debugString, System.DateTime.Now); - transactionIdentifierInternal++; - byte [] startingAddressReadLocal = new byte[2]; - byte [] quantityReadLocal = new byte[2]; - byte[] startingAddressWriteLocal = new byte[2]; - byte[] quantityWriteLocal = new byte[2]; - byte writeByteCountLocal = 0; - if (serialport != null) - if (!serialport.IsOpen) - { - if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - } - if (tcpClient == null & !udpFlag & serialport == null) - { - if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ConnectionException("connection error"); - } - if (startingAddressRead > 65535 | quantityRead > 125 | startingAddressWrite > 65535 | values.Length > 121) - { - if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now); - throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000"); - } - int[] response; - this.transactionIdentifier = BitConverter.GetBytes((uint)transactionIdentifierInternal); - this.protocolIdentifier = BitConverter.GetBytes((int)0x0000); - this.length = BitConverter.GetBytes((int)11 + values.Length * 2); - this.functionCode = 0x17; - startingAddressReadLocal = BitConverter.GetBytes(startingAddressRead); - quantityReadLocal = BitConverter.GetBytes(quantityRead); - startingAddressWriteLocal = BitConverter.GetBytes(startingAddressWrite); - quantityWriteLocal = BitConverter.GetBytes(values.Length); - writeByteCountLocal = Convert.ToByte(values.Length * 2); - Byte[] data = new byte[17 +2+ values.Length*2]; - data[0] = this.transactionIdentifier[1]; - data[1] = this.transactionIdentifier[0]; - data[2] = this.protocolIdentifier[1]; - data[3] = this.protocolIdentifier[0]; - data[4] = this.length[1]; - data[5] = this.length[0]; - data[6] = this.unitIdentifier; - data[7] = this.functionCode; - data[8] = startingAddressReadLocal[1]; - data[9] = startingAddressReadLocal[0]; - data[10] = quantityReadLocal[1]; - data[11] = quantityReadLocal[0]; - data[12] = startingAddressWriteLocal[1]; - data[13] = startingAddressWriteLocal[0]; - data[14] = quantityWriteLocal[1]; - data[15] = quantityWriteLocal[0]; - data[16] = writeByteCountLocal; - - for (int i = 0; i < values.Length; i++) - { - byte[] singleRegisterValue = BitConverter.GetBytes((int)values[i]); - data[17 + i*2] = singleRegisterValue[1]; - data[18 + i*2] = singleRegisterValue[0]; - } - crc = BitConverter.GetBytes(calculateCRC(data, (ushort)(data.Length - 8), 6)); - data[data.Length - 2] = crc[0]; - data[data.Length - 1] = crc[1]; - if (serialport != null) - { - dataReceived = false; - bytesToRead = 5 + 2*quantityRead; - // serialport.ReceivedBytesThreshold = bytesToRead; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte [] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length - 6]; - Array.Copy(data, 6, sendData, 0, data.Length - 6); - SendDataChanged(this); - } - data = new byte[2100]; - readBuffer = new byte[256]; - DateTime dateTimeSend = DateTime.Now; - byte receivedUnitIdentifier = 0xFF; - while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - { - while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout)) - System.Threading.Thread.Sleep(1); - data = new byte[2100]; - Array.Copy(readBuffer, 0, data, 6, readBuffer.Length); - receivedUnitIdentifier = data[6]; - } - if (receivedUnitIdentifier != this.unitIdentifier) - data = new byte[2100]; - else - countRetries = 0; - } - else if (tcpClient.Client.Connected | udpFlag) - { - if (udpFlag) - { - UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port); - udpClient.Send(data, data.Length-2, endPoint); - portOut = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; - udpClient.Client.ReceiveTimeout = 5000; - endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut); - data = udpClient.Receive(ref endPoint); - } - else - { - stream.Write(data, 0, data.Length-2); - if (debug) - { - byte [] debugData = new byte[data.Length-2]; - Array.Copy(data, 0, debugData, 0, data.Length-2); - if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: "+BitConverter.ToString(debugData) ,System.DateTime.Now); - } - if (SendDataChanged != null) - { - sendData = new byte[data.Length-2]; - Array.Copy(data, 0, sendData, 0, data.Length-2); - SendDataChanged(this); - - } - data = new Byte[2100]; - int NumberOfBytes = stream.Read(data, 0, data.Length); - if (ReceiveDataChanged != null) - { - receiveData = new byte[NumberOfBytes]; - Array.Copy(data, 0, receiveData, 0, NumberOfBytes); - if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now); - ReceiveDataChanged(this); - } - } - } - if (data[7] == 0x97 & data[8] == 0x01) - { - if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master"); - } - if (data[7] == 0x97 & data[8] == 0x02) - { - if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid"); - } - if (data[7] == 0x97 & data[8] == 0x03) - { - if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid"); - } - if (data[7] == 0x97 & data[8] == 0x04) - { - if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now); - throw new EasyModbus.Exceptions.ModbusException("error reading"); - } - response = new int[quantityRead]; - for (int i = 0; i < quantityRead; i++) - { - byte lowByte; - byte highByte; - highByte = data[9 + i * 2]; - lowByte = data[9 + i * 2 + 1]; - - data[9 + i * 2] = lowByte; - data[9 + i * 2 + 1] = highByte; - - response[i] = BitConverter.ToInt16(data, (9 + i * 2)); - } - return (response); - } - - /// - /// Close connection to Master Device. - /// - public void Disconnect() - { - if (debug) StoreLogData.Instance.Store("Disconnect", System.DateTime.Now); - if (serialport != null) - { - if (serialport.IsOpen & !this.receiveActive) - serialport.Close(); - if (ConnectedChanged != null) - ConnectedChanged(this); - return; - } - if (stream != null) - stream.Close(); - if (tcpClient != null) - tcpClient.Close(); - connected = false; - if (ConnectedChanged != null) - ConnectedChanged(this); - - } - - /// - /// Destructor - Close connection to Master Device. - /// - ~ ModbusClient() - { - if (debug) StoreLogData.Instance.Store("Destructor called - automatically disconnect", System.DateTime.Now); - if (serialport != null) - { - if (serialport.IsOpen) - serialport.Close(); - return; - } - if (tcpClient != null & !udpFlag) - { - if (stream !=null) - stream.Close(); - tcpClient.Close(); - } - } - - /// - /// Returns "TRUE" if Client is connected to Server and "FALSE" if not. In case of Modbus RTU returns if COM-Port is opened - /// - public bool Connected - { - get - { - if (serialport != null) - { - return (serialport.IsOpen); - } - - if (udpFlag & tcpClient != null) - return true; - if (tcpClient == null) - return false; - else - { - return connected; - - } - - } - } - - public bool Available(int timeout) - { - // Ping's the local machine. - System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping(); - IPAddress address = System.Net.IPAddress.Parse(ipAddress); - - // Create a buffer of 32 bytes of data to be transmitted. - string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data); - - // Wait 10 seconds for a reply. - System.Net.NetworkInformation.PingReply reply = pingSender.Send(address, timeout, buffer); - - if (reply.Status == System.Net.NetworkInformation.IPStatus.Success) - return true; - else - return false; - } - - /// - /// Gets or Sets the IP-Address of the Server. - /// - public string IPAddress - { - get - { - return ipAddress; - } - set - { - ipAddress = value; - } - } - - /// - /// Gets or Sets the Port were the Modbus-TCP Server is reachable (Standard is 502). - /// - public int Port - { - get - { - return port; - } - set - { - port = value; - } - } - - /// - /// Gets or Sets the UDP-Flag to activate Modbus UDP. - /// - public bool UDPFlag - { - get - { - return udpFlag; - } - set - { - udpFlag = value; - } - } - - /// - /// Gets or Sets the Unit identifier in case of serial connection (Default = 0) - /// - public byte UnitIdentifier - { - get - { - return unitIdentifier; - } - set - { - unitIdentifier = value; - } - } - - - /// - /// Gets or Sets the Baudrate for serial connection (Default = 9600) - /// - public int Baudrate - { - get - { - return baudRate; - } - set - { - baudRate = value; - } - } - - /// - /// Gets or Sets the of Parity in case of serial connection - /// - public Parity Parity - { - get - { - if (serialport != null) - return parity; - else - return Parity.Even; - } - set - { - if (serialport != null) - parity = value; - } - } - - - /// - /// Gets or Sets the number of stopbits in case of serial connection - /// - public StopBits StopBits - { - get - { - if (serialport != null) - return stopBits; - else - return StopBits.One; - } - set - { - if (serialport != null) - stopBits = value; - } - } - - /// - /// Gets or Sets the connection Timeout in case of ModbusTCP connection - /// - public int ConnectionTimeout - { - get - { - return connectTimeout; - } - set - { - connectTimeout = value; - } - } - - /// - /// Gets or Sets the serial Port - /// - public string SerialPort - { - get - { - - return serialport.PortName; - } - set - { - if (value == null) - { - serialport = null; - return; - } - if (serialport != null) - serialport.Close(); - this.serialport = new SerialPort(); - this.serialport.PortName = value; - serialport.BaudRate = baudRate; - serialport.Parity = parity; - serialport.StopBits = stopBits; - serialport.WriteTimeout = 10000; - serialport.ReadTimeout = connectTimeout; - serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); - } - } - - /// - /// Gets or Sets the Filename for the LogFile - /// - public string LogFileFilename - { - get - { - return StoreLogData.Instance.Filename; - } - set - { - StoreLogData.Instance.Filename = value; - if (StoreLogData.Instance.Filename != null) - debug = true; - else - debug = false; - } - } - - } -} diff --git a/EasyModbus_Net60/ModbusServer.cs b/EasyModbus_Net60/ModbusServer.cs deleted file mode 100644 index 13374cd..0000000 --- a/EasyModbus_Net60/ModbusServer.cs +++ /dev/null @@ -1,2266 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net.Sockets; -using System.Net; -using System.Threading; -using System.Net.NetworkInformation; -using System.IO.Ports; - -namespace EasyModbus -{ -#region class ModbusProtocol - /// - /// Modbus Protocol informations. - /// - public class ModbusProtocol - { - public enum ProtocolType { ModbusTCP = 0, ModbusUDP = 1, ModbusRTU = 2}; - public DateTime timeStamp; - public bool request; - public bool response; - public UInt16 transactionIdentifier; - public UInt16 protocolIdentifier; - public UInt16 length; - public byte unitIdentifier; - public byte functionCode; - public UInt16 startingAdress; - public UInt16 startingAddressRead; - public UInt16 startingAddressWrite; - public UInt16 quantity; - public UInt16 quantityRead; - public UInt16 quantityWrite; - public byte byteCount; - public byte exceptionCode; - public byte errorCode; - public UInt16[] receiveCoilValues; - public UInt16[] receiveRegisterValues; - public Int16[] sendRegisterValues; - public bool[] sendCoilValues; - public UInt16 crc; - } -#endregion - -#region structs - struct NetworkConnectionParameter - { - public NetworkStream stream; //For TCP-Connection only - public Byte[] bytes; - public int portIn; //For UDP-Connection only - public IPAddress ipAddressIn; //For UDP-Connection only - } -#endregion - -#region TCPHandler class - internal class TCPHandler - { - public delegate void DataChanged(object networkConnectionParameter); - public event DataChanged dataChanged; - - public delegate void NumberOfClientsChanged(); - public event NumberOfClientsChanged numberOfClientsChanged; - - TcpListener server = null; - - - private List tcpClientLastRequestList = new List(); - - public int NumberOfConnectedClients { get; set; } - - public string ipAddress = null; - - /// When making a server TCP listen socket, will listen to this IP address. - public IPAddress LocalIPAddress { - get { return localIPAddress; } - } - private IPAddress localIPAddress = IPAddress.Any; - - /// - /// Listen to all network interfaces. - /// - /// TCP port to listen - public TCPHandler(int port) - { - server = new TcpListener(LocalIPAddress, port); - server.Start(); - server.BeginAcceptTcpClient(AcceptTcpClientCallback, null); - } - - /// - /// Listen to a specific network interface. - /// - /// IP address of network interface to listen - /// TCP port to listen - public TCPHandler(IPAddress localIPAddress, int port) - { - this.localIPAddress = localIPAddress; - server = new TcpListener(LocalIPAddress, port); - server.Start(); - server.BeginAcceptTcpClient(AcceptTcpClientCallback, null); - } - - - private void AcceptTcpClientCallback(IAsyncResult asyncResult) - { - TcpClient tcpClient = new TcpClient(); - try - { - tcpClient = server.EndAcceptTcpClient(asyncResult); - tcpClient.ReceiveTimeout = 4000; - if (ipAddress != null) - { - string ipEndpoint = tcpClient.Client.RemoteEndPoint.ToString(); - ipEndpoint = ipEndpoint.Split(':')[0]; - if (ipEndpoint != ipAddress) - { - tcpClient.Client.Disconnect(false); - return; - } - } - } - catch (Exception) { } - try - { - server.BeginAcceptTcpClient(AcceptTcpClientCallback, null); - Client client = new Client(tcpClient); - NetworkStream networkStream = client.NetworkStream; - networkStream.ReadTimeout = 4000; - networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client); - } - catch (Exception) { } - } - - private int GetAndCleanNumberOfConnectedClients(Client client) - { - lock (this) - { - int i = 0; - bool objetExists = false; - foreach (Client clientLoop in tcpClientLastRequestList) - { - if (client.Equals(clientLoop)) - objetExists = true; - } - try - { - tcpClientLastRequestList.RemoveAll(delegate (Client c) - { - return ((DateTime.Now.Ticks - c.Ticks) > 40000000); - } - - ); - } - catch (Exception) { } - if (!objetExists) - tcpClientLastRequestList.Add(client); - - - return tcpClientLastRequestList.Count; - } - } - - private void ReadCallback(IAsyncResult asyncResult) - { - NetworkConnectionParameter networkConnectionParameter = new NetworkConnectionParameter(); - Client client = asyncResult.AsyncState as Client; - client.Ticks = DateTime.Now.Ticks; - NumberOfConnectedClients = GetAndCleanNumberOfConnectedClients(client); - if (numberOfClientsChanged != null) - numberOfClientsChanged(); - if (client != null) - { - int read; - NetworkStream networkStream = null; - try - { - networkStream = client.NetworkStream; - - read = networkStream.EndRead(asyncResult); - } - catch (Exception ex) - { - return; - } - - - if (read == 0) - { - //OnClientDisconnected(client.TcpClient); - //connectedClients.Remove(client); - return; - } - byte[] data = new byte[read]; - Buffer.BlockCopy(client.Buffer, 0, data, 0, read); - networkConnectionParameter.bytes = data; - networkConnectionParameter.stream = networkStream; - if (dataChanged != null) - dataChanged(networkConnectionParameter); - try - { - networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client); - } - catch (Exception) - { - } - } - } - - public void Disconnect() - { - try - { - foreach (Client clientLoop in tcpClientLastRequestList) - { - clientLoop.NetworkStream.Close(00); - } - } - catch (Exception) { } - server.Stop(); - - } - - - internal class Client - { - private readonly TcpClient tcpClient; - private readonly byte[] buffer; - public long Ticks { get; set; } - - public Client(TcpClient tcpClient) - { - this.tcpClient = tcpClient; - int bufferSize = tcpClient.ReceiveBufferSize; - buffer = new byte[bufferSize]; - } - - public TcpClient TcpClient - { - get { return tcpClient; } - } - - public byte[] Buffer - { - get { return buffer; } - } - - public NetworkStream NetworkStream - { - get { - - return tcpClient.GetStream(); - - } - } - } - } -#endregion - - /// - /// Modbus TCP Server. - /// - public class ModbusServer - { - private bool debug = false; - Int32 port = 502; - ModbusProtocol receiveData; - ModbusProtocol sendData = new ModbusProtocol(); - Byte[] bytes = new Byte[2100]; - //public Int16[] _holdingRegisters = new Int16[65535]; - public HoldingRegisters holdingRegisters; - public InputRegisters inputRegisters; - public Coils coils; - public DiscreteInputs discreteInputs; - private int numberOfConnections = 0; - private bool udpFlag; - private bool serialFlag; - private int baudrate = 9600; - private System.IO.Ports.Parity parity = Parity.Even; - private System.IO.Ports.StopBits stopBits = StopBits.One; - private string serialPort = "COM1"; - private SerialPort serialport; - private byte unitIdentifier = 1; - private int portIn; - private IPAddress ipAddressIn; - private UdpClient udpClient; - private IPEndPoint iPEndPoint; - private TCPHandler tcpHandler; - Thread listenerThread; - Thread clientConnectionThread; - private ModbusProtocol[] modbusLogData = new ModbusProtocol[100]; - public bool FunctionCode1Disabled {get; set;} - public bool FunctionCode2Disabled { get; set; } - public bool FunctionCode3Disabled { get; set; } - public bool FunctionCode4Disabled { get; set; } - public bool FunctionCode5Disabled { get; set; } - public bool FunctionCode6Disabled { get; set; } - public bool FunctionCode15Disabled { get; set; } - public bool FunctionCode16Disabled { get; set; } - public bool FunctionCode23Disabled { get; set; } - public bool PortChanged { get; set; } - object lockCoils = new object(); - object lockHoldingRegisters = new object(); - private volatile bool shouldStop; - - private IPAddress localIPAddress = IPAddress.Any; - - /// - /// When creating a TCP or UDP socket, the local IP address to attach to. - /// - public IPAddress LocalIPAddress - { - get { return localIPAddress; } - set { if (listenerThread == null) localIPAddress = value; } - } - - public ModbusServer() - { - holdingRegisters = new HoldingRegisters(this); - inputRegisters = new InputRegisters(this); - coils = new Coils(this); - discreteInputs = new DiscreteInputs(this); - - } - - #region events - public delegate void CoilsChangedHandler(int coil, int numberOfCoils); - public event CoilsChangedHandler CoilsChanged; - - public delegate void HoldingRegistersChangedHandler(int register, int numberOfRegisters); - public event HoldingRegistersChangedHandler HoldingRegistersChanged; - - public delegate void NumberOfConnectedClientsChangedHandler(); - public event NumberOfConnectedClientsChangedHandler NumberOfConnectedClientsChanged; - - public delegate void LogDataChangedHandler(); - public event LogDataChangedHandler LogDataChanged; - #endregion - - public void Listen() - { - - listenerThread = new Thread(ListenerThread); - listenerThread.Start(); - } - - public void StopListening() - { - if (SerialFlag & (serialport != null)) - { - if (serialport.IsOpen) - serialport.Close(); - shouldStop = true; - } - try - { - tcpHandler.Disconnect(); - listenerThread.Abort(); - - } - catch (Exception) { } - listenerThread.Join(); - try - { - - clientConnectionThread.Abort(); - } - catch (Exception) { } - } - - private void ListenerThread() - { - if (!udpFlag & !serialFlag) - { - if (udpClient != null) - { - try - { - udpClient.Close(); - } - catch (Exception) { } - } - tcpHandler = new TCPHandler(LocalIPAddress, port); - if (debug) StoreLogData.Instance.Store($"EasyModbus Server listing for incomming data at Port {port}, local IP {LocalIPAddress}", System.DateTime.Now); - tcpHandler.dataChanged += new TCPHandler.DataChanged(ProcessReceivedData); - tcpHandler.numberOfClientsChanged += new TCPHandler.NumberOfClientsChanged(numberOfClientsChanged); - } - else if (serialFlag) - { - if (serialport == null) - { - if (debug) StoreLogData.Instance.Store("EasyModbus RTU-Server listing for incomming data at Serial Port " + serialPort, System.DateTime.Now); - serialport = new SerialPort(); - serialport.PortName = serialPort; - serialport.BaudRate = this.baudrate; - serialport.Parity = this.parity; - serialport.StopBits = stopBits; - serialport.WriteTimeout = 10000; - serialport.ReadTimeout = 1000; - serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); - serialport.Open(); - } - } - else - while (!shouldStop) - { - if (udpFlag) - { - if (udpClient == null | PortChanged) - { - IPEndPoint localEndoint = new IPEndPoint(LocalIPAddress, port); - udpClient = new UdpClient(localEndoint); - if (debug) StoreLogData.Instance.Store($"EasyModbus Server listing for incomming data at Port {port}, local IP {LocalIPAddress}", System.DateTime.Now); - udpClient.Client.ReceiveTimeout = 1000; - iPEndPoint = new IPEndPoint(IPAddress.Any, port); - PortChanged = false; - } - if (tcpHandler != null) - tcpHandler.Disconnect(); - try - { - bytes = udpClient.Receive(ref iPEndPoint); - portIn = iPEndPoint.Port; - NetworkConnectionParameter networkConnectionParameter = new NetworkConnectionParameter(); - networkConnectionParameter.bytes = bytes; - ipAddressIn = iPEndPoint.Address; - networkConnectionParameter.portIn = portIn; - networkConnectionParameter.ipAddressIn = ipAddressIn; - ParameterizedThreadStart pts = new ParameterizedThreadStart(this.ProcessReceivedData); - Thread processDataThread = new Thread(pts); - processDataThread.Start(networkConnectionParameter); - } - catch (Exception) - { - } - } - - } - } - - #region SerialHandler - private bool dataReceived = false; - private byte[] readBuffer = new byte[2094]; - private DateTime lastReceive; - private int nextSign = 0; - private void DataReceivedHandler(object sender, - SerialDataReceivedEventArgs e) - { - int silence = 4000 / baudrate; - if ((DateTime.Now.Ticks - lastReceive.Ticks) > TimeSpan.TicksPerMillisecond*silence) - nextSign = 0; - - - SerialPort sp = (SerialPort)sender; - - int numbytes = sp.BytesToRead; - byte[] rxbytearray = new byte[numbytes]; - - sp.Read(rxbytearray, 0, numbytes); - - Array.Copy(rxbytearray, 0, readBuffer, nextSign, rxbytearray.Length); - lastReceive= DateTime.Now; - nextSign = numbytes+ nextSign; - if (ModbusClient.DetectValidModbusFrame(readBuffer, nextSign)) - { - - dataReceived = true; - nextSign= 0; - - NetworkConnectionParameter networkConnectionParameter = new NetworkConnectionParameter(); - networkConnectionParameter.bytes = readBuffer; - ParameterizedThreadStart pts = new ParameterizedThreadStart(this.ProcessReceivedData); - Thread processDataThread = new Thread(pts); - processDataThread.Start(networkConnectionParameter); - dataReceived = false; - - } - else - dataReceived = false; - } - #endregion - - #region Method numberOfClientsChanged - private void numberOfClientsChanged() - { - numberOfConnections = tcpHandler.NumberOfConnectedClients; - if (NumberOfConnectedClientsChanged != null) - NumberOfConnectedClientsChanged(); - } - #endregion - - object lockProcessReceivedData = new object(); - #region Method ProcessReceivedData - private void ProcessReceivedData(object networkConnectionParameter) - { - lock (lockProcessReceivedData) - { - Byte[] bytes = new byte[((NetworkConnectionParameter)networkConnectionParameter).bytes.Length]; - if (debug) StoreLogData.Instance.Store("Received Data: " + BitConverter.ToString(bytes), System.DateTime.Now); - NetworkStream stream = ((NetworkConnectionParameter)networkConnectionParameter).stream; - int portIn = ((NetworkConnectionParameter)networkConnectionParameter).portIn; - IPAddress ipAddressIn = ((NetworkConnectionParameter)networkConnectionParameter).ipAddressIn; - - - Array.Copy(((NetworkConnectionParameter)networkConnectionParameter).bytes, 0, bytes, 0, ((NetworkConnectionParameter)networkConnectionParameter).bytes.Length); - - ModbusProtocol receiveDataThread = new ModbusProtocol(); - ModbusProtocol sendDataThread = new ModbusProtocol(); - - try - { - UInt16[] wordData = new UInt16[1]; - byte[] byteData = new byte[2]; - receiveDataThread.timeStamp = DateTime.Now; - receiveDataThread.request = true; - if (!serialFlag) - { - //Lese Transaction identifier - byteData[1] = bytes[0]; - byteData[0] = bytes[1]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.transactionIdentifier = wordData[0]; - - //Lese Protocol identifier - byteData[1] = bytes[2]; - byteData[0] = bytes[3]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.protocolIdentifier = wordData[0]; - - //Lese length - byteData[1] = bytes[4]; - byteData[0] = bytes[5]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.length = wordData[0]; - } - - //Lese unit identifier - receiveDataThread.unitIdentifier = bytes[6 - 6 * Convert.ToInt32(serialFlag)]; - //Check UnitIdentifier - if ((receiveDataThread.unitIdentifier != this.unitIdentifier) & (receiveDataThread.unitIdentifier != 0)) - return; - - // Lese function code - receiveDataThread.functionCode = bytes[7 - 6 * Convert.ToInt32(serialFlag)]; - - // Lese starting address - byteData[1] = bytes[8 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[9 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.startingAdress = wordData[0]; - - if (receiveDataThread.functionCode <= 4) - { - // Lese quantity - byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.quantity = wordData[0]; - } - if (receiveDataThread.functionCode == 5) - { - receiveDataThread.receiveCoilValues = new ushort[1]; - // Lese Value - byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveCoilValues, 0, 2); - } - if (receiveDataThread.functionCode == 6) - { - receiveDataThread.receiveRegisterValues = new ushort[1]; - // Lese Value - byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveRegisterValues, 0, 2); - } - if (receiveDataThread.functionCode == 15) - { - // Lese quantity - byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.quantity = wordData[0]; - - receiveDataThread.byteCount = bytes[12 - 6 * Convert.ToInt32(serialFlag)]; - - if ((receiveDataThread.byteCount % 2) != 0) - receiveDataThread.receiveCoilValues = new ushort[receiveDataThread.byteCount / 2 + 1]; - else - receiveDataThread.receiveCoilValues = new ushort[receiveDataThread.byteCount / 2]; - // Lese Value - Buffer.BlockCopy(bytes, 13 - 6 * Convert.ToInt32(serialFlag), receiveDataThread.receiveCoilValues, 0, receiveDataThread.byteCount); - } - if (receiveDataThread.functionCode == 16) - { - // Lese quantity - byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.quantity = wordData[0]; - - receiveDataThread.byteCount = bytes[12 - 6 * Convert.ToInt32(serialFlag)]; - receiveDataThread.receiveRegisterValues = new ushort[receiveDataThread.quantity]; - for (int i = 0; i < receiveDataThread.quantity; i++) - { - // Lese Value - byteData[1] = bytes[13 + i * 2 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[14 + i * 2 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveRegisterValues, i * 2, 2); - } - - } - if (receiveDataThread.functionCode == 23) - { - // Lese starting Address Read - byteData[1] = bytes[8 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[9 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.startingAddressRead = wordData[0]; - // Lese quantity Read - byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.quantityRead = wordData[0]; - // Lese starting Address Write - byteData[1] = bytes[12 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[13 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.startingAddressWrite = wordData[0]; - // Lese quantity Write - byteData[1] = bytes[14 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[15 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, wordData, 0, 2); - receiveDataThread.quantityWrite = wordData[0]; - - receiveDataThread.byteCount = bytes[16 - 6 * Convert.ToInt32(serialFlag)]; - receiveDataThread.receiveRegisterValues = new ushort[receiveDataThread.quantityWrite]; - for (int i = 0; i < receiveDataThread.quantityWrite; i++) - { - // Lese Value - byteData[1] = bytes[17 + i * 2 - 6 * Convert.ToInt32(serialFlag)]; - byteData[0] = bytes[18 + i * 2 - 6 * Convert.ToInt32(serialFlag)]; - Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveRegisterValues, i * 2, 2); - } - } - } - catch (Exception exc) - { } - this.CreateAnswer(receiveDataThread, sendDataThread, stream, portIn, ipAddressIn); - //this.sendAnswer(); - this.CreateLogData(receiveDataThread, sendDataThread); - - if (LogDataChanged != null) - LogDataChanged(); - } - } - #endregion - - #region Method CreateAnswer - private void CreateAnswer(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - - switch (receiveData.functionCode) - { - // Read Coils - case 1: - if (!FunctionCode1Disabled) - this.ReadCoils(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - break; - // Read Input Registers - case 2: - if (!FunctionCode2Disabled) - this.ReadDiscreteInputs(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Read Holding Registers - case 3: - if (!FunctionCode3Disabled) - this.ReadHoldingRegisters(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Read Input Registers - case 4: - if (!FunctionCode4Disabled) - this.ReadInputRegisters(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Write single coil - case 5: - if (!FunctionCode5Disabled) - this.WriteSingleCoil(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Write single register - case 6: - if (!FunctionCode6Disabled) - this.WriteSingleRegister(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Write Multiple coils - case 15: - if (!FunctionCode15Disabled) - this.WriteMultipleCoils(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Write Multiple registers - case 16: - if (!FunctionCode16Disabled) - this.WriteMultipleRegisters(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Error: Function Code not supported - case 23: - if (!FunctionCode23Disabled) - this.ReadWriteMultipleRegisters(receiveData, sendData, stream, portIn, ipAddressIn); - else - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - } - - break; - // Error: Function Code not supported - default: sendData.errorCode = (byte) (receiveData.functionCode + 0x80); - sendData.exceptionCode = 1; - sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn); - break; - } - sendData.timeStamp = DateTime.Now; - } - #endregion - - private void ReadCoils(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - if ((receiveData.quantity < 1) | (receiveData.quantity > 0x07D0)) //Invalid quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - if ((receiveData.quantity % 8) == 0) - sendData.byteCount = (byte)(receiveData.quantity / 8); - else - sendData.byteCount = (byte)(receiveData.quantity / 8 + 1); - - sendData.sendCoilValues = new bool[receiveData.quantity]; - lock (lockCoils) - Array.Copy(coils.localArray, receiveData.startingAdress + 1, sendData.sendCoilValues, 0, receiveData.quantity); - } - if (true) - { - Byte[] data; - - if (sendData.exceptionCode > 0) - data = new byte[9 + 2*Convert.ToInt32(serialFlag)]; - else - data = new byte[9 + sendData.byteCount+ 2*Convert.ToInt32(serialFlag)]; - - Byte[] byteData = new byte[2]; - - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - //ByteCount - data[8] = sendData.byteCount; - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendCoilValues = null; - } - - if (sendData.sendCoilValues != null) - for (int i = 0; i < (sendData.byteCount); i++) - { - byteData = new byte[2]; - for (int j = 0; j < 8; j++) - { - - byte boolValue; - if (sendData.sendCoilValues[i * 8 + j] == true) - boolValue = 1; - else - boolValue = 0; - byteData[1] = (byte)((byteData[1]) | (boolValue << j)); - if ((i * 8 + j + 1) >= sendData.sendCoilValues.Length) - break; - } - data[9 + i] = byteData[1]; - } - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - } - } - - private void ReadDiscreteInputs(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - if ((receiveData.quantity < 1) | (receiveData.quantity > 0x07D0)) //Invalid quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - if ((receiveData.quantity % 8) == 0) - sendData.byteCount = (byte)(receiveData.quantity / 8); - else - sendData.byteCount = (byte)(receiveData.quantity / 8 + 1); - - sendData.sendCoilValues = new bool[receiveData.quantity]; - Array.Copy(discreteInputs.localArray, receiveData.startingAdress + 1, sendData.sendCoilValues, 0, receiveData.quantity); - } - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)]; - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - //ByteCount - data[8] = sendData.byteCount; - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendCoilValues = null; - } - - if (sendData.sendCoilValues != null) - for (int i = 0; i < (sendData.byteCount); i++) - { - byteData = new byte[2]; - for (int j = 0; j < 8; j++) - { - - byte boolValue; - if (sendData.sendCoilValues[i * 8 + j] == true) - boolValue = 1; - else - boolValue = 0; - byteData[1] = (byte)((byteData[1]) | (boolValue << j)); - if ((i * 8 + j + 1) >= sendData.sendCoilValues.Length) - break; - } - data[9 + i] = byteData[1]; - } - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if(debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - } - } - - private void ReadHoldingRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - if ((receiveData.quantity < 1) | (receiveData.quantity > 0x007D)) //Invalid quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - sendData.byteCount = (byte)(2 * receiveData.quantity); - sendData.sendRegisterValues = new Int16[receiveData.quantity]; - lock (lockHoldingRegisters) - Buffer.BlockCopy(holdingRegisters.localArray, receiveData.startingAdress * 2 + 2, sendData.sendRegisterValues, 0, receiveData.quantity * 2); - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = (ushort)(0x03 + sendData.byteCount); - - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)]; - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - //ByteCount - data[8] = sendData.byteCount; - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - - - if (sendData.sendRegisterValues != null) - for (int i = 0; i < (sendData.byteCount / 2); i++) - { - byteData = BitConverter.GetBytes((Int16)sendData.sendRegisterValues[i]); - data[9 + i * 2] = byteData[1]; - data[10 + i * 2] = byteData[0]; - } - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - } - } - - private void ReadInputRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - if ((receiveData.quantity < 1) | (receiveData.quantity > 0x007D)) //Invalid quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - sendData.byteCount = (byte)(2 * receiveData.quantity); - sendData.sendRegisterValues = new Int16[receiveData.quantity]; - Buffer.BlockCopy(inputRegisters.localArray, receiveData.startingAdress * 2 + 2, sendData.sendRegisterValues, 0, receiveData.quantity * 2); - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = (ushort)(0x03 + sendData.byteCount); - - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)]; - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - //ByteCount - data[8] = sendData.byteCount; - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - - - if (sendData.sendRegisterValues != null) - for (int i = 0; i < (sendData.byteCount / 2); i++) - { - byteData = BitConverter.GetBytes((Int16)sendData.sendRegisterValues[i]); - data[9 + i * 2] = byteData[1]; - data[10 + i * 2] = byteData[0]; - } - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - } - } - - private void WriteSingleCoil(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - sendData.startingAdress = receiveData.startingAdress; - sendData.receiveCoilValues = receiveData.receiveCoilValues; - if ((receiveData.receiveCoilValues[0] != 0x0000) & (receiveData.receiveCoilValues[0] != 0xFF00)) //Invalid Value - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if (((receiveData.startingAdress + 1) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - if (receiveData.receiveCoilValues[0] == 0xFF00) - { - lock (lockCoils) - coils[receiveData.startingAdress + 1] = true; - } - if (receiveData.receiveCoilValues[0] == 0x0000) - { - lock (lockCoils) - coils[receiveData.startingAdress + 1] = false; - } - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = 0x06; - - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[12 + 2 * Convert.ToInt32(serialFlag)]; - - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - else - { - byteData = BitConverter.GetBytes((int)receiveData.startingAdress); - data[8] = byteData[1]; - data[9] = byteData[0]; - byteData = BitConverter.GetBytes((int)receiveData.receiveCoilValues[0]); - data[10] = byteData[1]; - data[11] = byteData[0]; - } - - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - if (CoilsChanged != null) - CoilsChanged(receiveData.startingAdress+1, 1); - } - } - - private void WriteSingleRegister(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - sendData.startingAdress = receiveData.startingAdress; - sendData.receiveRegisterValues = receiveData.receiveRegisterValues; - - if ((receiveData.receiveRegisterValues[0] < 0x0000) | (receiveData.receiveRegisterValues[0] > 0xFFFF)) //Invalid Value - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if (((receiveData.startingAdress + 1) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - lock (lockHoldingRegisters) - holdingRegisters[receiveData.startingAdress + 1] = unchecked((short)receiveData.receiveRegisterValues[0]); - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = 0x06; - - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[12 + 2 * Convert.ToInt32(serialFlag)]; - - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - else - { - byteData = BitConverter.GetBytes((int)receiveData.startingAdress); - data[8] = byteData[1]; - data[9] = byteData[0]; - byteData = BitConverter.GetBytes((int)receiveData.receiveRegisterValues[0]); - data[10] = byteData[1]; - data[11] = byteData[0]; - } - - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - if (HoldingRegistersChanged != null) - HoldingRegistersChanged(receiveData.startingAdress+1, 1); - } - } - - private void WriteMultipleCoils(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - sendData.startingAdress = receiveData.startingAdress; - sendData.quantity = receiveData.quantity; - - if ((receiveData.quantity == 0x0000) | (receiveData.quantity > 0x07B0)) //Invalid Quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if ((((int)receiveData.startingAdress + 1 + (int)receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - lock (lockCoils) - for (int i = 0; i < receiveData.quantity; i++) - { - int shift = i % 16; - /* if ((i == receiveData.quantity - 1) & (receiveData.quantity % 2 != 0)) - { - if (shift < 8) - shift = shift + 8; - else - shift = shift - 8; - }*/ - int mask = 0x1; - mask = mask << (shift); - if ((receiveData.receiveCoilValues[i / 16] & (ushort)mask) == 0) - - coils[receiveData.startingAdress + i + 1] = false; - else - - coils[receiveData.startingAdress + i + 1] = true; - - } - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = 0x06; - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[12 + 2 * Convert.ToInt32(serialFlag)]; - - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - else - { - byteData = BitConverter.GetBytes((int)receiveData.startingAdress); - data[8] = byteData[1]; - data[9] = byteData[0]; - byteData = BitConverter.GetBytes((int)receiveData.quantity); - data[10] = byteData[1]; - data[11] = byteData[0]; - } - - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - if (CoilsChanged != null) - CoilsChanged(receiveData.startingAdress+1, receiveData.quantity); - } - } - - private void WriteMultipleRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - sendData.startingAdress = receiveData.startingAdress; - sendData.quantity = receiveData.quantity; - - if ((receiveData.quantity == 0x0000) | (receiveData.quantity > 0x07B0)) //Invalid Quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if ((((int)receiveData.startingAdress + 1 + (int)receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - lock (lockHoldingRegisters) - for (int i = 0; i < receiveData.quantity; i++) - { - holdingRegisters[receiveData.startingAdress + i + 1] = unchecked((short)receiveData.receiveRegisterValues[i]); - } - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = 0x06; - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[12 + 2 * Convert.ToInt32(serialFlag)]; - - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - else - { - byteData = BitConverter.GetBytes((int)receiveData.startingAdress); - data[8] = byteData[1]; - data[9] = byteData[0]; - byteData = BitConverter.GetBytes((int)receiveData.quantity); - data[10] = byteData[1]; - data[11] = byteData[0]; - } - - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - if (HoldingRegistersChanged != null) - HoldingRegistersChanged(receiveData.startingAdress+1, receiveData.quantity); - } - } - - private void ReadWriteMultipleRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = this.unitIdentifier; - sendData.functionCode = receiveData.functionCode; - - - if ((receiveData.quantityRead < 0x0001) | (receiveData.quantityRead > 0x007D) | (receiveData.quantityWrite < 0x0001) | (receiveData.quantityWrite > 0x0079) | (receiveData.byteCount != (receiveData.quantityWrite * 2))) //Invalid Quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 3; - } - if ((((int)receiveData.startingAddressRead + 1 + (int)receiveData.quantityRead) > 65535) | (((int)receiveData.startingAddressWrite + 1 + (int)receiveData.quantityWrite) > 65535) | (receiveData.quantityWrite < 0) | (receiveData.quantityRead < 0)) //Invalid Starting adress or Starting address + quantity - { - sendData.errorCode = (byte)(receiveData.functionCode + 0x80); - sendData.exceptionCode = 2; - } - if (sendData.exceptionCode == 0) - { - sendData.sendRegisterValues = new Int16[receiveData.quantityRead]; - lock (lockHoldingRegisters) - Buffer.BlockCopy(holdingRegisters.localArray, receiveData.startingAddressRead * 2 + 2, sendData.sendRegisterValues, 0, receiveData.quantityRead * 2); - - lock (holdingRegisters) - for (int i = 0; i < receiveData.quantityWrite; i++) - { - holdingRegisters[receiveData.startingAddressWrite + i + 1] = unchecked((short)receiveData.receiveRegisterValues[i]); - } - sendData.byteCount = (byte)(2 * receiveData.quantityRead); - } - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = Convert.ToUInt16(3 + 2 * receiveData.quantityRead); - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)]; - - Byte[] byteData = new byte[2]; - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - //Function Code - data[7] = sendData.functionCode; - - //ByteCount - data[8] = sendData.byteCount; - - - if (sendData.exceptionCode > 0) - { - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - sendData.sendRegisterValues = null; - } - else - { - if (sendData.sendRegisterValues != null) - for (int i = 0; i < (sendData.byteCount / 2); i++) - { - byteData = BitConverter.GetBytes((Int16)sendData.sendRegisterValues[i]); - data[9 + i * 2] = byteData[1]; - data[10 + i * 2] = byteData[0]; - } - - } - - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - if (HoldingRegistersChanged != null) - HoldingRegistersChanged(receiveData.startingAddressWrite+1, receiveData.quantityWrite); - } - } - - private void sendException(int errorCode, int exceptionCode, ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn) - { - sendData.response = true; - - sendData.transactionIdentifier = receiveData.transactionIdentifier; - sendData.protocolIdentifier = receiveData.protocolIdentifier; - - sendData.unitIdentifier = receiveData.unitIdentifier; - sendData.errorCode = (byte)errorCode; - sendData.exceptionCode = (byte)exceptionCode; - - if (sendData.exceptionCode > 0) - sendData.length = 0x03; - else - sendData.length = (ushort)(0x03 + sendData.byteCount); - - if (true) - { - Byte[] data; - if (sendData.exceptionCode > 0) - data = new byte[9 + 2 * Convert.ToInt32(serialFlag)]; - else - data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)]; - Byte[] byteData = new byte[2]; - sendData.length = (byte)(data.Length - 6); - - //Send Transaction identifier - byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier); - data[0] = byteData[1]; - data[1] = byteData[0]; - - //Send Protocol identifier - byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier); - data[2] = byteData[1]; - data[3] = byteData[0]; - - //Send length - byteData = BitConverter.GetBytes((int)sendData.length); - data[4] = byteData[1]; - data[5] = byteData[0]; - - //Unit Identifier - data[6] = sendData.unitIdentifier; - - - data[7] = sendData.errorCode; - data[8] = sendData.exceptionCode; - - - try - { - if (serialFlag) - { - if (!serialport.IsOpen) - throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened"); - //Create CRC - sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6); - byteData = BitConverter.GetBytes((int)sendData.crc); - data[data.Length - 2] = byteData[0]; - data[data.Length - 1] = byteData[1]; - serialport.Write(data, 6, data.Length - 6); - if (debug) - { - byte[] debugData = new byte[data.Length - 6]; - Array.Copy(data, 6, debugData, 0, data.Length - 6); - if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now); - } - } - else if (udpFlag) - { - //UdpClient udpClient = new UdpClient(); - IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn); - udpClient.Send(data, data.Length, endPoint); - - } - else - { - stream.Write(data, 0, data.Length); - if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now); - } - } - catch (Exception) { } - } - } - - private void CreateLogData(ModbusProtocol receiveData, ModbusProtocol sendData) - { - for (int i = 0; i < 98; i++) - { - modbusLogData[99 - i] = modbusLogData[99 - i - 2]; - - } - modbusLogData[0] = receiveData; - modbusLogData[1] = sendData; - - } - - - - public int NumberOfConnections - { - get - { - return numberOfConnections; - } - } - - public ModbusProtocol[] ModbusLogData - { - get - { - return modbusLogData; - } - } - - public int Port - { - get - { - return port; - } - set - { - port = value; - - - } - } - - public bool UDPFlag - { - get - { - return udpFlag; - } - set - { - udpFlag = value; - } - } - - public bool SerialFlag - { - get - { - return serialFlag; - } - set - { - serialFlag = value; - } - } - - public int Baudrate - { - get - { - return baudrate; - } - set - { - baudrate = value; - } - } - - public System.IO.Ports.Parity Parity - { - get - { - return parity; - } - set - { - parity = value; - } - } - - public System.IO.Ports.StopBits StopBits - { - get - { - return stopBits; - } - set - { - stopBits = value; - } - } - - public string SerialPort - { - get - { - return serialPort; - } - set - { - serialPort = value; - if (serialPort != null) - serialFlag = true; - else - serialFlag = false; - } - } - - public byte UnitIdentifier - { - get - { - return unitIdentifier; - } - set - { - unitIdentifier = value; - } - } - - - - - /// - /// Gets or Sets the Filename for the LogFile - /// - public string LogFileFilename - { - get - { - return StoreLogData.Instance.Filename; - } - set - { - StoreLogData.Instance.Filename = value; - if (StoreLogData.Instance.Filename != null) - debug = true; - else - debug = false; - } - } - - - - - public class HoldingRegisters - { - public Int16[] localArray = new Int16[65535]; - ModbusServer modbusServer; - - public HoldingRegisters(EasyModbus.ModbusServer modbusServer) - { - this.modbusServer = modbusServer; - } - - public Int16 this[int x] - { - get { return this.localArray[x]; } - set - { - this.localArray[x] = value; - - } - } - } - - public class InputRegisters - { - public Int16[] localArray = new Int16[65535]; - ModbusServer modbusServer; - - public InputRegisters(EasyModbus.ModbusServer modbusServer) - { - this.modbusServer = modbusServer; - } - - public Int16 this[int x] - { - get { return this.localArray[x]; } - set - { - this.localArray[x] = value; - - } - } - } - - public class Coils - { - public bool[] localArray = new bool[65535]; - ModbusServer modbusServer; - - public Coils(EasyModbus.ModbusServer modbusServer) - { - this.modbusServer = modbusServer; - } - - public bool this[int x] - { - get { return this.localArray[x]; } - set - { - this.localArray[x] = value; - - } - } - } - - public class DiscreteInputs - { - public bool[] localArray = new bool[65535]; - ModbusServer modbusServer; - - public DiscreteInputs(EasyModbus.ModbusServer modbusServer) - { - this.modbusServer = modbusServer; - } - - public bool this[int x] - { - get { return this.localArray[x]; } - set - { - this.localArray[x] = value; - - } - } - - - } - } -} - \ No newline at end of file diff --git a/EasyModbus_Net60/StoreLogData.cs b/EasyModbus_Net60/StoreLogData.cs deleted file mode 100644 index 3345038..0000000 --- a/EasyModbus_Net60/StoreLogData.cs +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright (c) 2018-2020 Rossmann-Engineering -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software -and associated documentation files (the "Software"), -to deal in the Software without restriction, -including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission -notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace EasyModbus -{ - /// - /// Store Log-Data in a File - /// - public sealed class StoreLogData - { - private String filename = null; - private static volatile StoreLogData instance; - private static object syncObject = new Object(); - - /// - /// Private constructor; Ensures the access of the class only via "instance" - /// - private StoreLogData() - { - } - - /// - /// Returns the instance of the class (singleton) - /// - /// instance (Singleton) - public static StoreLogData Instance - { - get - { - if (instance == null) - { - lock (syncObject) - { - if (instance == null) - instance = new StoreLogData(); - } - } - - return instance; - } - } - - /// - /// Store message in Log-File - /// - /// Message to append to the Log-File - public void Store(String message) - { - if (this.filename == null) - return; - - using (System.IO.StreamWriter file = - new System.IO.StreamWriter(Filename, true)) - { - file.WriteLine(message); - } - } - - /// - /// Store message in Log-File including Timestamp - /// - /// Message to append to the Log-File - /// Timestamp to add to the same Row - public void Store(String message, DateTime timestamp) - { - try - { - using (System.IO.StreamWriter file = - new System.IO.StreamWriter(Filename, true)) - { - file.WriteLine(timestamp.ToString("dd.MM.yyyy H:mm:ss.ff ") + message); - } - } - catch (Exception e) - { - - } - } - - /// - /// Gets or Sets the Filename to Store Strings in a File - /// - public string Filename - { - get - { - return filename; - } - set - { - filename = value; - } - } - } -}