Skip to content

Commit

Permalink
Merge commit 'f96247576725ec9dcd764d5bd4f8c5402f2b56a1' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent Wilms committed Nov 22, 2024
2 parents 07233a9 + f962475 commit bbd7dcd
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 18 deletions.
6 changes: 3 additions & 3 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,12 +408,12 @@ It might happen that a server should not support all Modbus functions or only a

var server = new ModbusTcpServer()
{
RequestValidator = (unitIdentifier, functionCode, address, quantityOfRegisters) =>
RequestValidator = args =>
{
if (functionCode == ModbusFunctionCode.WriteSingleRegister)
if (args.FunctionCode == ModbusFunctionCode.WriteSingleRegister)
return ModbusExceptionCode.IllegalFunction;

else if (address < 5 || address > 15)
else if (args.Address < 5 || args.Address > 15)
return ModbusExceptionCode.IllegalDataAddress;

else
Expand Down
14 changes: 5 additions & 9 deletions doc/samples/modbus_validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,17 @@ var server = new ModbusTcpServer()
RequestValidator = this.ModbusValidator;
};

private ModbusExceptionCode ModbusValidator(
byte unitIdentifier,
ModbusFunctionCode functionCode,
ushort address,
ushort quantityOfRegisters)
private ModbusExceptionCode ModbusValidator(RequestValidatorArgs args)
{
// check if address is within valid holding register limits
var holdingLimits = (address >= 50 && address < 90) ||
address >= 2000 && address < 2100;
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 = address >= 1000 && address < 2000;
var inputLimits = args.Address >= 1000 && args.Address < 2000;

// go through all cases and return proper response
return (functionCode, holdingLimits, inputLimits) switch
return (args.FunctionCode, holdingLimits, inputLimits) switch
{
// holding registers
(ModbusFunctionCode.ReadHoldingRegisters, true, _) => ModbusExceptionCode.OK,
Expand Down
9 changes: 8 additions & 1 deletion src/FluentModbus/Server/ModbusRequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,14 @@ private bool CheckRegisterBounds(ModbusFunctionCode functionCode, ushort address
{
if (ModbusServer.RequestValidator is not null)
{
var result = ModbusServer.RequestValidator(UnitIdentifier, functionCode, address, quantityOfRegisters);
var result = ModbusServer.RequestValidator(new RequestValidatorArgs
{
UnitIdentifier = UnitIdentifier,
Address = address,
QuantityOfRegisters = quantityOfRegisters,
FunctionCode = functionCode,
ConnectionName = DisplayName
});

if (result > ModbusExceptionCode.OK)
{
Expand Down
33 changes: 32 additions & 1 deletion src/FluentModbus/Server/ModbusServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,37 @@ public readonly struct CoilsChangedEventArgs
public int[] Coils { get; init; }
}

/// <summary>
/// Provides data for the request validator.
/// </summary>
public readonly struct RequestValidatorArgs
{
/// <summary>
/// The unit identifier for the request.
/// </summary>
public byte UnitIdentifier { get; init; }

/// <summary>
/// Modbus function code.
/// </summary>
public ModbusFunctionCode FunctionCode { get; init; }

/// <summary>
/// Address of the first register or coil to read or write.
/// </summary>
public ushort Address { get; init; }

/// <summary>
/// Quantity of registers or coils to read or write.
/// </summary>
public ushort QuantityOfRegisters { get; init; }

/// <summary>
/// DisplayName of the connection that is requesting the data.
/// </summary>
public string ConnectionName { get; init; }
}

/// <summary>
/// Base class for a Modbus server.
/// </summary>
Expand Down Expand Up @@ -144,7 +175,7 @@ protected ModbusServer(bool isAsynchronous, ILogger logger)
/// <summary>
/// Gets or sets a method that validates each client request.
/// </summary>
public Func<byte, ModbusFunctionCode, ushort, ushort, ModbusExceptionCode>? RequestValidator { get; set; }
public Func<RequestValidatorArgs, ModbusExceptionCode>? RequestValidator { get; set; }

/// <summary>
/// Gets or sets whether the events should be raised when register or coil data changes. Default: false.
Expand Down
8 changes: 4 additions & 4 deletions tests/FluentModbus.Tests/ModbusServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,12 @@ public async void RespectsRequestValidator(ModbusFunctionCode functionCode, usho

using var server = new ModbusTcpServer()
{
RequestValidator = (unitIdentifier, functionCode, address, quantityOfRegisters) =>
RequestValidator = args =>
{
var holdingLimits = (address >= 50 && address < 90) ||
address >= 2000 && address < 2100;
var holdingLimits = args.Address >= 50 && args.Address < 90 ||
args.Address >= 2000 && args.Address < 2100;

var inputLimits = address >= 1000 && address < 2000;
var inputLimits = args.Address >= 1000 && args.Address < 2000;

return (functionCode, holdingLimits, inputLimits) switch
{
Expand Down

0 comments on commit bbd7dcd

Please sign in to comment.