摘要: 近日 见同事正在看 高焕堂新书 《UML+OOPC 嵌入式C语言开发精讲》偶然发现他对COR模式存在严重误解。废话少说 ,具体如下: 在他的大作 32.5 章节里 用到该模式代码如下:#include "lw_oopc_kc.h"#include "ex32-il.h"CLASS(LED_P0){ IMPLEMENTS(IL); void (*init)(LED_P0*); IL* next;};...阅读全文
posted @ 2010-01-05 09:14 wangok 阅读(1787) 评论(10) 编辑

                                                            OPC的基本概念
1
服务器、组、数据项

        OPC服务器由三类对象组成:服务器(Server)、组(Group)、数据项(Item)。服务器对象(Server)拥有服务器的所有信息,同时也是组对象(Group)的容器。组对象(Group)拥有本组的所有信息,同时包容并逻辑组织OPC数据项(Item)。
OPC组对象(Group)提供了客户组织数据的一种方法。客户可对之进行读写,还可设置客户端的数据更新速率。当服务器缓冲区内数据发生改变时,OPC 将向客户发出通知,客户得到通知后再进行必要的处理,而无需浪费大量的时间进行查询。OPC规范定义了两种组对象:公共组和局部组(私有组)。公共组由多 个客户共有,局部组只隶属于一个OPC客户。一般说来,客户和服务器的一对连接只需要定义一个组对象。 在每个组对象中,客户可以加入多个OPC数据项(Item)。  
OPC数据项是服务器端定义的对象,通常指向设备的一个寄存器单元。OPC客户对设备寄存器的操作都是通过其数据项来完成的,通过定义数据项,OPC规范 尽可能的隐藏了设备的特殊信息,也使OPC服务器的通用性大大增强。OPC数据项并不提供对外接口,客户不能直接对之进行操作,所有操作都是通过组对象进行的。
客户操作数据项的一般步骤为:
(1)通过服务器对象接口枚举服务器端定义的所有数据项,如果客户对服务器所定义的数据项非常熟悉,此步可以  忽略。
(2)将要操作的数据项加入客户定义的组对象中。
(3)通过组对象对数据项进行读写等操作。
每个数据项的数据结构包括三个成员变量:即数据值、数据质量和时间戳。数据值是以VARIANT形式表示的。应当注意,数据项表示同数据源的连接而不等同 于数据源,无论客户是否定义数据项,数据源都是客观存在的。可以把数据项看作数据源的地址,即数据源的引用,而不应看作数据源本身。

 

