Apollo3zehn / FluentModbus

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

change Find method #85

Open blueskit opened 1 year ago

blueskit commented 1 year ago

Currently, there is a use case as follows: As a ModbusServer, the client (ModbusRTU) of the other party requires a non-zero unitIdentifier, which prevents access to the data in the ModbusServer.

+-------------------+            +---------------+           +------------------+ 
|                   |     TCP    |               |   RS485   |                  |
| ModbusTcpServer   |   <----->  | ModbusGate    |  <------> | ModbusRTU Client |
| (FluentModbus)   |            | (Hardware)    |           |                  |
+-------------------+            +---------------+           +------------------+

After inspection, the Find() method in class ModbusServer is as follows:

        private Span<byte> Find(byte unitIdentifier, Dictionary<byte, byte[]> map)
        {
            if (unitIdentifier == 0)
            {
                if (map.Count == 1)
                    return map.First().Value;

                else
                    throw new ArgumentException(ErrorMessage.ModbusServer_ZeroUnitOverloadOnlyApplicableInSingleUnitMode);
            }

            else
            {
                if (!map.TryGetValue(unitIdentifier, out var buffer))
                    throw new KeyNotFoundException(ErrorMessage.ModbusServer_UnitIdentifierNotFound);

                return buffer;
            }
        }

If the Find method is changed to a protected virtual method, then the problem can be solved by deriving a class from ModbusServer as follows.

 public class ModbusSlaveOneTcpServer : FluentModbus.ModbusTcpServer
 {
      ModbusSlaveOneTcpServer()
      {
        AddUnit(1);
      }

        proteted override Span<byte> Find(byte unitIdentifier, Dictionary<byte, byte[]> map)
        {
           if (map.Count == 1 || unitIdentifier==0)
               return map.First().Value;
          else if (map!=null && map.TryGetValue(unitIdentifier, out var buffer))
                return buffer;
          else
               throw new KeyNotFoundException(ErrorMessage.ModbusServer_UnitIdentifierNotFound);
        }
    }

Please change the Find method in class ModbusServer to a protected method, or if there is a better way, please consider it.

Apollo3zehn commented 1 year ago

Hi, thanks for your suggestion. I am wondering why you cannot simply call AddUnit(1) in your derived class (as you did in ModbusSlaveOneTcpServer) and then always work with that unit?

You can access the corresponding registers by calling e.g. GetHoldingRegisters(unitIdentifier: 1) or GetHoldingRegisterBuffer<T>(unitIdentifier: 1), etc.

Or did I overlook something?