SCADACLOUD智能平台实现技术

11 篇文章 0 订阅
4 篇文章 0 订阅

1、概念阐述

       ScadaCloud是一个分布式、跨平台、跨网络的实时在线平台,让您够方便地使用PC、iPhone、iPad终端在任何时间、任何地点监控您关心的设备当前运行状况。ScadaCloud提供了从端到云的完整的解决方案,向用户提供SAAS(SoftwareAs A Service,软件即服务)。

       ScadaCloud把传统C/S架构的信息平台,发展为以Cloud为平台的服务中心,充分共享有效的公共资源。B/S架构在分布式系统中也成为主流架构。ScadaCloud主要以Web和中间件作为基础支撑技术。

      ScadaCloud智能技术帮助用户在先进的基础设施和系统集成基础上,采用可持续、可靠、经济的方式便捷管理运营需求。同时,在用户重点基础设施中也处于指挥中心的地位,可以掌控电力、水和热力的供应,以及楼宇、基础设施自动化都等所有重点领域的运营。

       本文以将Ajax(Asynchronous JavaScript and XML)模式引入ScadaCloud中,并结合Ajax、SVG(ScableVectorGraphics)和Corba等多项技术,实现了异步交互机制。

2、ScadaCloud的技术与优势

1)、基础技术组成

  • WEB:HTML/Ajax/javascript;
  • 中间件:Corba;
  • 图形:SVG;
  • 开发语言:C++/C#/java。

2)、优势

  •  所有工作都在WEB浏览器上完成该,没有插件,工作站无需安装软件;
  • 丰富精美的基于SVG的可视化界面;
  •  跨平台、跨语言;
  •  完整的从端到云的解决方案;
  •  每个用户都相当于一套功能强大、全面的SCADA平台。

        实时监控系统中厂站视图中配置好的图形是一张简要的厂站单线图,后台系统需要这样一张图。因此,绘图工具提供了对矢量图形SVG的支持,可以将厂站视图导出为SVG图形文件,后台系统可以导入该图形直接利用。

3、SVG模块

1)、什么是SVG?

  • SVG 指可伸缩矢量图形(Scalable Vector Graphics);
  • SVG 用来定义用于网络的基于矢量的图形;
  • SVG 使用XML格式定义图形;
  • SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失;
  • SVG 是万维网联盟的标准;
  • SVG 与诸如DOM和XSL之类的W3C标准是一个整体。

2)、SVG 的历史和优势

        在2003年1月,SVG1.1被确立为W3C标准。参与定义SVG的组织有:太阳微系统、Adobe、苹果公司、IBM 以及柯达。与其他图像格式相比,使用SVG的优势在于:

  • SVG可被非常多的工具读取和修改(比如记事本);
  • SVG与JPEG和GIF图像比起来,尺寸更小,且可压缩性更强;
  • SVG是可伸缩的;
  • SVG 图像可在任何的分辨率下被高质量地打印;
  • SVG可在图像质量不下降的情况下被放大;
  • SVG图像中的文本是可选的,同时也是可搜索的(很适合制作地图);
  • SVG可以与Java技术一起运行;
  • SVG是开放的标准;
  • SVG文件是纯粹的XML。

        SVG的主要竞争者是Flash。与Flash相比,SVG最大的优势是与其他标准(比如XSL和DOM)相兼容。而Flash则是未开源的私有技术。今天,所有浏览器均支持SVG文件,不过需要安装插件的Internet Explorer 除外。插件是免费的,比如Adobe SVG Viewer。

3)、SVG 实例

        下面的例子是一个简单的SVG文件的例子。SVG文件必须使用.svg后缀来保存:

<?xml version="1.0"standalone="no"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG1.1//EN"

"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%"version="1.1"

xmlns="http://www.w3.org/2000/svg">

<circle cx="100" cy="50"r="40" stroke="black"

stroke-width="2" fill="red"/>

</svg>
        代码解释:

        第一行包含了XML声明。请注意standalone属性!该属性规定此SVG文件是否是“独立的”,或含有对外部文件的引用。standalone="no"意味着SVG文档会引用一个外部文件-在这里是DTD文件。第2和 3行引用了这个外部的SVG-DTD。

       该DTD位于“http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”。该DTD位于W3C,含有所有允许的SVG元素。

        SVG代码以<svg>元素开始,包括开启标签<svg>和关闭标签</svg>。这是根元素。width和height属性可设置此SVG文档的宽度和高度。version属性可定义所使用的SVG版本,xmlns属性可定义SVG命名空间。

        SVG的<circle>用来创建一个圆。cx和cy属性定义圆中心的x和y 坐标。如果忽略这两个属性,那么圆点会被设置为(0, 0)。r属性定义圆的半径。stroke和 stroke-width 属性控制如何显示形状的轮廓。我们把圆的轮廓设置为2px宽,黑边框。fill属性设置形状内的颜色。我们把填充颜色设置为红色。关闭标签的作用是关闭 SVG 元素和文档本身。

        注释:所有的开启标签必须有关闭标签!

