Mozilla IoT(WoTの実装)をさわってみました

# はじめに

IoTシステムの開発をWeb技術を使って行うことができるWeb of Things(WoT)という[W3Cの仕様](https://www.w3.org/WoT/)があります。
WoTのルールに従ってThing（デバイス）の振る舞いを定義・実装することで、Web技術者がIoTシステムを開発できるようにすること、IoTシステム開発の技術的な敷居を下げること、がこの仕様の狙いと思われます。
WoTの調査の一環として、WoTの実装である[Mozilla IoT](https://iot.mozilla.org/)を試してみることにしました。

# WoTについて

WoTでは、センサやアクチュエータ等のThingが持つ機能をREST APIやWebSocket APIで利用するためのインターフェースを定義する標準的な方法を提供します。インターフェースを標準化プログラムをWebThingと呼ぶことにします。

インターフェースを標準化するため、Thingを制御するクライアントプログラムをRESTやWebSocket等のWeb技術を使って開発できるようになります。
さらに、Thingが提供する機能の利用の仕方はJSON-LDの形式でクライアントプログラムから参照できるようになるため、多様なWebThingを操作する汎用的なクライアントプログラムを実現できるようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/e545eb9e-cc87-315b-0807-f9758a834a38.png" width=50%>

# Mpzilla IoTが提供するプログラム

* [WebThings Framework](https://iot.mozilla.org/framework/)
デバイスをWebThing化するためのフレームワークを提供します。JavaScript、Python、Java等複数の言語向けのフレームワークがあります。

* [WebThings Gateway](https://iot.mozilla.org/gateway/)
~~WebThingのクライアントプログラムであるWebThings Gatewayを提供します。~~　家庭内等の同じネットワークに配置されたデバイスをWebThingとしてインターネットに公開するためのWebThings Gatewayを提供します。WebThings GatewayはAdd-Onを追加することで多様なデバイスを接続できるようになっています。Add-Onのひとつに、WebThingのAdd-Onもあります。
WebThings Gatewayは、接続したデバイスをWebブラウザから操作するためのGUIも提供します。また、Rules機能によりThingの機能を自動制御することもできますし、Floorplanによりデバイスの配置された場所を管理することもできます。

<img width="542" alt="スクリーンショット 2019-08-25 23.19.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/1598d5c7-ef2d-50bd-4908-1357986a397b.png">

また、プログラムの提供ではないですが、MozillaはTunnelingサービスも提供しているため、これを利用することで(試していないですが)、Firewall内に配置したGatewayのGUIをFirewall外からであっても利用できるようになると思われます。

# Mozilla IoTで試したこと

WebThings Frameworkを使ったサンプル(JavaScript版)を実行し、それをWebThings Gatewayに接続し、Webブラウザを使って操作できるようにします。

## WebThingsのサンプルのインストール

下記を参照してインストールを行いました。
https://iot.mozilla.org/framework/

今回はJavaScript版で試しました。
前提としてNode.js(npm)がインストールされている必要があります。
実行したコマンドをメモしておきます。

```
mkdir wthing
cd wthing
npm init
npm i webthing -S
npm i uuid -S
```

webthingのインストールのときに一緒にダウンロードされたサンプルプログラムを利用します。
node_modulesフォルダの下から取り出します。

```
cp node_modules/webthing/example/*.js .
```

サンプルを実行します。
3つのサンプルがありますが、今回は以下を試しました。

```
node multiple-things.js
```

実行後、Webブラウザでhttp://localhost:8888にアクセスした結果、JSONが返ってきたら成功です。

ここで返ってきたJSONが、Thingsのインターフェース定義をJSON-LDで表現したものです。
クライアントプログラムでは、この定義を利用してThingsが持つ機能を知ることができます。

## WebThings Gatewayのインストール

以下に従って実施しました。
https://github.com/mozilla-iot/gateway

色々なモジュールをインストールする必要がありそうなので、Vagrantを使って仮想環境を作成して実施することにしました。
OSにはdebianを利用します。

```
cd gateway
vagrant init debian/stretch64
```

作成されたVagrantfileを編集し、以下の記載の行のコメントを外して保存します。

```
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.10"
```

これにより、ホストOSから192.168.33.10のIPで仮想環境にアクセスできるようになります。

仮想環境を起動し、SSH接続します。

```
vagrant up
vagrant ssh
```

以下のコマンドを実施してNode.jsの環境を構築します。

```
sudo apt update
sudo apt install pkg-config
sudo apt install curl
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
. ~/.bashrc
nvm install --lts
nvm use --lts
node -v
```

インストールしたnodeのバージョンが表示されたら成功です。

```
nvm alias default lts/*
```

上記によりltsのバージョンをデフォルトに設定する。

手順によると、Bluetooth及びUSB関連のインストールをしていますが、今回は仮想環境で実施するためこれらは実施しません。
続けて以下を実施していきます。

```
sudo apt install autoconf
sudo apt install libpng16-16
sudo apt install git
sudo apt install build-essential
sudo apt install libnanomsg4 libnanomsg-dev
```

ここまでが前提環境の構築となります。

次に、WebThings Gatewayをインストールします。

```
mkdir mozilla-iot-gateway
cd mozilla-iot-gateway
git clone https://github.com/mozilla-iot/gateway.git
cd gateway
npm i
npm start
```

以上でWebThings Gatewayが立ち上がります。

## WebThings Gatewayを使ってWebThingを操作してみる

ホストOSのWebブラウザを開いて以下にアクセスします。

http://192.168.33.10:8080/

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/1e17b59c-fdfc-00f6-d310-0fd5145f0008.png" width="70%"/>

ここでsubdomainを設定することで、WebThings GatewayがFirewallの中にあったとしてもインターネットからWebThings Gatewayを操作できるようになると思われますが、今回はWebThings Gatewayを試してみたいだけなので、Skipボタンを押してこの設定は行わないことにします。

次にユーザ登録を行います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/2002daf3-29e1-0392-5413-c784cbf31099.png" width="70%"/>

必要な情報を入力し、Nextボタンを押します。
Thingsの画面が表示されますが、まだ何も登録していないため以下のような画面が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/ce209a80-6e69-0d6b-b2bf-967420b484ad.png" width="70%"/>

ホストOSで起動させているサンプルのWebThingを登録してみます。

WebThings Gatewayは、Add-Onを追加することで多様なデバイスを操作できるように設計されており、WebThingもAdd-onの一つとして登録する必要があります。

WebThingのAdd-onを追加する手順を説明します。
左上のメニューボタンを押して出てきたサイドメニューのSettingsを押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/ca417580-9678-c529-54f1-26399d428342.png" width="70%"/>

以下のようなメニューが表示されますのでAdd-onsを押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/ce51b6d4-342b-9545-fb47-3c9ccb0db06c.png" width="70%"/>

Add-onsはまだ何も追加していない状態なので以下のように空の画面が表示されます。
右下の+ボタンを押下します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/e6f83fcf-29eb-d8af-8b29-06f6bd4ed6a7.png" width="70%"/>

Add-onの一覧が表示されるので、ここからWeb Thingを探し+ Addボタンを押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/9de26c05-2e20-205d-6f3c-1d3c2594d1d2.png" width="70%"/>

左上の←ボタンから一つ前の画面に戻ると以下の画面が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/addea28e-0451-74a4-9243-5c127aa1edc8.png" width="70%"/>

Configureボタンを押し、URLを入力します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/b19850fb-284f-75dc-761e-a7f6f96e7620.png" width="70%"/>

urlsの下の+ボタンを押し、WebThings Gatewayが稼働する仮想環境からホストOSで稼働うサンプルのWebThingを特定するためのURLを入力します。
今回の環境では、以下のURLでWeb Thingを特定できます。

http://192.168.56.1:8888

画面からこれを入力し、Applyボタンを押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/35450035-f219-2643-c1f7-4fbe8058a898.png" width="70%"/>

これでAdd-onの追加は完了です。

WebThings GatewayでWebThingを扱えるようになったため、左上の←ボタンを押し、左上のメニューボタンを押し、サイドメニューからThingsを選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/ce209a80-6e69-0d6b-b2bf-967420b484ad.png" width="70%"/>

右下の+ボタンを押下します。
My LampとMy Humidity Sensorの二つのThingが見つかります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/9a3e2ad9-f468-7a34-cc65-c254af884559.png" width="70%"/>

各Thingの右のSaveボタンを押します。
右上の←ボタンを押すと以下の画面が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/cfb33d83-fef5-0538-083b-87b446b96f35.png" width="70%"/>

My Humidity Sensorの値を確認すること、またMy Lampを操作をすることができるようになりました。
My Lamp上部の円を押すことでOn/Offができますし、右上のヒトデのようなボタンを押すことで細かい設定を行うことも可能です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/36e7be74-b86c-38f0-c546-acd41a748547.png" width="70%"/>

再度メニューのRulesを使って自動制御を設定することも簡単にできそうです。
(Humidityが20%以上になったらLampを付ける、逆に20%未満になったらLampを消す、といったRulesはとても簡単に作れました)

また、WebThings Gateway経由でWebThingにアクセスするためには以下の手順でAuthorizationの設定をする必要があるようです。

1.　WebThings Gatewayの画面から、[Settings]-[Developer]-[Create local authorization]の順にクリックします。
2.　Authorization Request画面が表示されますので、ここでアクセスさせたいThingを選択します。ここではAllow for all Thingsを選択しました。
3.　Allowボタンを押下します。
4.　JSON Web Tokenが生成され、これを利用したCurl等を利用したアクセスのサンプルが表示されます。

上記サンプルを参考しWebThings GatewayにアクセスするとREST APIにアクセスできます。

# 最後に

Mozilla IoTを利用すれば、WebThingの開発(今回はサンプルをそのまま利用しましたが)や、WebThingをWebブラウザから操作する仕組みが簡単に作れそうです。

WebThings Frameworkによる支援があるとはいえ、多機能なデバイスをWebThing化することは手間がかかるため、デバイスメーカによるWebThingの提供や多様なWebThingが流通され、簡単に入手できるようになると良いと思います。

今後は、WebThings Frameworkで実際にWebThingを開発してみようと思います。
また、REST API、WebSocket API以外の通信方式(MQTT等)を利用する方法についても調べられたらと思っています。

間違いや認識違い等あればお気軽にご指摘頂けましたら幸いです。