LoginSignup
2

More than 3 years have passed since last update.

posted at

updated at

自作SORACOM InventoryのエージェントinventorydでIoTデバイスを簡単に遠隔操作する

はじめに

IoTデバイスの遠隔操作したくないですか?
したいに決まってますよね!
ということで今回お勧めするのはSORACOM Inventoryです。

1分でラズパイを遠隔再起動するよ

注意
すでにSORACOM Inventoryを使用中の場合、以下を実行すると費用が発生します。(初期費用100円、利用料金50円)
未使用の場合は150円の無料枠に入ります。


SORACOM Airで接続中のラズパイに入ってrootで以下のコマンドを実行しましょう。

curl -L -O https://github.com/1stship/inventoryd/releases/download/v0.0.1/inventoryd_0.0.1_linux_arm.tar.gz
tar zxf inventoryd_0.0.1_linux_arm.tar.gz
./inventoryd --init # 質問にはEnterのみでよい(yで回答したことになる)
echo "/sbin/reboot" > resources/3/0/4
./inventoryd -b

こんな感じで表示されればOKです。

2020/01/13 12:37:59 Start Bootstrap
2020/01/13 12:38:00 Request Bootstrap accepted
2020/01/13 12:38:01 Bootstrap finished
Bootstrap finish
2020/01/13 12:38:01 Registering...
2020/01/13 12:38:04 Register finished. Location is SKdsWwKWEq
2020/01/13 12:38:04 READ /1/0
2020/01/13 12:38:04 READ /2/0
2020/01/13 12:38:05 READ /3/0
2020/01/13 12:38:05 READ /4/0
2020/01/13 12:38:06 READ /5/0
2020/01/13 12:38:06 READ /6/0
2020/01/13 12:38:06 READ /7/0
2020/01/13 12:38:07 READ /8/0
2020/01/13 12:38:07 READ /9/0

SORACOMコンソールにログインして、SORACOM Inventoryのデバイス管理メニューに入ります。

スクリーンショット 2020-01-13 21.12.00.png

デバイスを選択して、詳細をクリックします。

スクリーンショット 2020-01-13 21.16.35.png

Reboot /3/0/4を探して、実行ボタンをクリックします。

スクリーンショット 2020-01-13 21.25.47.png

「コマンド実行」をクリックします。

スクリーンショット 2020-01-13 21.27.03.png

2020/01/13 12:38:58 EXECUTE /3/0/4
Connection to 192.168.2.3 closed by remote host.
Connection to 192.168.2.3 closed.

はい、ラズパイが再起動しました。やったね!完!

SORACOM Inventoryとは

完!でもよかったのですが、上でやったことは何なのか説明をします。

皆さん、SORACOM Inventory使ってますか?というかそもそも知ってますか?
ぶっちゃけ使ってない人多いんじゃないかと思います。Qiitaのキーワード0件でしたし。(記事自体はありました)

SORACOM Inventoryの公式の説明は以下の通り。

Inventory は、OMA LightweightM2M(LwM2M)をベースにしたデバイス管理のためのフレームワークを提供するサービスです。SORACOM Air と連携したデバイスの自動登録が可能です。

LwM2Mというプロトコルを使ってデバイスを管理するためのサービスです。LwM2Mで必要になるサーバはSORACOMにてフルマネージドで提供されています。そのため、自前でサーバやAWSなどのクラウドを用意することなく、デバイス管理や遠隔操作ができるようになります。

「I」のサービスである「Inventory」は、「H」のサービスである「Harvest」の次に出たサービスです。Harvest以前のサービスのBeamやFunnelは他のサービスと連携することが前提になっていましたが、他のクラウドサービスが必要なくSORACOMだけで完結できるHarvestはとっつきやすく、IoTの入り口として最適ですよね。そしてHarvestによってデータの蓄積や可視化(これはInventoryの翌年出たLagoonで強化される)ができるようになってくると、それをもとにデバイスに制御をかけたい、というのは当然の流れ、、そしてデバイス管理サービスのInventoryが登場します。これもSORACOMだけで完結できる、という点はHarvestと同じで、ユーザーの用意するものはデバイスとSORACOM Airの回線のみです。

使ってみると、デバイスのステータスを取得したり再起動したりということが、SORACOMのコンソールやAPI経由で簡単にできるようになるので、デバイス管理や遠隔操作にはとっても便利です。