4)、HTML 页面中的 SVG

        <embed>标签被所有主流的浏览器支持,并允许使用脚本。当在HTML页面中嵌入SVG时使用<embed>标签是Adobe SVG Viewer推荐的方法!然而,如果需要创建合法的 XHTML,就不能使用<embed>。任何HTML规范中都没有<embed>标签。

        语法:

        <embed src="rect.svg"width="300" height="100" type="image/svg+xml"

        pluginspage="http://www.adobe.com/svg/viewer/install/"/>

4、图符库实现

图4.1 有轨电车监控图

1)、SVG图符库原理

     如图4.1信号系统图形所示,动态图形主要包括信号机、轨道和道岔等设备。如我们可以把信号机的状态枚举,生成图符中的多状态图元。

2)、信号机图符

图4.2 信号机状态0

<symbolid="SIGNAL0">

            <circle fill="#999999"r="9.73177" id="svg_0" cx="10" cy="10"stroke="#000000"/>

            <circle fill="#999999"r="9.73047" id="svg_1" cx="10" cy="30"stroke="#000000"/>

            <circle fill="#999999"r="9.73047" id="svg_2" cx="10" cy="50"stroke="#000000"/>

            <rect x="4.00002"stroke-linecap="null" y="26.66667"transform="rotate(45, 10, 29.668)" fill="#b2b2b2"

                width="12"stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_3" stroke="#000000"/>

            <rect x="4.00132"stroke-linecap="null" y="47.0013"transform="rotate(90, 10, 50)" fill="#b2b2b2"width="12"

               stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_4" stroke="#000000"/>

</symbol>

图4.3 信号机状态1

<symbolid="SIGNAL1">

            <circle fill="#ff0000"r="9.73177" id="svg_5" cx="10" cy="10"stroke="#000000"/>

            <circle fill="#999999"r="9.73047" id="svg_6" cx="10" cy="30"stroke="#000000"/>

            <circle fill="#999999"r="9.73047" id="svg_7" cx="10" cy="50"stroke="#000000"/>

            <rect x="4.00002"stroke-linecap="null" y="26.66667"transform="rotate(45, 10, 29.668)" fill="#b2b2b2"

                width="12"stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_8" stroke="#000000"/>

            <rect x="4.00132"stroke-linecap="null" y="47.0013"transform="rotate(90, 10, 50)" fill="#b2b2b2"width="12"

               stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_9" stroke="#000000"/>

</symbol>

图4.4 信号机状态2

<symbolid="SIGNAL2">

            <circle fill="#999999"r="9.73177" id="svg_10" cx="10" cy="10"stroke="#000000"/>

            <circle fill="#ffff00"r="9.73047" id="svg_11" cx="10" cy="30"stroke="#000000"/>

            <circle fill="#999999"r="9.73047" id="svg_12" cx="10" cy="50"stroke="#000000"/>

            <rect x="4.00002"stroke-linecap="null" y="26.66667"transform="rotate(45, 10, 29.668)" fill="#ffffff"

                width="12"stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_13" stroke="#000000"/>

            <rect x="4.00132"stroke-linecap="null" y="47.0013"transform="rotate(90, 10, 50)" fill="#b2b2b2"width="12"

               stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_14" stroke="#000000"/>

</symbol>


图4.5 信号机状态3

<symbolid="SIGNAL3">

            <circle fill="#999999"r="9.73177" id="svg_15" cx="10" cy="10"stroke="#000000"/>

            <circle fill="#999999"r="9.73047" id="svg_16" cx="10" cy="30"stroke="#000000"/>

            <circle fill="#00ff00"r="9.73047" id="svg_17" cx="10" cy="50"stroke="#000000"/>

            <rect x="4.00002"stroke-linecap="null" y="26.66667"transform="rotate(45, 10, 29.668)" fill="#b2b2b2"

                width="12"stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_18" stroke="#000000"/>

            <rect x="4.00132"stroke-linecap="null" y="47.0013"transform="rotate(90, 10, 50)" fill="#ffffff"width="12"

               stroke-linejoin="null" stroke-dasharray="null"height="6" id="svg_19" stroke="#000000"/>

</symbol>

3)、图符引用说明

        <usex="33.00015" y="174.33333" symbol_name="#SIGNAL"width="80" xlink:href="#SIGNAL0"

        symbol_maxindex="3" id="ZXL_DT08_DN001_V01"height="100"/>

        本案例中增加两个私有属性:symbol_name和symbol_maxindex,symbol_name表示图元属于何种图符(所有名称要唯一定义),symbol_maxindex表示当前图符的最大状态索引值(从0开始)。id号也就是图符对应的实时数据库“点”值,后面章节会详细描述怎么操作图符,产生不同动态切换的效果。

4、中间件实现

         这一节主要讲述java与c++两种语言实现过程,本文只简述通用方法描述不同服务器之间的数据流处理过程,更复杂的业务处理,请您根据实际用户要求设计。

        Web服务器作为客户端与实时服务器交互数据,过程如下:

  • 初始化:  第一连接成功后,Web服务从实时服务器获取全数据;
  • 接收通知:当实时服务器有变化数据或告警,通知Web服务器;
  • 汲取数据:Web服务器根据通知的消息,从实时服务器获取最新的数据;
  •  心跳:    为防止网络中断等情况影响,使用alive或hello函数进行心跳探测。

        实时服务器作为服务端与Web服务器交互数据,过程如下:

  • 监听:    实时服务器监听管理所有连接的用户;
  • 数据接口:为Web服务器提供必要的接口;
  • 数据处理:与实时库交换,处理变化的数据,并及时各个连接的用户;
  •  心跳:    为防止网络中断等情况影响,使用alive或hello函数进行心跳探测。

