|
@@ -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
|