Apollo3zehn / FluentModbus

Lightweight and fast client and server implementation of the Modbus protocol (TCP/RTU).
MIT License
188 stars 69 forks source link

Modify functionality of any single unit special case #97

Open ChrisProto opened 10 months ago

ChrisProto commented 10 months ago

This is related to Issue #93 "Modify functionality of single unit zero special case". In that issue, I described special functionality that we can have with just a single unit defined with a unit identifier of zero.

Since that time, I realized that this special functionality is not dependent upon a unit identifier of zero, and that we can actually allow this with any single unit.

In our case, I wanted to create a single TCP unit with Identifier 1, and have it accept any incoming Unit Identifier. (The Unit Identifier in the response is the same as what was supplied in the response. This was fixed earlier in changes related to Issue #93.)

I have created a pull request into your dev branch with these changes.

Future Ideas FluentModbus is different from the previous package we were using because it supports multiple units in the Server classes. This will allow us to create a Modbus router. (You have probably already thought of this, but here are some of my observations.)

For example, we could create a Server that contains ten units, with Identifiers 1 through 10.

In this case, we don't have a single unit, so the special handling would not apply. Specifically:

Suppose that some of the ten units we have defined can accept broadcast messages and some cannot (or the engineer setting this up wants to prohibit broadcast messages to those units.) We need to keep this kind of configuration information on a per-Unit basis.

I put some comments in the code to this effect: I think that we should create a UnitInfo class that defines each Unit. It would contain the Unit Identifier, the four buffers for data, routing information, and other configuration parameters. It would give us the following benefits:

  1. Gather all the unit parameters into one place.
  2. Allow us to use a lock to control access to the list of units. This would allow us to add or remove units dynamically while the server is running.
  3. Allow for more efficient processing. Once we locate the UnitInfo object for the unit that can handle an incoming message, then we can pass that reference to as many methods as needed to process the message.

The UnitInfo class would contain properties like these: (This is not actual code.)

unsigned byte UnitIdentifier

byte[] InputRegisters
byte[] HoldingRegisters
byte[] InputCoils
byte[] HoldingCoils

boolean UnitAcceptsBroadcast
boolean UnitIgnoresUnitIdentifiers (This only makes sense for a single unit, and would be ignored otherwise.)

ModbusClient ModbusClient  (This is the external unit we will forward messages to.)

To handle broadcast messages, we would need to select a list of these UnitInfo objects where UnitAcceptsBroadcast is true and then process the incoming message for each one. Note that typically broadcast messages get no response, so they are used for writing the same value to multiple units.

Let me know what you think.