ModbusSlaveService.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using ModbusSimulationProtocol.Data;
  2. using ModbusSimulationProtocol.Interface;
  3. using NModbus;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. namespace ModbusSimulationProtocol.Services;
  7. public class ModbusSlaveService : IModbusSlaveService, IDisposable
  8. {
  9. private readonly IModbusLogger? _logger;
  10. private readonly ModbusFactory _factory;
  11. private IModbusTcpSlaveNetwork? _network = null;
  12. private bool disposedValue;
  13. public ModbusSlaveService(IModbusLogger? logger)
  14. {
  15. _logger = logger;
  16. _factory = new ModbusFactory(logger: _logger);
  17. }
  18. public void Initialize(string ip, ushort port)
  19. {
  20. ArgumentNullException.ThrowIfNullOrWhiteSpace(ip);
  21. if (_network is not null)
  22. {
  23. WriteLog(LoggingLevel.Information, "The slave network has been created.");
  24. return;
  25. }
  26. try
  27. {
  28. TcpListener listener = new TcpListener(IPAddress.Parse(ip), (int)port);
  29. _network = _factory.CreateSlaveNetwork(listener);
  30. }
  31. catch (Exception ex)
  32. {
  33. WriteLog(LoggingLevel.Error, ex.ToString());
  34. }
  35. }
  36. public void ActivateNetwork()
  37. {
  38. if (_network is null)
  39. {
  40. WriteLog(LoggingLevel.Warning, "Performs initializing before activating network.");
  41. return;
  42. }
  43. Task.Run(async () =>
  44. {
  45. try
  46. {
  47. WriteLog(LoggingLevel.Information, $"Starts async listening.");
  48. await _network.ListenAsync();
  49. }
  50. catch (Exception ex)
  51. {
  52. WriteLog(LoggingLevel.Error, ex.ToString());
  53. }
  54. });
  55. }
  56. public void AddSlave(byte slaveId,
  57. int coilCount, int discreteInputCount, int holdingRegisterCount, int inputRegisterCount)
  58. {
  59. if (_network is null)
  60. {
  61. WriteLog(LoggingLevel.Warning, "Performs initializing before adding any slave.");
  62. return;
  63. }
  64. try
  65. {
  66. var slave = _factory.CreateSlave(slaveId, new SlaveDataStore(coilCount, discreteInputCount, holdingRegisterCount, inputRegisterCount));
  67. _network.AddSlave(slave);
  68. }
  69. catch (Exception ex)
  70. {
  71. WriteLog(LoggingLevel.Error, ex.ToString());
  72. }
  73. }
  74. public void RemoveSlave(byte slaveId)
  75. {
  76. if (_network is null)
  77. {
  78. WriteLog(LoggingLevel.Warning, "The slave network do not exist even.");
  79. return;
  80. }
  81. if (_network.GetSlave(slaveId) is null)
  82. {
  83. WriteLog(LoggingLevel.Warning, "The specified slave do not exist. Failed to remove.");
  84. return;
  85. }
  86. try
  87. {
  88. _network.RemoveSlave(slaveId);
  89. WriteLog(LoggingLevel.Information, $"The slave {slaveId} has been removed.");
  90. }
  91. catch (Exception ex)
  92. {
  93. WriteLog(LoggingLevel.Error, ex.ToString());
  94. }
  95. }
  96. public int GetConnectedMasterCount()
  97. {
  98. if (_network is null)
  99. {
  100. WriteLog(LoggingLevel.Warning, "The slave network do not exist even.");
  101. return 0;
  102. }
  103. return _network.Masters.Count;
  104. }
  105. private void WriteLog(LoggingLevel loggingLevel, string log)
  106. {
  107. _logger?.Log(loggingLevel, $"[{nameof(ModbusSlaveService)}]:{log}");
  108. }
  109. protected virtual void Dispose(bool disposing)
  110. {
  111. if (!disposedValue)
  112. {
  113. if (disposing)
  114. {
  115. // TODO: dispose managed state (managed objects)
  116. _network?.Dispose();
  117. _network = null;
  118. }
  119. // TODO: free unmanaged resources (unmanaged objects) and override finalizer
  120. // TODO: set large fields to null
  121. disposedValue = true;
  122. }
  123. }
  124. // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
  125. // ~ModbusSlaveService()
  126. // {
  127. // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
  128. // Dispose(disposing: false);
  129. // }
  130. public void Dispose()
  131. {
  132. // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
  133. Dispose(disposing: true);
  134. GC.SuppressFinalize(this);
  135. }
  136. }