Esempio n. 1
0
        /// <summary>
        /// 以位为单位,创建数据写入的核心报文
        /// </summary>
        /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param>
        /// <param name="value">原始的bool数组数据</param>
        /// <param name="analysisAddress">对地址分析的委托方法</param>
        /// <returns>带有成功标识的报文对象</returns>
        public static OperateResult <byte[]> BuildWriteBitCoreCommand(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  = MelsecHelper.TransBoolArrayToByteData(value);
            byte[] command = new byte[10 + buffer.Length];
            command[0] = 0x01;                                                        // 批量写入数据命令
            command[1] = 0x14;
            command[2] = 0x01;                                                        // 以位为单位成批写入
            command[3] = 0x00;
            command[4] = BitConverter.GetBytes(analysis.Content2)[0];                 // 起始地址的地位
            command[5] = BitConverter.GetBytes(analysis.Content2)[1];
            command[6] = BitConverter.GetBytes(analysis.Content2)[2];
            command[7] = analysis.Content1.DataCode;                                  // 指明写入的数据
            command[8] = (byte)(value.Length % 256);                                  // 软元件长度的地位
            command[9] = (byte)(value.Length / 256);
            buffer.CopyTo(command, 10);

            return(OperateResult.CreateSuccessResult(command));
        }
        /// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="value">数据值</param>
        /// <param name="plcNumber">PLC编号</param>
        /// <returns>带有成功标志的指令数据</returns>
        public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte plcNumber)
        {
            var analysis = MelsecHelper.McA1EAnalysisAddress(address);

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

            int length = -1;

            if (analysis.Content1.DataType == 1)
            {
                // 按照位写入的操作,数据需要重新计算
                length = value.Length;
                value  = MelsecHelper.TransBoolArrayToByteData(value);
            }

            // 默认信息----注意:高低字节交错
            byte subtitle = analysis.Content1.DataType == 0x01 ? (byte)0x02 : (byte)0x03;

            byte[] _PLCCommand = new byte[12 + value.Length];
            _PLCCommand[0]  = subtitle;                              // 副标题
            _PLCCommand[1]  = plcNumber;                             // PLC号
            _PLCCommand[2]  = 0x0A;                                  // CPU监视定时器(L)这里设置为0x00,0x0A,等待CPU返回的时间为10*250ms=2.5秒
            _PLCCommand[3]  = 0x00;                                  // CPU监视定时器(H)
            _PLCCommand[4]  = (byte)(analysis.Content2 % 256);       // 起始软元件(开始读取的地址)
            _PLCCommand[5]  = (byte)(analysis.Content2 / 256);
            _PLCCommand[6]  = 0x00;
            _PLCCommand[7]  = 0x00;
            _PLCCommand[8]  = analysis.Content1.DataCode[1];         // 软元件代码(L)
            _PLCCommand[9]  = analysis.Content1.DataCode[0];         // 软元件代码(H)
            _PLCCommand[10] = (byte)(length % 256);                  // 软元件点数
            _PLCCommand[11] = 0x00;

            // 判断是否进行位操作
            if (analysis.Content1.DataType == 0x01)
            {
                if (length > 0)
                {
                    _PLCCommand[10] = (byte)(length % 256);                       // 软元件点数
                }
                else
                {
                    _PLCCommand[10] = (byte)(value.Length * 2 % 256);             // 软元件点数
                }
            }
            else
            {
                _PLCCommand[10] = (byte)(value.Length / 2 % 256);                 // 软元件点数
            }

            Array.Copy(value, 0, _PLCCommand, 12, value.Length);                  // 将具体的要写入的数据附加到写入命令后面

            return(OperateResult.CreateSuccessResult(_PLCCommand));
        }
