using IPLCConnect; using NModbus; using System.Runtime.CompilerServices; namespace ModbusConnect { [PLCProtocol(PLCProtocol.Modbus)] public sealed class Modbus : IPLCConnect.IPLCConnect { public PLCProtocol Protocol => PLCProtocol.Modbus; private System.Net.Sockets.TcpClient? tcpClient; private IModbusMaster? modbus; private bool isConnected; public bool IsConnected { get => isConnected; set { if (isConnected == value) return; isConnected = value; StatusChanged?.Invoke(this, value); } } public string IP { get; set; } = "127.0.0.1"; public int Port { get; set; } = 502; public byte SlaveID { get; set; } = 1; public event EventHandler StatusChanged; public void Connect() { try { var modbusFactory = new NModbus.ModbusFactory(); tcpClient = new System.Net.Sockets.TcpClient(); var result = tcpClient.ConnectAsync(IP, Port).Wait(500); IsConnected = result; if (!IsConnected) return; modbus = modbusFactory.CreateMaster(tcpClient); IsConnected = true; } catch { IsConnected = false; } } public void DisConnect() { try { tcpClient?.Close(); } catch { } IsConnected = false; } public void Dispose() { DisConnect(); } public void Init(string ip, int port) { IP = ip; Port = port; } public T Read(string addr) where T : unmanaged { if(modbus == null ||tcpClient == null || !tcpClient.Connected) { IsConnected = false; return default; } if (string.IsNullOrEmpty(addr)) return default; ushort startaddr = ushort.Parse(addr); byte addrnum =(byte)Unsafe.SizeOf(); ushort[] data = new ushort[addrnum / 2]; try { if (modbus != null) { data = modbus.ReadHoldingRegisters(SlaveID, (ushort)(startaddr + (addrnum >> 2) - 1), (ushort)(addrnum >> 1)); } } catch { DisConnect(); } return Unsafe.As(ref data[0]); } public void Write(string addr, T value) where T : unmanaged { if (modbus == null) return; if (string.IsNullOrEmpty(addr)) return; ushort address = ushort.Parse(addr); byte bytecount = (byte)Unsafe.SizeOf(); try { ushort[] datas = new ushort[bytecount / 2]; Unsafe.CopyBlock(ref Unsafe.As(ref datas[0]), ref Unsafe.As(ref value), (uint)datas.Length * 2); modbus.WriteMultipleRegisters(SlaveID, (ushort)(address + (bytecount >> 1) - 1 - 1), datas); } catch { DisConnect(); } } public bool ReadBit(string addr, byte bitindex) { if (string.IsNullOrEmpty(addr)) return false; var result = Read(addr); return (result & (1 << bitindex)) != 0; } public void Writebit(string addr, byte bitindex, bool value) { if (string.IsNullOrEmpty(addr)) return; var result = Read(addr); result = (ushort)(value ? result | (1 << bitindex) : result & ~(1 << bitindex)); Write(addr, Unsafe.As(ref result)); } } }