### Starting Modbus TCP Server C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Starts the Modbus TCP server instance, making it ready to accept incoming client connections. ```C# server.Start(); ``` -------------------------------- ### Starting ModbusRtuServer on COM Port (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Illustrates how to start the previously instantiated `ModbusRtuServer`. The `Start` method requires specifying the serial port name (e.g., 'COM1') where the RTU communication will occur. ```C# server.Start(port: "COM1"); ``` -------------------------------- ### Install FluentModbus Package - PowerShell Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Instructions on how to create a new .NET Core console project and add the FluentModbus NuGet package using the .NET CLI in PowerShell. ```PowerShell PS> dotnet new console PS> dotnet add package FluentModbus ``` -------------------------------- ### Starting FluentModbus TCP Server Task - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_tcp.md This code starts the ModbusTcpServer in a separate Task. It includes setting up a CancellationTokenSource for graceful shutdown and a loop that periodically calls DoServerWork while holding a lock on the server's buffer. ```C# /* run Modbus TCP server */ var cts = new CancellationTokenSource(); var task_server = Task.Run(async () => { server.Start(); serverLogger.LogInformation("Server started."); while (!cts.IsCancellationRequested) { // lock is required to synchronize buffer access between this application and one or more Modbus clients lock (server.Lock) { DoServerWork(server); } // update server buffer content once per second await Task.Delay(TimeSpan.FromSeconds(1)); } }, cts.Token); ``` -------------------------------- ### Starting FluentModbus TCP Client Task - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_tcp.md This snippet starts the ModbusTcpClient in a separate Task. It connects the client, calls the DoClientWork method (not shown), handles potential exceptions, disconnects the client, and waits for user input before exiting. ```C# /* run Modbus TCP client */ var task_client = Task.Run(() => { client.Connect(); try { DoClientWork(client, clientLogger); } catch (Exception ex) { clientLogger.LogError(ex.Message); } client.Disconnect(); Console.WriteLine("Tests finished. Press any key to continue."); Console.ReadKey(intercept: true); }); ``` -------------------------------- ### Initializing FluentModbus RTU Server and Client in C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_rtu.md Sets up the necessary components for Modbus RTU communication, including defining COM ports, configuring logging, creating server and client instances, and attaching an event handler. Requires the FluentModbus library and a COM port setup. ```C# static async Task Main(string[] args) { /* Modbus RTU uses a COM port for communication. Therefore, to run * this sample, you need to make sure that there are real or virtual * COM ports available. The easiest way is to install one of the free * COM port bridges available in the internet. That way, the Modbus * server can connect to e.g. COM1 which is virtually linked to COM2, * where the client is connected to. * * When you only want to use the client and communicate to an external * Modbus server, simply remove all server related code parts in this * sample and connect to real COM port using only the client. */ /* define COM ports */ var serverPort = "COM1"; var clientPort = "COM2"; /* create logger */ var loggerFactory = LoggerFactory.Create(loggingBuilder => { loggingBuilder.SetMinimumLevel(LogLevel.Debug); loggingBuilder.AddConsole(); }); var serverLogger = loggerFactory.CreateLogger("Server"); var clientLogger = loggerFactory.CreateLogger("Client"); /* create Modbus RTU server */ using var server = new ModbusRtuServer(unitIdentifier: 1) { // see 'RegistersChanged' event below EnableRaisingEvents = true }; /* subscribe to the 'RegistersChanged' event (in case you need it) */ server.RegistersChanged += (sender, registerAddresses) => { // the variable 'registerAddresses' contains a list of modified register addresses }; /* create Modbus RTU client */ var client = new ModbusRtuClient(); } ``` -------------------------------- ### Initializing FluentModbus TCP Server and Client - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_tcp.md This snippet demonstrates the initial setup for a Modbus TCP server and client application using the FluentModbus library. It includes creating a logger, instantiating the ModbusTcpServer and ModbusTcpClient classes, and subscribing to the RegistersChanged event on the server. ```C# static async Task Main(string[] args) { /* create logger */ var loggerFactory = LoggerFactory.Create(loggingBuilder => { loggingBuilder.SetMinimumLevel(LogLevel.Debug); loggingBuilder.AddConsole(); }); var serverLogger = loggerFactory.CreateLogger("Server"); var clientLogger = loggerFactory.CreateLogger("Client"); /* create Modbus TCP server */ using var server = new ModbusTcpServer(serverLogger) { // see 'RegistersChanged' event below EnableRaisingEvents = true }; /* subscribe to the 'RegistersChanged' event (in case you need it) */ server.RegistersChanged += (sender, registerAddresses) => { // the variable 'registerAddresses' contains a list of modified register addresses }; /* create Modbus TCP client */ var client = new ModbusTcpClient(); ``` -------------------------------- ### Starting FluentModbus RTU Server Task in C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_rtu.md Starts the Modbus RTU server on a specified COM port within an asynchronous task. It logs the server status and enters a loop to perform server-side operations, ensuring thread-safe access to the server's buffer using a lock. Requires a `ModbusRtuServer` instance and a `CancellationTokenSource`. ```C# /* run Modbus RTU server */ var cts = new CancellationTokenSource(); var task_server = Task.Run(async () => { server.Start(serverPort); serverLogger.LogInformation("Server started."); while (!cts.IsCancellationRequested) { // lock is required to synchronize buffer access between this application and the Modbus client lock (server.Lock) { DoServerWork(server); } // update server buffer content once per second await Task.Delay(TimeSpan.FromSeconds(1)); } }, cts.Token); ``` -------------------------------- ### Manipulating Modbus Coils/Discrete Inputs (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Shows how to get the buffer for Coils or Discrete Inputs and use convenience methods like Set, Get, and Toggle to manipulate individual bits by address. No endianness handling is required for bit data. ```C# // Get buffer var coils = server.GetCoils(); // or server.GetDiscreteInputs() // Set bit. coils.Set(address: 1, value: true); var value = coils.Get(address: 1); // should return 'true' // Unset bit coils.Set(address: 2, value: false); var value = coils.Get(address: 1); // should return 'false' // Toggle bit coils.Toggle(address: 2, value: false); var value = coils.Get(address: 1); // should return 'true' ``` -------------------------------- ### Defining Modbus Read Parameters C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md This snippet shows how to define the necessary parameters for reading data from a Modbus device, including the unit identifier, starting address, and the number of values (count) to read. ```C# var unitIdentifier = 0xFF; // 0x00 and 0xFF are the defaults for TCP/IP-only Modbus devices. var startingAddress = 0; var count = 10; ``` -------------------------------- ### Asynchronous Modbus TCP Server Operation C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Provides a complete example of running a Modbus TCP server asynchronously, demonstrating how to access and update server registers (`HoldingRegisters`) while ensuring thread-safe access using the server's built-in lock. ```C# var cts = new CancellationTokenSource(); var random = new Random(); var server = new ModbusTcpServer(); server.Start(); while (!cts.IsCancellationRequested) { var registers = server.GetHoldingRegisters(); // lock is required to synchronize buffer access between // this application and one or more Modbus clients lock (server.Lock) { var value = random.Next(0, 100); registers.SetLittleEndian(address: 0, value); } // update server register content only once per second await Task.Delay(TimeSpan.FromSeconds(1)); } server.Dispose(); ``` -------------------------------- ### Starting FluentModbus RTU Client Task in C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_rtu.md Connects the Modbus RTU client to a specified COM port and executes client-side communication logic within an asynchronous task. It includes error handling for client operations and ensures the client connection is closed afterward. Requires a `ModbusRtuClient` instance. ```C# /* run Modbus RTU client */ var task_client = Task.Run(() => { client.Connect(clientPort); try { DoClientWork(client, clientLogger); } catch (Exception ex) { clientLogger.LogError(ex.Message); } client.Close(); Console.WriteLine("Tests finished. Press any key to continue."); Console.ReadKey(intercept: true); }); ``` -------------------------------- ### Reading Modbus Holding Registers (short) C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Reads a specified number of holding registers from a Modbus device starting at a given address, interpreting the raw register data as an array of 16-bit signed integers (`short`). Requires an initialized `client` object. ```C# var shortData = client.ReadHoldingRegisters(unitIdentifier, startingAddress, count); ``` -------------------------------- ### Instantiating Modbus TCP Server C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Creates a new instance of the `ModbusTcpServer` class, which is the first step in setting up a Modbus TCP server. ```C# var server = new ModbusTcpServer(); ``` -------------------------------- ### Instantiate Modbus RTU Client - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Shows how to create a new instance of the ModbusRtuClient, either with default COM port settings or with custom settings for baud rate, parity, and stop bits. ```C# // use default COM port settings var client = new ModbusRtuClient(); // use custom COM port settings: var client = new ModbusRtuClient() { BaudRate = 9600, Parity = Parity.None, StopBits = StopBits.Two }; ``` -------------------------------- ### Instantiating ModbusRtuServer (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Shows how to create a new instance of the `ModbusRtuServer` class. Requires providing a `unitIdentifier` in the range 1-247, which must be unique for each server/slave on the RTU network. ```C# var server = new ModbusRtuServer(unitIdentifier: 1); ``` -------------------------------- ### Connect Modbus TCP Client - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Demonstrates various ways to connect a Modbus TCP client instance to a server, including using default settings, specifying an IP address, or specifying both IP address and port. ```C# // use default IP address 127.0.0.1 and port 502 client.Connect(); // use specified IP address and default port 502 client.Connect(IPAddress.Parse("127.0.0.1")); // use specified IP adress and port client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 502)); ``` -------------------------------- ### Enabling and Subscribing to Modbus Server Events (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Demonstrates how to enable event raising on a Modbus server (TCP shown) by setting `EnableRaisingEvents` to true. It then shows how to subscribe to the `RegistersChanged` and `CoilsChanged` events to receive notifications when data changes. ```C# using var server = new ModbusTcpServer(...) { // 'EnableRaisingEvents' is disabled by default to improve // performance. But now we want events to be raised: EnableRaisingEvents = true }; server.RegistersChanged += (sender, registerAddresses) => { ... }; server.CoilsChanged += (sender, coilAddresses) => { ... }; ``` -------------------------------- ### Disposing ModbusRtuServer (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Shows the correct way to release resources held by the `ModbusRtuServer` instance when it is no longer needed. Calling `Dispose()` is essential for proper cleanup. ```C# server.Dispose(); ``` -------------------------------- ### Instantiate Modbus TCP Client - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Creates a new instance of the ModbusTcpClient class, which is used to communicate with Modbus TCP servers. ```C# var client = new ModbusTcpClient(); ``` -------------------------------- ### Stopping FluentModbus RTU Server and Waiting for Client in C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_rtu.md Manages the shutdown sequence by awaiting the completion of the client task, then using a cancellation token to signal the server task to stop. It waits for the server task to finish its cleanup and finally calls the server's `Stop` method. Requires the server and client tasks and the cancellation token source. ```C# // wait for client task to finish await task_client; // stop server cts.Cancel(); await task_server; server.Stop(); serverLogger.LogInformation("Server stopped."); } ``` -------------------------------- ### Performing Modbus RTU Client Operations (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_rtu.md This method demonstrates various common Modbus RTU client operations using different function codes (FC01, FC02, FC03, FC04, FC05, FC06, FC16). It is intended to be executed once upon client startup. It requires a ModbusRtuClient instance and an ILogger for logging results. Data is typically returned as Span, which can be converted to an array using ToArray() if needed. ```C# static void DoClientWork(ModbusRtuClient client, ILogger logger) { Span data; var sleepTime = TimeSpan.FromMilliseconds(100); var unitIdentifier = 0x01; var startingAddress = 0; var registerAddress = 0; // ReadHoldingRegisters = 0x03, // FC03 data = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 10); logger.LogInformation("FC03 - ReadHoldingRegisters: Done"); Thread.Sleep(sleepTime); // WriteMultipleRegisters = 0x10, // FC16 client.WriteMultipleRegisters(unitIdentifier, startingAddress, new byte[] { 10, 00, 20, 00, 30, 00, 255, 00, 255, 01 }); logger.LogInformation("FC16 - WriteMultipleRegisters: Done"); Thread.Sleep(sleepTime); // ReadCoils = 0x01, // FC01 data = client.ReadCoils(unitIdentifier, startingAddress, 10); logger.LogInformation("FC01 - ReadCoils: Done"); Thread.Sleep(sleepTime); // ReadDiscreteInputs = 0x02, // FC02 data = client.ReadDiscreteInputs(unitIdentifier, startingAddress, 10); logger.LogInformation("FC02 - ReadDiscreteInputs: Done"); Thread.Sleep(sleepTime); // ReadInputRegisters = 0x04, // FC04 data = client.ReadInputRegisters(unitIdentifier, startingAddress, 10); logger.LogInformation("FC04 - ReadInputRegisters: Done"); Thread.Sleep(sleepTime); // WriteSingleCoil = 0x05, // FC05 client.WriteSingleCoil(unitIdentifier, registerAddress, true); logger.LogInformation("FC05 - WriteSingleCoil: Done"); Thread.Sleep(sleepTime); // WriteSingleRegister = 0x06, // FC06 client.WriteSingleRegister(unitIdentifier, registerAddress, 127); logger.LogInformation("FC06 - WriteSingleRegister: Done"); } ``` -------------------------------- ### Disposing ModbusTcpClient using 'using' (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/CHANGELOG.md Demonstrates the use of the 'using' statement with ModbusTcpClient, which now implements IDisposable, ensuring proper resource cleanup after the client is no longer needed. ```csharp using var client = new ModbusTcpClient(...) ``` -------------------------------- ### Span Extension Methods for Endianness (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Lists the available extension methods provided for `Span` to handle data conversion between different endianness formats (Big Endian, Little Endian, Mid-Little Endian) when reading from or writing to Modbus registers. ```C# void registers.SetBigEndian(...); void registers.SetLittleEndian(...); void registers.SetMidLittleEndian(...); Span registers.GetBigEndian(...); Span registers.GetLittleEndian(...); Span registers.GetMidLittleEndian(...); ``` -------------------------------- ### Waiting for Client and Stopping Server - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_tcp.md This code waits for the client task to finish using await. Once the client is done, it signals the server task to cancel using the CancellationTokenSource, waits for the server task to complete, and finally calls server.Stop(). ```C# // wait for client task to finish await task_client; // stop server cts.Cancel(); await task_server; server.Stop(); serverLogger.LogInformation("Server stopped."); } ``` -------------------------------- ### Updating ModbusTcpServer Data Synchronously (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Demonstrates how to operate the ModbusTcpServer in synchronous mode. The application is responsible for updating the server's data buffers by calling `server.Update()` after modifying registers. This mode requires careful timing to ensure safe access without locks, typically waiting until `IsReady` is true. ```C# var cts = new CancellationTokenSource(); var random = new Random(); var server = new ModbusTcpServer(isAsynchronous: false); server.Start(); while (!cts.IsCancellationRequested) { var registers = server.GetHoldingRegisters(); var value = random.Next(0, 100); registers.SetLittleEndian(address: 0, value); server.Update(); await Task.Delay(TimeSpan.FromMilliseconds(100)); } ``` -------------------------------- ### Updating Modbus RTU Server Registers (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_rtu.md This method demonstrates how a Modbus RTU server can periodically update its holding registers. It shows two approaches: using the standard Span view and using high-performance buffer access with different data types (byte, short, int). It requires a ModbusRtuServer instance and uses the Random class to generate sample data. ```C# static void DoServerWork(ModbusRtuServer server) { var random = new Random(); // Option A: normal performance version, more flexibility /* get buffer in standard form (Span) */ var registers = server.GetHoldingRegisters(); registers.SetLittleEndian(startingAddress: 5, random.Next()); // Option B: high performance version, less flexibility /* interpret buffer as array of bytes (8 bit) */ var byte_buffer = server.GetHoldingRegisterBuffer(); byte_buffer[20] = (byte)(random.Next() >> 24); /* interpret buffer as array of shorts (16 bit) */ var short_buffer = server.GetHoldingRegisterBuffer(); short_buffer[30] = (short)(random.Next(0, 100) >> 16); /* interpret buffer as array of ints (32 bit) */ var int_buffer = server.GetHoldingRegisterBuffer(); int_buffer[40] = random.Next(0, 100); } ``` -------------------------------- ### Connect Modbus RTU Client - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Connects a Modbus RTU client instance to a server using a specified COM port name. ```C# client.Connect("COM1"); ``` -------------------------------- ### Perform Various Modbus Operations (FC01-FC06, FC10, FC16) using FluentModbus C# Client Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_tcp.md This function `DoClientWork` demonstrates several standard Modbus TCP function codes (FC01, FC02, FC03, FC04, FC05, FC06, FC16) using a `ModbusTcpClient` instance. It reads and writes registers and coils, logging the completion of each operation and pausing briefly between calls. It requires a `ModbusTcpClient` and an `ILogger` instance. Data is handled using `Span`. ```C# static void DoClientWork(ModbusTcpClient client, ILogger logger) { Span data; var sleepTime = TimeSpan.FromMilliseconds(100); var unitIdentifier = 0x00; var startingAddress = 0; var registerAddress = 0; // ReadHoldingRegisters = 0x03, // FC03 data = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 10); logger.LogInformation("FC03 - ReadHoldingRegisters: Done"); Thread.Sleep(sleepTime); // WriteMultipleRegisters = 0x10, // FC16 client.WriteMultipleRegisters(unitIdentifier, startingAddress, new byte[] { 10, 00, 20, 00, 30, 00, 255, 00, 255, 01 }); logger.LogInformation("FC16 - WriteMultipleRegisters: Done"); Thread.Sleep(sleepTime); // ReadCoils = 0x01, // FC01 data = client.ReadCoils(unitIdentifier, startingAddress, 10); logger.LogInformation("FC01 - ReadCoils: Done"); Thread.Sleep(sleepTime); // ReadDiscreteInputs = 0x02, // FC02 data = client.ReadDiscreteInputs(unitIdentifier, startingAddress, 10); logger.LogInformation("FC02 - ReadDiscreteInputs: Done"); Thread.Sleep(sleepTime); // ReadInputRegisters = 0x04, // FC04 data = client.ReadInputRegisters(unitIdentifier, startingAddress, 10); logger.LogInformation("FC04 - ReadInputRegisters: Done"); Thread.Sleep(sleepTime); // WriteSingleCoil = 0x05, // FC05 client.WriteSingleCoil(unitIdentifier, registerAddress, true); logger.LogInformation("FC05 - WriteSingleCoil: Done"); Thread.Sleep(sleepTime); // WriteSingleRegister = 0x06, // FC06 client.WriteSingleRegister(unitIdentifier, registerAddress, 127); logger.LogInformation("FC06 - WriteSingleRegister: Done"); } ``` -------------------------------- ### Writing Single Modbus Register (short) C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Writes a single 16-bit signed integer (`short`) value to a specified register address on a Modbus device. Includes code to read the value back from the server to verify the write operation. ```C# var unitIdentifier = 0xFF; var startingAddress = 0; var registerAddress = 0; var quantity = 10; var shortData = new short[] { 4263 }; client.WriteSingleRegister(unitIdentifier, registerAddress, shortData); // read back from server to prove correctness var shortDataResult = client.ReadHoldingRegisters(unitIdentifier, startingAddress, 1); Console.WriteLine(shortDataResult[0]); // should print '4263' ``` -------------------------------- ### Implementing Modbus Server Request Validation (C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Configures a ModbusTcpServer with a RequestValidator lambda function. This function checks the incoming request arguments (args) and returns a ModbusExceptionCode to indicate if the request is valid or should result in an exception response (e.g., IllegalFunction, IllegalDataAddress). ```C# var server = new ModbusTcpServer() { RequestValidator = args => { if (args.FunctionCode == ModbusFunctionCode.WriteSingleRegister) return ModbusExceptionCode.IllegalFunction; else if (args.Address < 5 || args.Address > 15) return ModbusExceptionCode.IllegalDataAddress; else return ModbusExceptionCode.OK; } }; ``` -------------------------------- ### Checking Specific Modbus Coil Bit C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Shows how to check the state of a specific bit (coil) within the `Span` returned by the `ReadCoils` method using bitwise operations. ```C# var position = 2; var boolValue = ((boolData[0] >> position) & 1) > 0; ``` -------------------------------- ### Asynchronously Reading Modbus Data to Array C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Demonstrates how to perform an asynchronous read operation using a Modbus client and convert the resulting `Span` data into a standard array (`byte[]`) for later use or return from an async method. ```C# async byte[] DoAsync() { var client = new ModbusTcpClient(); client.Connect(...); await ; return client.ReadHoldingRegisters(1, 2, 3).ToArray(); } ``` -------------------------------- ### Convert Span to Array - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Explains how to convert a Span back into a standard array, which involves copying the data but allows the data to be used in contexts where Span is not supported (e.g., async methods). ```C# float[] floatArray = floatSpan.ToArray(); ``` -------------------------------- ### Writing Single Modbus Coil (boolean) C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Writes a single boolean value (`true` or `false`) to a specified coil address on a Modbus device. ```C# client.WriteSingleCoil(unitIdentifier, registerAddress, true); ``` -------------------------------- ### Connect Modbus Client with Endianness - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Illustrates how to explicitly specify the endianness (BigEndian or LittleEndian) when connecting Modbus TCP or RTU clients to ensure correct data interpretation, overriding the default little-endian expectation. ```C# var client = new ModbusTcpClient(...); client.Connect(..., ModbusEndianness.BigEndian); var client = new ModbusRtuClient(...); client.Connect(..., ModbusEndianness.BigEndian); ``` -------------------------------- ### Reading Modbus Holding Registers (float) C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Reads holding registers and interprets the data as an array of single-precision floating-point numbers (`float`) using a generic overload. It then demonstrates accessing and printing the first and last values. ```C# // interpret data as float var floatData = client.ReadHoldingRegisters(unitIdentifier, startingAddress, count); var firstValue = floatData[0]; var lastValue = floatData[floatData.Length - 1]; Console.WriteLine($"Fist value is {firstValue}"); Console.WriteLine($"Last value is {lastValue}"); ``` -------------------------------- ### Writing Integer and Short Values to Holding Registers (Big Endian, C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Compares writing a 4-byte integer versus a 2-byte short value to holding registers using `SetBigEndian`. Highlights the need to explicitly specify the type (``, ``) or cast the value to ensure the correct number of bytes is written. ```C# // This will write an 4 byte integer registers.SetBigEndian(address: 1, value: 99); /* recommended */ registers.SetBigEndian(address: 1, value: 99); // These will write a 2 byte short registers.SetBigEndian(address: 1, value: 99); /* recommended */ registers.SetBigEndian(address: 1, value: (short)99); ``` -------------------------------- ### Reading Modbus Coils (boolean) C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Defines parameters for reading boolean values (coils) from a Modbus device and performs the read operation. The result is a `Span` where each bit represents a boolean value. ```C# var unitIdentifier = 0xFF; var startingAddress = 0; var quantity = 10; var boolData = client.ReadCoils(unitIdentifier, startingAddress, quantity); ``` -------------------------------- ### Writing Multiple Modbus Registers (float) C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Writes an array of single-precision floating-point numbers (`float`) to multiple consecutive registers on a Modbus device. This uses a generic overload for convenience. ```C# var floatData = new float[] { 1.1F, 9557e3F }; client.WriteMultipleRegisters(unitIdentifier, startingAddress, floatData); ``` -------------------------------- ### Disposing Modbus TCP Server C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Disposes of the Modbus TCP server instance, releasing resources and shutting down the server gracefully. ```C# server.Dispose(); ``` -------------------------------- ### Updating FluentModbus Server Holding Registers - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_tcp.md This method, intended to be called periodically by the server task, shows two options for updating the server's holding registers: a standard performance version using GetHoldingRegisters() and a high-performance version using GetHoldingRegisterBuffer() to access the underlying buffer as different data types (byte, short, int). ```C# static void DoServerWork(ModbusTcpServer server) { var random = new Random(); // Option A: normal performance version, more flexibility /* get buffer in standard form (Span) */ var registers = server.GetHoldingRegisters(); registers.SetLittleEndian(startingAddress: 5, random.Next()); // Option B: high performance version, less flexibility /* interpret buffer as array of bytes (8 bit) */ var byte_buffer = server.GetHoldingRegisterBuffer(); byte_buffer[20] = (byte)(random.Next() >> 24); /* interpret buffer as array of shorts (16 bit) */ var short_buffer = server.GetHoldingRegisterBuffer(); short_buffer[30] = (short)(random.Next(0, 100) >> 16); /* interpret buffer as array of ints (32 bit) */ var int_buffer = server.GetHoldingRegisterBuffer(); int_buffer[40] = random.Next(0, 100); } ``` -------------------------------- ### Writing Double Value to Holding Registers (Big Endian, C#) Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Illustrates how to write a double-precision floating-point value to the server's holding registers using the `SetBigEndian` extension method. A double value occupies 8 bytes, spanning multiple 16-bit registers (e.g., addresses 1-4). ```C# // Get a reference to the holding registers. var registers = server.GetHoldingRegisters(); // Write a double value (0.85) to address 1. // With an 8-byte double value, this will be written into // the holding registers 1 - 4. registers.SetBigEndian(address: 1, value: 0.85); ``` -------------------------------- ### Access Value in Span - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Shows how to access elements within a Span using array-like indexing after it has been cast to the desired type. ```C# var floatValue = myFloatSpan[0]; ``` -------------------------------- ### Cast Span to Other Types - C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/index.md Demonstrates how to efficiently reinterpret a Span as a Span of another value type (like int or float) using MemoryMarshal.Cast, without copying the underlying data. ```C# Span byteSpan = new byte[] { 1, 2, 3, 4 }.AsSpan(); Span intSpan = MemoryMarshal.Cast(byteSpan); Span floatSpan = MemoryMarshal.Cast(intSpan); ``` -------------------------------- ### Implementing Custom Request Validation in FluentModbus C# Source: https://github.com/apollo3zehn/fluentmodbus/blob/dev/doc/samples/modbus_validator.md This C# snippet demonstrates how to assign a custom validation method (`ModbusValidator`) to the `RequestValidator` property of a `ModbusTcpServer`. The `ModbusValidator` function checks the requested address against predefined valid ranges for holding and input registers and uses a switch expression to return `ModbusExceptionCode.OK` for valid requests or an appropriate error code like `IllegalDataAddress` or `IllegalFunction` for invalid ones. ```C# var server = new ModbusTcpServer() { RequestValidator = this.ModbusValidator; }; private ModbusExceptionCode ModbusValidator(RequestValidatorArgs args) { // check if address is within valid holding register limits var holdingLimits = args.Address >= 50 && args.Address < 90 || args.Address >= 2000 && args.Address < 2100; // check if address is within valid input register limits var inputLimits = args.Address >= 1000 && args.Address < 2000; // go through all cases and return proper response return (args.FunctionCode, holdingLimits, inputLimits) switch { // holding registers (ModbusFunctionCode.ReadHoldingRegisters, true, _) => ModbusExceptionCode.OK, (ModbusFunctionCode.ReadWriteMultipleRegisters, true, _) => ModbusExceptionCode.OK, (ModbusFunctionCode.WriteMultipleRegisters, true, _) => ModbusExceptionCode.OK, (ModbusFunctionCode.WriteSingleRegister, true, _) => ModbusExceptionCode.OK, (ModbusFunctionCode.ReadHoldingRegisters, false, _) => ModbusExceptionCode.IllegalDataAddress, (ModbusFunctionCode.ReadWriteMultipleRegisters, false, _) => ModbusExceptionCode.IllegalDataAddress, (ModbusFunctionCode.WriteMultipleRegisters, false, _) => ModbusExceptionCode.IllegalDataAddress, (ModbusFunctionCode.WriteSingleRegister, false, _) => ModbusExceptionCode.IllegalDataAddress, // input registers (ModbusFunctionCode.ReadInputRegisters, _, true) => ModbusExceptionCode.OK, (ModbusFunctionCode.ReadInputRegisters, _, false) => ModbusExceptionCode.IllegalDataAddress, // deny other function codes _ => ModbusExceptionCode.IllegalFunction }; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.