1)、COBRA原理

        省略。

2)、接口文件定义(CloudDaqService.idl)

// **********************************************************************

//

// Copyright (c) 2014

// XXXXX有限公司

// 2014.05.07

// liuxuezong, PSD, Shanghai, China

// All Rights Reserved

//

//**********************************************************************

#ifndef _CLOUDDAQSERVICE_IDL_

#define _CLOUDDAQSERVICE_IDL_

 

//

// version 1.0.0

//

 

module CloudDaqService

{

      struct point_stream

      {

           stringpointcode;

           octettype;

           floatvalue;

      };

 

      typedefsequence <point_stream> pointStreamSeq;

 

      struct event_stream

      {

               octet type;         

           sequence<octet>value;

      };

 

      // Thisexception is raised every time a failure or error is

      //detected in a treatment.

      exception GeneralException

      {

           stringerror_msg;

      };

     

      interface EventHandler

      {

           void onNotify(in event_stream event);

          

           //@interface: EventHandler

           //@method   : alive

           //@purpose  : test is the EventHandler isagain instantiate and

           //             so if daq communication part isrunning

           //             if the call of the method pass,EventHandler is alive;

           //             else CORBA send an exceptionStateClosed.

           void alive(); 

      };

     

      interface RegAgent

      {

           void hello() raises(GeneralException);

 

           boolean write(in point_stream data) raises(GeneralException);

 

           boolean bulkWrite(in pointStreamSeq datum) raises(GeneralException);

 

           pointStreamSeq getPointsValue() raises(GeneralException);

 

           void setEventHandler(in EventHandler handler) raises(GeneralException);      

      };

 

      interface RegManager

      {         

           RegAgent createInterface(in string user) raises(GeneralException);

 

           void deleteInterface(in string user) raises(GeneralException);

      };

};

 

#endif

 

//

// EOF clouddaqservice.idl

//


3)、Web服务器作为Corba客户端

3.1)MeterRemote .java(Dwr定义的接口,后面将描述)

package com.test.ajax;

 

import org.directwebremoting.ScriptBuffer;

import org.directwebremoting.ScriptSession;

importorg.directwebremoting.ServerContextFactory;

import org.directwebremoting.Browser;

import org.directwebremoting.WebContextFactory;

import org.directwebremoting.ui.dwr.Util;

 

import java.util.Collection;

import java.util.List;

importjava.util.concurrent.ScheduledThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

 

public class MeterRemote implements Runnable

{

     static CloudService daqnsrv = null;

     protected transient boolean active = false;

     int nToggleNum = 0;

     static int nCount = 0;

 

     public MeterRemote()

    {

           ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);

           executor.scheduleAtFixedRate(this,1, 1, TimeUnit.SECONDS);

      }

 

    public void run()

    {

        if (active)

        {

             pageProc();

         }

    }

   

    public synchronized void toggle()

    {

           nToggleNum++;

           active= !active;

           System.out.println("toggleclicked!" + nToggleNum);

           System.out.println("active:"+ active);

           if (active)

           {

                 pageProc();

           }

      }

 

     public void pageProc()

     {

           Stringpage = ServerContextFactory.get().getContextPath() + "/index.jsp";          

           Browser.withPage(page,new Runnable()

           {

                publicvoid run()

               {                                

                      if (daqnsrv != null && daqnsrv.isRunning())

                      {

                            ScriptBufferscript = new ScriptBuffer();

                            intValue = nCount;

                            StringstrPointCode = "ZXL_DT08_DN001_V01";

                            List<pointdata>points = daqnsrv.peekDaqService();

                            if(!points.isEmpty())

                            {

                                 for(pointdata data : points)

                                 {

                                       strPointCode= data.getPointCode();

                                       Value = (int)data.getValue();

                                       script.appendCall("setObjectValue",strPointCode, Value);

                                 }

                                  Collection<ScriptSession>mySessions = Browser.getTargetSessions();

                                  for(ScriptSession scriptSession:mySessions)

                                  {

                                       scriptSession.addScript(script);

                                  }

                            }

                            nCount++;

                      }                    

                 }

           });

           if (daqnsrv == null)

           {

                 daqnsrv= new CloudService();

                 daqnsrv.startCorba();

           }

      }

}


3.2)、CloudService.java

package com.test.ajax;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import java.util.Properties;

import java.io.UnsupportedEncodingException;

import org.omg.CosNaming.*;

import org.omg.CORBA.*;

 

import org.omg.PortableServer.IdAssignmentPolicyValue; 

import org.omg.PortableServer.ImplicitActivationPolicyValue; 

import org.omg.PortableServer.LifespanPolicyValue;

import org.omg.PortableServer.POA;

import org.omg.PortableServer.POAHelper;

 

import CloudDaqService.EventHandler;

import CloudDaqService.EventHandlerHelper;

import CloudDaqService.RegAgent;

import CloudDaqService.RegManager;

import CloudDaqService.RegManagerHelper;

