123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- using FluentModbus;
- using ProtocalGeneral;
- using System.Net;
- using System.Runtime.InteropServices;
- namespace ModBusTcp;
- public class Modbus_Tcp : IModBus<byte[]?>
- {
- private ModbusTcpClient? _master;
- private IPEndPoint? EndPoint;
- private string? _name;
- private string _ip = string.Empty;
- private ushort _port;
- private ITcpConnectNority? _connect;
- public bool Initialize(string name, ITcpConnectNority tcpConnect)
- {
- if (!string.IsNullOrEmpty(this._name))
- return false;
- this._name = name;
- this._name ??= "Default";
- this._connect = tcpConnect;
- return true;
- }
- public bool Open(string ip, ushort port, bool notify = true)
- {
- if (this._master is not null)
- return false;
- if (!IPAddress.TryParse(ip, out IPAddress? address) || address is null)
- return false;
- try
- {
- IPEndPoint endPoint = new(address, port);
- ModbusTcpClient client = new()
- {
- ReadTimeout = 500,
- ConnectTimeout = 500
- };
- if (notify)
- client.Connect(endPoint);
- this._ip = ip;
- this._port = port;
- this.EndPoint = endPoint;
- this._master = client;
- }
- catch
- {
- return false;
- }
- return true;
- }
- public byte[]? GetBuffer(ushort index, ushort count, byte slaveAddress = 1)
- {
- if (this._master is null)
- return null;
- try
- {
- lock (this)
- {
- Span<byte> bytes = this._master.ReadHoldingRegisters(0x00, index, count);
- if (bytes == null)
- return null;
- return bytes.ToArray();
- }
- }
- catch
- {
- TryReconnect();
- return null;
- }
- }
- public unsafe bool SetFloat(ushort index, float value, byte slaveAddress = 1)
- {
- if (this._master is null)
- return false;
- byte[] bytes = new byte[4];
- float* pSource = &value;
- byte* pByte = (byte*)pSource;
- bytes[0] = pByte[3];
- bytes[1] = pByte[2];
- bytes[2] = pByte[1];
- bytes[3] = pByte[0];
- try
- {
- lock (this)
- this._master.WriteMultipleRegisters(0x00, (int)index, bytes);
- }
- catch
- {
- return false;
- }
- return true;
- }
- public unsafe bool SetValue<T>(ushort index, T value, byte slaveAddress = 1) where T : struct
- {
- if (this._master is null)
- return false;
- int size = Marshal.SizeOf<T>();
- if (size % 4 != 0)
- return false;
- byte[] bytes = new byte[size];
- #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
- T* pSource = &value;
- #pragma warning restore CS8500
- byte* pByte = (byte*)pSource;
- for (int i = 0; i < size; i += 4)
- {
- bytes[i] = pByte[i + 3];
- bytes[i + 1] = pByte[i + 2];
- bytes[i + 2] = pByte[i + 1];
- bytes[i + 3] = pByte[i];
- }
- try
- {
- lock (this)
- this._master.WriteMultipleRegisters(0x00, (int)index, bytes);
- }
- catch
- {
- return false;
- }
- return true;
- }
- public unsafe bool SetUshort(ushort index, ushort value, byte slaveAddress = 1)
- {
- if (this._master is null)
- return false;
- ushort* pUshort = &value;
- byte* pByte = (byte*)pUshort;
- byte[] result = [pByte[1], pByte[0]];
- try
- {
- lock (this)
- this._master.WriteSingleRegister(0x00, index, result);
- }
- catch
- {
- return false;
- }
- return true;
- }
- public bool Close()
- {
- this._master?.Dispose();
- this._master = null;
- this.IsCanceled = true;
- return true;
- }
- private volatile bool IsCanceled = false;
- private readonly Semaphore semaphore = new(1, 1);
- private void TryReconnect()
- {
- if (!semaphore.WaitOne(0))
- return;
- this._master?.Disconnect();
- this._connect?.DisConnect(this._ip, this._port);
- Task.Factory.StartNew(() =>
- {
- IsCanceled = false;
- this._master ??= new()
- {
- ReadTimeout = 500,
- ConnectTimeout = 500
- };
- try
- {
- while (true)
- {
- if (this.IsCanceled)
- return;
- try
- {
- this._master.Connect(EndPoint!);
- break;
- }
- catch
- {
- Thread.Sleep(1000);
- }
- }
- this._connect?.Connect(this._ip, this._port);
- }
- finally
- {
- semaphore.Release();
- }
- });
- }
- }
|