SORACOM Enterprise Buttonの簡易位置情報を用い地域外での押しミスを防ぐ(CloudFunctions/Python版)


TL;DR(まとめ)

  • SORACOM Enterprise Buttonの簡易位置情報を用いて、ある地域でのみ動作するボタンを構築した
  • 2019/7/2 SORACOM Discoveryにて新発表されたSORACOM Funkを用い、GCPのCloudFunctionsを動作させた
  • 「地域外」はCloudFunctions側で判断しているので、ボタン動作回数は通常通り消費される

機材

SORACOM Enterprise Button (初期ボタン登録は済んでいるものとします)

主に使ったもの

SORACOM Funk
CloudFunctions(GCP)
pyjwt(JWT(Json Web Token)Python版ライブラリ)

構築内容

SORACOM Enterprise Buttonを押した際に、SORACOM Funk経由でCloudFunctionsを起動させます。
CloudFunctionsの中で位置情報を取得します。(このときにjwt使用)
地域外であれば動作、そうでなければ動作しないようにします。
判断するロジックの部分のみを記事にします。

構築手順

CloudFunctions設定

後でSORACOMのコンソールから起動関数を指定するため、先にCloudFunctionsを記載します。
CloudFunctionsの画面から関数の作成を選択し、以下の通りに入力しましょう。ここで★の部分のURLはSORACOM Funk設定にて用いるため取得しておきます。
関数の名前はなんでも良いですが、enterprise_buttonとでもしておきましょう。
デフォルトのNode.jsでも良いですが、Pythonでも記載できるのでPythonを選択しました。

続けてrequirements.txtの編集です。
pyjwtを用いるため、requirements.txtに以下記載をしましょう。(ここに記載した内容が pip installされるイメージです)

CloudFunctions(requirements.txt)
pyjwt

以下が実行関数です。デフォルトの起動関数名hello_worldからexec_buttonに変えているため、
実行関数名と環境変数の設定がこの後必要です。

SORACOMの説明では、httpヘッダにx-soracom-tokenがあり、それをJWTでデコードできるとのこと。
というわけでこうなります。

CloudFunctions(main.py)
import jwt
import os

def exec_button(request):
    if 'x-soracom-token' not in request.headers:
        return 'Not from soracom button.'

    # Decode jwt token. (algorithm : RS256)
    data = jwt.decode(request.headers.get("x-soracom-token"), verify=False)
    if not is_inside_area(data['ctx']['location']):
        return 'Out of area.'

    # Write your code here.
    return 'Inside area.'

def is_inside_area(position):
    northwest = {'lat': float(os.environ.get('northwest_lat', 1.0001)), 'lon': float(os.environ.get('northwest_lon', 178.0001))}
    southeast = {'lat': float(os.environ.get('southeast_lat', 0.0001)), 'lon': float(os.environ.get('southeast_lon', 179.0001))}
    if 'lat' not in position or not(isinstance(position['lat'], float)):
        return False
    if not(southeast['lat'] <= position['lat'] and position['lat'] <= northwest['lat']):
        return False
    if not(northwest['lon'] <= position['lon'] and position['lon'] <= southeast['lon']):
        return False
    return True

補足:is_inside_area関数では、取得した簡易位置情報(緯度経度)がその領域に含まれているかどうかを判断しています。

この枠内にあるか?を判断している
northwest - - - - -
-                 -
-                 -
-                 -
- - - - - southeast

実行関数名をexec_buttonにします。
詳細設定が必要なので、その下のEnvironment variables, networking, timeouts and moreをクリックします。

環境変数のみ以下の通りに指定します。(その他はデフォルトでOK)
デプロイしておきましょう。(関数を初回に作成する場合は「作成」です)

これでCloudFunctionsの設定は完了です。

SORACOM Enterprise Button設定

SORACOMコンソールから、Funkと位置情報の有効化の設定を行います。
該当するEnterprise Buttonが所属するSIMグループの設定ページを開いてください。(私はenterprisebuttonというグループ名)
設定する箇所は赤枠で囲った2箇所です。

では順に設定していきましょう。
SORACOM Air for Cellular設定 : 位置情報の取得を有効化します。また、バイナリパーサとして@buttonを設定します。

SORACOM Funk設定 : FunkでCloudFunctionsを実行するようにします。★で取得した関数のエンドポイントを記載します。

これで位置情報が取得できた場合に、地域外を判定することができます。
これにより地域外で誤って押してしまった際に動作をさせない、なんてことができますね。
参考になれば幸いです。