Node-REDからSORACOM APIを使ってSIMタグを読み書きする方法

# はじめに
遠隔地に設置したIoTゲートウェイに外部からパラメータを渡したい場合、いくつかの方法があるかと思いますが、今回はSORACOMプラットフォームで構築したIoTシステムにおいて、[SIMのタグ](https://users.soracom.io/ja-jp/docs/air/set-tag/)を使った方法をご紹介します。
なお、サーバーで動作するパラメータ設定画面およびIoTゲートウェイのプログラムはNode-REDを使って構築することとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/640c68b1-1071-10cc-27fc-2dfd48873631.png)

1. Webブラウザから設定用のサーバーにアクセスして設定する
1. サーバーからSORACOMのSIMタグを書き込む
1. 現場のIoTゲートウェイがSIMタグを読み取る

なお、この記事は既にSORACOMとNode-REDをお使いの方を対象としており、[アカウント作成](https://users.soracom.io/ja-jp/guides/getting-started/create-account/)などの基礎的な作業は省いていますので、ご了承ください。
また、利用するSORACOMのサービスは無償の範囲もありますが、<font color="red">基本的に有償となります</font>。数百円単位であまり多くはありませんが<font color="red">費用が発生します</font>ので、各サービスのサイトで費用をご確認ください。

また、検証に当たっては私の過去の記事（[AWS上にNode-RED環境を構築する方法](https://qiita.com/ozk009/items/a120de616326cead7c7c)、[Windowsを使った開発環境の構築する方法](https://qiita.com/ozk009/items/52ef82063b5a4b579628)）を参考にしていただければと思います。

# 準備
## SAMユーザー設定
サーバーからのSIMのタグを読み書きするためのSAMユーザーを作成します。

1. [SORACOMドキュメント](https://users.soracom.io/ja-jp/docs/sam/create-sam-user/)を参考に、SAMユーザーを作成し、[認証キーを取得](https://users.soracom.io/ja-jp/docs/sam/create-sam-user/#%e8%aa%8d%e8%a8%bc%e3%82%ad%e3%83%bc%e3%82%92%e7%94%9f%e6%88%90%e3%81%99%e3%82%8b)します
1. 続いて以下の手順でSAMユーザーの権限を設定します  
権限設定のJSONは以下となります
```json
{
  "statements": [
    {
      "api": [
        "Subscriber:getSubscriber",
        "Subscriber:putSubscriberTags"
      ],
      "effect": "allow"
    }
  ]
}
```
## タグの追加
パラメーターを保存するタグを追加し、初期値を入れておきます。  
今回は安易ですが、文字列の「param1」と数値の「param2」とします。
1. SORACOMコンソールのSIM管理画面で対象のSIMを選択（クリックする）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/468ae678-29ec-df36-d742-000e55f7cde2.png)
1. タグを選択し、「param1（abc）」と「param2（123）」を追加して保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/c3177330-74de-5fbc-1079-45f2b83bd869.png)

# サーバー側の処理
<b>※この記事のメインとなる箇所なので、この章が一番重たいです。</b>
パラメーターの設定画面をNode-REDで作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/83c2e5d5-55fd-8ed8-12f6-baa6552c75da.png)

フローは以下の5つの構成となっています
- 1.初期値セット…SIM情報と認証情報をセットする
- 2.認証情報取得…APIを使うための認証
- 3.初期値取得…APIを実行し、SIMタグ情報を読み取る
- 4.初期値設定…3.で取得した情報を初期値として画面にセットする&画面上の変更を変数にセットする
- 5.設定（タグ上書き）…画面で変更したパラメーターをSIMタグに上書きする

各ノードの設定については以降の節で説明します。

## 1.初期値セット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/f98d5fbc-568d-eda5-bf4c-3800bb9c874f.png)

ここでは初期値として、対象のSIMのIMSIとSAMユーザーの認証キーID（「keyID-」から始まる文字列）と認証キーシークレット（「secret-」から始まる文字列）をchangeノードでflow変数「imsi」「authKeyId」「authKey」にセットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/36bc8108-b37e-bd6d-bc31-58a59e4a6e1b.png)

## 2.認証情報取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/1a698e87-2741-06d1-981f-148da9528166.png)

SORACOM APIでは認証キーIDと認証キーシークレットで認証し、APIキーとAPIトークンを取得し、APIをコールします（詳細は[こちら](https://users.soracom.io/ja-jp/tools/api/key-and-token/)）。
1. functionノードで認証キーIDと認証キーシークレットをJSONにセットします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/fdc5cf36-ab56-598b-1242-ee63f83d1306.png)
    ```javascript
    msg.headers = {
        "Content-Type": "application/json"
    };
    
    msg.payload = {
        "authKeyId": flow.get("authKeyId"),
        "authKey": flow.get("authKey")
    };
    
    return msg;
    ```
1. http requestノードで認証リクエストする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/7cf61e96-61b1-f83d-d3d3-907268a1857e.png)
    - メソッドは「POST」
    - URLは「https://api.soracom.io/v1/auth」
    - 出力形式は「JSONオブジェクト」
1. changeノードで受信したAPIキーとAPIトークンをflow変数「apiKey」「token」に保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/32bafdd6-d942-5148-ba35-a135056a8360.png)

## 3.初期値取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/b8fe4b29-f9a1-932c-2883-940ce75ce1a8.png)

