使用C#進行基於PI的開發

來源:互聯網
上載者:User

標籤:

 

首先欲基於PI-SDK開發PI資料庫,必須先安裝PI-SDK,然後再VS中建立了一個aspnet網站,添加引用:PI-SDK 1.2 Type Library 和 PISDKCommon 1.2 Type Library

花了很多時間在PISDK下面找了一個能執行個體化的類PISDKClass,後來又發現原來Servers 是這個對象的一個屬性.

private PISDK.IPISDK piSDK= new PISDK.PISDKClass();

private PISDK.Server _piServer;

private PISDK.PIPoint _piPoint;

在Page_Load事件枚舉所有的資料來源,添加到DropSownlist.

foreach(PISDK.Server item in piSDK.Servers)

{

DropDownList1.Items.Add(srv.Name);

}

設定_piServer為dropdown裡面選中的資料庫

_piServer = piSDK.Servers[DropDownList1.Text];

然後下面接著防置一個文字框來讀取使用者輸入的Tag點,Tag有點相當於普通資料庫的欄位.但是又不一樣,關於這個暫時不細說了

和一個ListBox來得到這個Tag的所有屬性.代碼如下:

_piPoint = _piServer.PIPoints[tbxTagName.Text];

ListBox1.Items.Clear();

foreach (PISDK.PointAttribute ptatr in _piPoint.PointAttributes)

{

ListBox1.Items.Add(ptatr.Name);

}

讀取Tag屬性的值可以用下述屬性.

tbxAttValue.Text = _piPoint.PointAttributes[ListBox1.Text].Value.ToString();

如果要更新這個屬性的值呢?仍然很簡單

PISDK.PointAttribute ptatr;

_piPoint = _piServer.PIPoints[tbxTagName.Text];

ptatr = _piPoint.PointAttributes[lblAttrName.Text];

_piPoint.PointAttributes.ReadOnly = false;

ptatr.Value = tbxAttValue.Text;

_piPoint.PointAttributes.ReadOnly = true;

blNotion.Text = "更新成功!";

其實最後一句想用MessageBox可惜在asp.net下面一直找不到好的使用MessageBox的方法,原來在CodeProject上面找了一個,但是因為後來發現在Atlas的updatepanel中不能使用,也就作罷了

OK,上面就是我根據SDK-Manual裡面的一個Basic例子,用C#改寫了一下,實現了和例子一樣的功能,雖然今天花費了

下面是一個簡單的和SDK的對比:

首先欲基於PI-SDK開發PI資料庫,必須先安裝PI-SDK,然後再VS中建立了一個aspnet網站,添加引用:PI-SDK 1.2 Type Library 和 PISDKCommon 1.2 Type Library

接著看文檔上面VB的例子代碼是

Option Explicit

Dim srv as Server

Dim pt As PIPoint

for Each srv In Servers

Combo1.AddItem srv.Name

Next srv

為了把這兩個地方改成能運行得C#代碼還花費了不少力氣,因為原來沒有做的東西都是很簡單的.net東西,基本上沒有用到過和COM組件進行互動.首先說什麼不能執行個體花,接著又說什麼Servers不行,花了很多時間在PISDK下面找了一個能執行個體化的類PISDKClass,後來又發現原來Servers 是這個對象的一個屬性.

private PISDK.IPISDK piSDK= new PISDK.PISDKClass();

private PISDK.Server _piServer;

private PISDK.PIPoint _piPoint;

在Page_Load事件枚舉所有的資料來源,添加到DropSownlist.

foreach(PISDK.Server item in piSDK.Servers)

{

DropDownList1.Items.Add(srv.Name);

}

設定_piServer為dropdown裡面選中的資料庫

_piServer = piSDK.Servers[DropDownList1.Text];

然後下面接著防置一個文字框來讀取使用者輸入的Tag點,Tag有點相當於普通資料庫的欄位.但是又不一樣,關於這個暫時不細說了

和一個ListBox來得到這個Tag的所有屬性.代碼如下:

_piPoint = _piServer.PIPoints[tbxTagName.Text];

ListBox1.Items.Clear();

foreach (PISDK.PointAttribute ptatr in _piPoint.PointAttributes)

{

ListBox1.Items.Add(ptatr.Name);

}

讀取Tag屬性的值可以用下述屬性.

