Просмотр исходного кода

Refactor ModbusSimulationProtocol

SenGao 1 неделя назад
Родитель
Сommit
b88ca642fe

+ 9 - 8
CommunicationProtocols/ModbusSimulationProtocol/Data/PointSource.cs

@@ -1,27 +1,28 @@
 using NModbus;
+using System.Xml.Linq;
 
 namespace ModbusSimulationProtocol.Data;
 
 public class PointSource<TPoint> : IPointSource<TPoint>
 {
+    private readonly string _name;
     private readonly int _capacity;
     private readonly TPoint[] _points;
-    private readonly bool _writeable;
-    private readonly object _lock = new object();
-
+    private readonly object _lock = new();
+    
     /// <summary>
-    /// A discription to a kind of register.
+    /// The implementation to the <typeparamref name="TPoint"/> register.
     /// </summary>
+    /// <param name="name">The name of this register.</param>
     /// <param name="capacity">A number between 1 and 65536 inclusive.</param>
-    /// <param name="writeable">True if this PointSource can be wrote.</param>
-    public PointSource(int capacity, bool? writeable = null)
+    public PointSource(string name, int capacity = 65536)
     {
         ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(capacity, ushort.MinValue, nameof(capacity));
         ArgumentOutOfRangeException.ThrowIfGreaterThan(capacity, ushort.MaxValue + 1, nameof(capacity));
 
+        _name = name;
         _capacity = capacity;
         _points = new TPoint[_capacity];
-        _writeable = writeable ?? false;
     }
 
     public TPoint[] ReadPoints(ushort startAddress, ushort numberOfPoints)
@@ -44,7 +45,7 @@ public class PointSource<TPoint> : IPointSource<TPoint>
 
     public void WritePoints(ushort startAddress, TPoint[] points)
     {
-        if (!_writeable || points.Length == 0) return;
+        if (points.Length == 0) return;
 
         int start = startAddress;
         int count = points.Length;

+ 9 - 13
CommunicationProtocols/ModbusSimulationProtocol/Data/SlaveDataStore.cs

@@ -9,35 +9,31 @@ public class SlaveDataStore : ISlaveDataStore
     private readonly IPointSource<ushort> _holdingRegisters;
     private readonly IPointSource<ushort> _inputRegisters;
 
-    public SlaveDataStore(
-        int coilDiscreteCount,
-        int coilInputCount,
-        int holdingRegisterCount,
-        int inputRegisterCount)
+    public SlaveDataStore()
     {
-        _coilDiscretes = new PointSource<bool>(coilDiscreteCount, writeable: true);
-        _coilInputs = new PointSource<bool>(coilInputCount, writeable: false);
-        _holdingRegisters = new PointSource<ushort>(holdingRegisterCount, writeable: true);
-        _inputRegisters = new PointSource<ushort>(inputRegisterCount, writeable: false);
+        _coilDiscretes = new PointSource<bool>("CoilDiscretes");
+        _coilInputs = new PointSource<bool>("CoilInputs");
+        _holdingRegisters = new PointSource<ushort>("HoldingRegisters");
+        _inputRegisters = new PointSource<ushort>("InputRegisters");
     }
 
     /// <summary>
-    /// Read and Write
+    /// Read-Write
     /// </summary>
     public IPointSource<bool> CoilDiscretes => _coilDiscretes;
 
     /// <summary>
-    /// Read Only
+    /// Read-Only
     /// </summary>
     public IPointSource<bool> CoilInputs => _coilInputs;
 
     /// <summary>
-    /// Read and Write
+    /// Read-Write
     /// </summary>
     public IPointSource<ushort> HoldingRegisters => _holdingRegisters;
 
     /// <summary>
-    /// Read Only
+    /// Read-Only
     /// </summary>
     public IPointSource<ushort> InputRegisters => _inputRegisters;
 }

+ 0 - 12
CommunicationProtocols/ModbusSimulationProtocol/Interface/IModbusMasterClient.cs

@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ModbusSimulationProtocol.Interface
-{
-    public interface IModbusMasterClient : IDisposable
-    {
-    }
-}

+ 9 - 6
CommunicationProtocols/ModbusSimulationProtocol/Interface/IModbusSlaveService.cs

@@ -1,10 +1,13 @@
-namespace ModbusSimulationProtocol.Interface;
+using NModbus;
+
+namespace ModbusSimulationProtocol.Interface;
 
 public interface IModbusSlaveService : IDisposable
 {
-    void Initialize(string ip, ushort port);
-    void ActivateNetwork();
-    void AddSlave(byte slaveId, int coilCount, int discreteInputCount, int holdingRegisterCount, int inputRegisterCount);
-    void RemoveSlave(byte slaveId);
-    int GetConnectedMasterCount();
+    bool Initialize(string ip, ushort port, byte slaveId);
+    bool Open();
+    bool TryWriteValues<TPoint>(IPointSource<TPoint> source, ushort address, TPoint[] points);
+    bool TryReadValues<TPoint>(IPointSource<TPoint> source, ushort address, ushort count, out TPoint[]? outPoints);
+
+    ISlaveDataStore SlaveDataStore {  get; }
 }

+ 0 - 78
CommunicationProtocols/ModbusSimulationProtocol/Services/ModbusMasterClient.cs

@@ -1,78 +0,0 @@
-using ModbusSimulationProtocol.Interface;
-using NModbus;
-using System.Net.Sockets;
-
-namespace ModbusSimulationProtocol.Services;
-
-public class ModbusMasterClient : IModbusMasterClient
-{
-    private readonly IModbusLogger? _logger;
-
-    private readonly ModbusFactory _factory;
-    private IModbusMaster? _master = null;
-
-    private bool disposedValue;
-
-    public ModbusMasterClient(IModbusLogger? logger)
-    {
-        _logger = logger;
-
-        _factory = new ModbusFactory();
-    }
-
-    public void Initialize(string ip,ushort port)
-    {
-        ArgumentNullException.ThrowIfNullOrWhiteSpace(ip);
-        if (_master is not null)
-        {
-            WriteLog(LoggingLevel.Information, "The master has been created.");
-            return;
-        }
-
-        try
-        {
-            TcpClient tcpClient = new TcpClient(ip, port);
-            _master = _factory.CreateMaster(tcpClient);
-        }
-        catch (Exception ex)
-        {
-            WriteLog(LoggingLevel.Error, ex.ToString());
-        }
-    }
-
-
-
-    private void WriteLog(LoggingLevel loggingLevel, string log)
-    {
-        _logger?.Log(loggingLevel, $"[{nameof(ModbusMasterClient)}]:{log}");
-    }
-
-    protected virtual void Dispose(bool disposing)
-    {
-        if (!disposedValue)
-        {
-            if (disposing)
-            {
-                // TODO: dispose managed state (managed objects)
-            }
-
-            // TODO: free unmanaged resources (unmanaged objects) and override finalizer
-            // TODO: set large fields to null
-            disposedValue = true;
-        }
-    }
-
-    // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
-    // ~ModbusMasterClient()
-    // {
-    //     // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
-    //     Dispose(disposing: false);
-    // }
-
-    public void Dispose()
-    {
-        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
-        Dispose(disposing: true);
-        GC.SuppressFinalize(this);
-    }
-}

+ 41 - 40
CommunicationProtocols/ModbusSimulationProtocol/Services/ModbusSlaveService.cs

@@ -1,8 +1,8 @@
-using ModbusSimulationProtocol.Data;
-using ModbusSimulationProtocol.Interface;
+using ModbusSimulationProtocol.Interface;
 using NModbus;
 using System.Net;
 using System.Net.Sockets;
+using SlaveDataStore = ModbusSimulationProtocol.Data.SlaveDataStore;
 
 namespace ModbusSimulationProtocol.Services;
 
@@ -11,7 +11,8 @@ public class ModbusSlaveService : IModbusSlaveService
     private readonly IModbusLogger? _logger;
 
     private readonly ModbusFactory _factory;
-    private IModbusTcpSlaveNetwork? _network = null;
+    private readonly ISlaveDataStore _slaveDataStore;
+    private IModbusTcpSlaveNetwork? _network;
 
     private bool disposedValue;
 
@@ -20,41 +21,54 @@ public class ModbusSlaveService : IModbusSlaveService
         _logger = logger;
 
         _factory = new ModbusFactory(logger: _logger);
+        _slaveDataStore = new SlaveDataStore();
     }
 
