Raspberry PiからMindSphereへ (4)外部からAPIを使う

# 更新
2020/06/03　サービスクレデンシャル→アプリケーション・クレデンシャルに修正
概念を間違っていました……


# APIに外部からアクセスしてみる
## APIに外部からアクセスする方法

以前、MindSphereのアプリにアクセスするためには権限(ロール)が必要と書きました。

これからアクティブ・クライアント(MindSphere外部=ラズパイなど)からアセットにアクセスするのですが、これはつまりロールをまったく持たない人間に、「ロールに相当する」権限を与える必要があるということです。
その「ロール相当」がアプリケーション・クレデンシャルです。
これさえあれば、ラズパイであれ、自社サーバーであれ、Postmanであれ、APIに接続することができます。MindSphereログイン・アカウントすらなくても、APIにアクセスすることが可能です。


アプリケーション・クレデンシャルは、MindSphereのロールとは**無関係に**使用できます。
まったくアプリケーション特有ロールを持っていなくても使えます。



逆にアプリケーション・クレデンシャルを持っていても、前回見たテスターやindex.htmlは見ることができません。あくまでアプリケーション・クレデンシャルは部外者がAPIを操作するための権限で、index.htmlを表示する権限ではありません。
index.htmlを見たいときは、ブラウザなどからSettingを開いてロールを割り当てる必要があります。
我々開発者はロールもアプリケーション・クレデンシャルも両方必要になりますが、データ操作をするだけならアプリケーション・クレデンシャルだけでOKですし、アプリを見るだけならロールだけでも大丈夫です。

