LoginSignup
4

More than 1 year has passed since last update.

Organization

Sigfox CallbackとGoogle Cloud Platform連携

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

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
What you can do with signing up
4