昨天又有人问我 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. Codeforces 264B Good Sequences(DP+素数筛)

    题目链接:http://codeforces.com/problemset/problem/264/B 题目大意:给出n个单调递增的数,让你找出最长的好序列,好序列是一种单调递增的并且相邻元素的最大公 ...

  2. js中的Object.seal()与Object.freeze()

    关键字:seal, freeze, property descriptor. 1.Object.seal() 参考文档(2)中这样描述: The Object.seal() method seals ...

  3. Asp.net Vnext 自定义日志

    概述 本文已经同步到<Asp.net Vnext 系列教程 >中] 可以通过自定义日志,把错误消息记录到数据库 实现 在启动文件Startup Configure方法中加入自定义的日志提供 ...

  4. C语言:奇偶归一猜想

    1.奇偶归一猜想——求多少步归一.(10分) 题目内容: 奇偶归一猜想——对于每一个正整数,如果它是奇数,则对它乘3再加1,如果它是偶数,则对它除以2,如此循环,最终都能够得到1. 如n = 11,得 ...

  5. span 超出内容自动换行

    <span style="width:80%;word-break:normal;display:block;word-warp:break-word;overflow:hidden; ...

  6. JSTL使用

    1.标签函数库 核心标签库                 c I18N格式标签库   fmt SQL标签库  sql XML标签库  xml 函数标签库 fn 2.JSTL支持EL 二:表达式标签 ...

  7. Git 简史

    同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代.Linux 内核开源项目有着为数众广的参与者.绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991 ...

  8. 请爱护你的JTAG烧录口---记录

        排除了下载线的问题后,还是不能访问FPGA的JTAG口,那么很有可能你的FPGA芯片的JTAG口已经损坏.此时请用万用表检查TCK,TMS,TDO和Tdi是否和GND短路,如果任何一个信号对地 ...

  9. ACM 水果 hdu 1263 一题多解

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1263 文章末有相应的一些测试数据供参考. 传统的数组解题方式 思路一: 三种属性的数据放在一个结构体里面, ...

  10. python获取当前系统的桌面的路径

    一,用内置的winreg(推荐) import winregdef get_desktop():    key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,\  ...