# PLC-CommunTools: Modbus, MQTT and serial debugging from one .NET solution

> PLC-CommunTools is a C# 12 and .NET 8 communication testing toolkit for Windows industrial hardware, with Modbus TCP/RTU, MQTT and serial support, a CLI client, an ASP.NET Core API and a Docker Compose deployment. It suits engineers who need to talk to a PLC from a script or a terminal, and the project is explicit that it is still being improved, with a legacy tree kept alongside the rewritten solution.

**SmallRob/PLC-CommunTools** — 针对工业上位机的通讯测试工具类及实例。包含各类厂商的PLC协议及基础的TCP、串口通讯、IO口通讯等协议通讯功能的实现整合，努力完善中。

- Repository: https://github.com/SmallRob/PLC-CommunTools
- Stars: 780 · Forks: 220
- Language: C#
- License: not declared
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/smallrob-plc-communtools

## A communication test bench rather than a control application

PLC-CommunTools is described as a modern communication debugging and testing tool for Windows industrial PLC hardware communication protocols. The Chinese project description frames it as a collection of communication testing tool classes and examples, integrating implementations of various vendors' PLC protocols together with basic TCP, serial port and IO port communication, and it says plainly that the work is ongoing.

That framing matters for what you should expect. This is a bench for talking to hardware, not a control system. It knows how to open a connection to a device, read a register, write a value, watch a register change and report the connection status, and the API surface is organised around exactly those verbs.

The stack is current: C# 12 on .NET 8 LTS, with ASP.NET Core 8.0 for the server side, Entity Framework Core 8.0 over SQLite for storage, MQTTnet 5.x as the MQTT client, and System.CommandLine for the command line client. Docker with Docker Compose handles containerised deployment, with Nginx as the reverse proxy in front.

The protocol list is short and specific: Modbus TCP/RTU, MQTT and serial port communication. The project description mentions TCP, serial and IO port communication more generally, and the topic tags cover plc-controller, port, socket, tcp, tool and websocket.

One thing to note early is the shape of the repository. The top level holds `CommunTools.New.sln`, `src/`, `tests/`, `docker/`, `docs/`, `examples/` and a directory called `old_version/`, described in the project structure as legacy code kept for reference. A rewrite that keeps its previous implementation alongside is a signal about the project's stage, and the Chinese description saying it is still being improved says it plainly.

## Reading and writing Modbus registers from the CLI

The command line client is the fastest way to see whether the tool works against your hardware. The documented examples cover the four operations you would reach for first: connect, read, write and monitor.

```bash
# Connect to a Modbus device
dotnet run --project src/Clients/Commun.Client.CLI/Commun.Client.CLI.csproj -- connect --protocol Modbus --address 192.168.1.100 --port 502
```

The connect subcommand takes a protocol name, an address and a port, and the example uses port 502, which is the standard Modbus TCP port. The device is then addressed by an id in the following commands:

```bash
# Read register value
dotnet run --project src/Clients/Commun.Client.CLI/Commun.Client.CLI.csproj -- read --device <device-id> --register 100

# Write register value
dotnet run --project src/Clients/Commun.Client.CLI/Commun.Client.CLI.csproj -- write --device <device-id> --register 100 --value 12345

# Monitor register changes
dotnet run --project src/Clients/Commun.Client.CLI/Commun.Client.CLI.csproj -- monitor --device <device-id> --register 100 --interval 1000
```

The monitor command takes an interval in milliseconds, and the example polls every 1000 ms.

Running the whole path through `dotnet run` on every invocation is verbose for something you intend to script, and the documentation does not show an installed `dotnet tool` invocation, so plan on building the CLI project once and referencing the binary, or wrapping `dotnet run` in a shell function of your own.

The examples directory carries runnable samples for several protocols, including `ModbusExample.cs`, `MqttExample.cs`, `SerialExample.cs`, `OpcUaExample.cs` and a `ComprehensiveExample.cs`, all in a `PLCCommunTools.Examples.csproj`. The presence of an OPC UA example is worth checking against the documented protocol list, which names only Modbus, MQTT and serial, so whether OPC UA is a supported protocol or only a stub is something to verify in the source before you plan around it.

## A layered solution with protocols isolated in Core