import CloudDaqService.point_stream;

 

public class CloudService

{

      privatestatic String lpArgs[];

      privatestatic RegAgent regAgent_;

      privatestatic RegManager regManager_;

      privatestatic DaqEventHandler eventhandler;

      privatestatic boolean bStartFlag = true;   

      privatestatic boolean bExceptionFlag = true;

 

      classCorbaProc implements Runnable

      {

       public void run()

        {

           System.out.println("CloudService的CorbaProc线程runstart!");

           while (bStartFlag)

           {        

                 try

                 {         

                      org.omg.CORBA.Object managerObj;

                      // 创建并初始化ORB

                      //String nameservice ="corbaloc::localhost:10003/NameService"; 

                        

                      // 生成一个ORB,并初始化,这个和Server端一样    

                      // Properties props = newProperties();

                      //props.put("org.omg.CORBA.ORBInitialPort", "10003");  

                      //props.put("org.omg.CORBA.ORBInitialHost","10.35.95.100");  

                      // ORB orb = ORB.init(lpArgs,props);

                      ORB orb = ORB.init(lpArgs, null);

                     

                      // 得到一个NameComponent类型的对象

                      // get the root naming context

                      org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");

                      // Use NamingContextExt instead ofNamingContext, 

                      // part of the Interoperablenaming Service.  

                      // NamingContextExt ncRef =NamingContextExtHelper.narrow(objRef);

 

                      NamingContextExt ncRef =NamingContextExtHelper.narrow(orb

                                   .string_to_object("corbaloc::localhost:10003/NameService"));

                      // nc的id域为FirstTimeSevice,kind域为空字符串

                      NameComponent name = newNameComponent("CloudDaqService", "");

                      NameComponent path[] = { name };                 

 

                      // 从命名服务上下文中获得特定的命名服务对象        

                      managerObj = ncRef.resolve(path);

                     

                      // Instantiate Servant and createreference

                      POA rootPOA =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));

                 

                   DaqEventHandler handler = newDaqEventHandler();

                   rootPOA.activate_object(handler);

                   EventHandler ref =EventHandlerHelper.narrow(

                       rootPOA.servant_to_reference(handler));

                                   

                      // Narrow the previous object toobtain the correct type

                      regManager_ =RegManagerHelper.narrow(managerObj);     

                          

                      regAgent_ =regManager_.createInterface("admin");

                

                      regAgent_.setEventHandler(ref);

                     

                      rootPOA.the_POAManager().activate();

                     

                      bExceptionFlag= false;

                     

                      orb.run();                      

                 }

                 catch (Exception e)

                 {

                      System.out.println("ERROR :" + e);

                      bExceptionFlag = true;

                 }                    

           }

           System.out.println("CloudService的CorbaProc线程runstop!");

        }

      }

     

      public CloudService()

      {

          

      }

 

      public boolean isRunning()

      {

           return (bExceptionFlag == false);

      }

     

      public void startCorba()

      {

           CorbaProc dataid = new CorbaProc();    

           Thread threadDataProc = new Thread(dataid);      

           threadDataProc.start();   

      }

     

      public List<pointdata> peekDaqService()

      {

           try

           {

                 if (regAgent_ == null)

                 {

                      returnnull;

                 }

                 List<pointdata>list = new ArrayList<pointdata>();

                 point_stream[]streamSeq = regAgent_.getPointsValue();

                 inti, nCount = streamSeq.length;

                 for (i = 0; i < nCount; i++)

                 {         

                      pointdatapt = new pointdata();

                      pt.setPointCode(streamSeq[i].pointcode);

                      pt.setValue(streamSeq[i].value);

                      list.add(pt);                    

                 }

                 returnlist;

           }

           catch (Exception e)

           {  

                 e.printStackTrace();

                 bExceptionFlag= true;           

           }

           returnnull;    

      }

}


3.3)、DaqEventHandler.java

package com.test.ajax;

 

import CloudDaqService.EventHandlerPOA;

import CloudDaqService.event_stream;

public class DaqEventHandler extendsEventHandlerPOA

{

      private static final long serialVersionUID = 1L;

 

      public DaqEventHandler()

      {

            

      }

 

      public void alive() {

           //TODO Auto-generated method stub

           intn = 0;

           n= 1;

      }

 

      public void onNotify(event_stream event) {

           //TODO Auto-generated method stub

          

      }    

}


3.4)、pointdata.java

package com.test.ajax;

 

import java.io.Serializable;

 

@SuppressWarnings("serial")

public class pointdata implements Serializable{

      private String pointcode;

      private int type;

      private float value;

 

      public float getValue() {

           returnvalue;

      }

      public void setValue(float value) {

           this.value= value;

      }

      public String getPointCode() {

           returnpointcode;

      }

      public void setPointCode(String pointcode) {

           this.pointcode= pointcode;

      } 

     

      public int getType() {

           returntype;

      }

      public void setType(int type) {

           this.type= type;

      } 

}


4)、实时服务器作为Corba服务端

3.1)RegAgent_impl

RegAgent _impl.h定义

#ifndef _REGAGENT_IMPL_H_

#define _REGAGENT_IMPL_H_

 

#include <OB/CORBA.h>

 

#if defined(_MSC_VER)

