using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace GcDevicePc.Common
{
    class GCModbus485
    {
        [DllImport(@"LibModbus.dll", EntryPoint = "fnLibModbus485", CharSet = CharSet.Unicode)]
        private static extern int fnLibModbus485(byte ucPort, int ulBaudRate, int timeout, ref UInt32 handle);

        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadCoilStatus")]
        private static extern int fnReadCoilStatus(UInt32 handle, byte slaveaddress, UInt16 address, UInt16 num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] dest, [MarshalAs(UnmanagedType.LPTStr)] string ip, UInt16 wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadInputStatus")]
        private static extern int fnReadInputStatus(UInt32 handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] dest, [MarshalAs(UnmanagedType.LPTStr)] string ipp, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadHoldingReg")]
        private static extern int fnReadHoldingReg(UInt32 handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] UInt16[] dest, [MarshalAs(UnmanagedType.LPTStr)] string ipp, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadInputReg")]
        private static extern int fnReadInputReg(UInt32 handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] UInt16[] dest, [MarshalAs(UnmanagedType.LPTStr)] string ipp, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteSingleCoil")]
        private static extern int fnWriteSingleCoil(UInt32 handle, byte slaveaddress, ushort address, ushort state, [MarshalAs(UnmanagedType.LPTStr)] string ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteHoldingReg")]
        private static extern int fnWriteHoldingReg(UInt32 handle, byte slaveaddress, ushort address, ushort state, [MarshalAs(UnmanagedType.LPTStr)] string ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteMultipleCoils")]
        private static extern int fnWriteMultipleCoils(UInt32 handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] src, [MarshalAs(UnmanagedType.LPTStr)] string ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteMultipleRegs")]
        private static extern int fnWriteMultipleRegs(UInt32 handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] UInt16[] src, [MarshalAs(UnmanagedType.LPTStr)] string ipp, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReportSlaveID")]
        private static extern int fnReportSlaveID(UInt32 handle, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] src, [MarshalAs(UnmanagedType.LPTStr)] string ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnMaskWriteReg")]
        private static extern int fnMaskWriteReg(UInt32 handle, byte slaveaddress, ushort address, ushort amask, ushort omask, [MarshalAs(UnmanagedType.LPTStr)] string ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadWriteMultipleRegs")]
        private static extern int fnReadWriteMultipleRegs(UInt32 handle, byte slaveaddress, ushort waddress, ushort wnum, ushort raddress, ushort rnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] UInt16[] dest, [MarshalAs(UnmanagedType.LPTStr)] string ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnLibModbusClose")]
        private static extern void fnLibModbusClose(UInt32 handle);

        private UInt32 hModbusHandle;

        private byte Port = 1;
        private int BaudRate = 9600;
        private int timeout = 2000;
        private string ip = "";
        private ushort wport = 502;

        public GCModbus485(byte uPort, int uBaudRate, int utimeout)
        {
            this.Port = uPort;
            this.BaudRate = uBaudRate;
            this.timeout = utimeout;
        }

        public int ModbusOpen()
        {
            int ret = 0;
            try
            {
                ret = fnLibModbus485(Port, BaudRate, timeout, ref hModbusHandle);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            return ret;
        }

        public int ModbusClose()
        {
            try
            {
                fnLibModbusClose(hModbusHandle);
                hModbusHandle = 0;
                return 0;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return -1;
            }
        }

        ~GCModbus485()
        {
            this.Port = 1;
            this.BaudRate = 9600;
            this.timeout = 2000;
        }

        public int ReadCoilStatus(byte slaveaddress, ushort addr, ushort num, ref byte[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnReadCoilStatus(hModbusHandle, slaveaddress, (ushort)(addr - 1), num, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }
            return ret;

        }

        public int ReadInputStatus(byte slaveaddress, ushort addr, ushort num, ref byte[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnReadInputStatus(hModbusHandle, slaveaddress, addr, num, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }

            return ret;
        }

        public int ReadHoldingReg(byte slaveaddress, ushort addr, ushort num, ref UInt16[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnReadHoldingReg(hModbusHandle, slaveaddress, (ushort)(addr - 1), num, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }
            return ret;
        }

        public int ReadInputReg(byte slaveaddress, ushort addr, ushort num, ref UInt16[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnReadInputReg(hModbusHandle, slaveaddress, addr, num, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }

            return ret;
        }

        public int WriteSingleCoil(byte slaveaddress, ushort addr, ushort state)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnWriteSingleCoil(hModbusHandle, slaveaddress, (ushort)(addr - 1), state, ip, wport);
            }
            catch
            {
                ret = -1;
            }

            return ret;
        }

        public int WriteHoldingReg(byte slaveaddress, ushort addr, ushort state)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnWriteHoldingReg(hModbusHandle, slaveaddress, (ushort)(addr - 1), state, ip, wport);
            }
            catch
            {
                ret = -1;
            }

            return ret;
        }

        public int WriteMultipleRegs(byte slaveaddress, ushort addr, ushort num, ref ushort[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnWriteMultipleRegs(hModbusHandle, slaveaddress, (ushort)(addr - 1), num, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }

            return ret;
        }

        public int ReportSlaveID(ref byte[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnReportSlaveID(hModbusHandle, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }
            return ret;
        }

        public int MaskWriteReg(byte slaveaddress, ushort addr, ushort amask, ushort omask)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnMaskWriteReg(hModbusHandle, slaveaddress, addr, amask, omask, ip, wport);
            }
            catch
            {
                ret = -1;
            }
            return ret;
        }

        public int ReadWriteMultipleRegs(byte slaveaddress, ushort waddr, ushort wnum, ushort raddr, ushort rnum, ref UInt16[] buf)
        {
            int ret = 0;
            try
            {
                if (hModbusHandle != 0)
                    ret = fnReadWriteMultipleRegs(hModbusHandle, slaveaddress, waddr, wnum, raddr, rnum, buf, ip, wport);
            }
            catch
            {
                ret = -1;
            }
            return ret;
        }
    }
}