Esempio n. 3
0
        /// <summary>
        /// 向PLC写入数据,数据格式为原始的字节类型
        /// </summary>
        /// <param name="address">初始地址</param>
        /// <param name="value">原始的字节数据</param>
        /// <returns>返回写入结果</returns>
        public override OperateResult Write(string address, byte[] value)
        {
            // 地址解析
            var analysis = AnalysisAddress(address);

            if (!analysis.IsSuccess)
            {
                return(analysis);
            }

            OperateResult <MelsecA1EDataType, byte[]> command;

            // 预处理指令
            if (analysis.Content1.DataType == 0x01)
            {
                // 位写入
                command = BuildWriteCommand(address, MelsecHelper.TransBoolArrayToByteData(value), value.Length);
            }
            else
            {
                // 字写入
                command = BuildWriteCommand(address, value);
            }

            if (!command.IsSuccess)
            {
                return(command);
            }

            OperateResult <byte[]> read = ReadFromCoreServer(command.Content2);

            if (!read.IsSuccess)
            {
                return(read);
            }

            if (read.Content[1] == 0)
            {
                return(OperateResult.CreateSuccessResult( ));
            }
            else
            {
                // 在A兼容1E协议中,结束代码后面紧跟的是异常信息的代码}
                return(new OperateResult(read.Content[1], StringResources.Language.MelsecPleaseReferToManulDocument));
            }
        }
        /// <summary>
        /// 以位为单位,创建数据写入的核心报文
        /// </summary>
        /// <param name="addressData">三菱Mc协议的数据地址</param>
        /// <param name="value">原始的bool数组数据</param>
        /// <returns>带有成功标识的报文对象</returns>
        public static byte[] BuildWriteBitCoreCommand(McAddressData addressData, bool[] value)
        {
            if (value == null)
            {
                value = new bool[0];
            }
            byte[] buffer  = MelsecHelper.TransBoolArrayToByteData(value);
            byte[] command = new byte[10 + buffer.Length];
            command[0] = 0x01;                                                        // 批量写入数据命令
            command[1] = 0x14;
            command[2] = 0x01;                                                        // 以位为单位成批写入
            command[3] = 0x00;
            command[4] = BitConverter.GetBytes(addressData.AddressStart)[0];          // 起始地址的地位
            command[5] = BitConverter.GetBytes(addressData.AddressStart)[1];
            command[6] = BitConverter.GetBytes(addressData.AddressStart)[2];
            command[7] = addressData.McDataType.DataCode;                             // 指明写入的数据
            command[8] = (byte)(value.Length % 256);                                  // 软元件长度的地位
            command[9] = (byte)(value.Length / 256);
            buffer.CopyTo(command, 10);

            return(command);
        }
