RaspberryPiとAWS IoTを使用した温湿度の可視化[前編]

IoT

はじめに

GMOグローバルサイン・ホールディングス(以下GSHD)CTO室のringoと言います。私は今年新卒でGSHDに入社してGMOテクノロジーブートキャンプ(GMOインターネットグループ新卒のエンジニア職やクリエイティブ職に向けた研修プログラム)、仮配属(OJT)期間を経てCTO室にて研究開発を行っています。入社から3カ月ぐらいはフルリモートだったのですが、最近は週2日で出社しておりオフィスにも慣れてきたところです。まさか入社して半年でブログ立ち上げから運用までを任されるようになるとは思ってもみなかったです。また機会があったらブログ立ち上げや新卒所感みたいなことも書きたいと思います。
さて、今回はOJT期間中に作ったAWSとRaspberryPiを使った温湿度のモニタリングについて書きます。

きっかけ

OJT期間でAWSを扱ったきっかけについて思い出してみると、IoT向けサービスを展開する上で、既存のクラウドベースのIoTサービスについて調査することを目的に、AWSとAzureを使う。だった気がします。
調査と言われましても実際に使わないことには分からないことが多いな、ということでIoTのHello World的な位置づけ(だと勝手に思ってる)センシングからの可視化をやってみようとなりました。幸い私は学生時代ロボットクラブに所属していたこともあってハード面は比較的触れます。そのためデータ収集~クラウド上で可視化というテーマはソフトウェアやクラウド側に集中することができる最適なテーマだったと思います。

この記事で扱うこと

システムの全体図になります。今回の前編の記事ではセンサーの値の取得からAWS IoTに送信するまでを書きます。

記事の前半ではAWS IoTにラズパイを登録しMQTTによる送受信を行います。後半部分ではラズパイにセンサーを接続しデータを取得し、整形してAWS IoTへ送信するところまでを行います。

用意するもの

  • AWSのアカウント
  • RaspberryPi
    RaspbianのセットアップとPythonのインストールができているもの
  • 温湿度センサ
    今回はBME280を使用しました。

ラズパイとAWS IoTを接続

Using the AWS IoT Device SDK to connect a device to AWS IoT Coreを参考にしながらAWS IoTにラズパイを接続します。
接続の手順は以下のようになります。
1. ポリシーを作成
2. ラズパイをAWS IoTに登録
3. 接続のための証明書を発行
4. 作成したポリシーを証明書にアタッチ

ポリシーを作成

AWS IoT Coreの画面を開き左のダッシュボードから 安全性 > ポリシー と進み 作成を選択します。

ポリシー名を入力し、操作するアクションを追加していきます。リソースARNの文字列はアクションを選択すると自動的に表示されます。
ここでは画像のようにポリシー名をblograspiPoricy、デバイスの接続とPublishだけ許可するポリシーを作成しました。

ラズパイをAWS IoTに登録

管理 > モノと進み作成を選択します。
作成を選択すると単一での登録か一括での登録かを聞かれるので単一での登録を選択し、Thing Registry にデバイスを追加の画面へ進みます。

この画面ではデバイス名やデバイスのタイプやグループが設定できます。デバイス名はblograspiとしました。

接続のための証明書を発行

モノに証明書を追加の画面が表示されます。自分で証明書を追加することもできますが、AWS IoTでは証明書を発行してくれるのでそれを利用します。1-Click 証明書作成 (推奨)を選択すると作成された証明書をダウンロードする画面に進みます。

ここで登録したモノの証明書、公開鍵、秘密鍵をダウンロードしておきます。AWS IoTのCA証明書もダウンロードしておきます。ダウンロードする証明書はAmazonRootCA1になります。証明書をダウンロードしたら忘れずに有効化を選択して証明書を有効にします。
ポリシーを追加を選択して次へ進みます。

作成したポリシーを証明書にアタッチ

ポリシーの一覧が表示されるので先ほど作成したポリシーを選択してモノの登録を完了します。

データの送信のテスト

Python の使用時に、デバイスから AWS IoT Core に MQTT メッセージを発行する方法を教えてください。
このページのサンプルプログラムをコピペしてきてpublish.pyとして保存し次の部分を適宜変更します。

ENDPOINT = "Your custom endpoint"
CLIENT_ID = "blograspi"
PATH_TO_ROOT = "./cert/AmazonRootCA1.pem"
PATH_TO_CERT = "./cert/Your-certificate.pem.crt"
PATH_TO_KEY = "./cert/Your-private.pem.key"
TOPIC = "pub/myhome"