-    public void Initialize(string ip, ushort port)
+    public ISlaveDataStore SlaveDataStore => _slaveDataStore;
+
+    public bool Initialize(string ip, ushort port, byte slaveId = 1)
     {
-        ArgumentNullException.ThrowIfNullOrWhiteSpace(ip);
+        if (string.IsNullOrWhiteSpace(ip))
+        {
+            WriteLog(LoggingLevel.Error, "Incorrect ip address.");
+            return false;
+        }
+
         if (_network is not null)
         {
-            WriteLog(LoggingLevel.Information, "The slave network has been created.");
-            return;
+            WriteLog(LoggingLevel.Warning, "The slave network has been created.");
+            return false;
         }
 
         try
         {
-            TcpListener listener = new TcpListener(IPAddress.Parse(ip), (int)port);
+            TcpListener listener = new(IPAddress.Parse(ip), (int)port);
             _network = _factory.CreateSlaveNetwork(listener);
+            var slave = _factory.CreateSlave(slaveId, _slaveDataStore);
+            _network.AddSlave(slave);
+            WriteLog(LoggingLevel.Information, "Completed initailization.");
+            return true;
         }
         catch (Exception ex)
         {
             WriteLog(LoggingLevel.Error, ex.ToString());
+            return false;
         }
     }
 
