SORACOM Sens'itのデータをIBM Cloud Functionsで受け取ってみた

# はじめに
この記事はIoTLTオンラインで登壇した話の補足です。登壇資料は[こちら](https://speakerdeck.com/miura55/soracom-sensitdeyou-ndemita)からご覧ください。
今回は5分で収まりきらなかったIBM Cloud FunctionsでSens'itのデータを溜め込むまでの詳細なお話をします。

# 用意するもの
- IBM Cloud(ライトアカウントでもOK)
- SORACOMユーザーコンソール
- Sens'it（[SORACOM IoTストア](https://soracom.jp/products/)から購入したもの)

事前に[Sens'itのセットアップ](https://dev.soracom.io/jp/start/sigfox_hw_sensit/)を済ませてSORACOM harvestでデータが表示出来る状態とします。

# SORACOM Beamからのデータを受け取ってみる
## Cloudantの用意
まずはデータを溜め込むためにデータベースを用意します。今回は、データの保存先としてCloudantを使います。CloudantはIBM Cloudが提供しているDBaaSです。NoSQLデータベースでIoTのデータを溜め込むにはうってつけのサービスです。Node-REDをIBM Cloudで使っている方はフローの保存にCloudantが使われているので、これをそのまま使ってもOKです。もし、Cloudantがリソースリストにない場合は、Cloudantのリソースを作成しておきます。Cloudantのリソース画面に移動したら、```サービスの資格情報```から```新規資格情報```を選択してCloudantの接続情報を作成しておきます。
![コメント 2020-06-16 023805.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/ad024ed2-eddb-063f-c547-e5bbecc94c44.png)

役割はManagerを選択しておきます。資格情報が作成されたらそこに表示されている```username```と```password```、```url```をどこかにメモしておきます。
次にSens'itのデータを貯めるためのデータベースを用意します。管理を選択し、そこからLaunch DashboardをクリックしてCloudantのダッシュボードにアクセスします。
![コメント 2020-06-16 024644.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/f221e471-ec38-86c9-43e6-d176462e5029.png)

ダッシュボードの右側の```Create Database```を選択して、データベース名を```sensit_data```とし、パーティションは```Non Partitioned```を選択して```Create```をクリックします。
![コメント 2020-06-16 210312.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/77d71dc0-2094-367f-e1bd-4b7d48c23c91.png)

## SigfoxデバイスIDを確認
続いて使用するSens'itのデバイスIDを確認します。SORACOMコンソールから```SORACOM Air for Sigfox```の中のデバイスの管理を選択し、使用しているSens'itのデバイスIDをメモしておきます。合わせて、SORACOMのユーザーコンソールにログインするときに使っているメールアドレスとパスワードもメモしておきます。
![コメント 2020-06-16 212001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/5b42cd8c-f7ba-4568-151e-186038b63de1.png)


## アクションの用意
最後にIBM Cloud Functionsのアクションを作成します。IBM Cloud Functionsのトップページに移動し、```作成の開始```を選択します。そこからActionsを選択したらお好きなアクション名を設定してRuntimeを```Python3.7```にしてCreateをクリックしてください。作成できたら以下のコードをアクションのエディタにコピペします。

```python:main.py
import json
import requests
from cloudant.client import Cloudant
from cloudant.query import Query
from cloudant.adapters import Replay429Adapter

def main(args):
    auths = getToken(args["SORACOM_EMAIL"], args["SORACOM_PASSWORD"])
    # Get current soracom sens'it data 
    timestamp = args["__ow_headers"]["x-soracom-timestamp"]
    headers = {
        'Accept': 'application/json',
        'X-Soracom-API-Key': auths["apiKey"],
        'X-Soracom-Token': auths["token"],
    }
    params = {
        'from': timestamp,
        'sort': 'asc'
    }
    response = requests.get('https://api.soracom.io/v1/sigfox_devices/{}/data'.format(args["DEVICE_ID"]),
                            headers=headers,
                            params=params)
    print(response.json())
    data = json.loads(response.json()[0]["content"])
    
    # Cloudantに接続
    client = Cloudant(args["USERNAME"], args["PASSWORD"], url=args["URL"], 
            adapter=Replay429Adapter(retries=10, initialBackoff=0.01)
        )
    client.connect()
    userdb = client["sensit_data"]
        
    #リクエストデータを登録（timestampをIDとする）
    data = {
        "_id": data["time"],
        "time": data["time"],
        "battery": data["battery"],
        "tempC": data["tempC"],
        "tempF": data["tempF"],
        "humidity": data["humidity"]
    }
    resistDocument = userdb.create_document(data)
    if resistDocument.exists():
        print("SUCCESS!")
    # Cloudantを切断
    client.disconnect()
    return { 'status': 200 }

def getToken(email, password):
    body = {
        "email": email,
        "password": password
    }
    response = requests.post("https://api.soracom.io/v1/auth", json=body)
    return response.json()

```
簡単にソースコードの解説をすると、SORACOM Beamから受け取るデータにはセンサーの情報が何も入ってませんでした。Beamの設定ではアクセスポイントぐらいしか設定項目がなかったので、特に送信するデータを自分で自由に設定できるわけではなさそうです(もし送信するデータを設定する方法を知っている方がいたら教えてほしいです…)。ただ、データを送信したときのタイムスタンプはリクエストデータから取得することができました。そこで、SORACOMの[APIリファレンス](https://dev.soracom.io/jp/docs/api/)に紹介されていたSigfoxのAPIを使って最新のセンサーデータを取得しています。また、序盤でアクセストークンをAPIで取得しているのは、アクセストークンが一定時間立つと無効になってしまうので、ユーザーネームとパスワードからアクセストークンを取得しています。あとは、データを整形してCloudantに送信するという仕組みです。

### パラメータの用意
アクションを用意できたらアクションを動かすためにパラメータを用意します。パラメータは先程メモしたアクセストークンなどをここで設定します。アクションのエディタ画面から```Parameters```を選択し、各パラメータを設定します。今回設定するパラメータは以下の通りです。

| Parameter Name   | Parameter Value                           |
|------------------|-------------------------------------------|
| SORACOM_EMAIL    | SORACOMユーザーコンソールのメールアドレス    |
| SORACOM_PASSWORD | SORASOMユーザーコンソールのパスワード       |
| PASSWORD         | Cloudantのパスワード                      |
| USERNAME         | Cloudantのユーザーネーム                  |
| URL              | CloudantのURL                             |

### APIエンドポイントの設定
それでは、最後にこのアクションを呼び出すためにAPIエンドポイントを設定します。Functionsのトップページに移動し、左のメニューからAPIを選択します。

![コメント 2020-06-16 233555.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/b6ab3f3e-4d64-49b6-4559-db1d71ced7b5.png)

APIの作成からAPI名とエンドポイントを設定して、操作の作成をクリックします。
![コメント 2020-06-16 234008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/b0440ba4-1fe9-e3a0-a455-909c074805ed.png)

操作の作成では、以下のようになります。パス名は自由に設定ていいですが、後で使うのでメモしておきましょう（スラッシュはパス名を入れると自動でつきます）。VerbにはPOSTを選択し、アクションは先程作成したアクションを選択します。応答コンテンツはapplication/jsonのままでいいです。入力を終えたら「作成」をクリックして作成します。途中で「Webアクションが自動的に有効になります」的な警告が出てきたらそのまま次にすすみます。

![コメント 2020-06-16 234417.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/f20b2c01-b8da-c68c-08b3-377dbc82db88.png)

作成が終わると以下のAPI設定画面が出てくるので、この中の```ルート```に書かれてるURLに先程のパスを合わせたものがSORACOM Beamで設定するエンドポイントURLになりますのでメモしておきましょう。

![コメント 2020-06-16 235652.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/67ac5f4a-074e-5684-cbc6-2bb633851950.png)

## SORACOM Beamの設定
続いて先程用意したエンドポイントをSORACOM Beamで設定します（~~本当はSORACOM Funkから呼び出せると嬉しい…~~）。SORACOM Air for Sigfoxの中のSigfoxグループの中からSens'itが登録しているグループを選択します。＋ボタンを押してエンドポイントを追加します。
![コメント 2020-06-17 000613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/1cf25c27-2f74-bd7c-faff-68d37a8a70ae.png)

設定方法としては先程メモしたエンドポイントURLのうち、```×××.us-south.apigw.appdomain.cloud```がホスト名となり、/以下のパスはパスに設定します。ポート番号は何も書かなくていいです。記入し終えたら、下にスクロールして```保存```をクリックします。


![コメント 2020-06-17 000857.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/a3b69b1b-1c61-c3f1-fb8d-a22c4cc5fb5d.png)

# 動作確認
これでIBM Cloud Functionsで値を受け取ることが出来る状態になります。1時間おきにデータが送信されて、Cloudantのデータベースを確認するとこのように温湿度のデータやバッテリーの残量をを溜め込むことができます。
![コメント 2020-06-17 003005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/6bd58ccf-d909-9794-a58d-a958267c12a3.png)

# おまけ
今回Soracomのキャンペーンで記事を投稿してSens'itを入手しました。
その時書いた記事はコチラ↓
[ソラコムの【あのボタン】で勤怠打刻してみた（その1）](https://qiita.com/K_M95/items/854cd0c498792574c8a6)
[ソラコムの【あのボタン】で勤怠打刻してみた（その2）](https://qiita.com/K_M95/items/aa022f7d39a5045a3098)