Modbus TCP client/server WPF application built with .NET 8.0 (Windows, WPF).
- Project structure and solution setup (WPF + MVVM with CommunityToolkit.Mvvm)
- Dependency Injection and typed configuration via
ServerSettings(Microsoft.Extensions.Options) - Modbus TCP client and server services using NModbus4 v2.0.0
- Connection UI, read/write for registers and coils
- Monitoring: periodic reads for Registers, Coils, Discrete Inputs, gated by a single global Continuous Read toggle
- Custom tab: per-row Area (HoldingRegister/Coil/InputRegister/DiscreteInput) and Type (uint/int/real/string), on-demand Read/Write, per-row Continuous Write, and live read updates driven by Trend-enabled rows
- Logging/Trend tab: select rows to trend, zoom/pan, CSV/PNG export, retention window 1–60 minutes
- Persistence for Custom entries to JSON (Save/Load)
- Start/Stop Modbus server from the UI
- .NET 8.0 SDK
- Visual Studio 2022 (17.0 or later) with .NET desktop development workload
-
Clone the repository
git clone https://github.com/yourusername/ModbusForge.git cd ModbusForge -
Restore NuGet packages
dotnet restore -
Build the solution
dotnet build -
Run the application
dotnet run --project ModbusForge
When you download and run the installer for ModbusForge, Windows Defender SmartScreen will likely show a warning because the application is not digitally signed with a commercial certificate.
To install the application, follow these steps:
- Run the
ModbusForge-x.x.x-setup.exeinstaller. - Windows will show a blue window titled "Windows protected your PC".
- Click on the More info link.
- The publisher will be listed as "Unknown". Click the Run anyway button to proceed with the installation.
-
Client and Server modes (configured via
ModbusForge/ModbusForge/appsettings.json, sectionServerSettings.Mode) -
Modbus TCP client operations: read/write holding registers, read coils, discrete inputs, and input registers
-
Global Continuous Read toggle that gates all periodic reads
-
Custom tab with per-row:
- Area:
HoldingRegister,Coil,InputRegister,DiscreteInput - Type:
uint,int,real(32-bit float across 2 registers),string(2 chars per 16-bit register) - On-demand Read/Write buttons
- Continuous Write (per-row)
- Live reads: when Global Continuous Read is ON, rows with
Trendenabled are read at the trend sample rate and theirValueupdates in the grid - Save/Load entries to JSON (
custom-entries.json)
- Area:
-
Logging/Trend
- Add/remove trend series per Custom row (
Trendcolumn) - Adjustable retention window (1–60 minutes)
- Zoom and pan controls, play/pause live window, reset axes
- Export/Import CSV, export PNG
- Add/remove trend series per Custom row (
- Configure in
ModbusForge/ModbusForge/appsettings.jsonunderServerSettings:Mode:ClientorServerDefaultPort,DefaultUnitId, etc.
- Both client and server services are registered; the
MainViewModelselects theIModbusServiceimplementation at runtime based onMode. - Server start/stop from UI is planned and under active development.
- The window title displays the application version from the assembly ProductVersion (fallback to
v2.1.0).
Below are PowerShell commands tested on Windows to produce a Release build and package artifacts.
- Build (Release):
dotnet clean
dotnet restore
dotnet build ModbusForge.sln -c Release- Publish (framework-dependent, single-file):
dotnet publish .\ModbusForge\ModbusForge.csproj -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true -p:PublishTrimmed=false -o .\publish\win-x64- Publish (self-contained, single-file):
dotnet publish .\ModbusForge\ModbusForge.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:PublishTrimmed=false -o .\publish\win-x64-sc- Create a ZIP artifact:
$version = "2.1.0"
Compress-Archive -Path .\publish\win-x64\* -DestinationPath .\ModbusForge-$version-win-x64.zip -Force
# or for self-contained
Compress-Archive -Path .\publish\win-x64-sc\* -DestinationPath .\ModbusForge-$version-win-x64-sc.zip -Force- Tag and create a GitHub Release (optional):
$version = "2.1.0"
git tag v$version
git push origin v$version
# If GitHub CLI is installed
gh release create v$version .\ModbusForge-$version-win-x64.zip -t "ModbusForge v$version" -n "See changelog in README"
# Optionally upload self-contained ZIP as well:
gh release upload v$version .\ModbusForge-$version-win-x64-sc.zipIf you don’t use the GitHub CLI, you can create a release manually on GitHub and upload the ZIP file(s).
- Create an Installer (optional):
This project uses Inno Setup to create a simple installer.
- Install Inno Setup: Download and install the latest version of Inno Setup from the official website.
- Compile the Script: Open the
setup/ModbusForge.issscript in the Inno Setup Compiler, or run it from the command line from the project root:The installer will be created in the& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "setup\ModbusForge.iss"
installersdirectory.
-
2.1.0 (2025-10-23)
- Added console logging tab for real-time monitoring of all Modbus operations
- Console displays connection attempts, successes, failures, and data operations
- Improved debugging and troubleshooting capabilities
- Fixed CS1002 syntax error in MainViewModel.cs that was preventing compilation
- Optimized TrendViewModel color lookup performance (O(n) → O(1)) for better chart rendering
- Improved error handling synchronization in color management
-
2.0.3 (2025-10-23)
- Enhanced error handling for continuous polling - monitors automatically disable on communication errors instead of showing disruptive pop-ups
- Improved UI clarity - renamed 'Cont.' column to 'Cont. Write' for better understanding
- Smart custom entry addition - auto-increments addresses and names when adding new entries
- Fixed Decode tab Read button functionality by making MainViewModel a singleton
- Cleaner trend charts by removing large data point geometries
-
2.0.2 (2025-10-23)
- Fixed client address offset issues
- Updated installer to version 2.0.2
-
2.0.1 (2025-10-23)
- Fixed server address offset issues
- Improved connection stability
-
2.0.0 (2025-10-22)
- Migrated from FluentModbus to NModbus4 for improved server stability
- Resolved server stopping issues
- Updated dependencies and improved error handling
-
1.3.0 (2025-08-27)
- Integrated MahApps.Metro theming and converted
MainWindowtoMetroWindow. - Kept Light theme (
Styles/Themes/Light.Blue.xaml). - Restored tabs to system look for clarity; improved DataGrid readability with gridlines and alternating rows.
- Minor UI polish and resources cleanup.
- Updated installer and README to 1.3.0.
- Integrated MahApps.Metro theming and converted
-
1.2.2 (2025-08-27)
- Fixed startup crash by registering
DecodeViewModelin DI (App.xaml.cs). - Restored missing
MenuItem_Donate_Clickhandler inMainWindow.xaml.cs. - Updated installer script
setup/ModbusForge.issto 1.2.2 (AppVersion, OutputBaseFilename). - Refreshed README version references and example commands to 1.2.2.
- Fixed startup crash by registering
-
1.1.1 (2025-08-23)
- Trend: added retention window control (1–60 minutes) with Apply action.
- Trend: Export CSV (selected/all series), Import CSV, and Export PNG buttons added to toolbar.
- Minor UI polish on Trend tab; wiring with
TrendViewModeland safe file dialogs.
-
1.1.0 (2025-08-23)
- Version bump and Simulation scaffolding: added Simulation tab UI bindings in
MainWindow.xaml. MainViewModel: simulation timer that ramps holding registers and toggles coils when in Server mode.ModbusServerService: helper methods for input registers and discrete inputs for simulation.
- Version bump and Simulation scaffolding: added Simulation tab UI bindings in
-
1.0.9 (2025-08-23)
- Custom tab continuous read/trend fix: when Global Continuous Read is ON, rows with
Trendenabled are read asynchronously by the trend timer and theirValueupdates live in the grid. - Removed per-row continuous read period in Custom; live reads are driven by the Trend sampler to avoid duplicate polling.
- Value formatting during trend reads now matches single-read behavior for
uint/int/real/coil/discreteinput. - README updated with Global Continuous Read behavior and Build/Release commands.
- Custom tab continuous read/trend fix: when Global Continuous Read is ON, rows with
-
1.0.8 (2025-08-22)
- Fixed XAML errors (XDG0008) by removing designer-only static types and relying on XAML arrays/resources.
- Decoupled LiveCharts types from ViewModel; Zoom locking now handled via
LockToZoomModeConverterusingZoomAndPanModein the view. - Trend tab improvements: Play/Pause live window, Reset axes, CSV export/import; PNG export draws a white background to avoid transparent/black backgrounds.
- Package alignment: SkiaSharp 3.116.1 + SkiaSharp.Views.WPF 3.116.1; LiveChartsCore.SkiaSharpView.WPF remains at 2.0.0-rc5.4.
- Minor cleanups and nullability adjustments.
- Logic function blocks: AND, OR, NOT, SET/RESET, timers (TON/TOF/TP)
- Connectors to Modbus registers/coils for inputs/outputs
- Visual block editor with wiring, polling, and write-back to registers
- Persistable simulation graphs and runtime execution with scan-cycle
ModbusForge/- Main WPF application projectConfiguration/- Application configuration filesConverters/- Value converters for XAML bindingsModels/- Data modelsServices/- Business logic and servicesViewModels/- ViewModels for MVVM patternViews/- XAML viewsApp.xaml- Application entry pointMainWindow.xaml- Main application window
This project uses the NModbus4 library for Modbus client and server functionality:
- NModbus4: https://github.com/NModbus4/NModbus4 (MIT License)
If you encounter issues with the .NET SDK:
-
Verify .NET 8.0 SDK is installed:
dotnet --versionShould return a version starting with
8.0 -
If not installed, download and install from .NET 8.0 Downloads
-
Restart your IDE/terminal after installation
If you encounter build issues:
-
Clean the solution:
dotnet clean -
Restore packages:
dotnet restore -
Rebuild the solution:
dotnet build
- When starting the Modbus server, if the configured port (default
502) is already in use, the app will not crash. Instead, it shows a friendly message and suggests trying an alternative port (e.g.,1502). - To find which process is using the port on Windows:
Then locate the PID in Task Manager or with:
netstat -ano | findstr :502You can either stop that process or change the server port in the UI and try again.tasklist | findstr <PID>
- Wire server start/stop into UI commands
- Finalize UI refactors and tab UX polish
- Implement simulation function blocks and connectors
- Add comprehensive error handling and user feedback
- Add unit and integration tests
This project is licensed under the MIT License - see the LICENSE file for details.