The project structure in the documentation is the clearest statement of the architecture. Under `src/` there are three top level folders: `Core/`, `Infrastructure/` and `Server/` and `Clients/`.

`Core/` holds the protocol libraries. `Commun.Protocols/` is the protocol abstraction layer, and the implementations sit beside it as `Commun.Modbus/` and `Commun.MQTT/`, with `Commun.Common/` for shared utilities. The abstraction layer is the interesting part: it is what makes the plugin architecture claim plausible, since a new protocol can be added behind the same interface without touching the clients.

`Infrastructure/` holds `Commun.Data/`, described as the data access layer using EF Core with SQLite, `Commun.Logging/` for logging services and `Commun.Configuration/` for configuration management. SQLite as the store is a pragmatic choice for a bench tool: no server to install, and the device registry travels with the container.

`Server/` contains `Commun.Server.API/`, the ASP.NET Core Web API. `Clients/` contains `Commun.Client.CLI/`, the terminal client.

That structure raises a question the documentation does not fully answer. The feature list names three client interfaces, WPF, WinForm and a CLI terminal, and the server side is described as ASP.NET Core Web API, WebSocket and gRPC. But the project structure diagram only shows `Commun.Client.CLI/` under `Clients/`, and the top level listing has no separate WPF or WinForm project directory. So either the desktop clients live elsewhere in the tree, they are being rewritten and not yet in place, or they are named as a goal rather than a shipped artefact. For a Windows industrial tool that is the difference between a desktop application you can hand to an operator and a tool only a developer can drive, so it is worth checking the `src/` tree yourself.

`tests/` holds unit and integration tests, `docker/` holds the container configuration, `docs/` the documentation, and `Directory.Build.props` and `global.json` sit at the root to pin shared build settings and the SDK version.

## The REST API for devices and protocol sessions

The server side exposes a small, conventional REST surface. The documented endpoints split cleanly into device management and protocol control.

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/devices` | Get all devices |
| GET | `/api/devices/{id}` | Get device by ID |
| POST | `/api/devices` | Create new device |
| PUT | `/api/devices/{id}` | Update device |
| DELETE | `/api/devices/{id}` | Delete device |
| GET | `/api/protocol/protocols` | Get available protocols |
| POST | `/api/protocol/{deviceId}/connect` | Connect to device |
| POST | `/api/protocol/{deviceId}/disconnect` | Disconnect from device |
| POST | `/api/protocol/{deviceId}/send` | Send command to device |
| GET | `/api/protocol/{deviceId}/status` | Get connection status |

The shape is a sensible one for a shared test bench. Device records are CRUD resources, while the protocol endpoints are actions on a device, which means a client can open a session, push a raw command and then poll the status without holding a connection itself.

The `protocols` endpoint is the one to call first in any integration, since it tells a client what the running build actually supports, which may be a wider or narrower set than the feature list advertises.

There is no authentication described on any endpoint, and the documentation does not mention it. The deployment path puts Nginx in front of the API, which suggests a deployment where the API is not meant to be exposed directly, but that is an inference about the setup rather than a documented security model. Treat the API as an unauthenticated internal service and put your own access control in front of it.

The feature list also names WebSocket and gRPC alongside the REST API, plus MCP integration for AI model integration and remote monitoring support. The endpoints table only covers the HTTP surface, so the shape of the WebSocket, gRPC and MCP interfaces is not documented in the README and would have to be read from the source.

## Building, testing and running the whole solution

Prerequisites are the .NET 8 SDK, with Docker optional for the containerised route. Local development is a build followed by a run of whichever project you want.

```bash
# Build the solution
dotnet build CommunTools.New.sln

# Run the server
dotnet run --project src/Server/Commun.Server.API/Commun.Server.API.csproj

# Run CLI tool
dotnet run --project src/Clients/Commun.Client.CLI/Commun.Client.CLI.csproj -- --help
```

The test suite follows the same convention, with a command for everything and one for a single project:

```bash
# Run all tests
dotnet test CommunTools.New.sln

# Run specific test project
dotnet test tests/Commun.Protocols.Tests/Commun.Protocols.Tests.csproj

