using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; using AMWD.Protocols.Modbus.Common.Contracts; using AMWD.Protocols.Modbus.Common.Events; using AMWD.Protocols.Modbus.Common.Models; using AMWD.Protocols.Modbus.Common.Protocols; namespace AMWD.Protocols.Modbus.Common.Utils { /// /// Implements a virtual Modbus client. /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class VirtualModbusClient : ModbusClientBase { #region Constructor /// /// Initializes a new instance of the class. /// /// DO NOT MODIFY connection or protocol. public VirtualModbusClient() : base(new VirtualConnection()) { Protocol = new VirtualProtocol(); TypedProtocol.CoilWritten += (sender, e) => CoilWritten?.Invoke(this, e); TypedProtocol.RegisterWritten += (sender, e) => RegisterWritten?.Invoke(this, e); } #endregion Constructor #region Events /// /// Indicates that a -value received through a remote client has been written. /// public event EventHandler CoilWritten; /// /// Indicates that a -value received from a remote client has been written. /// public event EventHandler RegisterWritten; #endregion Events #region Properties internal VirtualProtocol TypedProtocol => Protocol as VirtualProtocol; #endregion Properties #region Device Handling /// /// Adds a device to the virtual client. /// /// The unit id of the device. /// if the device was added successfully, otherwise. public bool AddDevice(byte unitId) => TypedProtocol.AddDevice(unitId); /// /// Removes a device from the virtual client. /// /// The unit id of the device. /// if the device was removed successfully, otherwise. public bool RemoveDevice(byte unitId) => TypedProtocol.RemoveDevice(unitId); #endregion Device Handling #region Entity Handling /// /// Gets a from the specified . /// /// The unit ID of the device. /// The address of the . public Coil GetCoil(byte unitId, ushort address) => TypedProtocol.GetCoil(unitId, address); /// /// Sets a to the specified . /// /// The unit ID of the device. /// The to set. public void SetCoil(byte unitId, Coil coil) => TypedProtocol.SetCoil(unitId, coil); /// /// Gets a from the specified . /// /// The unit ID of the device. /// The address of the . public DiscreteInput GetDiscreteInput(byte unitId, ushort address) => TypedProtocol.GetDiscreteInput(unitId, address); /// /// Sets a to the specified . /// /// The unit ID of the device. /// The to set. public void SetDiscreteInput(byte unitId, DiscreteInput discreteInput) => TypedProtocol.SetDiscreteInput(unitId, discreteInput); /// /// Gets a from the specified . /// /// The unit ID of the device. /// The address of the . public HoldingRegister GetHoldingRegister(byte unitId, ushort address) => TypedProtocol.GetHoldingRegister(unitId, address); /// /// Sets a to the specified . /// /// The unit ID of the device. /// The to set. public void SetHoldingRegister(byte unitId, HoldingRegister holdingRegister) => TypedProtocol.SetHoldingRegister(unitId, holdingRegister); /// /// Gets a from the specified . /// /// The unit ID of the device. /// The address of the . public InputRegister GetInputRegister(byte unitId, ushort address) => TypedProtocol.GetInputRegister(unitId, address); /// /// Sets a to the specified . /// /// The unit ID of the device. /// The to set. public void SetInputRegister(byte unitId, InputRegister inputRegister) => TypedProtocol.SetInputRegister(unitId, inputRegister); #endregion Entity Handling #region Methods /// protected override void Dispose(bool disposing) { TypedProtocol.Dispose(); base.Dispose(disposing); } #endregion Methods #region Connection internal class VirtualConnection : IModbusConnection { public string Name => nameof(VirtualConnection); public TimeSpan IdleTimeout { get; set; } public TimeSpan ConnectTimeout { get; set; } public TimeSpan ReadTimeout { get; set; } public TimeSpan WriteTimeout { get; set; } public void Dispose() { /* nothing to do */ } public Task> InvokeAsync( IReadOnlyList request, Func, bool> validateResponseComplete, CancellationToken cancellationToken = default) => Task.FromResult(request); } #endregion Connection } }