tbxAttValue.Text = _piPoint.PointAttributes[ListBox1.Text].Value.ToString();

如果要更新這個屬性的值呢?仍然很簡單

PISDK.PointAttribute ptatr;

_piPoint = _piServer.PIPoints[tbxTagName.Text];

ptatr = _piPoint.PointAttributes[lblAttrName.Text];

_piPoint.PointAttributes.ReadOnly = false;

ptatr.Value = tbxAttValue.Text;

_piPoint.PointAttributes.ReadOnly = true;

blNotion.Text = "更新成功!";

其實最後一句想用MessageBox可惜在asp.net下面一直找不到好的使用MessageBox的方法,原來在CodeProject上面

1>應用SDK從PI資料庫讀取資料

上一次的例子是通過PI-SDK擷取Tag的屬性並且修改它,我想更重要的是怎麼取出Tag的值和進行更新吧。在進行嘗試之前看了看文檔,瞭解了一下PISDK的對象結構,下面這一張就是PISDK的結構圖

 

簡要瞭解在例子中要用到的對象,並把它們的描述進行了簡單的翻譯,我想翻譯的目的應該是協助自己更好的進行學習,給出英文對照。不妥之處,忘大牛們指正:

 

//**********************本文開始*************************************************/

The Server object represents a single server (data archive). Server objects are retrieved from the Servers collection and provide access to the basic entities represented on each server, such as points, point classes, digital states, users, and groups. Some basic properties are available from the Server object as initially retrieved from the Servers collection.

    Typically a program will require a network connection to the server. Connections are established either by calling the Open method of the Server object explicitly or by accessing a property or calling a method of the Server object that requires server access, forcing an implicit connection.

    Many of the services available through the Server object are accessed through its properties which return other objects. For example, the PIPoints property provides a PIPoints collection object for accessing the various points on a server.

    伺服器(Server)對象表示了一個單獨的PI資料庫伺服器,伺服器對象可從伺服器集合中獲得並且提供了訪問每個資料庫中的實體的方法,這些實體包括點,點集合,數字量(開關量),使用者和組。伺服器對象提供了一些基本的屬性從而在伺服器集合中隊伺服器進行初始化。

      一般地,程式串連到伺服器需要網路連接屬性,這個串連可以通過伺服器對象的Open方法顯式的進行,也可以通過伺服器對象的某個屬性或方法串連需要驗證的伺服器來進行一個隱式的串連。

上面這一段有點不太懂,直到目前我都沒有用過顯式的Open方法,都是通過

    _piServer = piSDK.Servers.DefaultServer;

    這種所謂的隱式方法來串連,這個是不是就是所謂的隱式串連?因為在PISDK安裝的時候指定了一個PI資料來源,所以DefaultServer就是這個?所以我訪問的時候都不需要輸入使用者或者密碼

       我們可以通過伺服器對象的屬性來返回其他的對象從而獲得很多服務。例如,通過伺服器對象的PIPoints屬性返回的PIPoints集合的對象來訪問資料庫裡面的不同的點。

 

