はじめに
この記事は、春のIoTリレーハンズオン@関西の一環として開催される<SORACOM接続 + MQTT編>のハンズオン用資料です。
本ハンズオンでは、RaspbianをインストールしたRaspberry Pi(以降、ラズパイ)でSORACOMのサービスの基本部分をひととおり使えるようになるまでの手順をまとめています。
この記事では、8ステップあるハンズオン手順のうち、後半となるStep 6 ~ Step 8を掲載しています。
前半のStep 1 ~ Step 5はこちらです。
[Step 6.] ラズパイにADコンバータと光センサーを接続する
ラズパイには以下の図のように様々な電子部品を接続するピン(GPIOピンと呼ぶ)があります。それぞれにピン番号(例:左上のピンの灰色の1
))と名前(例:左上のピンの黄色の[3.3V PWR]
)が割り当てられていて役割も決まっています。
IoTコアのサンプルページより引用
ラズパイのGPIOで他のマイコンボードと違う点は、アナログ入力ピンが無いという点です。温度や光量、音量などはアナログ入力でセンサー部品が豊富にありますが、ラズパイではそれらセンサーのアナログデータを直接入力できません。ADコンバータ用ICを介して適切なビット長のデジタルデータに変換する必要があります(もしくはI2Cインターフェースをもったセンサー部品を入手する必要があります)。
当ハンズオンでは、フォトダイオードのアナログ入力を10ビット(0~1023)のデジタルデータに変換してラズパイに入力します。
【ToDo 6.1】ADコンバータとフォトトランジスタなど電子部品を準備する
以下の電子部品があるかどうか確認してください。
- ラズパイ(Raspberry Pi 2 Model B推奨)1個
- ブレッドボード(ハーフタイプEIC801を推奨) 1個
- ADコンバータ 8ピンIC MCP3002 1個
- フォトトランジスタ NJL7502L 1個
- 抵抗 7.5kΩ 1個
- オス・メスケーブル 6本
- オス・オスケーブルまたはジャンパーワイヤ 3本
欠品があるようでしたら補充してから以下の作業に入ってください。
【ToDo 6.2】ADコンバータとフォトトランジスタを配線する
ラズパイをシャットダウンし、電源ケーブルを抜いて電源オフします。
以下の図を元にラズパイとブレッドボード上に部品を配置しケーブルを配線してください。
- ADコンバータMCP3002をブレッドボードに差し込む。4つづつある左右のピンは、ブレッドボードの中央の溝にかかるようにし、半円状の切り欠きが図では下側に向くようにする。
- 7.5kΩ抵抗をADコンバータMCP3002
4
番とフォトトランジスタNJL7502Lの短い脚にあたるブレッドボードの穴に差し込む。 - フォトトランジスタNJL7502Lをブレッドボードの穴に差し込む。短い脚(カソード:陰極側)を図では下側になるようにする。
- オス・オスケーブルをMCP3002
3
番とフォトトランジスタNJL7502Lの短い脚にあたるブレッドボードの穴に差し込む。 - オス・メスケーブルをラズパイの
1
番ピン[3.3V PWR]
とブレッドボードの+(赤色)のラインに差し込む。 - オス・メスケーブルをラズパイの
9
番ピン[GND]
とMCP30024
番にあたるブレッドボードの穴に差し込む。 - オス・メスケーブルをラズパイの
19
番ピン[SPI0 MOSI]
とMCP30025
番にあたるブレッドボードの穴に差し込む。 - オス・メスケーブルをラズパイの
21
番ピン[SPI0 MISO]
とMCP30026
番にあたるブレッドボードの穴に差し込む。 - オス・メスケーブルをラズパイの
23
番ピン[SPI0 SCLK]
とMCP30027
番にあたるブレッドボードの穴に差し込む。 - オス・メスケーブルをラズパイの
24
番ピン[SPI0 CS0]
とMCP30021
番にあたるブレッドボードの穴に差し込む。 - オス・オスケーブルをブレッドボードの+(赤色)のラインとMCP3002
8
番にあたるブレッドボードの穴に差し込む。 - オス・オスケーブルをブレッドボードの+(赤色)のラインとフォトトランジスタNJL7502Lの長い脚(アノード:陽極側)にあたるブレッドボードの穴に差し込む。
【ToDo 6.3】SPIを使用可能にする
配線が終わればラズパイの電源を入れます。A/DコンバータMCP3002はSPIインターフェースを用いています。ラズパイでは初期状態でSPIモジュールを無効にしているためraspi-config
でSPIモジュールを動作するように設定します(Rasbian JESSIEでは以下の操作のみになりました)。
$ sudo raspi-config
・管理画面が出ますので「9 Advanced Options」を選択してEnter
・「A6 SPI」を選択
・「Would you like the SPI interface to be enabled?」と出るので「Yes」を選択
・「The SPI interface is enabled」と出るので「Ok」を選択
・「 Would you like the SPI kernel module to be loaded by default?」と出るので「Yes」を選択。
・「SPI kernel module will now be loaded by default」と出るので「Ok」を選択
・メニュー画面に戻ってくるので「Finish」を選択し、再起動を促されればそのままリブートします。
【ToDo 6.4】照度センサの動作確認
ADコンバータとフォトトランジスタの配線を確認するため、以下のPythonソースを実行します。
実行例を以下に示します。GPIOを利用するPythonコードはsudoをつけて実行する必要があります。実行時に光をあてたり遮ったりして、値が変化するか確認してください。
$ vi sora03.py
$ sudo python sora03.py
ch0 = 40, 0.13[V], ch1 = 391, 1.26[V] ←自然光
ch0 = 0, 0.00[V], ch1 = 400, 1.29[V]
ch0 = 0, 0.00[V], ch1 = 416, 1.34[V]
ch0 = 0, 0.00[V], ch1 = 413, 1.33[V]
ch0 = 77, 0.25[V], ch1 = 382, 1.23[V]
ch0 = 168, 0.54[V], ch1 = 370, 1.19[V]
ch0 = 220, 0.71[V], ch1 = 725, 2.34[V] ←スマホのライトをあてる
ch0 = 194, 0.63[V], ch1 = 936, 3.02[V]
ch0 = 122, 0.39[V], ch1 = 939, 3.03[V]
ch0 = 22, 0.07[V], ch1 = 936, 3.02[V]
ch0 = 0, 0.00[V], ch1 = 932, 3.01[V]
ch0 = 11, 0.04[V], ch1 = 729, 2.35[V]
ch0 = 116, 0.37[V], ch1 = 756, 2.44[V]
ch0 = 191, 0.62[V], ch1 = 13, 0.04[V] ←フォトトランジスタを隠す
ch0 = 224, 0.72[V], ch1 = 15, 0.05[V]
ch0 = 203, 0.65[V], ch1 = 13, 0.04[V]
^C$ ←[Ctrl]+Cキーで中断
※実行例にあるとおりADコンバータMCP3002は、2つのアナログ入力チャネルを持っており、今回はch1だけしか使っていません。時間があれば、ch0側にアナログ入力センサーを接続して2つのデータを取得できるようにしてみてください。
[Step 7.] 光センサーの値をMQTTブローカーに送信する
MQTTは、HTTPに比べ軽量で単純なプロトコルでIoT用途に向いています。
単純な構成図を以下に示します。
┏━━━━━━┓ ┏━━━━━━━━━┓ ┏━━━━━━┓
┃(A)Pub┃---->┃(B)Broker┃---->┃(C)Sub┃
┗━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━┛
(A)Publisher(発行者):ラズパイなどセンサーデータの送信
(B)MQ Broker(仲介者):データが発生したらSubscriberに通知
(C)Subscriber(購読者):センサーデータを受信
システム運用上の構成では(A)(B)(C)は以下のようになります。
- __(A)Pub__にラズパイなどのセンサーデータを送信するデバイス
- __(B)Broker__にsango時雨堂などMQTTサービスを提供しているクラウド
- __(C)Sub__にAWSなどのセンサーデータを蓄積するクラウド
詳細は割愛しますが、(B)BrokerのMQTTブローカーがセンサーデータのやり取りを仲介することによって、大量に配置されるIoTデバイスからのセンサーデータを効率よくクラウドにプッシュし蓄積することができるモデルです。
こういったデータ送受信の方式をPub/Subメッセージングモデルと呼びます。
【ToDo 7.1】ラズパイ上で(A)(B)(C)を実装し(A)(C)をコマンドで実行
今回MQTTの実装にはmosquittoを用います。
まずは(A)(B)(C)をすべてラズパイ上で実行して動作を確認してみましょう。
-
(A)Pub
mosquitto_pub
コマンドで光量データを送信 -
(B)Broker
mosquitto
サービスをバックグラウンドで稼働 -
(C)Sub
mosquitto_sub
コマンドで光量データを受信
mosquittoおよびmosquitto-clientsをインストールします。インストールと同時にMQブローカーのmosquittoサービスが起動しますので、以下のようにステータスを確認してください。
$ sudo apt-get install mosquitto mosquitto-clients
$ sudo /etc/init.d/mosquitto status
● mosquitto.service - LSB: mosquitto MQTT v3.1 message broker
Loaded: loaded (/etc/init.d/mosquitto)
Active: active (running) since Mon 2016-03-21 12:17:48 JST; 3 days ago
Process: 373 ExecStart=/etc/init.d/mosquitto start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/mosquitto.service
mq389 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Mar 21 12:17:48 raspberrypi mosquitto[373]: Starting network daemon:: mosquitto.
Mar 21 12:17:48 raspberrypi systemd[1]: Started LSB: mosquitto MQTT v3.1 message broker.
$
次に__(C)Sub__のデータを受信する側を準備します。新たに別のターミナルを起動しpi
ユーザーでログインします。以下のmosquitt_sub
コマンドを実行しデータを待ち受けください。spinning/3f/brightness000
の部分はトピックと呼ばれる「観察対象」です(ここではセンサー固有のIDとなる)。末尾の000
の部分は任意の数値にしてください(複数のセンサーがある際、区別するために必要です)。
$ mosquitto_sub -t spinning/3f/brightness000 -v # 000は任意の数字に変更
mosquitto
サービスのステータスを確認した元のターミナル画面に戻って、__(A)Sub__のデータを送信する側をコマンドで実行します。
$ mosquitto_pub -t spinning/3f/brightness000 -m 1023 # 000は任意の数字に変更
すると、mosquittp_sub
コマンドを実行していた別の画面でトピックおよびデータがSubscribe(=表示)されます。
$ mosquitto_sub -t spinning/3f/brightness000 -v
spinning/3f/brightness000 1023 ← トピックおよびデータがSubscribeされる
【ToDo 7.2】ラズパイ上で(A)(B)(C)を実装し(A)をPythonで実行
次に(B)(C)はそのままに、(A)Pub部分をPyhtonソースを実行し、すべてラズパイ上で実行して動作を確認してみましょう。
-
(A)Pub
pub_light.py
を実行しで光量データを定期的に送信 -
(B)Broker
mosquitto
サービスをバックグラウンドで稼働 -
(C)Sub
mosquito sub
コマンドで光量データを受信(別ターミナル画面)
以下のPythonソースを実行します。
実行例を以下に示します。10秒おきにPublishを行います。光をあてたり遮ったりして、値を変化させてください。
$ vi pub_light.py
$ sudo python pub_light.py
mosquitto_pub -t spinning/3f/brightness000 -m {"brightness": 562, "ID": "id000", "time_sensor": "2016-03-24 14:35:20"}
mosquitto_pub -t spinning/3f/brightness000 -m {"brightness": 572, "ID": "id000", "time_sensor": "2016-03-24 14:35:30"}
…
既にmosquittp_sub
コマンドを実行し待受け状態になっている別のターミナル画面を確認してください。以下のようにトピックとJSON形式のメッセージが表示されていればOKです。
$ mosquitto_sub -t spinning/3f/brightness000 -v
spinning/3f/brightness000 1023 ← コマンドで送られてきたトピックおよびデータ
spinning/3f/brightness000 {"brightness": 562, "ID": "id000", "time_sensor": "2016-03-24 14:35:20"} ← トピックおよびデータが10秒おきにSubscribeされていく
spinning/3f/brightness000 {"brightness": 572, "ID": "id000", "time_sensor": "2016-03-24 14:35:30"}
…
【Appendix】センサーデータをJSON形式でテキストファイルとして保存する
光量のアナログセンサーデータをJSONデータとしてテキストファイルに保存しておくと、以後のリレーハンズオンで行われるAWSで可視化セクションで再利用することができます。以下のようにコマンドを打って保存してみてください。
$ sudo python pub_light.py >> brightness000.json
カレントディレクトリにファイル名brightness000.json
でJSONデータが追記保存されます。
【ToDo 7.3】ラズパイ上で(A)(C)を実行し(B)に外部MQTTブローカーを使う
上記一通りの動作が確認できました。実際の運用ではMQTTブローカーにクラウドのサービスなどを用いることになりますので、時雨堂が開発している「sango」を使って試してみます。
-
(A)Pub
pub_light_to_cloud.py
を実行して照度データを定期的に送信 - (B)Broker 時雨堂 sangoサービスの無料プランを利用
-
(C)Sub
mosquito sub
コマンドで照度データを受信(別ターミナル画面)
以下のPythonソースを実行します。
実行する前に時雨堂「sango」でログイン登録をして下さい。ライトプランで10コネクションまで無料で使えます。登録後表示されるダッシュボードで、ユーザー名とパスワードを確認してください。
※ハンズオンで時雨堂「sango」に登録できない方は申し出てください(5名ほどなら一時的に一緒に使いましょう)。
実行例を以下に示します。15秒おきにPublishを行います。先ほどと同様に光をあてたり遮ったりして、値を変化させてください。
$ vi pub_light_to_cloud.py
$ sudo python pub_light_to_cloud.py
mosquitto_pub -t spinning/3f/brightness000 -m {"brightness": 562, "ID": "id000", "time_sensor": "2016-03-24 14:35:20"}
mosquitto_pub -t spinning/3f/brightness000 -m {"brightness": 572, "ID": "id000", "time_sensor": "2016-03-24 14:35:30"}
…
別のターミナル画面でmosquittp_sub
コマンドの実行を中断し、新たにsangoのMQTTブローカーにspinning/3f/brightness000トピックへのSubscribeを行う。
コマンド内に{…}で囲まれた文字列は以下のように{…}ごと差し替えてください。
- {account_name}はご自身のsangoアカウント(=githubアカウント)
- {password}はご自身のsangoアカウントのパスワード
新たにデータが流れてくれば正常にSubscribeできています。
$ mosquitto_sub -h lite.mqtt.shiguredo.jp -u {account_name}@github -P {password} -t {account_name}@github/spinning/3f/brightness000 -v
{account_name}@github/spinning/3f/brightness000 {"brightness": 579, "ID": "id000", "time_sensor": "2016-03-24 16:03:52"}
{account_name}@github/spinning/3f/brightness000 {"brightness": 542, "ID": "id000", "time_sensor": "2016-03-24 16:04:08"} ← トピックおよびデータが15秒おきにSubscribeされていく
…
[Step 8.] 光センサーの値をSORACOM Beamを使って外部MQTTブローカーに送信する
最後に、(A)Pubと(B)Broker間を、SORACOM Beamを中継するようにします。
-
(A)Pub
pub_light_to_beam.py
を実行してデータを定期的に送信 - SORACOM Beam経由で一括して安全にデータを中継
- (B)Broker 時雨堂 sangoサービスの無料プラン
-
(C)Sub
mosquito_sub
コマンドでデータを受信(別ターミナル画面)
SORACOM Beamは、Beamを使いたいSORACOM Airを特定のグループに設定することで適用することができます。特定のグループとは、すでにSORACOM Beam設定が済んでいるグループのことを指します。
SORACOMコンソールから所属グループを変更してみましょう。
【ToDo 8.1】SORACOMコンソールでグループ設定を行う
自身のPCのブラウザでSORACOMコンソールを表示させ、SORACOMアカウントでログインします。
メールアドレス・パスワードは、ご自身のSORACOMアカウントやハンズオン指定のSORACOMアカウントを入力して「ログイン」ボタンをクリックします。
SIM管理画面が表示されるのでSIMの名前などを入力し検索して、自分のIMSIをパソコン(のエディタなど)にコピーしておいてください。
自分のSIMの番号を控えておいてください。一番左のチェックボックスをクリックして、「操作」プルダウンを選び、SIM詳細画面を表示させます。
SIM詳細画面からグループの欄に「MQTT」を指定して、「閉じる」をクリック
【ToDo 8.2】SORACOM Beamを用いたPythonソースによるPublishの実行
以下のPythonソースを実行します。
実行例を以下に示します。これもまた15秒おきにPublishを行います。先ほどと同様に光をあてたり遮ったりして、値を変化させてください。
$ vi pub_light_to_cloud.py
$ $ sudo python pub_light_to_beam.py
mosquitto_pub -t {account_name}@github/spinning/3f/brightness000 -m {"brightness": 560, "ID": "id000", "time_sensor": "2016-03-25 02:44:16"} -h beam.soracom.io
mosquitto_pub -t {account_name}@github/spinning/3f/brightness000 -m {"brightness": 536, "ID": "id000", "time_sensor": "2016-03-25 02:44:32"} -h beam.soracom.io
…
別のターミナル画面で新たにsangoのMQTTブローカーにspinning/3f/brightness000トピックへのSubscribeを行う。
コマンド内に{…}で囲まれた文字列は以下のように{…}ごと差し替えてください。
- {account_name}はご自身のsangoアカウント(=githubアカウント)
- {password}はご自身のsangoアカウントのパスワード
- {imsi}はハンズオンで使っているSIMのIMSI番号
新たにデータが流れてくれば正常にSubscribeできています。
$ mosquitto_sub -h lite.mqtt.shiguredo.jp -u {account_name}@github -P {password} -t yoshidaken1@github/spinning/3f/brightness000/{imsi} -v
yoshidaken1@github/spinning/3f/brightness000/{imsi} {"brightness": 583, "ID": "id000", "time_sensor": "2016-03-25 02:48:52"}
yoshidaken1@github/spinning/3f/brightness000/{imsi} {"brightness": 576, "ID": "id000", "time_sensor": "2016-03-25 02:49:08"}
今回の場合、MQTTグループに属したSIMはすべてbeam.soracom.io経由でPublishされています。MQTTコネクションが1つにまとまりコネクション数の節約にもなるのですが、Publish元のセンサーデータはどのラズパイから送信してきたか特定できません。
そのためMQTTグループのSORACOM Beamでは、トピックの末尾にIMSI番号を付与する指定が可能になっています。
時間があれば、新たに自分でSORACOMグループを作成し(MQTT_00など。00は自分の番号)、上図に基づいたSORACOM Beam - MQTT 設定を行って、Publish/Subscribeしてみてください。