昨天又有人问我 OPC Client 编写,实际是他们不了解OPC 客户端的工作原理,要想写客户端程序,必须知道OPC对象, OPC逻辑对象模型包括3类对象:OPC server对象、OPC group对象、OPC item对象,每类对象都包括一系列接口。

OPC Server对象

主要功能为:1、创建和管理OPC Group对象;

2、管理服务器内部的状态信息;

OPC Group对象

主要功能为:1、管理OPC Group对象的内部状态信息;

2、创建和管理Items对象。

3、OPC服务器内部的实时数据存取服务(同步与异步方式)。

OPC组中有以下几个主要属性:Name :组的名字 ;Active:组的激活状态标志 ;Update Rate OPC:服务器向客户程序提交数据变化的刷新速率;Percent Dead band:数据死区,即能引起数据变化的最小数值百分比。

OPC ITEM 是非COM对象,在OPC标准中用来描述实时数据,是客户端不可见的对象。代表了与服务器中的数据的连接,它并不是数据源,而仅仅是与数据源的连接。每个项都有以下主要属性: Active项的激活状态、Value项的数值、类型为VARIANT、Quality项的品质,代表数值的可信度,类型为SHORT、TimeStamp时间戳,代表数据的存取时间。

你不管用什么开发语言只要了解上面几个对象,就会写程序了

下面举个VC的例子

HRESULT  r1;
 CLSID  clsid;
 LONG  TimeBias = 0;
 FLOAT  PercentDeadband = 0.0;
 DWORD  RevisedUpdateRate;
 LPWSTR  ErrorStr;
 char  str[100];
 CString  szErrorText;

m_pItemResult = NULL;

客户端程序必须对DCOM进行初始化设置,以保证OPC服务器端回调函数不会被堵塞。 
 r1 = CoInitialize(NULL);
 if (r1 != S_OK)
 { if (r1 == S_FALSE)
  { MessageBox("COM Library already initialized",
              "Error CoInitialize()", MB_OK+MB_ICONEXCLAMATION);
  }
  else
  { szErrorText.Format("Initialisation of COM Library failed. Error Code= %4x", r1);
   MessageBox(szErrorText,"Error CoInitialize()", MB_OK+MB_ICONERROR);
   SendMessage(WM_CLOSE);
   return;
  }
 }
 
 通过OPC服务器的ProgID查询注册表中相关CLSID。每个COM服务器都有一个字符串型的ProgID,通过ProgID可以得到全球惟一的CLSID,使用CLSIDFromProgID( )函数实现ProgID到CLSID的转换。 r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid);
 if (r1 != S_OK)
 { MessageBox("Retrival of CLSID failed",
       "Error CLSIDFromProgID()", MB_OK+MB_ICONERROR);
  CoUninitialize();
  SendMessage(WM_CLOSE);
  return;
 }

连接OPC服务器,查询对象的IID_IOPCServer接口。在连接OPC服务器前,OPC客户端需要事先指定计算机名和OPC数据访问服务器名,建立连接后,创建OPC组并添加OPC数据项。

r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer);
 if (r1 != S_OK)
 { MessageBox("Creation of IOPCServer-Object failed",
             "Error CoCreateInstance()", MB_OK+MB_ICONERROR);
  m_pIOPCServer = NULL;
  CoUninitialize();
  SendMessage(WM_CLOSE);
  return;
 }

创建OPC组,查询IOPCItemMgt接口。IOPCServer接口的AddGroup()方法可以创建一个有指定名称和属性的OPC组。

r1=m_pIOPCServer->AddGroup(L"grp1",   // [in] group name
      TRUE,     // [in] active
      500,     // [in] request this Update Rate from Server
      1,      // [in] Client handle
      &TimeBias,    // [in] no time interval to system UTC time
      &PercentDeadband,   // [in] no deadband, so all data changes are reported 
      LOCALE_ID,    // [in] Server uses English language for text values
      &m_GrpSrvHandle,  // [out] Server handle to identify this group in later calls
      &RevisedUpdateRate,  // [out] the answer form the Server to the requested update rate
         IID_IOPCItemMgt,  // [in] requested interface type of the group object
      (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface
 
 if (r1 == OPC_S_UNSUPPORTEDRATE)
 { 
  szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate );
  AfxMessageBox(szErrorText);
 }
 else
  if (FAILED(r1)){
   MessageBox("Can't add Group to Server!", "Error AddGroup()", MB_OK+MB_ICONERROR);
   m_pIOPCServer->Release();
   m_pIOPCServer = NULL;
   CoUninitialize();
   SendMessage(WM_CLOSE);
   return;
  }
添加OPC数据项。使用IOPCItemMgt接口的AddItem()方法可以添加具有特殊属性的指定数量的数据项。

// define an item table with one item as in-paramter for AddItem
 m_Items[0].szAccessPath    = L"";

m_Items[0].szItemID     = szItemID;  // 影响数据类型
 m_Items[0].bActive     = TRUE;   
 m_Items[0].hClient     = 1;
 m_Items[0].dwBlobSize    = 0;
 m_Items[0].pBlob     = NULL;
 m_Items[0].vtRequestedDataType = 0;    
             // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1,    // [in] add one item
       m_Items,    // [in] see above
       &m_pItemResult,   // [out] array with additional information about the item
       &m_pErrors);   // [out] tells which of the items was successfully added.
             // For any item which failed it provides a reason

