はじめに
暑いですよね。外出時に家電(エアコン)をリモコン制御してみたいと思い、Raspberry Piを買ってみました。
リモコンは下記の学習リモコン(Raspberry Pi専用)を買いました。便利です!
全体像
Slackで命令すると、自宅のエアコンが稼働します。やったね!!!
AWS IoTを使ってみたかったのです。
(自宅のRaspberry Piとクラウド(インターネット)をセキュアに接続したかった、というのもあります)
それでは、下記の順番で簡単に解説していきます。
- IoT Core
- API Gateway
- Slack
環境など
家
Raspberry Pi
- Raspberry Pi 3 Mobile B+
- Raspbian 9.4
- Python 3.6
家電
- エアコン
- 本体:MSZ-GV225-W
- リモコン:RH151
AWS
- API Gateway
- IoT Core
IoT Core
こちらを参考にIoT CoreとRaspberry Piの設定を行います。
-
https://qiita.com/gnk263/items/a7937259746c81a6b052
- 本記事を実現するにあたって、事前確認した際の記事です
具体的には下記となります。
- ポリシーの作成(IoT Core用)
- モノの作成
- 証明書の作成とダウンロード
- Raspberry PiにAWS IoTのSDKをインストール
API Gateway
API GatewayとIoT Coreの連携は、下記を参考にさせていただきました。
ポリシー作成
ロールにアタッチするポリシーを作成します。ポリシー名は任意です。
- サービス: IoT
- アクション: 書き込み(Publish)
- リソース: すべてのリソース
- 名前: iot-publish-poricy
ロール作成
API Gatewayで使用するロールを作成します。ロール名は任意です。
- ロール名: ApiGateway-HomeControl-Role
さきほど作成したポリシーをアタッチします。
なお、ここで作成したロールARNをコピーしておきます。
IoTエンドポイントの確認
IoT Coreの設定を選択し、エンドポイントをメモしておきます。
APIの作成
API GatewayのTOP画面にアクセスし、API作成を行います。API名は任意です。
- API名: HomeControl
リソースの作成
作成したAPIに対するリソースを作成します。リソース名は任意です。
- リソース名: control
メソッドの作成
POSTメソッドを作成します。
POSTメソッドのセットアップを行います。AWSリージョンやサブドメインは必要に応じて読み替えてください。
- 統合タイプ: AWSサービス
- AWSリージョン: ap-northeast-1
- AWSサブドメイン: xxxxx(IoTエンドポイント先頭の固有部分)
- HTTPメソッド: POST
- アクションの種類: パス上書きの使用
- パス上書き: Publishしたいtopics(先頭のtopicsが必要)
- 実行ロール: 先ほど作成したロール
APIの動作確認
IoT Coreのテスト準備
IoT Coreのテストを選択し、さきほど設定したトピックをsubscribeします。
なお、このときは、topics/
を除いて入力してください。
API Gatewayでテスト実行
API Gatewayでさきほど作成したPOSTメソッドを選択し、テストします。
リクエスト本文を適当に入力し、テストボタンを選択します。
{
"text": "this is test message!!!"
}
テスト結果
動作結果として、下記となれば成功です!
- API Gatewayのメソッドテスト
- ステータス: 200
- レスポンス本文: "message": "OK"
- IoT Coreのsubscribe
- "text": "this is test message!!!"
APIのデプロイ
アクションからAPIのデプロイを選択します。
新しいステージを作成してデプロイします。内容は適当です。
先ほど作成したControlのPOSTメソッドを選択し、URLをコピーしておきます。
Slack
Slash Commandsを使用します。アプリを検索して追加してください。
コマンドは/control
としておきます。お好みでどうぞ。
設定画面のURLに、さきほどデプロイしたAPIのアドレスを貼り付けます。
他の設定はお好みでどうぞ。最後に保存しましょう。
動作確認
さきほどと同じようにIoT Coreの準備をしましょう。手順は省略します。
ブラウザを開きっぱなしの場合はそのままでOKです。
では、実際にslackで試しましょう!
テスト結果
Slackのテスト結果
とりあえず応答が返ってきました。いい感じです。
IoT Coreのテスト結果
IoT Coreはこうなりました。
どうやらjson形式ではないようです。
API Gatewayの設定を頑張ればjson形式に変換できそうですが、今回はこのまま進めます。
Raspberry Pi
では、最後にRaspberry Piの環境作成を行っていきます。
AWS IoT CoreとRaspberry Piの接続については、下記を参考にしてください。これ以降はできるものとして進めていきます。
リモコンの学習
最初に紹介した通り、下記を使用します。
SW-No.1にエアコン電源ONを学習させます。
(学習方法は製品の説明書を参考にしてください)
- SW-No.1
- GPIO No.4
- PIN No.7
学習後、正常に動作するかを確認してください。
ソースコード
プログラム終了時にGPIO.cleanup()
を実行する必要があるため、実行ディレクトリにfinish.txt
を作成することで終了トリガーとしています。
(と、ここまで作っておいて、Slackでfinishパラメータを与えたらいいだけでは?と気づきました……)
IoT Coreとの接続に必要なパラメータは、外部設定ファイル(config.ini)から読み込むようにしています。
import os
import configparser
import time
import json
import RPi.GPIO as GPIO
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
# Use PIN 7 (GPIO 4)
GPIO_AIRCON_PIN = 7
# programme finish trigger file
FINISH_FILE = "finish.txt"
def main():
init_gpio()
(root_ca, private_key, certificate,
client_id, endpoint, port, topic) = parse_config_file()
# https://s3.amazonaws.com/aws-iot-device-sdk-python-docs/sphinx/html/index.html
client = AWSIoTMQTTClient(client_id)
client.configureEndpoint(endpoint, port)
client.configureCredentials(root_ca, private_key, certificate)
client.configureAutoReconnectBackoffTime(1, 32, 20)
client.configureOfflinePublishQueueing(-1)
client.configureDrainingFrequency(2)
client.configureConnectDisconnectTimeout(10)
client.configureMQTTOperationTimeout(5)
client.connect()
client.subscribe(topic, 1, subscribe_callback)
while True:
time.sleep(5)
if is_finish():
os.remove(FINISH_FILE)
GPIO.cleanup()
print("Finish remote controller")
break
def init_gpio():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(GPIO_AIRCON_PIN, GPIO.OUT, initial=GPIO.HIGH)
def parse_config_file():
config = configparser.ConfigParser()
config.read("config.ini")
return (
config["AWS_IOT_CONNECT"]["ROOT_CA"],
config["AWS_IOT_CONNECT"]["PRIVATE_KEY"],
config["AWS_IOT_CONNECT"]["CERTIFICATE"],
config["AWS_IOT_CORE"]["CLIENT_ID"],
config["AWS_IOT_CORE"]["ENDPOINT"],
int(config["AWS_IOT_CORE"]["PORT"]),
config["AWS_IOT_CORE"]["TOPIC"]
)
def subscribe_callback(client, userdata, message):
print("Received a new message: ")
print(message.payload)
print("from topic: ")
print(message.topic)
params = parse_payload(message.payload.decode(encoding="utf-8"))
print(json.dumps(params, indent=4))
remote_control(params)
print("--------------\n\n")
def parse_payload(payload):
params = {}
key_value_list = payload.split("&")
for item in key_value_list:
(key, value) = item.split("=")
params[key] = value
return params
def remote_control(params):
if params["text"] == "aircon":
print("Execute GPIO_AIRCON_PIN")
execute(GPIO_AIRCON_PIN)
def execute(pin_no):
GPIO.output(pin_no, True)
time.sleep(0.5)
GPIO.output(pin_no, False)
time.sleep(0.5)
def is_finish():
if os.path.isfile(FINISH_FILE):
return True
return False
if __name__ == "__main__":
main()
[AWS_IOT_CONNECT]
ROOT_CA = ./cert/root_ca.pem
PRIVATE_KEY = ./cert/private.pem.key
CERTIFICATE = ./cert/certificate.pem.crt.txt
[AWS_IOT_CORE]
CLIENT_ID = test_client_id
ENDPOINT = xxxxxxxnortheast-1.amazonaws.com
PORT = 8883
TOPIC = raspberry_pi/test
config.iniファイルの内容は、適宜変更してください。
ソースコードは、GitHubにも置いています。
動作方法
それでは、実際に動作してみましょう!!!!
開始
Raspberry Piで下記コマンドを実行します。
ssh接続を解除してもバックグラウンド実行してほしいため、nohup
を使用しています。
$ nohup sudo python sample_remote_control.py > output.txt &
slackで制御!
/control aircon
エアコン
が起動する!!!
終了
Raspberry Piで下記コマンドを実行します。
$ touch finish.txt
まとめ
エアコンの電気代を節約しつつ、仕事から解放されたらSlackでエアコンをONにすることで、帰宅時には快適です!!!