/// <summary> /// Read Segment Data Array form plc, use address tag name /// </summary> /// <param name="address">Tag name in plc</param> /// <param name="startIndex">array start index</param> /// <param name="length">array length</param> /// <returns>Results Bytes</returns> public OperateResult <byte[]> ReadSegment(string address, int startIndex, int length) { try { List <byte> bytesContent = new List <byte>( ); ushort alreadyFinished = 0; while (alreadyFinished < length) { ushort readLength = (ushort)Math.Min(length - alreadyFinished, 100); OperateResult <byte[]> read = ReadByCips(AllenBradleyHelper.PackRequestReadSegment(address, startIndex + alreadyFinished, readLength)); if (!read.IsSuccess) { return(read); } bytesContent.AddRange(read.Content); alreadyFinished += readLength; } return(OperateResult.CreateSuccessResult(bytesContent.ToArray( ))); } catch (Exception ex) { return(new OperateResult <byte[]>("Address Wrong:" + ex.Message)); } }
/// <summary> /// 使用指定的类型写入指定的节点数据 -> Writes the specified node data with the specified type /// </summary> /// <param name="address">节点的名称 -> Name of the node </param> /// <param name="typeCode">类型代码,详细参见<see cref="AllenBradleyHelper"/>上的常用字段 -> Type code, see the commonly used Fields section on the <see cref= "AllenBradleyHelper"/> in detail</param> /// <param name="value">实际的数据值 -> The actual data value </param> /// <param name="length">如果节点是数组,就是数组长度 -> If the node is an array, it is the array length </param> /// <returns>是否写入成功 -> Whether to write successfully</returns> public OperateResult WriteTag(string address, ushort typeCode, byte[] value, int length = 1) { OperateResult <byte[]> command = BuildWriteCommand(address, typeCode, value, length); if (!command.IsSuccess) { return(command); } OperateResult <byte[]> read = ReadFromCoreServer(command.Content); if (!read.IsSuccess) { return(read); } OperateResult check = CheckResponse(read.Content); if (!check.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(check)); } return(AllenBradleyHelper.ExtractActualData(read.Content, false)); }
/// <summary> /// 创建一个读取的报文指令 /// </summary> /// <param name="address">tag名的地址</param> /// <returns>包含结果对象的报文信息</returns> public OperateResult <byte[]> BuildReadCommand(string address) { byte tmp = (byte)((address.Length + 1) / 2 + 1); // UCMM 请求 byte[] buff = new byte[] { 0x00, 0x00, 0x00, 0x00, // 接口句柄,默认CIP 0x01, 0x00, // 超时 0x02, 0x00, // 项目数量 0xA1, 0x00, // 基于连接的地址项(用户连接的消息) 0x04, 0x00, // 接下来的连接标识符的数据长度 0x00, 0x00, 0x00, 0x00, // 和打开应答帧中的O-T网络连接号相同,偏移量36 0xB1, 0x00, // 封装连接的传输数据包的数据项 0x31, 0x01, // 后面数据包的长度,48个字节 ======= [需要修改] 0x00, 0x01, // 序号,从1开始 0x0A, // 服务 0x02, // 请求路径大小 0x01, 0x24, 0x02, 0x20, // 请求路径,有可能会改变 0x00, 0x01, // 请求数据点的个数 0x00, 0x01, // 从服务数第一个字节算起,每个服务的偏移量 0x4C, // 服务标识 tmp, // 请求路径大小 0x91, // 扩展符号 0x01, // 数据大小,该服务所对应的PLC中的测点名大小 0x01, 0x02, // 数据内容,该服务所对应的PLC中的测点名 0x00, 0x01, // 服务命令指定数据 }; return(OperateResult.CreateSuccessResult(AllenBradleyHelper.PackRequestHeader(0x65, SessionHandle, buff))); }
/// <summary> /// 批量读取数据信息,数据长度为读取的数组长度信息 -> Bulk read data information, data length for read array length information /// </summary> /// <param name="address">节点的名称 -> Name of the node </param> /// <param name="length">如果是数组,就为数组长度 -> In the case of arrays, the length of the array </param> /// <returns>带有结果对象的结果数据 -> Result data with result object </returns> public OperateResult <byte[]> Read(string[] address, int[] length) { // 指令生成 -> Instruction Generation OperateResult <byte[]> command = BuildReadCommand(address, length); if (!command.IsSuccess) { return(command); } // 核心交互 -> Core Interactions OperateResult <byte[]> read = ReadFromCoreServer(command.Content); if (!read.IsSuccess) { return(read); } // 检查反馈 -> Check Feedback OperateResult check = CheckResponse(read.Content); if (!check.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(check)); } // 提取数据 -> Extracting data return(AllenBradleyHelper.ExtractActualData(read.Content, true)); }
/// <summary> /// Build a read command bytes /// </summary> /// <param name="address">the address of the tag name</param> /// <param name="length">Array information, if not arrays, is 1 </param> /// <returns>Message information that contains the result object </returns> public OperateResult <byte[]> BuildReadCommand(string[] address, int[] length) { if (address == null || length == null) { return(new OperateResult <byte[]>("address or length is null")); } if (address.Length != length.Length) { return(new OperateResult <byte[]>("address and length is not same array")); } try { List <byte[]> cips = new List <byte[]>( ); for (int i = 0; i < address.Length; i++) { cips.Add(AllenBradleyHelper.PackRequsetRead(address[i], length[i])); } byte[] commandSpecificData = AllenBradleyHelper.PackCommandSpecificData(Slot, cips.ToArray( )); return(OperateResult.CreateSuccessResult(AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, commandSpecificData))); } catch (Exception ex) { return(new OperateResult <byte[]>("Address Wrong:" + ex.Message)); } }
/// <summary> /// 批量读取数据信息,数据长度无效 /// </summary> /// <param name="address">节点的地址格式</param> /// <returns>带有结果对象的结果数据</returns> public OperateResult <byte[]> Read(string[] address) { // 指令生成 OperateResult <byte[]> command = BuildReadCommand(address); if (!command.IsSuccess) { return(command); } // 核心交互 OperateResult <byte[]> read = ReadFromCoreServer(command.Content); if (!read.IsSuccess) { return(read); } // 检查反馈 OperateResult check = CheckResponse(read.Content); if (!check.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(check)); } // 提取数据 return(AllenBradleyHelper.ExtractActualData(read.Content, true)); }
/// <summary> /// 创建一个写入的报文指令 /// </summary> /// <param name="address">起始地址</param> /// <param name="typeCode">类型数据</param> /// <param name="data">数据</param> /// <returns>包含结果对象的报文信息</returns> public OperateResult <byte[]> BuildWriteCommand(string address, ushort typeCode, byte[] data) { byte[] cip = AllenBradleyHelper.PackRequestWrite(address, typeCode, data); byte[] commandSpecificData = AllenBradleyHelper.PackCommandSpecificData(cip); return(OperateResult.CreateSuccessResult(AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, commandSpecificData))); }
private OperateResult <byte[]> ReadByCips(params byte[][] cips) { OperateResult <byte[]> read = ReadCipFromServer(cips); if (!read.IsSuccess) { return(read); } // 提取数据 -> Extracting data return(AllenBradleyHelper.ExtractActualData(read.Content, true)); }
/// <summary> /// 创建一个读取的报文指令 /// </summary> /// <param name="address">tag名的地址</param> /// <returns>包含结果对象的报文信息</returns> public OperateResult <byte[]> BuildReadCommand(string[] address) { List <byte[]> cips = new List <byte[]>( ); foreach (var add in address) { cips.Add(AllenBradleyHelper.PackRequsetRead(add)); } byte[] commandSpecificData = AllenBradleyHelper.PackCommandSpecificData(cips.ToArray( )); return(OperateResult.CreateSuccessResult(AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, commandSpecificData))); }
/// <summary> /// Create a written message instruction /// </summary> /// <param name="address">The address of the tag name </param> /// <param name="typeCode">Data type</param> /// <param name="data">Source Data </param> /// <param name="length">In the case of arrays, the length of the array </param> /// <returns>Message information that contains the result object</returns> public OperateResult <byte[]> BuildWriteCommand(string address, ushort typeCode, byte[] data, int length = 1) { try { byte[] cip = AllenBradleyHelper.PackRequestWrite(address, typeCode, data, length); byte[] commandSpecificData = AllenBradleyHelper.PackCommandSpecificData(Slot, cip); return(OperateResult.CreateSuccessResult(AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, commandSpecificData))); } catch (Exception ex) { return(new OperateResult <byte[]>("Address Wrong:" + ex.Message)); } }
/// <summary> /// 使用CIP报文和服务器进行核心的数据交换 /// </summary> /// <param name="cips">Cip commands</param> /// <returns>Results Bytes</returns> public OperateResult <byte[]> ReadCipFromServer(params byte[][] cips) { byte[] commandSpecificData = AllenBradleyHelper.PackCommandSpecificData(Slot, cips); byte[] command = AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, commandSpecificData); // 核心交互 -> Core Interactions OperateResult <byte[]> read = ReadFromCoreServer(command); if (!read.IsSuccess) { return(read); } // 检查反馈 -> Check Feedback OperateResult check = CheckResponse(read.Content); if (!check.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(check)); } return(OperateResult.CreateSuccessResult(read.Content)); }
/// <summary> /// 6F 00 3E 00 00 00 00 00 /// </summary> /// <returns></returns> public byte[] SendRRData( ) { // UCMM 请求 byte[] buff = new byte[] { 0x00, 0x00, 0x00, 0x00, // 接口句柄,默认CIP 0x20, 0x00, // 超时 0x02, 0x00, // 项目数量,由于使用了一个地址项目和一个数据项目 0x00, 0x00, // 地址类型ID,该字段应为0,表示一个UCMM消息 0x00, 0x00, // 长度,由于UCMM消息使用NULL地址项,所以该字段应为0 0xB2, 0x00, // 数据类型ID,该字段应该是0x00B2来封装UCMM 0x2E, 0x00, // 后面数据包的长度,46个字节 // MR数据请求包 0x54, // 服务 0x02, // 请求路径大小 0x20, 0x06, 0x24, 0x01, // 请求路径,有可能会改变 0x07, // Priority/time_tick 0xF9, // Time-out_ticks 0x00, 0x00, 0x00, 0x00, // O-T Network Connection ID 0x08, 0x00, 0xFE, 0x80, // T-O Network Connection ID 由驱动产生??? 0x09, 0x00, // Connection Serial Number 0x4D, 0x00, // Verder ID 0x8B, 0x50, 0xD4, 0x0F, // Originator Serial Number 和T-O Network Connection ID相同 0x01, // 连接超时倍数 0x00, 0x00, 0x00, // 保留数据 0x00, 0x12, 0X7A, 0X00, // O-T RPI 0xF4, 0x43, // O-T 网络连接参数 0x00, 0x12, 0X7A, 0X00, // T-O RPI 0xF4, 0x43, // T-O 网络连接参数 0xA3, // 传输类型 0x02, // 传输路径大小,以字为单位 0x20, 0x02, 0x24, 0x01, // 连接路径,消息路由,实例 }; return(AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, buff)); }
/// <summary> /// 获取卸载一个已注册的会话的报文 -> /// Get a message to uninstall a registered session /// </summary> /// <returns>字节报文信息 -> BYTE message information </returns> public byte[] UnRegisterSessionHandle( ) { return(AllenBradleyHelper.PackRequestHeader(0x66, SessionHandle, new byte[0])); }
/// <summary> /// 向PLC注册会话ID的报文 -> /// Register a message with the PLC for the session ID /// </summary> /// <returns>报文信息 -> Message information </returns> public byte[] RegisterSessionHandle( ) { byte[] commandSpecificData = new byte[] { 0x01, 0x00, 0x00, 0x00, }; return(AllenBradleyHelper.PackRequestHeader(0x65, 0, commandSpecificData)); }
/// <summary> /// 创建一个读取的报文指令 /// </summary> /// <param name="address">tag名的地址</param> /// <returns>包含结果对象的报文信息</returns> public OperateResult <byte[]> BuildReadCommand(string address) { byte[] cip = AllenBradleyHelper.PackRequsetRead(address); return(OperateResult.CreateSuccessResult(AllenBradleyHelper.PackRequestHeader(0x6F, SessionHandle, AllenBradleyHelper.PackCommandSpecificData2(NetWorkConnectionID, cip)))); }