2021年8月11日水曜日

DRAGINO の LoRaWAN ゲートウェイと Azure IoT Hub を接続する

 最近 LoRaWAN を触ることになったんですが、通常は The Things Network を LoRaWANサーバとして利用しますが今回は The Things Network を経由せずに Microsoft Azure IoT Hub に接続したいという特殊な状況になってしまったためいろいろやってたんですが、これがえらいハマってしまったので記録として残しておこうと思いました。

使用する LoRaWANゲートウェイは DRAGINO の LPS8 です。

設定画面をいろいろ見ていると、Azureとかの設定もあるしこれは簡単にできそうだなーと思ったら全く違っていろいろ大変でした。

まずは端末の認証ですが、ゲートウェイ単体では OTAA(Over-the-Air Activation)はできませんので、ABP(Activation by Personalization)を使うことにします。ABPの設定は端末ごとに DevADDR、APP Session Key、Network Session Key の3つを設定画面で設定して、同じ値を端末に設定すればOKです。

以降、設定画面のキャプチャ掲載しますがファームの更新が結構頻繁にあるようなので実際とは異なる可能性あります。掲載時点でのファームのバージョンは lgw-5.4.1628078462 です。

ABPの設定をしたら、LoRaWAN Configuration の画面に移ります。Service Provider のところに、Built-in for ABP Decode to MQTT というまさしくそれな的なのがあるので選んで保存します。


次にMQTTの設定です。Azure IoT Hub にMQTTで接続するには、SASと呼ばれるセキュリティトークンを使用する方法と、X.509証明書を利用する方法があるようです。

https://www.dragino.com/downloads/downloads/LoRa_Gateway/LPS8/Firmware/Application_Note/MQTT_WebUserInterface-v0.3.pdf

この辺のマニュアルを読んでみると、Azureへの接続にはSASを利用しているように見えます。ただSASには有効期限があって、できるだけ短く(1時間とか)にするのがお作法のようで、設定しても1時間で繋がらなくなるなどになってしまうのでそれでは困るなーというわけでX.509証明書の方でやってみることにします(証明書も有効期限ありますがこちらは長く設定できるので)。

X.509証明書で接続するためにいろいろやんないといけないんですが、こちらのチュートリアルが比較的簡単に実行できました。

https://docs.microsoft.com/ja-jp/azure/iot-hub/tutorial-x509-scripts

上記チュートリアルを実行した前提で話を進めます。

接続には3つのファイルが必要になります。Azure の CA認証ファイル(ゲートウェイにデフォルトでインストールされている Azure.cer です)と、上記のチュートリアルで作成したデバイスの認証ファイル2つ(cert/new-device.cert.pem と private/new-device.key.pem)です。デバイスの認証ファイルはあらかじめゲートウェイにアップロードしておきます。

Azure設定画面を見てみると、CA認証ファイルの設定しかありません。やはりSASを利用する前提のようです。


ということで MQTT Server Profile を General に変更します。


ファイルは画面の設定のように選択しますが、User IDのところは {IoT hub name}.azure-devices.net/{device id} を設定します。

ここまでで設定は完璧です。完璧なんですが…

飛ばない… データ… いくら送っても… Azureまで飛んでこない… あう・・・

何で?特にエラー出るわけでもなく Azure のログにも大した情報は出ていない。ダメか、詰んだか。そういえば上のマニュアルで mqtt のサンプルコマンドが載ってたな。そうか、それを試すのだ。

ゲートウェイに SSH で接続して、コマンドで MQTT 送信してみます。

mosquitto_pub -d -h XXXX.azure-devices.net 
      -p 8883 -u XXXX.azure-devices.net/H0001 
      --cafile /etc/iot/cert/Azure.cer 
      --cert /etc/iot/cert/new-device.cert.pem 
      --key /etc/iot/cert/new-device.key.pem 
      -i H0001 
      -t devices/H0001/messages/events/ 
      -m "{ Hello }"

するとあれ?飛ぶぞ?えっ?えっ?
何が起きてるんだろう(まぁ、こんなことはよくあるけど)。マニュアルでは MQTT の処理は mqtt_process.sh がやってるとか書いてあった。じゃ何やってるかちょっと覗いてみるか。送信部分を抜粋。

# ------------------------------------------
# Call MQTT Publish command

# 1. Case with User, Password and Client ID present  (e.g. Azure)
if [ ! -z "$pass" ] && [ ! -z "$user" ] && [ ! -z "$clientID" ]; then
	case="1"  
	mosquitto_pub $D -h $server -p $port -q $pub_qos -i $clientID -t $pub_topic -u $user -P "$pass" $C $cafile $PUB_FLAG "$mqtt_data"
	
# 2. Case with Certificate, Key and ClientID present (e.g. AWS)
elif [ ! -z "$certfile" ] && [ ! -z "$key" ] && [ ! -z "$clientID" ]; then
	case="2"  
	mosquitto_pub $D -h $server -p $port -q $pub_qos -i $clientID -t $pub_topic --cert $cert --key $key $C $cafile $PUB_FLAG "$mqtt_data"
	
# 3. Case with no User, Certificate or ClientID present
elif [ -z "$user" ] && [ -z "$certfile" ] && [ -z "$clientID" ]; then
	case="3"  
	mosquitto_pub $D -h $server -p $port -q $pub_qos -t $pub_topic $PUB_FLAG "$mqtt_data" 
	
# 4. Case with no User, Certificate, but with ClientID present
elif [ -z "$user" ] && [ -z "$certfile" ] && [ ! -z "$clientID" ]; then
	case="4"  
	mosquitto_pub $D -h $server -p $port -q $pub_qos -i $clientID -t $pub_topic $PUB_FLAG "$mqtt_data"
	
# 5. Case with User and ClientID present, but no Password and no Certificate present
elif [ -z "$pass" ] && [ -z "$certfile" ] && [ ! -z "$user" ] && [ ! -z "$clientID" ]; then
	case="5"  
	mosquitto_pub $D -h $server -p $port -q $pub_qos -i $clientID -t $pub_topic -u $user $PUB_FLAG "$mqtt_data"
	
# 6. Case with User and Password present, but no ClientID and no Certificate present
elif [ ! -z "$user" ] && [ ! -z "$pass" ] && [ -z "$clientID" ] && [ -z "$certfile" ]; then
	case="6"  
	mosquitto_pub $D -h $server -p $port -q $pub_qos  -t $pub_topic -u $user -P "$pass" $PUB_FLAG "$mqtt_data"
	
# 0. Else - invalid parameters, just log
else
	case="Invalid parameters"  
	logger "[IoT.MQTT]:Invalid Parameters - mosquitto_pub not called."
fi
  
設定で処理が別れている様子。ログを見ると General の設定は case 2 にあたるようだ。よくみるとあれ? User IDの設定(-u)が無い! あー、それでかー、そんなことかー、ようやく原因がわかったー。おもむろに -u の設定を追加して保存。

これでようやく無事に送信はできるようになりました。

※注意 今回はアップリンクの話だけで、ダウンリンクはまだこれから試します。



0 件のコメント:

コメントを投稿