#pragma warning (disable : 4786)

#endif

 

#include <string.h>

#include <map>

#include <list>

 

#ifdef HAVE_STDLIB_H

#   include<stdlib.h>

#endif

 

#if defined(HAVE_STD_IOSTREAM) ||defined(HAVE_STD_STL)

using namespace std;

#endif

 

#include "clouddaqservice_skel.h"

using namespace CloudDaqService;

 

typedef map<int, int> StationStatusMap;

 

class RegAgent_impl : virtual publicPOA_CloudDaqService::RegAgent,

              publicPortableServer::RefCountServantBase

{

    PortableServer::POA_varpoa_;

public:

    RegAgent_impl(PortableServer::POA_ptrpoa);

             

    virtual ~RegAgent_impl();

 

    virtual PortableServer::POA_ptr

    _default_POA()

    {

        return PortableServer::POA::_duplicate(poa_);

    }

 

    virtual void hello()

       throw(GeneralException, CORBA::SystemException);

 

    virtualCORBA::Boolean write(const point_stream& data)

       throw(GeneralException, CORBA::SystemException);

 

    virtualCORBA::Boolean bulkWrite(const pointStreamSeq& datum)

       throw(GeneralException, CORBA::SystemException);

 

    virtual pointStreamSeq* getPointsValue()

       throw(GeneralException, CORBA::SystemException);

 

    virtual void setEventHandler(EventHandler_ptr handler)

       throw(GeneralException, CORBA::SystemException);

 

public:

      void onNotify(const event_stream &event);

 

      void alive();

 

      void destroy(void);

 
      bool checkException();   

 

private:

      JTCMutex         mutex_;        

 
      EventHandler_ptr Controller_;

 
      bool             bException_;

};

 

#endif // _REGAGENT_IMPL_H_

RegAgent _impl.cpp实现

#include "regagent_impl.h"

using namespace std;

 

RegAgent_impl::RegAgent_impl(PortableServer::POA_ptrpoa)

    :poa_(PortableServer::POA::_duplicate(poa))

{

    bException_= false;

}

 

RegAgent_impl::~RegAgent_impl()

{

}

 

void RegAgent_impl::hello()

    throw(GeneralException, CORBA::SystemException)

{

 

}

 

CORBA::Boolean RegAgent_impl::write(constpoint_stream &data)

   throw(GeneralException, CORBA::SystemException)

{

    return 0;

}

 

CORBA::Boolean RegAgent_impl::bulkWrite(constpointStreamSeq &datum)

   throw(GeneralException, CORBA::SystemException)

{

    CORBA::ULong nCount = datum.length();

    for (CORBA::ULong i = 0; i < nCount; i++)

    {

        point_stream data = datum[i];

        write(data);

    }

    return 0;

}

 

pointStreamSeq* RegAgent_impl::getPointsValue()

   throw(GeneralException, CORBA::SystemException)

{

    static intnCount = 0;

    pointStreamSeq_var lstRecord = new pointStreamSeq;

    long nSize= 1;

    lstRecord->length(nSize);

    point_stream data;

    data.type =1;

    data.pointcode = CORBA::string_dup("ZXL_DT08_DN001_V01");

    data.value = nCount++ % 5;

    lstRecord[0] = data;

    returnlstRecord._retn();

}

 

 

void RegAgent_impl::setEventHandler(EventHandler_ptrhandler)

   throw(GeneralException, CORBA::SystemException)

{

    Controller_ = EventHandler::_duplicate(handler);

}

 

void RegAgent_impl::onNotify(const event_stream&event)

{

    try

    {

        Controller_->onNotify(event);

    }

    catch (const CORBA::Exception &ex)

    {

        cerr<< ex << endl;

        bException_ = true;

    }

}

 

void RegAgent_impl::alive()

{

    try

    {

       Controller_->alive();

    }

    catch (const CORBA::Exception &ex)

    {

        cerr<< ex << endl;

        bException_ = true;

    }

}

 

void RegAgent_impl::destroy()

{

    // Get thePOA used when activating the Content_Iterator object.

    PortableServer::POA_var poa = this->_default_POA();

 

    // Get theobject ID associated with this servant.

    PortableServer::ObjectId_varoid = poa->servant_to_id(this);

 

    // Nowdeactivate the iterator object.

    poa->deactivate_object(oid.in());

 

    // Decreasethe reference count on our selves.

    _remove_ref();

}

 

bool RegAgent_impl::checkException()

{

    returnbException_;

}


3.2)RegManager_impl

RegManager_impl.h定义

#ifndef _REGMANAGER_IMPL_H_

#define _REGMANAGER_IMPL_H_

 

#include "regagent_impl.h"

 

typedef map<std::string, RegAgent_impl *>RegAgentMap;

 

class Worker;

 

class RegManager_impl : virtual public POA_CloudDaqService::RegManager,

      publicPortableServer::RefCountServantBase

