SCADACLOUD智能平臺實現技術

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、結論

    省略。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章