ナビゲーションをスキップする
All Places > All Things PI - Ask, Discuss, Connect > Japan PI Square > ブログ > 2017 > June
2017

機能の動作の確認、社内のデモのために、データの作成が必要なケースがあります。

 

そのために、色々なオプションがあります。

 

などあります。

 

今回はAF Analysisを使い、デモダータを作成したいと思います。

 

事前に準備した一分のデータをテーブルで作成しました。(このデータをExcelで作成しました)

 

このAFテーブルの定義です。

 

このデータを表示できる属性を作成します。データはAFテーブルに保存されているので、Table Lookのデータ参照を作成し、下記の定義を設定します。

他のテーブルデータ参照と違って、Whereの条件を使わずにAFテーブルに時系列データがあると設定します。

この属性のトレンドをPSEで下記のように表示されます。データは2017/01/01 00:00:00から2017/01/01 00:01:00までにだけあるので、この間だけにトレンドが現れます。

同じトレンドをループするために、AF Analysisで下記の分析を設定します。

一行目は現在の秒数を使用し、新しいタイムスタンプを作成します。このタイムスタンプはAFテーブルにあるタイムレンジの間にあります。

二行目では、モデルの属性の値を取得します。

 

この設定を使うと下記のデータを作成できます。

以前、PIタグの値をAFSDKのフォームアプリケーションから削除するサンプルをJapan PI Squareにポストしました。

AFSDKでPI Data Archiveのタグの値を削除するサンプル

今回は同様の動きをPI Web APIを使ってウェブから実現したく、このサンプルを作成しました。(クライアントはLinuxOSを想定しています)

HTMLファイルとJavaScriptファイルを作成し、Windows MachineのIISでホストするようにしました。

このウェブページからイベントを削除することが可能です。

CentOS (Linux)のクライアントマシンがあるので、そこからイベントの削除が可能です。

このサンプルではBasic認証を使用しているため、LinuxからアクセスしてもPI Web APIは動作します。

このウェブページは"Search Tags"ボタンにPI Web API Search Crawlerを使用しています。

”Delete Events”ボタンにはバッチリクエストでイベントを削除するようになっています。

