Apollo3zehn / FluentModbus

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

Delay message response #68

Closed masartomas closed 2 years ago

masartomas commented 2 years ago

Hello, is it possible to add option to delay message response from RTU server? It will be good to simulate devices whose have longer response delay than 3,5 character time. Thank you very much in advance

Apollo3zehn commented 2 years ago

Do you need a precise delay or just a minimum delay? A minimum could be easily added.

masartomas commented 2 years ago

Would prefer precise delay that you can set.

Apollo3zehn commented 2 years ago

Are you on a real time system? Windows for example has a default system tick time of 15 ms which can be reduced down to 1 ms. This is the minimum delay we can achieve with a timer. An alternative would be to burn CPU cycles but still the system might decide to put the current thread to sleep. I fear an exact delay is very difficult to implement. A normal timer just guarantees that a minimum time has passed. The maximum depends on the program and the OS. I could add a before send / after receive callback where you could add the delay yourself. What do you think?

masartomas commented 2 years ago

That solution should be good.

masartomas commented 2 years ago

I dont know if you already started working on it but if not it looks like minimum delay will also work if its that much easier to add.

Apollo3zehn commented 2 years ago

No not yet unfortunatly, I was too busy. I'll try again tomorrow morning. I will stick with the callback approach as it is useful in other scenarios as well. I will add sync and async versions.

Apollo3zehn commented 2 years ago

I think there are no changes required to implement the feature. ModbusRtuServer.Start(IModbusRtuSerialPort) accepts a IModbusRtuSerialPort. So you just need to implement it and within the method Write or WriteAsync, respectively, you can add your delay. A simple implementation can be found here: https://github.com/Apollo3zehn/FluentModbus/blob/master/src/FluentModbus/ModbusRtuSerialPort.cs

Examples:

    public void Write(byte[] buffer, int offset, int count)
    {
        Thread.Sleep(millisecondsTimeout: 3);
        // alternative: Thread.SpinWait()

       ...
    }

    public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
    {
        await Task.Delay(millisecondsDelay: 3);

        ...
    }

Would this be a solution for you?

masartomas commented 2 years ago

Yes it works fine and thank you