{

      PortableServer::POA_varpoa_;

public:

      RegManager_impl(PortableServer::POA_ptrpoa);

 

      Virtual ~RegManager_impl();

     

      virtual PortableServer::POA_ptr

      _default_POA()

     {

        returnPortableServer::POA::_duplicate(poa_);

     }

     

     RegAgent_ptr createInterface(const char* user)

       throw(GeneralException, CORBA::SystemException);

 

     void deleteInterface(const char* user)

       throw(GeneralException, CORBA::SystemException);

 

public:

      void OnNotify(const event_stream &event);

     

      void alive();

 

      bool checkAgent();

 

      const int getAgentSize();

 

private:

      JTCHandleT<Worker>    workThread_;

      RegAgentMap           RegagentMap_;

      JTCMutex              mutex_;   

};

 

#endif //

#include "regmanager_impl.h"

 

class Worker : public JTCThread

{

    //

    //Has this thread been stopped?

    //

    boolstop_;

public:

   Worker(RegManager_impl *regManager)

        :regManager_(regManager), stop_(false)

    {

    }

 

public:

    voidrun(void)

    {

        while (!stop_)

        {

           if (regManager_->getAgentSize())

           {

               if (1)

               {

                    event_stream event;

                    event.type = 1;

                    event.value.length(32);

                    unsigned char *pData =event.value.get_buffer();

                    for (int i = 0; i < 32;i++)

                    {

                        pData[i] = i;

                    }

                    memcpy(event.value.get_buffer(), pData, 32);

                   

                    //regManager_->OnNotify(event);

               }

               //else

               {

                    regManager_->alive();

               }

               regManager_->checkAgent();

           }

 

            sleep(1000);

        }

    }

 

    voidstop()

    {

       stop_ = true;

    }

 

private:

   RegManager_impl *regManager_;

};

RegManager_impl.cpp实现

RegManager_impl::RegManager_impl(PortableServer::POA_ptrpoa)

    :poa_(PortableServer::POA::_duplicate(poa))

{

   workThread_ = new Worker(this);

   workThread_->start();

}

 

RegManager_impl::~RegManager_impl()

{

    //

    // Wait for all other threads to be finished

    //

    while (workThread_->isAlive())

    {

        try

        {

            workThread_->stop();

            workThread_->join();

        }

        catch (const JTCInterruptedException &)

        {

        }

    }

}

 

RegAgent_ptr RegManager_impl::createInterface(constchar *user)

   throw(GeneralException, CORBA::SystemException)

{

    /*

    *Create a new RegAgent (which is never deleted)

    */

   assert(user != NULL && strlen(user) > 0);

 

   JTCSynchronized guard(mutex_);

 

    RegAgentMap::iterator i;

    if ((i = RegagentMap_.find(user)) != RegagentMap_.end())

    {

       const std::string key = (*i).first;

       RegAgent_impl *pAgent = (*i).second;

       RegAgent_ptr aref = pAgent->_this();

       return aref;

    }

 

    RegAgent_impl *AgentIf = new RegAgent_impl(poa_);

 

    /*

    *Obtain a reference using _this. This implicitely activates the

    *RegAgent servant (the RootPOA, which is the object's _default_POA,

    * hasthe IMPLICIT_ACTIVATION policy)

    */

 

    RegAgent_ptr aref = AgentIf->_this();

    assert (!CORBA::is_nil (aref));

 

    RegagentMap_[user] = AgentIf;

 

    /*

    *Return the reference

    */

   return aref;

}

 

void RegManager_impl::deleteInterface(constchar *user)

   throw(GeneralException, CORBA::SystemException)

{

    assert(user != NULL);

 

    JTCSynchronized guard(mutex_);

    RegAgentMap::iterator i;

    for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)

    {

        const std::string key = (*i).first;

        const char *val = (const char *)key.c_str();

        RegAgent_impl *pAgent = (*i).second;

        if (strcmp(val, user) == 0)

        {

            pAgent->destroy();

            RegagentMap_.erase(i);

            return;

        }

    }

}

 

void RegManager_impl::OnNotify(constevent_stream &event)

{

    JTCSynchronized guard(mutex_);

    RegAgentMap::iterator i;

    if (getAgentSize() <= 0)

    {

        return;

    }

 

    for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)

    {

        const std::string key = (*i).first;

        RegAgent_impl *pAgent = (*i).second;

        if (pAgent && !pAgent->checkException())

        {

            pAgent->onNotify(event);

        }

    }

}

 

void RegManager_impl::alive()

{

    JTCSynchronized guard(mutex_);

    RegAgentMap::iterator i;

    if (getAgentSize() <= 0)

    {

       return;

    }

 

    for (i = RegagentMap_.begin(); i != RegagentMap_.end(); i++)

    {

        const std::string key = (*i).first;

        RegAgent_impl *pAgent = (*i).second;

        if (pAgent && !pAgent->checkException())

        {

            pAgent->alive();

        }

    }

}

 

bool RegManager_impl::checkAgent()

{

    JTCSynchronized guard(mutex_);

    boolbRet = false;

    if (getAgentSize() <= 0)

    {

       return bRet;

    }

    RegAgentMap::iterator j = RegagentMap_.begin();

    RegAgentMap::iterator last = RegagentMap_.end();

    while (j != last)

    {

        const std::string key = (*j).first;

        RegAgent_impl *pAgent = (*j).second;

        if (pAgent && pAgent->checkException())

        {

            pAgent->destroy();

            RegagentMap_.erase(j);

            bRet = true;

            break;

        }

       ++j;

    }

    return bRet;

}

 