(PI Web API search crawlerは"Basic認証"では動作しない点にご注意ください。Basic認証を使用すると、参照することは可能ですが、新たなタグが追加されても、アップデートされることはありません。

Basic認証を使用して、最新のCrawler結果を使用したい場合、Indexed Search Shared Index CTPが使用できます。https://techsupport.osisoft.com/Downloads/File/53b2552a-2d62-4ae0-aa75-82b02c5a0ac6)

実際のファイルのコードは以下です。

 

Index.html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
  <meta name="viewport" content="width=400"/>
  <script type="text/javascript" src="http://code.angularjs.org/angular-1.0.1.js"></script>
  <script src="app.js"></script>
  <title>Delete Tag Events</title>  
</head>

<body ng-app="myApp">
    <div ng-controller="MyCtrl" >
        Search Tag Name : <input type="Text" ng-model="tagmask"><br>
        <button class="test" type="button" ng-click="searchtags()">
        <span class="ng-scope">Search Tags</span>
        </button>
        <div ng-show="TagSearchResult">
            <hr>
            Search Tag Results:<br>
            <div ng-repeat="item in search_items">
                {{item.Name}}
            </div>
            <hr>
            Start Time : <input type="Text" ng-model="starttime"><br>
            End Time : <input type="Text" ng-model="endtime"><br>
            Max delete event count : <input type="Text" ng-model="maxdelevnum" style="width:40px;">
            <br>
            <button class="test" type="button" ng-click="delete()">
            <span class="ng-scope">Delete Events</span>
            </button>
        </div>
        <div ng-show="DelResult">
            <hr>
            Delete Event Results:<br>
            <div ng-repeat="item in del_items">
                {{item.Content.Name}} 
                : Deleted {{item.Content.Count}} events
            </div>
            <hr>
        </div>
    </div>
</body>
</html>

app.js ( var servername ="localhost";の部分を自分の環境のPI Web API Server名に変更してください。もしBasic authenticationを使用する場合、XXXXXの部分も入れてください。)

angular.module('myApp', [])
.controller('MyCtrl', ['$scope','$http', function($scope,$http) {
    //Set PIWebAPI Server Name
    var servername ="localhost";
    //Basic Authentication
    //put the 64bit encoded (username:password) to the XXXXXXXXXXXXXXXXXXXXXXXXXXXXX for using Basic Authentication.
    $http.defaults.headers.common['Authorization'] = "Basic " + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    $http.defaults.headers.common['Content-Type'] = 'application/json';
    // Default values
    $scope.tagmask = "sin*";
    $scope.starttime = "*-8h";
    $scope.endtime = "*";
    $scope.maxdelevnum = "50000";
    $scope.TagSearchResult = false;
    $scope.DelResult = false;
    
    //"Search Tags" Button
    $scope.searchtags= function(){
        var batch_searchtags = {  
            "searchTags": {  
                "Method": "GET",  
                "Resource": "https://" + servername + "/piwebapi/search/query?q=name:"+$scope.tagmask +"&fields=Name"
            }
        }
        $http.post("https://" + servername + "/piwebapi/batch", batch_searchtags, {}).success(function(response) {
            $scope.search_items = response.searchTags.Content.Items;
        });
        //display the results
        $scope.TagSearchResult = true;
    };


    //"Delete Events Button
    $scope.delete= function(){
        var batch_data = {
            "searchTags": {  
                "Method": "GET",  
                "Resource": "https://" + servername + "/piwebapi/search/query?q=name:" + $scope.tagmask + "&fields=Name;Links"
            },  
            "getTagInfo": {  
                "Method": "GET",  
                "RequestTemplate" : {"Resource": "{0}?selectedfields=Name;Links.RecordedData"},
                "ParentIds": ["searchTags"],  
                "Parameters": ["$.searchTags.Content.Items[*].Links.Self"]  
            },
            "getData":{
                "Method" : "GET",
                "RequestTemplate" : {
                    "Resource": "{0}?maxCount=" + $scope.maxdelevnum + "&selectedfields=Items.Timestamp;Items.Value&StartTime="
                     + $scope.starttime + "&EndTime=" + $scope.endtime 
                },
                "ParentIds": ["getTagInfo"],
                "Parameters" : ["$.getTagInfo.Content.Items[*].Content.Links.RecordedData"]
            }
        }
        $http.post("https://" + servername + "/piwebapi/batch", batch_data, {}).success(function(response) {
            $scope.del_items = response.getTagInfo.Content.Items;
            //Tags loop
            var del_data_body="";
            for (var i = 0; i < response.getTagInfo.Content.Items.length; i++) {
                $scope.del_items[i].Content.Count = response.getData.Content.Items[i].Content.Items.length;
                del_data_body= response.getData.Content.Items[i].Content.Items;
                var tagaddress = response.getTagInfo.Content.Items[i].Content.Links.RecordedData + "?updateOption=remove";
                $http.post(tagaddress, del_data_body, {}).success(function(response) {
                    //alert("success to delete");
                })
            }
        });
        //display the results
        $scope.DelResult = true;
    }
}]);

 

PITagのイベントの削除はPI Data Archiveのパフォーマンスに影響することに注意してください。

また、このウェブサイトで200,000イベントを削除しようとするとエラーとなりました。

CentOSのFirefoxのブラウザから100,000イベントを削除することは可能でした。

ソースコードはGithubに挙がっています。

GitHub - kenji0711/PIWebAPIDeleteEvents

 

PI Data Archiveがテスト用、または開発用のものであればこのツールをご使用いただけます。

本番機にてPI Web API/AFSDKなどをご使用になる場合、End UserがPSA Licenseを持っている必要があります。

本サンプルは Jerome Lefebvre と共に作成しました。

LinuxOSにてApatchを使用して、このページをホストすることもテストしました。問題なく動作します。

その際には、認証はPI Web APIを使用するため、LinuxOSではなく、クライアントマシンからPI Web API Serverに対して認証されることになります。