あらゆる「モノ」がインターネットによってシームレスに相互接続される時代は、かつてなかった。モノのインターネット(IoT)という考え方は、イベント・ドリブン・パブ/サブ・アーキテクチャを使用して多くの問題に対する革新的なソリューションを提示することで、我々の世界を絶えず変革してきた。例えば、混雑したスペースで駐車場を探すという疲れる問題を解決するために、駐車場は駐車場の個々のセンサーから公開されるステータス更新を購読することで、どのスポットが空いているかを示すライブ電子ダッシュボードを設置している。このようなIoTアプリの構築は、多くのハードルのために困難である可能性がある。
これらのハードルの1つは、モバイルアプリとセンサーデバイスの間でリアルタイムで送信されるメッセージを処理できるサーバーをホストすることである。もうひとつは、スマート駐車場内の埋め込みセンサー・デバイスひとつひとつをサポートできる無線LANネットワークのホスティングだ。
しかし、PubNubと Soracomを並行して使用することで、開発者はこれらの課題を迅速に回避することができる。PubNubのリアルタイム・プラットフォームを使えば、開発者はサーバーのホスティングなどの面倒な作業を心配することなく、車両監視用の複雑なIoTソリューションを簡単に構築できる。さらに、Soracom Airと Soracom Beamを使えば、開発者は制限の多いWFIネットワークではなく、LTEを利用したIoTソリューションを簡単に構築できる。
チュートリアル概要
このチュートリアルでは、Raspberry Piと超音波センサーを使用して、駐車場が埋まっているか空いているかを検出するスマートパーキングシミュレーションを構築します。Soracom Airを使ってセンサーからセルラーデータ経由でPubNubにメッセージを送信します。そして、PubNubのPublish-Subscribe APIを使って、ライブの駐車場データをアプリのすべてのモバイル・ユーザーに即座に提供します。これを以下の図に示します。
完全なソースコードについては、ここをクリックしてください。
このデモを構築するには、以下のものが必要です:
- ラズベリーパイ(バージョン問わず)
- ブレッドボード
- HC-SR04超音波センサー
- メス-メス1本 + オス-メス6本のジャンパーワイヤー
- 1*kΩ抵抗1本と2kΩ*抵抗1本
- MicroSDカード + MicroSDからSDへのアダプタ
- Huawei USBスティックモデム
- Soracom Air Simカード
Raspberry Piのセットアップ
1.Raspbian OSのインストール
まだの方は、Raspberry PiにRaspbian OSをインストールしてください。そのために、まずローカルにインストールします。これはディスクイメージ形式なので、使用する前にディスクをフラッシュする必要があります。Etcherを使ってディスクをmicroSDカードアダプターにフラッシュすることができます。
RaspbianのOSファイルをmicroSDカードアダプターに入れたら、microSDカードをアダプターから取り外し、Raspberry Piの一番下のスロットに挿入します。OSがインストールされたら、キーボード、マウス、モニター、電源を接続してRaspberry Piを起動します。
2.センサーの設定
- 超音波センサーHC-SR04の VCC、Echo、GNDスロットに 、オスとメスのジャンパー線3本を差し込む 。 センサーのTrigスロットに、メスとメスのジャンパー線1本を差し込む。
- VCC ワイヤーをブレッドボードのプラスレールに、GND ワイヤーを マイナスレールに差し込む。
- Raspberry PiのGPIO 5Vをブレッドボードのプラスレールに、GPIO GNDをマイナスレールに接続する。
- TrigワイヤーをGPIO 23に接続する。
- Echoワイヤーをブレッドボードのブランクレールに差し込む。
- 1kΩの抵抗を使用して、別の空白のレールに接続する。(抵抗が必要な理由は、センサーの構成によってRaspberry Piが損傷しないように電圧出力を下げるためです)。
- 次に、2kΩ抵抗 を使って空白のレールをブレッドボードのマイナスレールにつなげます。2kΩの抵抗がない場合は、次の図のように1kΩの抵抗を2本連ねてください。
- 空いたスペースに、オスとメスのジャンパーワイヤーを使って GPIO 24にリンクします。
これで超音波センサーの設定は完了です。もしセンサーの設定に行き詰まったら、こちらのチュートリアルを参照してください。回路を作っている間、ブレッドボードのブランク・レールでは電流が水平に流れ、ブレッドボードのプラスとマイナスのレールでは電流が垂直に流れることを覚えておいてください。次に、PubNubとSoracomをIoTアプリにセットアップします。
PubNubのセットアップ
まず、PubNub Admin Consoleでアプリを作成する(無料)。コンソールでアプリを作成すると、次のステップでPubNubとSoracomを接続するために使用するPublishキーとSubscribeキーが表示されます。
Soracomのセットアップ
SIMの登録
Soracom Admin Consoleに移動します。ここで「SIMを登録」をクリックし、Soracom Air Simカードの裏面に記載されているICCIDと PUKを入力します。
USBモデムの設定
SIMカードを登録した後、SIMチップを取り出します(上の画像では紫色の丸で囲んでいます)。そしてHuawei USB Stick Modemに挿入します。SIMカードが上向きになっていることを確認してください。
Raspberry Piをセルラーデータで動かすには、Huawei USB Stick ModemをRaspberry PiのUSBポートに差し込むだけです。 青く点灯していれば(点滅していなければ)、モデムが3Gデータを正常に受信していることを示している。点滅している場合は、まだ接続しようとしていることを意味する。
青いライトが点灯したら、USBスティックモデムをRaspberry PiのNetwork Managerに追加します。これを行うには、まずRaspberry PiにNetwork Managerをインストールします。Raspberry Piのターミナルで次のように入力します。
sudo apt-get update && sudo apt-get install network-manager
次に、USBスティックモデムをSoracomアカウントに接続するために、Raspberry Piのターミナルから以下のコマンドを入力します。と をそれぞれのアカウント認証情報に置き換えてください。
sudo nmcli con add type gsm ifname "*" con-name soracom apn soracom.io user <ENTER_USERNAME> password <ENTER_PASSWORD>
この設定を有効にするには、Raspberry Piを再起動する必要があります。
sudo reboot
USBモデムがRaspberry Piのネットワーク・マネージャーに認識されていることを確認するために、次のように入力します:
ifconfig
と入力します。
ppp0
(USBモデム)が表示されるはずです。次に以下の3つのターミナルコマンドを入力し、Soracomのppp route metricスクリプトをダウンロードし、USBモデムを接続または再起動するたびにスクリプトが実行されるようにします。
sudo curl -o /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric https://soracom-files.s3.amazonaws.com/handson/90.set_ppp_route_metric
sudo chmod +x /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric
sudo /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric ppp0 up
これでUSBスティックモデムは正しく設定されたはずです。まだUSBスティックモデムの設定に行き詰っている場合は、Soracomのドキュメントをよく読んでください。
MQTTセットアップ
MQTT (Mosquitto)はRaspberry Pi IoTアプリからPubNubチャンネルにメッセージを発行するために使用するプロトコルの名前です。管理コンソールでサイドナビゲーションバーのGroupsというリンクを開き、新しいグループを追加します。この新しいグループをBeam-Soracomと呼びます。この新しいグループの基本設定で、Soracom Beam をクリックする。ここで、MQTTエントリーポイントを作成します。MQTTEntry Point を作成する際、以下のように入力されていることを確認してください。Destination Type にPubNub を指定する必要があります。Credentials Setと表示されているところに、PubNubの認証情報(PublishとSubscribe Key)を追加して、SoracomデバイスがPubNubチャネルにメッセージを発行できるようにします。
次に、管理コンソールで登録済みSIMカードを選択し、そのグループを先ほど作成したBeam-Soracomに設定します。 登録済みSIMカードのactivateをクリックし、アクティブになってデータを取得していることを確認します。
次に、Raspberry Piにmosquitto-clientsパッケージをインストールして、MQTTのpublishメソッドを使えるようにします。Raspberry Piのターミナルで以下のコマンドを実行する。
sudo apt-get update && sudo apt-get install mosquitto-clients
mosquitto-clientsがインストールされたので、mosquitto_pubコマンドをテストします。mosquitto_pubコマンドの書式は以下のようになります。tの後にチャンネル名parking_spotを挿入します。そして-mの後にテストメッセージ "test" を挿入します。PubNubアドミンコンソールでデバッグビューを表示します。Raspberry Piのターミナルで以下のコマンドを実行すると、メッセージがPubNubチャンネルに正常にパブリッシュされたことが確認できるはずです。
mosquitto_pub -h beam.soracom.io -p 1883 -t parking_spot -m "test"
これでSoracom Air DeviceはRaspberry PiからPubNubチャンネルにメッセージを正常にパブリッシュできるようになりました。これで、超音波センサーからパブリッシュし、Androidモバイルアプリからサブスクライブするコードを書き始める準備ができました。
発行 - 超音波センサーPythonスクリプト
pythonコードをsensor_publish.pyというスクリプトに書きます(このスクリプトはRaspberry Piの中にある必要があります!)。スクリプトの先頭で必要なモジュールをインポートすることから始めます。RPI.GPIO モジュールはセンサーからデータを取得します。time モジュールは、センサーから定期的に読み取り値を取得します。Signalと sysは、ユーザがコマンド^Cを使用したときにスクリプトを終了し、センサ・データの読み取りを停止するメソッドを記述します。Subprocessと jsonは、booleanを適切なJSON Stringフォーマットにパースし、PubNubチャネルに送信します。
import RPi.GPIO as GPIO
import time
import signal
import sys
import subprocess
import json
センサーのセットアップ
モジュールをインポートした後、GPIOオブジェクトがRaspberry Piボードのピン番号を使用していることを確認する必要があります。次の行でこれを行います。
GPIO.setmode(GPIO.BCM)
次に、入力ピンと出力ピンに値を割り当てる必要があります。入力ピンはECHO、出力ピンはTRIGと呼びます。ECHOは18番ピン(GPIO 24)に接続され、TRIGは16番ピン(GPIO 23)に接続されています。また
occupied
変数を初期化する必要があります。Falseに初期化します。
TRIG = 23
ECHO = 24
occupied = False
次に、センサーをセットアップする関数を定義します。この関数を
setup_sensor()
.ここで、どのピンが入力で、どのピンが出力かを定義しなければなりません。この関数は後でメイン関数の中で呼び出します。
def setup_sensor():
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)
センサー距離の読み取り
関数
get_distance()
関数を使用して、物体がセンサーからどのくらい離れているかのデータを取得します。この関数は、パルス信号が物体を通過して戻ってくるまでの時間を計算します。その時間を使って、センサーから物体までの距離を計算します。
def get_distance():
# set Trigger to HIGH
GPIO.output(TRIG, True)
# set Trigger after 0.01ms to LOW
time.sleep(0.00001)
GPIO.output(TRIG, False)
startTime = time.time()
stopTime = time.time()
# save start time
while 0 == GPIO.input(ECHO):
startTime = time.time()
# save time of arrival
while 1 == GPIO.input(ECHO):
stopTime = time.time()
# time difference between start and arrival
TimeElapsed = stopTime - startTime
# multiply with the sonic speed (34300 cm/s)
# and divide by 2, because there and back
distance = (TimeElapsed * 34300) / 2
return distance
駐車スペースの空き状況の公開
pythonスクリプトのメイン関数で駐車場の空き状況を公開します。これはスクリプトが開始されると実行される関数になります。main関数は以下の処理を順番に行う必要があります。
- センサーのセットアップ
- 駐車場の空き状況の初期チェックを行う。
- ステータスが変更されたかどうかをチェックする(5秒ごと):ステータスが変更された場合、新しいステータスのメッセージを発行する。このステータスを新しい最終更新ステータスとして保存する。
センサーをセットアップするために、先ほど定義した関数を呼び出す、
setup_sensor()
.次に、駐車スペースが空いているかどうか、初期チェックを行います。メソッド
initial_check()
メソッドを定義します。
そして、5秒ごとにループを実行し、車の新しい距離をチェックします。関数
get_distance()
が7cm(私のモデルでは駐車スペースの長さ)より大きければ、その駐車スペースは空いていると推測できます。この場合、車間距離は単なるノイズである。もし7cmより小さければ、その駐車スペースには車が停まっていることになる。
経費を最小限に抑え、効率を最大化するため、センサーが前回の読み取りからステータスが変化したことを示す場合にのみ、駐車スペースのステータスを更新する。これを以下に示す:
if __name__ == '__main__':
setup_sensor()
initial_check()
while True:
if (occupied and (get_distance() >= 7)) or (not occupied and (get_distance() < 7)):
// TODO toggle the availability of the parking space and publish new status
time.sleep(5)
これは以下のとおりです。
initial_check()
関数は変数
occupied
に駐車スペースの現在のステータスを代入します。先ほどインポートした
subprocess
モジュールを使って公開しなければなりません。このモジュールを使うと、pythonスクリプトからターミナルコマンドを実行することができます。メソッド
Popen()
メソッドを使って、ターミナルで入力するようにコマンドから文字列の配列を渡します。m の後に、JSON 文字列としてエンコードされたメッセージを渡します。
occupied
.これは、ヘルパー・メソッド
convertToJsonString()
を呼び出すことで、これを行うことができる。
def initial_check():
occupied = True if get_distance() < 7 else False
subprocess.Popen(["mosquitto_pub", "-h", "beam.soracom.io", "-p", "1883", "-t", "parking_spot", "-m", convertToJsonString(occupied)], stdout=subprocess.PIPE)
print(occupied)
def convertToJsonString(occupied):
dictionary_object = {
"occupied": occupied
}
return json.dumps(dictionary_object)
最後に、メイン関数の中で5秒ごとに実行されるループの中で、次のコードを書きます。これは、占有されているブール値をトグルし、最後に更新されたステータスと異なる場合は、 それをparking_spotチャンネルに公開します。
occupied = not occupied
subprocess.Popen(["mosquitto_pub", "-h", "beam.soracom.io", "-p", "1883", "-t", "parking_spot", "-m", convertToJsonString(occupied)], stdout=subprocess.PIPE)
print(occupied)
キル・スクリプト
Pythonスクリプトが適切に終了できるようにしなければなりません。ここでは
close()
をユーザーが ^C コマンドでスクリプトを kill したときに呼び出される関数として定義します。ここで、センサーの測定値をクリーンアップすることができます。
GPIO.cleanup()
.
def close(signal, frame):
print("Turning off ultrasonic distance detection...")
GPIO.cleanup()
sys.exit(0)
signal.signal(signal.SIGINT, close)
おめでとう、これで駐車スペースのステータスの更新を公開する python スクリプトが書けました。
サブスクライブ - Androidモバイルアプリ
センサーがPubNubチャンネルにデータをパブリッシュすることに成功したので、駐車場の空き状況データを含むチャンネルにサブスクライブするようにモバイルアプリをセットアップする必要があります。
PubNub Android SDKを利用するには、まずモジュールbuild.gradleファイルに以下のgradle依存関係を追加する必要があります。
implementation group: 'com.pubnub', name: 'pubnub-gson', version: '6.4.5'
次に、アプリがインターネットを使用できるようにするために、以下のAndroid Manifest Permissionsを追加します。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
このモバイルアプリでは、1つのアクティビティ(MainActivity クラス)を作成します。 このアクティビティには、3つのUI要素からなる基本的なビューが含まれます。
- 空車状況を表示するTextView
- 車のアイコンのImageView
- 駐車スペースアイコンのImageView
駐車スペースが空いているかどうかを表示するためにTextViewを使用し、駐車スペースの内側または外側に車のアイコンを表示するシンプルなアニメーションを用意します。駐車中の車のY位置は
203f
で、駐車していない車のY位置は
903f
.駐車場が空いているか埋まっているかを表示するために、アニメーションを使用して2つの間で位置を切り替えます。
まず、MainActivityクラスのフィールドを宣言します。
PubNub pubNub;
TextView occupiedText;
ImageView car, parkingSpot;
float outsideCar = 903f;
float parkedCar = 203f;
次に、UI要素をインスタンス化します。
findViewById()
メソッドでUI要素をインスタンス化します。
onCreate()
メソッドでUI要素をインスタンス化します。メイン・アクティビティのレイアウト・ファイルには、以下のUIエレメントが適切なIDで含まれていることを確認する必要があります。私が選んだIDは
occupiedText
,
car
および
parkingspot
.私のレイアウトファイル全体を見るには、ここをクリックしてください。
occupiedText = findViewById(R.id.occupiedText);
car = findViewById(R.id.car);
parkingSpot = findViewById(R.id.parkingspot);
次に
PubNub
インスタンスを作成し、AndroidアプリからPubNub APIを呼び出せるようにします。これを行うには、以下のコードを記述し、PubNub Admin Consoleでアプリを作成するときに生成したSubscribe Keyと Publish Keyを渡します。
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setSubscribeKey("ENTER_SUBSCRIBE_KEY_HERE");
pnConfiguration.setPublishKey("ENTER_PUBLISH_KEY_HERE");
pnConfiguration.setSecure(true);
pubNub = new PubNub(pnConfiguration);
これで
PubNub
インスタンスがインスタンス化されたので、センサーが駐車可否データを公開しているチャンネルparking_spotにサブスクライブすることができます。これを行うには、メッセージがチャネルにパブリッシュされたときのコールバックリスナーを追加する必要があります。それから、実際にチャンネルを購読しなければならない。これを以下に示す。
pubNub.addListener(new SubscribeCallback() {
@Override
public void status(PubNub pubnub, PNStatus status) {
}
@Override
public void message(PubNub pubnub, PNMessageResult message) {
// HANDLE MESSAGE
}
@Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
}
});
pubNub.subscribe()
.channels(Arrays.asList("parking_spot")) // subscribe to channels
.execute();
次に、メッセージを処理するロジックを実装します。基本的には、駐車場の現在の稼働状況をチェックすることで、モバイルアプリのUIで駐車場の空き状況を切り替えたい。したがって、私たちのチャンネルに公開されたばかりのメッセージをチェックし、駐車場が現在利用可能なのか、それとも埋まっているのかを確認します。利用可能な場合は、ヘルパーメソッド
carLeaveAnimation()
.占有されている場合は、ヘルパーメソッド
carEnterAnimation()
.このように
message()
メソッドの内部では次のようになります。
final boolean occupied = message.getMessage().getAsJsonObject().get("occupied").getAsBoolean();
runOnUiThread(new Runnable() {
public void run() {
if(occupied)
{
carEnterAnimation();
}
else
{
carLeaveAnimation();
}
}
});
で
carEnterAnimation()
では、単にtextviewにoccupiedと設定しています。また
animate()
メソッドを呼び出し、そのY位置を駐車スペースに移動します(変数に格納されたY座標の値に移動します、
parkedCar
).で
carLeaveAnimation()
では、単にtextviewをavailableに設定し、車のimageviewの
animate()
メソッドを呼び出し、Y位置を駐車スペースの外(Y座標の値、
outsideCar
).
private void carEnterAnimation()
{
car.animate().y(parkedCar).setDuration(1500);
occupiedText.setText("Occupied");
}
private void carLeaveAnimation()
{
car.animate().y(outsideCar).setDuration(1500);
occupiedText.setText("Vacant");
}
埋め込みコンテンツがこのページで利用できない場合は、https://www.youtube.com/embed/KySPa_D2ne0?enablejsapi=1&origin=https%3A%2F%2Fwww.pubnub.comで見ることもできます。
以上でモバイルアプリは完成です!これで、センサーから駐車場の空き状況の更新を受け取ることができました。
アプリの起動
センサーを起動するには、Raspberry Piのターミナルからスクリプトのあるディレクトリに入ります。そして以下のコマンドを実行します。
python sensor_publish.py
センサーがオンになり、距離測定値をチェックしていることがわかります。Androidモバイルアプリを実行すると、モバイルアプリのUIが更新され、駐車場のステータスが表示されます。
結論
おめでとうございます!これでシンプルなスマートパーキングIoTアプリが完成しました。完全なソースコードについては、 ここをクリックしてください。PubNubとSoracomを統合することで、LTEを使用してRaspberry Piからリアルタイムでメッセージを送信するIoTアプリを構築しました。Wifiネットワークに制限される代わりに、私たちのスマートパーキングIoTアプリは非常にポータブルで屋外での使用に最適です。
IoTダッシュボードのデモと ダッシュボードに基づいたIoTチュートリアルもご覧ください。
PubNubはあなたのお役に立ちますか?
この記事はPubNub.comに掲載されたものです。
PubNubのプラットフォームは、開発者がWebアプリ、モバイルアプリ、IoTデバイス向けにリアルタイムのインタラクティブ機能を構築、提供、管理できるように支援します。
私たちのプラットフォームの基盤は、業界最大かつ最もスケーラブルなリアルタイムエッジメッセージングネットワークです。世界15か所以上で8億人の月間アクティブユーザーをサポートし、99.999%の信頼性を誇るため、停電や同時実行数の制限、トラフィックの急増による遅延の問題を心配する必要はありません。
PubNubを体験
ライブツアーをチェックして、5分以内にすべてのPubNub搭載アプリの背後にある本質的な概念を理解する
セットアップ
PubNubアカウントにサインアップすると、PubNubキーに無料ですぐにアクセスできます。
始める
PubNubのドキュメントは、ユースケースやSDKに関係なく、あなたを立ち上げ、実行することができます。
Top comments (0)