const int RegManager_impl::getAgentSize()

{

    return RegagentMap_.size();

}


3.3)main.cpp

#include "stdafx.h"

#include <OB/CORBA.h>

#include <OB/CosNaming.h>

#include <OB/Properties.h>

#include "regmanager_impl.h"

 

#ifdef WIN32

#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")

#endif

 

using namespace std;

 

int Initialize()

{

    return 0;

}

 

void unInitialize()

{

  

}

 

//

// Signal handler for singal_com shutdown

//

#ifdef WIN32

BOOL handler(DWORD fdwCtrlType)

{

   switch (fdwCtrlType)

    {

    caseCTRL_C_EVENT:

       break;

    caseCTRL_CLOSE_EVENT:

       break;

    caseCTRL_BREAK_EVENT:

       break;

    caseCTRL_LOGOFF_EVENT:

       break;

    caseCTRL_SHUTDOWN_EVENT:

       break;

    }

    //

    //Terminate singal_com event loop

    //

    try

    {

       unInitialize();

    }

    catch(...)

    {

        // Can't throw here...

    }

   return TRUE;

}

 

#else

 

extern "C" void handler(int)

{

    //

    //Ignore further signals

    //

   struct sigaction ignore;

   ignore.sa_handler = SIG_IGN;

   sigemptyset(&ignore.sa_mask);

   ignore.sa_flags = 0;

 

    if (sigaction(SIGINT, &ignore, (structsigaction *)0) == -1)

       abort();

    if(sigaction(SIGTERM, &ignore, (struct sigaction *)0) == -1)

       abort();

    if(sigaction(SIGHUP, &ignore, (struct sigaction *)0) == -1)

       abort();

 

    //

    // Terminate signal_comc event loop

    //

    try

    {

       unInitialize();

 

    }

    catch(...)

    {

       // Can't throw here...

    }

}

#endif

 

//

// Install signal handler for signal_comshutdown

//

void install_signal_handler()

{

    //

    // Install signal handler for cleanup

    //

#ifdef WIN32

    BOOL rc = SetConsoleCtrlHandler((PHANDLER_ROUTINE)handler, TRUE);

    if (!rc)

    {

       abort();

    }

#else

   struct sigaction sa;          //New signal state

   sa.sa_handler = handler;      //Set handler function

   sigfillset(&sa.sa_mask);     // Mask all other signals while handler runs

   sa.sa_flags = 0 | SA_RESTART; // Restart interrupted system calls

 

    if (sigaction(SIGINT, &sa, (struct sigaction *)0) == -1)

       abort();

    if (sigaction(SIGHUP, &sa, (struct sigaction *)0) == -1)

       abort();

    if (sigaction(SIGTERM, &sa, (struct sigaction *)0) == -1)

       abort();

#endif

}

 

int main(int argc, char *argv[])

{ 

#ifdef WIN32

    HANDLE hMutex = ::CreateMutex(NULL, FALSE, "CloudDaqService");

    if (::GetLastError() == ERROR_ALREADY_EXISTS)

    {

       return 0;

    }

#endif

 

    //

    //Install signal handler for signal_com shutdown

    //

    install_signal_handler();

 

    Initialize();

 

    CORBA::ORB_var orb;

    try

    {

       // ORB initialization

       orb = CORBA::ORB_init(argc, argv);

       /*

        *Obtain a reference to the RootPOA and its Manager

       */

       

       CORBA::Object_var poaobj = orb->resolve_initial_references("RootPOA");

       PortableServer::POA_var root = PortableServer::POA::_narrow(poaobj);

       PortableServer::POAManager_var manager = root->the_POAManager();

       

       /*

        *Create a RegManager

       */

       RegManager_impl *regmgr = new RegManager_impl(root);

       

       /*

        *Activate the RegManager

       */

       

       PortableServer::ObjectId_var oid = root->activate_object(regmgr);

       CORBA::Object_var ref = root->id_to_reference(oid.in());

       

       /*

        *Acquire a reference to the Naming Service

       */

       

       CORBA::Object_var nsobj =

           orb->resolve_initial_references("NameService");

       

       CosNaming::NamingContext_var nc =

           CosNaming::NamingContext::_narrow(nsobj);

       

       if (CORBA::is_nil(nc))

        {

           cerr << "oops, I cannot access the Naming Service!"<< endl;

           exit (1);

        }

       

       /*

        *Construct Naming Service name for our SignalCommucation

       */

       

       CosNaming::Name name;

       name.length(1);

       name[0].id = CORBA::string_dup("CloudDaqService");

       name[0].kind = CORBA::string_dup("");

       

       /*

        *Store a reference to our Bank in the Naming Service. We use 'rebind'

        *here instead of 'bind', because rebind does not complain if the desired

        *name "CloudDaqService" is already registered, but silently overwritesit (the

        *existing reference is probably from an old incarnation of this server).

       */

       

       cout << "Binding CloudDaqService in the Naming Service ..." << flush;

       nc->rebind(name, ref);

       cout << "done." << endl;

       

       //regmgr->_remove_ref();

       

       /*

        *Activate the POA and start serving requests

       */

       

       printf("Running.\n");

       

       manager->activate();

       

       orb->run();

       

       /*

        *Shutdown(never reached)

       */

       CORBA::release(manager);

       CORBA::release(root);

    }

    catch (const CORBA::Exception &ex)

    {

       cerr << ex << endl;

    }

 

    if (!CORBA::is_nil(orb))

    {

        try

        {

            orb->destroy();

        }

        catch (const CORBA::Exception &ex)

        {

            cerr << ex << endl;

        }

    }

 

    unInitialize();

 

    return 0;

}


