3
4

More than 3 years have passed since last update.

Sigfox CallbackとGoogle Cloud Platform連携

Last updated at Posted at 2019-05-10

Google Cloud PlatformとSigfoxとの連携方法を説明します。今回の例は、Sigfoxデバイスから送信されたメッセージをSigfoxクラウドのCallback機能で、GCPに接続。Cloud FunctionsからPub/Sub、Data FlowからBigQueryまでを対象とします。
※こちら(動画)(チュートリアル)も参考に。
GCP ZService (2).png

事前準備

事前に、Google Cloud PlatformのアカウントとSigfoxバックエンドのアカウントを取得してください。Sigfoxバックエンドクラウドのアカウントをお持ちでない方は、Sigfox Shield for ArduinoM5Stack COM.X Sigfoxをご購入いただき、Sigfox Buyからアカウントを取得してください。

Google Cloud Platformプロジェクトの作成

下記手順でGCPプロジェクトを作成してください

  1. GCPコンソールに移動
  2. 画面左上のプロジェクト選択後、【新しいプロジェクト】を選択
  3. プロジェクト名を入力し【作成】ボタンをクリック(今回は”Sigfox-GCT"というプロジェクト名で説明します) gct01.png
  4. 再度、プロジェクト選択をクリックし、先ほど作成した新規プロジェクトを選択 gct02.png
  5. 左ナビゲーションメニューから"APIとサービス" > "ライブラリ"を開く
  6. 下記APIが有効になっているかを確認し、もし有効になっていない場合は有効にしてください
  • Cloud Functions API
  • Cloud Pub/Sub API
  • Cloud Datastore API
  • Cloud Build API

Sigfox Callback用Cloud Functionsをデプロイ

1.ローカル開発環境にGoogle Cloud SDK (gcloudコマンドラインツール)、git、python、pip、virtualenv、curlをインストールしてください。

2.先程作成したGCPプロジェクトの初期設定を下記コマンドで行います
$ gcloud init

3.Sigfoxデバイスのデータを受け取るPub/Sub topicを作成
$ gcloud pubsub topics create sigfox-data

4.必要に応じ、上記topicのメッセージをモニタリングするためのPub/Subサブスクリプションを作成します
$ gcloud pubsub subscriptions create sigfox-data-sub --topic sigfox-data

5.Sigfoxコールバックを受け付けるCloud Functions用に下記3ファイルを適当なフォルダ下に作成します。(ここでは"sigfox-gw"フォルダを作成し、そこに保存しておきます。)

\main.py
import sys

def callback_data(request):
  # [START functions_callback_data]

  import os
  import json
  import base64
  import datetime
  from flask import abort
  from rfc3339 import rfc3339
  from google.cloud import datastore, pubsub_v1

  if request.method == 'POST':
    http_user = os.environ.get('HTTP_USER')
    http_passwd = os.environ.get('HTTP_PASSWD')
    request_user = request.authorization["username"]
    request_passwd = request.authorization["password"]

    if request_user == http_user and request_passwd == http_passwd:
      request_dict = request.get_json()
      print('Received Sigfox message: {}'.format(request_dict))

      publisher = pubsub_v1.PublisherClient()
      topic = os.environ.get('PUBSUB_TOPIC_DATA')
      project_id = os.environ.get('GCP_PROJECT')
      if not topic or not project_id:
          print('Error reading Function environment variables')
          return abort(500)
      topic_name = 'projects/{project_id}/topics/{topic}'.format(
          project_id=project_id, topic=topic)

      try:
          time_int = int(request_dict['time'])
      except ValueError:
          time_int = float(request_dict['time'])
          time_int = int(time_int)
      event_time = rfc3339(time_int)
      request_json = json.dumps(request_dict)
      message_id = publisher.publish(topic_name, request_json.encode('utf-8'),
                                     ts=event_time.encode('utf-8'))
      print('Message published to Pub/Sub topic: {}'.format(topic_name))
      return '', 200
    else:
      print('Invalid HTTP Basic Authentication: '
            '{}'.format(request.authorization))
      return abort(401)
  else:
      print('Invalid HTTP Method to invoke Cloud Function. '
            'Only POST supported')
      return abort(405)
  # [END functions_callback_data]
\.env.yaml
PUBSUB_TOPIC_DATA: sigfox-data
HTTP_USER: user
HTTP_PASSWD: password

.env.yamlファイルのHTTP_USERHTTP_PASSWORDをご自由に設定してください。これらの項目は、SigfoxバックエンドクラウドからGCPにCallbackする際のCloud FunctionsがHTTPS通信時に、Sigfoxバックエンドを認証するために使用するBasic認証情報となります。

\requirements.txt
rfc3339
google-cloud-pubsub

6.sigfox-gwディレクトリに移動します
$ cd sigfox-gw

7.新たにPythonの仮想環境を作成します
$ py -3.7 -m venv myvenv (windows)
$ python3.7 -m venv myvenv (mac, linux)

8.Pythone仮想環境を起動します
$ myvenv\Scripts\activate (windows)
$ source myvenv/bin/activate (mac, linux)

9.必要なPythonモジュール群をインストールします。
(myvenv) $ pip install -r requirements.txt

10.下記コマンドを使用し、Cloud Functionsをデプロイします。(--region値は、ご自身がデータの蓄積・処理を希望するCloud Functionsリージョンを設定してください。)
(myvenv) $ gcloud functions deploy --region asia-northeast1 --runtime python37 --env-vars-file .env.yaml --trigger-http callback_data

このコマンドを実行すると、下記例のようなHTTPS Trigger URLがコマンド出力されます。

httpsTrigger:
  url: https://asia-northeast1-sigfox-gcp.cloudfunctions.net/callback_data

このURLはCloud FunctionsのリージョンやGCPプロジェクト名に応じ、下記フォーマットで出力されます。
https://[リージョン]-[プロジェクト名].cloudfunctions.net/callback_data

11.デプロイが終了すれば、Cloud FunctionsのWebコンソールで、Cloud Functionsがデプロイされていることを確認することができます。
image.png

Sigfox Callbackを作成

Sigfoxコールバックを受け付けるCloud Functionsが作成出来たので、次は、Sigfoxバックエンドクラウド上で、コールバックを作成します。
Sigfox Callbackは、デバイスタイプ単位で設定するため、DEVICETYPEリストから、ご自身のデバイスのデバイスタイプを選択し、Callback設定を開始してください。
image.png
AWSやAzureは専用のCallback作成メニューがありますが、GCPの場合は、Custom callbackを選択します。

image.png

各設定は下記の通りとなります。

項目 入力値
Type DATA_UPLINK
Channel URL
Url pattern 作成されたHTTPS Trigger URL*
Use HTTP Method POST
Send SNI
Headers Authorization Basic **
Content type application/json
Body { "deviceType" : "KCCS Network Monitoring", "device" : "{device}", "time" : {time}, "data" : "{data}", "seqNumber" : {seqNumber} }

※GCP Cloud Functionsのデプロイで生成されたURL。(https://[リージョン]-[プロジェクト名].cloudfunctions.net/callback_data )

※※Atuthorizationは、.env.yamlファイルで定義したHTTP_USERとHTTP_PASSWDからBase64エンコードした文字列となります。

全て設定し、[OK]ボタンをクリックするとCallbackが追加され、成功すると、下図のようにCloud Functionsのログで、SigfoxメッセージがPub/Sub Publishされていることが確認できます。
image.png

Sigfoxメッセージ保存用データベースを作成

次にSigfoxメッセージを保存するデータベースを作成します。

BigQueryテーブルの作成

  1. Google Cloud ConsoleのBigQuery画面へ移動します。
  2. 自身のプロジェクトにデータセットを作成します。データセットIDは任意(ここではds_sigfox)、ロケーションは今回は東京(asia-northeast1)にしておきます。
    image.png

  3. 作成したデータセットを選択し、テーブルを新規に作成します。
    image.png
    テーブルを作成する際には、Pub/Sub で入力されるデータ構造に準拠したテーブル定義をする必要があります。今回は、Sigfoxコールバックとして設定したdeviceType, device, time, data, seqNumberの5項目になります。

  4. テーブルが作成出来たら、テーブルの詳細画面から表IDをメモしておきます。
    image.png
    表IDは、[プロジェクトID]:[データソースID].[テーブルID]になります。

Pub/SubからBigQueryに保存するCloud Functionsを作成

Pub/SubからBigQueryにデータ保存する方法は、Dataflowを使うと簡単にできますが、Dataflowの料金体系が、数個のデバイスだけの場合には割高になるため、ここではCloud Functionsで実装します。

上述のSigfox Callback用Cloud Functionsをデプロイと同様に下記コードをデプロイします。

main.py
import os
import base64
import json
from google.cloud import bigquery

def main(event, context):
    """Triggered from a message on a Cloud Pub/Sub topic.
    Args:
         event (dict): Event payload.
         context (google.cloud.functions.Context): Metadata for the event.
    """
    PROJECT    = os.environ.get('PROJECT')
    DATASET    = os.environ.get('DATASET')
    TABLE      = os.environ.get('TABLE')
    print(DATASET)

    pubsub_message = base64.b64decode(event['data']).decode('utf-8')
    print(pubsub_message)

    d = json.loads(pubsub_message)

    output_rows = []

    output_rows.append([
        d['deviceType'],
        d['device'],
        d['time'],
        d['data'],
        d['seqNumber']
     ])

    bq_client   = bigquery.Client('zservice-295907')
    dataset_ref = bq_client.dataset('ds_pressure')
    table_ref   = dataset_ref.table('tb_pressure')
    table_obj   = bq_client.get_table(table_ref)
    error       = bq_client.insert_rows(table_obj, output_rows)

requirement.txt
google-api-python-client
google-cloud-bigquery
env.yaml
PROJECT: [ご自身のプロジェクト名]
DATASET: [ご自身のプロジェクト名]:[BigQueryのデータセット名]
TABLE: [ご自身のプロジェクト名]:[BigQueryのデータセット名].[テーブル名]

上記3種類のコードを準備できれば、下記コマンドを使用し、Cloud Functionsをデプロイします。
gcloud functions deploy FUNCTION_NAME --trigger-topic TOPIC_NAME FLAGS
ここでは、FUNCTION_NAME = storeToBigQuery、TOPIC_NAMEは、先に作成したPub/Subトピックであるsigfox-dataを指定します。FLAGSは、デプロイ時に指定するオプションですので、ここでは、--runtime python37 --env-vars-file .env.yaml としておきます。

動作確認

BigQueryのテーブルを確認すると、Sigfoxデバイスからのメッセージが保存されていることが確認できます。
image.png

image.png
Sigfox Japan KCCS

3
4
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4