A PIConstant collection maps display strings to PI-SDK enumerations. This provides a way for an application to display strings indicating choices of behavior for a user to select particular actions. The application then retrieves the associated constant and passes it to a particular method being called. A PIConstant collection contains members, stored and accessed as NamedValue objects that represent the display string (the name) and the constant (the value). A PIConstant collection is retrieved using PISDK.PIConstants.Item.

       PIConstant集合映射字串到PI-SDK枚舉。(使字串和枚舉的項一一對應)。它為程式提供了字串來代表使用者選擇的一個特殊的操作,然後程式可以把這個字串對應的值獲得並且把它傳送到使用的方法裡面去。PIConstant集合包含了Members(不知道什麼意思),存貯和訪問NamedValue對象。NamedValue對象是一個字串(名字)-常量(數值)對。PIConstant集合中的對象通過PISDK.PIConstants.Item來擷取

       我覺得這個PIConstant集合就是相當於在C#中用DialogueResult枚舉中用OK代表某個具體的意思。具體代表的東西我們不用關心,知道是什麼就可以了。NamedValue就是一個字串-常量對,有點像一個字典吧,最後一句話說PISDK.PIConstants.Item來擷取PIContant,但是我在C#中PISDK.PIConstants沒有Item屬性,反而使直接通過PISDK.PIConstants[Name]取到。同時NamedValue是在PISDKCommon命名空間下面

       The PIPoint object represents a point on a PI Server. The PIPoint is the primary access point to data on the Server as well as configuration of a point‘s properties. 

       PIPoint對象表徵PI資料庫裡面的點,PIPoint是訪問資料庫裡面點的值和屬性的主要方法。

       The PIData object is associated with a single PIPoint and is used to send and retrieve values to and from the server. It is accessed through the Data property of the PIPoint.

       PIData對象是和單獨的PIPoint聯絡的,它從伺服器擷取資料或者寫回資料到伺服器。它通過PIPoint的Data屬性得到。

    我們知道PI資料庫的資料分別儲存在Snapshot或者Archive中,一個是快照一個是檔案檔案,這樣做是為了方便PI資料庫對資料進行壓縮.那麼自然對資料庫的讀取也分為對Snapshot和Archive讀取.snapshot和archive的值都是用PIValue的形式表示的, PIValue對象包括了數值和時間。應用SDK從資料庫中擷取snapshop或者archive的值很簡單。

    首先串連資料庫,聲明一個PIServer:_piServer = piSDK.Servers.DefaultServer;

    然後利用PIServer的Points屬性訪回一個點的集合,再通過tagName來擷取點:PIPoint pt = _piServer.PIPoints[tbxTagName.Text];

    如果是使用Snapshot,直接聲明一個PIValue通過PIPoint的Snapshot屬性來傳回值:pv = pt.Data.Snapshot;

    然後我們就可以通過PIValue的Value屬性和TimeStamp屬性來擷取snapshot的值和該值對應的時間了。

        tbxValue.Text = pv.Value.ToString();

        tbxTime.Text = pv.TimeStamp.LocalDate.ToString();

    如果要讀取Archive的值,那麼要稍微麻煩一點,應為你要給定讀取的時間和模式,PIPoint對象的ArcValue方法是用來擷取Archive的值,協助的說明如下:

        object.ArcValue TimeStamp, Mode, AsynchStatus

    這個應該是VB的文法吧,我們可以看出他有三個參數。第一個是時間,C#中我們可以直接傳一個DateTime格式的資料進去,當然你也可以使用 PITime對象表示的時間,或者一個字串。Mode代表取出的模式,因為PI資料庫並不是每個時間都存有資料的,所以在你可以選擇模式是讀取你輸入時間的當前點,後面一個點,前面一個點或者插值表示的時間。最後一個參數不解,文檔裡面沒有說明,VB的例子則直接沒有傳這個參數,應該是一個選擇性參數,我的處理方法如下。

        RetrievalTypeConstants rtType;

        rtType = (RetrievalTypeConstants)piSDK.PIConstants["RetrievalTypeConstants"][cbxValue.Text].Value;

        pv = pt.Data.ArcValue(dt, rtType, new PISDKCommon.PIAsynchStatus());

    RetrievalTypeConstants 就是表示存模數式的,我這裡使用過一個下拉式清單方塊獲得可用的模式的,最後一個參數是通過傳一個新的執行個體下去,這裡不知道這樣和不合理,反正可以讀出資料我就沒有管了,又沒有達人解釋一下怎麼處理這種VB的選擇性參數的情況呢?我學著VSTS的那種Type.Missing又不可以。

    然後讀出來的PIValue同樣包含一個數值和一個時間,現在我想大家應該理解為什麼PIValue裡面要包含一個時間了吧。

    我覺得應用SDK很簡單,感覺和開發Excel很象,都是調用Com,也挺符合.net的開發習慣的,文檔也好,每個對象還有一個詳細的VB例子,雖然不是.net的,但是也可以大致瞭解得差不多。

 

2>應用SDK向PI資料庫寫入資料

    在PIData對象中有一個UpdateValue方法和UpdateValues方法,顧名思義,一個是更新單個資料,一個是更新一批資料。但是文檔裡面紅紅的標著Not Implemented兩個單詞,心頓時涼了,考慮到文檔的版本比我實際使用的SDK版本第一點,去Object Browser裡面搜尋了一下,果然找到了這個方法

       public virtual void UpdateValue(object newValue, object TimeStamp, PISDK.DataMergeConstants MergeType, PISDKCommon.PIAsynchStatus asynchStatus)

    這些參數的意思沒有文檔也挺好理解的,這裡就不說了,可是當我嘗試用這個方法去更新資料庫的時候,一樣拋出了Not Implemented的錯誤,當時心裡非常的鬱悶,這個也就是開頭我說到的麻煩。我的SDK的版本是1.2.0,問了一個比較有經驗的人,他說他沒有遇到過不能寫入的問題,等有時間去問問他,看看是不是版本的問題,如果有人能寫入的,請給我說一下你們的版本;

 

 

