Giter Club home page Giter Club logo

fluentmodbus's Introduction

FluentModbus

GitHub Actions NuGet

FluentModbus is a .NET Standard library (2.0 and 2.1) that provides Modbus TCP/RTU server and client implementations for easy process data exchange. Both, the server and the client, implement class 0, class 1 and class 2 (partially) functions of the specification. Namely, these are:

Class 0:

  • FC03: ReadHoldingRegisters
  • FC16: WriteMultipleRegisters

Class 1:

  • FC01: ReadCoils
  • FC02: ReadDiscreteInputs
  • FC04: ReadInputRegisters
  • FC05: WriteSingleCoil
  • FC06: WriteSingleRegister

Class 2:

  • FC15: WriteMultipleCoils
  • FC23: ReadWriteMultipleRegisters

Please see the introduction to get a more detailed description on how to use this library!

Below is a screenshot of the sample console output using a Modbus TCP server and client:

Sample.

fluentmodbus's People

Contributors

apollo3zehn avatar corentingallet avatar helynranta avatar iberisoft avatar lmartorella avatar lukaskarel avatar lukasschachner avatar maikebing avatar marnixrijnart avatar ondrejcopak-eaton avatar schotime avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluentmodbus's Issues

Modbus TCP poll not timing out

I am performing read on holding registers with modbus TCP cllient. However, when device does not reply, i am not getting any timeout exception and it just stucks there. I'm using the preview 4 nuget package.

Is the expected behavior? If it is, how is the proper way to get timeout?

Thanks in advance!

FluentModbus.ModbusException: 'The protocol identifier is invalid.'

Seems like a
var unitIdentifier = 0xFF;
giving this error when I using your examples.

The device manual saying:
"INPUT DATA AREA
The following table lists the registers of the input area (produced from the instrument and read by the
master), common to all PROFINET, ETHERCAT, ETHERNET/IP fieldbuses. The registers are 16 bit in size.
The input area is updated at a maximum frequency of 125 Hz (80 Hz in case of FIELBUS). The size
of the output area configured in the master fieldbus must match the size configured in the instrument"
Which seems to be OK. 16bit."

EasyModbus library reading registers but I have other issues with it.

Any suggestions?

Implement Disposable

I suggest to implement IDisposable. It is simpler to disconnect, if IDisposable is implemented.

When code gets complicated, you have two options:

  • call Disconnect() in multiple places
  • wrap all your code with try-finally and call Disconnect() only once in finally block

I offer implement this. Do you agree and should I make a PR? ๐Ÿ˜‰

Currently:

var client = new ModbusTcpClient();
// code here ...
// disconnect
client.Disconnect();

Suggestion:

using (var client = new ModbusTcpClient())
{
    // code here ...
    // will disconnect automatically
}

Malformed Modbus Message under certain Conditions

I'm seeing a weird issue while using this library with a simulator and I think it might be occurring with physical devices as well. To give some context, I'm continuously connecting to multiple devices using Modbus RTU (RS485) to have a close to live readout of values. Since this is a serial connection, I don't want to spend too much time trying to read one device if there is an error. I'm also using Retry Policy from Polly to retry ReadHoldingRegisters if there is an error or response timeout so that transient errors aren't displayed to the user.

When there are multiple errors/timeouts such that multiple devices exhaust their retries, I'm seeing the library send out malformed modbus messages to every device as if the buffer has somehow become corrupted or overflowed. However, I tried Closing and Reopening the connection to the client and even modifying the code so that it clears the buffer with zeroes, and somehow the library continues sending these malformed messages. Only closing the entire application or placing breakpoints in the debugger seems to clear up the issue.

This is the response I'm seeing from the simulator.
image

Data reversed

I use Modbus Slave to simulate slave, but I get reverse data.
image
Slave Log

000070-Rx:00 00 00 00 00 06 01 03 00 00 00 0A 
000071-Tx:00 00 00 00 00 17 01 03 14 01 09 01 83 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
000072-Rx:00 01 00 00 00 06 01 03 00 00 00 0A 
000073-Tx:00 01 00 00 00 17 01 03 14 01 09 01 83 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

