using SharpModbus;
using System;
using System.Collections.Generic;  
using System.Text;

namespace MES.Utility.Network
{
    public class ModbusHelper : IDisposable
    {
        public delegate void OnSendedData(byte[] bytes, string hexString);
        public event OnSendedData OnSended;

        public delegate void OnRecivedData(byte[] bytes, string hexString);
        public event OnRecivedData OnRecived;


        private object _lock = new object();
        private ModbusMaster master;
        private byte slaveId;
        public ModbusHelper(string ip, int port)
        {
            master = ModbusMaster.TCP(ip, port);
            master.OnSended += Master_OnSended; ;
            master.OnRecived += Master_OnRecived; ;
            slaveId = 1;
        }



        public ModbusHelper(string ip, int port, byte slaveId)
        {
            master = ModbusMaster.TCP(ip, port);
            master.OnSended += Master_OnSended;
            master.OnRecived += Master_OnRecived;
            this.slaveId = slaveId;

        }
        public ModbusHelper(SerialSettings setting, int timeout, byte slaveId)
        {
            master = ModbusMaster.RTU(setting, timeout);
            master.OnSended += Master_OnSended;
            master.OnRecived += Master_OnRecived;
            this.slaveId = slaveId;
        }

        #region ushort INT16 操作 

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegisterInt16(int address, out ushort value)
        {
            return ReadHoldRegisterInt16(slaveId, address, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegisterInt16(byte slaveId, int address, out ushort value)
        {
            bool flag = ReadHoldRegistersInt16(slaveId, address, 1, out ushort[] values);
            value = flag ? values[0] : (ushort)0;
            return flag;
        }



        /// <summary>
        /// 读取某个地址连续N个数据
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="count">读取的数量</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegistersInt16(int address, int count, out ushort[] value)
        {
            return ReadHoldRegistersInt16(slaveId, address, count, out value);
        }

        /// <summary>
        /// 读取某个地址连续N个数据
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="address"></param>
        /// <param name="count"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegistersInt16(byte slaveId, int address, int count, out ushort[] value)
        {
            lock (_lock)
                try
                {
                    value = master.ReadHoldingRegisters(slaveId, (ushort)address, (ushort)count);
                    return true;
                }
                catch
                {
                    value = null;
                    return false;
                }
        }


        /// <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">写入的数据</param>
        /// <returns>bool  写入成功还是失败</returns>
        public bool WriteHoldRegisterInt16(int address, ushort value)
        {
            return WriteHoldRegisterInt16(slaveId, address, value);
        }

        /// <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WriteHoldRegisterInt16(byte slaveId, int address, ushort value)
        {
            return WriteHoldRegistersInt16(slaveId, address, new ushort[] { value });
        }

        /// <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WriteHoldRegistersInt16(int address, ushort[] value)
        {
            return WriteHoldRegistersInt16(slaveId, address, value);
        }

        /// <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WriteHoldRegistersInt16(byte slaveId, int address, ushort[] value)
        {
            lock (_lock)
                try
                {
                    master.WriteRegisters(slaveId, (ushort)address, value);
                    return true;
                }
                catch
                {
                    return false;
                }
        }
        #endregion

        #region int INT32 操作
        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegisterInt32(int address, out int value)
        {
            return ReadHoldRegisterInt32(slaveId, address, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegisterInt32(byte slaveId, int address, out int value)
        {
            bool flag = ReadHoldRegistersInt32(slaveId, address, 1, out int[] values);
            value = flag ? values[0] : 0;
            return flag;
        }


        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="count">int32数据的数量，不是地址数</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegistersInt32(int address, int count, out int[] value)
        {
            return ReadHoldRegistersInt32(slaveId, address, count, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="count">int32数据的数量，不是地址数</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegistersInt32(byte slaveId, int address, int count, out int[] value)
        {
            lock (_lock)
                try
                {
                    List<int> valueList = new List<int>();
                    ushort[] values = master.ReadHoldingRegisters(slaveId, (ushort)address, (ushort)(2 * count));
                    for (int i = 0; i < values.Length; i += 2)
                    {
                        valueList.Add(ConvertRegistersToInt(new ushort[] { values[i], values[i + 1] }));
                    }
                    value = valueList.ToArray();
                    return true;
                }
                catch
                {
                    value = null;
                    return false;
                }
        }


        // <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WriteHoldRegisterInt32(int address, int value)
        {
            return WriteHoldRegisterInt32(slaveId, address, value);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns>bool 写入成功还是失败</returns>
        public bool WriteHoldRegisterInt32(byte slaveId, int address, int value)
        {
            return WriteHoldRegistersInt32(slaveId, address, new int[] { value });
        }

        // <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersInt32(int address, int[] values)
        {
            return WriteHoldRegistersInt32(slaveId, address, values);
        }

        /// <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersInt32(byte slaveId, int address, int[] values)
        {
            lock (_lock)
                try
                {
                    List<ushort> list = new List<ushort>();
                    foreach (int value in values)
                    {
                        ushort[] ushortValues = ConvertIntToRegisters(value);
                        list.AddRange(ushortValues);
                    }
                    master.WriteRegisters(slaveId, (ushort)address, list.ToArray());
                    return true;
                }
                catch
                {
                    return false;
                }
        }



        #endregion

        #region long INT64 操作
        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegisterInt64(int address, out long value)
        {
            return ReadHoldRegisterInt64(slaveId, address, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegisterInt64(byte slaveId, int address, out long value)
        {
            bool flag = ReadHoldRegistersInt64(slaveId, address, 1, out long[] values);
            value = flag ? values[0] : 0;
            return flag;
        }


        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="count">int32数据的数量，不是地址数</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegistersInt64(int address, int count, out long[] value)
        {
            return ReadHoldRegistersInt64(slaveId, address, count, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="count">int32数据的数量，不是地址数</param>
        /// <param name="value">传递：数据值</param>
        /// <returns>bool  读取成功还是失败</returns>
        public bool ReadHoldRegistersInt64(byte slaveId, int address, int count, out long[] value)
        {
            lock (_lock)
                try
                {
                    List<long> valueList = new List<long>();
                    ushort[] values = master.ReadHoldingRegisters(slaveId, (ushort)address, (ushort)(4 * count));
                    for (int i = 0; i < values.Length; i += 4)
                    {
                        valueList.Add(ConvertRegistersToLong(new ushort[] { values[i], values[i + 1], values[i + 2], values[i + 3] }));
                    }
                    value = valueList.ToArray();
                    return true;
                }
                catch
                {
                    value = null;
                    return false;
                }
        }


        // <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WriteHoldRegisterInt64(int address, long value)
        {
            return WriteHoldRegisterInt64(slaveId, address, value);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns>bool 写入成功还是失败</returns>
        public bool WriteHoldRegisterInt64(byte slaveId, int address, long value)
        {
            return WriteHoldRegistersInt64(slaveId, address, new long[] { value });
        }

        // <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersInt64(int address, long[] values)
        {
            return WriteHoldRegistersInt64(slaveId, address, values);
        }

        /// <summary>
        /// 写入一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersInt64(byte slaveId, int address, long[] values)
        {
            lock (_lock)
                try
                {
                    List<ushort> list = new List<ushort>();
                    foreach (int value in values)
                    {
                        ushort[] ushortValues = ConvertLongToRegisters(value);
                        list.AddRange(ushortValues);
                    }
                    master.WriteRegisters(slaveId, (ushort)address, list.ToArray());
                    return true;
                }
                catch
                {
                    return false;
                }
        }




        #endregion

        #region Float 32位数据操作
        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool ReadHoldRegisterFloat(int address, out float value)
        {
            return ReadHoldRegisterFloat(slaveId, address, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegisterFloat(byte slaveId, int address, out float value)
        {
            bool flag = ReadHoldRegistersFloat(slaveId, address, 1, out float[] values);
            value = flag ? (float)values[0] : (float)0;
            return flag;
        }


        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="count">float数据的数量，不是地址数</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegistersFloat(int address, int count, out float[] value)
        {
            return ReadHoldRegistersFloat(slaveId, address, count, out value);
        }
        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="count">float数据的数量，不是地址数</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegistersFloat(byte slaveId, int address, int count, out float[] value)
        {
            lock (_lock)
                try
                {
                    List<float> valueList = new List<float>();
                    ushort[] values = master.ReadHoldingRegisters(slaveId, (ushort)address, (ushort)(2 * count));
                    for (int i = 0; i < values.Length; i += 2)
                    {
                        valueList.Add(ConvertRegistersToFloat(values));
                    }
                    value = valueList.ToArray();
                    return true;
                }
                catch
                {
                    value = null;
                    return false;
                }

        }


        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegisterFloat(int address, float value)
        {
            return WriteHoldRegisterFloat(slaveId, address, value);
        }
        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegisterFloat(byte slaveId, int address, float value)
        {
            return WriteHoldRegistersFloat(slaveId, address, new float[] { value });
        }


        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersFloat(int address, float[] values)
        {
            return WriteHoldRegistersFloat(slaveId, address, values);
        }
        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersFloat(byte slaveId, int address, float[] values)
        {
            lock (_lock)
                try
                {
                    List<ushort> list = new List<ushort>();
                    foreach (float value in values)
                    {
                        list.AddRange(ConvertFloatToRegisters(value));
                        //byte[] bytes = BitConverter.GetBytes(value);
                        //ushort value1 = BitConverter.ToUInt16(new byte[] { bytes[0], bytes[1] }, 0);
                        //ushort value2 = BitConverter.ToUInt16(new byte[] { bytes[2], bytes[3] }, 0);
                        //list.Add(value1);
                        //list.Add(value2);
                    }
                    master.WriteRegisters(slaveId, (ushort)address, list.ToArray());
                    return true;
                }
                catch
                {
                    return false;
                }
        }

        #endregion

        #region Double 64位操作
        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool ReadHoldRegisterDouble(int address, out double value)
        {
            return ReadHoldRegisterDouble(slaveId, address, out value);
        }

        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegisterDouble(byte slaveId, int address, out double value)
        {
            bool flag = ReadHoldRegistersDouble(slaveId, address, 1, out double[] values);
            value = flag ? (double)values[0] : (double)0;
            return flag;
        }


        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="count">float数据的数量，不是地址数</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegistersDouble(int address, int count, out double[] value)
        {
            return ReadHoldRegistersDouble(slaveId, address, count, out value);
        }
        /// <summary>
        /// 读取一个地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="count">float数据的数量，不是地址数</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ReadHoldRegistersDouble(byte slaveId, int address, int count, out double[] value)
        {
            lock (_lock)
                try
                {
                    List<double> valueList = new List<double>();
                    ushort[] values = master.ReadHoldingRegisters(slaveId, (ushort)address, (ushort)(4 * count));
                    for (int i = 0; i < values.Length; i += 4)
                    {
                        valueList.Add(ConvertRegistersToDouble(values));
                    }
                    value = valueList.ToArray();
                    return true;
                }
                catch
                {
                    value = null;
                    return false;
                }

        }


        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegisterDouble(int address, double value)
        {
            return WriteHoldRegisterDouble(slaveId, address, value);
        }
        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegisterDouble(byte slaveId, int address, double value)
        {
            return WriteHoldRegistersDouble(slaveId, address, new double[] { value });
        }


        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersDouble(int address, double[] values)
        {
            return WriteHoldRegistersDouble(slaveId, address, values);
        }
        /// <summary>
        /// 写入地址
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool WriteHoldRegistersDouble(byte slaveId, int address, double[] values)
        {
            lock (_lock)
                try
                {
                    List<ushort> list = new List<ushort>();
                    foreach (double value in values)
                    {
                        list.AddRange(ConvertDoubleToRegisters(value));
                    }
                    master.WriteRegisters(slaveId, (ushort)address, list.ToArray());
                    return true;
                }
                catch
                {
                    return false;
                }
        }

        #endregion

        #region 字符串操作

        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str"></param>
        /// <returns></returns>
        public bool ReadHoldRegisterString(int address, int length, out string str)
        {
            return ReadHoldRegisterString(slaveId, address, length, Encoding.ASCII, out str);
        }

        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str"></param>
        /// <returns></returns>
        public bool ReadHoldRegisterString(int address, int length, Encoding encoding, out string str)
        {
            return ReadHoldRegisterString(slaveId, address, length, encoding, out str);
        }

        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str"></param>
        /// <returns></returns>
        public bool ReadHoldRegisterString(byte slaveId, int address, int length, out string str)
        {
            return ReadHoldRegisterString(slaveId, address, length, Encoding.ASCII, out str);
        }



        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str"></param>
        /// <returns></returns>
        public bool ReadHoldRegisterString(byte slaveId, int address, int length, Encoding encoding, out string str)
        {
            lock (_lock)
                try
                {
                    int count = length / 2 + length % 2;
                    ushort[] values = master.ReadHoldingRegisters(slaveId, (ushort)address, (ushort)(count));
                    str = ConvertRegistersToString(values, length, encoding);
                    return true;
                }
                catch
                {
                    str = "";
                    return false;
                }
        }



        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str">字符串内容</param>
        /// <returns></returns>
        public bool WriteHoldRegisterString(int address, int length, string str)
        {
            return WriteHoldRegisterString(slaveId, address, length, str, Encoding.ASCII);
        }

        public bool WriteHoldRegisterString(int address, int length, string str, Encoding encoding)
        {
            return WriteHoldRegisterString(slaveId, address, length, str, encoding);
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str">字符串内容</param>
        /// <returns></returns>
        public bool WriteHoldRegisterString(byte slaveId, int address, int length, string str)
        {
            lock (_lock)
                try
                {
                    ushort[] value = ConvertStringToRegisters(str, length, Encoding.ASCII);
                    master.WriteRegisters(slaveId, (ushort)address, value);
                    return true;
                }
                catch
                {
                    return false;
                }
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="slaveId">从站Id</param>
        /// <param name="address">地址</param>
        /// <param name="length">字符串总长度（不是地址长度，一个地址两个字符）</param>
        /// <param name="str">字符串内容</param>
        /// <returns></returns>
        public bool WriteHoldRegisterString(byte slaveId, int address, int length, string str, Encoding encoding)
        {
            lock (_lock)
                try
                {
                    ushort[] value = ConvertStringToRegisters(str, length, encoding);
                    master.WriteRegisters(slaveId, (ushort)address, value);
                    return true;
                }
                catch
                {
                    return false;
                }
        }

        #endregion

        #region 通用操作,线圈，输入寄存器等操作

        public bool ReadCoil(ushort address, out bool value)
        {
            return ReadCoil(slaveId, address, out value); //there is no code for single read
        }

        public bool ReadCoil(byte slave, ushort address, out bool value)
        {
            bool flag = ReadCoils(slave, address, 1, out bool[] values);
            value = flag ? values[0] : false;
            return flag;
        }
        public bool ReadCoils(ushort address, ushort count, out bool[] values)
        {
            return ReadCoils(slaveId, address, count, out values);
        }
        public bool ReadCoils(byte slave, ushort address, ushort count, out bool[] values)
        {
            lock (_lock)
            {
                try
                {
                    values = master.ReadCoils(slave, address, count);
                    return true;
                }
                catch
                {
                    values = null;
                    return false;
                }
            }
        }

        public bool WriteCoil(ushort address, bool value)
        {
            return WriteCoil(slaveId, address, value);
        }
        public bool WriteCoil(byte slave, ushort address, bool value)
        {
            lock (_lock)
                try
                {
                    master.WriteCoils(slave, address, value);
                    return true;
                }
                catch
                {
                    return false;
                }

        }
        public bool WriteCoils(ushort address, params bool[] values)
        {
            return WriteCoils(slaveId, address, values);
        }
        public bool WriteCoils(byte slave, ushort address, params bool[] values)
        {
            lock (_lock)
            {
                try
                {
                    master.WriteCoils(slave, address, values);
                    return true;
                }
                catch
                {
                    return false;
                }

            }
        }


        public bool ReadInput(ushort address, ushort count, out bool value)
        {
            return ReadInput(slaveId, address, out value);
        }

        public bool ReadInput(byte slave, ushort address, out bool value)
        {
            bool flag = ReadInputs(slave, address, 1, out bool[] values); //there is no code for single read
            value = flag ? values[0] : false;
            return flag;
        }
        public bool ReadInputs(ushort address, ushort count, out bool[] values)
        {
            return ReadInputs(slaveId, address, count, out values);
        }
        public bool ReadInputs(byte slave, ushort address, ushort count, out bool[] values)
        {
            lock (_lock)
            {
                try
                {
                    values = master.ReadInputs(slave, address, count);
                    return true;
                }
                catch
                {
                    values = null;
                    return false;
                }
            }

        }


        public bool ReadInputRegister(ushort address, out ushort value)
        {
            return ReadInputRegister(slaveId, address, out value);
        }
        public bool ReadInputRegister(byte slave, ushort address, out ushort value)
        {
            bool flag = ReadInputRegisters(slave, address, 1, out ushort[] values);
            value = flag ? values[0] : (ushort)0;
            return flag;
        }
        public bool ReadInputRegisters(ushort address, ushort count, out ushort[] values)
        {
            return ReadInputRegisters(slaveId, address, count, out values);
        }
        public bool ReadInputRegisters(byte slave, ushort address, ushort count, out ushort[] values)
        {
            lock (_lock)
            {
                try
                {
                    values = master.ReadInputRegisters(slave, address, count);
                    return true;
                }
                catch
                {
                    values = null;
                    return false;
                }
            }

        }


        public bool ReadHoldingRegister(ushort address, out ushort value)
        {
            return ReadHoldingRegister(slaveId, address, out value);
        }

        public bool ReadHoldingRegister(byte slave, ushort address, out ushort value)
        {
            bool flag = ReadHoldingRegisters(slave, address, 1, out ushort[] values);
            value = flag ? values[0] : (ushort)0;
            return flag;
        }
        public bool ReadHoldingRegisters(ushort address, ushort count, out ushort[] values)
        {
            return ReadHoldingRegisters(slaveId, address, count, out values);
        }

        public bool ReadHoldingRegisters(byte slave, ushort address, ushort count, out ushort[] values)
        {
            lock (_lock)
                try
                {
                    values = master.ReadHoldingRegisters(slave, address, count);
                    return true;
                }
                catch
                {
                    values = null;
                    return false;
                }
        }



        public bool WriteRegister(ushort address, ushort value)
        {
            return WriteRegister(slaveId, address, value);
        }
        public bool WriteRegister(byte slave, ushort address, ushort value)
        {
            lock (_lock)
                try
                {
                    master.WriteRegister(slave, address, value);
                    return true;
                }
                catch
                {
                    return false;
                }
        }


        public bool WriteRegisters(ushort address, params ushort[] values)
        {
            return WriteRegisters(slaveId, address, values);
        }

        public bool WriteRegisters(byte slave, ushort address, params ushort[] values)
        {
            lock (_lock)
                try
                {
                    master.WriteRegisters(slave, address, values);
                    return true;
                }
                catch
                {
                    return false;
                }
        }
        #endregion

        public void Dispose()
        {
            master.OnSended -= Master_OnSended;
            master.OnRecived -= Master_OnRecived;
            master.Dispose();

        }
        #region  数据转换功能 
        #region PLC寄存器与字符串数据转换
        public static string ConvertRegistersToString(ushort[] registers, int stringLength, Encoding encoding)
        {
            byte[] result = new byte[stringLength];
            byte[] registerResult = new byte[2];
            for (int i = 0; i < stringLength / 2; i++)
            {
                registerResult = BitConverter.GetBytes(registers[i]);
                result[i * 2] = registerResult[0];
                result[i * 2 + 1] = registerResult[1];
            }
            return encoding.GetString(result).Trim('\0').Trim();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <param name="count">字符串长度</param>
        /// <returns></returns>
        public static ushort[] ConvertStringToRegisters(string str, int count, Encoding encoding)
        {
            //需要多少地址
            int addressCount = count / 2 + count % 2;
            //这些地址共有多少字节
            byte[] bytesList = new byte[addressCount * 2];
            //将字符串拆成字节数组
            byte[] bytes = encoding.GetBytes(str);
            //依次放入byteList中
            for (int i = 0; i < bytesList.Length; i++)
            {
                //要考虑数组越界的情况
                if (i >= bytes.Length)
                {
                    bytesList[i] = 0x00;
                }
                else
                {
                    bytesList[i] = bytes[i];
                }
            }
            //封装ushort
            List<ushort> shortList = new List<ushort>();
            for (int i = 0; i < bytesList.Length; i += 2)
            {
                //将字节数组转为int存入list
                shortList.Add(BitConverter.ToUInt16(new byte[] { bytesList[i], bytesList[i + 1] }, 0));
            }
            return shortList.ToArray();
        }
        #endregion

        #region PLC寄存器与Double数据转换
        public static double ConvertRegistersToDouble(ushort[] registers)
        {
            if (registers.Length != 4)
                throw new ArgumentException("Input Array length invalid - Array langth must be '4'");
            ushort highRegister = registers[3];
            ushort highLowRegister = registers[2];
            ushort lowHighRegister = registers[1];
            ushort lowRegister = registers[0];
            byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
            byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister);
            byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister);
            byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
            byte[] longBytes = {
                lowRegisterBytes[0],
                lowRegisterBytes[1],
                lowHighRegisterBytes[0],
                lowHighRegisterBytes[1],
                highLowRegisterBytes[0],
                highLowRegisterBytes[1],
                highRegisterBytes[0],
                highRegisterBytes[1]
            };
            return BitConverter.ToDouble(longBytes, 0);
        }
        public static ushort[] ConvertDoubleToRegisters(double doubleValue)
        {
            byte[] doubleBytes = BitConverter.GetBytes(doubleValue);
            byte[] highRegisterBytes = { doubleBytes[6], doubleBytes[7] };
            byte[] highLowRegisterBytes = { doubleBytes[4], doubleBytes[5] };
            byte[] lowHighRegisterBytes = { doubleBytes[2], doubleBytes[3] };
            byte[] lowRegisterBytes = { doubleBytes[0], doubleBytes[1] };
            ushort[] returnValue =
            {
                BitConverter.ToUInt16(lowRegisterBytes,0),
                BitConverter.ToUInt16(lowHighRegisterBytes,0),
                BitConverter.ToUInt16(highLowRegisterBytes,0),
                BitConverter.ToUInt16(highRegisterBytes,0)
            };
            return returnValue;
        }
        #endregion

        #region PLC寄存器与INT64数据转换
        public static float ConvertRegistersToFloat(ushort[] registers)
        {
            if (registers.Length != 2)
                throw new ArgumentException("Input Array length invalid - Array langth must be '2'");
            ushort highRegister = registers[1];
            ushort lowRegister = registers[0];
            byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
            byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
            byte[] floatBytes = {
                lowRegisterBytes[0],
                lowRegisterBytes[1],
                highRegisterBytes[0],
                highRegisterBytes[1]
            };
            return BitConverter.ToSingle(floatBytes, 0);
        }

        public static ushort[] ConvertFloatToRegisters(float floatValue)
        {
            byte[] floatBytes = BitConverter.GetBytes(floatValue);
            byte[] highRegisterBytes = { floatBytes[2], floatBytes[3] };
            byte[] lowRegisterBytes = { floatBytes[0], floatBytes[1] };
            ushort[] returnValue = { BitConverter.ToUInt16(lowRegisterBytes, 0), BitConverter.ToUInt16(highRegisterBytes, 0) };
            return returnValue;
        }
        #endregion

        #region PLC寄存器与INT64数据转换
        public static long ConvertRegistersToLong(ushort[] registers)
        {
            if (registers.Length != 4)
                throw new ArgumentException("Input Array length invalid - Array langth must be '4'");
            ushort highRegister = registers[3];
            ushort highLowRegister = registers[2];
            ushort lowHighRegister = registers[1];
            ushort lowRegister = registers[0];
            byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
            byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister);
            byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister);
            byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
            byte[] longBytes = {
                lowRegisterBytes[0],
                lowRegisterBytes[1],
                lowHighRegisterBytes[0],
                lowHighRegisterBytes[1],
                highLowRegisterBytes[0],
                highLowRegisterBytes[1],
                highRegisterBytes[0],
                highRegisterBytes[1]
            };
            return BitConverter.ToInt64(longBytes, 0);
        }
        public static ushort[] ConvertLongToRegisters(long longValue)
        {
            byte[] longBytes = BitConverter.GetBytes(longValue);
            byte[] highRegisterBytes = { longBytes[6], longBytes[7] };
            byte[] highLowRegisterBytes = { longBytes[4], longBytes[5] };
            byte[] lowHighRegisterBytes = { longBytes[2], longBytes[3] };
            byte[] lowRegisterBytes = { longBytes[0], longBytes[1] };
            ushort[] returnValue =
            {
                BitConverter.ToUInt16(lowRegisterBytes,0),
                BitConverter.ToUInt16(lowHighRegisterBytes,0),
                BitConverter.ToUInt16(highLowRegisterBytes,0),
                BitConverter.ToUInt16(highRegisterBytes,0)
            };
            return returnValue;
        }
        #endregion

        #region PLC寄存器与INT32数据转换
        public static int ConvertRegistersToInt(ushort[] registers)
        {
            if (registers.Length != 2)
                throw new ArgumentException("Input Array length invalid - Array langth must be '2'");
            ushort highRegister = registers[1];
            ushort lowRegister = registers[0];
            byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
            byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
            byte[] doubleBytes = {
                lowRegisterBytes[0],
                lowRegisterBytes[1],
                highRegisterBytes[0],
                highRegisterBytes[1]
            };
            return BitConverter.ToInt32(doubleBytes, 0);
        }

        public static ushort[] ConvertIntToRegisters(int intValue)
        {
            byte[] doubleBytes = BitConverter.GetBytes(intValue);
            byte[] highRegisterBytes = { doubleBytes[2], doubleBytes[3] };
            byte[] lowRegisterBytes = { doubleBytes[0], doubleBytes[1] };
            ushort[] returnValue = { BitConverter.ToUInt16(lowRegisterBytes, 0), BitConverter.ToUInt16(highRegisterBytes, 0) };
            return returnValue;
        }
        #endregion
        #endregion


        private void Master_OnRecived(byte[] bytes, string hexString)
        {
            OnRecived?.Invoke(bytes, hexString);
        }

        private void Master_OnSended(byte[] bytes, string hexString)
        {
            OnSended?.Invoke(bytes, hexString);
        }
    }
}
