(This note and the code comments are in Japanese and I do not intend to translate it to English, but the latest version of the code is posted on GitHub. The code should be readable enough that if you ignore all the comments, I believe it would still be a useful (but very brief) intro to using python to make requests against PI Web API.)

PI Web APIの特徴はプログラミングの言語とプラットホームを自由に選べることです。

 

Pythonを使い、PI Web APIのGETのリクエストの例を紹介したいと思います。

更に、テスト環境でよく使われている自己署名証明書についての設定も紹介します。

 

構成:python3 (3.5.0のみテスト)

pipのパッケージ: requests (2.8.1のみテスト)

Requestsについてパッケージのホームページは参考になります。

 

コードの最新版はGitHubに乗せていますので、ご参考ください。

 

■ 基本のコード

import json

import requests
# PI Web APIのリクエストはHTTPSが必要ですが、
# テストの環境では、PI Web APIのサーバーに自己署名証明書しかないことが多いです。
# この場合、HTTPSのリクエストをするとrequestsのパッケージか警告またはエラーが発生します。
# 下記の行は警告を無視するためです。
requests.packages.urllib3.disable_warnings()

# PI Web APIのサーバー名を記入してください。
piwebapi_server = ''
base_url = 'https://' + piwebapi_server + '/piwebapi/'

# PI Web APIにて認証は三種類ありますが、このポストではKerberosについては言及しません。
# Basic認識を使う場合はユーザー名とパスワードを送る必要があります。
# Anonymousを使う場合は下記のように空白でよいです。
user = ''
password = ''

def pi_get_requests(action, parameters={}):
  # pi_get_requestsの関数は変数として:
  # actionにelement、assetdatabasessetなどのController(Method)名か
  #   
  # parametersに"Url Parameters"を設定する

    # verify=Falseのパラメーターは自己署名証明書しかない環境では
    # エラーを発生させないためのパラメーターです。
    response = requests.get(url=base_url + controller,
                            params=parameters,
                            verify=False,
                            auth=(user, password))
    return json.loads(response.text)

# pi_get_requestsを綺麗に出力するため
def pprint(response):
    print(json.dumps(response, indent=4, sort_keys=True))

 

このポストで使用しているpi_get_requestsの構成は、piwebapi/helpのActionの構成を模倣するように設計されています。

 

■使用例

piwebapi/help/controllers/assetserversのページを見るとGet、GetByPathなどのActionsがあります。

 

ヘルプを参照すると、GetByPathのActionについて下記の情報が見つかります。

GetByPath
GET assetservers

URL Parameters

  • path

 

このヘルプから分かることは以下です:

  • Getのリクエストを使う
  • Controllerはassetserversです
  • Parameters(変数)はpathの変数のみがある

 

Pathの変数はAF Serverのパスになります。

# AF Server名を記入してください。
af_server_name = ''
parameters = {'path': r'\\' + af_server_name}
af_server = pi_get_requests('assetservers', parameters)

 

assetserversの他のActionにはGetがあります。

Get
GET assetservers/{webId}

Getの場合はWebIDが必要ですが、上記のaf_serverの変数から取得できます。

pi_get_requestsの第1引数にcontroller名+WebIDを設定し、第2引数のパラメーターは無しとすることでAF Serverの情報が取得できます。

webID = af_server['WebId']
pi_get_requests(r'assetservers/' + webID) == af_server # True

 

上記の例でWebIDを除くとすべてのAF Serverが取得できます。

allServers = pi_get_requests('assetservers')

 

■あるデータベースのエレメントを反復する

 

# piwebapi/help/controllers/assetdatabase/actions/getelementsによると
# あるデータベースのエレメントを収集したい場合は下記の様に収集できます。
# GET assetdatabases/{webId}/elements
af_server = ''
af_database = 'Pumps'
parameters = {'path': r'\\' + af_server + '\\' + af_database}
pump_db_web_Id = pi_get_requests('assetdatabases', parameters)['WebId']


# assetdaabases/{webId}/elementsのURLを作成し、
# エレメントを反復する
pumps = pi_get_requests('assetdatabases\{0}\elements'.format(pump_db_web_Id))


for element in pumps['Items']:
    print(element['Name'], element['TemplateName'])

web_Id))  for element in pumps['Items']:     print(element['Name'], element['TemplateName'])

 

■デバッグの情報

エラーが発生すると、レスポンスのヘッダーなどを見て何かあったと分かるケースが多いので、

pi_get_requestsを下記の様に編集するとこの情報が出力できます。

def pi_get_requests(controller, parameters={}, debug=False):
   # pi_get_requestsの関数は変数として:
   # controllerにelement、assetdatabasessetなどのController(Method)名
   # parametersに"Url Parameters"を設定する

    # verify=Falseのパラメーターは自己署名証明書しかない環境では
    # エラーを発生させないためのパラメーターです。
    response = requests.get(url=base_url + controller,
                            params=parameters,
                            verify=False,
                            auth=(user, password))
    if debug:
        # レスポンスなどを出力する
        print('デバッグのための情報です')
        print('{0: <10} {1}'.format('url:', response.url))
        print('{0: <10} {1}'.format('status:', response.status_code))
        print('{0: <10} {1}'.format('reason:   ', response.reason))
        print('{0: <10} '.format('headers:'))
        for key in response.headers:
            print('     {0: <17} {1}'.format(key + ':', response.headers[key]))
        # print('{0: <10} {1}'.format('text:'), response.text)
    return json.loads(response.text)

 

■セキュリティーについて

コーディングのファイルにパスワードを記入するのは良くないので、下記の様に実行する時にプロンプトを表示するようにもできます。

import getpass
_password = ''
def password():
    if _password != '':
        return _password
    password = getpass.getpass('please type in your password: ')
    return password

requestsのパッケージのSessionの機能も役立つと思います。

 

今後、Update、Deleteなどの例を記載するつもりです。