using System; using System.Collections.Generic; using NModbus; namespace Team.Utility { public class SlaveStorage : ISlaveDataStore { private readonly SparsePointSource _coilDiscretes; private readonly SparsePointSource _coilInputs; private readonly SparsePointSource _holdingRegisters; private readonly SparsePointSource _inputRegisters; public SlaveStorage() { _coilDiscretes = new SparsePointSource(); _coilInputs = new SparsePointSource(); _holdingRegisters = new SparsePointSource(); _inputRegisters = new SparsePointSource(); } public SparsePointSource CoilDiscretes { get { return _coilDiscretes; } } public SparsePointSource CoilInputs { get { return _coilInputs; } } public SparsePointSource HoldingRegisters { get { return _holdingRegisters; } } public SparsePointSource InputRegisters { get { return _inputRegisters; } } IPointSource ISlaveDataStore.CoilDiscretes { get { return _coilDiscretes; } } IPointSource ISlaveDataStore.CoilInputs { get { return _coilInputs; } } IPointSource ISlaveDataStore.HoldingRegisters { get { return _holdingRegisters; } } IPointSource ISlaveDataStore.InputRegisters { get { return _inputRegisters; } } } public class SparsePointSource : IPointSource { private readonly Dictionary _values = new(); public event EventHandler> StorageOperationOccurred; /// /// Gets or sets the value of an individual point wih tout /// /// /// public TPoint this[ushort registerIndex] { get => _values.TryGetValue(registerIndex, out var value) ? value : default; set => _values[registerIndex] = value; } public TPoint[] ReadPoints(ushort startAddress, ushort numberOfPoints) { var points = new TPoint[numberOfPoints]; for (ushort index = 0; index < numberOfPoints; index++) { points[index] = this[(ushort)(index + startAddress)]; } StorageOperationOccurred?.Invoke(this, new StorageEventArgs(PointOperation.Read, startAddress, points)); return points; } public void WritePoints(ushort startAddress, TPoint[] points) { for (ushort index = 0; index < points.Length; index++) { this[(ushort)(index + startAddress)] = points[index]; } StorageOperationOccurred?.Invoke(this, new StorageEventArgs(PointOperation.Write, startAddress, points)); } } public class StorageEventArgs : EventArgs { private readonly TPoint[] _points; public StorageEventArgs(PointOperation pointOperation, ushort startingAddress, TPoint[] points) { Operation = pointOperation; StartingAddress = startingAddress; _points = points; } public ushort StartingAddress { get; } public TPoint[] Points => _points; public PointOperation Operation { get; } } public enum PointOperation { Read, Write } }