# AVEVA PI

> AVEVA PI のドライバーの手引き。HTTPS 越しの PI Web API、ベアラーか Basic の認証、AF と PI ポイントのアドレス指定、読み取りと書き込み。

AVEVA PI のドライバーは、**AVEVA PI System** をその REST のインターフェース（HTTP 越しの JSON）である **PI Web API** で読み書きします。こちらから接続する方式のドライバーで、**Ganter Lab のほうから PI Web API のサービスにつなぎ**ます。通信は**既定で HTTPS** です。ドライバーは出すすべての要求に機器の資格情報を載せるので、暗号化のない接続はそれを公開してしまうからです。平文の HTTP は、機器ごとにはっきり選んだときにだけ存在します。

1 つのタグは、1 つの **AF の属性**、1 つの **PI ポイント**、あるいは PI Web API の生のストリームをアドレスに取り、そのスナップショット（現在）の値を読みます。

## 接続の項目 {#connection-fields}

| 項目 | 意味 | 形式 | 既定 |
|---|---|---|---|
| ホスト | PI Web API のサーバーのホスト名か IP アドレス。アドレス全体（`https://pi-host/piwebapi`）を貼り付けられます。前に付いた `https://` や `http://` は下の通信方式をそれに合わせてから取り除かれ、ポートはポート欄に、パスはリソースのパスに入ります。 | ホスト名か IP | 空 |
| ポート | サービスの TCP のポート。新しい機器では空のままで、空の欄は選んだ通信が答えるポート、つまり HTTPS なら 443、平文なら 80 という意味です。欄にはそのポートが灰色で表示され、通信の選択に合わせて変わります。0 で保存された機器も同じように表示されます。 | 1 から 65535、または空 | 空 |
| リソースのパス | 権限の部分の後ろに付ける、サービスのルートのパス。空、または `/` だけなら、PI Web API の標準のルートである `piwebapi` という意味です。ほかのパスは、入力したそのままドライバーが開くパスです。リバースプロキシの後ろの `/pi` で公開しているサービスには `/pi` で届き、その後ろには何も付けません。ブラウザーが必要とするパスの全体を、サービスがまだそこで答えるなら `piwebapi` も含めて書いてください。 | パスの文字列 | 空（= `piwebapi`） |
| 平文の HTTP で送る | この 1 台の機器だけを HTTPS から平文の HTTP に落とします。オフなら HTTPS で、PI Web API のふつうの通信です。パネルはその結果を述べます。平文の HTTP では、ベアラーのトークンやパスワードが要求のたびに暗号化されずに送られます。ほかの通信では答えない PI Web API のためだけに使ってください。 | オン／オフ | オフ |
| ユーザー名 | **HTTP Basic** の認証のためのアカウントで、ベアラーのトークンを設定していないときにだけ使われます。空のまま（トークンもなし）なら、要求は匿名になります。 | 自由記述 | 空 |
| パスワード | ユーザー名と組になるパスワード。Windows のユーザーごとに保存時に保護されます。別の Windows アカウントで入力した秘密は読めないものとして表示されるので、入力し直してください。 | 自由記述 | 空 |
| ベアラーのトークン | 要求のたびに `Authorization: Bearer …` として送るトークン。設定されているときは、ユーザー名とパスワードの組**より優先**されます。同じやり方で保存時に保護されます。 | トークンの文字列 | 空 |

