zoukankan      html  css  js  c++  java
  • 关于OPC Client 编写

    昨天又有人问我 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库。
  • 相关阅读:
    jquery 备忘笔记
    spring 集成 mybatis 后数据源初始化失败问题分析
    SpringMVC 资源国际化实现以及常见问题
    IE浏览器 get请求缓存问题
    Comparison method violates its general contract! 异常原因
    Security基础(六):部署Zabbix监控平台、配置及使用Zabbix监控系统、自定义Zabbix监控项目、实现Zabbix报警功能
    LVS负载均衡中arp_ignore和arp_annonuce参数配置
    iptables防火墙相关命令详解
    <三剑客> 老大:awk命令用法
    <三剑客> 老三:grep命令用法
  • 原文地址:https://www.cnblogs.com/zjoch/p/4333020.html
Copyright © 2011-2022 走看看