/// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="value">实际的数据信息</param>
        /// <returns>带有成功标志的指令数据</returns>
        public static OperateResult <byte[]> BuildWriteWordCommand(string address, byte[] value)
        {
            var addressResult = FxCalculateWordStartAddress(address);

            if (!addressResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(addressResult));
            }

            // 字节数据转换成ASCII格式
            if (value != null)
            {
                value = MelsecHelper.BuildBytesFromData(value);
            }

            ushort startAddress = addressResult.Content;

            byte[] _PLCCommand = new byte[11 + value.Length];
            _PLCCommand[0] = 0x02;                                                                    // STX
            _PLCCommand[1] = 0x31;                                                                    // Read
            _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[0];                        // Offect Address
            _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[1];
            _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[2];
            _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[3];
            _PLCCommand[6] = MelsecHelper.BuildBytesFromData((byte)(value.Length / 2))[0];            // Read Length
            _PLCCommand[7] = MelsecHelper.BuildBytesFromData((byte)(value.Length / 2))[1];
            Array.Copy(value, 0, _PLCCommand, 8, value.Length);
            _PLCCommand[_PLCCommand.Length - 3] = 0x03;                                               // ETX
            MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, _PLCCommand.Length - 2);     // CRC

            return(OperateResult.CreateSuccessResult(_PLCCommand));
        }
        /// <summary>
        /// 根据类型地址长度确认需要读取的指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="length">长度</param>
        /// <returns>带有成功标志的指令数据</returns>
        public static OperateResult <byte[]> BuildReadWordCommand(string address, ushort length)
        {
            var addressResult = FxCalculateWordStartAddress(address);

            if (!addressResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(addressResult));
            }

            length = (ushort)(length * 2);
            ushort startAddress = addressResult.Content;

            byte[] _PLCCommand = new byte[11];
            _PLCCommand[0] = 0x02;                                                    // STX
            _PLCCommand[1] = 0x30;                                                    // Read
            _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[0];        // 偏移地址
            _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[1];
            _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[2];
            _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[3];
            _PLCCommand[6] = MelsecHelper.BuildBytesFromData((byte)length)[0];        // 读取长度
            _PLCCommand[7] = MelsecHelper.BuildBytesFromData((byte)length)[1];
            _PLCCommand[8] = 0x03;                                                    // ETX
            MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, 9);          // CRC

            return(OperateResult.CreateSuccessResult(_PLCCommand));                   // Return
        }
        /// <summary>
        /// 根据类型地址长度确认需要读取的指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="length">bool数组长度</param>
        /// <returns>带有成功标志的指令数据</returns>
        public static OperateResult <byte[], int> BuildReadBoolCommand(string address, ushort length)
        {
            var addressResult = FxCalculateBoolStartAddress(address);

            if (!addressResult.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[], int>(addressResult));
            }

            // 计算下实际需要读取的数据长度
            ushort length2 = (ushort)((addressResult.Content2 + length - 1) / 8 - (addressResult.Content2 / 8) + 1);

            ushort startAddress = addressResult.Content1;

            byte[] _PLCCommand = new byte[11];
            _PLCCommand[0] = 0x02;                                                    // STX
            _PLCCommand[1] = 0x30;                                                    // Read
            _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[0];        // 偏移地址
            _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[1];
            _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[2];
            _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[3];
            _PLCCommand[6] = MelsecHelper.BuildBytesFromData((byte)length2)[0];       // 读取长度
            _PLCCommand[7] = MelsecHelper.BuildBytesFromData((byte)length2)[1];
            _PLCCommand[8] = 0x03;                                                    // ETX
            MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, 9);          // CRC

            return(OperateResult.CreateSuccessResult(_PLCCommand, (int)addressResult.Content3));
        }
        /// <summary>
        /// 将MC协议的核心报文打包成一个可以直接对PLC进行发送的原始报文
        /// </summary>
        /// <param name="mcCore">MC协议的核心报文</param>
        /// <param name="networkNumber">网络号</param>
        /// <param name="networkStationNumber">网络站号</param>
        /// <returns>原始报文信息</returns>
        public static byte[] PackMcCommand(byte[] mcCore, byte networkNumber = 0, byte networkStationNumber = 0)
        {
            byte[] plcCommand = new byte[22 + mcCore.Length];
            plcCommand[0]  = 0x35;                                                                        // 副标题
            plcCommand[1]  = 0x30;
            plcCommand[2]  = 0x30;
            plcCommand[3]  = 0x30;
            plcCommand[4]  = MelsecHelper.BuildBytesFromData(networkNumber)[0];                           // 网络号
            plcCommand[5]  = MelsecHelper.BuildBytesFromData(networkNumber)[1];
            plcCommand[6]  = 0x46;                                                                        // PLC编号
            plcCommand[7]  = 0x46;
            plcCommand[8]  = 0x30;                                                                        // 目标模块IO编号
            plcCommand[9]  = 0x33;
            plcCommand[10] = 0x46;
            plcCommand[11] = 0x46;
            plcCommand[12] = MelsecHelper.BuildBytesFromData(networkStationNumber)[0];                   // 目标模块站号
            plcCommand[13] = MelsecHelper.BuildBytesFromData(networkStationNumber)[1];
            plcCommand[14] = MelsecHelper.BuildBytesFromData((ushort)(plcCommand.Length - 18))[0];       // 请求数据长度
            plcCommand[15] = MelsecHelper.BuildBytesFromData((ushort)(plcCommand.Length - 18))[1];
            plcCommand[16] = MelsecHelper.BuildBytesFromData((ushort)(plcCommand.Length - 18))[2];
            plcCommand[17] = MelsecHelper.BuildBytesFromData((ushort)(plcCommand.Length - 18))[3];
            plcCommand[18] = 0x30;                                                                        // CPU监视定时器
            plcCommand[19] = 0x30;
            plcCommand[20] = 0x31;
            plcCommand[21] = 0x30;
            mcCore.CopyTo(plcCommand, 22);

            return(plcCommand);
        }
        /// <summary>
        /// 从地址,长度,是否位读取进行创建读取Ascii格式的MC的核心报文
        /// </summary>
        /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param>
        /// <param name="length">读取的长度信息</param>
        /// <param name="isBit">是否进行了位读取操作</param>
        /// <param name="analysisAddress">对地址分析的委托方法</param>
        /// <returns>带有成功标识的报文对象</returns>
        public static OperateResult <byte[]> BuildAsciiReadMcCoreCommand(string address, ushort length, bool isBit, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress)
        {
            OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            byte[] command = new byte[20];
            command[0]  = 0x30;                                                               // 批量读取数据命令
            command[1]  = 0x34;
            command[2]  = 0x30;
            command[3]  = 0x31;
            command[4]  = 0x30;                                                               // 以点为单位还是字为单位成批读取
            command[5]  = 0x30;
            command[6]  = 0x30;
            command[7]  = isBit ? (byte)0x31 : (byte)0x30;
            command[8]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0];                     // 软元件类型
            command[9]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1];
            command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位
            command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1];
            command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2];
            command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3];
            command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4];
            command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5];
            command[16] = MelsecHelper.BuildBytesFromData(length)[0];                                               // 软元件点数
            command[17] = MelsecHelper.BuildBytesFromData(length)[1];
            command[18] = MelsecHelper.BuildBytesFromData(length)[2];
            command[19] = MelsecHelper.BuildBytesFromData(length)[3];

            return(OperateResult.CreateSuccessResult(command));
        }
        /// <summary>
        /// 以字为单位,创建ASCII数据写入的核心报文
        /// </summary>
        /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param>
        /// <param name="value">实际的原始数据信息</param>
        /// <param name="analysisAddress">对地址分析的委托方法</param>
        /// <returns>带有成功标识的报文对象</returns>
        public static OperateResult <byte[]> BuildAsciiWriteWordCoreCommand(string address, byte[] value, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress)
        {
            OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            if (value == null)
            {
                value = new byte[0];
            }
            byte[] buffer = new byte[value.Length * 2];
            for (int i = 0; i < value.Length / 2; i++)
            {
                MelsecHelper.BuildBytesFromData(BitConverter.ToUInt16(value, i * 2)).CopyTo(buffer, 4 * i);
            }
            value = buffer;

            byte[] command = new byte[20 + value.Length];
            command[0]  = 0x31;                                                                              // 批量写入的命令
            command[1]  = 0x34;
            command[2]  = 0x30;
            command[3]  = 0x31;
            command[4]  = 0x30;                                                                              // 子命令
            command[5]  = 0x30;
            command[6]  = 0x30;
            command[7]  = 0x30;
            command[8]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0];                           // 软元件类型
            command[9]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1];
            command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0];       // 起始地址的地位
            command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1];
            command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2];
            command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3];
            command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4];
            command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5];
            command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[0];                // 软元件点数
            command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[1];
            command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[2];
            command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[3];
            value.CopyTo(command, 20);

            return(OperateResult.CreateSuccessResult(command));
        }
        /// <summary>
        /// 以位为单位,创建ASCII数据写入的核心报文
        /// </summary>
        /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param>
        /// <param name="value">原始的bool数组数据</param>
        /// <param name="analysisAddress">对地址分析的委托方法</param>
        /// <returns>带有成功标识的报文对象</returns>
        public static OperateResult <byte[]> BuildAsciiWriteBitCoreCommand(string address, bool[] value, Func <string, OperateResult <MelsecMcDataType, int> > analysisAddress)
        {
            OperateResult <MelsecMcDataType, int> analysis = analysisAddress(address);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            if (value == null)
            {
                value = new bool[0];
            }
            byte[] buffer = value.Select(m => m ? (byte)0x31 : (byte)0x30).ToArray( );

            byte[] command = new byte[20 + buffer.Length];
            command[0]  = 0x31;                                                                             // 批量写入的命令
            command[1]  = 0x34;
            command[2]  = 0x30;
            command[3]  = 0x31;
            command[4]  = 0x30;                                                                             // 子命令
            command[5]  = 0x30;
            command[6]  = 0x30;
            command[7]  = 0x31;
            command[8]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0];                          // 软元件类型
            command[9]  = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1];
            command[10] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0];      // 起始地址的地位
            command[11] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1];
            command[12] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2];
            command[13] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3];
            command[14] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4];
            command[15] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5];
            command[16] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[0];                // 软元件点数
            command[17] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[1];
            command[18] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[2];
            command[19] = MelsecHelper.BuildBytesFromData((ushort)(value.Length))[3];
            buffer.CopyTo(command, 20);

            return(OperateResult.CreateSuccessResult(command));
        }
        /// <summary>
        /// 生成位写入的数据报文信息,该报文可直接用于发送串口给PLC
        /// </summary>
        /// <param name="address">地址信息,每个地址存在一定的范围,需要谨慎传入数据。举例:M10,S10,X5,Y10,C10,T10</param>
        /// <param name="value"><c>True</c>或是<c>False</c></param>
        /// <returns>带报文信息的结果对象</returns>
        public static OperateResult <byte[]> BuildWriteBoolPacket(string address, bool value)
        {
            var analysis = FxAnalysisAddress(address);

            if (!analysis.IsSuccess)
            {
                return(OperateResult.CreateFailedResult <byte[]>(analysis));
            }

            // 二次运算起始地址偏移量,根据类型的不同,地址的计算方式不同
            ushort startAddress = analysis.Content2;

            if (analysis.Content1 == MelsecMcDataType.M)
            {
                if (startAddress >= 8000)
                {
                    startAddress = (ushort)(startAddress - 8000 + 0x0F00);
                }
                else
                {
                    startAddress = (ushort)(startAddress + 0x0800);
                }
            }
            else if (analysis.Content1 == MelsecMcDataType.S)
            {
                startAddress = (ushort)(startAddress + 0x0000);
            }
            else if (analysis.Content1 == MelsecMcDataType.X)
            {
                startAddress = (ushort)(startAddress + 0x0400);
            }
            else if (analysis.Content1 == MelsecMcDataType.Y)
            {
                startAddress = (ushort)(startAddress + 0x0500);
            }
            else if (analysis.Content1 == MelsecMcDataType.CS)
            {
                startAddress += (ushort)(startAddress + 0x01C0);
            }
            else if (analysis.Content1 == MelsecMcDataType.CC)
            {
                startAddress += (ushort)(startAddress + 0x03C0);
            }
            else if (analysis.Content1 == MelsecMcDataType.CN)
            {
                startAddress += (ushort)(startAddress + 0x0E00);
            }
            else if (analysis.Content1 == MelsecMcDataType.TS)
            {
                startAddress += (ushort)(startAddress + 0x00C0);
            }
            else if (analysis.Content1 == MelsecMcDataType.TC)
            {
                startAddress += (ushort)(startAddress + 0x02C0);
            }
            else if (analysis.Content1 == MelsecMcDataType.TN)
            {
                startAddress += (ushort)(startAddress + 0x0600);
            }
            else
            {
                return(new OperateResult <byte[]>(StringResources.Language.MelsecCurrentTypeNotSupportedBitOperate));
            }


            byte[] _PLCCommand = new byte[9];
            _PLCCommand[0] = 0x02;                                                       // STX
            _PLCCommand[1] = value ? (byte)0x37 : (byte)0x38;                            // Read
            _PLCCommand[2] = MelsecHelper.BuildBytesFromData(startAddress)[2];           // 偏移地址
            _PLCCommand[3] = MelsecHelper.BuildBytesFromData(startAddress)[3];
            _PLCCommand[4] = MelsecHelper.BuildBytesFromData(startAddress)[0];
            _PLCCommand[5] = MelsecHelper.BuildBytesFromData(startAddress)[1];
            _PLCCommand[6] = 0x03;                                                       // ETX
            MelsecHelper.FxCalculateCRC(_PLCCommand).CopyTo(_PLCCommand, 7);             // CRC

            return(OperateResult.CreateSuccessResult(_PLCCommand));
        }