程序退出时

OPC连接断开,释放接口指针。当程序退出或停止服务器时,依次删除Item(RemoveItems)、Group(RemoveGroups),释放资源。

void CAsynOPCDlg::OnStop( ) 停止服务器。
h1=m_IOPCItemMgt->RemoveItems(1,phServer,&pErrors);删除Items。
h1=m_IOPCServer->RemoveGroup(m_GrpSrvHandle,TRUE);删除Group。
m_IOPCServer->Release( );释放服务器。
m_IOPCServer=NULL;
CoUninitialize( );关闭COM库。

关于OPC Client 编写的更多相关文章

  1. 关于OPC Client 编写2

    最近在搞到一个OPC动态库OPCAutomation.dll,该动态库在http://www.kepware.com/可下载,下面介绍如何用C#进行OPC Client开发. 1.新建C#应用程序,命 ...

  2. 云平台制作(1)-OPC Client取数模块的制作

    近来由于工程需要,基于OPC DA 2.0搭建通用的取数模块,与远程webscoket服务端连接,并传输数据.在网上找了些资料,修改相应网友公开的源代码,基本达到要求,特供大家参考. 1.实体类 us ...

  3. 关于OPC的研究1]c# opc client源码调试和学习笔记

    c# opc client是一个在网上下载的示例程序,调试的时候还是费了一番周折,服务器端程序来自king view6.55,另文介绍. 1.注册dll 程序中有一个名叫OPCDAAuto.dll的文 ...

  4. 《连载 | 物联网框架ServerSuperIO教程》- 18.集成OPC Client,及使用步骤

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  5. 《物联网框架ServerSuperIO教程》-19.设备驱动和OPC Client支持mysql、oracle、sqlite、sqlserver的持久化。v3.6.4版本发布

    19.设备驱动和OPC Client支持mysql.oracle.sqlite.sqlserver的持久化 19.1     概述 ServerSuperIO支持设备驱动和OPC Client采集的数 ...

  6. (OPC Client .NET 开发类库)网上很多网友都有提过,.NET开发OPC Client不外乎下面三种方法

    1. 背景 OPC Data Access 规范是基于COM/DCOM定义的,因此大多数的OPC DA Server和client都是基于C++开发的,因为C++对COM/DCOM有最好的支持.现在, ...

  7. C#开发OPC Client程序

    前一段时间写了一个OPC Client程序,现在将简单介绍一下程序开发方法.测试环境最后将我写的程序开源到Github上去. 一.开发方法 我这里用的是一个OPC动态库OPCAutomation.dl ...

  8. C# WPF - MVVM实现OPC Client管理系统

    前言 本文主要讲解采用WPF MVVM模式设计OPC Client的过程,算作对于WPF MVVM架构的学习记录吧!不足之处请不吝赐教,感谢! 涉及知识点 C#基础 Xaml基础 命令.通知和数据绑定 ...

  9. Netty http client 编写总结

    Apache http client 有两个问题,第一个是 apache http client 是阻塞式的读取 Http request, 异步读写网络数据性能更好些.第二个是当 client 到 ...

随机推荐

  1. Spring框架的基本使用(IOC部分)

    Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. Spring的好处 1.方便解耦,简化开发: Spring就是一个大工厂,专门负责生成Bean,可以将所有对象创建和依赖关 ...

  2. MySQL执行计划explain的key_len解析

    前言:当用Explain查看SQL的执行计划时,里面有列显示了 key_len 的值,根据这个值可以判断索引的长度,在组合索引里面可以更清楚的了解到了哪部分字段使用到了索引.下面演示中,表结构的合理性 ...

  3. INSTEAD OF与AFTER触发器

    INSTEAD OF 触发器 AFTER 触发器(也叫“FOR”触发器)会在触发 insert.update 或是delect 动作之后执行.例如,一个 Employees 表上的 AFTER 触发器 ...

  4. Python学习笔记:bisect模块实现二分搜索

    在Python中可以利用bisect模块来实现二分搜索,该模块包含函数只有几个: import bisect L = [1,3,4,5,5,5,8,10] x = 5 bisect.bisect_le ...

  5. 使用文本用户界面(NMTUI)进行网络配置

    NetworkManager 文本用户界面(TUI)工具 nmtui 可提供一个文本界面配置由 NetworkManager 控制的网络.该工具包含在 NetworkManager-tui 子软件包中 ...

  6. JS验证表单中TEXT文本框中是否含有非法字符

    <form id="form" action="" method="post"> <input type="hi ...

  7. stellar

    13) Sundapeng.123 12) 有个问题问下,这里的私钥和公钥是随意生成的吗? 当前的配置启动的时候报错了 11) ssh root@39.108.127.234 Liansen2018 ...

  8. Java 之 JDBC

    mysql : //****** 四大金刚: 驱动类名.url.用户名.密码 //MySQL四大金刚 String driverClassname="com.mysql.jdbc.Drive ...

  9. 【LOJ】#2066. 「SDOI2016」墙上的句子

    题解 我一直也不会网络流--orz 我们分析下这道题,显然和行列没啥关系,就是想给你n + m个串 那么我们对于非回文单词之外的单词,找到两两匹配的反转单词(即使另一个反转单词不会出现也要建出来) 具 ...

  10. USACO 5.5 Twofive

    TwofiveIOI 2001 In order to teach her young calvess the order of the letters in the alphabet, Bessie ...