メインコンテンツまでスキップ

自宅のラズパイにいつでもどこでもAzure Cloud Shellからアクセスする

· 約7分
moritalous
お知らせ

過去にQiitaに投稿した内容のアーカイブです。

外出時に自宅のラズパイが気になることありませんか? ブラウザさえあれば、Azure Cloud Shellからアクセスできますので、紹介します。

仕組み

IoT Hub デバイス ストリームの機能を使います。2020/11/1現在プレビュー状態ですが、誰でも試すことが可能です。

Azure IoT Hub デバイス ストリームによって、さまざまな cloud-to-device 通信シナリオのセキュリティで保護された双方向 TCP トンネルの作成が容易になります。 デバイス ストリームは、デバイスとサービス エンドポイント間のプロキシとして機能する、IoT Hub ストリーミング エンドポイントによって仲介されます。

device-stream-proxy-diagram.png

(画像は公式サイトのものです) https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-device-streams-overview

IoT Hubが仲介することで、通常はファイアーウォールに防がれてアクセスできないRaspberry Piに外部からアクセスできるようになります。

環境

デバイス側

Raspberry Pi 3 Raspberry Pi OS (32-bit) Lite 最新版(2020-08-20)

セットアップ

以下の手順で進めます。

  1. Azure IoT Hubの設定
  2. デバイス(Raspberry Pi)側の設定
  3. サービス(Azure Cloud Shell)側の設定

1. Azure IoT Hubの設定

Azure IoT Hubの作成は、Azure Cloud Shellで実行します。

Azure IoT 拡張機能を追加

AzureCloudShell
az extension add --name azure-iot

Azure IoT Hubを作成

無料のSKUで作成します。 デバイスストリームに対応しているリージョンは限られています。

  • 米国中部
  • 米国中部 EUAP
  • 東南アジア
  • 北ヨーロッパ
AzureCloudShell
az iot hub create --name [IoT Hub名] --resource-group [リソースグループ名] --location centralus --sku f1 --partition-count 2

デバイスを作成

Raspberry PiがIoTデバイス扱いとなりますので、IoT Hubにデバイスを作成します。デバイスIDはraspberrypiとしました。

AzureCloudShell
az iot hub device-identity create --hub-name [IoT Hub名] --device-id raspberrypi

接続文字列を取得

接続文字列は2種類必要です。

デバイス(Raspberry Pi)側で使用する接続文字列

AzureCloudShell
az iot hub device-identity connection-string show --hub-name [IoT Hub名] --device-id raspberrypi --output tsv

サービス(Azure Cloud Shell)側で使用する接続文字列

AzureCloudShell
az iot hub connection-string show --policy-name service --hub-name [IoT Hub名] --output tsv

これで、Azure IoT Hubの設定は完了です。

2. デバイス(Raspberry Pi)側の設定

つづけてRaspberry Piの設定です。 OSをインストールした直後の状態から進めたいと思います。

必要なソフトウェアのインストール

RaspberryPi
sudo apt install git cmake libssh-dev libcurl4-openssl-dev uuid-dev -y

デバイス側ソースの取得

パブリックプレビュー用ブランチを使用します。

RaspberryPi
git clone -b public-preview https://github.com/Azure/azure-iot-sdk-c.git
cd azure-iot-sdk-c
git submodule update --init

ソースの修正

azure-iot-sdk-c/iothub_client/samples/iothub_client_c2d_streaming_proxy_sampleにあるiothub_client_c2d_streaming_proxy_sample.cにデバイス側で使用する接続文字列を指定します。(70行目です)

iothub_client_c2d_streaming_proxy_sample.c
static const char* connectionString = "[device connection string]";

makeする

公式ドキュメントではmake -jと書いてありますが、メモリ不足で失敗しますので、-jは外しました。

RaspberryPi
cd ~/azure-iot-sdk-c/
mkdir cmake
cd cmake
cmake ..
make