Master code

        static void Fluent()
        {
            var client = new ModbusTcpClient();
            client.Connect(IPEndPoint.Parse("127.0.0.1:502"));
            var d1 = client.ReadHoldingRegisters<ushort>(1, 0, 10);
            Console.WriteLine(string.Join(";", d1.ToArray().Select(BitConverter.GetBytes).Select(c => BitConverter.ToString(c)).ToArray()));
            Console.WriteLine(string.Join(";", d1.ToArray()));

            var d2 = client.ReadHoldingRegisters(1, 0, 10);
            Console.WriteLine(BitConverter.ToString(d2.ToArray()));
            Console.WriteLine(string.Join(";", d2.ToArray()));

            client.Disconnect();
        }

Master output

01-09;01-83;00-00;00-00;00-00;00-00;00-00;00-00;00-00;00-00
2305;33537;0;0;0;0;0;0;0;0
01-09-01-83-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
1;9;1;131;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
Slave send Master output
265(0x0109) 2305(0x0901)
387(0x0183) 33537(0x8301)

I tested it in NModbus, it works correct.
NModbus code

        static void NModbus()
        {
            using var tcpClient = new TcpClient();
            tcpClient.Connect(IPEndPoint.Parse("127.0.0.1:502"));
            using var client = new ModbusFactory().CreateMaster(tcpClient);
            var d = client.ReadHoldingRegisters(1, 0, 10);
            Console.WriteLine(string.Join(";", d.Select(BitConverter.GetBytes).Select(c => BitConverter.ToString(c)).ToArray()));
            Console.WriteLine(string.Join(";", d));
        }

NModbus output

09-01;83-01;00-00;00-00;00-00;00-00;00-00;00-00;00-00;00-00
265;387;0;0;0;0;0;0;0;0

Connect-Query-Disconnect vs. persistent connection

Hi,

your library is very useful and well written, so thank you.

I need to constantly read from a modbus device, let's say every second or so.
The Modus protocol does not provide any mechanism to check server status (a sort of ping/heartbeat) so I was wondering what is the best way to approach this.

  1. Open connection, read registers and close connection each second
  2. Keep the connection open and read data every second, try reconnect if can't read.

I saw that you rely on the TcpCLient.Connected which may be unreliable. What is your suggestion? How would you proceed?

Thanks a lot
A

Fix failing tests.

Tests fail mostly on Ubuntu, never locally. The custom error message is "The TCP connection closed unexpectedly." and only happens for the "ProtocolTests". The server instance is recreated for each test and every test uses a new port, so what causes the random issues?

Exception trying to read more then 123 registers

256 bytes is not enough to read all data. MBAP + PDU maximum size is 260 bytes.

public ModbusTcpMessageBuffer()
{
    this.Buffer = ArrayPool<byte>.Shared.Rent(256);

    this.RequestWriter = new ExtendedBinaryWriter(new MemoryStream(this.Buffer));
    this.ResponseReader = new ExtendedBinaryReader(new MemoryStream(this.Buffer));
}

ModbusTcpClient IsConnected property has defect

Issue

See here

public void Connect(IPEndPoint remoteEndpoint, ModbusEndianness endianness) 
{
...
            _tcpClient?.Close();
            _tcpClient = new TcpClient();

            if (!_tcpClient.ConnectAsync(remoteEndpoint.Address, remoteEndpoint.Port).Wait(this.ConnectTimeout))
                throw new Exception(ErrorMessage.ModbusClient_TcpConnectTimeout);

            _networkStream = _tcpClient.GetStream();
...
}

When _tcpClient.ConnectAsync success, at this moment I close the Modbus Server, _tcpClient.GetStream will be null or disposed, causing ObjectDisposedException or NullReferenceException while reading/writing data.