でもちょっと大変なところがありまして、LwM2Mのエージェントを自分で作らなければならないんですよね。そのため導入のハードルが高いと思われがちです。(SORACOM HarvestのとりあえずTCP/UDPでデータ投げときゃOKからの落差がすごい)

そもそもLwM2Mって何?というところから始まって、WakaamaLeshanなどの参照実装や、懇切丁寧なREADMEのあるSORACOM Inventory agent for Javaはあるものの、これを読んで自分のデバイスに合わせてソースを改変してビルドするのはまあ大変です。なんか簡単に扱えるようにしたい。

SORACOM Inventoryのエージェントを自作しよう

というところで色々あって僕はSORACOM Inventoryには思い入れがあるので、なんかやろうかなと思いまして、扱いやすいSORACOM Inventoryのエージェントを自作することにしました。というか2019年のゴールデンウイークを丸ごと費やして作って、inventorydという名前でGitHubに公開していたのですが、当時はブログを書いたりしていなかったのでここで改めて紹介します。

inventoryd
SORACOM Inventory access tool in Golang
https://github.com/1stship/inventoryd

基本的な考えは以下の2つです。

・ビルド済のシングルバイナリで動作する
・リソース対応のためにリビルドが必要なく、ファイルの配置で対応できる

要はApache HTTP Server(httpd)と同じ感じで使えるようにしたい、ということです。名前もそれっぽくしています。

多くの人はWebサーバ(HTTPサーバ)を立てようとした時、HTTPサーバのソースを改変してビルドしたりしないと思うんですよね。大抵は、httpdやnginxをビルド済のパッケージをインストールして、公開用のディレクトリにファイルを置いたり、PHPなどのスクリプトファイルを置いたりするところから始めると思います。そんな感じで使えるものであれば、ソースコードを読んだり改変したりビルドしたりしない非開発者の人でもSORACOM Inventoryを使えるようになるかもしれない。

そんなものを目指して作りました。Go言語で書いているのはビルド済みのシングルバイナリで提供するのが一番ユーザー側に負担がかからず簡単に導入できるだろう、ということと、当時Go言語に興味があって何か作ってみようという思いがあったからです。(Go言語で書いた最初のプログラムなのでクオリティはお察し。。プロトタイプ的なものと思っていただければ)

inventorydの基本的な考え方

LwM2Mでは、デバイスへの問い合わせや書き込み、実行などをオブジェクトモデルというもので定義し、そのモデルをパスに割り当てています。

例えば先ほどの「Reboot /3/0/4」というのは、Deviceというモデルの仕様にObjectIDが3と定義されており、次の0は最初のリソースを表し、(同じ定義のモデルが複数ある場合は/3/1/4、3/2/4と2個目の数字が上がっていく)、その中のItem ID="4"としてRebootが以下のように記載されています。

<Item ID="4">
  <Name>Reboot</Name>
  <Operations>E</Operations>
  <MultipleInstances>Single</MultipleInstances>
  <Mandatory>Mandatory</Mandatory>
  <Type/>
  <RangeEnumeration/>
  <Units/>
  <Description>
    <![CDATA[ Reboot the LwM2M Device to restore the Device from unexpected firmware failure. ]]>
  </Description>
</Item>

従って、/3/0/4はDeviceというモデルの最初のリソースに対してRebootというExecuteを実行するもの、ということになります。HTTPのRESTのパスであれば、
POST /Device/0/Reboot
のようになっても良さそうなものですが、LwM2Mは通信が軽量なプロトコルを目指しており、上のような仕様がサーバ、デバイス間で共有されているものとして、番号で対象を伝えることになっています。

このパスと、デバイス内のファイルを一致させるというのがinventorydの基本的な考えです。

./inventoryd --init

を実行した時に、resourcesディレクトリが作成され、その中にはオブジェクトモデルに応じたリソースのファイルが作成されています。そしてこのファイルに対してREADするとそのファイルの中身が返り、WRITEするとファイルが書き換えられ、EXECUTEするとそのファイルがスクリプトとして実行される、という動作をします。

init直後はリソースはデフォルト値を返すだけのものになっており、あまり役に立ちません。このファイルを適切な値やスクリプトで置き換えたり、WRITEされた値を他のプログラムで使用するなどすることによって、ちゃんとしたデバイス管理ができることになります。最初の例では/3/0/4を/sbin/rebootとしましたが、これにより/3/0/4(LwM2Mで定義されたReboot)をラスパイの再起動(/sbin/reboot)と結びつけることができました。