makeが成功するとazure-iot-sdk-c/cmake/iothub_client/samples/iothub_client_c2d_streaming_proxy_sample/iothub_client_c2d_streaming_proxy_sampleが生成されます

わかり易い場所に移動します。

RaspberryPi
mkdir ~/bin
cp iothub_client/samples/iothub_client_c2d_streaming_proxy_sample/iothub_client_c2d_streaming_proxy_sample ~/bin/

自動起動の設定

serviceファイルを作成します。

iothub_client_c2d_streaming_proxy.service
[Unit]
Description=IoT Hub Client C2D Streaming Proxy
After=network.target

[Service]
ExecStart=/home/pi/bin/iothub_client_c2d_streaming_proxy_sample
WorkingDirectory=/home/pi/bin
StandardOutput=inherit
StandardError=inherit
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

serviceを有効にして起動します。

RaspberryPi
sudo mv ~/iothub_client_c2d_streaming_proxy.service.service /etc/systemd/system/
sudo systemctl enable iothub_client_c2d_streaming_proxy.service
sudo systemctl start iothub_client_c2d_streaming_proxy.service

デバイス(Raspberry Pi)側の設定は完了です。

3. サービス(Azure Cloud Shell)側の設定

サービス側のサンプルはNode.jsで動作します。Azure Cloud Shellで提供されているNode.jsのバージョンはv8.16.0ですが、v10以上が必要なので、まずはNode.jsをセットアップします。

Node.jsのインストール

AzureCloudShell
wget https://nodejs.org/dist/v10.19.0/node-v10.19.0-linux-x64.tar.gz
mkdir ~/node
tar zxf node-v10.19.0-linux-x64.tar.gz -C ~/node/
cd node
ln -s node-v10.19.0-linux-x64 node
echo 'export PATH=~/node/node/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

サービス側ソースの取得

AzureCloudShell
wget https://github.com/Azure-Samples/azure-iot-samples-node/archive/streams-preview.zip
unzip streams-preview.zip
mv azure-iot-samples-node-streams-preview/iot-hub/Quickstarts ~/

外部ライブラリーの取得

AzureCloudShell
cd ~/Quickstarts/device-streams-service/
npm install azure-iothub@streams-preview
npm install

環境変数の設定

Node.jsのプログラムは環境変数を参照するようですので、必要な情報を環境変数にセットします。 IOTHUB_CONNECTION_STRINGにサービス側で使用する接続文字列をセットします。 ※Azure CLIで取得して設定するように工夫してみました

AzureCloudShell
echo 'export IOTHUB_CONNECTION_STRING="`az iot hub connection-string show --policy-name service --hub-name [IoT Hub名] --output tsv`"'>> ~/.bashrc
echo 'export STREAMING_TARGET_DEVICE=raspberrypi' >> ~/.bashrc
echo 'export PROXY_PORT=2222' >> ~/.bashrc
source ~/.bashrc

これでサービス(Azure Cloud Shell)側の設定は完了です。

接続

準備は整いましたので、実際に接続してみましょう。 デバイス側はもう特に触りませんので、Azure Cloud Shell上で作業します。

AzureCloudShell
cd ~/Quickstarts/device-streams-service/
node proxy.js &
ssh pi@localhost -p 2222

Node.jsのProxyプログラムはフォアグラウンドで動作する仕組みなのでバックグラウンドで動作させます。 localhost(=Azure Cloud Shell)の2222ポートにSSHで接続することで、デバイス側に接続ができます。

Azure Cloud Shellのインスタンスが停止したあとでも、接続の手順を行うとデバイス側に接続できます。

AzureのAndroidアプリからもこの通り。 これでいつでもどこでもRaspberry Piにアクセスできますね。

Screenshot_20201101-205702.png

参考サイト

https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-device-streams-overview https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-device-streams-proxy-c https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-device-streams-proxy-nodejs