エンドポイントはAWS IoTのダッシュボードから設定を選択すると確認できます。
また、証明書の発行でダウンロードした証明書、秘密鍵、CA証明書を配置しておきます。

プログラムの変更ができたらAWS IoTのコンソールで ACT > テスト と進みます。ここでトピックへメッセージを発行したり、メッセージをサブスクライブすることができます。プログラムを動かす前にトピックのサブスクリプションにpub/myhomeと入力しサブスクライブしておきます。

$ pip install awsiotsdk
$ python publish.py

ラズパイ上で上のコマンドを実行するとサンプルプログラムが実行されAWS IoTへメッセージが送信されるはずです。


正しくメッセージを受け取れていれば画像のようにAWS IoT上で送信されたメッセージが確認できます。

センサーの接続

センサーの接続にはSWITCHCIENCEのサンプルを使用しました。
SWITCHSCIENCE/BME280
Python2用に書かれているのでちょっと編集します。
変更点としては

  • print部分の書き方をPython3用に書き換え
  • 取得した生データを補正する関数内でprintしてたのを使いやすいように返り値で取得できるように変更

編集したコードがコチラになります。
また、動かすのにsmbusが必要になります。

これでセンサーのから温度、湿度、気圧が取得できます。

データの送信

センサーの接続とデータの送信どちらもできることが確認できたのであとは組み合わるだけです。
送信する頻度は1秒ごとで、JSONの形に整形して送信することにします。

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

from awscrt import io, mqtt, auth, http
from awsiot import mqtt_connection_builder

import bme280
import json
import datetime
import time

# Define ENDPOINT, CLIENT_ID, PATH_TO_CERT, PATH_TO_KEY, PATH_TO_ROOT, MESSAGE, TOPIC, and RANGE
ENDPOINT = "Your custom endpoint"
CLIENT_ID = "blograspi"
PATH_TO_ROOT = "./cert/AmazonRootCA1.pem"
PATH_TO_CERT = "./cert/Your-certificate.pem.crt"
PATH_TO_KEY = "./cert/Your-private.pem.key"
TOPIC = "pub/myhome"

# Spin up resources
event_loop_group = io.EventLoopGroup(1)
host_resolver = io.DefaultHostResolver(event_loop_group)
client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)
mqtt_connection = mqtt_connection_builder.mtls_from_path(
            endpoint=ENDPOINT,
            cert_filepath=PATH_TO_CERT,
            pri_key_filepath=PATH_TO_KEY,
            client_bootstrap=client_bootstrap,
            ca_filepath=PATH_TO_ROOT,
            client_id=CLIENT_ID,
            clean_session=False,
            keep_alive_secs=6
            )
print("Connecting to {} with client ID '{}'...".format(
        ENDPOINT, CLIENT_ID))
# Make the connect() call
connect_future = mqtt_connection.connect()
# Future.result() waits until a result is available
connect_future.result()
print("Connected!")
# Publish message to server desired number of times.
while True:
    date = str(datetime.date.today())
    nowtime = datetime.datetime.now()
    get_time = str(nowtime.hour) + ':' + str(nowtime.minute) + ':' + str(nowtime.second)
    sensor_data = bme280.readData()
    temp = "%6.2f" % (sensor_data[0])
    press = "%7.2f" % (sensor_data[1])
    hum = "%6.2f" % (sensor_data[2])
    data = {
        'raspiId' : CLIENT_ID,
        'temperature' : temp,
        'pressure' : press,
        'humidity' : hum,
        'get_date' : date,
        'get_time' : get_time,
    }
    # client.publish(TOPIC, json.dumps(data), 1)
    mqtt_connection.publish(topic=TOPIC, payload=json.dumps(data), qos=mqtt.QoS.AT_LEAST_ONCE)
    time.sleep(1)
disconnect_future = mqtt_connection.disconnect()
disconnect_future.result()

AWS IoTで受信

画像のように送信されたデータがAWS IoTで確認出来たら成功です。

終わりに

今回はAWS IoTにラズパイを登録し、センサーのデータを送信するところまでできました。これだけだとただデータを送信しているだけで保存や解析などは何もできていません。ですので、次回はデータを保存しグラフ化する部分について書く予定です。