# Run with verbose output
dotnet test CommunTools.New.sln --verbosity normal
```

The named test project path tells you where the protocol tests live, which is where you would look for the expected behaviour of a Modbus or MQTT implementation.

The container route is the shortest path to a running server, and it differs from the local route in one respect worth noting: the compose file lives in the `docker/` subdirectory rather than at the root.

```bash
# Clone the repository
git clone https://github.com/SmallRob/PLC-CommunTools.git
cd PLC-CommunTools

# Start with Docker Compose
cd docker
docker-compose up -d
```

That is a multi-container orchestration, so expect the API plus supporting services such as the database and the reverse proxy to come up together, and expect the ports to be whatever the compose file maps them to. The documentation does not list those ports, so they are something to read out of `docker/` before you point a client at the API.

## A rewrite in progress, with the old code kept in the tree

Two details in the repository layout deserve attention before you adopt this.

The first is `old_version/`, described in the project structure as legacy code kept for reference. Combined with the solution file name `CommunTools.New.sln` and the Chinese description saying the tool is still being improved, the picture is of a rewrite that has not finished. That is not a criticism so much as a warning about expectations: documentation, structure and shipped features may not line up yet, and the mismatch between the named WPF and WinForm clients and the single CLI project in the tree is a concrete example.

The second is the licence. The README states that the project is licensed under the MIT License with a pointer to a LICENSE file, but the repository metadata does not classify the licence and the top level listing does not obviously show a LICENSE entry. Check the file before you rely on those terms, particularly if you intend to embed the protocol libraries in a commercial product, since that is exactly the case where the difference between MIT and something else matters.

There are no GitHub releases for the project, so versions are not published as artefacts and the last push was on 2026-06-25. If you depend on it, pin to a commit rather than expecting a release stream.

The contributing guide is a standard fork, branch, commit, push and pull request flow, and the acknowledgements credit ASP.NET Core, MQTTnet for MQTT support and System.CommandLine for the CLI framework. The project is also credited to a community of contributors in the Chinese section, which points at a Chinese-speaking industrial developer audience as its primary user base.

## Conclusion

Adopt PLC-CommunTools if you need Modbus, MQTT or serial access to industrial hardware from a .NET codebase or from a terminal, and are prepared to read the source for behaviour the documentation leaves open. Do not adopt it as a packaged SCADA client, since the WPF and WinForm clients are named in the feature list but the source tree ships only the CLI, and check first that the licence file in the repository matches the MIT terms the README claims, because the repository metadata does not classify it.

## FAQ

### What protocols does PLC-CommunTools support?

The documented protocol support is Modbus TCP/RTU, MQTT and serial port communication. The feature list also names an extensible protocol plugin system, and an `OpcUaExample.cs` file exists in the examples directory even though OPC UA is not in the documented list.

### How do I connect to a Modbus device with the CLI?

Run the CLI with the `connect` subcommand, passing `--protocol Modbus`, an `--address` and a `--port`, for example `dotnet run --project src/Clients/Commun.Client.CLI/Commun.Client.CLI.csproj -- connect --protocol Modbus --address 192.168.1.100 --port 502`.

### How do I run PLC-CommunTools with Docker?

Clone the repository, change into the `docker` directory and run `docker-compose up -d`. The compose file lives in the `docker/` subdirectory rather than at the repository root, and the documentation does not list the mapped ports.

### Does PLC-CommunTools have a desktop GUI client?

The feature list names WPF, WinForm and CLI clients, but the documented project structure shows only `Commun.Client.CLI/` under `src/Clients/`. Whether the desktop clients are present in the source tree or are a planned part of the rewrite needs checking in the repository.

### What licence does PLC-CommunTools use?

The README states the project is licensed under the MIT License and points to a LICENSE file, but the repository metadata does not classify the licence. Read the LICENSE file before relying on those terms, especially if you plan to embed the protocol libraries in a commercial product.

### Is PLC-CommunTools still being developed?

The repository is not archived and the last push was on 2026-06-25, but there are no GitHub releases and the project description says the tool is still being improved. A directory named `old_version/` is kept in the tree alongside `CommunTools.New.sln`, which points to an ongoing rewrite.

## Sources

- [Issues](https://github.com/SmallRob/PLC-CommunTools/issues)
- [README](https://github.com/SmallRob/PLC-CommunTools/blob/master/README.md)
- [SmallRob/PLC-CommunTools on GitHub](https://github.com/SmallRob/PLC-CommunTools)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/smallrob-plc-communtools