5、Ajax实现

1)AJAX概念

        AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。Ajax的概念由Jesse James Garrett所提出。

        传统的Web应用允许用户端填写表单(form),当提交表单时就向Web服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分HTML码往往是相同的。由于每次应用的沟通都需要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这导致了用户界面的回应比本机应用慢得多。

        与此不同,AJAX应用可以仅向服务器发送并取回必须的数据,并在客户端采用JavaScript处理来自服务器的回应。因为在服务器和浏览器之间交换的数据大量减少(大约只有原来的5%)[来源请求],服务器回应更快了。同时,很多的处理工作可以在发出请求的客户端机器上完成,因此Web服务器的负荷也减少了。

2)Dwr与SVG动态数据

        DWR(DirectWeb Remoting)是一个WEB远程调用框架。利用这个框架可以让AJAX开发变得很简单。客户端利用JavaScript直接调用服务端的Java方法,并返回值给JavaScript函数,就好像直接本地客户端调用一样。

2.1)index.jsp

<%@ pagelanguage="java" contentType="text/html; charset=utf-8"

  pageEncoding="utf-8"%>

<!DOCTYPEHTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<%

      String path = request.getContextPath();

%>

<metahttp-equiv="Content-Type" content="text/html;charset=utf-8">

<scripttype='text/javascript' src='dwr/engine.js'></script>

<scripttype='text/javascript' src='dwr/util.js'></script>

<scripttype='text/javascript' src='dwr/interface/MeterRemote.js'></script>

 

<scriptlanguage="javascript">

functionInit()

{

      dwr.engine.setActiveReverseAjax(true);

}

    

functionsetObjectValue(pointcode, value)

{

      var svgDocument = window.tramway.getSVGDocument();

      var Shape =svgDocument.getElementById(pointcode);

      var symbolname = Shape.getAttribute("symbol_name");

      var maxindex =parseInt(Shape.getAttribute("symbol_maxindex"));

      value = value % (maxindex + 1);

      var urlSymbol = symbolname +value.toString();

      Shape.setAttribute("xlink:href",urlSymbol);

}

 

</script>

</head>

 

<bodyonLoad="Init()" >

<buttonοnclick="MeterRemote.toggle();">启动/button>

<embedid="tramway" src="symbols.svg" width="1366"height="600" type="image/svg+xml" >

</body>

</html>   
        SVG文件为symboles.svg,该文件放在“D:\MyEclipse 8.6\testAjax\WebRoot”目录下。MeterRemote为java的类,该对象会主动调用脚本函数“setObjectValue”。

        SVG多状态图符根据传递的参数pointcode,利用svg的getAttribute函数获取当前图元对象(注意对象为null处理),再使用setAttribute函数修改xlink:herf的对象引用,从而产生图形显示的动态效果。

2.2)web.xml

<?xml version="1.0"encoding="UTF-8"?> 

<web-appversion="3.0"  

   xmlns="http://java.sun.com/xml/ns/javaee"  

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  

   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 

 <display-name></display-name>  

 <servlet> 

   <servlet-name>dwr-invoker</servlet-name> 

   <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> 

   <init-param> 

       <param-name>debug</param-name> 

       <param-value>true</param-value> 

   </init-param>

   <init-param>

       <description>是否激活反向Ajax</description>

              <param-name>activeReverseAjaxEnabled</param-name>
               
              <param-value>true</param-value>

              </init-param>

              <init-param>

                <description>在WEB启动时是否创建范围为application的creator</description>
                
                <param-name>initApplicationScopeCreatorsAtStartup</param-name>
                
                <param-value>true</param-value>

              </init-param>             

   <load-on-startup>1</load-on-startup>

 </servlet> 

 <servlet-mapping> 

   <servlet-name>dwr-invoker</servlet-name> 

   <url-pattern>/dwr/*</url-pattern> 

 </servlet-mapping> 

 <welcome-file-list> 

   <welcome-file>index.jsp</welcome-file> 

 </welcome-file-list> 

</web-app> 


2.3)dwr.xml

<?xml version="1.0"encoding="UTF-8"?> 

<!DOCTYPE dwr PUBLIC"-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd"> 

<dwr>

<allow>

<create creator="new"javascript="MeterRemote" scope="application">

<param name="class"value="com.test.ajax.MeterRemote"></param>

</create>

</allow>

</dwr>

图5.1 “com.test.ajax.MeterRemote”目录

         <create creator="new"javascript="MeterRemote" scope="application">

MeterRemote即3.1节的类MeterRemote.java。

         <param name="class"value="com.test.ajax.MeterRemote"></param>

com.test.ajax.MeterRemote即Value目录与图5.1源文件MeterRemote.java目录一致。

6、ScadaCloud结构图

    省略。

7、结论

    省略。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值