Esempio n. 5
0
        private byte[] ReadByCommand(byte[] command)
        {
            if (command[2] == 0x01)
            {
                // 位读取
                ushort length     = ByteTransform.TransUInt16(command, 8);
                int    startIndex = (command[6] * 65536 + command[5] * 256 + command[4]);

                if (command[7] == MelsecMcDataType.M.DataCode)
                {
                    byte[] buffer = mBuffer.GetBytes(startIndex, length);
                    return(MelsecHelper.TransBoolArrayToByteData(buffer));
                }
                else if (command[7] == MelsecMcDataType.X.DataCode)
                {
                    byte[] buffer = xBuffer.GetBytes(startIndex, length);
                    return(MelsecHelper.TransBoolArrayToByteData(buffer));
                }
                else if (command[7] == MelsecMcDataType.Y.DataCode)
                {
                    byte[] buffer = yBuffer.GetBytes(startIndex, length);
                    return(MelsecHelper.TransBoolArrayToByteData(buffer));
                }
                else
                {
                    throw new Exception(StringResources.Language.NotSupportedDataType);
                }
            }
            else
            {
                // 字读取
                ushort length     = ByteTransform.TransUInt16(command, 8);
                int    startIndex = (command[6] * 65536 + command[5] * 256 + command[4]);
                if (command[7] == MelsecMcDataType.M.DataCode)
                {
                    bool[] buffer = mBuffer.GetBytes(startIndex, length * 16).Select(m => m != 0x00).ToArray( );
                    return(SoftBasic.BoolArrayToByte(buffer));
                }
                else if (command[7] == MelsecMcDataType.X.DataCode)
                {
                    bool[] buffer = xBuffer.GetBytes(startIndex, length * 16).Select(m => m != 0x00).ToArray( );
                    return(SoftBasic.BoolArrayToByte(buffer));
                }
                else if (command[7] == MelsecMcDataType.Y.DataCode)
                {
                    bool[] buffer = yBuffer.GetBytes(startIndex, length * 16).Select(m => m != 0x00).ToArray( );
                    return(SoftBasic.BoolArrayToByte(buffer));
                }
                else if (command[7] == MelsecMcDataType.D.DataCode)
                {
                    return(dBuffer.GetBytes(startIndex * 2, length * 2));
                }
                else if (command[7] == MelsecMcDataType.W.DataCode)
                {
                    return(wBuffer.GetBytes(startIndex * 2, length * 2));
                }
                else
                {
                    throw new Exception(StringResources.Language.NotSupportedDataType);
                }
            }
        }
        /// <summary>
        /// 根据类型地址以及需要写入的数据来生成指令头
        /// </summary>
        /// <param name="address">起始地址</param>
        /// <param name="value">数据值,对于写入位地址来说,应该传入{0x01,0x00,0x01} 通断通这样的数组</param>
        /// <param name="networkNumber">网络号</param>
        /// <param name="networkStationNumber">网络站号</param>
        /// <returns>解析后的指令</returns>
        public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte networkNumber = 0, byte networkStationNumber = 0)
        {
            OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address);

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

            int length = -1;

            if (analysis.Content1.DataType == 1)
            {
                // 按照位写入的操作,数据需要重新计算
                length = value.Length;
                value  = MelsecHelper.TransBoolArrayToByteData(value);
            }

            byte[] _PLCCommand = new byte[21 + value.Length];
            _PLCCommand[0]  = 0x50;                                          // 副标题
            _PLCCommand[1]  = 0x00;
            _PLCCommand[2]  = networkNumber;                                 // 网络号
            _PLCCommand[3]  = 0xFF;                                          // PLC编号
            _PLCCommand[4]  = 0xFF;                                          // 目标模块IO编号
            _PLCCommand[5]  = 0x03;
            _PLCCommand[6]  = networkStationNumber;                          // 目标模块站号
            _PLCCommand[7]  = (byte)((_PLCCommand.Length - 9) % 256);        // 请求数据长度
            _PLCCommand[8]  = (byte)((_PLCCommand.Length - 9) / 256);
            _PLCCommand[9]  = 0x0A;                                          // CPU监视定时器
            _PLCCommand[10] = 0x00;
            _PLCCommand[11] = 0x01;                                          // 批量读取数据命令
            _PLCCommand[12] = 0x14;
            _PLCCommand[13] = analysis.Content1.DataType;                    // 以点为单位还是字为单位成批读取
            _PLCCommand[14] = 0x00;
            _PLCCommand[15] = BitConverter.GetBytes(analysis.Content2)[0];   // 起始地址的地位
            _PLCCommand[16] = BitConverter.GetBytes(analysis.Content2)[1];
            _PLCCommand[17] = BitConverter.GetBytes(analysis.Content2)[2];
            _PLCCommand[18] = analysis.Content1.DataCode;                    // 指明写入的数据

            // 判断是否进行位操作
            if (analysis.Content1.DataType == 1)
            {
                if (length > 0)
                {
                    _PLCCommand[19] = (byte)(length % 256);                  // 软元件长度的地位
                    _PLCCommand[20] = (byte)(length / 256);
                }
                else
                {
                    _PLCCommand[19] = (byte)(value.Length * 2 % 256);        // 软元件长度的地位
                    _PLCCommand[20] = (byte)(value.Length * 2 / 256);
                }
            }
            else
            {
                _PLCCommand[19] = (byte)(value.Length / 2 % 256);            // 软元件长度的地位
                _PLCCommand[20] = (byte)(value.Length / 2 / 256);
            }
            Array.Copy(value, 0, _PLCCommand, 21, value.Length);

            return(OperateResult.CreateSuccessResult(_PLCCommand));
        }