├── .gitignore ├── NModbus ├── NModbus.build ├── NModbus.shfbproj ├── NModbusPublic.snk ├── README.txt ├── lib │ ├── FTD2XX.dll │ ├── Unme │ │ ├── Unme.Common.XML │ │ ├── Unme.Common.dll │ │ └── Unme.MbUnit.Framework.Extensions.dll │ └── log4net │ │ └── log4net.dll ├── src │ ├── FtdAdapter │ │ ├── FtdAdapter.csproj │ │ ├── FtdDeviceInfo.cs │ │ ├── FtdEnums.cs │ │ ├── FtdUsbPort.cs │ │ ├── NativeMethods.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Modbus.Extensions │ │ ├── EnronModbus.cs │ │ ├── Modbus.Extensions.csproj │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ ├── Modbus.IntegrationTests │ │ ├── App.config │ │ ├── CustomMessages │ │ │ ├── CustomReadHoldingRegistersRequest.cs │ │ │ ├── CustomReadHoldingRegistersResponse.cs │ │ │ ├── CustomWriteMultipleRegistersRequest.cs │ │ │ └── CustomWriteMultipleRegistersResponse.cs │ │ ├── EnronFixture.cs │ │ ├── FtdUsbPortAdapterFixture.cs │ │ ├── Modbus.IntegrationTests.csproj │ │ ├── ModbusMasterFixture.cs │ │ ├── ModbusSerialMasterFixture.cs │ │ ├── NModbusSerialAsciiMasterFixture.cs │ │ ├── NModbusSerialAsciiMasterJamodSerialAsciiSlaveFixture.cs │ │ ├── NModbusSerialAsciiMasterNModbusSerialAsciiSlaveFixture.cs │ │ ├── NModbusSerialRtuMasterDl06SlaveFixture.cs │ │ ├── NModbusSerialRtuMasterFixture.cs │ │ ├── NModbusSerialRtuMasterNModbusSerialRtuSlaveFixture.cs │ │ ├── NModbusSerialRtuSlaveFixture.cs │ │ ├── NModbusTcpMasterJamodTcpSlaveFixture.cs │ │ ├── NModbusTcpMasterNModbusTcpSlaveFixture.cs │ │ ├── NModbusTcpSlaveFixture.cs │ │ ├── NModbusUdpMasterNModbusUdpSlaveFixture.cs │ │ ├── NModbusUdpSlaveFixture.cs │ │ ├── NModbusUsbAsciiMasterFixture.cs │ │ ├── NModbusUsbAsciiNModbusSerialAsciiFixture.cs │ │ ├── NModbusUsbRtuMasterFixture.cs │ │ ├── NModbusUsbRtuMasterNModbusSerialRtuSlaveFixture.cs │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ ├── Modbus.UnitTests │ │ ├── Data │ │ │ ├── DataStoreEventArgsFixture.cs │ │ │ ├── DataStoreFixture.cs │ │ │ ├── DiscreteCollectionFixture.cs │ │ │ ├── ModbusDataCollectionFixture.cs │ │ │ └── RegisterCollectionFixture.cs │ │ ├── Device │ │ │ ├── ModbusMasterFixture.cs │ │ │ ├── ModbusSerialMasterFixture.cs │ │ │ ├── ModbusSlaveFixture.cs │ │ │ └── TcpConnectionEventArgsFixture.cs │ │ ├── IO │ │ │ ├── AbstractStreamResourceFixture.cs │ │ │ ├── ModbusAsciiTransportFixture.cs │ │ │ ├── ModbusRtuTransportFixture.cs │ │ │ ├── ModbusSerialTransportFixture.cs │ │ │ ├── ModbusTcpTransportFixture.cs │ │ │ ├── ModbusTransportFixture.cs │ │ │ └── UdpClientAdapterFixture.cs │ │ ├── Message │ │ │ ├── DiagnosticsRequestResponseFixture.cs │ │ │ ├── MessageUtility.cs │ │ │ ├── ModbusMessageFactoryFixture.cs │ │ │ ├── ModbusMessageFixture.cs │ │ │ ├── ModbusMessageImplFixture.cs │ │ │ ├── ModbusMessageWithDataFixture.cs │ │ │ ├── ReadCoilsInputsRequestFixture.cs │ │ │ ├── ReadCoilsInputsResponseFixture.cs │ │ │ ├── ReadHoldingInputRegistersRequestFixture.cs │ │ │ ├── ReadHoldingInputRegistersResponseFixture.cs │ │ │ ├── ReadWriteMultipleRegistersRequestFixture.cs │ │ │ ├── ReturnQueryDataRequestResponseFixture.cs │ │ │ ├── SlaveExceptionResponseFixture.cs │ │ │ ├── WriteMultipleCoilsRequestFixture.cs │ │ │ ├── WriteMultipleCoilsResponseFixture.cs │ │ │ ├── WriteMultipleRegistersRequestFixture.cs │ │ │ ├── WriteMultipleRegistersResponseFixture.cs │ │ │ ├── WriteSingleCoilRequestResponseFixture.cs │ │ │ └── WriteSingleRegisterRequestResponseFixture.cs │ │ ├── Modbus.UnitTests.csproj │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── SlaveExceptionFixture.cs │ │ └── Utility │ │ │ ├── CollectionUtilityFixture.cs │ │ │ ├── DiscriminatedUnionFixture.cs │ │ │ ├── ModbusUtilityFixture.cs │ │ │ └── SerialConnectionFixture.cs │ ├── Modbus │ │ ├── Data │ │ │ ├── DataStore.cs │ │ │ ├── DataStoreEventArgs.cs │ │ │ ├── DataStoreFactory.cs │ │ │ ├── DiscreteCollection.cs │ │ │ ├── IModbusMessageDataCollection.cs │ │ │ ├── ModbusDataCollection.cs │ │ │ ├── ModbusDataType.cs │ │ │ └── RegisterCollection.cs │ │ ├── Device │ │ │ ├── IModbusMaster.cs │ │ │ ├── IModbusSerialMaster.cs │ │ │ ├── ModbusDevice.cs │ │ │ ├── ModbusIpMaster.cs │ │ │ ├── ModbusMaster.cs │ │ │ ├── ModbusMasterTcpConnection.cs │ │ │ ├── ModbusSerialMaster.cs │ │ │ ├── ModbusSerialSlave.cs │ │ │ ├── ModbusSlave.cs │ │ │ ├── ModbusSlaveRequestEventArgs.cs │ │ │ ├── ModbusTcpSlave.cs │ │ │ ├── ModbusUdpSlave.cs │ │ │ └── TcpConnectionEventArgs.cs │ │ ├── GlobalSuppressions.cs │ │ ├── IO │ │ │ ├── EmptyTransport.cs │ │ │ ├── ISerialPortAdapter.cs │ │ │ ├── ISerialResource.cs │ │ │ ├── IStreamResource.cs │ │ │ ├── ModbusAsciiTransport.cs │ │ │ ├── ModbusIpTransport.cs │ │ │ ├── ModbusRtuTransport.cs │ │ │ ├── ModbusSerialTransport.cs │ │ │ ├── ModbusTransport.cs │ │ │ ├── SerialPortAdapter.cs │ │ │ ├── StreamResourceUtility.cs │ │ │ ├── TcpClientAdapter.cs │ │ │ └── UdpClientAdapter.cs │ │ ├── Message │ │ │ ├── DiagnosticsRequestResponse.cs │ │ │ ├── IModbusMessage.cs │ │ │ ├── IModbusMessageWithData.cs │ │ │ ├── IModbusRequest.cs │ │ │ ├── ModbusMessage.cs │ │ │ ├── ModbusMessageFactory.cs │ │ │ ├── ModbusMessageImpl.cs │ │ │ ├── ModbusMessageWithData.cs │ │ │ ├── ReadCoilsInputsRequest.cs │ │ │ ├── ReadCoilsInputsResponse.cs │ │ │ ├── ReadHoldingInputRegistersRequest.cs │ │ │ ├── ReadHoldingInputRegistersResponse.cs │ │ │ ├── ReadWriteMultipleRegistersRequest.cs │ │ │ ├── SlaveExceptionResponse.cs │ │ │ ├── WriteMultipleCoilsRequest.cs │ │ │ ├── WriteMultipleCoilsResponse.cs │ │ │ ├── WriteMultipleRegistersRequest.cs │ │ │ ├── WriteMultipleRegistersResponse.cs │ │ │ ├── WriteSingleCoilRequestResponse.cs │ │ │ └── WriteSingleRegisterRequestResponse.cs │ │ ├── Modbus.cs │ │ ├── Modbus.csproj │ │ ├── ModbusDevice.cd │ │ ├── ModbusTransport.cd │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── SlaveException.cs │ │ └── Utility │ │ │ ├── DiscriminatedUnion.cs │ │ │ └── ModbusUtility.cs │ ├── MySample │ │ ├── App.config │ │ ├── Driver.cs │ │ ├── MySample.csproj │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ └── NModbus.sln └── tools │ ├── MbUnit │ ├── MbUnit.Framework.dll │ ├── MbUnit.Framework.xml │ ├── MbUnit.Tasks.dll │ ├── QuickGraph.Algorithms.dll │ ├── QuickGraph.Algorithms.xml │ ├── QuickGraph.dll │ └── QuickGraph.xml │ ├── RhinoMocks │ ├── Rhino.Mocks.dll │ └── Rhino.Mocks.xml │ ├── jamod │ ├── SerialSlave.class │ ├── SerialSlave.java │ ├── TcpSlave.class │ ├── TcpSlave.java │ ├── comm.jar │ ├── jamod.jar │ ├── javax.comm.properties │ └── win32com.dll │ ├── nant │ └── NantGoogleCode.dll │ ├── ncover │ └── NCoverExplorer.NAntTasks.dll │ └── nmodbus │ ├── Modbus.dll │ ├── TestDriver.cs │ ├── TestDriver.exe │ └── log4net.dll └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | S7.Net/bin 2 | S7.Net/obj 3 | S7.Net.UnitTest/bin 4 | S7.Net.UnitTest/obj 5 | *.DotSettings 6 | *.v11 7 | *.user 8 | *.suo 9 | *.ncrunchproject 10 | *.nupkg 11 | .vs 12 | *.lock.json 13 | obj/ 14 | bin/ -------------------------------------------------------------------------------- /NModbus/NModbus.shfbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | Debug 7 | AnyCPU 8 | 2.0 9 | {fbebe54e-c54f-4b49-9c64-6ceefffaa413} 10 | 1.8.0.0 11 | 13 | Documentation 14 | Documentation 15 | Documentation 16 | 17 | .\docs\ 18 | Documentation 19 | NModbus is a C# 3.0 implementation of the Modbus protocol. 20 | AutoDocumentCtors, Namespace, TypeParameter 21 | InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 3.5 33 | NModbus 34 | Prototype 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | .NET wrapper for Future Device Technologies USB driver. This assembly contains unsafe code and must be run with full trust. 43 | Modbus. 44 | Modbus data. 45 | Modbus device. 46 | Modbus transport IO. 47 | Modbus messages. 48 | Modbus utility methods. 49 | 50 | 51 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | lib\log4net\log4net.dll 60 | 61 | 62 | lib\Unme\Unme.Common.dll 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /NModbus/NModbusPublic.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/NModbusPublic.snk -------------------------------------------------------------------------------- /NModbus/README.txt: -------------------------------------------------------------------------------- 1 | NModbus 2 | 3 | What is it? 4 | ----------- 5 | NModbus is a C# 3.0 implementation of the Modbus protocol. 6 | 7 | More information at the NModbus project web site http://nmodbus.com/ 8 | 9 | 10 | The Latest Version 11 | ------------------ 12 | The latest binary distribution can be found on the NModbus project web site http://nmodbus.com/ 13 | 14 | The latest source for the project can be found at the NModbus project's google code page http://code.google.com/p/nmodbus/ 15 | 16 | 17 | Documentation 18 | ------------- 19 | Documentation is available in chm format (NModbus.chm) 20 | 21 | 22 | License 23 | ------- 24 | Copyright (c) 2006 Scott Alexander 25 | 26 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 27 | and associated documentation files (the "Software"), to deal in the Software without restriction, 28 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 29 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 30 | furnished to do so, subject to the following conditions: 31 | 32 | The above copyright notice and this permission notice shall be included in all copies or substantial 33 | portions of the Software. 34 | 35 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 36 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 37 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 38 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 39 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /NModbus/lib/FTD2XX.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/lib/FTD2XX.dll -------------------------------------------------------------------------------- /NModbus/lib/Unme/Unme.Common.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/lib/Unme/Unme.Common.dll -------------------------------------------------------------------------------- /NModbus/lib/Unme/Unme.MbUnit.Framework.Extensions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/lib/Unme/Unme.MbUnit.Framework.Extensions.dll -------------------------------------------------------------------------------- /NModbus/lib/log4net/log4net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/lib/log4net/log4net.dll -------------------------------------------------------------------------------- /NModbus/src/FtdAdapter/FtdEnums.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | namespace FtdAdapter 3 | { 4 | /// 5 | /// Specifies the number of stop bits used on the UsbPort object. 6 | /// 7 | [SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")] 8 | [SuppressMessage("Microsoft.Naming", "CA1717:OnlyFlagsEnumsShouldHavePluralNames")] 9 | public enum FtdStopBits 10 | { 11 | /// 12 | /// One stop bit is used. 13 | /// 14 | One = 1, 15 | /// 16 | /// 1.5 stop bits are used. 17 | /// 18 | OnePointFive, 19 | /// 20 | /// Two stop bits are used. 21 | /// 22 | Two 23 | } 24 | 25 | /// 26 | /// Specifies the parity used on the UsbPort object. 27 | /// 28 | public enum FtdParity 29 | { 30 | /// 31 | /// No parity check occurs. 32 | /// 33 | None = 0, 34 | /// 35 | /// Sets the parity bit so that the count of bits set is an odd number. 36 | /// 37 | Odd, 38 | /// 39 | /// Sets the parity bit so that the count of bits set is an even number. 40 | /// 41 | Even, 42 | /// 43 | /// Leaves the parity bit set to 1. 44 | /// 45 | Mark, 46 | /// 47 | /// Leaves the parity bit set to 0. 48 | /// 49 | Space 50 | } 51 | 52 | /// 53 | /// Specifies the flow control used on the UsbPort object. 54 | /// 55 | [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")] 56 | public enum FtdFlowControl 57 | { 58 | /// 59 | /// No flow control is used 60 | /// 61 | None = 0x0000, 62 | /// 63 | /// RTS CTS are used for flow control 64 | /// 65 | RtsCts = 0x0100, 66 | /// 67 | /// DTR DSR are used for flow control 68 | /// 69 | DtrDsr = 0x0200, 70 | /// 71 | /// XON XOFF are used for flow control 72 | /// 73 | XonXoff = 0x0400 74 | } 75 | 76 | /// 77 | /// Specifies the result of a UsbPort operation. 78 | /// 79 | internal enum FtdStatus 80 | { 81 | OK = 0, 82 | InvalidHandle, 83 | DeviceNotFound, 84 | DeviceNotOpened, 85 | IOError, 86 | InsufficientResources, 87 | InvalidParameter, 88 | InvalidBaudRate, 89 | DeviceNotOpenedForErase, 90 | DeviceNotOpenedForWrite, 91 | FailedToWriteDevice, 92 | EEPromReadFailed, 93 | EEPromWriteFailed, 94 | EEPromEraseFailed, 95 | EEPromNotPresent, 96 | EEPromNotProgrammed, 97 | InvalidArgs, 98 | OtherError 99 | } 100 | 101 | /// 102 | /// Specifies how to open the device 103 | /// 104 | internal enum OpenExFlags 105 | { 106 | BySerialNumber = 1, 107 | ByDescription = 2, 108 | ByLocation = 4 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /NModbus/src/FtdAdapter/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace FtdAdapter 8 | { 9 | internal static class NativeMethods 10 | { 11 | [DllImport(FtdAssemblyName)] 12 | internal static extern FtdStatus FT_Close(uint deviceHandle); 13 | [DllImport(FtdAssemblyName)] 14 | internal static extern FtdStatus FT_Open(uint deviceId, ref uint deviceHandle); 15 | [DllImport(FtdAssemblyName)] 16 | internal static extern FtdStatus FT_SetBaudRate(uint deviceHandle, uint baudRate); 17 | [DllImport(FtdAssemblyName)] 18 | internal static extern FtdStatus FT_SetFlowControl(uint handle, ushort usFlowControl, byte uXon, byte uXoff); 19 | [DllImport(FtdAssemblyName)] 20 | internal static extern FtdStatus FT_SetDataCharacteristics(uint deviceHandle, byte wordLength, byte stopBits, byte parity); 21 | [DllImport(FtdAssemblyName)] 22 | internal static extern FtdStatus FT_Read(uint deviceHandle, byte[] buffer, uint bytesToRead, ref uint bytesReturned); 23 | [DllImport(FtdAssemblyName)] 24 | internal static extern FtdStatus FT_Write(uint deviceHandle, byte[] buffer, uint bytesToWrite, ref uint bytesWritten); 25 | [DllImport(FtdAssemblyName)] 26 | internal static extern FtdStatus FT_SetTimeouts(uint deviceHandle, uint readTimeout, uint writeTimeout); 27 | [DllImport(FtdAssemblyName)] 28 | internal static extern FtdStatus FT_Purge(uint deviceHandle, uint mask); 29 | [DllImport(FtdAssemblyName)] 30 | internal static extern FtdStatus FT_CreateDeviceInfoList(ref uint deviceCount); 31 | [DllImport(FtdAssemblyName)] 32 | internal static extern FtdStatus FT_GetDeviceInfoDetail(uint index, ref uint flags, ref uint type, ref uint id, 33 | ref uint locid, [In] [Out] byte[] serial, [In] [Out] byte[] description, ref uint deviceHandle); 34 | [DllImport(FtdAssemblyName)] 35 | internal static extern FtdStatus FT_OpenEx(byte[] key, uint flags, ref uint deviceHandle); 36 | [DllImport(FtdAssemblyName)] 37 | internal static extern FtdStatus FT_OpenEx(uint locationId, uint flags, ref uint deviceHandle); 38 | 39 | private const string FtdAssemblyName = "FTD2XX.dll"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /NModbus/src/FtdAdapter/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("FtdAdapter")] 6 | [assembly: AssemblyProduct("NModbus")] 7 | [assembly: AssemblyCopyright("Licensed under MIT License.")] 8 | [assembly: AssemblyDescription("Provides support for the FTD2XX USB driver.")] 9 | [assembly: ComVisible(false)] 10 | [assembly: CLSCompliant(false)] 11 | [assembly: Guid("60741108-f477-476c-8139-c50ac621089f")] 12 | [assembly: AssemblyVersion("1.9.0.0")] 13 | [assembly: AssemblyFileVersion("1.9.0.0")] 14 | -------------------------------------------------------------------------------- /NModbus/src/FtdAdapter/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:2.0.50727.3074 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FtdAdapter { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FtdAdapter.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Port is already open.. 65 | /// 66 | internal static string PortIsAlreadyOpen { 67 | get { 68 | return ResourceManager.GetString("PortIsAlreadyOpen", resourceCulture); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.Extensions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Modbus.Extensions")] 6 | [assembly: AssemblyProduct("NModbus")] 7 | [assembly: AssemblyCopyright("Licensed under MIT License.")] 8 | [assembly: AssemblyDescription("Provides utiltiy extensions for the NModbus library.")] 9 | [assembly: ComVisible(false)] 10 | [assembly: CLSCompliant(false)] 11 | [assembly: Guid("A0218720-E559-434d-AB0D-CC03E6D69F46")] 12 | [assembly: AssemblyVersion("1.9.0.0")] 13 | [assembly: AssemblyFileVersion("1.9.0.0")] 14 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/CustomMessages/CustomReadHoldingRegistersRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using Modbus.Message; 5 | 6 | namespace Modbus.IntegrationTests.CustomMessages 7 | { 8 | public class CustomReadHoldingRegistersRequest : IModbusMessage 9 | { 10 | private byte _functionCode; 11 | private byte _slaveAddress; 12 | private ushort _startAddress; 13 | private ushort _numberOfPoints; 14 | private ushort _transactionId; 15 | 16 | public CustomReadHoldingRegistersRequest(byte functionCode, byte slaveAddress, ushort startAddress, ushort numberOfPoints) 17 | { 18 | _functionCode = functionCode; 19 | _slaveAddress = slaveAddress; 20 | _startAddress = startAddress; 21 | _numberOfPoints = numberOfPoints; 22 | } 23 | 24 | public byte[] MessageFrame 25 | { 26 | get 27 | { 28 | List frame = new List(); 29 | frame.Add(SlaveAddress); 30 | frame.AddRange(ProtocolDataUnit); 31 | 32 | return frame.ToArray(); 33 | } 34 | } 35 | 36 | public byte[] ProtocolDataUnit 37 | { 38 | get 39 | { 40 | List pdu = new List(); 41 | 42 | pdu.Add(FunctionCode); 43 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) StartAddress))); 44 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) NumberOfPoints))); 45 | 46 | return pdu.ToArray(); 47 | } 48 | } 49 | 50 | public ushort TransactionId 51 | { 52 | get { return _transactionId; } 53 | set { _transactionId = value; } 54 | } 55 | 56 | public byte FunctionCode 57 | { 58 | get { return _functionCode; } 59 | set { _functionCode = value; } 60 | } 61 | 62 | public byte SlaveAddress 63 | { 64 | get { return _slaveAddress; } 65 | set { _slaveAddress = value; } 66 | } 67 | 68 | public ushort StartAddress 69 | { 70 | get { return _startAddress; } 71 | set { _startAddress = value; } 72 | } 73 | 74 | public ushort NumberOfPoints 75 | { 76 | get { return _numberOfPoints; } 77 | set { _numberOfPoints = value; } 78 | } 79 | 80 | public void Initialize(byte[] frame) 81 | { 82 | if (frame == null) 83 | throw new ArgumentNullException("frame"); 84 | 85 | if (frame.Length != 6) 86 | throw new ArgumentException("Invalid frame.", "frame"); 87 | 88 | SlaveAddress = frame[0]; 89 | FunctionCode = frame[1]; 90 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 91 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/CustomMessages/CustomReadHoldingRegistersResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Modbus.Data; 5 | using Modbus.Message; 6 | using Unme.Common; 7 | 8 | namespace Modbus.IntegrationTests.CustomMessages 9 | { 10 | public class CustomReadHoldingRegistersResponse : IModbusMessage 11 | { 12 | private byte _functionCode; 13 | private byte _slaveAddress; 14 | private byte _byteCount; 15 | private ushort _transactionId; 16 | private RegisterCollection _data; 17 | 18 | public ushort[] Data 19 | { 20 | get 21 | { 22 | return _data.ToArray(); 23 | } 24 | } 25 | 26 | public byte[] MessageFrame 27 | { 28 | get 29 | { 30 | List frame = new List(); 31 | frame.Add(SlaveAddress); 32 | frame.AddRange(ProtocolDataUnit); 33 | 34 | return frame.ToArray(); 35 | } 36 | } 37 | 38 | public byte[] ProtocolDataUnit 39 | { 40 | get 41 | { 42 | List pdu = new List(); 43 | 44 | pdu.Add(_functionCode); 45 | pdu.Add(ByteCount); 46 | pdu.AddRange(_data.NetworkBytes); 47 | 48 | return pdu.ToArray(); 49 | } 50 | } 51 | 52 | public ushort TransactionId 53 | { 54 | get { return _transactionId; } 55 | set { _transactionId = value; } 56 | } 57 | 58 | public byte FunctionCode 59 | { 60 | get { return _functionCode; } 61 | set { _functionCode = value; } 62 | } 63 | 64 | public byte SlaveAddress 65 | { 66 | get { return _slaveAddress; } 67 | set { _slaveAddress = value; } 68 | } 69 | 70 | public byte ByteCount 71 | { 72 | get 73 | { 74 | return _byteCount; 75 | } 76 | set { _byteCount = value; } 77 | } 78 | 79 | public void Initialize(byte[] frame) 80 | { 81 | if (frame == null) 82 | throw new ArgumentNullException("frame"); 83 | 84 | if (frame.Length < 3 || frame.Length < 3 + frame[2]) 85 | throw new ArgumentException("Message frame does not contain enough bytes.", "frame"); 86 | 87 | SlaveAddress = frame[0]; 88 | FunctionCode = frame[1]; 89 | ByteCount = frame[2]; 90 | _data = new RegisterCollection(frame.Slice(3, ByteCount).ToArray()); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/CustomMessages/CustomWriteMultipleRegistersRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using Modbus.Data; 6 | using Modbus.Message; 7 | using Unme.Common; 8 | 9 | namespace Modbus.IntegrationTests.CustomMessages 10 | { 11 | public class CustomWriteMultipleRegistersRequest : IModbusMessage 12 | { 13 | private byte _functionCode; 14 | private byte _slaveAddress; 15 | private byte _byteCount; 16 | private ushort _startAddress; 17 | private ushort _numberOfPoints; 18 | private ushort _transactionId; 19 | private RegisterCollection _data; 20 | 21 | public CustomWriteMultipleRegistersRequest(byte functionCode, byte slaveAddress, ushort startAddress, RegisterCollection data) 22 | { 23 | _functionCode = functionCode; 24 | _slaveAddress = slaveAddress; 25 | _startAddress = startAddress; 26 | _numberOfPoints = (ushort) data.Count; 27 | _byteCount = data.ByteCount; 28 | _data = data; 29 | } 30 | 31 | public byte[] MessageFrame 32 | { 33 | get 34 | { 35 | List frame = new List(); 36 | frame.Add(SlaveAddress); 37 | frame.AddRange(ProtocolDataUnit); 38 | 39 | return frame.ToArray(); 40 | } 41 | } 42 | 43 | public byte[] ProtocolDataUnit 44 | { 45 | get 46 | { 47 | List pdu = new List(); 48 | 49 | pdu.Add(FunctionCode); 50 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) StartAddress))); 51 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) NumberOfPoints))); 52 | pdu.Add(ByteCount); 53 | pdu.AddRange(Data.NetworkBytes); 54 | 55 | return pdu.ToArray(); 56 | } 57 | } 58 | 59 | public ushort TransactionId 60 | { 61 | get { return _transactionId; } 62 | set { _transactionId = value; } 63 | } 64 | 65 | public byte FunctionCode 66 | { 67 | get { return _functionCode; } 68 | set { _functionCode = value; } 69 | } 70 | 71 | public byte SlaveAddress 72 | { 73 | get { return _slaveAddress; } 74 | set { _slaveAddress = value; } 75 | } 76 | 77 | public ushort StartAddress 78 | { 79 | get { return _startAddress; } 80 | set { _startAddress = value; } 81 | } 82 | 83 | public ushort NumberOfPoints 84 | { 85 | get { return _numberOfPoints; } 86 | set { _numberOfPoints = value; } 87 | } 88 | 89 | public byte ByteCount 90 | { 91 | get { return _byteCount; } 92 | set { _byteCount = value; } 93 | } 94 | 95 | public RegisterCollection Data 96 | { 97 | get { return _data; } 98 | set { _data = value; } 99 | } 100 | 101 | public void Initialize(byte[] frame) 102 | { 103 | if (frame == null) 104 | throw new ArgumentNullException("frame"); 105 | 106 | if (frame.Length < 7 || frame.Length < 7 + frame[6]) 107 | throw new FormatException("Message frame does not contain enough bytes."); 108 | 109 | SlaveAddress = frame[0]; 110 | FunctionCode = frame[1]; 111 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 112 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 113 | ByteCount = frame[6]; 114 | Data = new RegisterCollection(frame.Slice(7, ByteCount).ToArray()); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/CustomMessages/CustomWriteMultipleRegistersResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using Modbus.Message; 5 | 6 | namespace Modbus.IntegrationTests.CustomMessages 7 | { 8 | public class CustomWriteMultipleRegistersResponse : IModbusMessage 9 | { 10 | private byte _functionCode; 11 | private byte _slaveAddress; 12 | private ushort _startAddress; 13 | private ushort _numberOfPoints; 14 | private ushort _transactionId; 15 | 16 | public byte[] MessageFrame 17 | { 18 | get 19 | { 20 | List frame = new List(); 21 | frame.Add(SlaveAddress); 22 | frame.AddRange(ProtocolDataUnit); 23 | 24 | return frame.ToArray(); 25 | } 26 | } 27 | 28 | public byte[] ProtocolDataUnit 29 | { 30 | get 31 | { 32 | List pdu = new List(); 33 | 34 | pdu.Add(FunctionCode); 35 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) StartAddress))); 36 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) NumberOfPoints))); 37 | 38 | return pdu.ToArray(); 39 | } 40 | } 41 | 42 | public ushort TransactionId 43 | { 44 | get { return _transactionId; } 45 | set { _transactionId = value; } 46 | } 47 | 48 | public byte FunctionCode 49 | { 50 | get { return _functionCode; } 51 | set { _functionCode = value; } 52 | } 53 | 54 | public byte SlaveAddress 55 | { 56 | get { return _slaveAddress; } 57 | set { _slaveAddress = value; } 58 | } 59 | 60 | public ushort StartAddress 61 | { 62 | get { return _startAddress; } 63 | set { _startAddress = value; } 64 | } 65 | 66 | public ushort NumberOfPoints 67 | { 68 | get { return _numberOfPoints; } 69 | set { _numberOfPoints = value; } 70 | } 71 | 72 | public void Initialize(byte[] frame) 73 | { 74 | if (frame == null) 75 | throw new ArgumentNullException("frame"); 76 | 77 | if (frame.Length < 6) 78 | throw new FormatException("Message frame does not contain enough bytes."); 79 | 80 | SlaveAddress = frame[0]; 81 | FunctionCode = frame[1]; 82 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 83 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/EnronFixture.cs: -------------------------------------------------------------------------------- 1 | using MbUnit.Framework; 2 | using Modbus.Extensions.Enron; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | [TestFixture] 7 | public class EnronFixture : NModbusSerialRtuMasterDl06SlaveFixture 8 | { 9 | [Test] 10 | public virtual void ReadHoldingRegisters32() 11 | { 12 | uint[] registers = Master.ReadHoldingRegisters32(SlaveAddress, 104, 2); 13 | Assert.AreEqual(new uint[] { 0, 0 }, registers); 14 | } 15 | 16 | [Test] 17 | public virtual void ReadInputRegisters32() 18 | { 19 | uint[] registers = Master.ReadInputRegisters32(SlaveAddress, 104, 2); 20 | Assert.AreEqual(new uint[] { 0, 0 }, registers); 21 | } 22 | 23 | [Test] 24 | public virtual void WriteSingleRegister32() 25 | { 26 | ushort testAddress = 200; 27 | uint testValue = 350; 28 | 29 | uint originalValue = Master.ReadHoldingRegisters32(SlaveAddress, testAddress, 1)[0]; 30 | Master.WriteSingleRegister32(SlaveAddress, testAddress, testValue); 31 | Assert.AreEqual(testValue, Master.ReadHoldingRegisters32(SlaveAddress, testAddress, 1)[0]); 32 | Master.WriteSingleRegister32(SlaveAddress, testAddress, originalValue); 33 | Assert.AreEqual(originalValue, Master.ReadHoldingRegisters(SlaveAddress, testAddress, 1)[0]); 34 | } 35 | 36 | [Test] 37 | public virtual void WriteMultipleRegisters32() 38 | { 39 | ushort testAddress = 120; 40 | uint[] testValues = new uint[] { 10, 20, 30, 40, 50 }; 41 | 42 | uint[] originalValues = Master.ReadHoldingRegisters32(SlaveAddress, testAddress, (ushort) testValues.Length); 43 | Master.WriteMultipleRegisters32(SlaveAddress, testAddress, testValues); 44 | uint[] newValues = Master.ReadHoldingRegisters32(SlaveAddress, testAddress, (ushort) testValues.Length); 45 | Assert.AreEqual(testValues, newValues); 46 | Master.WriteMultipleRegisters32(SlaveAddress, testAddress, originalValues); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/FtdUsbPortAdapterFixture.cs: -------------------------------------------------------------------------------- 1 | using FtdAdapter; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | [TestFixture] 7 | public class FtdUsbPortAdapterFixture 8 | { 9 | [Test] 10 | public void GetDeviceInfos() 11 | { 12 | var deviceInfos = FtdUsbPort.GetDeviceInfos(); 13 | Assert.IsNotNull(deviceInfos); 14 | Assert.AreEqual(1, deviceInfos.Length); 15 | } 16 | 17 | [Test] 18 | public void GetDeviceInfo() 19 | { 20 | var deviceInfo = FtdUsbPort.GetDeviceInfo(0); 21 | Assert.IsNotNull(deviceInfo); 22 | 23 | Assert.AreEqual("ftCARN75", deviceInfo.SerialNumber); 24 | Assert.AreEqual(" USB Serial Converter", deviceInfo.Description); 25 | } 26 | 27 | [Test] 28 | public void OpenByIndex() 29 | { 30 | using (var port = new FtdUsbPort()) 31 | { 32 | port.OpenByIndex(0); 33 | Assert.IsTrue(port.IsOpen); 34 | } 35 | } 36 | 37 | [Test] 38 | public void OpenByLocationId() 39 | { 40 | var deviceInfo = FtdUsbPort.GetDeviceInfo(0); 41 | Assert.IsNotNull(deviceInfo); 42 | 43 | using (var port = new FtdUsbPort()) 44 | { 45 | port.OpenByLocationId(deviceInfo.LocationId); 46 | Assert.IsTrue(port.IsOpen); 47 | } 48 | } 49 | 50 | [Test] 51 | public void OpenByDescription() 52 | { 53 | var deviceInfo = FtdUsbPort.GetDeviceInfo(0); 54 | Assert.IsNotNull(deviceInfo); 55 | 56 | using (var port = new FtdUsbPort()) 57 | { 58 | port.OpenByDescription(deviceInfo.Description); 59 | Assert.IsTrue(port.IsOpen); 60 | } 61 | } 62 | 63 | [Test] 64 | public void OpenBySerialNumber() 65 | { 66 | var deviceInfo = FtdUsbPort.GetDeviceInfo(0); 67 | Assert.IsNotNull(deviceInfo); 68 | 69 | using (var port = new FtdUsbPort()) 70 | { 71 | port.OpenBySerialNumber(deviceInfo.SerialNumber); 72 | Assert.IsTrue(port.IsOpen); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/ModbusSerialMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using MbUnit.Framework; 2 | using Modbus.Device; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | public abstract class ModbusSerialMasterFixture : ModbusMasterFixture 7 | { 8 | [Test] 9 | public virtual void ReturnQueryData() 10 | { 11 | Assert.IsTrue(((ModbusSerialMaster) Master).ReturnQueryData(SlaveAddress, 18)); 12 | Assert.IsTrue(((ModbusSerialMaster) Master).ReturnQueryData(SlaveAddress, 5)); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialAsciiMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO.Ports; 3 | using Modbus.Device; 4 | using MbUnit.Framework; 5 | 6 | namespace Modbus.IntegrationTests 7 | { 8 | [TestFixture] 9 | public class NModbusSerialAsciiMasterFixture 10 | { 11 | [Test, ExpectedException(typeof(TimeoutException))] 12 | public void NModbusAsciiMaster_ReadTimeout() 13 | { 14 | using (SerialPort port = ModbusMasterFixture.CreateAndOpenSerialPort(ModbusMasterFixture.DefaultMasterSerialPortName)) 15 | { 16 | IModbusSerialMaster master = ModbusSerialMaster.CreateAscii(port); 17 | master.ReadCoils(100, 1, 1); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialAsciiMasterJamodSerialAsciiSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Device; 3 | using MbUnit.Framework; 4 | using System.Globalization; 5 | 6 | namespace Modbus.IntegrationTests 7 | { 8 | [TestFixture] 9 | public class NModbusSerialAsciiMasterJamodSerialAsciiSlaveFixture : ModbusMasterFixture 10 | { 11 | private string program = String.Format(CultureInfo.InvariantCulture, "SerialSlave {0} ASCII", DefaultSlaveSerialPortName); 12 | 13 | [TestFixtureSetUp] 14 | public override void Init() 15 | { 16 | base.Init(); 17 | 18 | StartJamodSlave(program); 19 | 20 | MasterSerialPort = CreateAndOpenSerialPort(DefaultMasterSerialPortName); 21 | Master = ModbusSerialMaster.CreateAscii(MasterSerialPort); 22 | } 23 | 24 | /// 25 | /// Jamod slave does not support this function 26 | /// 27 | public override void ReadWriteMultipleRegisters() 28 | { 29 | } 30 | 31 | [Test] 32 | public override void ReadCoils() 33 | { 34 | base.ReadCoils(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialAsciiMasterNModbusSerialAsciiSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Device; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | [TestFixture] 7 | public class NModbusSerialAsciiMasterNModbusSerialAsciiSlaveFixture : ModbusSerialMasterFixture 8 | { 9 | [TestFixtureSetUp] 10 | public override void Init() 11 | { 12 | base.Init(); 13 | 14 | MasterSerialPort = CreateAndOpenSerialPort(DefaultMasterSerialPortName); 15 | Master = ModbusSerialMaster.CreateAscii(MasterSerialPort); 16 | SetupSlaveSerialPort(); 17 | Slave = ModbusSerialSlave.CreateAscii(SlaveAddress, SlaveSerialPort); 18 | 19 | StartSlave(); 20 | } 21 | 22 | [Test] 23 | public override void ReadCoils() 24 | { 25 | base.ReadCoils(); 26 | } 27 | 28 | [Test] 29 | public override void ReadInputs() 30 | { 31 | base.ReadInputs(); 32 | } 33 | 34 | [Test] 35 | public override void ReadHoldingRegisters() 36 | { 37 | base.ReadHoldingRegisters(); 38 | } 39 | 40 | [Test] 41 | public override void ReadInputRegisters() 42 | { 43 | base.ReadInputRegisters(); 44 | } 45 | 46 | [Test] 47 | public override void WriteSingleCoil() 48 | { 49 | base.WriteSingleCoil(); 50 | } 51 | 52 | [Test] 53 | public override void WriteMultipleCoils() 54 | { 55 | base.WriteMultipleCoils(); 56 | } 57 | 58 | [Test] 59 | public override void WriteSingleRegister() 60 | { 61 | base.WriteSingleRegister(); 62 | } 63 | 64 | [Test] 65 | public override void WriteMultipleRegisters() 66 | { 67 | base.WriteMultipleRegisters(); 68 | } 69 | 70 | [Test] 71 | public override void ReadWriteMultipleRegisters() 72 | { 73 | base.ReadWriteMultipleRegisters(); 74 | } 75 | 76 | [Test] 77 | public override void ReturnQueryData() 78 | { 79 | base.ReturnQueryData(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialRtuMasterDl06SlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Device; 2 | using MbUnit.Framework; 3 | using System; 4 | 5 | namespace Modbus.IntegrationTests 6 | { 7 | [TestFixture] 8 | public class NModbusSerialRtuMasterDl06SlaveFixture : ModbusSerialMasterFixture 9 | { 10 | [TestFixtureSetUp] 11 | public override void Init() 12 | { 13 | base.Init(); 14 | 15 | MasterSerialPort = CreateAndOpenSerialPort("COM4"); 16 | Master = ModbusSerialMaster.CreateRtu(MasterSerialPort); 17 | } 18 | 19 | /// 20 | /// Not supported by the DL06 21 | /// 22 | public override void ReadWriteMultipleRegisters() 23 | { 24 | } 25 | 26 | /// 27 | /// Not supported by the DL06 28 | /// 29 | public override void ReturnQueryData() 30 | { 31 | } 32 | 33 | [Test] 34 | public override void ReadCoils() 35 | { 36 | base.ReadCoils(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialRtuMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO.Ports; 3 | using Modbus.Device; 4 | using MbUnit.Framework; 5 | 6 | namespace Modbus.IntegrationTests 7 | { 8 | [TestFixture] 9 | public class NModbusSerialRtuMasterFixture 10 | { 11 | [Test, ExpectedException(typeof(TimeoutException))] 12 | public void NModbusRtuMaster_ReadTimeout() 13 | { 14 | using (SerialPort port = ModbusMasterFixture.CreateAndOpenSerialPort(ModbusMasterFixture.DefaultMasterSerialPortName)) 15 | { 16 | IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port); 17 | master.ReadCoils(100, 1, 1); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialRtuMasterNModbusSerialRtuSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Device; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | [TestFixture] 7 | public class NModbusSerialRtuMasterNModbusSerialRtuSlaveFixture : ModbusSerialMasterFixture 8 | { 9 | [TestFixtureSetUp] 10 | public override void Init() 11 | { 12 | base.Init(); 13 | 14 | SetupSlaveSerialPort(); 15 | Slave = ModbusSerialSlave.CreateRtu(SlaveAddress, SlaveSerialPort); 16 | StartSlave(); 17 | 18 | MasterSerialPort = CreateAndOpenSerialPort(DefaultMasterSerialPortName); 19 | Master = ModbusSerialMaster.CreateRtu(MasterSerialPort); 20 | } 21 | 22 | [Test] 23 | public override void ReadCoils() 24 | { 25 | base.ReadCoils(); 26 | } 27 | 28 | [Test] 29 | public override void ReadHoldingRegisters() 30 | { 31 | base.ReadHoldingRegisters(); 32 | } 33 | 34 | [Test] 35 | public override void ReadInputs() 36 | { 37 | base.ReadInputs(); 38 | } 39 | 40 | [Test] 41 | public override void WriteSingleCoil() 42 | { 43 | base.WriteSingleCoil(); 44 | } 45 | 46 | [Test] 47 | public override void WriteMultipleCoils() 48 | { 49 | base.WriteMultipleCoils(); 50 | } 51 | 52 | [Test] 53 | public override void WriteSingleRegister() 54 | { 55 | base.WriteSingleRegister(); 56 | } 57 | 58 | [Test] 59 | public override void WriteMultipleRegisters() 60 | { 61 | base.WriteMultipleRegisters(); 62 | } 63 | 64 | 65 | [Test, Ignore("Need to fix RTU slave for this function code")] 66 | public override void ReadWriteMultipleRegisters() 67 | { 68 | base.ReadWriteMultipleRegisters(); 69 | } 70 | 71 | [Test] 72 | public override void ReturnQueryData() 73 | { 74 | base.ReturnQueryData(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusSerialRtuSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using MbUnit.Framework; 5 | using System.IO.Ports; 6 | using Modbus.Device; 7 | using Modbus.Data; 8 | using System.Threading; 9 | 10 | namespace Modbus.IntegrationTests 11 | { 12 | [TestFixture] 13 | public class NModbusSerialRtuSlaveFixture 14 | { 15 | [TestFixtureSetUp] 16 | public void SetUp() 17 | { 18 | log4net.Config.XmlConfigurator.Configure(); 19 | } 20 | 21 | [Test] 22 | public void NModbusSerialRtuSlave_BonusCharacter_VerifyTimeout() 23 | { 24 | using (SerialPort masterPort = ModbusMasterFixture.CreateAndOpenSerialPort(ModbusMasterFixture.DefaultMasterSerialPortName)) 25 | using (SerialPort slavePort = ModbusMasterFixture.CreateAndOpenSerialPort(ModbusMasterFixture.DefaultSlaveSerialPortName)) 26 | { 27 | IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(masterPort); 28 | 29 | ModbusSerialSlave slave = ModbusSerialSlave.CreateRtu(1, slavePort); 30 | slave.DataStore = DataStoreFactory.CreateTestDataStore(); 31 | 32 | Thread slaveThread = new Thread(slave.Listen); 33 | slaveThread.IsBackground = true; 34 | slaveThread.Start(); 35 | 36 | // assert successful communication 37 | Assert.AreEqual(new bool[] { false, true }, master.ReadCoils(1, 1, 2)); 38 | 39 | // write "bonus" character 40 | masterPort.Write("*"); 41 | 42 | // assert successful communication 43 | Assert.AreEqual(new bool[] { false, true }, master.ReadCoils(1, 1, 2)); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusTcpMasterJamodTcpSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Sockets; 3 | using Modbus.Device; 4 | using MbUnit.Framework; 5 | using System.Globalization; 6 | 7 | namespace Modbus.IntegrationTests 8 | { 9 | [TestFixture] 10 | public class NModbusTcpMasterJamodTcpSlaveFixture : ModbusMasterFixture 11 | { 12 | private string program = String.Format(CultureInfo.InvariantCulture, "TcpSlave {0}", Port); 13 | 14 | [TestFixtureSetUp] 15 | public override void Init() 16 | { 17 | base.Init(); 18 | 19 | StartJamodSlave(program); 20 | 21 | MasterTcp = new TcpClient(TcpHost.ToString(), Port); 22 | Master = ModbusIpMaster.CreateIp(MasterTcp); 23 | } 24 | 25 | /// 26 | /// Not supported by the Jamod Slave 27 | /// 28 | public override void ReadWriteMultipleRegisters() 29 | { 30 | } 31 | 32 | [Test] 33 | public override void ReadCoils() 34 | { 35 | base.ReadCoils(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusTcpMasterNModbusTcpSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | using Modbus.Device; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.IntegrationTests 6 | { 7 | [TestFixture] 8 | public class NModbusTcpMasterNModbusTcpSlaveFixture : ModbusMasterFixture 9 | { 10 | [TestFixtureSetUp] 11 | public override void Init() 12 | { 13 | base.Init(); 14 | 15 | SlaveTcp = new TcpListener(TcpHost, Port); 16 | SlaveTcp.Start(); 17 | Slave = ModbusTcpSlave.CreateTcp(SlaveAddress, SlaveTcp); 18 | StartSlave(); 19 | 20 | MasterTcp = new TcpClient(TcpHost.ToString(), Port); 21 | Master = ModbusIpMaster.CreateIp(MasterTcp); 22 | } 23 | 24 | [TestFixtureTearDown] 25 | public void TestFixtureTearDown() 26 | { 27 | SlaveTcp.Stop(); 28 | MasterTcp.Close(); 29 | CleanUp(); 30 | } 31 | 32 | [Test] 33 | public override void ReadCoils() 34 | { 35 | base.ReadCoils(); 36 | } 37 | 38 | [Test] 39 | public override void ReadInputs() 40 | { 41 | base.ReadInputs(); 42 | } 43 | 44 | [Test] 45 | public override void WriteSingleCoil() 46 | { 47 | base.WriteSingleCoil(); 48 | } 49 | 50 | [Test] 51 | public override void WriteMultipleCoils() 52 | { 53 | base.WriteMultipleCoils(); 54 | } 55 | 56 | [Test] 57 | public override void WriteSingleRegister() 58 | { 59 | base.WriteSingleRegister(); 60 | } 61 | 62 | [Test] 63 | public override void WriteMultipleRegisters() 64 | { 65 | base.WriteMultipleRegisters(); 66 | } 67 | 68 | [Test] 69 | public override void ReadMaximumNumberOfHoldingRegisters() 70 | { 71 | base.ReadMaximumNumberOfHoldingRegisters(); 72 | } 73 | 74 | [Test] 75 | public override void ReadWriteMultipleRegisters() 76 | { 77 | base.ReadWriteMultipleRegisters(); 78 | } 79 | 80 | [Test] 81 | public override void SimpleReadRegistersPerformanceTest() 82 | { 83 | base.SimpleReadRegistersPerformanceTest(); 84 | } 85 | 86 | [Test] 87 | public override void ExecuteCustomMessage_ReadHoldingRegisters() 88 | { 89 | base.ExecuteCustomMessage_ReadHoldingRegisters(); 90 | } 91 | 92 | [Test] 93 | public override void ExecuteCustomMessage_WriteMultipleRegisters() 94 | { 95 | base.ExecuteCustomMessage_WriteMultipleRegisters(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusUdpMasterNModbusUdpSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | using Modbus.Device; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.IntegrationTests 6 | { 7 | [TestFixture] 8 | public class NModbusUdpMasterNModbusUdpSlaveFixture : ModbusMasterFixture 9 | { 10 | [TestFixtureSetUp] 11 | public override void Init() 12 | { 13 | base.Init(); 14 | 15 | SlaveUdp = new UdpClient(Port); 16 | Slave = ModbusUdpSlave.CreateUdp(SlaveUdp); 17 | StartSlave(); 18 | 19 | MasterUdp = new UdpClient(); 20 | MasterUdp.Connect(DefaultModbusIPEndPoint); 21 | Master = ModbusIpMaster.CreateIp(MasterUdp); 22 | } 23 | 24 | [Test] 25 | public override void ReadCoils() 26 | { 27 | base.ReadCoils(); 28 | } 29 | 30 | [Test] 31 | public override void SimpleReadRegistersPerformanceTest() 32 | { 33 | base.SimpleReadRegistersPerformanceTest(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusUsbAsciiMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using FtdAdapter; 3 | using Modbus.Device; 4 | using MbUnit.Framework; 5 | 6 | namespace Modbus.IntegrationTests 7 | { 8 | [TestFixture] 9 | public class NModbusUsbAsciiMasterFixture 10 | { 11 | [Test, ExpectedException(typeof(TimeoutException))] 12 | public void NModbusUsbAsciiMaster_ReadTimeout() 13 | { 14 | using (FtdUsbPort port = ModbusMasterFixture.CreateAndOpenUsbPort(ModbusMasterFixture.DefaultMasterUsbPortId)) 15 | { 16 | IModbusSerialMaster master = ModbusSerialMaster.CreateAscii(port); 17 | master.ReadCoils(100, 1, 1); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusUsbAsciiNModbusSerialAsciiFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Device; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | [TestFixture] 7 | public class NModbusUsbAsciiNModbusSerialAsciiFixture : ModbusSerialMasterFixture 8 | { 9 | [TestFixtureSetUp] 10 | public override void Init() 11 | { 12 | base.Init(); 13 | 14 | SetupSlaveSerialPort(); 15 | Slave = ModbusSerialSlave.CreateAscii(SlaveAddress, SlaveSerialPort); 16 | StartSlave(); 17 | 18 | MasterUsbPort = CreateAndOpenUsbPort(DefaultMasterUsbPortId); 19 | Master = ModbusSerialMaster.CreateAscii(MasterUsbPort); 20 | } 21 | 22 | [Test] 23 | public override void ReadCoils() 24 | { 25 | base.ReadCoils(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusUsbRtuMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using FtdAdapter; 3 | using Modbus.Device; 4 | using MbUnit.Framework; 5 | 6 | namespace Modbus.IntegrationTests 7 | { 8 | [TestFixture] 9 | public class NModbusUsbRtuMasterFixture 10 | { 11 | [Test, ExpectedException(typeof(TimeoutException))] 12 | public void NModbusUsbRtuMaster_ReadTimeout() 13 | { 14 | using (FtdUsbPort port = ModbusMasterFixture.CreateAndOpenUsbPort(ModbusMasterFixture.DefaultMasterUsbPortId)) 15 | { 16 | IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port); 17 | master.ReadCoils(100, 1, 1); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/NModbusUsbRtuMasterNModbusSerialRtuSlaveFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Device; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.IntegrationTests 5 | { 6 | [TestFixture] 7 | public class NModbusUsbRtuMasterNModbusSerialRtuSlaveFixture : ModbusSerialMasterFixture 8 | { 9 | [TestFixtureSetUp] 10 | public override void Init() 11 | { 12 | base.Init(); 13 | 14 | SetupSlaveSerialPort(); 15 | Slave = ModbusSerialSlave.CreateRtu(SlaveAddress, SlaveSerialPort); 16 | StartSlave(); 17 | 18 | MasterUsbPort = CreateAndOpenUsbPort(DefaultMasterUsbPortId); 19 | Master = ModbusSerialMaster.CreateRtu(MasterUsbPort); 20 | } 21 | 22 | /// 23 | /// Not implemented by slave yet 24 | /// 25 | public override void ReadWriteMultipleRegisters() 26 | { 27 | } 28 | 29 | [Test] 30 | public override void ReadCoils() 31 | { 32 | base.ReadCoils(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.IntegrationTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Modbus.IntegrationTests")] 6 | [assembly: AssemblyProduct("NModbus")] 7 | [assembly: AssemblyCopyright("Licensed under MIT License.")] 8 | [assembly: ComVisible(false)] 9 | [assembly: CLSCompliant(false)] 10 | [assembly: Guid("6ddc8745-7d6d-4b5e-8e81-c23c7338bbab")] 11 | [assembly: AssemblyVersion("1.9.0.0")] 12 | [assembly: AssemblyFileVersion("1.9.0.0")] 13 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Data/DataStoreEventArgsFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Modbus.Data; 4 | using MbUnit.Framework; 5 | 6 | namespace Modbus.UnitTests.Data 7 | { 8 | [TestFixture] 9 | public class DataStoreEventArgsFixture 10 | { 11 | [Test] 12 | public void CreateDataStoreEventArgs() 13 | { 14 | var eventArgs = DataStoreEventArgs.CreateDataStoreEventArgs(5, ModbusDataType.HoldingRegister, new ushort[] { 1, 2, 3 }); 15 | Assert.AreEqual(ModbusDataType.HoldingRegister, eventArgs.ModbusDataType); 16 | Assert.AreEqual(5, eventArgs.StartAddress); 17 | Assert.AreEqual(new ushort[] { 1, 2, 3 }, eventArgs.Data.B.ToArray()); 18 | } 19 | 20 | [Test, ExpectedArgumentException] 21 | public void CreateDataStoreEventArgs_InvalidType() 22 | { 23 | var eventArgs = DataStoreEventArgs.CreateDataStoreEventArgs(5, ModbusDataType.HoldingRegister, new int[] { 1, 2, 3 }); 24 | } 25 | 26 | [Test, ExpectedArgumentNullException] 27 | public void CreateDataStoreEventArgs_DataNull() 28 | { 29 | var eventArgs = DataStoreEventArgs.CreateDataStoreEventArgs(5, ModbusDataType.HoldingRegister, default(ushort[])); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Data/DiscreteCollectionFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using MbUnit.Framework; 3 | using System.Linq; 4 | 5 | namespace Modbus.UnitTests.Data 6 | { 7 | [TestFixture] 8 | public class DiscreteCollectionFixture 9 | { 10 | [Test] 11 | public void ByteCount() 12 | { 13 | DiscreteCollection col = new DiscreteCollection(true, true, false, false, false, false, false, false, false); 14 | Assert.AreEqual(2, col.ByteCount); 15 | } 16 | 17 | [Test] 18 | public void ByteCountEven() 19 | { 20 | DiscreteCollection col = new DiscreteCollection(true, true, false, false, false, false, false, false); 21 | Assert.AreEqual(1, col.ByteCount); 22 | } 23 | 24 | [Test] 25 | public void NetworkBytes() 26 | { 27 | DiscreteCollection col = new DiscreteCollection(true, true); 28 | Assert.AreEqual(new byte[] { 3 }, col.NetworkBytes); 29 | } 30 | 31 | [Test] 32 | public void CreateNewDiscreteCollectionInitialize() 33 | { 34 | DiscreteCollection col = new DiscreteCollection(true, true, true); 35 | Assert.AreEqual(3, col.Count); 36 | Assert.IsFalse(col.Contains(false)); 37 | } 38 | 39 | [Test] 40 | public void CreateNewDiscreteCollectionFromBoolParams() 41 | { 42 | DiscreteCollection col = new DiscreteCollection(true, false, true); 43 | Assert.AreEqual(3, col.Count); 44 | } 45 | 46 | [Test] 47 | public void CreateNewDiscreteCollectionFromBytesParams() 48 | { 49 | DiscreteCollection col = new DiscreteCollection(1, 2, 3); 50 | Assert.AreEqual(24, col.Count); 51 | } 52 | 53 | [Test] 54 | public void CreateNewDiscreteCollectionFromBytesParamsOrder() 55 | { 56 | DiscreteCollection col = new DiscreteCollection(194); 57 | Assert.AreEqual(new bool[] { false, true, false, false, false, false, true, true }, col.ToArray()); 58 | } 59 | 60 | [Test] 61 | public void CreateNewDiscreteCollectionFromBytesParamsOrder2() 62 | { 63 | DiscreteCollection col = new DiscreteCollection(157, 7); 64 | Assert.AreEqual(new bool[] { true, false, true, true, true, false, false, true, true, true, true, false, false, false, false, false }, col.ToArray()); 65 | } 66 | 67 | [Test] 68 | public void Resize() 69 | { 70 | DiscreteCollection col = new DiscreteCollection(byte.MaxValue, byte.MaxValue); 71 | Assert.AreEqual(16, col.Count); 72 | col.RemoveAt(3); 73 | Assert.AreEqual(15, col.Count); 74 | } 75 | 76 | [Test] 77 | public void BytesPersistence() 78 | { 79 | DiscreteCollection col = new DiscreteCollection(byte.MaxValue, byte.MaxValue); 80 | Assert.AreEqual(16, col.Count); 81 | byte[] originalBytes = col.NetworkBytes; 82 | col.RemoveAt(3); 83 | Assert.AreEqual(15, col.Count); 84 | Assert.AreNotEqual(originalBytes, col.NetworkBytes); 85 | } 86 | 87 | [Test] 88 | public void AddCoil() 89 | { 90 | DiscreteCollection col = new DiscreteCollection(); 91 | Assert.AreEqual(0, col.Count); 92 | col.Add(true); 93 | Assert.AreEqual(1, col.Count); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Data/ModbusDataCollectionFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Data; 3 | using MbUnit.Framework; 4 | using System.Linq; 5 | 6 | namespace Modbus.UnitTests.Data 7 | { 8 | [TestFixture] 9 | public class ModbusDataCollectionFixture 10 | { 11 | [Test] 12 | public void FromReadOnlyList() 13 | { 14 | ModbusDataCollection col = new ModbusDataCollection(new bool[] { true, false }); 15 | Assert.AreEqual(3, col.Count); 16 | } 17 | 18 | [Test] 19 | public void ModbusDataCollection_FromParams() 20 | { 21 | ModbusDataCollection col = new ModbusDataCollection(true, false); 22 | Assert.AreEqual(3, col.Count); 23 | } 24 | 25 | [Test] 26 | public void Empty() 27 | { 28 | ModbusDataCollection col = new ModbusDataCollection(); 29 | Assert.AreEqual(1, col.Count); 30 | } 31 | 32 | [Test] 33 | public void AddDefaultBool() 34 | { 35 | ModbusDataCollection col = new ModbusDataCollection(true, true); 36 | Assert.AreEqual(3, col.Count); 37 | Assert.AreEqual(new bool[] { false, true, true }, col.ToArray()); 38 | } 39 | 40 | [Test] 41 | public void AddDefaultUshort() 42 | { 43 | ModbusDataCollection col = new ModbusDataCollection(1, 1); 44 | Assert.AreEqual(3, col.Count); 45 | Assert.AreEqual(new ushort[] { 0, 1, 1 }, col.ToArray()); 46 | } 47 | 48 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 49 | public void SetZeroElementUsingItem() 50 | { 51 | ModbusDataCollection col = new ModbusDataCollection(true, false); 52 | col[0] = true; 53 | } 54 | 55 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 56 | public void InsertZeroElement() 57 | { 58 | ModbusDataCollection col = new ModbusDataCollection(true, false); 59 | col.Insert(0, true); 60 | } 61 | 62 | [Test] 63 | public void Clear() 64 | { 65 | ModbusDataCollection col = new ModbusDataCollection(true, false); 66 | col.Clear(); 67 | Assert.AreEqual(1, col.Count); 68 | } 69 | 70 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 71 | public void RemoveAtZeroElement() 72 | { 73 | ModbusDataCollection col = new ModbusDataCollection(true, false); 74 | col.RemoveAt(0); 75 | } 76 | 77 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 78 | public void RemoveZeroElement() 79 | { 80 | ModbusDataCollection col = new ModbusDataCollection(); 81 | col.Remove(default(bool)); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Data/RegisterCollectionFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.UnitTests.Data 5 | { 6 | [TestFixture] 7 | public class RegisterCollectionFixture 8 | { 9 | [Test] 10 | public void ByteCount() 11 | { 12 | RegisterCollection col = new RegisterCollection(1, 2, 3); 13 | Assert.AreEqual(6, col.ByteCount); 14 | } 15 | 16 | [Test] 17 | public void NewRegisterCollection() 18 | { 19 | RegisterCollection col = new RegisterCollection(5, 3, 4, 6); 20 | Assert.IsNotNull(col); 21 | Assert.AreEqual(4, col.Count); 22 | Assert.AreEqual(5, col[0]); 23 | } 24 | 25 | [Test] 26 | public void NewRegisterCollectionFromBytes() 27 | { 28 | RegisterCollection col = new RegisterCollection(new byte[] { 0, 1, 0, 2, 0, 3 }); 29 | Assert.IsNotNull(col); 30 | Assert.AreEqual(3, col.Count); 31 | Assert.AreEqual(1, col[0]); 32 | Assert.AreEqual(2, col[1]); 33 | Assert.AreEqual(3, col[2]); 34 | } 35 | 36 | [Test] 37 | public void RegisterCollectionNetworkBytes() 38 | { 39 | RegisterCollection col = new RegisterCollection(5, 3, 4, 6); 40 | byte[] bytes = col.NetworkBytes; 41 | Assert.IsNotNull(bytes); 42 | Assert.AreEqual(8, bytes.Length); 43 | Assert.AreEqual(new byte[] { 0, 5, 0, 3, 0, 4, 0, 6 }, bytes); 44 | } 45 | 46 | [Test] 47 | public void RegisterCollectionEmpty() 48 | { 49 | RegisterCollection col = new RegisterCollection(); 50 | Assert.IsNotNull(col); 51 | Assert.AreEqual(0, col.NetworkBytes.Length); 52 | } 53 | 54 | [Test] 55 | public void ModifyRegister() 56 | { 57 | RegisterCollection col = new RegisterCollection(1, 2, 3, 4); 58 | col[0] = 5; 59 | } 60 | 61 | [Test] 62 | public void AddRegister() 63 | { 64 | RegisterCollection col = new RegisterCollection(); 65 | Assert.AreEqual(0, col.Count); 66 | col.Add(45); 67 | Assert.AreEqual(1, col.Count); 68 | } 69 | 70 | [Test] 71 | public void RemoveRegister() 72 | { 73 | RegisterCollection col = new RegisterCollection(3, 4, 5); 74 | Assert.AreEqual(3, col.Count); 75 | col.RemoveAt(2); 76 | Assert.AreEqual(2, col.Count); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Device/ModbusMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MbUnit.Framework; 3 | using Modbus.Device; 4 | using Modbus.IO; 5 | using Rhino.Mocks; 6 | using Unme.MbUnit.Framework.Extensions; 7 | using System.Linq; 8 | 9 | namespace Modbus.UnitTests.Device 10 | { 11 | [TestFixture] 12 | public class ModbusMasterFixture 13 | { 14 | [Test] 15 | public void ReadCoils() 16 | { 17 | var mockSerialResource = MockRepository.GenerateStub(); 18 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 19 | 20 | AssertUtility.Throws(() => master.ReadCoils(1, 1, 0)); 21 | AssertUtility.Throws(() => master.ReadCoils(1, 1, 2001)); 22 | } 23 | 24 | [Test] 25 | public void ReadInputs() 26 | { 27 | var mockSerialResource = MockRepository.GenerateStub(); 28 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 29 | 30 | AssertUtility.Throws(() => master.ReadInputs(1, 1, 0)); 31 | AssertUtility.Throws(() => master.ReadInputs(1, 1, 2001)); 32 | } 33 | 34 | [Test] 35 | public void ReadHoldingRegisters() 36 | { 37 | var mockSerialResource = MockRepository.GenerateStub(); 38 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 39 | 40 | AssertUtility.Throws(() => master.ReadHoldingRegisters(1, 1, 0)); 41 | AssertUtility.Throws(() => master.ReadHoldingRegisters(1, 1, 126)); 42 | } 43 | 44 | [Test] 45 | public void ReadInputRegisters() 46 | { 47 | var mockSerialResource = MockRepository.GenerateStub(); 48 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 49 | 50 | AssertUtility.Throws(() => master.ReadInputRegisters(1, 1, 0)); 51 | AssertUtility.Throws(() => master.ReadInputRegisters(1, 1, 126)); 52 | } 53 | 54 | [Test] 55 | public void WriteMultipleRegisters() 56 | { 57 | var mockSerialResource = MockRepository.GenerateStub(); 58 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 59 | 60 | AssertUtility.Throws(() => master.WriteMultipleRegisters(1, 1, null)); 61 | AssertUtility.Throws(() => master.WriteMultipleRegisters(1, 1, new ushort[] { })); 62 | AssertUtility.Throws(() => master.WriteMultipleRegisters(1, 1, Enumerable.Repeat(1, 124).ToArray())); 63 | } 64 | 65 | [Test] 66 | public void WriteMultipleCoils() 67 | { 68 | var mockSerialResource = MockRepository.GenerateStub(); 69 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 70 | 71 | AssertUtility.Throws(() => master.WriteMultipleCoils(1, 1, null)); 72 | AssertUtility.Throws(() => master.WriteMultipleCoils(1, 1, new bool[] { })); 73 | AssertUtility.Throws(() => master.WriteMultipleCoils(1, 1, Enumerable.Repeat(false, 1969).ToArray())); 74 | } 75 | 76 | [Test] 77 | public void ReadWriteMultipleRegisters() 78 | { 79 | var mockSerialResource = MockRepository.GenerateStub(); 80 | var master = ModbusSerialMaster.CreateRtu(mockSerialResource); 81 | 82 | // validate numberOfPointsToRead 83 | AssertUtility.Throws(() => master.ReadWriteMultipleRegisters(1, 1, 0, 1, new ushort[] { 1 })); 84 | AssertUtility.Throws(() => master.ReadWriteMultipleRegisters(1, 1, 126, 1, new ushort[] { 1 })); 85 | 86 | // validate writeData 87 | AssertUtility.Throws(() => master.ReadWriteMultipleRegisters(1, 1, 1, 1, null)); 88 | AssertUtility.Throws(() => master.ReadWriteMultipleRegisters(1, 1, 1, 1, new ushort[] { })); 89 | AssertUtility.Throws(() => master.ReadWriteMultipleRegisters(1, 1, 1, 1, Enumerable.Repeat(1, 122).ToArray())); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Device/ModbusSerialMasterFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO.Ports; 3 | using Modbus.Device; 4 | using Modbus.IO; 5 | using MbUnit.Framework; 6 | using Rhino.Mocks; 7 | 8 | namespace Modbus.UnitTests.Device 9 | { 10 | [TestFixture] 11 | public class ModbusSerialMasterFixture 12 | { 13 | [Test] 14 | public void CreateRtu_SerialPortFactoryMethod() 15 | { 16 | IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(new SerialPort()); 17 | 18 | Assert.AreEqual(Modbus.DefaultTimeout, master.Transport.StreamResource.ReadTimeout); 19 | } 20 | 21 | [Test] 22 | public void CreateRtu_UsbPortFactoryMethod() 23 | { 24 | MockRepository mocks = new MockRepository(); 25 | IStreamResource mockStreamResource = mocks.StrictMock(); 26 | 27 | Expect.Call(mockStreamResource.WriteTimeout).Return(0); 28 | Expect.Call(mockStreamResource.InfiniteTimeout).Return(0); 29 | mockStreamResource.WriteTimeout = Modbus.DefaultTimeout; 30 | Expect.Call(mockStreamResource.ReadTimeout).Return(0); 31 | Expect.Call(mockStreamResource.InfiniteTimeout).Return(0); 32 | mockStreamResource.ReadTimeout = Modbus.DefaultTimeout; 33 | 34 | mocks.ReplayAll(); 35 | var master = ModbusSerialMaster.CreateRtu(mockStreamResource); 36 | mocks.VerifyAll(); 37 | } 38 | 39 | [Test] 40 | public void CreateAscii_SerialPortFactoryMethod() 41 | { 42 | IModbusSerialMaster master = ModbusSerialMaster.CreateAscii(new SerialPort()); 43 | 44 | Assert.AreEqual(Modbus.DefaultTimeout, master.Transport.StreamResource.ReadTimeout); 45 | Assert.AreEqual(Modbus.DefaultTimeout, master.Transport.StreamResource.ReadTimeout); 46 | } 47 | 48 | [Test] 49 | public void CreateAscii_UsbPortFactoryMethod() 50 | { 51 | MockRepository mocks = new MockRepository(); 52 | IStreamResource mockSerialResource = mocks.StrictMock(); 53 | 54 | Expect.Call(mockSerialResource.WriteTimeout).Return(0); 55 | Expect.Call(mockSerialResource.InfiniteTimeout).Return(0); 56 | mockSerialResource.WriteTimeout = Modbus.DefaultTimeout; 57 | Expect.Call(mockSerialResource.ReadTimeout).Return(0); 58 | Expect.Call(mockSerialResource.InfiniteTimeout).Return(0); 59 | mockSerialResource.ReadTimeout = Modbus.DefaultTimeout; 60 | 61 | mocks.ReplayAll(); 62 | ModbusSerialMaster.CreateAscii(mockSerialResource); 63 | mocks.VerifyAll(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Device/TcpConnectionEventArgsFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Device; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Device 6 | { 7 | [TestFixture] 8 | public class TcpConnectionEventArgsFixture 9 | { 10 | [Test, ExpectedArgumentNullException] 11 | public void TcpConnectionEventArgs_NullEndPoint() 12 | { 13 | new TcpConnectionEventArgs(null); 14 | } 15 | 16 | [Test, ExpectedArgumentException] 17 | public void TcpConnectionEventArgs_EmptyEndPoint() 18 | { 19 | new TcpConnectionEventArgs(String.Empty); 20 | } 21 | 22 | [Test] 23 | public void TcpConnectionEventArgs() 24 | { 25 | var args = new TcpConnectionEventArgs("foo"); 26 | 27 | Assert.AreEqual("foo", args.EndPoint); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/IO/AbstractStreamResourceFixture.cs: -------------------------------------------------------------------------------- 1 | using MbUnit.Framework; 2 | using Rhino.Mocks; 3 | using Modbus.IO; 4 | using System.IO.Ports; 5 | 6 | namespace Modbus.UnitTests.IO 7 | { 8 | [TestFixture] 9 | public class AbstractStreamResourceFixture 10 | { 11 | [Test] 12 | public void InitializeSerialPortTimeouts() 13 | { 14 | MockRepository mocks = new MockRepository(); 15 | IStreamResource mockStreamResource = mocks.StrictMock(); 16 | 17 | Expect.Call(mockStreamResource.WriteTimeout).Return(1); 18 | Expect.Call(mockStreamResource.InfiniteTimeout).Return(0); 19 | Expect.Call(mockStreamResource.WriteTimeout).Return(1); 20 | mockStreamResource.WriteTimeout = 1; 21 | Expect.Call(mockStreamResource.ReadTimeout).Return(1); 22 | Expect.Call(mockStreamResource.InfiniteTimeout).Return(0); 23 | Expect.Call(mockStreamResource.ReadTimeout).Return(1); 24 | mockStreamResource.ReadTimeout = 1; 25 | 26 | mocks.ReplayAll(); 27 | StreamResourceUtility.InitializeDefaultTimeouts(mockStreamResource); 28 | mocks.VerifyAll(); 29 | } 30 | 31 | [Test] 32 | public void SetupTimeoutsDefaultTimeout() 33 | { 34 | MockRepository mocks = new MockRepository(); 35 | IStreamResource mockStreamResource = mocks.StrictMock(); 36 | 37 | Expect.Call(mockStreamResource.WriteTimeout).Return(SerialPort.InfiniteTimeout); 38 | Expect.Call(mockStreamResource.InfiniteTimeout).Return(SerialPort.InfiniteTimeout); 39 | mockStreamResource.WriteTimeout = Modbus.DefaultTimeout; 40 | Expect.Call(mockStreamResource.ReadTimeout).Return(SerialPort.InfiniteTimeout); 41 | Expect.Call(mockStreamResource.InfiniteTimeout).Return(SerialPort.InfiniteTimeout); 42 | mockStreamResource.ReadTimeout = Modbus.DefaultTimeout; 43 | 44 | mocks.ReplayAll(); 45 | StreamResourceUtility.InitializeDefaultTimeouts(mockStreamResource); 46 | mocks.VerifyAll(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/IO/ModbusSerialTransportFixture.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Modbus.Data; 3 | using Modbus.IO; 4 | using Modbus.Message; 5 | using Modbus.UnitTests.Message; 6 | using Modbus.Utility; 7 | using MbUnit.Framework; 8 | using Rhino.Mocks; 9 | using System; 10 | 11 | namespace Modbus.UnitTests.IO 12 | { 13 | [TestFixture] 14 | public class ModbusSerialTransportFixture : ModbusMessageFixture 15 | { 16 | [Test] 17 | public void CreateResponse() 18 | { 19 | ModbusAsciiTransport transport = new ModbusAsciiTransport(MockRepository.GenerateStub()); 20 | ReadCoilsInputsResponse expectedResponse = new ReadCoilsInputsResponse(Modbus.ReadCoils, 2, 1, new DiscreteCollection(true, false, false, false, false, false, false, true)); 21 | byte lrc = ModbusUtility.CalculateLrc(expectedResponse.MessageFrame); 22 | ReadCoilsInputsResponse response = transport.CreateResponse(new byte[] { 2, Modbus.ReadCoils, 1, 129, lrc }) as ReadCoilsInputsResponse; 23 | Assert.IsNotNull(response); 24 | AssertModbusMessagePropertiesAreEqual(expectedResponse, response); 25 | } 26 | 27 | [Test, ExpectedException(typeof(IOException))] 28 | public void CreateResponseErroneousLrc() 29 | { 30 | ModbusAsciiTransport transport = new ModbusAsciiTransport(MockRepository.GenerateStub()); 31 | transport.CheckFrame = true; 32 | transport.CreateResponse(new byte[] { 19, Modbus.ReadCoils, 0, 0, 0, 2, 115 }); 33 | } 34 | 35 | [Test] 36 | public void CreateResponseErroneousLrcDoNotCheckFrame() 37 | { 38 | ModbusAsciiTransport transport = new ModbusAsciiTransport(MockRepository.GenerateStub()); 39 | transport.CheckFrame = false; 40 | transport.CreateResponse(new byte[] { 19, Modbus.ReadCoils, 0, 0, 0, 2, 115 }); 41 | } 42 | 43 | /// 44 | /// When using the serial RTU protocol the beginning of the message could get mangled leading to an unsupported message type. 45 | /// We want to be sure to try the message again so clear the RX buffer and try again. 46 | /// 47 | [Test] 48 | public void UnicastMessage_PurgeReceiveBuffer() 49 | { 50 | MockRepository mocks = new MockRepository(); 51 | IStreamResource serialResource = mocks.StrictMock(); 52 | ModbusSerialTransport transport = new ModbusRtuTransport(serialResource); 53 | 54 | serialResource.DiscardInBuffer(); 55 | serialResource.Write(null, 0, 0); 56 | LastCall.IgnoreArguments(); 57 | 58 | // mangled response 59 | Expect.Call(serialResource.Read(new byte[] { 0, 0, 0, 0 }, 0, 4)).Return(4); 60 | 61 | serialResource.DiscardInBuffer(); 62 | serialResource.Write(null, 0, 0); 63 | LastCall.IgnoreArguments(); 64 | 65 | // normal response 66 | ReadCoilsInputsResponse response = new ReadCoilsInputsResponse(Modbus.ReadCoils, 2, 1, new DiscreteCollection(true, false, true, false, false, false, false, false)); 67 | 68 | // read header 69 | Expect.Call(serialResource.Read(new byte[] { 0, 0, 0, 0 }, 0, 4)).Do(((Func) delegate(byte[] buf, int offset, int count) 70 | { 71 | Array.Copy(response.MessageFrame, 0, buf, 0, 4); 72 | return 4; 73 | })); 74 | 75 | // read remainder 76 | Expect.Call(serialResource.Read(new byte[] { 0, 0 }, 0, 2)).Do(((Func) delegate(byte[] buf, int offset, int count) 77 | { 78 | Array.Copy(ModbusUtility.CalculateCrc(response.MessageFrame), 0, buf, 0, 2); 79 | return 2; 80 | })); 81 | 82 | mocks.ReplayAll(); 83 | 84 | ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 2, 3, 4); 85 | transport.UnicastMessage(request); 86 | 87 | mocks.VerifyAll(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/IO/UdpClientAdapterFixture.cs: -------------------------------------------------------------------------------- 1 | using MbUnit.Framework; 2 | using Modbus.IO; 3 | using System.Net.Sockets; 4 | using Rhino.Mocks; 5 | using System.Net; 6 | using Unme.MbUnit.Framework.Extensions; 7 | using System; 8 | using System.IO; 9 | 10 | namespace Modbus.UnitTests.IO 11 | { 12 | [TestFixture] 13 | public class UdpClientAdapterFixture 14 | { 15 | [Test] 16 | public void Read_ArgumentValidation() 17 | { 18 | var adapter = new UdpClientAdapter(new UdpClient()); 19 | 20 | // buffer 21 | AssertUtility.Throws(() => adapter.Read(null, 1, 1)); 22 | 23 | // offset 24 | AssertUtility.Throws(() => adapter.Read(new byte[2], -1, 2)); 25 | AssertUtility.Throws(() => adapter.Read(new byte[2], 3, 3)); 26 | 27 | AssertUtility.Throws(() => adapter.Read(new byte[2], 0, -1)); 28 | AssertUtility.Throws(() => adapter.Read(new byte[2], 1, 2)); 29 | } 30 | 31 | [Test, ExpectedException(typeof(IOException))] 32 | public void Read_NotEnoughInBuffer() 33 | { 34 | var mocks = new MockRepository(); 35 | var adapter = mocks.PartialMock(new UdpClient()); 36 | 37 | IPEndPoint endPoint = null; 38 | Expect.Call(adapter.Read(ref endPoint)) 39 | .Return(new byte[] { 1, 2, 3, 4, 5 }); 40 | 41 | mocks.ReplayAll(); 42 | 43 | var buffer = new byte[5]; 44 | 45 | // read first part of message 46 | Assert.AreEqual(4, adapter.Read(buffer, 0, 4)); 47 | 48 | // read remainder... not enough in buffer 49 | Assert.AreEqual(2, adapter.Read(buffer, 3, 2)); 50 | } 51 | 52 | [Test] 53 | public void Read_SingleMessageInTwoParts() 54 | { 55 | var mocks = new MockRepository(); 56 | var adapter = mocks.PartialMock(new UdpClient()); 57 | 58 | IPEndPoint endPoint = null; 59 | Expect.Call(adapter.Read(ref endPoint)) 60 | .Return(new byte[] { 1, 2, 3, 4, 5 }); 61 | 62 | mocks.ReplayAll(); 63 | 64 | var buffer = new byte[5]; 65 | 66 | // read first part of message 67 | Assert.AreEqual(3, adapter.Read(buffer, 0, 3)); 68 | 69 | // read remainder 70 | Assert.AreEqual(2, adapter.Read(buffer, 3, 2)); 71 | 72 | Assert.AreEqual(new byte[] { 1, 2, 3, 4, 5 }, buffer); 73 | 74 | mocks.VerifyAll(); 75 | } 76 | 77 | [Test] 78 | public void Read_TwoMessages() 79 | { 80 | var mocks = new MockRepository(); 81 | var adapter = mocks.PartialMock(new UdpClient()); 82 | 83 | IPEndPoint endPoint = null; 84 | 85 | // first datagram 86 | Expect.Call(adapter.Read(ref endPoint)) 87 | .Return(new byte[] { 1 }); 88 | 89 | // second datagram 90 | Expect.Call(adapter.Read(ref endPoint)) 91 | .Return(new byte[] { 2, 3, 4 }); 92 | 93 | mocks.ReplayAll(); 94 | 95 | // read first datagram 96 | var buffer = new byte[1]; 97 | Assert.AreEqual(1, adapter.Read(buffer, 0, 1)); 98 | 99 | // read second datagram 100 | buffer = new byte[3]; 101 | Assert.AreEqual(3, adapter.Read(buffer, 0, 3)); 102 | 103 | Assert.AreEqual(new byte[] { 2, 3, 4 }, buffer); 104 | 105 | mocks.VerifyAll(); 106 | } 107 | 108 | [Test] 109 | public void Write_ArgumentValidation() 110 | { 111 | var adapter = new UdpClientAdapter(new UdpClient()); 112 | 113 | // buffer 114 | AssertUtility.Throws(() => adapter.Write(null, 1, 1)); 115 | 116 | // offset 117 | AssertUtility.Throws(() => adapter.Write(new byte[2], -1, 2)); 118 | AssertUtility.Throws(() => adapter.Write(new byte[2], 3, 3)); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/DiagnosticsRequestResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Message; 2 | using MbUnit.Framework; 3 | using Modbus.Data; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class DiagnosticsRequestResponseFixture 9 | { 10 | [Test] 11 | public void ToString_Test() 12 | { 13 | var message = new DiagnosticsRequestResponse(Modbus.DiagnosticsReturnQueryData, 3, new RegisterCollection(5)); 14 | 15 | Assert.AreEqual("Diagnostics message, sub-function return query data - {5}.", message.ToString()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/MessageUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Modbus.UnitTests.Message 7 | { 8 | public static class MessageUtility 9 | { 10 | /// 11 | /// Creates a collection initialized to a default value. 12 | /// 13 | public static T CreateDefaultCollection(V defaultValue, int size) where T : ICollection, new() 14 | { 15 | if (size < 0) 16 | throw new ArgumentOutOfRangeException("Collection size cannot be less than 0."); 17 | 18 | T col = new T(); 19 | 20 | for (int i = 0; i < size; i++) 21 | col.Add(defaultValue); 22 | 23 | return col; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ModbusMessageFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Modbus.Message; 6 | using MbUnit.Framework; 7 | 8 | namespace Modbus.UnitTests.Message 9 | { 10 | [TestFixture] 11 | public class ModbusMessageFixture 12 | { 13 | [Test] 14 | public void ProtocolDataUnitReadCoilsRequest() 15 | { 16 | ModbusMessage message = new ReadCoilsInputsRequest(Modbus.ReadCoils, 1, 100, 9); 17 | byte[] expectedResult = { Modbus.ReadCoils, 0, 100, 0, 9 }; 18 | Assert.AreEqual(expectedResult, message.ProtocolDataUnit); 19 | } 20 | 21 | [Test] 22 | public void MessageFrameReadCoilsRequest() 23 | { 24 | ModbusMessage message = new ReadCoilsInputsRequest(Modbus.ReadCoils, 1, 2, 3); 25 | byte[] expectedMessageFrame = { 1, Modbus.ReadCoils, 0, 2, 0, 3 }; 26 | Assert.AreEqual(expectedMessageFrame, message.MessageFrame); 27 | } 28 | 29 | [Test] 30 | public void ModbusMessageToStringOverriden() 31 | { 32 | var messageTypes = from message in typeof(ModbusMessage).Assembly.GetTypes() 33 | where !message.IsAbstract && message.IsSubclassOf(typeof(ModbusMessage)) 34 | select message; 35 | 36 | foreach (Type messageType in messageTypes) 37 | Assert.IsNotNull(messageType.GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), 38 | String.Concat("No ToString override in message ", messageType.FullName)); 39 | } 40 | 41 | internal static void AssertModbusMessagePropertiesAreEqual(IModbusMessage obj1, IModbusMessage obj2) 42 | { 43 | Assert.AreEqual(obj1.FunctionCode, obj2.FunctionCode); 44 | Assert.AreEqual(obj1.SlaveAddress, obj2.SlaveAddress); 45 | Assert.AreEqual(obj1.MessageFrame, obj2.MessageFrame); 46 | Assert.AreEqual(obj1.ProtocolDataUnit, obj2.ProtocolDataUnit); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ModbusMessageImplFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ModbusMessageImplFixture 9 | { 10 | [Test] 11 | public void ModbusMessageCtorInitializesProperties() 12 | { 13 | ModbusMessageImpl messageImpl = new ModbusMessageImpl(5, Modbus.ReadCoils); 14 | Assert.AreEqual(5, messageImpl.SlaveAddress); 15 | Assert.AreEqual(Modbus.ReadCoils, messageImpl.FunctionCode); 16 | } 17 | 18 | [Test] 19 | public void Initialize() 20 | { 21 | ModbusMessageImpl messageImpl = new ModbusMessageImpl(); 22 | messageImpl.Initialize(new byte[] { 1, 2, 9, 9, 9, 9 }); 23 | Assert.AreEqual(1, messageImpl.SlaveAddress); 24 | Assert.AreEqual(2, messageImpl.FunctionCode); 25 | } 26 | 27 | [Test, ExpectedArgumentNullException] 28 | public void ChecckInitializeFrameNull() 29 | { 30 | ModbusMessageImpl messageImpl = new ModbusMessageImpl(); 31 | messageImpl.Initialize(null); 32 | } 33 | 34 | [Test] 35 | [ExpectedException(typeof(FormatException))] 36 | public void InitializeInvalidFrame() 37 | { 38 | ModbusMessageImpl messageImpl = new ModbusMessageImpl(); 39 | messageImpl.Initialize(new byte[] { 1 }); 40 | } 41 | 42 | [Test] 43 | public void ProtocolDataUnit() 44 | { 45 | ModbusMessageImpl messageImpl = new ModbusMessageImpl(11, Modbus.ReadCoils); 46 | byte[] expectedResult = { Modbus.ReadCoils }; 47 | Assert.AreEqual(expectedResult, messageImpl.ProtocolDataUnit); 48 | } 49 | 50 | [Test] 51 | public void MessageFrame() 52 | { 53 | ModbusMessageImpl messageImpl = new ModbusMessageImpl(11, Modbus.ReadHoldingRegisters); 54 | byte[] expectedMessageFrame = { 11, Modbus.ReadHoldingRegisters }; 55 | Assert.AreEqual(expectedMessageFrame, messageImpl.MessageFrame); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ModbusMessageWithDataFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ModbusMessageWithDataFixture 9 | { 10 | [Test] 11 | public void ModbusMessageWithDataFixtureCtorInitializesProperties() 12 | { 13 | ModbusMessageWithData message = new ReadCoilsInputsResponse(Modbus.ReadCoils, 10, 1, new DiscreteCollection(true, false, true)); 14 | Assert.AreEqual(Modbus.ReadCoils, message.FunctionCode); 15 | Assert.AreEqual(10, message.SlaveAddress); 16 | } 17 | 18 | [Test] 19 | public void ProtocolDataUnitReadCoilsResponse() 20 | { 21 | ModbusMessageWithData message = new ReadCoilsInputsResponse(Modbus.ReadCoils, 1, 2, new DiscreteCollection(true)); 22 | byte[] expectedResult = { 1, 2, 1 }; 23 | Assert.AreEqual(expectedResult, message.ProtocolDataUnit); 24 | } 25 | 26 | [Test] 27 | public void DataReadCoilsResponse() 28 | { 29 | DiscreteCollection col = new DiscreteCollection(false, true, false, true, false, true, false, false, false, false); 30 | ModbusMessageWithData message = new ReadCoilsInputsResponse(Modbus.ReadCoils, 11, 1, col); 31 | Assert.AreEqual(col.Count, message.Data.Count); 32 | Assert.AreEqual(col.NetworkBytes, message.Data.NetworkBytes); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ReadCoilsInputsRequestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ReadCoilsInputsRequestFixture 9 | { 10 | [Test] 11 | public void CreateReadCoilsRequest() 12 | { 13 | ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 5, 1, 10); 14 | Assert.AreEqual(Modbus.ReadCoils, request.FunctionCode); 15 | Assert.AreEqual(5, request.SlaveAddress); 16 | Assert.AreEqual(1, request.StartAddress); 17 | Assert.AreEqual(10, request.NumberOfPoints); 18 | } 19 | 20 | [Test] 21 | public void CreateReadInputsRequest() 22 | { 23 | ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadInputs, 5, 1, 10); 24 | Assert.AreEqual(Modbus.ReadInputs, request.FunctionCode); 25 | Assert.AreEqual(5, request.SlaveAddress); 26 | Assert.AreEqual(1, request.StartAddress); 27 | Assert.AreEqual(10, request.NumberOfPoints); 28 | } 29 | 30 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 31 | public void CreateReadCoilsInputsRequestTooMuchData() 32 | { 33 | new ReadCoilsInputsRequest(Modbus.ReadCoils, 1, 2, Modbus.MaximumDiscreteRequestResponseSize + 1); 34 | } 35 | 36 | [Test] 37 | public void CreateReadCoilsInputsRequestMaxSize() 38 | { 39 | ReadCoilsInputsRequest response = new ReadCoilsInputsRequest(Modbus.ReadCoils, 1, 2, Modbus.MaximumDiscreteRequestResponseSize); 40 | Assert.AreEqual(Modbus.MaximumDiscreteRequestResponseSize, response.NumberOfPoints); 41 | } 42 | 43 | [Test] 44 | public void ToString_ReadCoilsRequest() 45 | { 46 | ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 5, 1, 10); 47 | 48 | Assert.AreEqual("Read 10 coils starting at address 1.", request.ToString()); 49 | } 50 | 51 | [Test] 52 | public void ToString_ReadInputsRequest() 53 | { 54 | ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadInputs, 5, 1, 10); 55 | 56 | Assert.AreEqual("Read 10 inputs starting at address 1.", request.ToString()); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ReadCoilsInputsResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ReadCoilsResponseFixture 9 | { 10 | [Test] 11 | public void CreateReadCoilsResponse() 12 | { 13 | ReadCoilsInputsResponse response = new ReadCoilsInputsResponse(Modbus.ReadCoils, 5, 2, new DiscreteCollection(true, true, true, true, true, true, false, false, true, true, false)); 14 | Assert.AreEqual(Modbus.ReadCoils, response.FunctionCode); 15 | Assert.AreEqual(5, response.SlaveAddress); 16 | Assert.AreEqual(2, response.ByteCount); 17 | DiscreteCollection col = new DiscreteCollection(true, true, true, true, true, true, false, false, true, true, false); 18 | Assert.AreEqual(col.NetworkBytes, response.Data.NetworkBytes); 19 | } 20 | 21 | [Test] 22 | public void CreateReadInputsResponse() 23 | { 24 | ReadCoilsInputsResponse response = new ReadCoilsInputsResponse(Modbus.ReadInputs, 5, 2, new DiscreteCollection(true, true, true, true, true, true, false, false, true, true, false)); 25 | Assert.AreEqual(Modbus.ReadInputs, response.FunctionCode); 26 | Assert.AreEqual(5, response.SlaveAddress); 27 | Assert.AreEqual(2, response.ByteCount); 28 | DiscreteCollection col = new DiscreteCollection(true, true, true, true, true, true, false, false, true, true, false); 29 | Assert.AreEqual(col.NetworkBytes, response.Data.NetworkBytes); 30 | } 31 | 32 | [Test] 33 | public void ToString_Coils() 34 | { 35 | ReadCoilsInputsResponse response = new ReadCoilsInputsResponse(Modbus.ReadCoils, 5, 2, new DiscreteCollection(true, true, true, true, true, true, false, false, true, true, false)); 36 | 37 | Assert.AreEqual("Read 11 coils - {1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0}.", response.ToString()); 38 | } 39 | 40 | [Test] 41 | public void ToString_Inputs() 42 | { 43 | ReadCoilsInputsResponse response = new ReadCoilsInputsResponse(Modbus.ReadInputs, 5, 2, new DiscreteCollection(true, true, true, true, true, true, false, false, true, true, false)); 44 | 45 | Assert.AreEqual("Read 11 inputs - {1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0}.", response.ToString()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ReadHoldingInputRegistersRequestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ReadHoldingInputRegistersRequestFixture 9 | { 10 | [Test] 11 | public void CreateReadHoldingRegistersRequest() 12 | { 13 | ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 5, 1, 10); 14 | Assert.AreEqual(Modbus.ReadHoldingRegisters, request.FunctionCode); 15 | Assert.AreEqual(5, request.SlaveAddress); 16 | Assert.AreEqual(1, request.StartAddress); 17 | Assert.AreEqual(10, request.NumberOfPoints); 18 | } 19 | 20 | [Test] 21 | public void CreateReadInputRegistersRequest() 22 | { 23 | ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadInputRegisters, 5, 1, 10); 24 | Assert.AreEqual(Modbus.ReadInputRegisters, request.FunctionCode); 25 | Assert.AreEqual(5, request.SlaveAddress); 26 | Assert.AreEqual(1, request.StartAddress); 27 | Assert.AreEqual(10, request.NumberOfPoints); 28 | } 29 | 30 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 31 | public void CreateReadHoldingInputRegistersRequestTooMuchData() 32 | { 33 | new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 1, 2, Modbus.MaximumRegisterRequestResponseSize + 1); 34 | } 35 | 36 | [Test] 37 | public void CreateReadHoldingInputRegistersRequestMaxSize() 38 | { 39 | ReadHoldingInputRegistersRequest response = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 1, 2, Modbus.MaximumRegisterRequestResponseSize); 40 | Assert.AreEqual(Modbus.MaximumRegisterRequestResponseSize, response.NumberOfPoints); 41 | } 42 | 43 | [Test] 44 | public void ToString_ReadHoldingRegistersRequest() 45 | { 46 | ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 5, 1, 10); 47 | 48 | Assert.AreEqual("Read 10 holding registers starting at address 1.", request.ToString()); 49 | } 50 | 51 | [Test] 52 | public void ToString_ReadInputRegistersRequest() 53 | { 54 | ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadInputRegisters, 5, 1, 10); 55 | 56 | Assert.AreEqual("Read 10 input registers starting at address 1.", request.ToString()); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ReadHoldingInputRegistersResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | using System; 5 | 6 | namespace Modbus.UnitTests.Message 7 | { 8 | [TestFixture] 9 | public class ReadHoldingInputRegistersResponseFixture 10 | { 11 | [Test, ExpectedArgumentNullException] 12 | public void ReadHoldingInputRegistersResponse_NullData() 13 | { 14 | new ReadHoldingInputRegistersResponse(0, 0, null); 15 | } 16 | 17 | [Test] 18 | public void ReadHoldingRegistersResponse() 19 | { 20 | ReadHoldingInputRegistersResponse response = new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 5, new RegisterCollection(1, 2)); 21 | Assert.AreEqual(Modbus.ReadHoldingRegisters, response.FunctionCode); 22 | Assert.AreEqual(5, response.SlaveAddress); 23 | Assert.AreEqual(4, response.ByteCount); 24 | RegisterCollection col = new RegisterCollection(1, 2); 25 | Assert.AreEqual(col.NetworkBytes, response.Data.NetworkBytes); 26 | } 27 | 28 | [Test] 29 | public void ToString_ReadHoldingRegistersResponse() 30 | { 31 | ReadHoldingInputRegistersResponse response = new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1)); 32 | Assert.AreEqual("Read 1 holding registers.", response.ToString()); 33 | } 34 | 35 | [Test] 36 | public void ReadInputRegistersResponse() 37 | { 38 | ReadHoldingInputRegistersResponse response = new ReadHoldingInputRegistersResponse(Modbus.ReadInputRegisters, 5, new RegisterCollection(1, 2)); 39 | Assert.AreEqual(Modbus.ReadInputRegisters, response.FunctionCode); 40 | Assert.AreEqual(5, response.SlaveAddress); 41 | Assert.AreEqual(4, response.ByteCount); 42 | RegisterCollection col = new RegisterCollection(1, 2); 43 | Assert.AreEqual(col.NetworkBytes, response.Data.NetworkBytes); 44 | } 45 | 46 | [Test] 47 | public void ToString_ReadInputRegistersResponse() 48 | { 49 | ReadHoldingInputRegistersResponse response = new ReadHoldingInputRegistersResponse(Modbus.ReadInputRegisters, 1, new RegisterCollection(1)); 50 | Assert.AreEqual("Read 1 input registers.", response.ToString()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ReadWriteMultipleRegistersRequestFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ReadWriteMultipleRegistersRequestFixture 9 | { 10 | [Test] 11 | public void ReadWriteMultipleRegistersRequest() 12 | { 13 | RegisterCollection writeCollection = new RegisterCollection(255, 255, 255); 14 | ReadWriteMultipleRegistersRequest request = new ReadWriteMultipleRegistersRequest(5, 3, 6, 14, writeCollection); 15 | Assert.AreEqual(Modbus.ReadWriteMultipleRegisters, request.FunctionCode); 16 | Assert.AreEqual(5, request.SlaveAddress); 17 | 18 | // test read 19 | Assert.IsNotNull(request.ReadRequest); 20 | Assert.AreEqual(request.SlaveAddress, request.ReadRequest.SlaveAddress); 21 | Assert.AreEqual(3, request.ReadRequest.StartAddress); 22 | Assert.AreEqual(6, request.ReadRequest.NumberOfPoints); 23 | 24 | // test write 25 | Assert.IsNotNull(request.WriteRequest); 26 | Assert.AreEqual(request.SlaveAddress, request.WriteRequest.SlaveAddress); 27 | Assert.AreEqual(14, request.WriteRequest.StartAddress); 28 | Assert.AreEqual(writeCollection.NetworkBytes, request.WriteRequest.Data.NetworkBytes); 29 | } 30 | 31 | [Test] 32 | public void ProtocolDataUnit() 33 | { 34 | RegisterCollection writeCollection = new RegisterCollection(255, 255, 255); 35 | ReadWriteMultipleRegistersRequest request = new ReadWriteMultipleRegistersRequest(5, 3, 6, 14, writeCollection); 36 | byte[] pdu = { 0x17, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x03, 0x06, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }; 37 | Assert.AreEqual(pdu, request.ProtocolDataUnit); 38 | } 39 | 40 | [Test] 41 | public void ToString_ReadWriteMultipleRegistersRequest() 42 | { 43 | RegisterCollection writeCollection = new RegisterCollection(255, 255, 255); 44 | ReadWriteMultipleRegistersRequest request = new ReadWriteMultipleRegistersRequest(5, 3, 6, 14, writeCollection); 45 | 46 | Assert.AreEqual("Write 3 holding registers starting at address 14, and read 6 registers starting at address 3.", request.ToString()); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/ReturnQueryDataRequestResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class ReturnQueryDataRequestResponseFixture 9 | { 10 | [Test] 11 | public void ReturnQueryDataRequestResponse() 12 | { 13 | RegisterCollection data = new RegisterCollection(1, 2, 3, 4); 14 | DiagnosticsRequestResponse request = new DiagnosticsRequestResponse(Modbus.DiagnosticsReturnQueryData, 5, data); 15 | Assert.AreEqual(Modbus.Diagnostics, request.FunctionCode); 16 | Assert.AreEqual(Modbus.DiagnosticsReturnQueryData, request.SubFunctionCode); 17 | Assert.AreEqual(5, request.SlaveAddress); 18 | Assert.AreEqual(data.NetworkBytes, request.Data.NetworkBytes); 19 | } 20 | 21 | [Test] 22 | public void ProtocolDataUnit() 23 | { 24 | RegisterCollection data = new RegisterCollection(1, 2, 3, 4); 25 | DiagnosticsRequestResponse request = new DiagnosticsRequestResponse(Modbus.DiagnosticsReturnQueryData, 5, data); 26 | Assert.AreEqual(new byte[] { 8, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4 }, request.ProtocolDataUnit); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/SlaveExceptionResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Message; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.UnitTests.Message 5 | { 6 | [TestFixture] 7 | public class SlaveExceptionResponseFixture 8 | { 9 | [Test] 10 | public void CreateSlaveExceptionResponse() 11 | { 12 | SlaveExceptionResponse response = new SlaveExceptionResponse(11, Modbus.ReadCoils + Modbus.ExceptionOffset, 2); 13 | Assert.AreEqual(11, response.SlaveAddress); 14 | Assert.AreEqual(Modbus.ReadCoils + Modbus.ExceptionOffset, response.FunctionCode); 15 | Assert.AreEqual(2, response.SlaveExceptionCode); 16 | } 17 | 18 | [Test] 19 | public void SlaveExceptionResponsePDU() 20 | { 21 | SlaveExceptionResponse response = new SlaveExceptionResponse(11, Modbus.ReadCoils + Modbus.ExceptionOffset, 2); 22 | Assert.AreEqual(new byte[] { response.FunctionCode, response.SlaveExceptionCode }, response.ProtocolDataUnit); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/WriteMultipleCoilsRequestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Data; 3 | using Modbus.Message; 4 | using Modbus.Utility; 5 | using MbUnit.Framework; 6 | 7 | namespace Modbus.UnitTests.Message 8 | { 9 | [TestFixture] 10 | public class WriteMultipleCoilsRequestFixture 11 | { 12 | [Test] 13 | public void CreateWriteMultipleCoilsRequest() 14 | { 15 | DiscreteCollection col = new DiscreteCollection(true, false, true, false, true, true, true, false, false); 16 | WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(34, 45, col); 17 | Assert.AreEqual(Modbus.WriteMultipleCoils, request.FunctionCode); 18 | Assert.AreEqual(34, request.SlaveAddress); 19 | Assert.AreEqual(45, request.StartAddress); 20 | Assert.AreEqual(9, request.NumberOfPoints); 21 | Assert.AreEqual(2, request.ByteCount); 22 | Assert.AreEqual(col.NetworkBytes, request.Data.NetworkBytes); 23 | } 24 | 25 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 26 | public void CreateWriteMultipleCoilsRequestTooMuchData() 27 | { 28 | new WriteMultipleCoilsRequest(1, 2, MessageUtility.CreateDefaultCollection(true, Modbus.MaximumDiscreteRequestResponseSize + 1)); 29 | } 30 | 31 | [Test] 32 | public void CreateWriteMultipleCoilsRequestMaxSize() 33 | { 34 | WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(1, 2, MessageUtility.CreateDefaultCollection(true, Modbus.MaximumDiscreteRequestResponseSize)); 35 | Assert.AreEqual(Modbus.MaximumDiscreteRequestResponseSize, request.Data.Count); 36 | } 37 | 38 | [Test] 39 | public void ToString_WriteMultipleCoilsRequest() 40 | { 41 | DiscreteCollection col = new DiscreteCollection(true, false, true, false, true, true, true, false, false); 42 | WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(34, 45, col); 43 | 44 | Assert.AreEqual("Write 9 coils starting at address 45.", request.ToString()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/WriteMultipleCoilsResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class WriteMultipleCoilsResponseFixture 9 | { 10 | [Test] 11 | public void CreateWriteMultipleCoilsResponse() 12 | { 13 | WriteMultipleCoilsResponse response = new WriteMultipleCoilsResponse(17, 19, 45); 14 | Assert.AreEqual(Modbus.WriteMultipleCoils, response.FunctionCode); 15 | Assert.AreEqual(17, response.SlaveAddress); 16 | Assert.AreEqual(19, response.StartAddress); 17 | Assert.AreEqual(45, response.NumberOfPoints); 18 | } 19 | 20 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 21 | public void CreateWriteMultipleCoilsResponseTooMuchData() 22 | { 23 | new WriteMultipleCoilsResponse(1, 2, Modbus.MaximumDiscreteRequestResponseSize + 1); 24 | } 25 | 26 | [Test] 27 | public void CreateWriteMultipleCoilsResponseMaxSize() 28 | { 29 | WriteMultipleCoilsResponse response = new WriteMultipleCoilsResponse(1, 2, Modbus.MaximumDiscreteRequestResponseSize); 30 | Assert.AreEqual(Modbus.MaximumDiscreteRequestResponseSize, response.NumberOfPoints); 31 | } 32 | 33 | [Test] 34 | public void ToString_Test() 35 | { 36 | var response = new WriteMultipleCoilsResponse(1, 2, 3); 37 | 38 | Assert.AreEqual("Wrote 3 coils starting at address 2.", response.ToString()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/WriteMultipleRegistersRequestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Data; 3 | using Modbus.Message; 4 | using Modbus.Utility; 5 | using MbUnit.Framework; 6 | 7 | namespace Modbus.UnitTests.Message 8 | { 9 | [TestFixture] 10 | public class WriteMultipleRegistersRequestFixture 11 | { 12 | [Test] 13 | public void CreateWriteMultipleRegistersRequestFixture() 14 | { 15 | RegisterCollection col = new RegisterCollection(10, 20, 30, 40, 50); 16 | WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(11, 34, col); 17 | Assert.AreEqual(Modbus.WriteMultipleRegisters, request.FunctionCode); 18 | Assert.AreEqual(11, request.SlaveAddress); 19 | Assert.AreEqual(34, request.StartAddress); 20 | Assert.AreEqual(10, request.ByteCount); 21 | Assert.AreEqual(col.NetworkBytes, request.Data.NetworkBytes); 22 | } 23 | 24 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 25 | public void CreateWriteMultipleRegistersRequestTooMuchData() 26 | { 27 | new WriteMultipleRegistersRequest(1, 2, MessageUtility.CreateDefaultCollection(3, Modbus.MaximumRegisterRequestResponseSize + 1)); 28 | } 29 | 30 | [Test] 31 | public void CreateWriteMultipleRegistersRequestMaxSize() 32 | { 33 | WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(1, 2, MessageUtility.CreateDefaultCollection(3, Modbus.MaximumRegisterRequestResponseSize)); 34 | Assert.AreEqual(Modbus.MaximumRegisterRequestResponseSize, request.NumberOfPoints); 35 | } 36 | 37 | [Test] 38 | public void ToString_WriteMultipleRegistersRequest() 39 | { 40 | RegisterCollection col = new RegisterCollection(10, 20, 30, 40, 50); 41 | WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(11, 34, col); 42 | 43 | Assert.AreEqual("Write 5 holding registers starting at address 34.", request.ToString()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/WriteMultipleRegistersResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Message 6 | { 7 | [TestFixture] 8 | public class WriteMultipleRegistersResponseFixture 9 | { 10 | [Test] 11 | public void CreateWriteMultipleRegistersResponse() 12 | { 13 | WriteMultipleRegistersResponse response = new WriteMultipleRegistersResponse(12, 39, 2); 14 | Assert.AreEqual(Modbus.WriteMultipleRegisters, response.FunctionCode); 15 | Assert.AreEqual(12, response.SlaveAddress); 16 | Assert.AreEqual(39, response.StartAddress); 17 | Assert.AreEqual(2, response.NumberOfPoints); 18 | } 19 | 20 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 21 | public void CreateWriteMultipleRegistersResponseTooMuchData() 22 | { 23 | new WriteMultipleRegistersResponse(1, 2, Modbus.MaximumRegisterRequestResponseSize + 1); 24 | } 25 | 26 | [Test] 27 | public void CreateWriteMultipleRegistersResponseMaxSize() 28 | { 29 | WriteMultipleRegistersResponse response = new WriteMultipleRegistersResponse(1, 2, Modbus.MaximumRegisterRequestResponseSize); 30 | Assert.AreEqual(Modbus.MaximumRegisterRequestResponseSize, response.NumberOfPoints); 31 | } 32 | 33 | [Test] 34 | public void ToString_Test() 35 | { 36 | var response = new WriteMultipleRegistersResponse(1, 2, 3); 37 | 38 | Assert.AreEqual("Wrote 3 holding registers starting at address 2.", response.ToString()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/WriteSingleCoilRequestResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Message; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.UnitTests.Message 5 | { 6 | [TestFixture] 7 | public class WriteSingleCoilRequestResponseFixture 8 | { 9 | [Test] 10 | public void NewWriteSingleCoilRequestResponse() 11 | { 12 | WriteSingleCoilRequestResponse request = new WriteSingleCoilRequestResponse(11, 5, true); 13 | Assert.AreEqual(11, request.SlaveAddress); 14 | Assert.AreEqual(5, request.StartAddress); 15 | Assert.AreEqual(1, request.Data.Count); 16 | Assert.AreEqual(Modbus.CoilOn, request.Data[0]); 17 | } 18 | 19 | [Test] 20 | public void ToString_True() 21 | { 22 | var request = new WriteSingleCoilRequestResponse(11, 5, true); 23 | 24 | Assert.AreEqual("Write single coil 1 at address 5.", request.ToString()); 25 | } 26 | 27 | [Test] 28 | public void ToString_False() 29 | { 30 | var request = new WriteSingleCoilRequestResponse(11, 5, false); 31 | 32 | Assert.AreEqual("Write single coil 0 at address 5.", request.ToString()); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Message/WriteSingleRegisterRequestResponseFixture.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Message; 2 | using MbUnit.Framework; 3 | 4 | namespace Modbus.UnitTests.Message 5 | { 6 | [TestFixture] 7 | public class WriteSingleRegisterRequestResponseFixture 8 | { 9 | [Test] 10 | public void NewWriteSingleRegisterRequestResponse() 11 | { 12 | WriteSingleRegisterRequestResponse message = new WriteSingleRegisterRequestResponse(12, 5, 1200); 13 | Assert.AreEqual(12, message.SlaveAddress); 14 | Assert.AreEqual(5, message.StartAddress); 15 | Assert.AreEqual(1, message.Data.Count); 16 | Assert.AreEqual(1200, message.Data[0]); 17 | } 18 | 19 | [Test] 20 | public void ToStringOverride() 21 | { 22 | WriteSingleRegisterRequestResponse message = new WriteSingleRegisterRequestResponse(12, 5, 1200); 23 | Assert.AreEqual("Write single holding register 1200 at address 5.", message.ToString()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Modbus.UnitTests")] 6 | [assembly: AssemblyProduct("NModbus")] 7 | [assembly: AssemblyCopyright("Licensed under MIT License.")] 8 | [assembly: ComVisible(false)] 9 | [assembly: CLSCompliant(false)] 10 | [assembly: Guid("244bb5c5-2aec-437a-b1c3-4b312ace54fc")] 11 | [assembly: AssemblyVersion("1.9.0.0")] 12 | [assembly: AssemblyFileVersion("1.9.0.0")] 13 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Utility/CollectionUtilityFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using MbUnit.Framework; 6 | using Modbus.Data; 7 | using Modbus.UnitTests.Message; 8 | using Modbus.Utility; 9 | using Unme.Common; 10 | 11 | namespace Modbus.UnitTests.Utility 12 | { 13 | [TestFixture] 14 | public class CollectionUtilityFixture 15 | { 16 | [Test] 17 | public void SliceMiddle() 18 | { 19 | byte[] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 20 | Assert.AreEqual(new byte[] { 3, 4, 5, 6, 7 }, test.Slice(2, 5).ToArray()); 21 | } 22 | 23 | [Test] 24 | public void SliceBeginning() 25 | { 26 | byte[] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 27 | Assert.AreEqual(new byte[] { 1, 2 }, test.Slice(0, 2).ToArray()); 28 | } 29 | 30 | [Test] 31 | public void SliceEnd() 32 | { 33 | byte[] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 34 | Assert.AreEqual(new byte[] { 9, 10 }, test.Slice(8, 2).ToArray()); 35 | } 36 | 37 | [Test] 38 | public void SliceCollection() 39 | { 40 | Collection col = new Collection(new bool[] { true, false, false, false, true, true }); 41 | Assert.AreEqual(new bool[] { false, false, true }, col.Slice(2, 3).ToArray()); 42 | } 43 | 44 | [Test] 45 | public void SliceReadOnlyCollection() 46 | { 47 | ReadOnlyCollection col = new ReadOnlyCollection(new bool[] { true, false, false, false, true, true }); 48 | Assert.AreEqual(new bool[] { false, false, true }, col.Slice(2, 3).ToArray()); 49 | } 50 | 51 | [Test, ExpectedArgumentNullException] 52 | public void SliceNullICollection() 53 | { 54 | ICollection col = null; 55 | col.Slice(1, 1).ToArray(); 56 | } 57 | 58 | [Test, ExpectedArgumentNullException] 59 | public void SliceNullArray() 60 | { 61 | bool[] array = null; 62 | array.Slice(1, 1).ToArray(); 63 | } 64 | 65 | [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] 66 | public void CreateDefaultCollectionNegativeSize() 67 | { 68 | MessageUtility.CreateDefaultCollection(0, -1); 69 | } 70 | 71 | [Test] 72 | public void CreateDefaultCollection() 73 | { 74 | RegisterCollection col = MessageUtility.CreateDefaultCollection(3, 5); 75 | Assert.AreEqual(5, col.Count); 76 | Assert.AreEqual(new ushort[] { 3, 3, 3, 3, 3 }, col.ToArray()); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Utility/DiscriminatedUnionFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Utility; 3 | using MbUnit.Framework; 4 | 5 | namespace Modbus.UnitTests.Utility 6 | { 7 | [TestFixture] 8 | public class DiscriminatedUnionTestSuite 9 | { 10 | [Test] 11 | public void DiscriminatedUnion_CreateA() 12 | { 13 | var du = DiscriminatedUnion.CreateA("foo"); 14 | Assert.AreEqual(DiscriminatedUnionOption.A,du.Option); 15 | Assert.AreEqual("foo", du.A); 16 | } 17 | 18 | [Test] 19 | public void DiscriminatedUnion_CreateB() 20 | { 21 | var du = DiscriminatedUnion.CreateB("foo"); 22 | Assert.AreEqual(DiscriminatedUnionOption.B, du.Option); 23 | Assert.AreEqual("foo", du.B); 24 | } 25 | 26 | [Test] 27 | public void DiscriminatedUnion_AllowNulls() 28 | { 29 | var du = DiscriminatedUnion.CreateB(null); 30 | Assert.AreEqual(DiscriminatedUnionOption.B, du.Option); 31 | Assert.AreEqual(null, du.B); 32 | } 33 | 34 | [Test, ExpectedException(typeof(InvalidOperationException))] 35 | public void AccessInvalidOption_A() 36 | { 37 | var du = DiscriminatedUnion.CreateB("foo"); 38 | du.A.ToString(); 39 | } 40 | 41 | [Test, ExpectedException(typeof(InvalidOperationException))] 42 | public void AccessInvalidOption_B() 43 | { 44 | var du = DiscriminatedUnion.CreateA("foo"); 45 | du.B.ToString(); 46 | } 47 | 48 | [Test] 49 | public void DiscriminatedUnion_ToString() 50 | { 51 | var du = DiscriminatedUnion.CreateA("foo"); 52 | Assert.AreEqual(du.ToString(), "foo"); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /NModbus/src/Modbus.UnitTests/Utility/SerialConnectionFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Modbus.Net; 5 | using Modbus.Util; 6 | using NUnit.Framework; 7 | using System.Threading; 8 | 9 | namespace Modbus.UnitTests.Util 10 | { 11 | [TestFixture] 12 | public class SerialConnectionFixture 13 | { 14 | SerialParameters _serialParameters; 15 | SerialConnection _serialConnection; 16 | 17 | [SetUp] 18 | public void SetUp() 19 | { 20 | _serialParameters = new SerialParameters(); 21 | _serialParameters.PortName = "COM3"; 22 | 23 | _serialConnection = new SerialConnection(_serialParameters); 24 | 25 | //TODO what I really want to do above is have a config file w/ test settings which will vary by developement environment 26 | // e.g. SerialParameters sp = new SerialParameters(props.TestPortName, props.TestBaudRate, ... 27 | } 28 | 29 | [TearDown] 30 | public void TearDown() 31 | { 32 | if (_serialConnection.IsOpen) 33 | _serialConnection.Close(); 34 | 35 | Thread.Sleep(200); 36 | } 37 | 38 | [Test] 39 | public void CreateSerialConnectionDefaultParameters() 40 | { 41 | SerialConnection sc = new SerialConnection(new SerialParameters()); 42 | Assert.IsNotNull(sc); 43 | } 44 | 45 | [Test] 46 | public void CheckOpenConnection() 47 | { 48 | _serialConnection.Open(); 49 | Assert.IsTrue(_serialConnection.IsOpen); 50 | } 51 | 52 | [Test] 53 | public void CheckCloseConnection() 54 | { 55 | _serialConnection.Open(); 56 | Assert.IsTrue(_serialConnection.IsOpen); 57 | _serialConnection.Close(); 58 | Thread.Sleep(250); 59 | Assert.IsFalse(_serialConnection.IsOpen); 60 | } 61 | 62 | [Test] 63 | [ExpectedException(typeof(ArgumentException))] 64 | public void CheckOpenConnectionBadPortName() 65 | { 66 | _serialParameters.PortName = "JUNK"; 67 | SerialConnection sc = new SerialConnection(_serialParameters); 68 | sc.Open(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Data/DataStoreEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Linq; 6 | using Modbus.Utility; 7 | using Unme.Common; 8 | 9 | namespace Modbus.Data 10 | { 11 | /// 12 | /// Event args for read write actions performed on the DataStore. 13 | /// 14 | public class DataStoreEventArgs : EventArgs 15 | { 16 | private DataStoreEventArgs(ushort startAddress, ModbusDataType modbusDataType) 17 | { 18 | this.StartAddress = startAddress; 19 | this.ModbusDataType = modbusDataType; 20 | } 21 | 22 | /// 23 | /// Type of Modbus data (e.g. Holding register). 24 | /// 25 | public ModbusDataType ModbusDataType { get; private set; } 26 | 27 | /// 28 | /// Start address of data. 29 | /// 30 | public ushort StartAddress { get; private set; } 31 | 32 | /// 33 | /// Data that was read or written. 34 | /// 35 | [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] 36 | public DiscriminatedUnion, ReadOnlyCollection> Data { get; private set; } 37 | 38 | internal static DataStoreEventArgs CreateDataStoreEventArgs(ushort startAddress, ModbusDataType modbusDataType, IEnumerable data) 39 | { 40 | if (data == null) 41 | throw new ArgumentNullException("data"); 42 | 43 | if (!(typeof(T) == typeof(bool) || typeof(T) == typeof(ushort))) 44 | throw new ArgumentException("Generic type T should be of type bool or ushort"); 45 | 46 | var eventArgs = new DataStoreEventArgs(startAddress, modbusDataType); 47 | 48 | if (typeof(T) == typeof(bool)) 49 | { 50 | eventArgs.Data = DiscriminatedUnion, ReadOnlyCollection>.CreateA(data.Cast().ToReadOnly()); 51 | } 52 | else 53 | { 54 | eventArgs.Data = DiscriminatedUnion, ReadOnlyCollection>.CreateB(data.Cast().ToReadOnly()); 55 | } 56 | 57 | return eventArgs; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Data/DataStoreFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Unme.Common; 4 | 5 | namespace Modbus.Data 6 | { 7 | /// 8 | /// Data story factory. 9 | /// 10 | public static class DataStoreFactory 11 | { 12 | /// 13 | /// Factory method for default data store - register values set to 0 and discrete values set to false. 14 | /// 15 | public static DataStore CreateDefaultDataStore() 16 | { 17 | return CreateDefaultDataStore(UInt16.MaxValue, UInt16.MaxValue, UInt16.MaxValue, UInt16.MaxValue); 18 | } 19 | 20 | /// 21 | /// Factory method for default data store - register values set to 0 and discrete values set to false. 22 | /// 23 | public static DataStore CreateDefaultDataStore(ushort coilsCount, ushort inputsCount, ushort holdingRegistersCount, ushort inputRegistersCount) 24 | { 25 | DataStore dataStore = new DataStore(); 26 | 27 | Enumerable.Repeat(false, coilsCount).ForEach(value => dataStore.CoilDiscretes.Add(value)); 28 | Enumerable.Repeat(false, inputsCount).ForEach(value => dataStore.InputDiscretes.Add(value)); 29 | Enumerable.Repeat((ushort) 0, holdingRegistersCount).ForEach(value => dataStore.HoldingRegisters.Add(value)); 30 | Enumerable.Repeat((ushort) 0, inputRegistersCount).ForEach(value => dataStore.InputRegisters.Add(value)); 31 | 32 | return dataStore; 33 | } 34 | 35 | /// 36 | /// Factory method for test data store. 37 | /// 38 | public static DataStore CreateTestDataStore() 39 | { 40 | DataStore dataStore = new DataStore(); 41 | 42 | for (int i = 1; i < 3000; i++) 43 | { 44 | bool value = i % 2 > 0; 45 | dataStore.CoilDiscretes.Add(value); 46 | dataStore.InputDiscretes.Add(!value); 47 | dataStore.HoldingRegisters.Add((ushort) i); 48 | dataStore.InputRegisters.Add((ushort) (i * 10)); 49 | } 50 | 51 | return dataStore; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Data/DiscreteCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | 7 | namespace Modbus.Data 8 | { 9 | /// 10 | /// Collection of discrete values. 11 | /// 12 | public class DiscreteCollection : Collection, IModbusMessageDataCollection 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public DiscreteCollection() 18 | { 19 | } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | public DiscreteCollection(params bool[] bits) 25 | : this((IList) bits) 26 | { 27 | } 28 | 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | public DiscreteCollection(params byte[] bytes) 33 | : this((IList) (new BitArray(bytes)).Cast().ToArray()) 34 | { 35 | } 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | public DiscreteCollection(IList bits) 41 | : base(bits.IsReadOnly ? new List(bits) : bits) 42 | { 43 | } 44 | 45 | /// 46 | /// Gets the network bytes. 47 | /// 48 | public byte[] NetworkBytes 49 | { 50 | get 51 | { 52 | bool[] bits = new bool[Count]; 53 | CopyTo(bits, 0); 54 | 55 | BitArray bitArray = new BitArray(bits); 56 | 57 | byte[] bytes = new byte[ByteCount]; 58 | bitArray.CopyTo(bytes, 0); 59 | 60 | return bytes; 61 | } 62 | } 63 | 64 | /// 65 | /// Gets the byte count. 66 | /// 67 | public byte ByteCount 68 | { 69 | get 70 | { 71 | return (byte) ((Count + 7) / 8); 72 | } 73 | } 74 | 75 | /// 76 | /// Returns a that represents the current . 77 | /// 78 | /// 79 | /// A that represents the current . 80 | /// 81 | public override string ToString() 82 | { 83 | return String.Concat("{", String.Join(", ", this.Select(discrete => discrete ? "1" : "0").ToArray()), "}"); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Data/IModbusMessageDataCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Modbus.Data 4 | { 5 | /// 6 | /// Modbus message containing data. 7 | /// 8 | [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] 9 | public interface IModbusMessageDataCollection 10 | { 11 | /// 12 | /// Gets the network bytes. 13 | /// 14 | [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] 15 | byte[] NetworkBytes { get; } 16 | 17 | /// 18 | /// Gets the byte count. 19 | /// 20 | byte ByteCount { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Data/ModbusDataType.cs: -------------------------------------------------------------------------------- 1 | namespace Modbus.Data 2 | { 3 | /// 4 | /// Types of data supported by the Modbus protocol. 5 | /// 6 | public enum ModbusDataType 7 | { 8 | /// 9 | /// read/write register 10 | /// 11 | HoldingRegister, 12 | 13 | /// 14 | /// readonly register 15 | /// 16 | InputRegister, 17 | 18 | /// 19 | /// read/write discrete 20 | /// 21 | Coil, 22 | 23 | /// 24 | /// readonly discrete 25 | /// 26 | Input 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Data/RegisterCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Net; 6 | using Modbus.Utility; 7 | 8 | namespace Modbus.Data 9 | { 10 | /// 11 | /// Collection of 16 bit registers. 12 | /// 13 | public class RegisterCollection : Collection, IModbusMessageDataCollection 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | public RegisterCollection() 19 | { 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | public RegisterCollection(byte[] bytes) 26 | : this((IList) ModbusUtility.NetworkBytesToHostUInt16(bytes)) 27 | { 28 | } 29 | 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | public RegisterCollection(params ushort[] registers) 34 | : this((IList) registers) 35 | { 36 | } 37 | 38 | /// 39 | /// Initializes a new instance of the class. 40 | /// 41 | public RegisterCollection(IList registers) 42 | : base(registers.IsReadOnly ? new List(registers) : registers) 43 | { 44 | } 45 | 46 | /// 47 | /// Gets the network bytes. 48 | /// 49 | public byte[] NetworkBytes 50 | { 51 | get 52 | { 53 | List bytes = new List(); 54 | 55 | foreach (ushort register in this) 56 | bytes.AddRange(BitConverter.GetBytes((ushort) IPAddress.HostToNetworkOrder((short) register))); 57 | 58 | return bytes.ToArray(); 59 | } 60 | } 61 | 62 | /// 63 | /// Gets the byte count. 64 | /// 65 | public byte ByteCount 66 | { 67 | get 68 | { 69 | return (byte) (Count * 2); 70 | } 71 | } 72 | 73 | /// 74 | /// Returns a that represents the current . 75 | /// 76 | /// 77 | /// A that represents the current . 78 | /// 79 | public override string ToString() 80 | { 81 | return String.Concat("{", String.Join(", ", this.Select(v => v.ToString()).ToArray()), "}"); 82 | } } 83 | } 84 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Device/IModbusSerialMaster.cs: -------------------------------------------------------------------------------- 1 | using Modbus.IO; 2 | 3 | namespace Modbus.Device 4 | { 5 | /// 6 | /// Modbus Serial Master device. 7 | /// 8 | public interface IModbusSerialMaster : IModbusMaster 9 | { 10 | /// 11 | /// Transport for used by this master. 12 | /// 13 | new ModbusSerialTransport Transport { get; } 14 | 15 | /// 16 | /// Serial Line only. 17 | /// Diagnostic function which loops back the original data. 18 | /// NModbus only supports looping back one ushort value, this is a limitation of the "Best Effort" implementation of the RTU protocol. 19 | /// 20 | /// Address of device to test. 21 | /// Data to return. 22 | /// Return true if slave device echoed data. 23 | bool ReturnQueryData(byte slaveAddress, ushort data); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Device/ModbusDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.IO; 3 | using Unme.Common; 4 | 5 | namespace Modbus.Device 6 | { 7 | /// 8 | /// Modbus device. 9 | /// 10 | public abstract class ModbusDevice 11 | { 12 | private ModbusTransport _transport; 13 | 14 | internal ModbusDevice(ModbusTransport transport) 15 | { 16 | _transport = transport; 17 | } 18 | 19 | /// 20 | /// Gets the Modbus Transport. 21 | /// 22 | /// The transport. 23 | public ModbusTransport Transport 24 | { 25 | get 26 | { 27 | return _transport; 28 | } 29 | } 30 | 31 | /// 32 | /// Releases unmanaged and - optionally - managed resources 33 | /// 34 | public void Dispose() 35 | { 36 | Dispose(true); 37 | GC.SuppressFinalize(this); 38 | } 39 | 40 | /// 41 | /// Releases unmanaged and - optionally - managed resources 42 | /// 43 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources. 44 | protected virtual void Dispose(bool disposing) 45 | { 46 | if (disposing) 47 | DisposableUtility.Dispose(ref _transport); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Device/ModbusSlaveRequestEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | 4 | namespace Modbus.Device 5 | { 6 | /// 7 | /// Modbus Slave request event args containing information on the message. 8 | /// 9 | public class ModbusSlaveRequestEventArgs : EventArgs 10 | { 11 | private readonly IModbusMessage _message; 12 | 13 | internal ModbusSlaveRequestEventArgs(IModbusMessage message) 14 | { 15 | _message = message; 16 | } 17 | 18 | /// 19 | /// Gets the message. 20 | /// 21 | /// The message. 22 | public IModbusMessage Message 23 | { 24 | get { return _message; } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Device/ModbusTcpSlave.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Net.Sockets; 7 | using log4net; 8 | using Modbus.IO; 9 | using Unme.Common; 10 | using Unme.Common.NullReferenceExtension; 11 | 12 | namespace Modbus.Device 13 | { 14 | /// 15 | /// Modbus TCP slave device. 16 | /// 17 | public class ModbusTcpSlave : ModbusSlave, IDisposable 18 | { 19 | private readonly object _mastersLock = new object(); 20 | private readonly ILog _logger = LogManager.GetLogger(typeof(ModbusTcpSlave)); 21 | private readonly Dictionary _masters = new Dictionary(); 22 | private readonly TcpListener _server; 23 | 24 | private ModbusTcpSlave(byte unitId, TcpListener tcpListener) 25 | : base(unitId, new EmptyTransport()) 26 | { 27 | _server = tcpListener; 28 | } 29 | 30 | /// 31 | /// Gets the Modbus TCP Masters connected to this Modbus TCP Slave. 32 | /// 33 | public ReadOnlyCollection Masters 34 | { 35 | get 36 | { 37 | lock (_mastersLock) 38 | return new ReadOnlyCollection(_masters.Values.Select(mc => mc.TcpClient).ToList()); 39 | } 40 | } 41 | 42 | /// 43 | /// Modbus TCP slave factory method. 44 | /// 45 | public static ModbusTcpSlave CreateTcp(byte unitId, TcpListener tcpListener) 46 | { 47 | return new ModbusTcpSlave(unitId, tcpListener); 48 | } 49 | 50 | /// 51 | /// Start slave listening for requests. 52 | /// 53 | public override void Listen() 54 | { 55 | _logger.Debug("Start Modbus Tcp Server."); 56 | _server.Start(); 57 | 58 | _server.BeginAcceptTcpClient(AcceptCompleted, this); 59 | } 60 | 61 | internal void RemoveMaster(string endPoint) 62 | { 63 | lock (_mastersLock) 64 | { 65 | if (!_masters.Remove(endPoint)) 66 | throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "EndPoint {0} cannot be removed, it does not exist.", endPoint)); 67 | } 68 | 69 | _logger.InfoFormat("Removed Master {0}", endPoint); 70 | } 71 | 72 | internal void AcceptCompleted(IAsyncResult ar) 73 | { 74 | ModbusTcpSlave slave = (ModbusTcpSlave) ar.AsyncState; 75 | 76 | try 77 | { 78 | TcpClient client = _server.EndAcceptTcpClient(ar); 79 | var masterConnection = new ModbusMasterTcpConnection(client, slave); 80 | masterConnection.ModbusMasterTcpConnectionClosed += (sender, eventArgs) => RemoveMaster(eventArgs.EndPoint); 81 | 82 | lock (_mastersLock) 83 | _masters.Add(client.Client.RemoteEndPoint.ToString(), masterConnection); 84 | 85 | _logger.Debug("Accept completed."); 86 | 87 | // Accept another client 88 | _server.BeginAcceptTcpClient(AcceptCompleted, slave); 89 | } 90 | catch (ObjectDisposedException) 91 | { 92 | // this happens when the server stops 93 | } 94 | } 95 | 96 | /// 97 | /// Releases unmanaged and - optionally - managed resources 98 | /// 99 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources. 100 | protected override void Dispose(bool disposing) 101 | { 102 | base.Dispose(disposing); 103 | 104 | if (disposing) 105 | _masters.IfNotNull(m => m.Values.ForEach(client => DisposableUtility.Dispose(ref client))); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Device/ModbusUdpSlave.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | using log4net; 6 | using Modbus.IO; 7 | using Modbus.Message; 8 | using Unme.Common; 9 | 10 | namespace Modbus.Device 11 | { 12 | /// 13 | /// Modbus UDP slave device. 14 | /// 15 | public class ModbusUdpSlave : ModbusSlave 16 | { 17 | private static readonly ILog _logger = LogManager.GetLogger(typeof(ModbusUdpSlave)); 18 | private readonly UdpClient _udpClient; 19 | 20 | private ModbusUdpSlave(byte unitId, UdpClient udpClient) 21 | : base(unitId, new ModbusIpTransport(new UdpClientAdapter(udpClient))) 22 | { 23 | _udpClient = udpClient; 24 | } 25 | 26 | /// 27 | /// Modbus UDP slave factory method. 28 | /// Creates NModbus UDP slave with default 29 | /// 30 | public static ModbusUdpSlave CreateUdp(UdpClient client) 31 | { 32 | return new ModbusUdpSlave(Modbus.DefaultIpSlaveUnitId, client); 33 | } 34 | 35 | /// 36 | /// Modbus UDP slave factory method. 37 | /// 38 | public static ModbusUdpSlave CreateUdp(byte unitId, UdpClient client) 39 | { 40 | return new ModbusUdpSlave(unitId, client); 41 | } 42 | 43 | /// 44 | /// Start slave listening for requests. 45 | /// 46 | public override void Listen() 47 | { 48 | _logger.Debug("Start Modbus Udp Server."); 49 | _udpClient.BeginReceive(ReceiveRequestCompleted, this); 50 | } 51 | 52 | internal void ReceiveRequestCompleted(IAsyncResult ar) 53 | { 54 | IPEndPoint masterEndPoint = null; 55 | byte[] frame; 56 | 57 | try 58 | { 59 | frame = _udpClient.EndReceive(ar, ref masterEndPoint); 60 | } 61 | catch (ObjectDisposedException) 62 | { 63 | // this hapens when slave stops 64 | return; 65 | } 66 | 67 | ModbusUdpSlave slave = (ModbusUdpSlave) ar.AsyncState; 68 | 69 | _logger.DebugFormat("Read Frame completed {0} bytes", frame.Length); 70 | _logger.InfoFormat("RX: {0}", frame.Join(", ")); 71 | 72 | IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(frame.Slice(6, frame.Length - 6).ToArray()); 73 | request.TransactionId = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); 74 | 75 | // perform action and build response 76 | IModbusMessage response = slave.ApplyRequest(request); 77 | response.TransactionId = request.TransactionId; 78 | 79 | // write response 80 | byte[] responseFrame = Transport.BuildMessageFrame(response); 81 | _logger.InfoFormat("TX: {0}", responseFrame.Join(", ")); 82 | _udpClient.BeginSend(responseFrame, responseFrame.Length, masterEndPoint, WriteResponseCompleted, null); 83 | } 84 | 85 | internal void WriteResponseCompleted(IAsyncResult ar) 86 | { 87 | try 88 | { 89 | _udpClient.EndSend(ar); 90 | 91 | // Accept another request 92 | _udpClient.BeginReceive(ReceiveRequestCompleted, this); 93 | } 94 | catch (ObjectDisposedException) 95 | { 96 | // this happens when the slave stops 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /NModbus/src/Modbus/Device/TcpConnectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unme.Common; 3 | 4 | namespace Modbus.Device 5 | { 6 | internal class TcpConnectionEventArgs : EventArgs 7 | { 8 | public TcpConnectionEventArgs(string endPoint) 9 | { 10 | if (endPoint == null) 11 | throw new ArgumentNullException("endPoint"); 12 | if (endPoint.IsNullOrEmpty()) 13 | throw new ArgumentException(Resources.EmptyEndPoint); 14 | 15 | EndPoint = endPoint; 16 | } 17 | 18 | public string EndPoint { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | [module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Modbus")] 4 | [module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Modbus.Utility")] -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/EmptyTransport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Modbus.Message; 3 | 4 | namespace Modbus.IO 5 | { 6 | /// 7 | /// Empty placeholder. 8 | /// 9 | public class EmptyTransport : ModbusTransport 10 | { 11 | internal override byte[] ReadRequest() 12 | { 13 | throw new NotImplementedException(); 14 | } 15 | 16 | internal override IModbusMessage ReadResponse() 17 | { 18 | throw new NotImplementedException(); 19 | } 20 | 21 | internal override byte[] BuildMessageFrame(global::Modbus.Message.IModbusMessage message) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | 26 | internal override void Write(IModbusMessage message) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | 31 | internal override void OnValidateResponse(IModbusMessage request, IModbusMessage response) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/ISerialPortAdapter.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Modbus.IO 3 | { 4 | /// 5 | /// Adapter so we can mock the serial port 6 | /// 7 | public interface ISerialPortAdapter 8 | { 9 | string ReadLine(); 10 | 11 | int Read(byte[] buffer, int offset, int count); 12 | 13 | void Write(byte[] buffer, int offset, int count); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/ISerialResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Modbus.IO 4 | { 5 | /// 6 | /// Represents a serial resource. 7 | /// 8 | [Obsolete("Use IStreamResource instead.")] 9 | public interface ISerialResource 10 | { 11 | /// 12 | /// Indicates that no time-out should occur. 13 | /// 14 | int InfiniteTimeout { get; } 15 | 16 | /// 17 | /// Gets or sets the number of milliseconds before a time-out occurs when a read operation does not finish. 18 | /// 19 | int ReadTimeout { get; set; } 20 | 21 | /// 22 | /// Gets or sets the number of milliseconds before a time-out occurs when a write operation does not finish. 23 | /// 24 | int WriteTimeout { get; set; } 25 | 26 | /// 27 | /// Gets or sets the value used to interpret the end of a call to the ReadLine method. 28 | /// 29 | string NewLine { get; set; } 30 | 31 | /// 32 | /// Purges the receive buffer. 33 | /// 34 | void DiscardInBuffer(); 35 | 36 | /// 37 | /// Reads a number of bytes from the input buffer and writes those bytes into a byte array at the specified offset. 38 | /// 39 | /// The byte array to write the input to. 40 | /// The offset in the buffer array to begin writing. 41 | /// The number of bytes to read. 42 | /// The number of bytes read. 43 | int Read(byte[] buffer, int offset, int count); 44 | 45 | /// 46 | /// Reads up to the NewLine value in the input buffer. 47 | /// 48 | string ReadLine(); 49 | 50 | /// 51 | /// Writes a specified number of bytes to the port from an output buffer, starting at the specified offset. 52 | /// 53 | /// The byte array that contains the data to write to the port. 54 | /// The offset in the buffer array to begin writing. 55 | /// The number of bytes to write. 56 | void Write(byte[] buffer, int offset, int count); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/IStreamResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Modbus.IO 4 | { 5 | /// 6 | /// Represents a serial resource. 7 | /// Implementor - http://en.wikipedia.org/wiki/Bridge_Pattern 8 | /// 9 | public interface IStreamResource : IDisposable 10 | { 11 | /// 12 | /// Indicates that no time-out should occur. 13 | /// 14 | int InfiniteTimeout { get; } 15 | 16 | /// 17 | /// Gets or sets the number of milliseconds before a time-out occurs when a read operation does not finish. 18 | /// 19 | int ReadTimeout { get; set; } 20 | 21 | /// 22 | /// Gets or sets the number of milliseconds before a time-out occurs when a write operation does not finish. 23 | /// 24 | int WriteTimeout { get; set; } 25 | 26 | /// 27 | /// Purges the receive buffer. 28 | /// 29 | void DiscardInBuffer(); 30 | 31 | /// 32 | /// Reads a number of bytes from the input buffer and writes those bytes into a byte array at the specified offset. 33 | /// 34 | /// The byte array to write the input to. 35 | /// The offset in the buffer array to begin writing. 36 | /// The number of bytes to read. 37 | /// The number of bytes read. 38 | int Read(byte[] buffer, int offset, int count); 39 | 40 | /// 41 | /// Writes a specified number of bytes to the port from an output buffer, starting at the specified offset. 42 | /// 43 | /// The byte array that contains the data to write to the port. 44 | /// The offset in the buffer array to begin writing. 45 | /// The number of bytes to write. 46 | void Write(byte[] buffer, int offset, int count); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/ModbusAsciiTransport.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Text; 5 | using log4net; 6 | using Modbus.Message; 7 | using Modbus.Utility; 8 | using Unme.Common; 9 | 10 | namespace Modbus.IO 11 | { 12 | /// 13 | /// Refined Abstraction - http://en.wikipedia.org/wiki/Bridge_Pattern 14 | /// 15 | internal class ModbusAsciiTransport : ModbusSerialTransport 16 | { 17 | private static readonly ILog _logger = LogManager.GetLogger(typeof(ModbusAsciiTransport)); 18 | 19 | internal ModbusAsciiTransport(IStreamResource streamResource) 20 | : base(streamResource) 21 | { 22 | Debug.Assert(streamResource != null, "Argument streamResource cannot be null."); 23 | } 24 | 25 | internal override byte[] BuildMessageFrame(IModbusMessage message) 26 | { 27 | var frame = new List(); 28 | frame.Add((byte)':'); 29 | frame.AddRange(ModbusUtility.GetAsciiBytes(message.SlaveAddress)); 30 | frame.AddRange(ModbusUtility.GetAsciiBytes(message.ProtocolDataUnit)); 31 | frame.AddRange(ModbusUtility.GetAsciiBytes(ModbusUtility.CalculateLrc(message.MessageFrame))); 32 | frame.AddRange(Encoding.ASCII.GetBytes(Modbus.NewLine.ToCharArray())); 33 | 34 | return frame.ToArray(); 35 | } 36 | 37 | internal override bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame) 38 | { 39 | return ModbusUtility.CalculateLrc(message.MessageFrame) == messageFrame[messageFrame.Length - 1]; 40 | } 41 | 42 | internal override byte[] ReadRequest() 43 | { 44 | return ReadRequestResponse(); 45 | } 46 | 47 | internal override IModbusMessage ReadResponse() 48 | { 49 | return CreateResponse(ReadRequestResponse()); 50 | } 51 | 52 | internal byte[] ReadRequestResponse() 53 | { 54 | // read message frame, removing frame start ':' 55 | string frameHex = StreamResourceUtility.ReadLine(StreamResource).Substring(1); 56 | 57 | // convert hex to bytes 58 | byte[] frame = ModbusUtility.HexToBytes(frameHex); 59 | _logger.InfoFormat("RX: {0}", frame.Join(", ")); 60 | 61 | if (frame.Length < 3) 62 | throw new IOException("Premature end of stream, message truncated."); 63 | 64 | return frame; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/ModbusSerialTransport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.IO; 5 | using log4net; 6 | using Modbus.Message; 7 | using Unme.Common; 8 | 9 | namespace Modbus.IO 10 | { 11 | /// 12 | /// Transport for Serial protocols. 13 | /// Refined Abstraction - http://en.wikipedia.org/wiki/Bridge_Pattern 14 | /// 15 | public abstract class ModbusSerialTransport : ModbusTransport 16 | { 17 | private static readonly ILog _logger = LogManager.GetLogger(typeof(ModbusSerialTransport)); 18 | private bool _checkFrame = true; 19 | 20 | internal ModbusSerialTransport(IStreamResource streamResource) 21 | : base(streamResource) 22 | { 23 | Debug.Assert(streamResource != null, "Argument streamResource cannot be null."); 24 | } 25 | 26 | /// 27 | /// Gets or sets a value indicating whether LRC/CRC frame checking is performed on messages. 28 | /// 29 | public bool CheckFrame 30 | { 31 | get { return _checkFrame; } 32 | set { _checkFrame = value; } 33 | } 34 | 35 | internal void DiscardInBuffer() 36 | { 37 | StreamResource.DiscardInBuffer(); 38 | } 39 | 40 | internal override void Write(IModbusMessage message) 41 | { 42 | DiscardInBuffer(); 43 | 44 | byte[] frame = BuildMessageFrame(message); 45 | _logger.InfoFormat("TX: {0}", frame.Join(", ")); 46 | StreamResource.Write(frame, 0, frame.Length); 47 | } 48 | 49 | internal override IModbusMessage CreateResponse(byte[] frame) 50 | { 51 | IModbusMessage response = base.CreateResponse(frame); 52 | 53 | // compare checksum 54 | if (CheckFrame && !ChecksumsMatch(response, frame)) 55 | { 56 | string errorMessage = String.Format(CultureInfo.InvariantCulture, "Checksums failed to match {0} != {1}", response.MessageFrame.Join(", "), frame.Join(", ")); 57 | _logger.Error(errorMessage); 58 | throw new IOException(errorMessage); 59 | } 60 | 61 | return response; 62 | } 63 | 64 | internal abstract bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame); 65 | 66 | internal override void OnValidateResponse(IModbusMessage request, IModbusMessage response) 67 | { 68 | // no-op 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/SerialPortAdapter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO.Ports; 4 | using Unme.Common; 5 | 6 | namespace Modbus.IO 7 | { 8 | /// 9 | /// Concrete Implementor - http://en.wikipedia.org/wiki/Bridge_Pattern 10 | /// 11 | internal class SerialPortAdapter : IStreamResource 12 | { 13 | private SerialPort _serialPort; 14 | 15 | public SerialPortAdapter(SerialPort serialPort) 16 | { 17 | Debug.Assert(serialPort != null, "Argument serialPort cannot be null."); 18 | 19 | _serialPort = serialPort; 20 | _serialPort.NewLine = Modbus.NewLine; 21 | } 22 | 23 | public int InfiniteTimeout 24 | { 25 | get { return SerialPort.InfiniteTimeout; } 26 | } 27 | 28 | public int ReadTimeout 29 | { 30 | get { return _serialPort.ReadTimeout; } 31 | set { _serialPort.ReadTimeout = value; } 32 | } 33 | 34 | public int WriteTimeout 35 | { 36 | get { return _serialPort.WriteTimeout; } 37 | set { _serialPort.WriteTimeout = value; } 38 | } 39 | 40 | public void DiscardInBuffer() 41 | { 42 | _serialPort.DiscardInBuffer(); 43 | } 44 | 45 | public int Read(byte[] buffer, int offset, int count) 46 | { 47 | return _serialPort.Read(buffer, offset, count); 48 | } 49 | 50 | public void Write(byte[] buffer, int offset, int count) 51 | { 52 | _serialPort.Write(buffer, offset, count); 53 | } 54 | 55 | public void Dispose() 56 | { 57 | Dispose(true); 58 | GC.SuppressFinalize(this); 59 | } 60 | 61 | protected virtual void Dispose(bool disposing) 62 | { 63 | if (disposing) 64 | DisposableUtility.Dispose(ref _serialPort); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/StreamResourceUtility.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | 4 | namespace Modbus.IO 5 | { 6 | internal static class StreamResourceUtility 7 | { 8 | internal static string ReadLine(IStreamResource stream) 9 | { 10 | var result = new StringBuilder(); 11 | var singleByteBuffer = new byte[1]; 12 | 13 | do 14 | { 15 | stream.Read(singleByteBuffer, 0, 1); 16 | result.Append(Encoding.ASCII.GetChars(singleByteBuffer).First()); 17 | } while (!result.ToString().EndsWith(Modbus.NewLine)); 18 | 19 | return result.ToString().Substring(0, result.Length - Modbus.NewLine.Length); 20 | } 21 | 22 | /// 23 | /// Initializes stream read write timeouts to default value if they have not been overridden already. 24 | /// 25 | internal static void InitializeDefaultTimeouts(IStreamResource streamResource) 26 | { 27 | streamResource.WriteTimeout = streamResource.WriteTimeout == streamResource.InfiniteTimeout ? Modbus.DefaultTimeout : streamResource.WriteTimeout; 28 | streamResource.ReadTimeout = streamResource.ReadTimeout == streamResource.InfiniteTimeout ? Modbus.DefaultTimeout : streamResource.ReadTimeout; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/TcpClientAdapter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Net.Sockets; 4 | using Unme.Common; 5 | 6 | namespace Modbus.IO 7 | { 8 | /// 9 | /// Concrete Implementor - http://en.wikipedia.org/wiki/Bridge_Pattern 10 | /// 11 | internal class TcpClientAdapter : IStreamResource 12 | { 13 | private const int InfiniteTimeoutValue = 0; 14 | private NetworkStream _networkStream; 15 | 16 | public TcpClientAdapter(TcpClient tcpClient) 17 | { 18 | Debug.Assert(tcpClient != null, "Argument tcpClient cannot be null."); 19 | 20 | _networkStream = tcpClient.GetStream(); 21 | } 22 | 23 | public int InfiniteTimeout 24 | { 25 | get { return InfiniteTimeoutValue; } 26 | } 27 | 28 | public int ReadTimeout 29 | { 30 | get { return _networkStream.ReadTimeout; } 31 | set { _networkStream.ReadTimeout = value; } 32 | } 33 | 34 | public int WriteTimeout 35 | { 36 | get { return _networkStream.WriteTimeout; } 37 | set { _networkStream.WriteTimeout = value; } 38 | } 39 | 40 | public void Write(byte[] buffer, int offset, int size) 41 | { 42 | _networkStream.Write(buffer, offset, size); 43 | } 44 | 45 | public int Read(byte[] buffer, int offset, int size) 46 | { 47 | return _networkStream.Read(buffer, offset, size); 48 | } 49 | 50 | public void DiscardInBuffer() 51 | { 52 | _networkStream.Flush(); 53 | } 54 | 55 | public void Dispose() 56 | { 57 | Dispose(true); 58 | GC.SuppressFinalize(this); 59 | } 60 | 61 | protected virtual void Dispose(bool disposing) 62 | { 63 | if (disposing) 64 | DisposableUtility.Dispose(ref _networkStream); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/IO/UdpClientAdapter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using Unme.Common; 9 | 10 | namespace Modbus.IO 11 | { 12 | /// 13 | /// Concrete Implementor - http://en.wikipedia.org/wiki/Bridge_Pattern 14 | /// 15 | internal class UdpClientAdapter : IStreamResource 16 | { 17 | private const int InfiniteTimeoutValue = 0; 18 | private UdpClient _udpClient; 19 | private List _readBuffer; 20 | 21 | public UdpClientAdapter(UdpClient udpClient) 22 | { 23 | Debug.Assert(udpClient != null, "Argument udpClient cannot be null."); 24 | 25 | _udpClient = udpClient; 26 | } 27 | 28 | public int InfiniteTimeout 29 | { 30 | get { return InfiniteTimeoutValue; } 31 | } 32 | 33 | public int ReadTimeout 34 | { 35 | get { return _udpClient.Client.ReceiveTimeout; } 36 | set { _udpClient.Client.ReceiveTimeout = value; } 37 | } 38 | 39 | public int WriteTimeout 40 | { 41 | get { return _udpClient.Client.SendTimeout; } 42 | set { _udpClient.Client.SendTimeout = value; } 43 | } 44 | 45 | public void DiscardInBuffer() 46 | { 47 | // no-op 48 | } 49 | 50 | public int Read(byte[] buffer, int offset, int count) 51 | { 52 | if (buffer == null) 53 | throw new ArgumentNullException("buffer"); 54 | if (offset < 0) 55 | throw new ArgumentOutOfRangeException("offset", "Argument offset must be greater than or equal to 0."); 56 | if (offset > buffer.Length) 57 | throw new ArgumentOutOfRangeException("offset", "Argument offset cannot be greater than the length of buffer."); 58 | if (count < 0) 59 | throw new ArgumentOutOfRangeException("count", "Argument count must be greater than or equal to 0."); 60 | if (count > buffer.Length - offset) 61 | throw new ArgumentOutOfRangeException("count", "Argument count cannot be greater than the length of buffer minus offset."); 62 | 63 | IPEndPoint remoteIpEndPoint = null; 64 | if (_readBuffer == null || _readBuffer.Count() == 0) 65 | _readBuffer = Read(ref remoteIpEndPoint).ToList(); 66 | 67 | if (_readBuffer.Count() < count) 68 | throw new IOException("Not enough bytes in the datagram."); 69 | 70 | _readBuffer.CopyTo(0, buffer, offset, count); 71 | _readBuffer.RemoveRange(0, count); 72 | 73 | return count; 74 | } 75 | 76 | public void Write(byte[] buffer, int offset, int count) 77 | { 78 | if (buffer == null) 79 | throw new ArgumentNullException("buffer"); 80 | if (offset < 0) 81 | throw new ArgumentOutOfRangeException("offset", "Argument offset must be greater than or equal to 0."); 82 | if (offset > buffer.Length) 83 | throw new ArgumentOutOfRangeException("offset", "Argument offset cannot be greater than the length of buffer."); 84 | 85 | _udpClient.Send(buffer.Skip(offset).ToArray(), count); 86 | } 87 | 88 | public void Dispose() 89 | { 90 | Dispose(true); 91 | GC.SuppressFinalize(this); 92 | } 93 | 94 | /// 95 | /// This method facilitates unit testing. 96 | /// 97 | internal virtual byte[] Read(ref IPEndPoint remoteIpEndPoint) 98 | { 99 | return _udpClient.Receive(ref remoteIpEndPoint); 100 | } 101 | 102 | protected virtual void Dispose(bool disposing) 103 | { 104 | if (disposing) 105 | DisposableUtility.Dispose(ref _udpClient); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/DiagnosticsRequestResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Net; 7 | using Modbus.Data; 8 | using Unme.Common; 9 | 10 | namespace Modbus.Message 11 | { 12 | internal class DiagnosticsRequestResponse : ModbusMessageWithData, IModbusMessage 13 | { 14 | public DiagnosticsRequestResponse() 15 | { 16 | } 17 | 18 | public DiagnosticsRequestResponse(ushort subFunctionCode, byte slaveAddress, RegisterCollection data) 19 | : base(slaveAddress, Modbus.Diagnostics) 20 | { 21 | SubFunctionCode = subFunctionCode; 22 | Data = data; 23 | } 24 | 25 | public override int MinimumFrameSize 26 | { 27 | get { return 6; } 28 | } 29 | 30 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "May implement addtional sub function codes in the future.")] 31 | public ushort SubFunctionCode 32 | { 33 | get { return MessageImpl.SubFunctionCode.Value; } 34 | set { MessageImpl.SubFunctionCode = value; } 35 | } 36 | 37 | public override string ToString() 38 | { 39 | Debug.Assert(SubFunctionCode == Modbus.DiagnosticsReturnQueryData, "Need to add support for additional sub-function."); 40 | 41 | return String.Format(CultureInfo.InvariantCulture, "Diagnostics message, sub-function return query data - {0}.", Data); 42 | } 43 | 44 | protected override void InitializeUnique(byte[] frame) 45 | { 46 | SubFunctionCode = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 47 | Data = new RegisterCollection(frame.Slice(4, 2).ToArray()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/IModbusMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Modbus.Message 4 | { 5 | /// 6 | /// A message built by the master (client) that initiates a Modbus transaction. 7 | /// 8 | public interface IModbusMessage 9 | { 10 | /// 11 | /// The function code tells the server what kind of action to perform. 12 | /// 13 | byte FunctionCode { get; set; } 14 | 15 | /// 16 | /// Address of the slave (server). 17 | /// 18 | byte SlaveAddress { get; set; } 19 | 20 | /// 21 | /// Composition of the slave address and protocol data unit. 22 | /// 23 | [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] 24 | byte[] MessageFrame { get; } 25 | 26 | /// 27 | /// Composition of the function code and message data. 28 | /// 29 | [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] 30 | byte[] ProtocolDataUnit { get; } 31 | 32 | /// 33 | /// A unique identifier assigned to a message when using the IP protocol. 34 | /// 35 | ushort TransactionId { get; set; } 36 | 37 | /// 38 | /// Initializes a modbus message from the specified message frame. 39 | /// 40 | /// The frame. 41 | void Initialize(byte[] frame); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/IModbusMessageWithData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Modbus.Message 4 | { 5 | /// 6 | /// A Modbus message containing variably sized data property. 7 | /// 8 | [Obsolete("Only used by obsolete method.")] 9 | public interface IModbusMessageWithData : IModbusMessage 10 | { 11 | /// 12 | /// The message data. 13 | /// 14 | TData[] Data { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/IModbusRequest.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Modbus.Message 3 | { 4 | /// 5 | /// Methods specific to a modbus request message. 6 | /// 7 | public interface IModbusRequest : IModbusMessage 8 | { 9 | /// 10 | /// Validate the specified response against the current request. 11 | /// 12 | void ValidateResponse(IModbusMessage response); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ModbusMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace Modbus.Message 5 | { 6 | internal abstract class ModbusMessage 7 | { 8 | private ModbusMessageImpl _messageImpl; 9 | 10 | public ModbusMessage() 11 | { 12 | _messageImpl = new ModbusMessageImpl(); 13 | } 14 | 15 | public ModbusMessage(byte slaveAddress, byte functionCode) 16 | { 17 | _messageImpl = new ModbusMessageImpl(slaveAddress, functionCode); 18 | } 19 | 20 | public ushort TransactionId 21 | { 22 | get { return _messageImpl.TransactionId; } 23 | set { _messageImpl.TransactionId = value; } 24 | } 25 | 26 | public byte FunctionCode 27 | { 28 | get { return _messageImpl.FunctionCode; } 29 | set { _messageImpl.FunctionCode = value; } 30 | } 31 | 32 | public byte SlaveAddress 33 | { 34 | get { return _messageImpl.SlaveAddress; } 35 | set { _messageImpl.SlaveAddress = value; } 36 | } 37 | 38 | public ModbusMessageImpl MessageImpl 39 | { 40 | get { return _messageImpl; } 41 | } 42 | 43 | public byte[] MessageFrame 44 | { 45 | get { return _messageImpl.MessageFrame; } 46 | } 47 | 48 | public virtual byte[] ProtocolDataUnit 49 | { 50 | get { return _messageImpl.ProtocolDataUnit; } 51 | } 52 | 53 | public abstract int MinimumFrameSize { get; } 54 | 55 | public void Initialize(byte[] frame) 56 | { 57 | if (frame.Length < MinimumFrameSize) 58 | throw new FormatException(String.Format(CultureInfo.InvariantCulture, "Message frame must contain at least {0} bytes of data.", MinimumFrameSize)); 59 | 60 | _messageImpl.Initialize(frame); 61 | InitializeUnique(frame); 62 | } 63 | 64 | protected abstract void InitializeUnique(byte[] frame); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ModbusMessageFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace Modbus.Message 5 | { 6 | internal static class ModbusMessageFactory 7 | { 8 | private const int MinRequestFrameLength = 3; 9 | 10 | public static T CreateModbusMessage(byte[] frame) where T : IModbusMessage, new() 11 | { 12 | IModbusMessage message = new T(); 13 | message.Initialize(frame); 14 | 15 | return (T) message; 16 | } 17 | 18 | public static IModbusMessage CreateModbusRequest(byte[] frame) 19 | { 20 | if (frame.Length < MinRequestFrameLength) 21 | throw new FormatException(String.Format(CultureInfo.InvariantCulture, "Argument 'frame' must have a length of at least {0} bytes.", MinRequestFrameLength)); 22 | 23 | IModbusMessage request; 24 | byte functionCode = frame[1]; 25 | 26 | switch (functionCode) 27 | { 28 | case Modbus.ReadCoils: 29 | case Modbus.ReadInputs: 30 | request = CreateModbusMessage(frame); 31 | break; 32 | case Modbus.ReadHoldingRegisters: 33 | case Modbus.ReadInputRegisters: 34 | request = CreateModbusMessage(frame); 35 | break; 36 | case Modbus.WriteSingleCoil: 37 | request = CreateModbusMessage(frame); 38 | break; 39 | case Modbus.WriteSingleRegister: 40 | request = CreateModbusMessage(frame); 41 | break; 42 | case Modbus.Diagnostics: 43 | request = CreateModbusMessage(frame); 44 | break; 45 | case Modbus.WriteMultipleCoils: 46 | request = CreateModbusMessage(frame); 47 | break; 48 | case Modbus.WriteMultipleRegisters: 49 | request = CreateModbusMessage(frame); 50 | break; 51 | case Modbus.ReadWriteMultipleRegisters: 52 | request = CreateModbusMessage(frame); 53 | break; 54 | default: 55 | throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Unsupported function code {0}", functionCode), "frame"); 56 | } 57 | 58 | return request; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ModbusMessageImpl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Net; 5 | using Modbus.Data; 6 | 7 | namespace Modbus.Message 8 | { 9 | /// 10 | /// Class holding all implementation shared between two or more message types. 11 | /// Interfaces expose subsets of type specific implementations. 12 | /// 13 | internal class ModbusMessageImpl 14 | { 15 | public ModbusMessageImpl() 16 | { 17 | } 18 | 19 | public ModbusMessageImpl(byte slaveAddress, byte functionCode) 20 | { 21 | SlaveAddress = slaveAddress; 22 | FunctionCode = functionCode; 23 | } 24 | 25 | public byte? ByteCount { get; set; } 26 | 27 | public byte? ExceptionCode { get; set; } 28 | 29 | public ushort TransactionId { get; set; } 30 | 31 | public byte FunctionCode { get; set; } 32 | 33 | public ushort? NumberOfPoints { get; set; } 34 | 35 | public byte SlaveAddress { get; set; } 36 | 37 | public ushort? StartAddress { get; set; } 38 | 39 | public ushort? SubFunctionCode { get; set; } 40 | 41 | public IModbusMessageDataCollection Data { get; set; } 42 | 43 | public byte[] MessageFrame 44 | { 45 | get 46 | { 47 | List frame = new List(); 48 | frame.Add(SlaveAddress); 49 | frame.AddRange(ProtocolDataUnit); 50 | 51 | return frame.ToArray(); 52 | } 53 | } 54 | 55 | public byte[] ProtocolDataUnit 56 | { 57 | get 58 | { 59 | List pdu = new List(); 60 | 61 | pdu.Add(FunctionCode); 62 | 63 | if (ExceptionCode.HasValue) 64 | pdu.Add(ExceptionCode.Value); 65 | 66 | if (SubFunctionCode.HasValue) 67 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) SubFunctionCode.Value))); 68 | 69 | if (StartAddress.HasValue) 70 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) StartAddress.Value))); 71 | 72 | if (NumberOfPoints.HasValue) 73 | pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) NumberOfPoints.Value))); 74 | 75 | if (ByteCount.HasValue) 76 | pdu.Add(ByteCount.Value); 77 | 78 | if (Data != null) 79 | pdu.AddRange(Data.NetworkBytes); 80 | 81 | return pdu.ToArray(); 82 | } 83 | } 84 | 85 | public void Initialize(byte[] frame) 86 | { 87 | if (frame == null) 88 | throw new ArgumentNullException("frame", "Argument frame cannot be null."); 89 | 90 | if (frame.Length < Modbus.MinimumFrameSize) 91 | throw new FormatException(String.Format(CultureInfo.InvariantCulture, "Message frame must contain at least {0} bytes of data.", Modbus.MinimumFrameSize)); 92 | 93 | SlaveAddress = frame[0]; 94 | FunctionCode = frame[1]; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ModbusMessageWithData.cs: -------------------------------------------------------------------------------- 1 | using Modbus.Data; 2 | 3 | namespace Modbus.Message 4 | { 5 | internal abstract class ModbusMessageWithData : ModbusMessage where TData : IModbusMessageDataCollection 6 | { 7 | public ModbusMessageWithData() 8 | { 9 | } 10 | 11 | public ModbusMessageWithData(byte slaveAddress, byte functionCode) 12 | : base(slaveAddress, functionCode) 13 | { 14 | } 15 | 16 | public TData Data 17 | { 18 | get { return (TData) MessageImpl.Data; } 19 | set { MessageImpl.Data = value; } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ReadCoilsInputsRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Net; 5 | 6 | namespace Modbus.Message 7 | { 8 | internal class ReadCoilsInputsRequest : ModbusMessage, IModbusRequest 9 | { 10 | public ReadCoilsInputsRequest() 11 | { 12 | } 13 | 14 | public ReadCoilsInputsRequest(byte functionCode, byte slaveAddress, ushort startAddress, ushort numberOfPoints) 15 | : base(slaveAddress, functionCode) 16 | { 17 | StartAddress = startAddress; 18 | NumberOfPoints = numberOfPoints; 19 | } 20 | 21 | public ushort StartAddress 22 | { 23 | get { return MessageImpl.StartAddress.Value; } 24 | set { MessageImpl.StartAddress = value; } 25 | } 26 | 27 | public override int MinimumFrameSize 28 | { 29 | get { return 6; } 30 | } 31 | 32 | public ushort NumberOfPoints 33 | { 34 | get 35 | { 36 | return MessageImpl.NumberOfPoints.Value; 37 | } 38 | set 39 | { 40 | if (value > Modbus.MaximumDiscreteRequestResponseSize) 41 | throw new ArgumentOutOfRangeException("NumberOfPoints", String.Format(CultureInfo.InvariantCulture, "Maximum amount of data {0} coils.", Modbus.MaximumDiscreteRequestResponseSize)); 42 | 43 | MessageImpl.NumberOfPoints = value; 44 | } 45 | } 46 | 47 | public override string ToString() 48 | { 49 | return String.Format(CultureInfo.InvariantCulture, "Read {0} {1} starting at address {2}.", NumberOfPoints, FunctionCode == Modbus.ReadCoils ? "coils" : "inputs", StartAddress); 50 | } 51 | 52 | public void ValidateResponse(IModbusMessage response) 53 | { 54 | var typedResponse = (ReadCoilsInputsResponse) response; 55 | 56 | // best effort validation - the same response for a request for 1 vs 6 coils (same byte count) will pass validation. 57 | var expectedByteCount = (NumberOfPoints + 7) / 8; 58 | if (expectedByteCount != typedResponse.ByteCount) 59 | { 60 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 61 | "Unexpected byte count. Expected {0}, received {1}.", 62 | expectedByteCount, 63 | typedResponse.ByteCount)); 64 | } 65 | } 66 | 67 | protected override void InitializeUnique(byte[] frame) 68 | { 69 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 70 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ReadCoilsInputsResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Linq; 4 | using Modbus.Data; 5 | using Unme.Common; 6 | 7 | namespace Modbus.Message 8 | { 9 | internal class ReadCoilsInputsResponse : ModbusMessageWithData, IModbusMessage 10 | { 11 | public ReadCoilsInputsResponse() 12 | { 13 | } 14 | 15 | public ReadCoilsInputsResponse(byte functionCode, byte slaveAddress, byte byteCount, DiscreteCollection data) 16 | : base(slaveAddress, functionCode) 17 | { 18 | ByteCount = byteCount; 19 | Data = data; 20 | } 21 | 22 | public byte ByteCount 23 | { 24 | get { return MessageImpl.ByteCount.Value; } 25 | set { MessageImpl.ByteCount = value; } 26 | } 27 | 28 | public override int MinimumFrameSize 29 | { 30 | get { return 3; } 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return String.Format(CultureInfo.InvariantCulture, 36 | "Read {0} {1} - {2}.", 37 | Data.Count(), 38 | FunctionCode == Modbus.ReadInputs ? "inputs" : "coils", 39 | Data); 40 | } 41 | 42 | protected override void InitializeUnique(byte[] frame) 43 | { 44 | if (frame.Length < 3 + frame[2]) 45 | throw new FormatException("Message frame data segment does not contain enough bytes."); 46 | 47 | ByteCount = frame[2]; 48 | Data = new DiscreteCollection(frame.Slice(3, ByteCount).ToArray()); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ReadHoldingInputRegistersRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Net; 6 | 7 | namespace Modbus.Message 8 | { 9 | internal class ReadHoldingInputRegistersRequest : ModbusMessage, IModbusRequest 10 | { 11 | public ReadHoldingInputRegistersRequest() 12 | { 13 | } 14 | 15 | public ReadHoldingInputRegistersRequest(byte functionCode, byte slaveAddress, ushort startAddress, ushort numberOfPoints) 16 | : base(slaveAddress, functionCode) 17 | { 18 | StartAddress = startAddress; 19 | NumberOfPoints = numberOfPoints; 20 | } 21 | 22 | public ushort StartAddress 23 | { 24 | get { return MessageImpl.StartAddress.Value; } 25 | set { MessageImpl.StartAddress = value; } 26 | } 27 | 28 | public override int MinimumFrameSize 29 | { 30 | get { return 6; } 31 | } 32 | 33 | public ushort NumberOfPoints 34 | { 35 | get 36 | { 37 | return MessageImpl.NumberOfPoints.Value; 38 | } 39 | set 40 | { 41 | if (value > Modbus.MaximumRegisterRequestResponseSize) 42 | throw new ArgumentOutOfRangeException("NumberOfPoints", String.Format(CultureInfo.InvariantCulture, "Maximum amount of data {0} registers.", Modbus.MaximumRegisterRequestResponseSize)); 43 | 44 | MessageImpl.NumberOfPoints = value; 45 | } 46 | } 47 | 48 | public override string ToString() 49 | { 50 | return String.Format(CultureInfo.InvariantCulture, "Read {0} {1} registers starting at address {2}.", NumberOfPoints, FunctionCode == Modbus.ReadHoldingRegisters ? "holding" : "input", StartAddress); 51 | } 52 | 53 | public void ValidateResponse(IModbusMessage response) 54 | { 55 | var typedResponse = response as ReadHoldingInputRegistersResponse; 56 | Debug.Assert(typedResponse != null, "Argument response should be of type ReadHoldingInputRegistersResponse."); 57 | var expectedByteCount = NumberOfPoints * 2; 58 | 59 | if (expectedByteCount != typedResponse.ByteCount) 60 | { 61 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 62 | "Unexpected byte count. Expected {0}, received {1}.", 63 | expectedByteCount, 64 | typedResponse.ByteCount)); 65 | } 66 | } 67 | 68 | protected override void InitializeUnique(byte[] frame) 69 | { 70 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 71 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ReadHoldingInputRegistersResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Linq; 4 | using Modbus.Data; 5 | using Unme.Common; 6 | 7 | namespace Modbus.Message 8 | { 9 | internal class ReadHoldingInputRegistersResponse : ModbusMessageWithData, IModbusMessage 10 | { 11 | public ReadHoldingInputRegistersResponse() 12 | { 13 | } 14 | 15 | public ReadHoldingInputRegistersResponse(byte functionCode, byte slaveAddress, RegisterCollection data) 16 | : base(slaveAddress, functionCode) 17 | { 18 | if (data == null) 19 | throw new ArgumentNullException("data"); 20 | 21 | ByteCount = data.ByteCount; 22 | Data = data; 23 | } 24 | 25 | public byte ByteCount 26 | { 27 | get { return MessageImpl.ByteCount.Value; } 28 | set { MessageImpl.ByteCount = value; } 29 | } 30 | 31 | public override int MinimumFrameSize 32 | { 33 | get { return 3; } 34 | } 35 | 36 | public override string ToString() 37 | { 38 | return String.Format(CultureInfo.InvariantCulture, "Read {0} {1} registers.", Data.Count, FunctionCode == Modbus.ReadHoldingRegisters ? "holding" : "input"); 39 | } 40 | 41 | protected override void InitializeUnique(byte[] frame) 42 | { 43 | if (frame.Length < MinimumFrameSize + frame[2]) 44 | throw new FormatException("Message frame does not contain enough bytes."); 45 | 46 | ByteCount = frame[2]; 47 | Data = new RegisterCollection(frame.Slice(3, ByteCount).ToArray()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/ReadWriteMultipleRegistersRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Linq; 5 | using Modbus.Data; 6 | using Unme.Common; 7 | 8 | namespace Modbus.Message 9 | { 10 | internal class ReadWriteMultipleRegistersRequest : ModbusMessage, IModbusRequest 11 | { 12 | private ReadHoldingInputRegistersRequest _readRequest; 13 | private WriteMultipleRegistersRequest _writeRequest; 14 | 15 | public ReadWriteMultipleRegistersRequest() 16 | { 17 | } 18 | 19 | public ReadWriteMultipleRegistersRequest(byte slaveAddress, ushort startReadAddress, ushort numberOfPointsToRead, ushort startWriteAddress, RegisterCollection writeData) 20 | : base(slaveAddress, Modbus.ReadWriteMultipleRegisters) 21 | { 22 | _readRequest = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, slaveAddress, startReadAddress, numberOfPointsToRead); 23 | _writeRequest = new WriteMultipleRegistersRequest(slaveAddress, startWriteAddress, writeData); 24 | } 25 | 26 | public override byte[] ProtocolDataUnit 27 | { 28 | get 29 | { 30 | // read and write PDUs without function codes 31 | byte[] read = _readRequest.ProtocolDataUnit.Slice(1, _readRequest.ProtocolDataUnit.Length - 1).ToArray(); 32 | byte[] write = _writeRequest.ProtocolDataUnit.Slice(1, _writeRequest.ProtocolDataUnit.Length - 1).ToArray(); 33 | 34 | return FunctionCode.ToSequence().Concat(read, write).ToArray(); 35 | } 36 | } 37 | 38 | public ReadHoldingInputRegistersRequest ReadRequest 39 | { 40 | get { return _readRequest; } 41 | } 42 | 43 | public WriteMultipleRegistersRequest WriteRequest 44 | { 45 | get { return _writeRequest; } 46 | } 47 | 48 | public override int MinimumFrameSize 49 | { 50 | get { return 11; } 51 | } 52 | 53 | public override string ToString() 54 | { 55 | return String.Format(CultureInfo.InvariantCulture, 56 | "Write {0} holding registers starting at address {1}, and read {2} registers starting at address {3}.", 57 | _writeRequest.NumberOfPoints, 58 | _writeRequest.StartAddress, 59 | _readRequest.NumberOfPoints, 60 | _readRequest.StartAddress); 61 | } 62 | 63 | public void ValidateResponse(IModbusMessage response) 64 | { 65 | var typedResponse = (ReadHoldingInputRegistersResponse) response; 66 | 67 | var expectedByteCount = ReadRequest.NumberOfPoints * 2; 68 | if (expectedByteCount != typedResponse.ByteCount) 69 | { 70 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 71 | "Unexpected byte count in response. Expected {0}, received {1}.", 72 | expectedByteCount, 73 | typedResponse.ByteCount)); 74 | } 75 | } 76 | 77 | protected override void InitializeUnique(byte[] frame) 78 | { 79 | if (frame.Length < MinimumFrameSize + frame[10]) 80 | throw new FormatException("Message frame does not contain enough bytes."); 81 | 82 | byte[] readFrame = frame.Slice(2, 4).ToArray(); 83 | byte[] writeFrame = frame.Slice(6, frame.Length - 6).ToArray(); 84 | byte[] header = { SlaveAddress, FunctionCode }; 85 | 86 | _readRequest = ModbusMessageFactory.CreateModbusMessage(header.Concat(readFrame).ToArray()); 87 | _writeRequest = ModbusMessageFactory.CreateModbusMessage(header.Concat(writeFrame).ToArray()); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/SlaveExceptionResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | 5 | namespace Modbus.Message 6 | { 7 | internal class SlaveExceptionResponse : ModbusMessage, IModbusMessage 8 | { 9 | private static readonly Dictionary _exceptionMessages = CreateExceptionMessages(); 10 | 11 | public SlaveExceptionResponse() 12 | { 13 | } 14 | 15 | public SlaveExceptionResponse(byte slaveAddress, byte functionCode, byte exceptionCode) 16 | : base(slaveAddress, functionCode) 17 | { 18 | SlaveExceptionCode = exceptionCode; 19 | } 20 | 21 | public override int MinimumFrameSize 22 | { 23 | get { return 3; } 24 | } 25 | 26 | public byte SlaveExceptionCode 27 | { 28 | get { return MessageImpl.ExceptionCode.Value; } 29 | set { MessageImpl.ExceptionCode = value; } 30 | } 31 | 32 | /// 33 | /// Returns a that represents the current . 34 | /// 35 | /// 36 | /// A that represents the current . 37 | /// 38 | public override string ToString() 39 | { 40 | string message = _exceptionMessages.ContainsKey(SlaveExceptionCode) ? _exceptionMessages[SlaveExceptionCode] : Resources.Unknown; 41 | return String.Format(CultureInfo.InvariantCulture, Resources.SlaveExceptionResponseFormat, Environment.NewLine, FunctionCode, SlaveExceptionCode, message); 42 | } 43 | 44 | internal static Dictionary CreateExceptionMessages() 45 | { 46 | Dictionary messages = new Dictionary(9); 47 | 48 | messages.Add(1, Resources.IllegalFunction); 49 | messages.Add(2, Resources.IllegalDataAddress); 50 | messages.Add(3, Resources.IllegalDataValue); 51 | messages.Add(4, Resources.SlaveDeviceFailure); 52 | messages.Add(5, Resources.Acknowlege); 53 | messages.Add(6, Resources.SlaveDeviceBusy); 54 | messages.Add(8, Resources.MemoryParityError); 55 | messages.Add(10, Resources.GatewayPathUnavailable); 56 | messages.Add(11, Resources.GatewayTargetDeviceFailedToRespond); 57 | 58 | return messages; 59 | } 60 | 61 | protected override void InitializeUnique(byte[] frame) 62 | { 63 | if (FunctionCode <= Modbus.ExceptionOffset) 64 | throw new FormatException(Resources.SlaveExceptionResponseInvalidFunctionCode); 65 | 66 | SlaveExceptionCode = frame[2]; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/WriteMultipleCoilsRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using Modbus.Data; 7 | using Unme.Common; 8 | 9 | namespace Modbus.Message 10 | { 11 | internal class WriteMultipleCoilsRequest : ModbusMessageWithData, IModbusRequest 12 | { 13 | public WriteMultipleCoilsRequest() 14 | { 15 | } 16 | 17 | public WriteMultipleCoilsRequest(byte slaveAddress, ushort startAddress, DiscreteCollection data) 18 | : base(slaveAddress, Modbus.WriteMultipleCoils) 19 | { 20 | StartAddress = startAddress; 21 | NumberOfPoints = (ushort) data.Count; 22 | ByteCount = (byte) ((data.Count + 7) / 8); 23 | Data = data; 24 | } 25 | 26 | public byte ByteCount 27 | { 28 | get { return MessageImpl.ByteCount.Value; } 29 | set { MessageImpl.ByteCount = value; } 30 | } 31 | 32 | public ushort NumberOfPoints 33 | { 34 | get 35 | { 36 | return MessageImpl.NumberOfPoints.Value; 37 | } 38 | set 39 | { 40 | if (value > Modbus.MaximumDiscreteRequestResponseSize) 41 | throw new ArgumentOutOfRangeException("NumberOfPoints", String.Format(CultureInfo.InvariantCulture, "Maximum amount of data {0} coils.", Modbus.MaximumDiscreteRequestResponseSize)); 42 | 43 | MessageImpl.NumberOfPoints = value; 44 | } 45 | } 46 | 47 | public ushort StartAddress 48 | { 49 | get { return MessageImpl.StartAddress.Value; } 50 | set { MessageImpl.StartAddress = value; } 51 | } 52 | 53 | public override int MinimumFrameSize 54 | { 55 | get { return 7; } 56 | } 57 | 58 | public override string ToString() 59 | { 60 | return String.Format(CultureInfo.InvariantCulture, "Write {0} coils starting at address {1}.", NumberOfPoints, StartAddress); 61 | } 62 | 63 | public void ValidateResponse(IModbusMessage response) 64 | { 65 | var typedResponse = (WriteMultipleCoilsResponse) response; 66 | 67 | if (StartAddress != typedResponse.StartAddress) 68 | { 69 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 70 | "Unexpected start address in response. Expected {0}, received {1}.", 71 | StartAddress, 72 | typedResponse.StartAddress)); 73 | } 74 | 75 | if (NumberOfPoints != typedResponse.NumberOfPoints) 76 | { 77 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 78 | "Unexpected number of points in response. Expected {0}, received {1}.", 79 | NumberOfPoints, 80 | typedResponse.NumberOfPoints)); 81 | } 82 | } 83 | 84 | protected override void InitializeUnique(byte[] frame) 85 | { 86 | if (frame.Length < MinimumFrameSize + frame[6]) 87 | throw new FormatException("Message frame does not contain enough bytes."); 88 | 89 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 90 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 91 | ByteCount = frame[6]; 92 | Data = new DiscreteCollection(frame.Slice(7, ByteCount).ToArray()); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/WriteMultipleCoilsResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Net; 4 | 5 | namespace Modbus.Message 6 | { 7 | internal class WriteMultipleCoilsResponse : ModbusMessage, IModbusMessage 8 | { 9 | public WriteMultipleCoilsResponse() 10 | { 11 | } 12 | 13 | public WriteMultipleCoilsResponse(byte slaveAddress, ushort startAddress, ushort numberOfPoints) 14 | : base(slaveAddress, Modbus.WriteMultipleCoils) 15 | { 16 | StartAddress = startAddress; 17 | NumberOfPoints = numberOfPoints; 18 | } 19 | 20 | public ushort NumberOfPoints 21 | { 22 | get 23 | { 24 | return MessageImpl.NumberOfPoints.Value; 25 | } 26 | set 27 | { 28 | if (value > Modbus.MaximumDiscreteRequestResponseSize) 29 | throw new ArgumentOutOfRangeException("NumberOfPoints", String.Format(CultureInfo.InvariantCulture, "Maximum amount of data {0} coils.", Modbus.MaximumDiscreteRequestResponseSize)); 30 | 31 | MessageImpl.NumberOfPoints = value; 32 | } 33 | } 34 | 35 | public ushort StartAddress 36 | { 37 | get { return MessageImpl.StartAddress.Value; } 38 | set { MessageImpl.StartAddress = value; } 39 | } 40 | 41 | public override int MinimumFrameSize 42 | { 43 | get { return 6; } 44 | } 45 | 46 | public override string ToString() 47 | { 48 | return String.Format(CultureInfo.InvariantCulture, "Wrote {0} coils starting at address {1}.", NumberOfPoints, StartAddress); 49 | } 50 | 51 | protected override void InitializeUnique(byte[] frame) 52 | { 53 | StartAddress = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 54 | NumberOfPoints = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/WriteMultipleRegistersRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using Modbus.Data; 7 | using Unme.Common; 8 | 9 | namespace Modbus.Message 10 | { 11 | internal class WriteMultipleRegistersRequest : ModbusMessageWithData, IModbusRequest 12 | { 13 | public WriteMultipleRegistersRequest() 14 | { 15 | } 16 | 17 | public WriteMultipleRegistersRequest(byte slaveAddress, ushort startAddress, RegisterCollection data) 18 | : base(slaveAddress, Modbus.WriteMultipleRegisters) 19 | { 20 | StartAddress = startAddress; 21 | NumberOfPoints = (ushort) data.Count; 22 | ByteCount = (byte) (data.Count * 2); 23 | Data = data; 24 | } 25 | 26 | public byte ByteCount 27 | { 28 | get { return MessageImpl.ByteCount.Value; } 29 | set { MessageImpl.ByteCount = value; } 30 | } 31 | 32 | public ushort NumberOfPoints 33 | { 34 | get 35 | { 36 | return MessageImpl.NumberOfPoints.Value; 37 | } 38 | set 39 | { 40 | if (value > Modbus.MaximumRegisterRequestResponseSize) 41 | throw new ArgumentOutOfRangeException("NumberOfPoints", String.Format(CultureInfo.InvariantCulture, "Maximum amount of data {0} registers.", Modbus.MaximumRegisterRequestResponseSize)); 42 | 43 | MessageImpl.NumberOfPoints = value; 44 | } 45 | } 46 | 47 | public ushort StartAddress 48 | { 49 | get { return MessageImpl.StartAddress.Value; } 50 | set { MessageImpl.StartAddress = value; } 51 | } 52 | 53 | public override int MinimumFrameSize 54 | { 55 | get { return 7; } 56 | } 57 | 58 | public override string ToString() 59 | { 60 | return String.Format(CultureInfo.InvariantCulture, "Write {0} holding registers starting at address {1}.", NumberOfPoints, StartAddress); 61 | } 62 | 63 | public void ValidateResponse(IModbusMessage response) 64 | { 65 | var typedResponse = (WriteMultipleRegistersResponse) response; 66 | 67 | if (StartAddress != typedResponse.StartAddress) 68 | { 69 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 70 | "Unexpected start address in response. Expected {0}, received {1}.", 71 | StartAddress, 72 | typedResponse.StartAddress)); 73 | } 74 | 75 | if (NumberOfPoints != typedResponse.NumberOfPoints) 76 | { 77 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 78 | "Unexpected number of points in response. Expected {0}, received {1}.", 79 | NumberOfPoints, 80 | typedResponse.NumberOfPoints)); 81 | } 82 | } 83 | 84 | protected override void InitializeUnique(byte[] frame) 85 | { 86 | if (frame.Length < MinimumFrameSize + frame[6]) 87 | throw new FormatException("Message frame does not contain enough bytes."); 88 | 89 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 90 | NumberOfPoints = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 91 | ByteCount = frame[6]; 92 | Data = new RegisterCollection(frame.Slice(7, ByteCount).ToArray()); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/WriteMultipleRegistersResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Net; 4 | 5 | namespace Modbus.Message 6 | { 7 | internal class WriteMultipleRegistersResponse : ModbusMessage, IModbusMessage 8 | { 9 | public WriteMultipleRegistersResponse() 10 | { 11 | } 12 | 13 | public WriteMultipleRegistersResponse(byte slaveAddress, ushort startAddress, ushort numberOfPoints) 14 | : base(slaveAddress, Modbus.WriteMultipleRegisters) 15 | { 16 | StartAddress = startAddress; 17 | NumberOfPoints = numberOfPoints; 18 | } 19 | 20 | public ushort NumberOfPoints 21 | { 22 | get 23 | { 24 | return MessageImpl.NumberOfPoints.Value; 25 | } 26 | set 27 | { 28 | if (value > Modbus.MaximumRegisterRequestResponseSize) 29 | { 30 | throw new ArgumentOutOfRangeException("NumberOfPoints", 31 | String.Format(CultureInfo.InvariantCulture, "Maximum amount of data {0} registers.", Modbus.MaximumRegisterRequestResponseSize)); 32 | } 33 | 34 | MessageImpl.NumberOfPoints = value; 35 | } 36 | } 37 | 38 | public ushort StartAddress 39 | { 40 | get { return MessageImpl.StartAddress.Value; } 41 | set { MessageImpl.StartAddress = value; } 42 | } 43 | 44 | public override int MinimumFrameSize 45 | { 46 | get { return 6; } 47 | } 48 | 49 | public override string ToString() 50 | { 51 | return String.Format(CultureInfo.InvariantCulture, "Wrote {0} holding registers starting at address {1}.", NumberOfPoints, StartAddress); 52 | } 53 | 54 | protected override void InitializeUnique(byte[] frame) 55 | { 56 | StartAddress = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 57 | NumberOfPoints = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4)); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/WriteSingleCoilRequestResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using Modbus.Data; 8 | using Unme.Common; 9 | 10 | namespace Modbus.Message 11 | { 12 | internal class WriteSingleCoilRequestResponse : ModbusMessageWithData, IModbusRequest 13 | { 14 | public WriteSingleCoilRequestResponse() 15 | { 16 | } 17 | 18 | public WriteSingleCoilRequestResponse(byte slaveAddress, ushort startAddress, bool coilState) 19 | : base(slaveAddress, Modbus.WriteSingleCoil) 20 | { 21 | StartAddress = startAddress; 22 | Data = new RegisterCollection(coilState ? Modbus.CoilOn : Modbus.CoilOff); 23 | } 24 | 25 | public override int MinimumFrameSize 26 | { 27 | get { return 6; } 28 | } 29 | 30 | public ushort StartAddress 31 | { 32 | get { return MessageImpl.StartAddress.Value; } 33 | set { MessageImpl.StartAddress = value; } 34 | } 35 | 36 | public override string ToString() 37 | { 38 | Debug.Assert(Data != null, "Argument Data cannot be null."); 39 | Debug.Assert(Data.Count() == 1, "Data should have a count of 1."); 40 | 41 | return String.Format(CultureInfo.InvariantCulture, 42 | "Write single coil {0} at address {1}.", 43 | Data.First() == Modbus.CoilOn ? 1 : 0, 44 | StartAddress); 45 | } 46 | 47 | public void ValidateResponse(IModbusMessage response) 48 | { 49 | var typedResponse = (WriteSingleCoilRequestResponse) response; 50 | 51 | if (StartAddress != typedResponse.StartAddress) 52 | { 53 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 54 | "Unexpected start address in response. Expected {0}, received {1}.", 55 | StartAddress, 56 | typedResponse.StartAddress)); 57 | } 58 | 59 | if (Data.First() != typedResponse.Data.First()) 60 | { 61 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 62 | "Unexpected data in response. Expected {0}, received {1}.", 63 | Data.First(), 64 | typedResponse.Data.First())); 65 | } 66 | } 67 | 68 | protected override void InitializeUnique(byte[] frame) 69 | { 70 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 71 | Data = new RegisterCollection(frame.Slice(4, 2).ToArray()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Message/WriteSingleRegisterRequestResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using Modbus.Data; 8 | 9 | namespace Modbus.Message 10 | { 11 | internal class WriteSingleRegisterRequestResponse : ModbusMessageWithData, IModbusRequest 12 | { 13 | public WriteSingleRegisterRequestResponse() 14 | { 15 | } 16 | 17 | public WriteSingleRegisterRequestResponse(byte slaveAddress, ushort startAddress, ushort registerValue) 18 | : base(slaveAddress, Modbus.WriteSingleRegister) 19 | { 20 | StartAddress = startAddress; 21 | Data = new RegisterCollection(registerValue); 22 | } 23 | 24 | public override int MinimumFrameSize 25 | { 26 | get { return 6; } 27 | } 28 | 29 | public ushort StartAddress 30 | { 31 | get { return MessageImpl.StartAddress.Value; } 32 | set { MessageImpl.StartAddress = value; } 33 | } 34 | 35 | public override string ToString() 36 | { 37 | Debug.Assert(Data != null, "Argument Data cannot be null."); 38 | Debug.Assert(Data.Count() == 1, "Data should have a count of 1."); 39 | 40 | return String.Format(CultureInfo.InvariantCulture, "Write single holding register {0} at address {1}.", Data[0], StartAddress); 41 | } 42 | 43 | public void ValidateResponse(IModbusMessage response) 44 | { 45 | var typedResponse = (WriteSingleRegisterRequestResponse) response; 46 | 47 | if (StartAddress != typedResponse.StartAddress) 48 | { 49 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 50 | "Unexpected start address in response. Expected {0}, received {1}.", 51 | StartAddress, 52 | typedResponse.StartAddress)); 53 | } 54 | 55 | if (Data.First() != typedResponse.Data.First()) 56 | { 57 | throw new IOException(String.Format(CultureInfo.InvariantCulture, 58 | "Unexpected data in response. Expected {0}, received {1}.", 59 | Data.First(), 60 | typedResponse.Data.First())); 61 | } 62 | } 63 | 64 | protected override void InitializeUnique(byte[] frame) 65 | { 66 | StartAddress = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 2)); 67 | Data = new RegisterCollection((ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 4))); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Modbus.cs: -------------------------------------------------------------------------------- 1 | namespace Modbus 2 | { 3 | /// 4 | /// Defines constants related to the Modbus protocol. 5 | /// 6 | internal static class Modbus 7 | { 8 | // supported function codes 9 | public const byte ReadCoils = 1; 10 | public const byte ReadInputs = 2; 11 | public const byte ReadHoldingRegisters = 3; 12 | public const byte ReadInputRegisters = 4; 13 | public const byte WriteSingleCoil = 5; 14 | public const byte WriteSingleRegister = 6; 15 | public const byte Diagnostics = 8; 16 | public const ushort DiagnosticsReturnQueryData = 0; 17 | public const byte WriteMultipleCoils = 15; 18 | public const byte WriteMultipleRegisters = 16; 19 | public const byte ReadWriteMultipleRegisters = 23; 20 | 21 | public const int MaximumDiscreteRequestResponseSize = 2040; 22 | public const int MaximumRegisterRequestResponseSize = 127; 23 | 24 | // modbus slave exception offset that is added to the function code, to flag an exception 25 | public const byte ExceptionOffset = 128; 26 | 27 | // modbus slave exception codes 28 | public const byte Acknowledge = 5; 29 | public const byte SlaveDeviceBusy = 6; 30 | 31 | // default setting for number of retries for IO operations 32 | public const int DefaultRetries = 3; 33 | 34 | // default number of milliseconds to wait after encountering an ACKNOWLEGE or SLAVE DEVIC BUSY slave exception response. 35 | public const int DefaultWaitToRetryMilliseconds = 250; 36 | 37 | // default setting for IO timeouts in milliseconds 38 | public const int DefaultTimeout = 1000; 39 | 40 | // smallest supported message frame size (sans checksum) 41 | public const int MinimumFrameSize = 2; 42 | 43 | public const ushort CoilOn = 0xFF00; 44 | public const ushort CoilOff = 0x0000; 45 | 46 | // IP slaves should be addressed by IP 47 | public const byte DefaultIpSlaveUnitId = 0; 48 | 49 | // An existing connection was forcibly closed by the remote host 50 | public const int ConnectionResetByPeer = 10054; 51 | 52 | // used by the ASCII tranport to indicate end of message 53 | public const string NewLine = "\r\n"; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/ModbusDevice.cd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Device\ModbusDevice.cs 8 | AAAAAAAAAAAAAAAAAAAAAAQAAAAAgAAAAAAAAAAAAAA= 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Device\ModbusIpMaster.cs 18 | EAAAAAAAIgAAIBAAAAACABAAAACAAAAAACAAACAAIAg= 19 | 20 | 21 | 22 | 23 | 24 | Device\ModbusMaster.cs 25 | EAgAAAAAIAAAIBAAAAACABAAAACAAgAAAAAAACEAAAg= 26 | 27 | 28 | 29 | 30 | 31 | 32 | Device\ModbusSerialMaster.cs 33 | AAAAAAAAAgAAEQCAAAAAAAAAAAAAAAAAAAAAAAAABAA= 34 | 35 | 36 | 37 | 38 | 39 | 40 | Device\ModbusSlave.cs 41 | EAgAAAAAAAAAQGAAAAACAQAAAACAAgAAAABEAAAAAAg= 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Device\ModbusSerialSlave.cs 51 | AAAAAAAAAAAAEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 52 | 53 | 54 | 55 | 56 | 57 | Device\ModbusTcpSlave.cs 58 | AAAAAAAAAAAAAEAAQAAACAAQAAAAAAAEACAAAAAAQQA= 59 | 60 | 61 | 62 | 63 | 64 | Device\ModbusUdpSlave.cs 65 | ACAAAAAAAAAAAEAAAAAAAAIAAAAAAAAAAAAAAAAAIAA= 66 | 67 | 68 | 69 | 70 | 71 | Device\IModbusMaster.cs 72 | EAAAAAAAIAAAIBAAAAACABQAAACAAAAAAAAAACAAAAg= 73 | 74 | 75 | 76 | 77 | 78 | Device\IModbusSerialMaster.cs 79 | AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA= 80 | 81 | 82 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/ModbusTransport.cd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | IO\ModbusTransport.cs 8 | AAAAIgAAAAAIAEAAAAAAAAAAAAIAAAEBAAAAAAFAgAA= 9 | 10 | 11 | 12 | 13 | 14 | IO\ModbusIpTransport.cs 15 | AAAAAAAAAAAAEAgAAAAAAAAAIAIAQAAAAAAAAIAAgAA= 16 | 17 | 18 | 19 | 20 | 21 | IO\ModbusAsciiTransport.cs 22 | AAAAAAAAAAAIAEAAAAAAABAAAAAAAAEAAAAAAQAAgAA= 23 | 24 | 25 | 26 | 27 | 28 | IO\ModbusRtuTransport.cs 29 | AAACAAAAAAAIAEAAAAAAAAAgAgAAAAEAAAABAQAAgAA= 30 | 31 | 32 | 33 | 34 | 35 | IO\ModbusSerialTransport.cs 36 | AAAAAABAAAAAAEAAAABAAAAIAAQAAAAAAAAAAQFAAAA= 37 | 38 | 39 | 40 | 41 | 42 | IO\ModbusUdpTransport.cs 43 | AAAAAAAAAAAIAEAAAAAAABAAAAgAAAEAAAAAAAEAAAA= 44 | 45 | 46 | 47 | 48 | 49 | IO\ModbusTcpTransport.cs 50 | AAAACAAAAAAIAEAAAAAAABAAAAAAAAEAAAAAAAEAAAA= 51 | 52 | 53 | -------------------------------------------------------------------------------- /NModbus/src/Modbus/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | [assembly: AssemblyTitle("Modbus")] 7 | [assembly: AssemblyProduct("NModbus")] 8 | [assembly: AssemblyCopyright("Licensed under MIT License.")] 9 | [assembly: AssemblyDescription("Provides connectivity to Modbus slave compatible devices and applications.")] 10 | [assembly: ComVisible(false)] 11 | [assembly: CLSCompliant(false)] 12 | [assembly: Guid("a2ec5378-e1b7-4bb0-b696-1c657407eeb9")] 13 | [assembly: AssemblyVersion("1.9.0.0")] 14 | [assembly: AssemblyFileVersion("1.9.0.0")] 15 | 16 | 17 | 18 | #if SIGNED 19 | [assembly: InternalsVisibleTo(@"FtdAdapter, PublicKey=00240000048000009400000006020000002400005253413100040000010001008164fa1d8adb85038b7d1ad4a4dcb9d680e7b23398d318dcf6673432bca1256c191e8d82f90d4221d81d1a9065830c74d4d0062046707397e3dcc179c98c443cab8501dba986e78424fd395675281a3574cf7554da4aee1ce8a97e1826bc4a45856b1f5c4479c9e5051bf78999f9eb035a9987efae198d5d599c03e743c207e9")] 20 | # else 21 | [assembly: InternalsVisibleTo(@"FtdAdapter")] 22 | [assembly: InternalsVisibleTo(@"Modbus.UnitTests")] 23 | [assembly: InternalsVisibleTo(@"DynamicProxyGenAssembly2")] 24 | #endif 25 | -------------------------------------------------------------------------------- /NModbus/src/MySample/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /NModbus/src/MySample/MySample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | 9.0.30729 6 | 2.0 7 | {72FA8AB6-CE77-4578-8202-0DD32264783E} 8 | Exe 9 | Properties 10 | MySample 11 | MySample 12 | v3.5 13 | 14 | 15 | true 16 | full 17 | false 18 | bin\Debug\ 19 | DEBUG;TRACE 20 | prompt 21 | 4 22 | 23 | 24 | pdbonly 25 | true 26 | bin\Release\ 27 | TRACE 28 | prompt 29 | 4 30 | true 31 | 32 | 33 | bin\SignedRelease\ 34 | TRACE 35 | true 36 | pdbonly 37 | AnyCPU 38 | true 39 | GlobalSuppressions.cs 40 | prompt 41 | 42 | 43 | 44 | False 45 | ..\..\lib\log4net\log4net.dll 46 | 47 | 48 | 49 | 3.5 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {16FFB4F2-5556-439E-8729-92FB3425EF1F} 60 | FtdAdapter 61 | 62 | 63 | {FF96B252-2B24-44A1-A09C-6401B5D7ED23} 64 | Modbus 65 | 66 | 67 | 68 | 69 | 70 | 71 | 78 | -------------------------------------------------------------------------------- /NModbus/src/MySample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("MySample")] 6 | [assembly: AssemblyProduct("NModbus")] 7 | [assembly: AssemblyCopyright("Licensed under MIT License.")] 8 | [assembly: ComVisible(false)] 9 | [assembly: CLSCompliant(true)] 10 | [assembly: Guid("f2ba4cc2-ad31-4492-bfbf-377b50b9cbf2")] 11 | [assembly: AssemblyVersion("1.9.0.0")] 12 | [assembly: AssemblyFileVersion("1.9.0.0")] 13 | -------------------------------------------------------------------------------- /NModbus/tools/MbUnit/MbUnit.Framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/MbUnit/MbUnit.Framework.dll -------------------------------------------------------------------------------- /NModbus/tools/MbUnit/MbUnit.Tasks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/MbUnit/MbUnit.Tasks.dll -------------------------------------------------------------------------------- /NModbus/tools/MbUnit/QuickGraph.Algorithms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/MbUnit/QuickGraph.Algorithms.dll -------------------------------------------------------------------------------- /NModbus/tools/MbUnit/QuickGraph.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/MbUnit/QuickGraph.dll -------------------------------------------------------------------------------- /NModbus/tools/RhinoMocks/Rhino.Mocks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/RhinoMocks/Rhino.Mocks.dll -------------------------------------------------------------------------------- /NModbus/tools/jamod/SerialSlave.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/jamod/SerialSlave.class -------------------------------------------------------------------------------- /NModbus/tools/jamod/SerialSlave.java: -------------------------------------------------------------------------------- 1 | import net.wimpi.modbus.*; 2 | import net.wimpi.modbus.net.*; 3 | import net.wimpi.modbus.procimg.*; 4 | import net.wimpi.modbus.util.*; 5 | 6 | // class implementing a simple Modbus slave 7 | public class SerialSlave 8 | { 9 | 10 | public static void main(String[] args) 11 | { 12 | 13 | ModbusSerialListener listener = null; 14 | SimpleProcessImage spi = new SimpleProcessImage(); 15 | String portname = args[0]; 16 | 17 | if (Modbus.debug) System.out.println("jModbus ModbusSerial Slave"); 18 | 19 | try 20 | { 21 | //1. Prepare a process image 22 | spi = new SimpleProcessImage(); 23 | 24 | for (int i = 0; i < 3000; i++) 25 | spi.addDigitalOut(new SimpleDigitalOut(false)); 26 | 27 | 28 | for (int i = 0; i < 3000; i++) 29 | spi.addDigitalIn(new SimpleDigitalIn(false)); 30 | 31 | for (int i = 0; i < 3000; i++) 32 | spi.addRegister(new SimpleRegister(0)); 33 | 34 | for (int i = 0; i < 3000; i++) 35 | spi.addInputRegister(new SimpleInputRegister(0)); 36 | 37 | //2. Create the coupler and set the slave identity 38 | ModbusCoupler.getReference().setProcessImage(spi); 39 | ModbusCoupler.getReference().setMaster(false); 40 | ModbusCoupler.getReference().setUnitID(1); 41 | 42 | //3. Set up serial parameters 43 | SerialParameters params = new SerialParameters(); 44 | params.setPortName(portname); 45 | params.setBaudRate(9600); 46 | params.setDatabits(8); 47 | params.setParity("None"); 48 | params.setStopbits(1); 49 | params.setEncoding(args[1]); 50 | params.setEcho(false); 51 | if (Modbus.debug) System.out.println("Encoding [" + params.getEncoding() + "]"); 52 | 53 | //4. Set up serial listener 54 | listener = new ModbusSerialListener(params); 55 | listener.setListening(true); 56 | 57 | } 58 | catch (Exception ex) 59 | { 60 | ex.printStackTrace(); 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /NModbus/tools/jamod/TcpSlave.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/jamod/TcpSlave.class -------------------------------------------------------------------------------- /NModbus/tools/jamod/TcpSlave.java: -------------------------------------------------------------------------------- 1 | import net.wimpi.modbus.ModbusCoupler; 2 | import net.wimpi.modbus.Modbus; 3 | import net.wimpi.modbus.net.ModbusTCPListener; 4 | import net.wimpi.modbus.procimg.SimpleDigitalIn; 5 | import net.wimpi.modbus.procimg.SimpleDigitalOut; 6 | import net.wimpi.modbus.procimg.SimpleInputRegister; 7 | import net.wimpi.modbus.procimg.SimpleProcessImage; 8 | import net.wimpi.modbus.procimg.SimpleRegister; 9 | 10 | 11 | /** 12 | * Class implementing a simple Modbus/TCP slave. 13 | * A simple process image is available to test 14 | * functionality and behaviour of the implementation. 15 | * 16 | * @author Dieter Wimberger 17 | * @version 1.2rc1 (09/11/2004) 18 | */ 19 | public class TcpSlave { 20 | 21 | 22 | public static void main(String[] args) { 23 | 24 | ModbusTCPListener listener = null; 25 | SimpleProcessImage spi = null; 26 | int port = Modbus.DEFAULT_PORT; 27 | 28 | try { 29 | if(args != null && args.length ==1) { 30 | port = Integer.parseInt(args[0]); 31 | } 32 | System.out.println("jModbus Modbus Slave (Server)"); 33 | 34 | //1. Prepare a process image 35 | spi = new SimpleProcessImage(); 36 | 37 | for (int i = 0; i < 3000; i++) 38 | spi.addDigitalOut(new SimpleDigitalOut(false)); 39 | 40 | 41 | for (int i = 0; i < 3000; i++) 42 | spi.addDigitalIn(new SimpleDigitalIn(false)); 43 | 44 | for (int i = 0; i < 3000; i++) 45 | spi.addRegister(new SimpleRegister(0)); 46 | 47 | for (int i = 0; i < 3000; i++) 48 | spi.addInputRegister(new SimpleInputRegister(0)); 49 | 50 | 51 | //2. create the coupler holding the image 52 | ModbusCoupler.getReference().setProcessImage(spi); 53 | ModbusCoupler.getReference().setMaster(false); 54 | ModbusCoupler.getReference().setUnitID(1); 55 | 56 | //3. create a listener with 3 threads in pool 57 | if (Modbus.debug) System.out.println("Listening..."); 58 | listener = new ModbusTCPListener(3); 59 | listener.setAddress(java.net.InetAddress.getByAddress(new byte[] {127, 0, 0, 1})); 60 | listener.setPort(port); 61 | listener.start(); 62 | 63 | } catch (Exception ex) { 64 | ex.printStackTrace(); 65 | } 66 | }//main 67 | 68 | 69 | }//class TCPSlaveTest 70 | -------------------------------------------------------------------------------- /NModbus/tools/jamod/comm.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/jamod/comm.jar -------------------------------------------------------------------------------- /NModbus/tools/jamod/jamod.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/jamod/jamod.jar -------------------------------------------------------------------------------- /NModbus/tools/jamod/javax.comm.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Drivers loaded by the Java Communications API standard extension 3 | # at initialization time 4 | # 5 | # Format: 6 | # Each line must contain ONE driver definition only 7 | # Each line must be of the form: 8 | # driver= 9 | # No spaces or tabs in the line. 10 | # ClassName must implement the interface javax.comm.CommDriver 11 | # example: driver=Win32Serial 12 | # 13 | # 14 | # The hash(#) character indicates comment till end of line. 15 | # 16 | # Windows Serial Driver 17 | Driver=com.sun.comm.Win32Driver 18 | -------------------------------------------------------------------------------- /NModbus/tools/jamod/win32com.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/jamod/win32com.dll -------------------------------------------------------------------------------- /NModbus/tools/nant/NantGoogleCode.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/nant/NantGoogleCode.dll -------------------------------------------------------------------------------- /NModbus/tools/ncover/NCoverExplorer.NAntTasks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/ncover/NCoverExplorer.NAntTasks.dll -------------------------------------------------------------------------------- /NModbus/tools/nmodbus/Modbus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/nmodbus/Modbus.dll -------------------------------------------------------------------------------- /NModbus/tools/nmodbus/TestDriver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO.Ports; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | using Modbus.Device; 8 | 9 | /// 10 | /// Summary description for Class1 11 | /// 12 | public class TestDriver 13 | { 14 | static void Main(string[] args) 15 | { 16 | try 17 | { 18 | using (TcpClient client = new TcpClient("127.0.0.1", 502)) 19 | { 20 | client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); 21 | ModbusTcpMaster master = ModbusTcpMaster.CreateTcp(client); 22 | 23 | // read five input values 24 | ushort startAddress = 100; 25 | ushort numInputs = 5; 26 | bool[] inputs = master.ReadInputs(startAddress, numInputs); 27 | 28 | for (int i = 0; i < numInputs; i++) 29 | Console.WriteLine("Input {0}={1}", startAddress + i, inputs[i] ? 1 : 0); 30 | 31 | while (true) 32 | { 33 | } 34 | } 35 | } 36 | catch (Exception e) 37 | { 38 | Console.WriteLine(e.Message); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /NModbus/tools/nmodbus/TestDriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/nmodbus/TestDriver.exe -------------------------------------------------------------------------------- /NModbus/tools/nmodbus/log4net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mesta1/nmodbus/3df3eead53167e690f493fb8b807fdb10cb11fd8/NModbus/tools/nmodbus/log4net.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a fork of NModbus (https://code.google.com/archive/p/nmodbus/downloads) version 1.10, that is the last stable version (1.11 has a bug documented here http://www.mesta-automation.com/modbus-with-c-sharp-libraries-examples/#comment-392 and here http://www.mesta-automation.com/modbus-with-c-sharp-libraries-examples/#comment-562). 2 | 3 | If you are looking for something similar, I would recommend NModbus4 (https://github.com/nmodbus4/nmodbus4), which is a more up-to-date and maintained fork. 4 | --------------------------------------------------------------------------------