2 报警(Alarm)和事件(Event

      报警和事件处理机制增强了OPC客户处理异常的能力。服务器在工作过程中可能出现异常,此时,OPC客户可通过报警和事件处理接口得到通知,并能通过该接口获得服务器的当前状态。在很多场合,报警(Alarm)和事件(Event)的含义并不加以区分,两者也经常互换使用。从严格意义上讲,两者含义略有差别。

依据OPC规范,报警是一种异常状态,是OPC服务器或服务器的一个对象可能出现的所有状态中的一种特殊情况。例如,服务器上标记为FC101的一个单元可能有如下状态:高出警戒,严重高出警戒,正常,低于警戒,严重低于警戒。除了正常状态外,其他状态都视为报警状态。

事件则是一种可以检测到的出现的情况,这种情况或来自OPC客户,或来自OPC服务器,也可能来自OPC服务器所代表的设备,通常都有一定的物理意义。事件可能与服务器或服务器的一个对象的状态有关,也可能毫无关系。如高出警戒和正常状态的转换事件和服务器的某个对象的状态有关,而操作设备,改变系统配置以及出现系统错误等事件和对象状态就无任何关系。

 

3 OPC体系结构

      OPC规范提供了两套接口方案,即COM接口和自动化。COM接口效率高,通过该接口,客户能够发挥OPC服务器的最佳性能,采用C++语言的客户一般采COM接口方案;自动化接口使解释性语言和宏语言访问OPC服务器成为可能,采用VB语言的客户一般采用自动化接口。自动化接口使解释性语言和宏语言编写客户应用程序变得简单,然而自动化客户运行时需进行类型检查,这一点则大大牺牲了程序的运行速度。OPC服务器必须实现COM接口,是否实现自动化接口则取决于供应商的主观意愿。

 

4 服务器缓冲区数据和设备数据     

      OPC服务器本身就是一个可执行程序,该程序以设定的速率不断地同物理设备进行数据交互。服务器内有一个数据缓冲区,其中存有最新的数据值,数据质量戳和时间戳。时间戳表明服务器最近一次从设备读取数据的时间。服务器对设备寄存器的读取是不断进行的,时间戳也在不断更新。即使数据值和质量戳都没有发生变化,时间戳也会进行更新。客户既可从服务器缓冲区读取数据,也可直接从设备读取数据,从设备直接读取数据速度会慢一些,一般只有在故障诊断或极特殊的情况下才会采用。

 

5 同步和异步

     OPC客户和OPC服务器进行数据交互可以有两种不同方式,即同步方式和异步方式。在同步方式下,客户端发出请求并进入等待,直到服务器端返回数据,同步方式实现较为简单,当然也很浪费资源,当客户数目较少而且同服务器交互的数据量也比较少的时候可以采用这种方式;异步方式实现较为复杂,需要在客户程序中实现服务器回调函数。然而当有大量客户和大量数据交互时,异步方式能提供高效的性能,尽量避免阻塞客户数据请求,并最大可能地节省CPU和网络资源

 

6.订阅方式

   OPCclient 首先告诉OPCSERVER,她需要刷新哪些数据 以及刷新的频率是多少,然后立即返回做其它事情。当OPCSERVER发现这些数据发生了改变就采用回调机制将数据传给客户端,这种方式免除了客户端的 轮询,节省了很多资源。

 

最新正版智泰OPC服务器开发包(http://shop66418560.taobao.com/ )。QQ 1505956248

 

posted @ 2011-05-13 12:55 wangok 阅读(152) 评论(0) 编辑

      网上有很多关于OPC 的文章,可惜都很零乱,正好这段有点空,自己就整理下,形成系列文章 ,与大家共分享。今天这是第一篇。

1:什么是 OPC

OPC 全称是 Object Linking and Embeding OLE for Process Control ,它是一个工业标准,管理这个标准的国际组织是 OPC 基金会, OPC 基金会现有会员已超过 220 家。遍布全球,包括世界上所有主要的自动化控制系统、仪器仪表及过程控制系统的公司。它基于微软的 OLE( 现在的 Active X) COM ( 部件对象模型 ) DCOM ( 分布式部件对象模型 ) 技术。包括一整套接口、属性和方法的标准集,用于过程控制和制造业自动化系统。它的出现为基于 Windows 的应用程序和现场过程控制应用建立了桥梁。

你也可以简单的理解它为一种通讯协议,比如 RS-485 ,使你的设备 / 软件可以很方便的与别的设备 / 软件 很方便的交换数据。

2 :为什么需要 OPC

      在工业控制系统中,不同的供应商提供的设备之间需要交换数据,例如在实现下图 那样多层生产控制信息系统时,从处理设备数据的现场设备层,到进行过程处理的过程控制系统层,以至最上层的生产管理层,他们之间需要互相通讯,这时建立和普及一个有 效的数据交换标准将就是当务之急。这样情况下就有了 OPC 的用武之地。

               

     我们原来在 给一个化工厂 开发一个计量设备时,产生的计量数据需要与他们的生产控制系统对接,这时显然不可能开发一个私有协议(生产控制系统厂家 肯定不乐意兼容你的协议)。于是 采用了 OPC 协议,很好的解决了问题。


3 OPC 的组成

       OPC 主要有 OPCServer OPCClient 组成 ,OPCSERVER 可以简单理解为 发布数据的地方, opcclient 可以理解为消费数据的地方

4: 最新正版智泰OPC服务器开发包(http://shop66418560.taobao.com/ )。QQ 1505956248


                    

posted @ 2011-05-11 16:05 wangok 阅读(155) 评论(0) 编辑

CStatForServer 本类的作用是计算平均速率

 

void CStatForServer::RecordCurrentRate(float uploadrate, float downloadrate)

{

     //   if reach record interval

     DWORD    dwCurTime = GetTickCount();

     if (dwCurTime - m_dwLastRecordTime < RECORD_INTERVAL_MS)

         return;

     m_dwLastRecordTime = dwCurTime;

     if (ULONG_MAX != m_ulRecordTimes_Download

         && IsAnyTaskRunning())

     {

         m_ulRecordTimes_Download++; // 次数加一

         m_fAverageDownloadSpeed = m_fAverageDownloadSpeed + ((downloadrate - m_fAverageDownloadSpeed) / m_ulRecordTimes_Download ); // 这点可能难理解       

     }

 

     if (ULONG_MAX != m_ulRecordTimes_Upload)

     {

         m_ulRecordTimes_Upload++;

          m_fAverageUploadSpeed = m_fAverageUploadSpeed + ( (uploadrate - m_fAverageUploadSpeed) /      m_ulRecordTimes_Upload);      

     

      }

 

}

m_fAverageDownloadSpeed = m_fAverageDownloadSpeed + ((downloadrate - m_fAverageDownloadSpeed) / m_ulRecordTimes_Download );

 

这个算法不太好懂,它的意思是前面n-1次的avg值,然后现在有了第n次的实际值,开始算第n次的avg值

 这样计算的结果与所有次的值累加起来然后除以次数结果是一样的。

 他这个算法是根据数学公式运算简化后的结果

 

m_fAverageDownloadSpeed*m_ulRecordTimes_Download=m_fAverageDownloadSpeed*m_ulRecordTimes_Download+downloadrate - m_fAverageDownloadSpeed;

》》 原计算公式两边都乘以次数

      

 

m_fAverageDownloadSpeed*m_ulRecordTimes_Download="所有次的累加和"

 

m_fAverageDownloadSpeed*m_ulRecordTimes_Download+downloadrate - m_fAverageDownloadSpeed

 

=m_fAverageDownloadSpeed*(m_ulRecordTimes_Download-1)+downloadrate;

 

》》 前n-1次的平均值*次数+本次的速度等于所有次的累加和

 

OPC 服务器开发包 
  http://shop66418560.taobao.com

 

posted @ 2011-05-03 16:51 wangok 阅读(174) 评论(0) 编辑

DCOM设置- WINXP(SP1)

 

[注意]

以下为服务器配置过程。

客户端设置只需完成1-4即可。

 

1、运行DCOMCNFG进入DCOM设置(在XP中称为组件服务)

1.1、组件服务配置界面

 

 

2、打开组件服务\计算机\我的电脑,鼠标右键设置属性

 

3、注意默认属性的设置

 

4、注意默认COM安全性设置,设置访问权限和启动权限

4.1、在访问权限编辑界面中添加Everyone 设置允许访问权限。

 

 

4.2、在启动权限编辑界面中添加Everyone 设置允许启动权限。

 

5、设置组件服务\我的电脑\DCOM配置

 

 

 

5.1、设置应用程序DCOM设置,本例应用程序为OPC ASDPDEMO 1,这个名字随应用程序的不同会发生变化。进入属性设置窗口。

 

 

5.1.1、OPC ASDPDEMO 1属性中“常规”设置

 

5.1.2、OPC ASDPDEMO 1属性中“位置”设置

 

5.1.3、OPC ASDPDEMO 1属性中“安全性”设置

 

5.1.4、OPC ASDPDEMO 1属性中“标识”设置一,这个配置适用于服务器端软件需要界面显示的情况,服务器软件在前台运行。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5.1.5、5.1.1、OPC ASDPDEMO 1属性中常规设置二,这个配置适合于“服务型”服务器软件,在服务器软件所在系统中,无法看到服务器软件界面,服务器软件在后台运行。

 

5.2、按照OPC ASDPDEMO 1的设置选项设置 OpcEnum服务器软件。

 

 

OPC 服务器开发包  http://shop66418560.taobao.com

posted @ 2011-05-03 16:24 wangok 阅读(194) 评论(0) 编辑

    近日 见同事正在看 高焕堂新书 《UML+OOPC 嵌入式C语言开发精讲》偶然发现他对COR模式存在严重误解。

废话少说 ,具体如下:

  在他的大作 32.5 章节里 用到该模式

 

代码如下:

#include "lw_oopc_kc.h"
#include "ex32-il.h"

CLASS(LED_P0)
{
    IMPLEMENTS(IL);
    void (*init)(LED_P0*);
    IL* next;
};

CLASS(LED_P1)
{
    IMPLEMENTS(IL);
    void (*init)(LED_P1*);
    IL* next;
};

CLASS(LED_P2)
{
    IMPLEMENTS(IL);
    void (*init)(LED_P2*);
    IL* next;
};

 

/* EX32-led.c */
#include <REG51F.H>
#include "lw_oopc_kc.h"
#include "ex32-led.h"

static void init_1(LED_P1* t) {
       t->next = NULL;
//    xxx = 0xf3;
}

static int pass_1(char ty, char hx, void *t) {
    LED_P1 *cthis = (LED_P1*)t;
    IL* ps = cthis->next;
    if(ty=='1')
         {
           P1 = hx;
           return 1;
         }
    if(ty=='A') P1 = hx;
    if(ps == NULL) return 0;
    else  return ps->pass(ty, hx, ps);
}


CTOR(LED_P1)
    FUNCTION_SETTING(init, init_1)
    FUNCTION_SETTING(IL.pass, pass_1)
END_CTOR
// -------------------------------
 static void init_0(LED_P0* t) {
       t->next = NULL;
}

static int pass_0(char ty, char hx, void *t) {
    LED_P0 *cthis = (LED_P0*)t;
    IL* ps = cthis->next;
    if(ty=='0')
         {
           P0 = hx;
           return 1;
         }
    if(ty=='A') P0 = hx;
    if(ps == NULL) return 0;
    else  return ps->pass(ty, hx, ps);
}

CTOR(LED_P0)
    FUNCTION_SETTING(init, init_0)
    FUNCTION_SETTING(IL.pass, pass_0)
END_CTOR
//----------------------------------------
static void init_2(LED_P2* t) {
       t->next = NULL;
}

static int pass_2(char ty, char hx, void *t) {
    LED_P2 *cthis = (LED_P2*)t;
    IL* ps = cthis->next;
    if(ty=='2')
         {
           P2 = hx;
           return 1;
         }
    if(ty=='A') P2 = hx;
    if(ps == NULL) return 0;
    else  return ps->pass(ty, hx, ps);
}


CTOR(LED_P2)
    FUNCTION_SETTING(init, init_2)
    FUNCTION_SETTING(IL.pass, pass_2)
END_CTOR

 

 

 

这三个类 就是职责链中的负责处理请求与转发请求的类,但 严重问题是 他们与 请求基本存在一一对应的关系 

 if(ty=='0')
         {
           P0 = hx;
           return 1;
         }

这是LED_P0的责任, 如果 把'0'换为'1' 则就是  LED_P1的责任  这是我们从代码里发现的, 其实他自己在书里也已经写了(如果ty值为'0',表示这是LED_P0的责任,于是将另一个参数hx值送到P0。如果ty值为'A',表示这是所有对象的都有的责任,。。)  

 

结论:高焕堂完全误解了COR模式 ,其实这些代码散发着 重复的臭味 完全可以重构到表模式 具体如何重构 不用我说了吧??

 

 摘自这本书的高焕堂简介:

     从事IT行业近30年,被称为“台湾OO技术教父级代表人物”;近年来,专注与产业 企业及嵌入式产品的架构设计,被称为

“台湾软件架构设计大师”。。。。。

 

 

posted @ 2010-01-05 09:14 wangok 阅读(1787) 评论(10) 编辑

     昨天晚上看书时,又顺手翻了翻 《重构》记的07年第一次看到它的样章时 是那样的震撼,那样的激动。哦 原来我一直苦苦寻找的答案都在这里,原来写程序时,不知道一个函数该多大合适 ,不知道对于逻辑重复的问题 该怎么有效解决,不知道。。。 呵呵 有那么多的未知,那么多的迷惘。最大的痛苦 莫过于 明明知道程序写的不优雅,却苦无解决之道。

    对于有很多人把它和《设计模式》放在同一个高度,开始时自己也有很多怀疑,现在回头看看 确实是那样 他对我们程序质量的提升,开发速度的提高 都是非常有帮助的 超过,至少不低于设计模式。

     它很容易理解,也很容易学会,现在它成了我们团队的空气与水,对于每一个同事 我都强烈要求他们学习,没有重构 没有测试 我们无法写代码。嗅出了软件臭味,才会有改进的可能。它不仅仅是一本书,它已经改变了我们的开发方式,改变了我们对软件设计的认识。

    没有读过《设计模式》与《重构》你敢说自己懂设计吗? 至少我不敢。。。。

posted @ 2009-07-01 11:20 wangok 阅读(2596) 评论(34) 编辑
posted @ 2009-01-09 16:27 wangok 阅读(906) 评论(5) 编辑
posted @ 2009-01-06 15:20 wangok 阅读(979) 评论(1) 编辑
posted @ 2009-01-03 15:22 wangok 阅读(200) 评论(0) 编辑
posted @ 2008-12-27 15:01 wangok 阅读(1367) 评论(2) 编辑