Control.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using NModbus;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Runtime.CompilerServices;
  4. namespace PLCControl.ModBus
  5. {
  6. public class Control : IPLCControl
  7. {
  8. private object locker = new object();
  9. private System.Net.Sockets.TcpClient? tcpClient;
  10. private IModbusMaster? modbus;
  11. [AllowNull]
  12. public Action<bool> ConnectionChanged { get; set; }
  13. public bool IsConnected => tcpClient == null ? false : tcpClient.Connected;
  14. [AllowNull]
  15. public string IPAddress { get; set; } = "127.0.0.1";
  16. public int Port { get; set; } = 502;
  17. public byte SlaveID { get; set; } = 1;
  18. private bool _isConnected;
  19. private void InvokeConnectionChanged(bool isConnected)
  20. {
  21. lock (locker)
  22. {
  23. if (_isConnected == isConnected) return;
  24. ConnectionChanged?.Invoke(isConnected);
  25. _isConnected = isConnected;
  26. }
  27. }
  28. public bool Connect()
  29. {
  30. try
  31. {
  32. var modbusFactory = new NModbus.ModbusFactory();
  33. tcpClient = new System.Net.Sockets.TcpClient();
  34. var result = tcpClient.ConnectAsync(IPAddress, Port).Wait(500);
  35. if (!result) return false;
  36. modbus = modbusFactory.CreateMaster(tcpClient);
  37. InvokeConnectionChanged(true);
  38. return true;
  39. }
  40. catch (Exception ex)
  41. {
  42. return false;
  43. }
  44. }
  45. public void Disconnect()
  46. {
  47. try
  48. {
  49. tcpClient?.Close();
  50. InvokeConnectionChanged(false);
  51. }
  52. catch (Exception ex)
  53. {
  54. }
  55. }
  56. public bool ReadBit(ushort address, byte bitindex)
  57. {
  58. var result = Read(address, 2)[0];
  59. return (result & (1 << bitindex)) != 0;
  60. }
  61. private ushort[] Read(ushort startaddr, byte addrnum)
  62. {
  63. try
  64. {
  65. if (modbus == null) return new ushort[addrnum / 2];
  66. return modbus.ReadHoldingRegisters(SlaveID, (ushort)(startaddr +(addrnum>>2) - 1), (ushort)(addrnum >> 1));
  67. }
  68. catch
  69. {
  70. Disconnect();
  71. }
  72. return new ushort[addrnum / 2];
  73. }
  74. public void ReadDatas<T>(ushort startAddress, ref T value, byte bytecount) where T : unmanaged
  75. {
  76. if (modbus == null) return;
  77. try
  78. {
  79. var result = modbus.ReadHoldingRegisters(SlaveID, (ushort)(startAddress + (bytecount >>2) -1), (ushort)(bytecount >> 1)).Reverse().ToArray();
  80. Unsafe.CopyBlock(ref Unsafe.As<T, byte>(ref value), ref Unsafe.As<ushort, byte>(ref result[0]), (uint)bytecount);
  81. }
  82. catch
  83. {
  84. Disconnect();
  85. }
  86. }
  87. public void WriteDatas<T>(ushort address,ref T data,byte bytecount) where T: unmanaged
  88. {
  89. if (modbus == null) return;
  90. try
  91. {
  92. ushort[] datas = new ushort[bytecount / 2];
  93. Unsafe.CopyBlock(ref Unsafe.As<ushort, byte>(ref datas[0]), ref Unsafe.As<T, byte>(ref data), (uint)datas.Length * 2);
  94. modbus.WriteMultipleRegisters(SlaveID, (ushort)(address + (bytecount >>1) -1 - 1), datas);
  95. }
  96. catch
  97. {
  98. Disconnect();
  99. }
  100. }
  101. public short ReadInt16(ushort address)
  102. {
  103. return Unsafe.As<ushort, short>(ref Read(address, 2)[0]);
  104. }
  105. public void WriteBit(ushort address, byte bitindex, bool value)
  106. {
  107. var result = Read(address, 2)[0];
  108. result = (ushort)(value ? result | (1 << bitindex) : result & ~(1 << bitindex));
  109. WriteInt16(address, Unsafe.As<ushort, short>(ref result));
  110. }
  111. public void WriteInt16(ushort address, short value)
  112. {
  113. if (modbus == null) return;
  114. try
  115. {
  116. modbus.WriteSingleRegister(SlaveID, (ushort)(address - 1), Unsafe.As<short, ushort>(ref value));
  117. }
  118. catch
  119. {
  120. Disconnect();
  121. }
  122. }
  123. }
  124. }