At this time ModbusTcpClient._tcpClient is not null, ModbusTcpClient.IsConnected is true, but ModbusTcpClient._networkStream is null or disposed. Use if(!ModbusTcpClient.IsConnected) { ModbusTcpClient.Connect(...) } to reconnect will not work.

For now I catch ObjectDisposedException and NullReferenceException, then I create a new ModbusTcpClient to avoid this issue, rather than catch and call Connect directly.

_networkStream is null:

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at FluentModbus.ModbusTcpClient.TransceiveFrame(Byte unitIdentifier, ModbusFunctionCode functionCode, Action`1 extendFrame) in C:\projects\fluentmodbus\src\FluentModbus\Client\ModbusTcpClient.cs:line 197
   at FluentModbus.ModbusClient.ReadDiscreteInputs(Byte unitIdentifier, UInt16 startingAddress, UInt16 quantity) in C:\projects\fluentmodbus\src\FluentModbus\Client\ModbusClient.cs:line 237
...

_networkStream is disposed:

image

Timeout Exception on Linux in 4.0.0-preview1

When testing the preview1 version of the package, we encountered a bug where the client times out after first read from RTU server, which was no the behavior we had on the code of my version of the PR, so this makes me thing something broke in the new version, but i don't see anything that could break it and just on Linux for that matter.

Any help or hints would be appreciated

Connect fails if port is not specified

I am using ModbusTCP client to connect to an IP address
_modbusTcpClient.Connect("192.168.100.68", ModbusEndianness.BigEndian);

It fails if I don't add :502 after the IP address.
Is this expected behavior, since it says default port is 502?

Thanks in advance

Documentation is out of date

From the docs in Endianness:

var client = new ModbusRtuClient(..., ModbusEndianness.BigEndian);

Should be

client.Connect(port, ModbusEndianness.BigEndian);

ModbusTcpServer.MaxConnections not working

I have set MaxConnections = 2 but more connections can be established without problems and I also receive data.

grafik

Have I configured something wrong?
I would be happy about a solution.

ConnectionTimeout vs. MaxConnections in async ModbusTcpServer not working correctly

I have found a problem in the combination of MaxConnections and ConnectionTimeout (ModbusTcpServer).

The following function only works if server.IsAsynchronous = false.
https://github.com/Apollo3zehn/FluentModbus/blob/master/src/FluentModbus/Server/ModbusTcpServer.cs#L172

I have server.MaxConnections = 5 and server.ConnectionTimeout = 5sec.
I can successfully establish 5 connections to the server, then is server.ConnectionCount = 5.
If I disconnect one of the 5 connections, server.ConnectionCount should be 4 after ConnectionTimeout but it is 5, only in the synchronous mode it is 4.

For your information: even after a long time a ModbusTcpRequestHandler is not removed.
I have been continuously logging server.ConnectionCount in to the console and the value 5 has not changed.
Even if I disconnected all 5 connections I was not able to establish a new one, so the server had to be reinitialized.

The whole thing unfortunately only works in the synchronous mode of the ModbusTcpServer.

I'm not sure if I made a mistake, it would be great if you could look over it.

Delay message response

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

Use new indexing feature:

var floatData = client.ReadHoldingRegisters(0, 1, 2);
var firstValue = floatData[0];
var lastValue = floatData[^1];

The desire to add AOP functionality

Hello author,
I am an Asian with poor English, all the following content is from machine translation.
I am new to Modbus and would like the author to add AOP functionality, which would be useful to check if the commands are correct.
Or please tell me how to add AOP, I think I can do the job.

Modbus RTU Server not responding after Client Disconnected

After some series of testing, I realize that Modbus RTU Server (RS485 COM PORT) will not response after the initial connected client disconnected. I have tested with different Modbus POLL program.
The error code from the Read "Block with function 3 is time out". The connection status is "Connected".
Is there anything wrong with my setup?
image
image
Hope to get a response soonest.

Mid Little/Big endian

Hi,

I just wanted to let you know that the server we are working on in MidLittleEndian.
No problem, I just read bytes and then interpret byte order myself, I just wanted to let you know that there are these scenarios that are currently uncovered by the lib.

Cheers
A

Additional features for ModbusTcpServer

I have some questions about new features for the server.

Is it possible to limit the number of clients? Something like:

server = new ModbusTcpServer();
server.MaxConnections = 5;
server.Start();

Is it possible to disable or to set the max addresses server.MaxInputRegisterAddress = 10 (not only get) for some registers?
For example:

- Input Register
- Holding Register
- Read Coils
...

So that you get an "Illegal function"-Error in ModbusPoll or something.

Would be great if there was a solution for this.

Add timeout for ModbusRTUClients

If you use ReadRegisters Function and no server is connected or does not respond, you are stuck in the while loop in TransceiveFrame. There should be a possibility to set a timeout to return with error.

feat: support start Modbus tcp server with an specific port

It would be great if the ModbusTcpServer.Start() also supports an function with a port configuration. I already found the Start(IPEndPoint) where it would be possible to set the port.

For my point of view would be nice to have an method with for example an nullable string. If the string is null the default port 502 will be used.

About Message Receive

In Slave mode of the library, I can't seem to find a place to receive messages from the Master. For example, if the Master sends a request message with 03 function code, where can I receive it? I also want to be able to determine what function code the Master is requesting and what data it is receiving

Endianess for ModbusTcpServer

I have seen that the ModbusTcpServer checks if we have Little or Big-Endian.
My system (Linux ARM32) is Little-Endian. When I check the data (with ModbusPoll) - it is not reversed.

For example:

Span<short> inputreg = server.GetInputRegisterBuffer<short>();
inputreg[0] = 1;

In ModbusPoll I got "256" (0x0100), I expected "1" (0x0001).
It was possible that I manually reverse my data before with ModbusUtils.SwitchEndianness(), but I was wondering if there is a cleaner solution for it.

With the client I was able to receive the data in the correct endianess:

client.Connect(IPAddress.Parse("1.2.3.4"), ModbusEndianness.BigEndian);

It would be great if someone could help me, or tell me if it makes sense to reverse every single value before.

WriteMultipleRegisters Error

Hi, I would need to write an alphanumeric value inside a register, in particular the one with address 208.
For example: Test2022
I noticed the instruction below
client.WriteMultipleRegisters (machine.unitIdentifier, 208, new byte [] {084, 101, 115, 116, 050, 048, 050, 050});
it doesn't work as it should.
The machine displays only the value 2 (050).
I want to clarify that the machine's Endianness is Little.
what am I doing wrong?
thank you

Doesn't work on Linux in .Net Core

System.TypeLoadException: Could not set up parent class, due to: assembly:/home/pi/share/System.Private.CoreLib.dll type:Object member:(null)

SetBigEndian not working

Hello, either I do something wrong or there is a mistake.

The following behaviour can be observed:
grafik
grafik

I only want to write 16bit, but it looks like the SetBigEndian method writes more than 16bit and overwrites the other values.
If I write only one value it works, with more values this strange behaviour appears.

Without casting to short:
grafik
That will be because it is int and has 32bit.

I think the same behaviour applies to SetLittleEndian.

Error running .NET Core on Raspberry Pi

Hi, we created a sample app for reading modbus using TCP for Solar Inverter. On Windows it works 100% not on Raspberry Pi .
Generated error:
"A fatal error was encountered. The library 'libhostpolicy.so' required to execute the application was not found in '/home/pi/Ciram/'.
Failed to run as a self-contained app. If this should be a framework-dependent app, add the /home/pi/Ciram/ModbusApp.runtimeconfig.json file specifying the appropriate framework."

ModbusApp.runtimeconfig.json contains:

{
"runtimeOptions": {
"tfm": "netcoreapp3.1",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "3.1.0"
}
}
}

Other App's that we create with the same code, but without FluentModbus works on the Raspberry Pi.

This is what we used for all our products for windows and Raspberry Pi


Exe
netcoreapp3.1
ModbusApp.Program



-> this is new now.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.