

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# チュートリアル: AWS IoT と Raspberry Pi を使用した土壌湿度のモニタリング
<a name="iot-moisture-tutorial"></a>

このチュートリアルでは、[Raspberry Pi](https://www.raspberrypi.org/)、湿度センサー、 AWS IoT および を使用して、家の植物または庭の土壌湿度レベルをモニタリングする方法を示します。Raspberry Pi は、センサーから湿度レベルと温度を読み取り、データを送信するコードを実行します AWS IoT。湿度レベル AWS IoT がしきい値を下回ると、Amazon SNS トピックにサブスクライブしているアドレスに E メールを送信するルールを で作成します。

**注記**  
このチュートリアルは最新ではない可能性があります。このトピックの最初の公開以降に、いくつかの参照が置き換えられている可能性があります。

**Contents**
+ [前提条件](#iot-moisture-prereqs)
+ [セットアップ AWS IoT](iot-moisture-setup.md)
  + [ステップ 1: AWS IoT ポリシーを作成する](iot-moisture-policy.md)
  + [ステップ 2: AWS IoT モノ、証明書、プライベートキーを作成する](iot-moisture-create-thing.md)
  + [ステップ 3: Amazon SNS トピックおよびサブスクリプションを作成する](iot-moisture-create-sns-topic.md)
  + [ステップ 4: E メールを送信する AWS IoT ルールを作成する](iot-moisture-create-rule.md)
+ [Raspberry Pi と湿度センサーのセットアップ](iot-moisture-raspi-setup.md)

## 前提条件
<a name="iot-moisture-prereqs"></a>

このチュートリアルを完了するには、以下が必要です。
+  AWS アカウント。
+ 管理者権限を持つ IAM ユーザー。
+ [AWS IoT コンソール](https://console.aws.amazon.com/iot/home)にアクセスするための、Windows、macOS、Linux、または Unix を実行している開発用コンピュータ。
+ 最新の [Raspberry Pi OS](https://www.raspberrypi.com/software/operating-systems/) を実行する [Raspberry Pi 3B または 4B](https://www.raspberrypi.com/products/)。インストール手順については、Raspberry Pi ウェブサイトの「[Install an operating system](https://www.raspberrypi.com/documentation/computers/getting-started.html#installing-the-operating-system)」を参照してください。
+ Raspberry Pi 用のモニター、キーボード、マウス、Wi-Fi ネットワークまたはイーサネット接続。
+ Raspberry Pi 対応の湿度センサー。このチュートリアルで使用するセンサーは、[Adafruit STEMMA I2C 容量性湿度センサー](https://www.adafruit.com/product/4026)で、[JST 4 ピンからメスソケットへのケーブルヘッダー](https://www.adafruit.com/product/3950)を備えています。

# セットアップ AWS IoT
<a name="iot-moisture-setup"></a>

このチュートリアルを完了するには、次のリソースを作成する必要があります。デバイスを に接続するには AWS IoT、IoT モノ、デバイス証明書、および AWS IoT ポリシーを作成します。
+  AWS IoT モノ。

  モノは物理デバイス (この場合は Rasberry Pi) を表し、デバイスに関する静的メタデータを含みます。
+ デバイス証明書。

   AWS IoTに接続して認証するには、すべてのデバイスにデバイス証明書が必要です。
+  AWS IoT ポリシー。

  各デバイス証明書には、1 つ以上の AWS IoT ポリシーが関連付けられています。これらのポリシーは、デバイスがアクセスできる AWS IoT リソースを決定します。
+  AWS IoT ルート CA 証明書。

  デバイスやその他のクライアントは、 AWS IoT ルート CA 証明書を使用して、通信している AWS IoT サーバーを認証します。詳細については、「[サーバー認証](server-authentication.md)」を参照してください。
+  AWS IoT ルール。

  ルールには、クエリと 1 つ以上のルールアクションが含まれます。クエリは、デバイスメッセージからデータを抽出して、メッセージデータを処理する必要があるかどうかを判断します。ルールアクションにより、データがクエリに一致する場合の処理が指定されます。
+ Amazon SNS トピックおよびトピックサブスクリプション。

  このルールでは、Raspberry Pi からの湿度データがリッスンされます。値がしきい値を下回る場合、Amazon SNS トピックにメッセージを送信します。Amazon SNS は、トピックにサブスクライブしているすべての E メールアドレスにそのメッセージを送信します。

 



# ステップ 1: AWS IoT ポリシーを作成する
<a name="iot-moisture-policy"></a>

Raspberry Pi がメッセージを接続および送信できるようにする AWS IoT ポリシーを作成します AWS IoT。

1. [AWS IoT コンソール](https://console.aws.amazon.com/iot)で、[**今すぐ始める**] ボタンが表示された場合はそれをクリックします。それ以外の場合は、ナビゲーションペインで **[Security]** (セキュリティ) を展開し、**[Policies]** (ポリシー) を選択します。

1. [**ポリシーはまだ作成されていません**] ダイアログボックスが表示された場合は、[**ポリシーの作成**] を選択します。それ以外の場合は、[**Create (作成) **] を選択します。

1.  AWS IoT ポリシーの名前を入力します (例: **MoistureSensorPolicy**)。

1. [**Add statements (ステートメントの追加)**] セクションで、既存のポリシーを次の JSON に置き換えます。*region* と *account* を AWS リージョン と AWS アカウント number に置き換えます。  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "iot:Connect",
               "Resource": "arn:aws:iot:us-east-1:123456789012:client/RaspberryPi"
           },
           {
               "Effect": "Allow",
               "Action": "iot:Publish",
               "Resource": [
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/update",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/delete",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/get"
               ]
           },
           {
               "Effect": "Allow",
               "Action": "iot:Receive",
               "Resource": [
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/update/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/delete/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/get/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/update/rejected",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/delete/rejected"
               ]
           },
           {
               "Effect": "Allow",
               "Action": "iot:Subscribe",
               "Resource": [
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/update/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/delete/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/get/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/update/rejected",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/delete/rejected"
               ]
           },
           {
               "Effect": "Allow",
               "Action": [
                   "iot:GetThingShadow",
                   "iot:UpdateThingShadow",
                   "iot:DeleteThingShadow"
               ],
               "Resource": "arn:aws:iot:us-east-1:123456789012:thing/RaspberryPi"
           }
       ]
   }
   ```

1. **[作成]** を選択します。

# ステップ 2: AWS IoT モノ、証明書、プライベートキーを作成する
<a name="iot-moisture-create-thing"></a>

Raspberry Pi を表すモノを AWS IoT レジストリに作成します。

1. [AWS IoT コンソール](https://console.aws.amazon.com/iot/home)のナビゲーションペインで、[**管理**]、[**モノ**] の順に選択します。

1. [**まだモノがありません**] ダイアログボックスが表示された場合は、[**モノの登録**] を選択します。それ以外の場合は、[**Create (作成)**] を選択します。

1. ** AWS IoT モノの作成**ページで、**モノを 1 つ**作成する を選択します。

1. [**Add your device to the device registry (デバイスレジストリへのデバイスの追加)**] ページで、IoT モノの名前 (例: **RaspberryPi**) を入力し、[**次へ**] を選択します。作成後にモノの名前は変更できません。モノの名前を変更するには、新しいモノを作成して、新しい名前を付け、古いモノを削除する必要があります。

1. [**モノに証明書を追加**] ページで、[**証明書の作成**] を選択します。

1. [**ダウンロード**] リンクを選択して、証明書、プライベートキー、ルート CA 証明書をダウンロードします。
**重要**  
これは、証明書とプライベートキーをダウンロードできる唯一の時間です。

1. 証明書を有効にするには、[**Activate**] (有効化) を選択します。デバイスが AWS IoTに接続するには、証明書がアクティブである必要があります。

1. [**ポリシーのアタッチ**] を選択します。

1. [**Add a policy for your thing (モノのポリシーを追加)**] で、[**MoistureSensorPolicy**]、[**Register Thing (モノの登録)**] の順に選択します。

# ステップ 3: Amazon SNS トピックおよびサブスクリプションを作成する
<a name="iot-moisture-create-sns-topic"></a>

Amazon SNS トピックおよびサブスクリプションを作成します。

1. [AWS SNS コンソール](https://console.aws.amazon.com/sns/home)のナビゲーションペインで [**Topics**] (トピック) を選択し、[**Create topic**] (トピックの作成) を選択します。

1. タイプを **[標準]** として選択し、トピックの名前を入力します (例: **MoistureSensorTopic**）。

1. トピックの表示名を入力します (例: **Moisture Sensor Topic**)。これは、Amazon SNS コンソールでトピックに表示される名前です。

1. [**トピックの作成**] を選択します。

1. Amazon SNS トピックの詳細ページで、**[Create subscription]** (サブスクリプションの作成) を選択します。

1. [**Protocol (プロトコル)**] として [**Email (E メール)**] を選択してください。

1. [**エンドポイント**] に E メールアドレスを入力します。

1. [**Create subscription**] を選択します。

1. E メールクライアントを開き、**MoistureSensorTopic** という件名のメッセージを探します。E メールを開き、[**サブスクリプションを確認**] リンクを選択します。
**重要**  
サブスクリプションを確認するまで、この Amazon SNS トピックからの E メールアラートは受信されません。

入力したテキストが記載された E メールメッセージが届きます。

# ステップ 4: E メールを送信する AWS IoT ルールを作成する
<a name="iot-moisture-create-rule"></a>

 AWS IoT ルールは、デバイスからメッセージを受信したときに実行するクエリと 1 つ以上のアクションを定義します。 AWS IoT ルールエンジンは、デバイスによって送信されたメッセージをリッスンし、メッセージ内のデータを使用して何らかのアクションを実行する必要があるかどうかを判断します。詳細については、「[のルール AWS IoT](iot-rules.md)」を参照してください。

このチュートリアルでは、Raspberry Pi が `aws/things/RaspberryPi/shadow/update` にメッセージを発行します。これは、デバイスと Thing Shadow サービスで使用される内部 MQTT トピックです。Raspberry Pi は、次の形式のメッセージを発行します。

```
{
    "reported": {
        "moisture" : moisture-reading,
        "temp" : temperature-reading
    }
}
```

受信メッセージから湿度と温度データを抽出するクエリを作成します。また、湿度の読み取り値がしきい値を下回っている場合、データを受け取り、そのデータを Amazon SNS トピックのサブスクライバーに送信する Amazon SNS アクションも作成します。

**Amazon SNS ルールを作成する**

1. [[AWS IoT コンソール]](https://console.aws.amazon.com/iot/home) で、**[メッセージのルーティング]** を選択し、**[ルール]** を選択します。[**ルールはまだ作成されていません**] ダイアログボックスが表示された場合は、[**ルールの作成**] を選択します。それ以外の場合は、**[ルールを作成]** を選択します。

1. **[ルールプロパティ]** ページで、**MoistureSensorRule** などの **[ルール名]** を入力し、**Sends an alert when soil moisture level readings are too low** などの短い **[ルールの説明]** を入力します。

1. **[次へ]** を選択し、SQL ステートメントを設定します。**SQL バージョン**を **2016-03-23** として選択し、次の AWS IoT SQL クエリステートメントを入力します。

   ```
   SELECT * FROM '$aws/things/RaspberryPi/shadow/update/accepted' WHERE state.reported.moisture < 400
   ```

   このステートメントは、`moisture` の読み取り値が `400` より小さい場合にルールアクションをトリガーします。
**注記**  
別の値の使用が必要になる場合があります。Raspberry Pi でコードを実行したら、センサーに触れたり、水に入れたり、プランター内に置いたりすることで、センサーから取得した値を表示できます。

1. **[次へ]** を選択し、ルールアクションをアタッチします。**[アクション 1]** で、**[Simple Notification Service]** を選択します。このルールアクションの説明は **[SNS プッシュ通知としてメッセージを送信します]** です。

1. **[SNS トピック]** では、[ステップ 3: Amazon SNS トピックおよびサブスクリプションを作成する](iot-moisture-create-sns-topic.md)、、**MoistureSensorTopic** で作成したトピックを選択し、**[メッセージ形式]** を **[RAW]** のままにします。**[IAM role]** (IAM ロール) は、**[Create a new role]** (新しいロールの作成) を選択します。ロールの名前 (例: **LowMoistureTopicRole**) を入力し、**[ロールを作成]** を選択します。

1. **[次へ]** を選択して確認してから、**[作成]** を選択してルールを作成します。

# Raspberry Pi と湿度センサーのセットアップ
<a name="iot-moisture-raspi-setup"></a>



microSD カードを Raspberry Pi に挿入し、モニター、キーボード、マウスを接続し、Wi-Fi を使用していない場合はイーサネットケーブルも接続します。電源ケーブルはまだ接続しないでください。

JST ジャンパーケーブルを湿度センサーに接続します。ジャンパーの反対側には次の 4 本のワイヤがあります。
+ 緑: I2C SCL
+ 白: I2C SDA
+ 赤: 電源 (3.5 V)
+ 黒: アース

右側にあるイーサネットジャックで Raspberry Pi を保持します。この向きでは、上部に 2 列の GPIO ピンがあります。次の順序で、湿度センサーのワイヤをピンの下の列に接続します。左端のピンから、赤 (電源)、白 (SDA)、緑 (SCL) を接続します。1 つのピンをスキップし、黒い (アース) ワイヤを接続します。詳細については、「[Python Computer Wiring](https://learn.adafruit.com/adafruit-stemma-soil-sensor-i2c-capacitive-moisture-sensor/python-circuitpython-test)」を参照してください。

電源ケーブルを Raspberry Pi に接続し、もう一方の端をコンセントに接続して電源を入れます。

**Raspberry Pi を設定します。**

1. [**Welcome to Raspberry Pi**] で、[**Next**] を選択します。

1. 国、言語、タイムゾーン、キーボードレイアウトを選択します。[**Next**] を選択します。

1. Raspberry Pi のパスワードを入力し、[**Next**] を選択します。

1. Wi-Fi ネットワークを選択し、[**Next**] を選択します。Wi-Fi ネットワークを使用していない場合は、[**Skip**] を選択します。

1. [**Next**] を選択して、ソフトウェアの更新を確認します。更新が完了したら、[**Restart**] を選択して Raspberry Pi を再起動します。

Raspberry Pi が起動したら、I2C インターフェイスを有効にします。

1. Raspbian デスクトップの左上隅にある Raspberry アイコンをクリックし、[**Preferences**]、[**Raspberry Pi Configuration**] の順に選択します。

1. [**Interfaces**] タブの [**I2C**] で、[**Enable**] を選択します。

1. [**OK**] を選択します。

Adafruit STEMMA 湿度センサーのライブラリは、CircuitPython 向けに記述されています。それらのライブラリを Raspberry Pi で実行するには、最新バージョンの Python 3 をインストールする必要があります。

1. コマンドプロンプトから次のコマンドを実行して、Raspberry Pi ソフトウェアを更新します。

   `sudo apt-get update`

   `sudo apt-get upgrade`

1. 次のコマンドを実行して、Python 3 のインストールを更新します。

   `sudo pip3 install --upgrade setuptools`

1. 次のコマンドを実行して、Raspberry Pi GPIO ライブラリをインストールします。

   `pip3 install RPI.GPIO`

1. 次のコマンドを実行して、Adafruit Blinka ライブラリをインストールします。

   `pip3 install adafruit-blinka`

   詳細については、「[Installing CircuitPython Libraries on Raspberry Pi](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi)」を参照してください。

1. 次のコマンドを実行して、Adafruit Seesaw ライブラリをインストールします。

   `sudo pip3 install adafruit-circuitpython-seesaw`

1. 次のコマンドを実行して、 AWS IoT Device SDK for Python をインストールします。

   `pip3 install AWSIoTPythonSDK`

これで、必要なすべてのライブラリが Raspberry Pi にインストールされました。**moistureSensor.py** という名前のファイルを作成し、次の Python コードをファイルにコピーします。

```
from adafruit_seesaw.seesaw import Seesaw
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient
from board import SCL, SDA

import logging
import time
import json
import argparse
import busio

# Shadow JSON schema:
#
# {
#   "state": {
#       "desired":{
#           "moisture":<INT VALUE>,
#           "temp":<INT VALUE>            
#       }
#   }
# }

# Function called when a shadow is updated
def customShadowCallback_Update(payload, responseStatus, token):

    # Display status and data from update request
    if responseStatus == "timeout":
        print("Update request " + token + " time out!")

    if responseStatus == "accepted":
        payloadDict = json.loads(payload)
        print("~~~~~~~~~~~~~~~~~~~~~~~")
        print("Update request with token: " + token + " accepted!")
        print("moisture: " + str(payloadDict["state"]["reported"]["moisture"]))
        print("temperature: " + str(payloadDict["state"]["reported"]["temp"]))
        print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")

    if responseStatus == "rejected":
        print("Update request " + token + " rejected!")

# Function called when a shadow is deleted
def customShadowCallback_Delete(payload, responseStatus, token):

     # Display status and data from delete request
    if responseStatus == "timeout":
        print("Delete request " + token + " time out!")

    if responseStatus == "accepted":
        print("~~~~~~~~~~~~~~~~~~~~~~~")
        print("Delete request with token: " + token + " accepted!")
        print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")

    if responseStatus == "rejected":
        print("Delete request " + token + " rejected!")


# Read in command-line parameters
def parseArgs():

    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--endpoint", action="store", required=True, dest="host", help="Your device data endpoint")
    parser.add_argument("-r", "--rootCA", action="store", required=True, dest="rootCAPath", help="Root CA file path")
    parser.add_argument("-c", "--cert", action="store", dest="certificatePath", help="Certificate file path")
    parser.add_argument("-k", "--key", action="store", dest="privateKeyPath", help="Private key file path")
    parser.add_argument("-p", "--port", action="store", dest="port", type=int, help="Port number override")
    parser.add_argument("-n", "--thingName", action="store", dest="thingName", default="Bot", help="Targeted thing name")
    parser.add_argument("-id", "--clientId", action="store", dest="clientId", default="basicShadowUpdater", help="Targeted client id")

    args = parser.parse_args()
    return args


# Configure logging
# AWSIoTMQTTShadowClient writes data to the log
def configureLogging():

    logger = logging.getLogger("AWSIoTPythonSDK.core")
    logger.setLevel(logging.DEBUG)
    streamHandler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    streamHandler.setFormatter(formatter)
    logger.addHandler(streamHandler)


# Parse command line arguments
args = parseArgs()

if not args.certificatePath or not args.privateKeyPath:
    parser.error("Missing credentials for authentication.")
    exit(2)

# If no --port argument is passed, default to 8883
if not args.port: 
    args.port = 8883


# Init AWSIoTMQTTShadowClient
myAWSIoTMQTTShadowClient = None
myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient(args.clientId)
myAWSIoTMQTTShadowClient.configureEndpoint(args.host, args.port)
myAWSIoTMQTTShadowClient.configureCredentials(args.rootCAPath, args.privateKeyPath, args.certificatePath)

# AWSIoTMQTTShadowClient connection configuration
myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec
myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec

# Initialize Raspberry Pi's I2C interface
i2c_bus = busio.I2C(SCL, SDA)

# Intialize SeeSaw, Adafruit's Circuit Python library
ss = Seesaw(i2c_bus, addr=0x36)

# Connect to AWS IoT
myAWSIoTMQTTShadowClient.connect()

# Create a device shadow handler, use this to update and delete shadow document
deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(args.thingName, True)

# Delete current shadow JSON doc
deviceShadowHandler.shadowDelete(customShadowCallback_Delete, 5)

# Read data from moisture sensor and update shadow
while True:

    # read moisture level through capacitive touch pad
    moistureLevel = ss.moisture_read()

    # read temperature from the temperature sensor
    temp = ss.get_temp()

    # Display moisture and temp readings
    print("Moisture Level: {}".format(moistureLevel))
    print("Temperature: {}".format(temp))
    
    # Create message payload
    payload = {"state":{"reported":{"moisture":str(moistureLevel),"temp":str(temp)}}}

    # Update shadow
    deviceShadowHandler.shadowUpdate(json.dumps(payload), customShadowCallback_Update, 5)
    time.sleep(1)
```

このファイルを、見つけられる場所に保存します。以下のパラメータを使用して、コマンドラインから `moistureSensor.py` を実行します。

エンドポイント  
カスタム AWS IoT エンドポイント。詳細については、「[Device Shadow の REST API](device-shadow-rest-api.md)」を参照してください。

rootCA  
 AWS IoT ルート CA 証明書へのフルパス。

cert  
 AWS IoT デバイス証明書へのフルパス。

key  
 AWS IoT デバイス証明書のプライベートキーへのフルパス。

thingName  
モノの名前 (この場合は `RaspberryPi`)。

clientId  
MQTT クライアント ID。`RaspberryPi` を使用します。

コマンドラインは次のようになります。

`python3 moistureSensor.py --endpoint your-endpoint --rootCA ~/certs/AmazonRootCA1.pem --cert ~/certs/raspberrypi-certificate.pem.crt --key ~/certs/raspberrypi-private.pem.key --thingName RaspberryPi --clientId RaspberryPi`

センサーに触れたり、プランター内に置いたり、コップの水に入れたりして、センサーがさまざまなレベルの湿気にどのように反応するかを確認します。必要に応じて、`MoistureSensorRule` でしきい値を変更できます。湿度センサーの読み取り値がルールの SQL クエリステートメントで指定された値を下回ると、 は Amazon SNS トピックにメッセージ AWS IoT を発行します。湿度と温度データが含まれた E メールメッセージが届きます。

Amazon SNS からの E メールメッセージの受信を確認したら、**Ctrl\$1C** を押して Python プログラムを停止します。Python プログラムが、料金がかかる量のメッセージを送信することはほとんどありませんが、終了したらプログラムを停止することをお勧めします。