## アプリケーション・クレデンシャルを取得する
さて、そのアプリケーション・クレデンシャルをあらためて取得しましょう。
ランチパッドからDeveloper Cockpit、そしてAuthorization Managementに進みます。
左のサイドバーからApp Credentialsを選択。Applicationsペインからraspiappを選択します。
![Developer Cockpit.png](https://qiita-image-store.s3.amazonaws.com/0/365619/76613e04-f4d6-6936-e51b-f23feef7d981.png)
するとNo access has been issuedという表示が出ますから、Access Issueボタンをクリックします。


モーダルからRead and Writeを選択してsubmit。
![Developer Cockpit (1).png](https://qiita-image-store.s3.amazonaws.com/0/365619/6c6234e9-ed4e-2505-ddbc-010fa062a06d.png)

するとアプリケーション・クレデンシャルが発行されます。
注意してほしいのは、一度発行されたアプリケーション・クレデンシャルは再表示することができません。
**必ずメモを取っておいてください。**


## アプリケーション・クレデンシャルをエンコードする
取得したアプリケーション・クレデンシャルのIDとSecretを、Base64形式でエンコードします。
まずテキストエディタなどに保存したIDとSecretを以下のようにコロンで繋ぎ合わせてください。

> ID:Secret

一例として以下のようになると思います。

> tenant-raspiapp-1.0:35Ylz5sjkwdy1z8p2ibqIo34dgbRccyDUacOZ0IqNbJnuU


この文字列を、Base64形式でエンコードします。
例えば以下のようなサイトを使ってください。
[G Suite Toolbox  Encode / Decode](https://toolbox.googleapps.com/apps/encode_decode/)

**参考**・セキュリティ上このようなサイトを使用したくない場合はブラウザのデベロッパーツールを開き(ChromeでWindowsならF12、Macは⌘ + option + i )、コンソールから以下のJavsScriptを実行してみてください。

```javascript
window.btoa("コロンで挟んだアプリケーション・クレデンシャル");
```

**注意**・末尾に改行文字などが含まれないようにしてください

## トークンを取得する
さて、ようやくトークンを取得する準備が整いました。

ここからはMindSphere上にデプロイしたテスターでAPIをテストしますが、Postmanでも同じことができます。Postmanに慣れている方は、次章でPostmanによるアクセスを説明しますので、ここからは斜め読みで結構です。

テスターでは以下のようにフォームを埋めてください。

| 項目        | 内容                                                                       |
|-------------|----------------------------------------------------------------------------|
| Req Header1 | Content-Type: application/json                                             |
| Req Header2 | X-SPACE-AUTH-KEY:Basic {先程エンコードした文字列}        |
| 形式        | POST                                                                       |
| URL         | https://gateway.eu1.mindsphere.io/api/technicaltokenmanager/v3/oauth/token |


パラメータのフォームには以下の内容を貼ってください。

```json
{
"appName": "raspiapp",
"appVersion": "1.0",
"hostTenant": "テナント名",
"userTenant": "テナント名"
}
```

注意・ダブルクオーテーションはそのままで使用してください。

![APIテスター for Mind Sphere (1).png](https://qiita-image-store.s3.amazonaws.com/0/365619/c6f423a7-b221-57bd-7e2e-d1016702177f.png)


これでHTTPステータス・コード200が返ってくれば成功です。
access_tokenで始まるJSON形式のデータが返ってくるはずです。

## アクセストークンを使って時系列APIにアクセスする
ようやくこれで外部からAPIに接続することが可能になりました。

次も書き込みに挑戦してみましょう。フォームを以下のように設定します。

| 項目        | 内容                                                                                   |
|-------------|----------------------------------------------------------------------------------------|
| Req Header1 | Content-Type: application/json                                                         |
| Req Header2 | Authorization:Bearer {先程取得したトークン}                                             |
| 形式        | PUT                                                                                    |
| URL         | https://gateway.eu1.mindsphere.io/api/iottimeseries/v3/timeseries/{Asset ID}/rasPiData |

APIのURLに注目してください。あなたのテナント名が関わっていないURLです。アクティブクライアント(MindSphereの部外者)としてAPIにアクセスするので、テナントのURLではなくMindSphere Gatewayを通じたアクセスとなります。Gatewayは、MindSphereにアクセスする様々なデバイス(PCやMindSphere agent)の出入り口となってWEBアプリやサービス、IAMなどのアクセスを管理しています。

またパラメーターには以下のJSON形式のデータをセットします。

```json
[
	{
		"_time": "2019-02-26T07:13:30.000Z",
		"temperature":27.12
	}
]
```
注意・ブラケット([])も忘れずに

これで送信してください。
無事HTTPステータス・コードが204なら成功です！
レスポンスボディやContent-typeは空で戻ってきます。

時系列データの読み込みは省略しますが、「形式」をGETに直して送信すれば、先程書き込んだデータを取得することができるはずてず。

# Postmanを使って外部からのアクセスする
同じ内容にはなりますが、念の為PostmanからAPIにアクセスします。
外部からのAPI接続として、もしかしたらPostmanからアクセスしたほうがわかりやすいかもしれません。PHPによるAPIテストと重複する内容になりますので、そちらが終わってる方はこの章は飛ばしてもらっても大丈夫です。

## アクセストークンを取得する。

![スクリーンショット (6).png](https://qiita-image-store.s3.amazonaws.com/0/365619/469f502b-6dc9-cd3e-5d9a-2bddd165101b.png)

基本的にはテスターと同じです。

| 項目        | 内容                                                                       |
|-------------|----------------------------------------------------------------------------|
| Headers(1) | Content-Type: application/json                                             |
| Headers(2) | X-SPACE-AUTH-KEY:Basic {先程エンコードした文字列}        |
| メソッド        | POST                                                                       |
| URL         | https://gateway.eu1.mindsphere.io/api/technicaltokenmanager/v3/oauth/token |

![スクリーンショット (7).png](https://qiita-image-store.s3.amazonaws.com/0/365619/705c1639-5970-3b2f-e135-88afb2b50802.png)

リクエストボディは画像のようにRawを設定し、JSON(Application/json)で送信します。

![スクリーンショット (5).png](https://qiita-image-store.s3.amazonaws.com/0/365619/d2202a04-4852-4004-d368-26d03c7381ca.png)
画像のようにちゃんとトークンが返ってくれば成功です。

## Postmanで書き込む
![スクリーンショット (8).png](https://qiita-image-store.s3.amazonaws.com/0/365619/e3794923-851d-2632-312e-3bffcbd2e309.png)
先程取得したトークンを、Authorization: Bearer ヘッダに埋め込みます。

![スクリーンショット (9).png](https://qiita-image-store.s3.amazonaws.com/0/365619/9d9dafb7-bb7b-00c3-4d93-10b17429adbd.png)
Content-TypeにApplication/jsonを指定します。

| 項目        | 内容                                                                                   |
|-------------|----------------------------------------------------------------------------------------|
| Headers(1) | Authorization:Bearer {先程取得したトークン}    
| Headers(2) | Content-Type: application/json |
| 形式        | PUT                                                                                    |
| URL         | https://gateway.eu1.mindsphere.io/api/iottimeseries/v3/timeseries/{Asset ID}/rasPiData |


![スクリーンショット (10).png](https://qiita-image-store.s3.amazonaws.com/0/365619/f67db4e5-a292-5473-f9af-e5f8239e98e8.png)
(リクエストボディですが画像はちょっと間違ってます、すいません……)
以下のものをお使いください。

```json
[
	{
		"_time": "2019-02-26T07:13:30.000Z",
		"temperature":27.12
	}
]
```
注意・ブラケット([])も忘れずに


![スクリーンショット (11).png](https://qiita-image-store.s3.amazonaws.com/0/365619/89ac7942-c5e7-9a38-703a-04de80d815be.png)

Sendを押して、以上のようなHTTPステータスコード204が出ればOKです！


## 外部からのAPIアクセスに成功
さて、内部と外部からAPIにアクセスしました。
ここでいう内部とはMindSphere内部で、外部とはMindSphere以外の場所からという意味です。

Postmanはアプリケーション・クレデンシャルを使うことで「外部からの」接続が可能です。これはPHPのAPIテスターと同じ結果になると思います。
しかしPostmanでは、前者の「内部からの」やり方は通用しません。おそらくエラーが出ると思います。
これはPHPがMindSphere上でデプロイしているからアクセスできますが、Postmanはローカル上からのアクセスになり、MindSphereから外部に当たることになります。

今後Raspberry Piで外部からのAPIアクセスに挑戦してみたいと思います。

# 終わりに
今回はAPIの使い方を書きました。
次回はRaspberry PiからMindSphere APIにアクセスしてみたいと思います。
といっても基本的なことはこの記事でほぼ全て言い尽くしたので、あとはRaspberry Pi側でちょこっと実装するだけで済みそうです。

お疲れ様でした！