├── Mono
├── MacSlave.7z
└── LinuxSlave.7z
├── exe
└── Modbus Slave Simulation.7z
├── ModbusSlaveSimulation
├── Resources
│ ├── Logo.png
│ ├── Modbus.dll
│ ├── DarkBlue.png
│ ├── log4net.dll
│ ├── Unme.Common.dll
│ ├── FunctionCodes.png
│ ├── ModbusRTUTCP.ico
│ └── README.txt
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Program.cs
├── ModbusSlaveSimulation.csproj
├── Form1.cs
└── Form1.resx
├── screenshots
└── Modbus Slave Simulation.png
├── LICENSE
├── ModbusSlaveSimulation.sln
├── .gitattributes
├── README.md
└── .gitignore
/Mono/MacSlave.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/Mono/MacSlave.7z
--------------------------------------------------------------------------------
/Mono/LinuxSlave.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/Mono/LinuxSlave.7z
--------------------------------------------------------------------------------
/exe/Modbus Slave Simulation.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/exe/Modbus Slave Simulation.7z
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/Logo.png
--------------------------------------------------------------------------------
/screenshots/Modbus Slave Simulation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/screenshots/Modbus Slave Simulation.png
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/Modbus.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/Modbus.dll
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/DarkBlue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/DarkBlue.png
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/log4net.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/log4net.dll
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/Unme.Common.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/Unme.Common.dll
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/FunctionCodes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/FunctionCodes.png
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/ModbusRTUTCP.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GitHubDragonFly/ModbusSlaveSimulation/HEAD/ModbusSlaveSimulation/Resources/ModbusRTUTCP.ico
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 GitHubDragonFly
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
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 ModbusSlaveSimulation.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29613.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModbusSlaveSimulation", "ModbusSlaveSimulation\ModbusSlaveSimulation.csproj", "{B65F0AAE-0B33-44D3-BFA1-3EB53A0CFAC5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {B65F0AAE-0B33-44D3-BFA1-3EB53A0CFAC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {B65F0AAE-0B33-44D3-BFA1-3EB53A0CFAC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {B65F0AAE-0B33-44D3-BFA1-3EB53A0CFAC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {B65F0AAE-0B33-44D3-BFA1-3EB53A0CFAC5}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {4D21C88B-AC1C-4186-8723-E4E3A9AD01A5}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ModbusSlaveSimulation")]
9 | [assembly: AssemblyDescription("Modbus Slave Simulation with nModbus libraries - RTU / TCP / UDP / ASCIIoverRTU")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ModbusSlaveSimulation")]
13 | [assembly: AssemblyCopyright("Copyright © 2020 Godra")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("b65f0aae-0b33-44d3-bfa1-3eb53a0cfac5")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Resources/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.
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace ModbusSlaveSimulation
5 | {
6 | static class Program
7 | {
8 | static Program()
9 | {
10 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
11 | }
12 |
13 | ///
14 | /// The main entry point for the application.
15 | ///
16 | [STAThread]
17 | static void Main()
18 | {
19 | Application.EnableVisualStyles();
20 | Application.SetCompatibleTextRenderingDefault(false);
21 | Application.Run(new Form1());
22 | }
23 |
24 | static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
25 | {
26 | if (args.Name == null)
27 | {
28 | throw new NullReferenceException("Item name is null.");
29 | }
30 | else
31 | {
32 | if (!args.Name.StartsWith("ModbusSlave") && (args.Name.StartsWith("Modbus") || args.Name.StartsWith("log4net") || args.Name.StartsWith("Unme.Common")))
33 | {
34 | if (args.Name.Substring(0, args.Name.IndexOf(',')) == "Modbus")
35 | return System.Reflection.Assembly.Load(Properties.Resources.Modbus);
36 | if (args.Name.Substring(0, args.Name.IndexOf(',')) == "log4net")
37 | return System.Reflection.Assembly.Load(Properties.Resources.log4net);
38 | if (args.Name.Substring(0, args.Name.IndexOf(',')) == "Unme.Common")
39 | return System.Reflection.Assembly.Load(Properties.Resources.Unme_Common);
40 | }
41 | return null;
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/ModbusSlaveSimulation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B65F0AAE-0B33-44D3-BFA1-3EB53A0CFAC5}
8 | WinExe
9 | ModbusSlaveSimulation
10 | ModbusSlaveSimulation
11 | v4.0
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 | Resources\ModbusRTUTCP.ico
40 |
41 |
42 |
43 | False
44 | Resources\log4net.dll
45 | False
46 |
47 |
48 | False
49 | Resources\Modbus.dll
50 | False
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | False
64 | Resources\Unme.Common.dll
65 | False
66 |
67 |
68 |
69 |
70 | Form
71 |
72 |
73 | Form1.cs
74 |
75 |
76 |
77 |
78 | Form1.cs
79 |
80 |
81 | ResXFileCodeGenerator
82 | Resources.Designer.cs
83 | Designer
84 |
85 |
86 | True
87 | Resources.resx
88 | True
89 |
90 |
91 | SettingsSingleFileGenerator
92 | Settings.Designer.cs
93 |
94 |
95 | True
96 | Settings.settings
97 | True
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Reality Check
2 | Just for those of you who might be concerned about the Climate Change, here are couple of sobering insights:
3 | - Neil deGrasse Tyson's perspective on climate change: [YouTube Video](https://www.youtube.com/watch?v=tRA2SfSk2Tc)
4 | - My perspective, with statements from two AI entities: [Climate Change](https://githubdragonfly.github.io/viewers/templates/Climate%20Change.txt)
5 |
6 | # ModbusSlaveSimulation
7 | Standalone Windows app supporting Modbus RTU, TCP, UDP and ASCIIoverRTU protocols for simulation.
8 |
9 | Also included are its Mono versions for Linux and Mac OS X, these are VB Net versions so:
10 | - For Linux you will have to install `mono-complete` and `mono-vbnc` packages
11 | - Mac might be different depending on the OS X version, maybe install `mono` and `mono-basic` packages
12 |
13 | If a firewall is enabled then it might prompt you to allow this app to communicate on the network:
14 | - Normally it should be allowed to communicate on the private network otherwise it might not work properly
15 | - Do not allow public access unless you know what you are doing
16 | - Once the testing is done then remember to remove this app from the firewall's list of allowed apps
17 |
18 | The app is designed to allow running multiple instances of the app at the same time, for example:
19 | - Use the same protocol for each instance but with different port numbers, similar to:
20 | - IP 127.0.0.1 TCP Port 501 and IP 127.0.0.1 TCP Port 502
21 | - Use a mix of different protocols with help of other tools (like [com0com](https://pete.akeo.ie/search/label/com0com) for RTU protocol on Windows)
22 |
23 | The app should service requests for any valid Modbus slave ID.
24 |
25 | This is all based on modified [nModbus](https://code.google.com/p/nmodbus/) .NET 3.5 libraries:
26 | - MIT Licensed Copyright (c) 2006 Scott Alexander:
27 | - These are included as a resource for Windows version but are separate for Mono version
28 |
29 | Intended to be used as a quick testing tool:
30 | - Can be tested with its counterpart [ModbusMaster](https://github.com/GitHubDragonFly/ModbusMaster) (check the video further below)
31 | - Or maybe use the [AdvancedHMI](https://www.advancedhmi.com/) software instead since it is highly functional and free.
32 |
33 | # Screenshot
34 |
35 | 
36 |
37 | # Functionality
38 | - All values can be set before the connection is established - Coils, Discrete Inputs, Input Registers, Holding Registers.
39 | - The Data Grid View is set to initially show 20 rows of addresses but can be changed within the `Row Count` dropdown to show more or all rows if necessary.
40 | - In the Data Grid View, selected with the `I/O Address Range` dropdown, double-click the value to change it:
41 | - Boolean values will flip between 0 and 1
42 | - Uint16 values require unsigned integer value between 0 and 65535
43 | - Discrete Inputs and Input Registers provide `read-only` access to the Master application:
44 | - MODBUS device designated as `Master` can ONLY send requests to read these values
45 | - These values should be manipulated by the user directly in the simulator otherwise they will not be changing
46 | - Coils and Holding Registers provide `read/write` access to the Master application:
47 | - MODBUS device designated as `Master` can send requests to read these values as well as send requests to have these values be modified
48 | - These values can also be manipulated by the user directly in the simulator if necessary
49 | - For `RTU` and `ASCIIoverRTU` protocols, on a single PC, this simulator can use the help of:
50 | - [com0com](https://pete.akeo.ie/search/label/com0com) program for Windows to provide virtual serial port pairs
51 | - [tty0tty](https://github.com/freemed/tty0tty) program for Linux to provide virtual serial port pairs
52 | - Additional TextBox allows manual input of the serial port:
53 | - Mainly intended for Linux so those `tty0tty` virtual port pairs, like `/dev/tnt0` <=> `/dev/tnt1`, could be accessed
54 | - This box was removed in the Mac Mono version
55 | - The library also supports Masked Bit Write, function code 22 (0x16H or FC22).
56 |
57 | # Usage
58 |
59 | ## -> For Windows
60 | - Either use Windows executable files from the `exe` folder or follow the instructions below to build it yourself:
61 | - Download and install Visual Studio community edition (ideally 2019).
62 | - Download and extract the zip file of this project.
63 | - Open this as an existing project in Visual Studio and, on the menu, do:
64 | - Build/Build Solution (or press Ctrl-Shift-B).
65 | - Debug/Start Debugging (or press F5) to run the app.
66 | - Locate created EXE file in the `/bin/Debug` folder and copy it over to your preferred folder or Desktop
67 | - For testing RTU protocols use [com0com](https://pete.akeo.ie/search/label/com0com) to create virtual serial ports
68 |
69 | ## -> For Mono
70 | - Make sure that Mono is installed on your computer:
71 | - Both `mono-complete` and `mono-vbnc` packages for Linux
72 | - For Mac you might need to experiment, maybe `mono` and `mono-basic` packages
73 | - Download and extract the zip file of this project and locate Mono archive in the `Mono` folder.
74 | - Extract 4 files and potentially rename the newly created folder and/or exe file to something shorter if you wish (just to make the terminal navigation quicker).
75 | - Open the terminal, navigate to the folder and type: `sudo mono ModbusSlaveSimulation.exe`:
76 | - On Mac you might need to switch to the superuser `su` account
77 | - For testing RTU protocols, on Linux you can possibly install and use [tty0tty](https://github.com/freemed/tty0tty) virtual ports while on Mac the later OS X versions seem to have pseudo terminals - pairs of devices such as `/dev/ptyp3` and `/dev/ttyp3`.
78 |
79 | Note for Mac users: this was tested on an old iMac G5 PowerPC computer with Mono v2.10.2. Some odd behaviour was present in a sense that the app was loosing focus thus disrupting continuous TCP communication. There is a text box with red X that you can click to try to maintain focus (if you do something else afterwards then click it again). Since I cannot test it in any other way then it is left for you to experiment.
80 |
81 | # Video
82 |
83 | https://github.com/user-attachments/assets/3058bbad-4691-4670-95d9-b2f011199984
84 |
85 | # License
86 | Licensed under MIT license - see also the NModbus MIT License within the README.txt file inside the Resources folder.
87 |
88 | # Trademarks
89 | Any and all trademarks, either directly or indirectly mentioned in this project, belong to their respective owners.
90 |
91 | # Useful Resources
92 | The AdvancedHMI website [forum](https://www.advancedhmi.com/forum/), which is another open source project.
93 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
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 ModbusSlaveSimulation.Properties {
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", "16.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("ModbusSlaveSimulation.Properties.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 resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap DarkBlue {
67 | get {
68 | object obj = ResourceManager.GetObject("DarkBlue", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | internal static System.Drawing.Bitmap FunctionCodes {
77 | get {
78 | object obj = ResourceManager.GetObject("FunctionCodes", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Byte[].
85 | ///
86 | internal static byte[] log4net {
87 | get {
88 | object obj = ResourceManager.GetObject("log4net", resourceCulture);
89 | return ((byte[])(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | internal static System.Drawing.Bitmap Logo {
97 | get {
98 | object obj = ResourceManager.GetObject("Logo", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Byte[].
105 | ///
106 | internal static byte[] Modbus {
107 | get {
108 | object obj = ResourceManager.GetObject("Modbus", resourceCulture);
109 | return ((byte[])(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
115 | ///
116 | internal static System.Drawing.Icon ModbusRTUTCP {
117 | get {
118 | object obj = ResourceManager.GetObject("ModbusRTUTCP", resourceCulture);
119 | return ((System.Drawing.Icon)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Looks up a localized string similar to NModbus
125 | ///
126 | ///What is it?
127 | ///-----------
128 | ///NModbus is a C# 3.0 implementation of the Modbus protocol.
129 | ///
130 | ///More information at the NModbus project web site http://nmodbus.com/
131 | ///
132 | ///
133 | ///The Latest Version
134 | ///------------------
135 | ///The latest binary distribution can be found on the NModbus project web site http://nmodbus.com/
136 | ///
137 | ///The latest source for the project can be found at the NModbus project's google code page http://code.google.com/p/nmodbus/
138 | ///
139 | ///
140 | ///Documentation
141 | ///-------------
142 | ///Documentation is available in chm forma [rest of string was truncated]";.
143 | ///
144 | internal static string README {
145 | get {
146 | return ResourceManager.GetString("README", resourceCulture);
147 | }
148 | }
149 |
150 | ///
151 | /// Looks up a localized resource of type System.Byte[].
152 | ///
153 | internal static byte[] Unme_Common {
154 | get {
155 | object obj = ResourceManager.GetObject("Unme_Common", resourceCulture);
156 | return ((byte[])(obj));
157 | }
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\DarkBlue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\Resources\FunctionCodes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\Resources\log4net.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
129 |
130 |
131 | ..\Resources\Logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\Resources\Modbus.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
135 |
136 |
137 | ..\Resources\ModbusRTUTCP.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\Resources\README.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
141 |
142 |
143 | ..\Resources\Unme.Common.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
144 |
145 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Form1.cs:
--------------------------------------------------------------------------------
1 | // * This program is just another implementation of Modbus protocol in the form of a standalone Modbus Slave application
2 | // * supporting RTU/TCP/UDP/ASCIIoverRTU protocols.
3 | // *
4 | // * It is using modified nModbus .NET 3.5 libraries, Copyright (c) 2006 Scott Alexander ( https://code.google.com/p/nmodbus/ ),
5 | // * licensed under MIT license ( http://opensource.org/licenses/mit-license.php ) and included in the Project.
6 | // * See the README.txt file in the "Resources" folder.
7 | // *
8 | // * DataStore can be used to set values even before the connection is established.
9 | // *
10 | // * The slave is set to listen and communicate on a separate background thread in order to prevent GUI from freezing up.
11 | // *
12 | // * Register values are read and written to by the master as signed integer range -32768 to 32767.
13 | // * DataGridView is storing those same values as unsigned integer 0 to 65535 values.
14 | // *
15 | // * The program appears to be fully functional but provided AS IS (feel free to modify it but preserve all these comments).
16 | // *
17 | // * This particular version was coded in C# and designed for use in Windows and will not work as such in Mono.
18 | // * RTU/ASCIIoverRTU Modes could be used together with com0com Windows program to provide virtual serial port pairs.
19 | // *
20 | // * Since the DataGridView controls, used to display register values within the simulator window, seem to require
21 | // * rather fast computer, all instances were limited to initially have only 20 rows thus limiting the number of visible
22 | // * addresses (which should still be sufficient for simulation but can be changed via the combo box).
23 | // *
24 | // * There is also a TextBox added to allow manual input of the serial port to be used (generally for Linux usage).
25 | // *
26 | // * Currently, the simulator will service requests addressed to any slave.
27 | // * All requests will still be accessing the same data store.
28 |
29 | using Modbus.Data;
30 | using Modbus.Device;
31 | using System;
32 | using System.Drawing;
33 | using System.IO.Ports;
34 | using System.Net.Sockets;
35 | using System.Threading;
36 | using System.Net;
37 | using System.Windows.Forms;
38 |
39 | namespace ModbusSlaveSimulation
40 | {
41 | public partial class Form1 : Form
42 | {
43 | private SerialPort SerPort;
44 | private TcpListener ListenerTCP;
45 | private UdpClient ClientUDP;
46 | private ModbusSlave slave;
47 | private readonly DataStore dataStore;
48 | private readonly byte unitID = 1;
49 | private readonly Form formEditValue = new Form(); //<-|
50 | private readonly TextBox formTextbox = new TextBox(); //<-| Used to edit InputRegisters and HoldingRegisters values
51 | private readonly Button formButtonOK = new Button(); //<-|
52 | private int cellRowIndex;
53 | private int cellColIndex;
54 | private bool enableMessages = true;
55 | private bool dgvCDSet;
56 | private bool dgvIDSet;
57 | private bool dgvIRSet;
58 | private bool dgvHRSet;
59 | private Thread bckgndThread;
60 | private readonly ToolTip AllToolTip = new ToolTip();
61 |
62 | private delegate void ListMasterRequestsCallback(string strRequest);
63 | private delegate void UpdateCoilDiscretes(int slave, int index, string value);
64 | private delegate void UpdateInputDiscretes(int slave, int index, string value);
65 | private delegate void UpdateInputRegisters(int slave, int index, string value);
66 | private delegate void UpdateHoldingRegisters(int slave, int index, string value);
67 |
68 | private static bool IsNumeric(string value) => int.TryParse(value, out _);
69 |
70 | #region "Constructor"
71 |
72 | public Form1()
73 | {
74 | InitializeComponent();
75 |
76 | SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.ContainerControl | ControlStyles.SupportsTransparentBackColor, true);
77 |
78 | FormClosing += Form1_FormClosing;
79 | Load += Form1_Load;
80 |
81 | btnCloseRTUASCII.BackColor = Color.Gainsboro;
82 | btnCloseTCPUDP.BackColor = Color.Gainsboro;
83 |
84 | ModbusSlave.ModbusSlaveMessageReceived += ModbusMessageReceived;
85 |
86 | dataStore = DataStoreFactory.CreateDefaultDataStore();
87 | dataStore.DataStoreReadFrom += DataStoreReadFrom;
88 | dataStore.DataStoreWrittenTo += DataStoreWriteTo;
89 |
90 | cbRowCount.SelectedIndex = 0;
91 | cbCommMode.SelectedIndex = 0;
92 |
93 | dgvCD.ColumnCount = 17;
94 | dgvID.ColumnCount = 17;
95 | dgvHR.ColumnCount = 11;
96 | dgvIR.ColumnCount = 11;
97 |
98 | formButtonOK.DialogResult = DialogResult.OK;
99 | formButtonOK.Text = "OK";
100 | formEditValue.Name = "Set Value";
101 | formEditValue.Text = "Set Value";
102 | formEditValue.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
103 | formEditValue.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
104 | formEditValue.AcceptButton = formButtonOK;
105 | formEditValue.BackgroundImage = ModbusSlaveSimulation.Properties.Resources.DarkBlue;
106 | formEditValue.Icon = ModbusSlaveSimulation.Properties.Resources.ModbusRTUTCP;
107 | formEditValue.BackgroundImageLayout = ImageLayout.Stretch;
108 | formEditValue.Size = new Size(180, 100);
109 | formEditValue.MinimumSize = new Size(180, 100);
110 | formEditValue.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
111 | formEditValue.MinimizeBox = false;
112 | formEditValue.MaximizeBox = false;
113 | formEditValue.Controls.Add(formTextbox);
114 | formEditValue.Controls.Add(formButtonOK);
115 | formTextbox.Size = new Size(60, 25);
116 | formTextbox.MaxLength = 5;
117 | formTextbox.Location = new Point(25, 25);
118 | formButtonOK.Size = new Size(52, 25);
119 | formButtonOK.Location = new Point(formTextbox.Width + 35, 23);
120 | formButtonOK.FlatStyle = FlatStyle.Standard;
121 | formButtonOK.UseVisualStyleBackColor = false;
122 | formButtonOK.BackColor = Color.Gainsboro;
123 | formButtonOK.BringToFront();
124 |
125 | formEditValue.Load += FormEditValue_Load;
126 | formButtonOK.Click += FormButtonOK_Click;
127 | formButtonOK.MouseHover += FormButtonOK_MouseHover;
128 | }
129 |
130 | #endregion
131 |
132 | #region "Requests / Updates"
133 |
134 | private void MasterRequests(object sender, ModbusSlaveRequestEventArgs e)
135 | {
136 | if (enableMessages)
137 | ListMasterRequests(e.Message.ToString());
138 | }
139 |
140 | private void ListMasterRequests(string str)
141 | {
142 | if (InvokeRequired)
143 | Invoke(new ListMasterRequestsCallback(ListMasterRequests), new object[] { str });
144 | else
145 | {
146 | ListBox1.Items.Add(str); // Add and show requests in the application window
147 |
148 | if (ListBox1.Items.Count > 2048)
149 | ListBox1.Items.RemoveAt(0);
150 |
151 | ListBox1.SelectedIndex = ListBox1.Items.Count - 1;
152 | }
153 | }
154 |
155 | private void UpdateCD(int slave, int index, string value) // Update CoilDiscretes values
156 | {
157 | if (index < 65535)
158 | {
159 | if (InvokeRequired)
160 | {
161 | Invoke(new UpdateCoilDiscretes(UpdateCD), new object[] { slave, index, value });
162 | }
163 | else
164 | {
165 | if (value == "0")
166 | dataStore.CoilDiscretes[index + 1] = false;
167 | else
168 | dataStore.CoilDiscretes[index + 1] = true;
169 |
170 | int div = Math.DivRem(index, 16, out int reminder);
171 |
172 | if (!(div >= dgvCD.Rows.Count))
173 | dgvCD.Rows[div].Cells[reminder + 1].Value = Convert.ToInt32(value);
174 | }
175 | }
176 | }
177 |
178 | private void UpdateID(int slave, int index, string value) // Update InputDiscretes values
179 | {
180 | if (index < 65535)
181 | {
182 | if (InvokeRequired)
183 | {
184 | Invoke(new UpdateInputDiscretes(UpdateID), new object[] { slave, index, value });
185 | }
186 | else
187 | {
188 | if (value == "0")
189 | dataStore.InputDiscretes[index + 1] = false;
190 | else
191 | dataStore.InputDiscretes[index + 1] = true;
192 |
193 | int div = Math.DivRem(index, 16, out int reminder);
194 |
195 | if (!(div >= dgvID.Rows.Count))
196 | dgvID.Rows[div].Cells[reminder + 1].Value = Convert.ToInt32(value);
197 | }
198 | }
199 | }
200 |
201 | private void UpdateIR(int slave, int index, string value) // Update InputRegisters values
202 | {
203 | if (index < 65535)
204 | {
205 | if (InvokeRequired)
206 | {
207 | Invoke(new UpdateInputRegisters(UpdateIR), new object[] { slave, index, value });
208 | }
209 | else
210 | {
211 | dataStore.InputRegisters[index + 1] = Convert.ToUInt16(value);
212 |
213 | int div = Math.DivRem(index, 10, out int reminder);
214 |
215 | if (!(div >= dgvIR.Rows.Count))
216 | dgvIR.Rows[div].Cells[reminder + 1].Value = value;
217 | }
218 | }
219 | }
220 |
221 | private void UpdateHR(int slave, int index, string value) // Update HoldingRegisters values
222 | {
223 | if (index < 65535)
224 | {
225 | if (InvokeRequired)
226 | {
227 | Invoke(new UpdateHoldingRegisters(UpdateHR), new object[] { slave, index, value });
228 | }
229 | else
230 | {
231 | dataStore.HoldingRegisters[index + 1] = Convert.ToUInt16(value);
232 |
233 | int div = Math.DivRem(index, 10, out int reminder);
234 |
235 | if (!(div >= dgvHR.Rows.Count))
236 | dgvHR.Rows[div].Cells[reminder + 1].Value = value;
237 | }
238 | }
239 | }
240 |
241 | #endregion
242 |
243 | #region "DataStore"
244 |
245 | private void DataStoreReadFrom(object sender, DataStoreEventArgs e)
246 | {
247 | switch (e.ModbusDataType)
248 | {
249 | case ModbusDataType.Coil:
250 | // Read CoilDiscretes values
251 | // add code here
252 | break;
253 | case ModbusDataType.Input:
254 | // Read InputDiscretes values
255 | // add code here
256 | break;
257 | case ModbusDataType.InputRegister:
258 | // Read InputRegisters values
259 | // add code here
260 | break;
261 | case ModbusDataType.HoldingRegister:
262 | // Read HoldingRegisters values
263 | // add code here
264 | break;
265 | }
266 |
267 | if (lblMessage.Text != "Comms Okay")
268 | lblMessage.Invoke((MethodInvoker)delegate { lblMessage.Text = "Comms Okay"; });
269 | }
270 |
271 | private void DataStoreWriteTo(object sender, DataStoreEventArgs e)
272 | {
273 | int address = e.StartAddress;
274 |
275 | switch (e.ModbusDataType)
276 | {
277 | case ModbusDataType.Coil:
278 | // Write CoilDiscretes values
279 | for (int i = 0; i <= e.Data.A.Count - 1; i++)
280 | {
281 | if (e.Data.A[i])
282 | UpdateCD(1, address, "1");
283 | else
284 | UpdateCD(1, address, "0");
285 |
286 | address += 1;
287 | }
288 |
289 | break;
290 | case ModbusDataType.HoldingRegister:
291 | // Write HoldingRegisters values
292 | for (int i = 0; i <= e.Data.B.Count - 1; i++)
293 | {
294 | UpdateHR(1, address, e.Data.B[i].ToString());
295 | address += 1;
296 | }
297 |
298 | break;
299 | }
300 |
301 | if (lblMessage.Text != "Comms Okay")
302 | lblMessage.Invoke((MethodInvoker)delegate { lblMessage.Text = "Comms Okay"; });
303 | }
304 |
305 | #endregion
306 |
307 | #region "DataGridView"
308 |
309 | //CoilDiscretes (Digital Outputs - I/O Address Range 000000)
310 | private void DataGridViewCD_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
311 | {
312 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 4095 && e.ColumnIndex == 16))
313 | return;
314 |
315 | lblCellNumber.Text = (Convert.ToInt32(dgvCD.Rows[e.RowIndex].Cells[0].Value.ToString().Substring(0, 6)) + e.ColumnIndex - 1).ToString().PadLeft(6, '0');
316 | }
317 |
318 | private void DataGridViewCD_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
319 | {
320 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 4095 && e.ColumnIndex == 16))
321 | return;
322 |
323 | dgvCD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Convert.ToInt32(!Convert.ToBoolean(dgvCD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value));
324 | UpdateCD(1, Convert.ToInt32(16 * e.RowIndex + e.ColumnIndex - 1), dgvCD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
325 | }
326 |
327 | //InputDiscretes (Digital Inputs - I/O Address Range 100000)
328 | private void DataGridViewID_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
329 | {
330 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 4095 && e.ColumnIndex == 16))
331 | return;
332 |
333 | lblCellNumber.Text = (Convert.ToInt32(dgvID.Rows[e.RowIndex].Cells[0].Value.ToString().Substring(0, 6)) + e.ColumnIndex - 1).ToString();
334 | }
335 |
336 | private void DataGridViewID_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
337 | {
338 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 4095 && e.ColumnIndex == 16))
339 | return;
340 |
341 | dgvID.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Convert.ToInt32(!Convert.ToBoolean(dgvID.Rows[e.RowIndex].Cells[e.ColumnIndex].Value));
342 | UpdateID(1, Convert.ToInt32(16 * e.RowIndex + e.ColumnIndex - 1), dgvID.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
343 | }
344 |
345 | //InputRegisters (Analog Inputs - I/O Address range 300000)
346 | private void DataGridViewIR_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
347 | {
348 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 6553 && e.ColumnIndex > 5))
349 | return;
350 |
351 | lblCellNumber.Text = (Convert.ToInt32(dgvIR.Rows[e.RowIndex].Cells[0].Value.ToString().Substring(0, 6)) + e.ColumnIndex - 1).ToString();
352 | }
353 |
354 | private void DataGridViewIR_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
355 | {
356 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 6553 && e.ColumnIndex > 5))
357 | return;
358 |
359 | cellRowIndex = e.RowIndex;
360 | cellColIndex = e.ColumnIndex;
361 |
362 | DialogResult dr = formEditValue.ShowDialog();
363 |
364 | if (dr == DialogResult.OK)
365 | {
366 | if (IsNumeric(formTextbox.Text))
367 | {
368 | if (Convert.ToInt32(formTextbox.Text) < 0 || Convert.ToInt32(formTextbox.Text) > 65535)
369 | {
370 | MessageBox.Show("The value must be integer number 0 to 65535!");
371 | formTextbox.Text = "";
372 | return;
373 | }
374 |
375 | dgvIR.Rows[cellRowIndex].Cells[cellColIndex].Value = formTextbox.Text;
376 | UpdateIR(1, 10 * cellRowIndex + cellColIndex - 1, dgvIR.Rows[cellRowIndex].Cells[cellColIndex].Value.ToString());
377 | }
378 | else
379 | MessageBox.Show("The value must be integer number 0 to 65535!");
380 |
381 | formTextbox.Text = "";
382 | formEditValue.Hide();
383 | }
384 | }
385 |
386 | //Holding Registers (Analog Outputs - I/O Address Range 400000)
387 | private void DataGridViewHR_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
388 | {
389 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 6553 && e.ColumnIndex > 5))
390 | return;
391 |
392 | lblCellNumber.Text = (Convert.ToInt32(dgvHR.Rows[e.RowIndex].Cells[0].Value.ToString().Substring(0, 6)) + e.ColumnIndex - 1).ToString();
393 | }
394 |
395 | private void DataGridViewHR_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
396 | {
397 | if (e.RowIndex == -1 || e.ColumnIndex == 0 || (e.RowIndex == 6553 && e.ColumnIndex > 5))
398 | return;
399 |
400 | cellRowIndex = e.RowIndex;
401 | cellColIndex = e.ColumnIndex;
402 |
403 | DialogResult dr = formEditValue.ShowDialog();
404 |
405 | if (dr == DialogResult.OK)
406 | {
407 | if (IsNumeric(formTextbox.Text))
408 | {
409 | if (Convert.ToInt32(formTextbox.Text) < 0 || Convert.ToInt32(formTextbox.Text) > 65535)
410 | {
411 | MessageBox.Show("The value must be integer number 0 to 65535!");
412 | return;
413 | }
414 | dgvHR.Rows[cellRowIndex].Cells[cellColIndex].Value = formTextbox.Text;
415 | UpdateHR(1, 10 * cellRowIndex + cellColIndex - 1, dgvHR.Rows[cellRowIndex].Cells[cellColIndex].Value.ToString());
416 | }
417 | else
418 | MessageBox.Show("The value must be integer number 0 to 65535!");
419 |
420 | formTextbox.Text = "";
421 | formEditValue.Hide();
422 | }
423 | }
424 |
425 | #endregion
426 |
427 | #region "Private Methods"
428 |
429 | private void AddRowsColumnsdgvCD(int RowCount)
430 | {
431 | if (!dgvCDSet)
432 | {
433 | // Set address column labels and set all valid cell values to dataStore values
434 | for (int i = 0; i <= RowCount - 1; i++)
435 | {
436 | if (i < 17)
437 | dgvCD.Columns[i].HeaderCell.Style.BackColor = Color.LightSeaGreen;
438 |
439 | for (int j = 0; j <= 16; j++)
440 | {
441 | if (i == 4095 && j > 15)
442 | break;
443 |
444 | if (j == 0)
445 | {
446 | //Show address range up to 065535
447 | if (i == 4095)
448 | dgvCD.Rows[i].Cells[j].Value = "0" + (16 * i + 1).ToString().PadLeft(5, '0') + "-" + "0" + (16 * i + 15).ToString().PadLeft(5, '0');
449 | else
450 | dgvCD.Rows[i].Cells[j].Value = "0" + (16 * i + 1).ToString().PadLeft(5, '0') + "-" + "0" + (16 * i + 16).ToString().PadLeft(5, '0');
451 | }
452 | else
453 | {
454 | if (dataStore.CoilDiscretes[i * 16 + j])
455 | dgvCD.Rows[i].Cells[j].Value = 1;
456 | else
457 | dgvCD.Rows[i].Cells[j].Value = 0;
458 | }
459 | }
460 | }
461 | dgvCDSet = true;
462 | }
463 | }
464 |
465 | private void AddRowsColumnsdgvID(int RowCount)
466 | {
467 | if (!dgvIDSet)
468 | {
469 | // Set address column labels and set all valid cell values to dataStore values
470 | for (int i = 0; i <= RowCount - 1; i++)
471 | {
472 | if (i < 17)
473 | dgvID.Columns[i].HeaderCell.Style.BackColor = Color.SeaGreen;
474 |
475 | for (int j = 0; j <= 16; j++)
476 | {
477 | if (i == 4095 && j > 15)
478 | break;
479 |
480 | if (j == 0)
481 | {
482 | //Show address range up to 165535
483 | if (i == 4095)
484 | dgvID.Rows[i].Cells[j].Value = "1" + (16 * i + 1).ToString().PadLeft(5, '0') + "-" + "1" + (16 * i + 15).ToString().PadLeft(5, '0');
485 | else
486 | dgvID.Rows[i].Cells[j].Value = "1" + (16 * i + 1).ToString().PadLeft(5, '0') + "-" + "1" + (16 * i + 16).ToString().PadLeft(5, '0');
487 | }
488 | else
489 | {
490 | if (dataStore.InputDiscretes[i * 16 + j])
491 | dgvID.Rows[i].Cells[j].Value = 1;
492 | else
493 | dgvID.Rows[i].Cells[j].Value = 0;
494 | }
495 | }
496 | }
497 | dgvIDSet = true;
498 | }
499 | }
500 |
501 | private void AddRowsColumnsdgvIR(int RowCount)
502 | {
503 | if (!dgvIRSet)
504 | {
505 | // Set address column labels and set all valid cell values to dataStore values
506 | for (int i = 0; i <= RowCount - 1; i++)
507 | {
508 | if (i < 11)
509 | dgvIR.Columns[i].HeaderCell.Style.BackColor = Color.SteelBlue;
510 |
511 | for (int j = 0; j <= 10; j++)
512 | {
513 | if (i == 6553 && j > 5)
514 | break;
515 |
516 | if (j == 0)
517 | {
518 | //Show address range up to 365535
519 | if (i == 6553)
520 | dgvIR.Rows[i].Cells[j].Value = "3" + (10 * i + 1).ToString().PadLeft(5, '0') + "-" + "3" + (10 * i + 5).ToString().PadLeft(5, '0');
521 | else
522 | dgvIR.Rows[i].Cells[j].Value = "3" + (10 * i + 1).ToString().PadLeft(5, '0') + "-" + "3" + (10 * i + 10).ToString().PadLeft(5, '0');
523 | }
524 | else
525 | dgvIR.Rows[i].Cells[j].Value = dataStore.InputRegisters[i * 10 + j];
526 | }
527 | }
528 | dgvIRSet = true;
529 | }
530 | }
531 |
532 | private void AddRowsColumnsdgvHR(int RowCount)
533 | {
534 | if (!dgvHRSet)
535 | {
536 | // Set address column labels and set all valid cell values to dataStore values
537 | for (int i = 0; i <= RowCount - 1; i++)
538 | {
539 | if (i < 11)
540 | dgvHR.Columns[i].HeaderCell.Style.BackColor = Color.LightSteelBlue;
541 |
542 | for (int j = 0; j <= 10; j++)
543 | {
544 | if (i == 6553 && j > 5)
545 | break;
546 |
547 | if (j == 0)
548 | {
549 | //Show address range up to 465535
550 | if (i == 6553)
551 | dgvHR.Rows[i].Cells[j].Value = "4" + (10 * i + 1).ToString().PadLeft(5, '0') + "-" + "4" + (10 * i + 5).ToString().PadLeft(5, '0');
552 | else
553 | dgvHR.Rows[i].Cells[j].Value = "4" + (10 * i + 1).ToString().PadLeft(5, '0') + "-" + "4" + (10 * i + 10).ToString().PadLeft(5, '0');
554 | }
555 | else
556 | dgvHR.Rows[i].Cells[j].Value = dataStore.HoldingRegisters[i * 10 + j];
557 | }
558 | }
559 | dgvHRSet = true;
560 | }
561 | }
562 |
563 | private void Form1_Load(object sender, EventArgs e)
564 | {
565 | cbBaud.SelectedIndex = 15;
566 | cbDataBits.SelectedIndex = 3;
567 | cbParity.SelectedIndex = 0;
568 | cbStopBits.SelectedIndex = 0;
569 |
570 | GetSerialPorts();
571 |
572 | btnCloseRTUASCII.Enabled = false;
573 |
574 | cbIO.SelectedIndex = 0;
575 |
576 | dgvCD.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
577 | dgvID.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
578 | dgvHR.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
579 | dgvIR.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
580 | AddRowsColumnsdgvCD(Convert.ToInt32(cbRowCount.SelectedItem));
581 | AddRowsColumnsdgvID(Convert.ToInt32(cbRowCount.SelectedItem));
582 | AddRowsColumnsdgvIR(Convert.ToInt32(cbRowCount.SelectedItem));
583 | AddRowsColumnsdgvHR(Convert.ToInt32(cbRowCount.SelectedItem));
584 |
585 | Focus();
586 | }
587 |
588 | private void Form1_FormClosing(object sender, FormClosingEventArgs e)
589 | {
590 | if (bckgndThread != null)
591 | {
592 | if (bckgndThread.IsAlive)
593 | bckgndThread.Join(10);
594 |
595 | bckgndThread = null;
596 | }
597 |
598 | if (SerPort != null)
599 | {
600 | if (SerPort.IsOpen)
601 | {
602 | SerPort.DiscardInBuffer();
603 | SerPort.DiscardOutBuffer();
604 | SerPort.Close();
605 | }
606 |
607 | SerPort.Dispose();
608 | }
609 |
610 | if (formEditValue != null)
611 | {
612 | formEditValue.Close();
613 | formEditValue.Dispose();
614 | }
615 | }
616 |
617 | private void FormEditValue_Load(object sender, EventArgs e)
618 | {
619 | formTextbox.Focus();
620 | }
621 |
622 | private void FormButtonOK_Click(object sender, EventArgs e)
623 | {
624 | formEditValue.DialogResult = DialogResult.OK;
625 | }
626 |
627 | private void FormButtonOK_MouseHover(object sender, EventArgs e)
628 | {
629 | formTextbox.Focus();
630 | }
631 |
632 | private void ButtonOpenRTUASCII_Click(object sender, EventArgs e)
633 | {
634 | SerPort = new SerialPort();
635 |
636 | if (!string.IsNullOrWhiteSpace(tbManualCOM.Text))
637 | SerPort.PortName = tbManualCOM.Text;
638 | else
639 | SerPort.PortName = cbPort.SelectedItem.ToString();
640 |
641 | SerPort.BaudRate = Convert.ToInt32(cbBaud.SelectedItem.ToString());
642 | SerPort.Parity = (Parity)cbParity.SelectedIndex;
643 | SerPort.DataBits = Convert.ToInt32(cbDataBits.SelectedItem.ToString());
644 | SerPort.StopBits = (StopBits)cbStopBits.SelectedIndex + 1;
645 | SerPort.Handshake = Handshake.None;
646 | SerPort.DtrEnable = true;
647 | SerPort.RtsEnable = true;
648 |
649 | try
650 | {
651 | SerPort.Open();
652 | }
653 | catch (Exception ex)
654 | {
655 | MessageBox.Show(ex.ToString());
656 | return;
657 | }
658 |
659 | if (cbCommMode.SelectedIndex == 0) //RTU
660 | slave = ModbusSerialSlave.CreateRtu(unitID, SerPort);
661 | else if (cbCommMode.SelectedIndex == 3) //ASCIIoverRTU
662 | slave = ModbusSerialSlave.CreateAscii(unitID, SerPort);
663 |
664 | slave.ModbusSlaveRequestReceived += MasterRequests;
665 | slave.DataStore = dataStore;
666 |
667 | btnOpenRTUASCII.Enabled = false;
668 | btnOpenRTUASCII.BackColor = Color.Gainsboro;
669 | btnCloseRTUASCII.Enabled = true;
670 | btnCloseRTUASCII.BackColor = Color.LightSteelBlue;
671 | btnRefresh.Enabled = false;
672 | btnRefresh.BackColor = Color.Gainsboro;
673 |
674 | cbPort.Enabled = false;
675 | cbBaud.Enabled = false;
676 | cbDataBits.Enabled = false;
677 | cbParity.Enabled = false;
678 | cbStopBits.Enabled = false;
679 | cbCommMode.Enabled = false;
680 | cbRowCount.Enabled = false;
681 | tbManualCOM.Enabled = false;
682 |
683 | bckgndThread = new Thread(BckgndThreadTask) { IsBackground = true };
684 | bckgndThread.Start();
685 | }
686 |
687 | private void ButtonOpenTCPUDP_Click(object sender, EventArgs e)
688 | {
689 | int tcpPort = int.Parse(tbPort.Text);
690 | IPAddress ipAddr = new IPAddress(0);
691 | IPHostEntry IPHE = null;
692 | try
693 | {
694 | if (IPAddress.TryParse(tbIP.Text, out ipAddr))
695 | {
696 | if (cbCommMode.SelectedIndex == 1) //TCP
697 | ListenerTCP = new TcpListener(ipAddr, tcpPort);
698 | else if (cbCommMode.SelectedIndex == 2) //UDP
699 | ClientUDP = new UdpClient(new IPEndPoint(ipAddr, tcpPort));
700 | }
701 | else
702 | {
703 | IPHE = Dns.GetHostEntry(tbIP.Text);
704 |
705 | if (cbCommMode.SelectedIndex == 1) //TCP
706 | ListenerTCP = new TcpListener(IPHE.AddressList[1], tcpPort);
707 | else if (cbCommMode.SelectedIndex == 2) //UDP
708 | ClientUDP = new UdpClient(new IPEndPoint(IPHE.AddressList[1], tcpPort));
709 | }
710 | }
711 | catch (Exception)
712 | {
713 | MessageBox.Show("Invalid IP address or hostname!");
714 | return;
715 | }
716 |
717 | if (cbCommMode.SelectedIndex == 1) //TCP
718 | slave = ModbusTcpSlave.CreateTcp(unitID, ListenerTCP);
719 | else if (cbCommMode.SelectedIndex == 2) //UDP
720 | slave = ModbusUdpSlave.CreateUdp(unitID, ClientUDP);
721 |
722 | slave.ModbusSlaveRequestReceived += MasterRequests;
723 | slave.DataStore = dataStore;
724 |
725 | btnOpenTCPUDP.Enabled = false;
726 | btnOpenTCPUDP.BackColor = Color.Gainsboro;
727 |
728 | btnCloseTCPUDP.Enabled = true;
729 | btnCloseTCPUDP.BackColor = Color.LightSteelBlue;
730 |
731 | tbIP.Enabled = false;
732 | tbPort.Enabled = false;
733 | cbCommMode.Enabled = false;
734 | cbRowCount.Enabled = false;
735 |
736 | bckgndThread = new Thread(BckgndThreadTask) { IsBackground = true };
737 | bckgndThread.Start();
738 | }
739 |
740 | private void ButtonCloseRTUASCII_Click(object sender, EventArgs e)
741 | {
742 | if (SerPort != null)
743 | {
744 | if (SerPort.IsOpen)
745 | {
746 | SerPort.DiscardInBuffer();
747 | SerPort.DiscardOutBuffer();
748 | SerPort.Close();
749 | }
750 |
751 | SerPort.Dispose();
752 | }
753 |
754 | if (slave != null)
755 | {
756 | slave.Transport.Dispose();
757 | slave.StopListen();
758 | slave.Dispose();
759 | }
760 |
761 | btnOpenRTUASCII.Enabled = true;
762 | btnOpenRTUASCII.BackColor = Color.LightSteelBlue;
763 |
764 | btnCloseRTUASCII.Enabled = false;
765 | btnCloseRTUASCII.BackColor = Color.Gainsboro;
766 |
767 | btnRefresh.Enabled = true;
768 | btnRefresh.BackColor = Color.LightSteelBlue;
769 |
770 | cbPort.Enabled = true;
771 | cbBaud.Enabled = true;
772 | cbDataBits.Enabled = true;
773 | cbParity.Enabled = true;
774 | cbStopBits.Enabled = true;
775 | cbCommMode.Enabled = true;
776 | cbRowCount.Enabled = true;
777 | tbManualCOM.Enabled = true;
778 | }
779 |
780 | private void ButtonCloseTCPUDP_Click(object sender, EventArgs e)
781 | {
782 | if (slave != null)
783 | {
784 | slave.Transport.Dispose();
785 | slave.StopListen();
786 | slave.Dispose();
787 | }
788 |
789 | btnOpenTCPUDP.Enabled = true;
790 | btnOpenTCPUDP.BackColor = Color.LightSteelBlue;
791 | btnCloseTCPUDP.Enabled = false;
792 | btnCloseTCPUDP.BackColor = Color.Gainsboro;
793 |
794 | tbIP.Enabled = true;
795 | tbPort.Enabled = true;
796 | cbCommMode.Enabled = true;
797 | cbRowCount.Enabled = true;
798 | }
799 |
800 | private void BckgndThreadTask()
801 | {
802 | try
803 | {
804 | slave.Listen();
805 | }
806 | catch (Exception)
807 | {
808 | }
809 |
810 | bckgndThread = null;
811 | }
812 |
813 | private void ButtonRefresh_Click(object sender, EventArgs e)
814 | {
815 | GetSerialPorts();
816 | }
817 |
818 | private void GetSerialPorts()
819 | {
820 | string[] portnames = SerialPort.GetPortNames();
821 | cbPort.Items.Clear();
822 |
823 | if (portnames.Length == 0)
824 | {
825 | cbPort.Items.Add("none found");
826 | btnOpenRTUASCII.Enabled = false;
827 | }
828 | else
829 | {
830 | foreach (string sPort in portnames)
831 | {
832 | cbPort.Items.Add(sPort);
833 | }
834 |
835 | btnOpenRTUASCII.Enabled = true;
836 | }
837 |
838 | cbPort.Sorted = true;
839 | cbPort.SelectedIndex = 0;
840 | }
841 |
842 | private void ComboBoxIO_SelectedIndexChanged(object sender, EventArgs e)
843 | {
844 | if (cbIO.SelectedIndex == 0)
845 | dgvCD.BringToFront();
846 | else if (cbIO.SelectedIndex == 1)
847 | dgvID.BringToFront();
848 | else if (cbIO.SelectedIndex == 2)
849 | dgvIR.BringToFront();
850 | else
851 | dgvHR.BringToFront();
852 |
853 | lblCellNumber.Text = "";
854 | Invalidate();
855 | }
856 |
857 | private void ComboBoxRowCount_SelectedIndexChanged(object sender, EventArgs e)
858 | {
859 | dgvCDSet = false;
860 | dgvIDSet = false;
861 | dgvIRSet = false;
862 | dgvHRSet = false;
863 |
864 | if (cbRowCount.SelectedItem.ToString() == "MAX")
865 | {
866 | dgvCD.RowCount = 4096;
867 | dgvID.RowCount = 4096;
868 | dgvHR.RowCount = 6554;
869 | dgvIR.RowCount = 6554;
870 | AddRowsColumnsdgvCD(4096);
871 | AddRowsColumnsdgvID(4096);
872 | AddRowsColumnsdgvIR(6554);
873 | AddRowsColumnsdgvHR(6554);
874 | }
875 | else
876 | {
877 | dgvCD.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
878 | dgvID.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
879 | dgvHR.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
880 | dgvIR.RowCount = Convert.ToInt32(cbRowCount.SelectedItem);
881 | AddRowsColumnsdgvCD(Convert.ToInt32(cbRowCount.SelectedItem));
882 | AddRowsColumnsdgvID(Convert.ToInt32(cbRowCount.SelectedItem));
883 | AddRowsColumnsdgvIR(Convert.ToInt32(cbRowCount.SelectedItem));
884 | AddRowsColumnsdgvHR(Convert.ToInt32(cbRowCount.SelectedItem));
885 | }
886 |
887 | Invalidate();
888 | }
889 |
890 | private void ComboBoxCommMode_SelectedIndexChanged(object sender, EventArgs e)
891 | {
892 | if (cbCommMode.SelectedIndex == 0 || cbCommMode.SelectedIndex == 3) //RTU or ASCIIoverRTU
893 | {
894 | gbRTU.Enabled = true;
895 | gbRTU.BringToFront();
896 | gbTCP.Enabled = false;
897 | gbTCP.SendToBack();
898 | }
899 | else //TCP or UDP
900 | {
901 | gbTCP.Enabled = true;
902 | gbTCP.BringToFront();
903 | gbRTU.Enabled = false;
904 | gbRTU.SendToBack();
905 | }
906 | }
907 |
908 | private void ListBox1_DoubleClick(object sender, EventArgs e)
909 | {
910 | enableMessages = !enableMessages;
911 | }
912 |
913 | private void CheckBox1_CheckedChanged(object sender, EventArgs e)
914 | {
915 | if (CheckBox1.Checked)
916 | ListBox1.Show();
917 | else
918 | {
919 | ListBox1.Hide();
920 | ListBox1.Items.Clear();
921 | }
922 | }
923 |
924 | private void TextBoxManualCOM_TextChanged(object sender, EventArgs e)
925 | {
926 | if (!string.IsNullOrWhiteSpace(tbManualCOM.Text))
927 | btnOpenRTUASCII.Enabled = true;
928 | else
929 | btnOpenRTUASCII.Enabled = false;
930 | }
931 |
932 | private void ModbusMessageReceived(object sender, Modbus.ModbusMessagesEventArgs e)
933 | {
934 | if (e.Message == "Master closed Socket connection.")
935 | {
936 | slave.StopListen();
937 | slave.Listen();
938 | }
939 |
940 | if (lblMessage.InvokeRequired)
941 | lblMessage.Invoke((MethodInvoker)delegate { lblMessage.Text = e.Message; });
942 | else
943 | lblMessage.Text = e.Message;
944 | }
945 |
946 | #endregion
947 |
948 | #region "ToolTips"
949 |
950 | private void ButtonCloseRTUASCII_MouseHover(object sender, EventArgs e)
951 | {
952 | if (btnCloseRTUASCII.Enabled)
953 | AllToolTip.SetToolTip(btnCloseRTUASCII, "Close serial port.");
954 | }
955 |
956 | private void ButtonOpenRTUASCII_MouseHover(object sender, EventArgs e)
957 | {
958 | if (btnOpenRTUASCII.Enabled)
959 | AllToolTip.SetToolTip(btnOpenRTUASCII, "Open serial port with currently selected parameters.");
960 | }
961 |
962 | private void ButtonRefresh_MouseHover(object sender, EventArgs e)
963 | {
964 | AllToolTip.SetToolTip(btnRefresh, "Refresh serial ports list.");
965 | }
966 |
967 | private void LabelManual_MouseHover(object sender, EventArgs e)
968 | {
969 | AllToolTip.SetToolTip(lblManual, "Set COM port manually.");
970 | }
971 |
972 | private void LabelRowCount_MouseHover(object sender, EventArgs e)
973 | {
974 | AllToolTip.SetToolTip(lblRowCount, "Number of rows visible in the DataGridView.");
975 | }
976 |
977 | private void CheckBox1_MouseHover(object sender, EventArgs e)
978 | {
979 | AllToolTip.SetToolTip(CheckBox1, "Show/Hide messages window.");
980 | }
981 |
982 | private void GroupBoxFC_MouseHover(object sender, EventArgs e)
983 | {
984 | AllToolTip.SetToolTip(gbFC, "Function Code 15 - Write Multiple Coils" + Environment.NewLine + "Function Code 16 - Write Multiple Registers" + Environment.NewLine + "Function Code 22 - Masked Bit Write" + Environment.NewLine + "Function Code 23 - ReadWrite Multiple Registers");
985 | }
986 |
987 | private void ListBox1_MouseHover(object sender, EventArgs e)
988 | {
989 | AllToolTip.SetToolTip(ListBox1, "Double click to pause showing incoming master request messages.");
990 | }
991 |
992 | private void PictureBox1_MouseHover(object sender, EventArgs e)
993 | {
994 | AllToolTip.SetToolTip(PictureBox1, "https://code.google.com/p/nmodbus/");
995 | }
996 |
997 | #endregion
998 | }
999 | }
1000 |
--------------------------------------------------------------------------------
/ModbusSlaveSimulation/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 |
123 | 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
200 |
201 |
202 |
203 | True
204 |
205 |
206 | True
207 |
208 |
209 | True
210 |
211 |
212 | True
213 |
214 |
215 | True
216 |
217 |
218 | True
219 |
220 |
221 | True
222 |
223 |
224 | True
225 |
226 |
227 | True
228 |
229 |
230 | True
231 |
232 |
233 | True
234 |
235 |
236 | True
237 |
238 |
239 | True
240 |
241 |
242 | True
243 |
244 |
245 | True
246 |
247 |
248 | True
249 |
250 |
251 | True
252 |
253 |
254 | True
255 |
256 |
257 | True
258 |
259 |
260 | True
261 |
262 |
263 | True
264 |
265 |
266 | True
267 |
268 |
269 | True
270 |
271 |
272 | True
273 |
274 |
275 | True
276 |
277 |
278 | True
279 |
280 |
281 | True
282 |
283 |
284 | True
285 |
286 |
287 | True
288 |
289 |
290 | True
291 |
292 |
293 | True
294 |
295 |
296 | True
297 |
298 |
299 | True
300 |
301 |
302 | True
303 |
304 |
305 | True
306 |
307 |
308 | True
309 |
310 |
311 | True
312 |
313 |
314 | True
315 |
316 |
317 | True
318 |
319 |
320 | True
321 |
322 |
323 | True
324 |
325 |
326 | True
327 |
328 |
329 | True
330 |
331 |
332 | True
333 |
334 |
335 | True
336 |
337 |
338 | True
339 |
340 |
341 | True
342 |
343 |
344 | True
345 |
346 |
347 | True
348 |
349 |
350 | True
351 |
352 |
353 | True
354 |
355 |
356 | True
357 |
358 |
359 | True
360 |
361 |
362 | True
363 |
364 |
365 | True
366 |
367 |
368 | True
369 |
370 |
371 |
372 | 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
636 |
637 |
638 |
639 |
640 | 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
705 | rkJggg==
706 |
707 |
708 |
709 |
710 | AAABAAEAICAQAAEABADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAAAAAAAAAAAAAAAAAA
711 | AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//
712 | AAD///8AAADMzMwAAAAAAAAADMzAAAAAzMzMwAAAAAAAAAzMzAAADMwAAMwAAAAMwAAMzAzAAMzAAAAM
713 | wAAADMAADMwAwAzAAAAAAMwAAAzAAAzMAAwMwAAAAAAMwAAMzAAMzAAADAAAAAAAAMwADMzADMwAAMwA
714 | AAAAAADMAAzAwAzMAADAAAAAAAAADMAMwMwMzAAAwAAAAAAAAAzADMDMDMwAAMAAAAAAAAAAzAzADAzM
715 | AADAAAAAAAAAAMwMwAzMzAAAwAAAAAAAAAAMzMAAzMwAAMAAAAAAAAAADMzAAMzMAADAAAAAAAAAAADM
716 | wAAMzAAAzAAAAAAAAAAAzMAAAMwAAAwAAAAAAAwAAMzAAADMwAAMAAAAAADMAADMwAAAzMAADMAAAAAM
717 | wAAAzMAAAAzAAAzAAAAADMAAAMzAAAAAwAAAzAAADMAAAADMwAAAAMwAAMwAAAzAAAAAzMAAAADMAAAM
718 | zMzMAAAAAAzAAAAADMAAAMzMwAAAAAAMwAAAAAzAAAAAAAAAAAAADMAAAAAAzAAAAAAAAAAAAAzAAAAA
719 | AMwAAAAAAAAAAAAAwAAAAAAMAAAAAAAAAAAAAMAAAAAADAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAA
720 | wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwP/+H8B//g+PP54nH5+eNn/Pnjp/5
721 | 44+//OGPP/zlj3/+ZI9//mSPf/8mj3//Jg9//4cPf/+HD3//x48//8fPv/vHx7/zx8ef58fnn+fH98+f
722 | x/PPn8fz4D/n+fB/5/n//+f8///n/P//9/7///f+///3////9////////////w==
723 |
724 |
725 |
--------------------------------------------------------------------------------