/// <summary> /// 以位为单位,创建数据写入的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="value">原始的bool数组数据</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildWriteBitCoreCommand(string address, bool[] value) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(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> /// 读取指定地址的bool数据对象 /// </summary> /// <param name="address">三菱的地址信息</param> /// <param name="length">数组的长度</param> /// <returns>带有成功标志的结果对象</returns> public OperateResult <bool[]> ReadBool(string address, ushort length) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <bool[]>(analysis)); } if (analysis.Content1.DataType == 0) { return(new OperateResult <bool[]>(StringResources.Language.MelsecCurrentTypeNotSupportedWordOperate)); } if (analysis.Content1.DataCode == MelsecMcDataType.M.DataCode) { return(OperateResult.CreateSuccessResult(mBuffer.GetBytes(analysis.Content2, length).Select(m => m != 0x00).ToArray( ))); } else if (analysis.Content1.DataCode == MelsecMcDataType.X.DataCode) { return(OperateResult.CreateSuccessResult(xBuffer.GetBytes(analysis.Content2, length).Select(m => m != 0x00).ToArray( ))); } else if (analysis.Content1.DataCode == MelsecMcDataType.Y.DataCode) { return(OperateResult.CreateSuccessResult(yBuffer.GetBytes(analysis.Content2, length).Select(m => m != 0x00).ToArray( ))); } else { return(new OperateResult <bool[]>(StringResources.Language.NotSupportedDataType)); } }
/// <summary> /// 从三菱PLC中批量读取位软元件,返回读取结果 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">读取的长度</param> /// <returns>带成功标志的结果数据对象</returns> /// <remarks> /// 地址支持的列表如下: /// <list type="table"> /// <listheader> /// <term>地址名称</term> /// <term>示例</term> /// <term>地址进制</term> /// </listheader> /// <item> /// <term>内部继电器</term> /// <term>M100,M200</term> /// <term>10</term> /// </item> /// <item> /// <term>输入继电器</term> /// <term>X100,X1A0</term> /// <term>16</term> /// </item> /// <item> /// <term>输出继电器</term> /// <term>Y100,Y1A0</term> /// <term>16</term> /// </item> /// <item> /// <term>锁存继电器</term> /// <term>L100,L200</term> /// <term>10</term> /// </item> /// <item> /// <term>报警器</term> /// <term>F100,F200</term> /// <term>10</term> /// </item> /// <item> /// <term>边沿继电器</term> /// <term>V100,V200</term> /// <term>10</term> /// </item> /// <item> /// <term>链接继电器</term> /// <term>B100,B1A0</term> /// <term>16</term> /// </item> /// <item> /// <term>步进继电器</term> /// <term>S100,S200</term> /// <term>10</term> /// </item> /// </list> /// </remarks> /// <example> /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\MelsecAscii.cs" region="ReadBool" title="Bool类型示例" /> /// </example> public OperateResult <bool[]> ReadBool(string address, ushort length) { // 解析地址 OperateResult <MelsecMcDataType, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <bool[]>(analysis)); } // 位读取校验 if (analysis.Content1.DataType == 0x00) { return(new OperateResult <bool[]>(StringResources.Language.MelsecReadBitInfo)); } // 核心交互 var read = Read(address, length); if (!read.IsSuccess) { return(OperateResult.CreateFailedResult <bool[]>(read)); } // 转化bool数组 return(OperateResult.CreateSuccessResult(read.Content.Select(m => m == 0x01).ToArray( ))); }
/// <summary> /// 根据类型地址长度确认需要读取的指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">长度</param> /// <param name="networkNumber">网络号</param> /// <param name="networkStationNumber">网络站号</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildReadCommand(string address, ushort length, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } byte[] _PLCCommand = new byte[21]; _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] = 0x0C; // 请求数据长度 _PLCCommand[8] = 0x00; _PLCCommand[9] = 0x0A; // CPU监视定时器 _PLCCommand[10] = 0x00; _PLCCommand[11] = 0x01; // 批量读取数据命令 _PLCCommand[12] = 0x04; _PLCCommand[13] = analysis.Content1.DataType; // 以点为单位还是字为单位成批读取 _PLCCommand[14] = 0x00; _PLCCommand[15] = (byte)(analysis.Content2 % 256); // 起始地址的地位 _PLCCommand[16] = (byte)(analysis.Content2 / 256); _PLCCommand[17] = 0x00; _PLCCommand[18] = analysis.Content1.DataCode; // 指明读取的数据 _PLCCommand[19] = (byte)(length % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(length / 256); return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 从地址,长度,是否位读取进行创建读取Ascii格式的MC的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="length">读取的长度信息</param> /// <param name="isBit">是否进行了位读取操作</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildAsciiReadMcCoreCommand(string address, ushort length, bool isBit) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(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> /// 从三菱PLC中批量读取位软元件,返回读取结果 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">读取的长度</param> /// <returns>带成功标志的结果数据对象</returns> /// <remarks> /// 地址支持的列表如下: /// <list type="table"> /// <listheader> /// <term>地址名称</term> /// <term>示例</term> /// <term>地址进制</term> /// </listheader> /// <item> /// <term>内部继电器</term> /// <term>M100,M200</term> /// <term>10</term> /// </item> /// <item> /// <term>输入继电器</term> /// <term>X100,X1A0</term> /// <term>16</term> /// </item> /// <item> /// <term>输出继电器</term> /// <term>Y100,Y1A0</term> /// <term>16</term> /// </item> /// <item> /// <term>锁存继电器</term> /// <term>L100,L200</term> /// <term>10</term> /// </item> /// <item> /// <term>报警器</term> /// <term>F100,F200</term> /// <term>10</term> /// </item> /// <item> /// <term>边沿继电器</term> /// <term>V100,V200</term> /// <term>10</term> /// </item> /// <item> /// <term>链接继电器</term> /// <term>B100,B1A0</term> /// <term>16</term> /// </item> /// <item> /// <term>步进继电器</term> /// <term>S100,S200</term> /// <term>10</term> /// </item> /// </list> /// </remarks> /// <example> /// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\Profinet\melsecTest.cs" region="ReadBool" title="Bool类型示例" /> /// </example> public OperateResult <bool[]> ReadBool(string address, ushort length) { // 解析地址 OperateResult <MelsecMcDataType, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <bool[]>(analysis)); } // 位读取校验 if (analysis.Content1.DataType == 0x00) { return new OperateResult <bool[]>( ) { Message = "读取位变量数组只能针对位软元件,如果读取字软元件,请调用Read方法" } } ; // 核心交互 var read = Read(address, length); if (!read.IsSuccess) { return(OperateResult.CreateFailedResult <bool[]>(read)); } // 转化bool数组 return(OperateResult.CreateSuccessResult(read.Content.Select(m => m == 0x01).ToArray())); }
/// <summary> /// 往指定的地址里写入bool数组对象 /// </summary> /// <param name="address">三菱的地址信息</param> /// <param name="value">值</param> /// <returns>是否成功的结果</returns> public OperateResult Write(string address, bool[] value) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <bool[]>(analysis)); } if (analysis.Content1.DataType == 0) { return(new OperateResult <bool[]>(StringResources.Language.MelsecCurrentTypeNotSupportedWordOperate)); } if (analysis.Content1.DataCode == MelsecMcDataType.M.DataCode) { mBuffer.SetBytes(value.Select(m => m ? (byte)1 : (byte)0).ToArray( ), analysis.Content2); return(OperateResult.CreateSuccessResult( )); } else if (analysis.Content1.DataCode == MelsecMcDataType.X.DataCode) { xBuffer.SetBytes(value.Select(m => m ? (byte)1 : (byte)0).ToArray( ), analysis.Content2); return(OperateResult.CreateSuccessResult( )); } else if (analysis.Content1.DataCode == MelsecMcDataType.Y.DataCode) { yBuffer.SetBytes(value.Select(m => m ? (byte)1 : (byte)0).ToArray( ), analysis.Content2); return(OperateResult.CreateSuccessResult( )); } else { return(new OperateResult <bool[]>(StringResources.Language.NotSupportedDataType)); } }
/// <summary> /// 根据类型地址长度确认需要读取的报文 /// </summary> /// <param name="address">起始地址</param> /// <param name="length">长度</param> /// <param name="networkNumber">网络号信息</param> /// <param name="networkStationNumber">网络站号信息</param> /// <returns>带有成功标志的指令数据</returns> public static OperateResult <byte[]> BuildReadCommand(string address, ushort length, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } // 默认信息----注意:高低字节交错 byte[] _PLCCommand = new byte[42]; _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] = 0x30; // 请求数据长度 _PLCCommand[15] = 0x30; _PLCCommand[16] = 0x31; _PLCCommand[17] = 0x38; _PLCCommand[18] = 0x30; // CPU监视定时器 _PLCCommand[19] = 0x30; _PLCCommand[20] = 0x31; _PLCCommand[21] = 0x30; _PLCCommand[22] = 0x30; // 批量读取数据命令 _PLCCommand[23] = 0x34; _PLCCommand[24] = 0x30; _PLCCommand[25] = 0x31; _PLCCommand[26] = 0x30; // 以点为单位还是字为单位成批读取 _PLCCommand[27] = 0x30; _PLCCommand[28] = 0x30; _PLCCommand[29] = analysis.Content1.DataType == 0 ? (byte)0x30 : (byte)0x31; _PLCCommand[30] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 _PLCCommand[31] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; _PLCCommand[32] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 _PLCCommand[33] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; _PLCCommand[34] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; _PLCCommand[35] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; _PLCCommand[36] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; _PLCCommand[37] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; _PLCCommand[38] = MelsecHelper.BuildBytesFromData(length)[0]; // 软元件点数 _PLCCommand[39] = MelsecHelper.BuildBytesFromData(length)[1]; _PLCCommand[40] = MelsecHelper.BuildBytesFromData(length)[2]; _PLCCommand[41] = MelsecHelper.BuildBytesFromData(length)[3]; return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 以字为单位,创建ASCII数据写入的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="value">实际的原始数据信息</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildAsciiWriteWordCoreCommand(string address, byte[] value) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(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> /// 写入自定义的数据到数据内存中去 /// </summary> /// <param name="address">地址</param> /// <param name="value">数据值</param> /// <returns>是否写入成功的结果对象</returns> public override OperateResult Write(string address, byte[] value) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } if (analysis.Content1.DataCode == MelsecMcDataType.M.DataCode) { byte[] buffer = SoftBasic.ByteToBoolArray(value).Select(m => m ? (byte)1 : (byte)0).ToArray( ); mBuffer.SetBytes(buffer, analysis.Content2); return(OperateResult.CreateSuccessResult( )); } else if (analysis.Content1.DataCode == MelsecMcDataType.X.DataCode) { byte[] buffer = SoftBasic.ByteToBoolArray(value).Select(m => m ? (byte)1 : (byte)0).ToArray( ); xBuffer.SetBytes(buffer, analysis.Content2); return(OperateResult.CreateSuccessResult( )); } else if (analysis.Content1.DataCode == MelsecMcDataType.Y.DataCode) { byte[] buffer = SoftBasic.ByteToBoolArray(value).Select(m => m ? (byte)1 : (byte)0).ToArray( ); yBuffer.SetBytes(buffer, analysis.Content2); return(OperateResult.CreateSuccessResult( )); } else if (analysis.Content1.DataCode == MelsecMcDataType.D.DataCode) { dBuffer.SetBytes(value, analysis.Content2 * 2); return(OperateResult.CreateSuccessResult( )); } else if (analysis.Content1.DataCode == MelsecMcDataType.W.DataCode) { wBuffer.SetBytes(value, analysis.Content2 * 2); return(OperateResult.CreateSuccessResult( )); } else { return(new OperateResult <byte[]>(StringResources.Language.NotSupportedDataType)); } }
/// <summary> /// 以位为单位,创建ASCII数据写入的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="value">原始的bool数组数据</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildAsciiWriteBitCoreCommand(string address, bool[] value) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(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]; value.CopyTo(command, 20); return(OperateResult.CreateSuccessResult(command)); }
/// <summary> /// 从地址,长度,是否位读取进行创建读取的MC的核心报文 /// </summary> /// <param name="address">三菱的地址信息,具体格式参照<seealso cref="MelsecMcNet"/> 的注释说明</param> /// <param name="length">读取的长度信息</param> /// <param name="isBit">是否进行了位读取操作</param> /// <returns>带有成功标识的报文对象</returns> public static OperateResult <byte[]> BuildReadMcCoreCommand(string address, ushort length, bool isBit) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } byte[] command = new byte[10]; command[0] = 0x01; // 批量读取数据命令 command[1] = 0x04; command[2] = isBit ? (byte)0x01 : (byte)0x00; // 以点为单位还是字为单位成批读取 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)(length % 256); // 软元件的长度 command[9] = (byte)(length / 256); return(OperateResult.CreateSuccessResult(command)); }
/// <summary> /// 读取自定义的寄存器的值。按照字为单位 /// </summary> /// <param name="address">起始地址,示例:"D100","M100"</param> /// <param name="length">数据长度</param> /// <exception cref="IndexOutOfRangeException"></exception> /// <returns>byte数组值</returns> public override OperateResult <byte[]> Read(string address, ushort length) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } if (analysis.Content1.DataCode == MelsecMcDataType.M.DataCode) { bool[] buffer = mBuffer.GetBytes(analysis.Content2, length * 16).Select(m => m != 0x00).ToArray( ); return(OperateResult.CreateSuccessResult(SoftBasic.BoolArrayToByte(buffer))); } else if (analysis.Content1.DataCode == MelsecMcDataType.X.DataCode) { bool[] buffer = xBuffer.GetBytes(analysis.Content2, length * 16).Select(m => m != 0x00).ToArray( ); return(OperateResult.CreateSuccessResult(SoftBasic.BoolArrayToByte(buffer))); } else if (analysis.Content1.DataCode == MelsecMcDataType.Y.DataCode) { bool[] buffer = yBuffer.GetBytes(analysis.Content2, length * 16).Select(m => m != 0x00).ToArray( ); return(OperateResult.CreateSuccessResult(SoftBasic.BoolArrayToByte(buffer))); } else if (analysis.Content1.DataCode == MelsecMcDataType.D.DataCode) { return(OperateResult.CreateSuccessResult(dBuffer.GetBytes(analysis.Content2 * 2, length * 2))); } else if (analysis.Content1.DataCode == MelsecMcDataType.W.DataCode) { return(OperateResult.CreateSuccessResult(wBuffer.GetBytes(analysis.Content2 * 2, length * 2))); } else { return(new OperateResult <byte[]>(StringResources.Language.NotSupportedDataType)); } }
/// <summary> /// 分析地址的方法,允许派生类里进行重写操作 /// </summary> /// <param name="address">地址信息</param> /// <returns>解析后的数据信息</returns> protected virtual OperateResult <MelsecMcDataType, int> McAnalysisAddress(string address) { return(MelsecHelper.McAnalysisAddress(address)); }
/// <summary> /// 根据类型地址以及需要写入的数据来生成报文 /// </summary> /// <param name="address">起始地址</param> /// <param name="value">写入数据的实际值</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, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } // 预处理指令 if (analysis.Content1.DataType == 0x01) { // 位写入 value = value.Select(m => m == 0x00 ? (byte)0x30 : (byte)0x31).ToArray( ); } else { // 字写入 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[] _PLCCommand = new byte[42 + value.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; _PLCCommand[22] = 0x31; // 批量写入的命令 _PLCCommand[23] = 0x34; _PLCCommand[24] = 0x30; _PLCCommand[25] = 0x31; _PLCCommand[26] = 0x30; // 子命令 _PLCCommand[27] = 0x30; _PLCCommand[28] = 0x30; _PLCCommand[29] = analysis.Content1.DataType == 0 ? (byte)0x30 : (byte)0x31; _PLCCommand[30] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 _PLCCommand[31] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; _PLCCommand[32] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 _PLCCommand[33] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; _PLCCommand[34] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; _PLCCommand[35] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; _PLCCommand[36] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; _PLCCommand[37] = MelsecHelper.BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; // 判断是否进行位操作 if (analysis.Content1.DataType == 1) { _PLCCommand[38] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[0]; // 软元件点数 _PLCCommand[39] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[1]; _PLCCommand[40] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[2]; _PLCCommand[41] = MelsecHelper.BuildBytesFromData((ushort)value.Length)[3]; } else { _PLCCommand[38] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[0]; // 软元件点数 _PLCCommand[39] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[1]; _PLCCommand[40] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[2]; _PLCCommand[41] = MelsecHelper.BuildBytesFromData((ushort)(value.Length / 4))[3]; } Array.Copy(value, 0, _PLCCommand, 42, value.Length); return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <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, ushort> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } int length = -1; if (analysis.Content1.DataType == 1) { // 按照位写入的操作,数据需要重新计算 int length2 = value.Length % 2 == 0 ? value.Length / 2 : value.Length / 2 + 1; byte[] buffer = new byte[length2]; for (int i = 0; i < length2; i++) { if (value[i * 2 + 0] != 0x00) { buffer[i] += 0x10; } if ((i * 2 + 1) < value.Length) { if (value[i * 2 + 1] != 0x00) { buffer[i] += 0x01; } } } length = value.Length; value = buffer; } 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] = (byte)(analysis.Content2 % 256); // 起始地址的地位 _PLCCommand[16] = (byte)(analysis.Content2 / 256); _PLCCommand[17] = 0x00; _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)); }
/// <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)); }