使用示例程序
该程序包括多个元素,操作员可使用这些元素触发以下动作:
启动程序时,仅启用“启动示例” (Start Sample) 按钮。单击此按钮后,程序将生成所需的 OPC 对象。随即会启用其它按钮。
单击“ 启动示例” (Start Sample) 按钮后,以 C# 编写并使用 .NET- Framework 的 OPC 自定义接口(异步通信)的示例程序的启动对话框 .
程序说明 :
1 选择 .NET 组件
2 将 ProgID 转换为 CLSID
3 建立与 OPC 服务器的连接
4 创建 OPC 组
5 添加数据项
6 请求 IConnectionPointContainer 接口
7 请求 IOPCAsyncIO2 接口
8 创建回调对象
9 连接 OPC 服务器与客户端的回调对象
10 执行所需的写入和读取操作
11 接收 OPC 服务器的通知
12 删除对象并释放内存
步骤 1:选择 .NET 组件
要配合使用 OPC 数据访问的自定义接口和 .NET,必须在您的 Visual Basic 项目中使用上述运行时可调用包装 (RCW) 。在该示例项目中,OpcRcw.Da 和 OpcRcw.Comn 组件已添完毕。
如果它们未出现在选项中,也可使用“浏览” (Browse) 按钮从下列文件夹中进行选择: “ <安装路径> SIEMENS SIMATIC.NET opc2in”
步骤 2:将 ProgID 转换为 CLSID
为了对其进行标识,每个 COM 服务器都有一个 ProgID 且该 ProgID 分配给世界上唯一的类型。使用 GetTypeFromProgID() 函数可实现上述操作。SIMATIC NET 的 OPC 服务器的 ProgID 是 L"OPC.SimaticNET":
Type svrComponenttyp = Type.Get TypeFromProgID(L"OPC.SimaticNET");
步骤 3:建立与 OPC 服务器的连接
Activator 类的 CreateInstance() 函数生成一个具有之前指定类型的类的实例:
pIOPCServer =
(IOPCServer)Activato r.CreateInstance(svrComponenttyp
);
该程序段的结果是 IOPCServer 类型的接口变量 pIOPCServer。
步骤 4:创建 OPC 组
IOPCServer 接口具有用于创建组的 AddGroup() 方法:
pIOPCServer.AddGroup(GROUP_NAME,
0,
dwRequestedUpdateRate,
hClientGroup,
hTimeBias..AddrOfPinnedObject(),
hDeadban d.AddrOfPinnedObject(),
dwLCID,
out pSvrGroupHandle,
out pRevUpdateRate,
ref out pobjGroup1)
注意
hDeadband 和 hTimeBias 的内存分配由 GCHandle.Alloc() 函数完成。
GCHandle hTimeBias;
hTimeBias = GCHandle.Alloc(tim ebias,GCHandleType.Pinned);
GCHandle hDeadband;
hDeadband = GCHandle.Alloc(deadband,GCHandleType.Pinned);
这些函数处理传送变量时间偏倚和死区(百分比死区)的非管理型内存。
当不再需要管理句柄时,必须按如下所示再次将其释放:
if (hTimeBias.IsAllocated) hTimeBias. Free();
if (hDeadband.IsAllocated) hDeadband.Free();
该程序段的结果是一个具有指定名称和所需属性的组。AddGroup() 还返回 pobjGroup1变量作为返回参数,即组对象的接口。
使用类型调整调用 IOPCGroupStateMgt ,可以只从返回的组接口 pobjGroup1 获取该接口。该调用的简化形式对应于 COM 方法 Queryinterface()。
稍后需使用 IOPCGroupStateMgt 接口的 S etState() 方法激活和禁用组。
pIOPCGroupStateMgt = (IOPCGroupStateMgt)pob jGroup1;
步骤 5:添加数据项
IOPCItemMgt 接口具有用于创建 OPC 数据项的 AddItems() 方法:
((IOPCItemMgt)pobjGroup1).AddItems(2,ItemDeffArray,out
pResults,out pErrors);
该程序段的结果是服务器添加两个具有 itemd efs 参数中所指定属性的数据项。此外,还会对结果结构 OPCITEMRESULT 的变量(服务器句柄、目标系统上数据项的数据类型等)进行初始化。
由于结果通过基础 COM 接口写入至非管理型内存,因此来自管理型 .NET 代码的访问必须利用封送函数:
OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure(pos,
typeof(OPCITEMRESULT));
Ite mSvrHandleArray[0] = result.hServer;
pos = new IntPtr(pos.ToInt32() +
Marshal.SizeOf(typeof(OPCITEMRESULT)));
OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure
(pos,typ eof(OPCITEMRESULT));
ItemSvrHandleArray[1] = result.hServer;
步骤 6:请求 IConnectionPointContainer 接口
IConnectionPointContainer 类型的 pIConnectionPointContainer 变量可源自 m_group_1 变量。
pIConnectionPointContai ner =
(IConnectionPointContainer)pobjGroup1;
定位 IConnectionPoint 接口需要使用该接口。
步骤 7:请求 IOPCAsyncIO2 接口
pIOPCAsyncIO2 类型的 pIOPCAsyncIO2 变量可源自 pobjGroup1 变量。
pIOPCAsyncIO2 = (IOPCAsyncIO2)pobjGroup1;
该接口提供用于异步读取和写入值的方法。
步骤 8:创建回调对象
为了允许 OPC 服务器返回异步操作的值,必须在客户端上执行 I OPCDataCallback 接口。
public class OPCAsync :System.Windows.Forms.Form ,
IOPCDataCallback
使用 IConnectionPointContainer 接口的 FindConnectionPoint() 方法建立 OPC 服务器的 IConnectionPoint 和 IOPCDataCallback 接口间的连接。该连接将为异步调用生成一个回调对象。
Guid iid = typeof(IO PCDataCallback).GUID;
pIConnectionPointContainer.FindConnectionPoint(ref iid,
out
pIConnectionPoint);
步骤 9:连接 OPC 服务器与客户端的回调对象
OPC 服务器的回调对象与客户端应用程序间的连接通过 Advise() 方法来建立。返回变量 dwCookie 是该连接的 ID 。
pIConnectionPoint.Advise(this,out dwCookie);
步骤 10:执行所需的写入或读取操作
在步骤 7 中生成的 Read() 和 Write() 方法可通过 IOPCAsyncIO2 接口来访问:
pIOPCAsyncIO2.Read(1,ItemSvrHandleArray,nTransactionID+1,
out nCancelid,out pErrors);
步骤 11:接收 OPC 服务器的通知
如果激活组中激活数据项的数据发生更改,服务器将调用回调对象的 OnDataC hange 方法。读取操作完成后,服务器调用 OnReadComplete() 方法;写入操作完成后,服务器调用 OnWriteComplete() 方法。服务器将返回值以参数的形式传递至方法。
virtual void OnDataChange(
Int32 dwTransid,
Int32 hGroup,
Int32 hrMasterquality,
Int32 hrMastererror,
Int32 dwCount,
int[] phClientItems,
object[] pvValues,
short[] pwQualities,
FILETIME[] pftTimeStamps,
int[] pErrors,
)
步骤 12:删除对象并释放内存
退出程序前或单击“ 停止”(Stop) 后,必须删除已生成的 OPC 对象并释放所占用的内存。
pIConnectionPoint.Unadvise(dwCookie);
Marshal.ReleaseComObject(pIConnectionPoint);
Mar shal.ReleaseComObject (pIConnectionPointContainer);
Marshal.ReleaseComObject(pIOPCAsyncIO2);
Marshal.ReleaseComObject(pIOPCGroupStateMgt);
Marshal.ReleaseComObject(pobjGroup1);
Marshal.ReleaseComObject(pIOPCServer);
释放内存
使用 COM 时,客户端有时需要释放服务器所请求的内存。相关规则如下:
• [out]:将从服务器请求具有该属性的参数的内存。
• [in,out] :将从客户端请求此类参数的内存。服务器可以再次释放内存并对其进行重新分配。
• [in] :客户端将请求内存。服务器不负责释放内存。
原文标题:以 C# 编写的 OPC 自定义接口(异步通信)
文章出处:【微信公众号:机器人及PLC自动化应用】欢迎添加关注!文章转载请注明出处。
全部0条评论
快来发表一下你的评论吧 !