このようなファイルによる対応付けであれば、CやJavaのコードを書いてビルドすることなくファイルの読み書きやシェルスクリプトの記載で対応できるので、比較的簡単に対応できそうですよね。

また、READやWRITEをファイル読み書きでは無く、スクリプトとして実行させたいという場合は、ファイル名の.read、.writeとつけて、実行権をもったスクリプトとすることで対応できるようにしています。

わかりやすいところで説明すると、Current Time /3/0/13はinit直後の状態ではタイムスタンプが0(1970/01/01 00:00:00 UTC)を返すだけですが、/3/0/13.readを

date +%s

として記載し、

chmod 755 resources/3/0/13.read

として実行権を付与することで、現在時刻を返すようになります。

初期状態(1970/01/01 00:00:00 UTC)
スクリーンショット 2020-01-13 22.56.51.png

スクリプト設置後(現在時刻が表示される)
スクリーンショット 2020-01-13 22.58.48.png

同様に、/3/0/13.writeに時刻を設定するスクリプトを記載することで、時刻をOSに反映させることができます。(値は標準入力で渡すので、readで受け取れます)

read TIMESTAMP
date -s "@$TIMESTAMP"

設定します。
スクリーンショット 2020-01-13 23.16.07.png

これで時刻の設定ができました。(ちなみにタイムスタンプ型はコンソールで読み出すと、「Mon Jan 13 14:14:38 UTC 2020」のような形になるのですが、書き込む時にはYYYYmmddTHHMMSS.fff(UTCからの差、日本時間だと+09)にしないと送信できないという罠があります)

このように、比較的簡単なスクリプトを設置することで、動的な値にも対応できるようになっています。ここではコンソールからの操作をしていますが、当然Web APIも用意されています。

WebAPIを使うことで、管理しているデバイスから値を収集したり、特定の処理を実行させたりを自動化するのも簡単に実現できますね。

ちょっと高度な使い方: Observe

LwM2MにはObserveという面白い仕組みがありまして、サーバから監視対象として設定したリソースは、サーバから読み出さなくてもデバイスから自発的に送信する、というものです。

例えばメモリの使用量を記録するとしましょう。
Memory Freeは/3/0/10なので、/3/0/10.readを以下のスクリプトにします。

free | grep 'Mem' | tr -s ' ' | cut -d" " -f7

freeコマンドのavailableのメモリを取得しています。LwM2Mの仕様を見ると単位はkBなのですが、変化がわかりにくくなるのでとりあえずbyte単位です。

コンソールから/3/0/10をObserveすると、5秒に1回Notifyというイベントが発生しているのがわかります。

2020/01/13 14:51:37 OBSERVE /3/0/10
2020/01/13 14:51:37 Notify /3/0/10
2020/01/13 14:51:42 Notify /3/0/10
2020/01/13 14:51:47 Notify /3/0/10

inventorydではObserveされたリソースの値を5秒に1回確認し、値が変わっていればサーバーに通知する、という動作をします。そしてこのNotifyはSORACOMのアプリケーションサービスのBeam、Funnel、Harvest、Funk、そしてUnified Endpointに送ることができます。

分かりやすいところでHarvestに連携させるとこんな感じです。

スクリーンショット 2020-01-13 23.58.22.png

メモリ量の推移がharvestに記録されていることがわかりますね。これ結構簡単じゃないですか?やったことはinventorydをダウンロード、初期設定、起動したことと、メモリを取得するスクリプトをちょっとググって入れただけです。それだけでもうこの状態になる。ある意味HarvestにTCP/UDPでデータ送るより簡単ですよ。

また、inventorydはObserveの際、値が変わっていればNotifyという動作をするため、例えば何かのエラーフラグとかを監視させておいて、それがtrueになったらFunkに通知させる、といった使い方もできそうです。

SORACOM Inventory、何だかすごく便利そうじゃないですか?

インターネットからでも使用可能

SORACOM Inventoryの他のアプリケーションサービスにない特長として、インターネットからソラコム回線なしで使用可能、というのがあります。

以下のページの方法でデバイスID、キーを払い出して、
https://dev.soracom.io/jp/start/inventory_registration_with_keys/