接続のとき、ドライバーはサービスのルートを HEAD で確かめ、答えなければ GET に切り替えます。HTTPS では、サービスの TLS の証明書は、Windows が信頼しているとき、またはこのドライバーのページの[現場設備へのアクセス](#equipment-access)でその証明書そのものを承認したときに受け入れられます。読み出し周期は設定できます。機器の既定（1000 ms）は、自分の周期を書いていないすべてのタグに効きます。

## PI Web API の準備 {#prepare-pi-web-api}

ドライバーは HTTP Basic によるユーザー名とパスワード、またはベアラートークンでサインインします。PI Web API は Kerberos だけを認証方式として出荷され、ドライバーは Kerberos を話さないため、インストールしたばかりのサービスは、PI Web API のサーバーで次のどちらかを済ませるまでステーションを拒否するのが普通です。

| 方法 | 設定する場所 | その後 |
| --- | --- | --- |
| Basic 認証 | PI Web API Admin Utility の Authentication Options ページで Basic にチェックを入れて適用します。または PI System Explorer の Configuration データベースで、OSIsoft > PI Web API > インスタンス名 の下の System Configuration 要素を選び、AuthenticationMethods 属性に Basic を加えて変更をチェックインします。PI Web API のサービスを再起動します。 | 機器の接続カードのユーザー名とパスワードに、PI System が受け付ける Windows アカウントを入れます。ドメインアカウントは DOMAIN\user と書きます |
| ベアラートークン | AVEVA Identity Manager と組み合わせて設定した PI Web API (Bearer 認証) | トークンは機器のベアラートークン欄に入れます |

サービスが Basic を提示せずに 401 を返したときは、機器のページがドライバーの英語のエラーの代わりに、この手順とともにそう示します。Basic を提示したうえで機器が送ったアカウントを拒否したときは、ユーザー名またはパスワードが拒否されたと示し、接続カードを指し示します。どちらの通知も、サービスが応答すればひとりでに消えます。ジャーナルとエージェントも同じ手順を読みます。サービスが拒否したベアラートークンは、ドライバー自身の言葉で示されます。

## タグのアドレス指定 {#tag-addressing}

タグの **PI パス**の項目は、4 つの形を受け付けます。

| 形 | 見た目 | 解決のされ方 |
|---|---|---|
| AF の属性のパス | `\\AFServer\Database\Element\SubElement\|Attribute` | `attributes?path=…` で一度引いて、その属性の WebId を得ます |
| PI ポイントのパス | `\\PIServer\TagName` | `points?path=…` で一度引いて、そのポイントの WebId を得ます |
| WebId | WebId の文字列そのもの | そのまま使います（`\`、`\|`、`/` を含まない長い文字列として見分けます） |
| 相対 URL | `streams/{webId}/value`、`streamsets/…`、`attributes?…`、`points?…` | サービスのルートの下に、そのまま送ります |

パスの参照は 12 時間キャッシュされるので、落ち着いた定周期読み出しがそれを繰り返すことはありません。最初の 3 つの形では、読み取りはストリームの**スナップショットの値**（`streams/{webId}/value`）を GET し、JSON の `Value` の項目を取り出します。相対 URL はそのまま読まれるので、値の文書で答える endpoint を指してください。結果は、タグに宣言したデータ型に変換されます。

そのサンプルに対するアーカイブ自身の判定も、一緒に読みます。アーカイブが**良好でない**、**疑わしい**、あるいは**差し替えられた**（測定ではなく手で入れた数値）と印を付けた値は、現場設備の読み取りではないので、読み取りとしては公開しません。タグは品質の悪い状態になり、その理由が 3 つのどれだったかを述べます。応答が値を運んでいないときや、1 つの値ではなくデジタルの状態で答えたときも同じで、後者ではその状態の名前が理由の一部になります。その代わりに何かを作ることはありませんし、文書が測定であるかのように届くこともありません。

PI Web API が拒んだ読み取り（たとえばポイントを読む権利のないアカウントのような、成功の範囲の外の状態）も品質の悪い状態になり、その理由は状態と、サービスが一緒に言ったこと（`HTTP 403 Forbidden: …`）を名指しします。サービスが知らないパスは、そのパスを名指しして、そう伝えます。空のアドレス、4 つの形のどれでもないアドレス、宣言した型として読めない応答も理由を伝えます。まったく答えないサービスは、機器の接続の失敗です。機器がそれを伝えて接続し直し、そのタグは機器を指します。

例です。

- `\\PI-SRV01\FURNACE.TEMP`：昔ながらの PI ポイント。
- `\\AF-SRV\Plant\Line 3\Furnace|Temperature`：AF の属性。
- `streams/F1DPmNQx2kqBk0qbIVMoxAVBJw/value`：生のストリームの URL で、ほかの道具からすでに WebId を持っているときに便利です。

## 書き込み {#writes}

書き込めるアクセスのタグは、PI Web API のストリームの endpoint を通じて書きます。`streams/{webId}/value` へ `{"Timestamp":"*","Value":…}` を POST します（時刻の `*` は今という意味です）。書き込みには解決できる WebId が要るので、AF のパス、PI ポイントのパス、WebId、そして相対の `streams/…` の URL でアドレスを取ったタグで働きます。最後の場合は、その URL から WebId を読み取り、アドレスがその先に何の読み取り側の下位リソース（たとえば `recorded`）を運んでいても、書き込みはそのストリームの値の endpoint に届きます。相対の形のうち 3 つは拒否されます。どれも 1 つのストリームの値ではなく文書で答えるので、書き込みが違うリソースを指してしまうからです。`streamsets/…`、`attributes?…`、`points?…` の 3 つで、拒否は受け付ける形を名指しします。書き込みが届くかどうかは、PI Web API が書き込みを受けるように構成されていることと、そのアカウントがそのポイントへの書き込みの権利を持っていることにもよります。PI Web API が拒んだ書き込みには、状態と、サービスが一緒に言ったこと（たとえば `HTTP 403 Forbidden: …`）が答えとして返り、値を書いた側はその理由を読めます。

タグの書き込みの入力欄に入力する値は工業値です。生値がバスに出る前に、そのタグの変換の段階が逆向きに適用されます。[Connector](connector) のページに書いてあるとおりです。

## 対応するデータ型 {#supported-data-types}

Boolean、Int32、Int64、Float、Double、String です。数値の PI ポイントは、たいてい Float か Double です。デジタルの状態は 1 つの値ではないので、それで答えるポイントは、タグがどの型を宣言していても、その状態を名指しした品質の悪い読み取りになります。

## コマンド {#commands}

ポイントを読み書きするほかに、PI Web API の endpoint には何かをするよう頼めます。どの要求を受け付けるかは、そのサービス自身の事情です。1 つずつ機器のページの**コマンド**のカードで宣言してください。名前、サービスのルートの下で POST する先の相対 URL、そして受け取る 1 つの値の名前（任意）で、その値は要求の本文として運ばれます。行の実行の操作がそれを送り、サービスが何と答えたかを伝えます。コマンドは、このステーション自身の OPC UA のアドレス空間で機器のメソッドにもなります。サービスが拒んだ要求には、状態と、サービスが一緒に言ったことが答えとして返ります。拒否された書き込みと同じ言葉です。

## 機器検出 {#discovery}

**機器検出**のボタンは、1 つのサービスを読みます。ドライバーのページの「スキャンの範囲」のカードに、そのアドレスと、巡回を始める AF の要素を `#` で区切って入れてください。`https://pi-host/piwebapi#\\AF-SRV\Plant\Line 3` のようになります。スキャンはその要素を解決し、その下のすべての要素を巡り、属性 1 つにつきポイント 1 つを、それぞれ自分のストリームでアドレスを取った形で備えた機器を差し出します。スキャンは資格情報なしにサービスを読みます。資格情報を持つはずの機器がまだ存在しないうちに走るからです。ですから、あらゆる要求に認証を求める PI Web API は何も答えないので、その機器は手で追加してください。サービスはホストで追加し、タグは AF か PI のパスで追加します。[Connector](connector) のページの、機器を追加する流れのとおりです。

PI の機器のページには**タグ検出**が出ません。巡回は AF 要素から始まり、その要素を機器は持っていないので、機器の点はこのスキャンから来るか、手で追加します（[機器のタグを検出する](connector-discovery#discovering-a-devices-tags)を参照）。

## 現場設備へのアクセス {#equipment-access}

ポートに証明書を割り当てていない PI Web API は、自前の自己署名の証明書を作って使います。Windows にインストールされたどのルートもその証明書を保証しませんが、そのルートをこのコンピューターにインストールする必要はありません。最初の接続は拒否され、機器はツリーとそのページで**証明書の承認を待っています**と表示し、そのページの**証明書を確認する**のボタンがこのカードをその証明書の位置で開きます。証明書は、AVEVA PI のドライバーのページの最後にある**現場設備へのアクセス**で、判断を待ちます。OPC UA のドライバーのページにあるのと同じカードです。

| グループ | 並ぶもの | できること |
|---|---|---|
| 承認待ち | 拒否された証明書の 1 つ 1 つが、証明書が名乗る名前の下に並びます。SHA-256 のフィンガープリント、それに出会ったアドレス、最後に試した日時と回数、詳細（主体、発行者、ドメイン名、有効期間）が出ます。機器の**証明書を確認する**で開いた証明書には「確認のために選択中」の印が付きます。 | **承認する**と、次の接続の試みからその証明書を受け入れます。**遮断する**と、ここにふたたび並べることなく拒否し続けます。**承認待ちの証明書をすべて破棄**は、何も承認も遮断もせずに一覧を空にします。 |
| 承認した現場設備 | 承認した証明書と取り込んだ証明書が、誰がいつ判断したかと、それぞれに最後に出会ったアドレスとともに並びます。 | **承認を取り下げる**と、接続を閉じ、その証明書を一覧に戻します。**証明書を取り込む**と、手元にある公開証明書のファイル（.der、.cer、.crt、.pem）を最初の接続より前に承認します。 |
| 遮断した現場設備 | 遮断した証明書が並びます。遮断した証明書は、Windows が信頼していても拒否されます。 | **遮断を解除**すると、承認はせずに、その証明書を一覧に戻します。 |

承認する前に、PI サーバーを管理している担当者とフィンガープリントを照合してください。承認で受け入れるのはその証明書だけで、しかも有効期間の内側だけです。承認は、Windows に足りないルートと、証明書に書かれた名前の代わりになります。そのため、IP アドレスで接続する PI Web API も、証明書に別の名前が書かれていてもつながります。証明書のそのほかの点は何もゆるめません。承認した証明書のアドレスで現場設備が別の証明書を出すと（証明書の更新、ポートへの別の証明書の割り当てなど）、読み取りは止まり、新しい証明書がここで待ち、ステーションが**確認する**のボタン付きで「証明書が変わりました：`<名前>`」と知らせます。Windows がすでに信頼している証明書はこれまでどおり受け入れられ、ここには出ません。何かが自動で承認されることはありません。

ドライバー自身の失敗は、名前のない TLS のエラーではなく理由を述べます：「この現場設備の証明書（フィンガープリントの先頭 16 文字）は、AVEVA PI ドライバーのページの「現場設備へのアクセス」であなたの承認を待っています。承認すると読み取りが始まります。」遮断した証明書なら「…はこのステーションで遮断されています。AVEVA PI ドライバーのページの「現場設備へのアクセス」で確認してください。」となります。有効期間の外にある証明書、失効した証明書、署名の壊れた証明書は、その理由で拒否され、一覧には並びません。承認しても健全にはならないからです。「スキャンの範囲」のカードからのサービスのスキャンも、同じ判断にしたがいます。知らない証明書はその文でスキャンを終わらせ、ここで待ちます。

判断はステーションのデータフォルダーの `ua\pki\aveva-pi` に保存され、再起動しても残ります。操作が描かれるのは Connector を構成できるロールだけで、操作が効くのはステーション自身のウィンドウの中だけです。別の機器のブラウザーはカードを読むだけで変えられず、エージェントのツールが証明書を承認することもありません（`connector_browse` は待っている機器を `awaitingCertificate` で示します）。一覧に並ぶ承認待ちの証明書は 100 件までです。いっぱいになると、新しい証明書は引き続き拒否されますが一覧には並ばず、カードがそのことを伝えます。