現時点でSIMタグに保存されている値を取得します。
1. functionノードでAPIキーとAPIトークン、対象SIMのIMSIをセットする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/7b093634-c930-3259-17fb-3b7cc08bc52c.png)
    ```javascript
    msg.headers = {
        "Content-Type": "application/json",
        "X-Soracom-API-Key": flow.get("apiKey"),
        "X-Soracom-Token": flow.get("token")
    };
    
    msg.imsi = flow.get("imsi");
    
    return msg;
    ```
1. http requestノードでSIM情報を取得する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/43db4f13-02ef-bac6-1835-a4bc4f03207e.png)
    - メソッドは「GET」
    - URLは「https://api.soracom.io/v1/subscribers/{{{imsi}}}」
    - 出力形式は「JSONオブジェクト」
1. タグ情報がpayloadのtagsに入っているので、changeノードでflow変数に保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/1e11b78d-1580-1922-866e-f4f4fd9490ba.png)

## 4.初期値設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/25a4a09a-bd27-e35d-0746-ee60e465c05e.png)

1. param1（text inputノード）、param2（numericノード）を設定用にmsg.payloadにセットする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/69283ea4-28a6-1a6c-a0d9-d30092b4b7c5.png)
1. 設定画面でparam1やparam2が変更されたタイミングでflow変数にセットするchangeノード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/f2361643-2425-4d03-d262-da450a7a4d0b.png)

## 5.設定（タグ上書き）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/453d95af-2f62-500a-b478-7a0e4a92fefb.png)

設定画面で変更した値をSORACOMに送ってタグを上書きします。
1. param1とparam2がflow変数に格納されているので、functionノードで送信データ（JSON）を作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/9717b960-e4b1-2e44-59c8-3b757f9acd7c.png)
    ```javascript
    msg.headers = {
        "Content-Type": "application/json",
        "X-Soracom-API-Key": flow.get("apiKey"),
        "X-Soracom-Token": flow.get("token")
    };
    
    msg.payload = [{
        "tagName": "param1",
        "tagValue": String(flow.get("param1"))
    },{
        "tagName": "param2",
        "tagValue": String(flow.get("param2"))
    }];
    
    msg.imsi = global.get("imsi");
    
    return msg;
    ```
1. http requestノードでパラメーターを送信する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/ba748cf3-ecad-8123-0017-2835291cd64d.png)
    - メソッドは「PUT」
    - URLは「https://api.soracom.io/v1/subscribers/{{{imsi}}}/tags」
    - 出力形式は「JSONオブジェクト」

## 設定画面
設定画面はNode-REDのダッシュボードを使って行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/8a31b157-0130-3458-14e2-4ad48f78a0f6.png)
上のようにtext inputノード、numericノード、buttonノードを置き、以下の画面で行うこととします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/760af390-639e-f33e-465b-131e868fb1e6.png)

## 動作確認
### タグの取得と画面表示
1. 下図の1,2,3の順でinjectノードのボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/8e69d5dc-4bb3-7ec8-3784-3b20b68ee778.png)
1. 問題なければ、設定画面にタグの値（例ではparam1が「abc」param2が「123」）が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/701e0251-6d9e-bb57-e31b-9726700a2c70.png)
※SORACOMコンソールのSIM詳細画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/edb63736-e260-93ca-c7fa-27e9bfddbf55.png)

### タグ値の変更と反映
1. 設定画面でparam1とparam2を変更（例ではparam1を「abcdef」param2を「234」に変更）し、設定ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/d93e8e00-e9fe-12ee-884c-7c887e8fd052.png)
1. SORACOMコンソールのSIM詳細画面でタグの値が書き換わっていれば成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/444790b1-70b2-6d2d-817d-bb3122d634d7.png)

## 自動初期化設定
このままでは自動で値が入らないので、初期化処理を自動化します。
1. 認証情報取得をするため、「初期値セット」のinjectノードをNode-RED起動の0.1秒後に実行し、認証情報の有効期限切れに備えて、24時間に1度繰り返して実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/49706865-3681-6cb6-d832-e45bf5bf75c8.png)
1. 1.で取得した認証情報を使って初期値を取得するinjectノードをNode-RED起動の5秒後に実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/224587fd-4ff1-fae7-19b7-d0f70f06a88c.png)
1. 2.で取得した値を画面に表示するinjectノードをNode-RED起動の10秒後に実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/a30e745c-05e7-8520-91ee-abc79fb740a0.png)
<b>※かなり雑にやってます…もっと良い方法があればご教示いただけると幸いです</b>



# ゲートウェイ側の設定
IoTゲートウェイでパラメーターを取得する実装について説明します。
パラメーターの使い方はそれぞれだと思うので、SIMタグの取得方法のみ紹介します。
と言ってもSORACOM Air SIM（またはArc）で接続したゲートウェイからHTTPリクエストするだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/fae94273-c07c-f3c1-ebf4-0258706c5b00.png)

http requestノードの設定は以下となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/46dc9935-a9a6-9480-f714-c9a00de176d9.png)
    - メソッドは「GET」
    - URLは「http://metadata.soracom.io/v1/subscriber.tags」
    - 出力形式は「JSONオブジェクト」

injectノードのボタンをクリックすると、値が取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/89ba9981-ccde-0c38-c221-01788d48d40b.png)

# まとめ
今回の記事も詳細説明をかなり省いています。
ここもっと詳しく教えてとかあればコメントいただけると幸いです。