inventory実行時のオプションを以下のように変えるだけです。

inventoryd --identity <払い出されたデバイスID> --psk <払い出されたシークレットキー(base64)>

ちなみにこれまで実行した際に指定していた-bというオプションは、LwM2Mのブートストラップという仕組みを使用したもので、これを使うとSORACOM Airの回線で簡単・安全に認証情報の取得ができます。デバイスごとにパスワードを発行・保存しなくても良いのでとても簡単・便利です。逆に認証情報の発行・保存さえすれば、SORACOM Airの回線でなくとも使用できます。この場合、価格的にはInventoryの使用料金50円だけで済むのでとても安価ですね。

使いどころあるかわかりませんが、PCやサーバに入れても動いて、値の取得や遠隔操作できるようになりますよ(外向きのUDP 5684ポートが空いていれば)

他の遠隔操作方法との比較

ソラコムを使っていると遠隔操作には色々な方法があります。
最近出たSORACOM Napterはとても強力で、遠隔操作はこれで十分、という考えもあると思います。
また、SORACOM BeamとAWS IoTを組み合わせ、MQTTでコマンドを送る、ということもされていると思います。

比較ポイントはいくつかありますが、以下のように比較してみました。

項目 Napter Beam + AWS IoT Inventory
価格 300円/月 0.0018円 * コマンド数(AWS IoT部分除く) 50円/月
同期/非同期 同期 非同期 同期
必要サービス SORACOMで完結 AWSと連携 SORACOMで完結
コマンド発行方法 デバイスにサービスが必要(SSHやWebAPIなど) AWSのWebAPIもしくはMQTT SORACOMのWebAPI
コマンド発行結果 デバイスのサービス次第 仕組みを考える必要あり WebAPIの実行結果
SORACOM Air回線 必須 必須(BeamではなくKryptonとの組み合わせなら要らない) 必須ではない

価格としてはコマンド発行数が少なければBeam + AWS IoT、コマンド発行数が多ければInventoryが有利です。Napterは必要な時のみ使用するという考えなので、使用が前提となっているサービスより割高と考えられます。

コマンドの発行や結果の受け取りはInventoryが一番簡単だと考えています。SORACOMのAPIを使えばよく、応答も同期的に返ってきます。一方AWS IoTは非同期で、応答を返す場合は応答用のトピックを用意して、それを受信する何らかのサブスクライバを用意して受信する、といったことが必要になり、かなり面倒です。逆にAWS IoTは仕組みさえできていれば、多数のデバイスに非同期にメッセージを送り、非同期に返されたメッセージをまとめて収集することができます。同期処理はデバイスが多くなってくると、ひとつずつメッセージを送って応答を取得するのに時間がかかると予想されます。

また、最初の方にも上げましたが、SORACOM InventoryはSORACOMだけで完結できるサービスです。Napterもそうですね。BeamはAWS IoTと組み合わせることになるので、クラウド用意するの大変、となる可能性があります。AWS IoTはそこそこ難しいサービスですしね。逆にクラウドに慣れているのであれば、Beam + AWS IoTはAWSの様々なサービスと連携できる長所を活かせます。

ということで、所感としてそれぞれの構成で向いているのは、以下のような感じかと思います。

SORACOM Napter - デバイスに人が直接アクセスしてのアドホックな操作
SORACOM Inventory - デバイスの項目を指定しての取得や監視、設定値の変更、定型的な操作
SORACOM Beam + AWS IoT - 定常的な値の取得や多数のデバイスに対する一斉操作

すでに他の方法で運用されているところに無理に入れることもないですが、今Harvestで値をとっているだけのところに、ちょっとした制御を入れたい、というような場合にはベストチョイスなのでは無いかと思っています。

おわりに

SORACOM InventoryはIoTデバイスを簡単に管理できるサービスということが感じられましたでしょうか?
inventorydは正直去年公開してからほぼ手つかずですが、また折を見てアップデートしていきたいと思っています。ご要望あればなんらかの形でお伝えください。(このブログへのコメント、GitHubへのIssueなど)そのうち対応するかも知れません。

次回はinventorydを開発の技術的な面を書く予定です。
予定タイトル:「SORACOM Inventoryエージェント開発に向けてDTLS、CoAP、LwM2MをGo言語で実装する」

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2