昨天又有人问我 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库。

最新文章

  1. SSH免密码登陆原理
  2. 学习mongo系列(三) update() save()
  3. NBU AIX ORACLE10G RAC恢复到AIX单实例(表空间恢复)
  4. visualgo 数据结构与算法可视化工具
  5. 事务Isolation Level 例子详解
  6. 简单又实用的分享!SharePoint母版页引用(实战)
  7. 20165221 《网络对抗技术》EXP1 PC平台逆向破解
  8. Elasticsearch学习笔记(十一)Mapping原理
  9. intptr_t 指针
  10. sqlserver 2012 分页
  11. 转载http协议
  12. 学习笔记69—金蝶财务软件安装教程(KIS12.3,win10)
  13. Linux Platform驱动模型(三) _platform+cdev
  14. python中网络编程基础
  15. ARP 欺骗攻击与防御
  16. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二十三)Structured Streaming遇到问题:Set(TopicName-0) are gone. Some data may have been missed
  17. Oracle和Mysql中mybatis模糊匹配查询区别
  18. 2018.09.02 bzoj1025: [SCOI2009]游戏(计数dp+线筛预处理)
  19. eclipse中debug模式不能启动运行,run运行模式却能启动运行!
  20. 《C++ Primer Plus》第9章 内存模型和名称空间 学习笔记

热门文章

  1. IntelliJ IDEA + Tomcat ;On Upate Action 与 On Frame Deactivation
  2. LeetCode664. Strange Printer
  3. OA项目Spring.Net代替抽象工厂(三)
  4. Java MongoDB : Save image example
  5. hdu 1085 有num1个 1 ,num2个 2 ,num3个 5 (母函数)
  6. 【51nod】1251 Fox序列的数量
  7. 二、 sql*plus常用命令
  8. xshell连接linux,切换焦点,自动执行ctrl+c
  9. FILE operattion
  10. 个人博客www.0x002.com