-    public void ActivateNetwork()
+    public bool Open()
     {
         if (_network is null)
         {
-            WriteLog(LoggingLevel.Warning, "Performs initializing before activating network.");
-            return;
+            WriteLog(LoggingLevel.Error, "Performs initializing before doing any operation.");
+            return false;
         }
 
         Task.Run(async () =>
         {
             try
             {
-                WriteLog(LoggingLevel.Information, $"Starts async listening.");
+                WriteLog(LoggingLevel.Information, "Starts Tcp Listening");
                 await _network.ListenAsync();
             }
             catch (Exception ex)
@@ -62,63 +76,51 @@ public class ModbusSlaveService : IModbusSlaveService
                 WriteLog(LoggingLevel.Error, ex.ToString());
             }
         });
+        return true;
     }
 
-    public void AddSlave(byte slaveId,
-                         int coilCount, int discreteInputCount, int holdingRegisterCount, int inputRegisterCount)
+    public bool TryWriteValues<TPoint>(IPointSource<TPoint> source, ushort address, TPoint[] points)
     {
         if (_network is null)
         {
-            WriteLog(LoggingLevel.Warning, "Performs initializing before adding any slave.");
-            return;
+            WriteLog(LoggingLevel.Error, "Performs initializing before doing any operation.");
+            return false;
         }
 
         try
         {
-            var slave = _factory.CreateSlave(slaveId, new SlaveDataStore(coilCount, discreteInputCount, holdingRegisterCount, inputRegisterCount));
-            _network.AddSlave(slave);
+            source.WritePoints(address, points);
+            return true;
         }
         catch (Exception ex)
         {
             WriteLog(LoggingLevel.Error, ex.ToString());
+            return false;
         }
     }
 
-    public void RemoveSlave(byte slaveId)
+    public bool TryReadValues<TPoint>(IPointSource<TPoint> source, ushort address, ushort count, out TPoint[]? outPoints)
     {
         if (_network is null)
         {
-            WriteLog(LoggingLevel.Warning, "The slave network do not exist even.");
-            return;
-        }
-
-        if (_network.GetSlave(slaveId) is null)
-        {
-            WriteLog(LoggingLevel.Warning, "The specified slave do not exist. Failed to remove.");
-            return;
+            WriteLog(LoggingLevel.Error, "Performs initializing before doing any operation.");
+            outPoints = null;
+            return false;
         }
 
         try
         {
-            _network.RemoveSlave(slaveId);
-            WriteLog(LoggingLevel.Information, $"The slave {slaveId} has been removed.");
+            outPoints = source.ReadPoints(address, count);
+            return true;
         }
         catch (Exception ex)
         {
             WriteLog(LoggingLevel.Error, ex.ToString());
+            outPoints = null;
+            return false;
         }
     }
 
-    public int GetConnectedMasterCount()
-    {
-        if (_network is null)
-        {
-            WriteLog(LoggingLevel.Warning, "The slave network do not exist even.");
-            return 0;
-        }
-
-        return _network.Masters.Count;
-    }
     private void WriteLog(LoggingLevel loggingLevel, string log)
     {
         _logger?.Log(loggingLevel, $"[{nameof(ModbusSlaveService)}]:{log}");
@@ -132,7 +134,6 @@ public class ModbusSlaveService : IModbusSlaveService
             {
                 // TODO: dispose managed state (managed objects)
                 _network?.Dispose();
-                _network = null;
             }
 
             // TODO: free unmanaged resources (unmanaged objects) and override finalizer

+ 21 - 6
Tools/ModbusMasterSlaveSim/Program.cs

@@ -11,10 +11,18 @@ internal class Program
     {
         IModbusLogger logger =new ModbusLogger();
         IModbusSlaveService modbusSlaveService =new ModbusSlaveService(logger);
-        modbusSlaveService.Initialize("127.0.0.1", 1502);
-        modbusSlaveService.AddSlave(1, 64, 64, 64, 64);
-        modbusSlaveService.AddSlave(2, 128, 128, 128, 128);
-        modbusSlaveService.ActivateNetwork();
+        modbusSlaveService.Initialize("127.0.0.1", 1502, 1);
+        modbusSlaveService.Open();
+        var coilDiscretes = modbusSlaveService.SlaveDataStore.CoilDiscretes;
+        modbusSlaveService.TryWriteValues(coilDiscretes, 0, [true, false, true, true]);
+        modbusSlaveService.TryReadValues(coilDiscretes,0,5,out var outPoints);
+        if (outPoints is not null)
+        {
+            foreach (var point in outPoints)
+            {
+                Console.WriteLine(point);
+            }
+        }
 
         TcpClient masterTcpClient = new TcpClient("127.0.0.1", 1502);
         var factory = new ModbusFactory();
@@ -25,8 +33,15 @@ internal class Program
             Console.WriteLine("Waiting for 3s...");
             await Task.Delay(3000);
 
-            master.WriteSingleCoil(1, 0, true);
-            var rst = master.ReadCoils(1, 0, 2);
+            master.WriteSingleCoil(1, 10, true);
+            var rst = master.ReadCoils(1, 10, 2);
+            if (rst is not null)
+            {
+                foreach (var point in rst)
+                {
+                    Console.WriteLine(point);
+                }
+            }
         });