3>應用API從PI資料庫讀取資料

    SDK不行,還好我們還有PI-API,這個感覺和Win32 API挺象的吧,都是一寫用C寫的函數,PISDK其實就是把PIAPI封裝了一下,可惜我對P/Invoke不怎麼熟悉,如果大家對這個也不熟悉的話,我覺得這兩篇文章還是不錯,作為預備知識。

    在C#中通過P/Invoke調用Win32 DLL

    如何在C#中使用Win32和其他庫

    這兩篇文章看了我還是頗有收穫的,至少知道參考型別在傳遞的時候不需要ref關鍵字,因為在.net中本身就是按地址傳遞的,呵呵,可能是基礎知識太差。

    不過看API的文檔和SDK的文檔相比真是天壤之別,API文檔只有一個簡單的概述,例子也沒有,參數的說明更是往往只有一句話,不過還好吧,我慢慢的試還是試出來了一些。

    對於資料讀取和寫入還是分為snapshot和archive,就是兩個不同的函數,參數也差不多類似。

    PI-API函數是按組分開的,有Point函數,Archive函數和snapshot函數等。

    從archive資料庫讀取資料有兩個,一個是擴充函數,功能多一些,所以我們在這裡使用的是擴充函數來讀取資料,其文檔的聲明如下:     

        int32 PIPROC piar_getarcvaluex(

      int32 ptnum,

        int32 mode,

      float64 PIPTR *drval,

      int32 PIPTR *ival,

      void PIPTR *bval,

      uint32 PIPTR *bsize,

        int32 PIPTR *istat,

      int16 PIPTR *flags,

        PITIMESTAMP PIPTR *time);

    int32,uint32這些都是PIAPI裡面自己定義的類型,從名字可以很簡單的看出他們對應32位整數,32位不帶正負號的整數,在C#中這些,.net已經給我們定製好了,還比較方便。

    PITIMESTAMP 是一個結構體,定義很簡單,我們直接在C#中定製一個類似的結構就好了。

    ptnum是PI tag號對應的一個Int32位的整數來代表資料庫中的一個點,可以通過API函數pipt_findpoint把Tag名字轉換成ptnum。

    mode和SDK裡面的模式很類似,就是看是讀取前面一個點,還是後面一個點的值。

    如果讀取出來的是浮點值,drval就是這個值;如果讀取出來的是整型值,ival就是這個值;bval是一個字串,bsize是這個字串的緩衝區大小,istat是代表數值量的值,flags文檔上面的說明是

Data quality flag mask不解。time是值對應的時間,相當於SDK裡面的pv.TimeStamp.LocalDate。

    對於字串,這裡我看了半天,因為string類型是一個不定長的字串,所以是不能用在這個地方的,這個地方的bval應該是使用 StringBuilder,StringBuilder.Capacity就表示了bsize,這一點還是衝上面那兩篇文章看到的,真是基礎差,呵呵。

    對於void指標,我是把它處理成為object類型,因為我們基本上不用到字串的值,所以這裡我也沒有測試,達人指導一下,呵呵。綜上,我的C#格式的函數是

        [DllImport("piapi32.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.StdCall)]

        public static extern Int32 piar_getarcvaluex(

            Int32 ptnum,

            Int32 mode,

            ref Double drval,

            ref Int32 ival,

            [MarshalAs(UnmanagedType.AsAny)] object bval,

            ref UInt32 bsize,

            ref Int32 istat,

            ref Int16 flags,

            ref PITime.PITIMESTAMP time);

    第五個參數必須Mashall成AsAny類型,要不直接使用object類型是不行的。那麼我怎麼知道他是Any類型呢?因為文檔上面VB的函數調用聲明是bVal As Any,這也是一點靈感吧。至於返回的Int32值是代表調用是否成功的,就和win32 API類似吧。

使用C#進行基於PI的開發

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.