AWSIoTとMQTTでラジコンを屋外からリモート操作

以下の記事で作成したラジコンを、屋外から操作するようにしてみます。 camelrush.hatenablog.com

従来のイメージ

もともと、このラジコンはスマホテザリングを使用したWifi環境で動作するようにしていました。

f:id:camelrush:20200331001438p:plain
従来のイメージ

新しいイメージ

これを屋外から操作できるように構成変更します。

f:id:camelrush:20200330231650p:plain
新しいイメージ

環境

  • MQTTブローカーには、AWS IoT Coreを使用します。
  • Publisher、Subscriberとも、Pahoライブラリを使用します。
  • PublisherはS3上に配置した静的サイトで作成し、そこからPaho on JavaScriptで送信します。
  • SubscriberはRaspberryPi上のPythonで行います。こちらもPaho on Pythonです。

使用ソース

github.com

AWS IoT Core 環境設定

  • AWS IoT Coreにブローカー設定します。最初にモノ※の登録を行います。
  • ※モノ=Thingsの直訳で、操作対象のデバイス自体を指しているようなのだけど、もうちょっとよい訳はなかったのかなぁ…。
  • 以下の記事を参考に、モノの登録を行っていきます。
  • qiita.com
  • 登録に併せて、RootCA証明書、1-Click証明書と秘密鍵のダウンロードを行い、ポリシーのアタッチまで進めてください。

IAMユーザの作成

以下のページを参考に、IAMユーザを追加します。
my-scribble.net

Subscriber(Python on RaspberryPi)の作成

RaspberryPi上に、Subscriber環境を構築します。

  • 最初に、Python環境に対して、Pahoライブラリのインストールを行います。
$ pip install paho-mqtt
  • プログラムは前述のGitのファイルをCloneして配置します。
  • Clone内容のうち「awcert」フォルダの内容を削除し、前述のIoT Core環境構築でダウンロードしたRootCA証明書、1-Click証明書と秘密鍵に差し替えます。
  • ソース「miniRc.py」上部にある、「# MQTT定義」部分を、作成したIoTCore環境の内容に書き換えます。
# MQTT定義
AWSIoT_ENDPOINT = "xxxxxxxxxxxx-xxx.iot.ap-northeast-1.amazonaws.com" # IoTCoreエンドポイント※
MQTT_PORT = 8883
MQTT_TOPIC_TO = "miniRcTo"
MQTT_TOPIC_FROM = "miniRcFrom"
MQTT_ROOTCA = "./awscert/xxxxxxxxxCA1.pem" # RootCA証明書ファイル名
MQTT_CERT = "./awscert/xxxxxxxxxxxxx-certificate.pem.crt" #1-Click証明書ファイル名
MQTT_PRIKEY = "./awscert/xxxxxxxxxxxxx-private.pem.key" #1-Click証明書の秘密鍵ファイル名

※IoTCoreエンドポイントは、AWSコンソールの「IoTCore」サービスから「設定」を選択することで確認できます。

  • サービスは以下のコマンドで開始します。
$ python3 miniRc.py
  • 起動後「connected.」と表示されればOKです。

Publisher(JavaScript on S3 WebSite)の作成

S3上に、PublisherとなるWebサイトを配置します。

  • 任意のバケットを作成し、公開用フォルダを作成します。
  • 前述のGitにある、「awss3page」フォルダの内容をアップロードします。
  • アップロード時のオプション画面で、「パブリックアクセス許可を管理する」に「このオブジェクトにパブリック読み取りアクセス権限を付与する」を指定します。
  • アップロードしたファイルのうち、「control_view.html」にブラウザから直接アクセスします。
  • コントローラ画面が表示されたらOKです。
    f:id:camelrush:20200330235901p:plain
    操作画面

    ※中央にある「AccessDenined」は気にしないでください。後でカメラ動画を表示することを画策しています。

動作確認

以上で、環境作成は終了です。表示されたWebページでコントローラを操作してみてください。(あ、書き忘れましたが、画面はスマートフォンのタッチイベントしか対応していません。マウスでは動かないはずです)うまくいかない場合は、以下のいずれかを確認してください。

  • WebPageで開発者ツールを表示して「Connected.」メッセージが表示されているか。
  • IoTCoreの「テスト」画面で、「トピックのサブスクリプション」にトピック「miniRcTo」を設定し、操作した分のメッセージが表示されるか。
  • SubscriberであるPythonの実行画面に、操作した分のメッセージが表示されるか。

まとめ

これで屋外から操作することができるようになりました。ただ、この実装っておそらくセキュリティに大きな問題があると思っています。

  • S3の操作ページがパブリックアクセスとなっていること
  • JavaScriptにシークレットアクセスキーがガッツリ組み込まれているので、ハックで課金させ放題

このあたり、よくアンチパターンとして紹介されている「アクセスキーを直接コードに埋め込まないでください。 」というやつなんでしょうね。
https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-access-keys-best-practices.html
でも、公開Webから直接MQTT送信するにはこうならざるを得ないのではないかなぁ…。サーバサイドに送ってLambda介してとかやると、せっかくのMQTTの速度が遅くなるような気がするし…。アドバイスあれば、教えてください。

今後

次回は送受信を逆にし、RaspberryPiで撮影した画像をMJpeg方式でWebページの方にMQTT送信して、撮影画像のリアルタイムストリーミングに挑戦しようと思います!