屋内環境を手軽にモニタリングする～⑦簡易ツールにまとめる～

## はじめに
一連の記事で、一般的な環境情報と産業オートメーション機器の稼動情報を取得するために作成したJavaライブラリについて簡単に紹介してきました。整理すると以下の通りです。

- [BLEアドバタイズ信号スキャン](https://qiita.com/s5uishida/items/a4543c9e7fb13b4c7c6e) ([bluez-dbus](https://github.com/hypfvieh/bluez-dbus)使用)
- [CC2650 - 温度(物体、周囲)、湿度、照度、気圧、運動(角速度、加速度、磁気)](https://qiita.com/s5uishida/items/79a2de6a7026ef230e9b) ([bluez-dbus](https://github.com/hypfvieh/bluez-dbus)使用)
- [MH-Z19B - CO2濃度](https://qiita.com/s5uishida/items/1759498f8f706c4c3314) ([jSerialComm](https://github.com/Fazecast/jSerialComm)使用)
- [PPD42ND - PM2.5濃度](https://qiita.com/s5uishida/items/4ae7784aeaf50df1e3d3) ([Pi4J](https://pi4j.com/)使用)
- [OPC-UA - 産業オートメーション機器の稼動情報](https://qiita.com/s5uishida/items/60954d356a3ea1048c61) ([Eclipse Milo](https://github.com/eclipse/milo)使用)

これらのデータを取得してモニタリングするとともに、取得したデータを他の用途に利用するための仕組みを入れて、簡単なツール(**[rainy](https://github.com/s5uishida/rainy)**)にまとめました。Raspberry Pi 3BにJavaを入れて、[Apache Felix](https://felix.apache.org/) (OSGiフレームワーク)上で動作させています。**rainy**をビルドしてツールにまとめたものは**rainy-felix.zip**として**[こちら](https://github.com/s5uishida/rainy/releases)**で公開しています。

**rainy**の概要のイメージは以下の通りです。
<img width="800" alt="rainy_overview_0_jp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/81686767-d322-467e-4215-de2c48183355.png">
また、次のイメージは、同じRaspberry Pi 3Bにモニタリング機能を同居させた構成です。
<img width="800" alt="rainy_overview_2_jp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/33ccf8b5-15b8-9cf6-bb5c-84648ccf38d2.png">
使用している機器は以下の通りです。
<img width="700" alt="rainy_hardware_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/4b9ffa15-c6e0-f28a-ee9c-315d559d927d.png">
MH-Z19BにUSBシリアル通信アダプターで接続する場合の機器は以下の通りです。
<img width="700" alt="rainy_hardware_0.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/8efb979b-b799-7732-d3b5-1d94a9b0e255.png">
なお、本記事は、[こちらのGithub](https://github.com/s5uishida/rainy)とほぼ同じ内容です。

## 目次
* [目的](#purpose)
* [OSのセットアップ](#setup_os)
* [データ送信のセットアップ](#setup_sending_data)
    * [InfluxDBのインストールと起動](#install_influxdb)
    * [Mosquitto (MQTTブローカ)のインストールと起動](#install_mosquitto)
* [可視化ツールのセットアップ](#install_visualization)
    * [Grafanaのインストールと起動](#install_grafana)
    * [Chronografのインストールと起動](#install_chronograf)
    * [自己署名証明書によるHTTPS接続確認](#test_https_connection)
        * [自己署名による公開鍵(cert.pem)と秘密鍵(cert.key)を作成する](#create_self_signed_cert)
        * [/etc/rainyディレクトリを作成して、公開鍵と秘密鍵を配置する](#create_directory)
        * [GrafanaのHTTPS設定](#set_grafana_https)
        * [ChronografのHTTPS設定](#set_chronograf_https)
* [rainyの設定 - rainy/conf](#configuration)
    * [rainy.properties](#rainy_properties)
    * [データ送信の接続設定](#setting_connection_sending_data)
        * [InfluxDB - influxdb.properties](#influxdb_properties)
        * [MQTT - mqtt.properties](#mqtt_properties)
    * [センサーとプロトコルの設定](#setting_sensors)
        * [CC2650 - cc2650.properties](#cc2650_properties)
        * [MH-Z19B - mhz19b.properties](#mhz19b_properties)
        * [PPD42NS - ppd42ns.properties](#ppd42ns_properties)
        * [OPC-UA - opcua.properties](#opcua_properties)
            * [OPC-UAサーバ - conf/opcua/milo-public-demo.properties](#opcua_server_properties)
* [rainy起動](#run_rainy)
    * [センサーデータをログファイルに出力する](#output_sensor_value)
    * [InfluxDBに作成されたデータベース名を確認する](#check_database)
* [可視化ツールでダッシュボードを作成する](#create_dashboards)
    * [Grafanaの場合](#case_grafana)
    * [Chronografの場合](#case_chronograf)
* [MQTTブローカに送られたデータを確認する](#check_mqtt_data)
* [制限事項](#limitations)
* [バンドル一覧](#bundle_list)

<h2 id="purpose">目的</h2>
このツール**rainy**の目的を簡潔に言うと、以下の通りです。

- 屋内(プライベート/オフィス/工場)において、一般的な環境情報と産業オートメーション機器の稼動情報を取得する。
- これらのデータを概ねリアルタイムにモニタリングし、また、その他の用途で利用できるようにする。
- Raspberry Pi 3B (arm)とUbuntuマシン(amd64)の上で、Java / OSGiアプリケーションとして稼動させる。

**rainy**は、正式な運用には機能も性能も不十分と思いますが、コンパクトで手軽に試せるツールと思います。

<h2 id="setup_os">OSのセットアップ</h2>
Raspberry Pi 3B上で**rainy**を稼動させるためのセットアップについては、[こちら](https://qiita.com/s5uishida/items/1759498f8f706c4c3314)と[こちら](https://qiita.com/s5uishida/items/4ae7784aeaf50df1e3d3)を参考にして下さい。Raspberry Pi 3B内蔵のBluetoothとシリアル通信(UART)を同時に使用することができます。

<h2 id="setup_sending_data">データ送信のセットアップ</h2>
**rainy**は、データの送信先にInfluxDBとMQTTブローカに対応しています。

<h3 id="install_influxdb">InfluxDBのインストールと起動</h3>
Ubuntu 18.04の仮想マシンで[InfluxDB](https://www.influxdata.com/)を使用しています。インストール手順は、[こちら](https://portal.influxdata.com/downloads/)が参考になります。

```
# wget https://dl.influxdata.com/influxdb/releases/influxdb_1.7.8_amd64.deb
# dpkg -i influxdb_1.7.8_amd64.deb
# systemctl enable influxdb.service
# systemctl start influxdb.service
```

なお、Rasbperry Pi 3BにInfluxDBをインストールする手順は、以下の通りです。

```
# wget https://dl.influxdata.com/influxdb/releases/influxdb_1.7.8_armhf.deb
# dpkg -i influxdb_1.7.8_armhf.deb
# systemctl enable influxdb.service
# systemctl start influxdb.service
```

<h3 id="install_mosquitto">Mosquitto (MQTTブローカ)のインストールと起動</h3>
Ubuntu 18.04の仮想マシンで[Mosquitto](https://mosquitto.org/)(MQTTブローカ)を使用しています。インストール手順は、以下の通りです。

```
# apt-get update
# apt-get install mosquitto
# apt-get install mosquitto-clients
# systemctl enable mosquitto.service
# systemctl start mosquitto.service
```

なお、Rasbperry Pi 3BにMosquittoをインストールする手順も同じです。

<h2 id="install_visualization">可視化ツールのセットアップ</h2>

<h3 id="install_grafana">Grafanaのインストールと起動</h3>
Ubuntu 18.04の仮想マシンで[Grafana](https://grafana.com/)を使用しています。インストール手順は、[こちら](https://grafana.com/grafana/download?platform=linux)が参考になります。

```
# wget https://dl.grafana.com/oss/release/grafana_6.3.4_amd64.deb
# dpkg -i grafana_6.3.4_amd64.deb
# systemctl enable grafana-server.service
# systemctl start grafana-server.service
```

なお、Rasbperry Pi 3BにGrafanaをインストールする手順は、以下の通りです。

```
# wget https://dl.grafana.com/oss/release/grafana_6.3.4_armhf.deb
# dpkg -i grafana_6.3.4_armhf.deb
# systemctl enable grafana-server.service
# systemctl start grafana-server.service
```

<h3 id="install_chronograf">Chronografのインストールと起動</h3>
Ubuntu 18.04の仮想マシンで[Chronograf](https://www.influxdata.com/time-series-platform/chronograf/)を使用しています。インストール手順は、[こちら](https://portal.influxdata.com/downloads/)が参考になります。

```
# wget https://dl.influxdata.com/chronograf/releases/chronograf_1.7.14_amd64.deb
# dpkg -i chronograf_1.7.14_amd64.deb
# systemctl enable chronograf.service
# systemctl start chronograf.service
```

なお、Rasbperry Pi 3BにChronografをインストールする手順は、以下の通りです。

```
# wget https://dl.influxdata.com/chronograf/releases/chronograf_1.7.14_armhf.deb
# dpkg -i chronograf_1.7.14_armhf.deb
# systemctl enable chronograf.service
# systemctl start chronograf.service
```

<h3 id="test_https_connection">自己署名証明書によるHTTPS接続確認</h3>
一般に、自己署名証明書を本番運用に用いるのは推奨されませんが、テスト目的なら構わないと思います。

<h4 id="create_self_signed_cert">自己署名による公開鍵(cert.pem)と秘密鍵(cert.key)を作成する</h4>

```
# openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout cert.key -out cert.pem -subj "/CN=localhost" -days 365
```

<h4 id="create_directory">/etc/rainyディレクトリを作成して、公開鍵と秘密鍵を配置する</h4>

```
# mkdir /etc/rainy
# cp cert.pem cert.key /etc/rainy/
# cd /etc/rainy
# chmod 0644 cert.pem cert.key
```

<h4 id="set_grafana_https">GrafanaのHTTPS設定</h4>
詳細は[こちら](https://grafana.com/docs/installation/configuration/)を参照して下さい。

- `/etc/grafana/grafana.ini`を編集します。

```diff
@@ -29,7 +29,7 @@
 #################################### Server ####################################
 [server]
 # Protocol (http, https, socket)
-;protocol = http
+protocol = https
 
 # The ip address to bind to, empty will bind to all interfaces
 ;http_addr =
@@ -58,8 +58,8 @@
 ;enable_gzip = false
 
 # https certs & key file
-;cert_file =
-;cert_key =
+cert_file = /etc/rainy/cert.pem
+cert_key = /etc/rainy/cert.key
 
 # Unix socket path
 ;socket =
```

- Grafanaを再起動し、ブラウザで`https://hostAddress:3000/`に接続します。

```
# systemctl restart grafana-server.service
```

<h4 id="set_chronograf_https">ChronografのHTTPS設定</h4>
詳細は[こちら](https://docs.influxdata.com/chronograf/v1.7/administration/managing-security/)を参照して下さい。

- `/etc/default/chronograf`を編集します。

```
TLS_CERTIFICATE=/etc/rainy/cert.pem
TLS_PRIVATE_KEY=/etc/rainy/cert.key
```

- Chronografを再起動し、ブラウザで`https://hostAddress:8888/`に接続します。

```
# systemctl restart chronograf.service
```

<h2 id="configuration">rainyの設定 - rainy/conf</h2>
<h3 id="rainy_properties">rainy.properties</h3>
- **`clientID`**  
  **rainy**稼動時の、ツールとしてのユニークなIDを設定します。
- **`cc2650`**  
  CC2650を使用する場合は`true`に設定します。デフォルトは`false`。
- **`mhz19b`**  
  MH-Z19Bを使用する場合は`true`に設定します。デフォルトは`false`。
- **`ppd42ns`**  
  PPD42NSを使用する場合は`true`に設定します。デフォルトは`false`。  
  **注意点。PPD42NSはPi4Jから使用するため、rainyはRaspberry Pi (arm)シリーズでのみ、PPD42NSを使用できます。amd64のLinuxマシンではPi4Jを使えないため、その場合は`false`に設定して下さい。**
- **`opcua`**  
  OPC-UAを使用する場合は`true`に設定します。デフォルトは`false`。

<h3 id="setting_connection_sending_data">データ送信の接続設定</h3>
<h4 id="influxdb_properties">InfluxDB - influxdb.properties</h4>
- **`influxDBUrl`**
- **`userName`**
- **`password`**
- `actions`  
  バッチ処理数の単位を設定します。デフォルトは`1000`。
- `flushDuration`  
  flushする時間間隔(msec)を設定します。デフォルトは`1000`。
- `dataOnly`  
  データのみ取得する場合は`true`に設定します。デフォルトは`true`。

<h4 id="mqtt_properties">MQTT - mqtt.properties</h4>
- **`brokerUri`**
- `userName`
- `password`
- **`clientID`**  
  MQTTブローカに接続する際のクライアントIDの前半の文字列を設定します。後半の文字列はシステムが任意の文字列を割り当てて、クライアントIDを完成させます。
- `qos`  
  デフォルトは`0`。
- `topic`  
  MQTTブローカにpublishする際のトピック文字列を設定します。デフォルトは`rainy`。

<h3 id="setting_sensors">センサーとプロトコルの設定<h3>

<h4 id="cc2650_properties">CC2650 - cc2650.properties</h4>
[こちら](https://qiita.com/s5uishida/items/79a2de6a7026ef230e9b)も参考になります。

- **`bluetoothAdapter`**  
  Bluetoothアダプタ名を設定します。デフォルトは`hci0`。使用可能なアダプタ名を確認するには以下のように`hciconfig`コマンドを使用します。

```
# hciconfig -a
hci0:   Type: Primary  Bus: UART
        BD Address: B8:27:EB:7D:0F:7D  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING 
        RX bytes:28342 acl:441 sco:0 events:2265 errors:0
        TX bytes:34605 acl:441 sco:0 commands:1955 errors:0
        Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
        Link policy: RSWITCH SNIFF 
        Link mode: SLAVE ACCEPT 
        Name: 'raspberrypi'
        Class: 0x000000
        Service Classes: Unspecified
        Device Class: Miscellaneous, 
        HCI Version: 4.1 (0x7)  Revision: 0x168
        LMP Version: 4.1 (0x7)  Subversion: 0x2209
        Manufacturer: Broadcom Corporation (15)
```

- **`influxDB`**  
  InfluxDBを使用する場合は`true`に設定します。デフォルトは`false`。
- **`mqtt`**  
  MQTTブローカを使用する場合は`true`に設定します。デフォルトは`false`。
- `prettyPrinting`  
  MQTTブローカに送信する際のJSON形式のデータをログに出力する場合は`true`に設定します。デフォルトは`false`。なお、`conf/logging.properties`の以下のログレベルの変更も必要です。

  ```
  #io.github.s5uishida.level=INFO
  -->
  io.github.s5uishida.level=FINE
  ```

- `readCrontab`  
  データを取得する際のスケジュールをcrontab形式で設定します。デフォルトは毎分。
- `batteryLevel`  
  バッテリーレベルを取得する場合は`true`に設定します。デフォルトは`false`。
- 温度センサーの設定例
  - **`temperature`**  
    温度を取得する場合は`true`に設定します。デフォルトは`false`。
  - `temperatureNotify`  
    通知機能を使用する場合は`true`に設定します。デフォルトは`false`。通知機能を有効にすると、`readCrontab`で指定したスケジュールは無効になります。
  - `temperatureNotificationPeriod`  
    通知の時間間隔を指定します(msec)。デフォルトは`1000`。
- 運動(角速度 / 加速度 / 磁気)
  - `gyroscope`  
    角速度を取得する場合は`true`に設定します。デフォルトは`false`。
  - `accelerometer`  
    加速度を取得する場合は`true`に設定します。デフォルトは`false`。
  - `magnetometer`  
    磁気を取得する場合は`true`に設定します。デフォルトは`false`。
  - `movementNotify`  
    運動に関するセンサーの通知機能を使用する場合は`true`に設定します。通知機能を有効にすると、`readCrontab`で指定したスケジュールは無効になります。
  - `movementNotificationPeriod`  
    通知の時間間隔を指定します(msec)。デフォルトは`1000`。
  - `wakeOnMotion`  
    揺れを検知した時に、運動に関するセンサーデータを送信する場合は`true`に設定します。有効にした場合、10秒間に渡って、指定した通知の時間間隔で運動に関するセンサーデータを送信します。デフォルトは`false`。
  - `accelerometerRange`  
    Accelerometer範囲(G)を設定します。デフォルトは`2`。
- **`devices`**  
  CC2650デバイスのアドレスをスペースを空けて書きます。なお、CC2650デバイスのアドレスを確認するには、`hcitool`コマンドを以下のように実行します。

```
# hcitool lescan
LE Scan ...
B0:B4:48:B9:92:86 (unknown)
B0:B4:48:B9:92:86 CC2650 SensorTag
```

`hcitool`コマンドを実行して、CC2650の電源ボタンを押すと、上記のようにスキャンされたアドレスが表示されます。

<h4 id="mhz19b_properties">MH-Z19B - mhz19b.properties</h4>
[こちら](https://github.com/s5uishida/mh-z19b-driver)も参考になります。

**注意点。PPD42NSと一緒に使用する場合、PPD42NSの4番ピン(黄色)をRaspberry Pi 3Bの19番ピン(GPIO10)または38番ピン(GPIO20)に接続します。あるいは、PPD42NSの4番ピン(黄色)をRaspberry Pi 3Bの8番ピン(GPIO14)に接続する場合、MH-Z19BにはUSBシリアル通信アダプタ経由でRaspberry Pi 3Bに接続して下さい(DSD TECH SH-U09C USB to TTL Serial Adapter with FTDI FT232RL Chipなど)。MH-Z19BをUSBシリアル通信アダプタに接続すると、シリアル通信のポート名は、`/dev/ttyUSB0`になると思います。**

- **`portName`**  
  シリアル通信のポート名を設定します。デフォルトは`/dev/ttyAMA0`。
- **`influxDB`**  
  InfluxDBを使用する場合は`true`に設定します。デフォルトは`false`。
- **`mqtt`**  
  MQTTブローカを使用する場合は`true`に設定します。デフォルトは`false`。
- `prettyPrinting`  
  MQTTブローカに送信する際のJSON形式のデータをログに出力する場合は`true`に設定します。デフォルトは`false`。なお、`conf/logging.properties`の以下のログレベルの変更も必要です。

  ```
  #io.github.s5uishida.level=INFO
  -->
  io.github.s5uishida.level=FINE
  ```

- `readCrontab`  
  データを取得する際のスケジュールをcrontab形式で設定します。デフォルトは毎分。

<h4 id="ppd42ns_properties">PPD42NS - ppd42ns.properties</h4>
[こちら](https://github.com/s5uishida/ppd42ns-driver)も参考になります.

- **`gpioPin`**  
  `GPIO_10`、`GPIO_20`または`GPIO_14`のいずれかを設定します。デフォルトは`GPIO_10`。
- **`influxDB`**  
  InfluxDBを使用する場合は`true`に設定します。デフォルトは`false`。
- **`mqtt`**  
  MQTTブローカを使用する場合は`true`に設定します。デフォルトは`false`。
- `prettyPrinting`  
  MQTTブローカに送信する際のJSON形式のデータをログに出力する場合は`true`に設定します。デフォルトは`false`。なお、`conf/logging.properties`の以下のログレベルの変更も必要です。

  ```
  #io.github.s5uishida.level=INFO
  -->
  io.github.s5uishida.level=FINE
  ```

- `readCrontab`  
  データを取得する際のスケジュールをcrontab形式で設定します。デフォルトは毎分。

<h4 id="opcua_properties">OPC-UA - opcua.properties</h4>

- **`influxDB`**  
  InfluxDBを使用する場合は`true`に設定します。デフォルトは`false`。
- **`mqtt`**  
  MQTTブローカを使用する場合は`true`に設定します。デフォルトは`false`。
- `prettyPrinting`  
  MQTTブローカに送信する際のJSON形式のデータをログに出力する場合は`true`に設定します。デフォルトは`false`。なお、`conf/logging.properties`の以下のログレベルの変更も必要です。

  ```
  #io.github.s5uishida.level=INFO
  -->
  io.github.s5uishida.level=FINE
  ```

- `keyStoreType`
- `keyStoreAlias`
- `keyStorePassword`
- `certificate`

<h5 id="opcua_server_properties">OPC-UAサーバ - conf/opcua/milo-public-demo.properties</h5>
以下は、[Eclipse Miloの公開デモサーバ](https://github.com/eclipse/milo)の設定例です。

- **`use`**  
  このOPC-UAサーバに接続する場合は`true`に設定します。デフォルトは`false`。
- **`serverName`**  
  OPC-UAサーバ名を設定します。
- **`endpointIP`**  
  OPC-UAサーバのアドレスを設定します。
- **`endpointPort`**  
  OPC-UAサーバのポート番号を設定します。
- `securityPolicy`  
  securityPolicyについて、`Basic128Rsa15`、`Basic256`、`Basic256Sha256`、`None`のいずれかを設定します。デフォルトは`None`。
- `securityMode`  
  securityModeについて、`Sign`、`SignAndEncrypt`、`None`のいずれかを設定します。デフォルトは`None`。
- `userName`
- `password`
- `requestTimeout`  
  デフォルトは`10000`(msec)。
- `sessionTimeout`  
  デフォルトは`10000`(msec)。
- `publishingInterval`  
  MonitoredItemにおけるpublishingIntervalを設定します(msec)。デフォルトは`1000`。
- `samplingInterval`  
  MonitoredItemにおけるsamplingIntervalを設定します(msec)。デフォルトは`500`。
- `queueSize`  
  MonitoredItemにおけるqueueSizeを設定します。デフォルトは`10`。
- `dataChangeTrigger`  
  MonitoredItemにおけるDataChangeTriggerについて、以下のいずれかを設定します。  
  - `0` for DataChangeTrigger.Status
  - `1` for DataChangeTrigger.StatusValue
  - `2` for DataChangeTrigger.StatusValueTimestamp  
  デフォルトは`1`。
- **`nodeIDs`**  
  観測するノードIDをスペースを空けて書きます。書式は以下の通りです。

  ```
  <namespaceIndex>,<identifier>,<depth>
  ```

以下はサンプルです。depthに`-1`を設定すると、ノードIDを起点に末端までノードIDを探索します。

  ```
  nodeIDs=2,Dynamic/RandomInt32,0 \
	  2,Dynamic/RandomInt64,0 \
	  2,Dynamic,-1 \
	  0,2295,-1
  ```

上記の例では、ノードIDに`2,Dynamic/RandomInt32`と`2,Dynamic/RandomInt64`を明示的に指定し、併せて、`2,Dynamic`と`0,2295`(VendorServerInfo)から下の階層のノードIDを末端まで探索します。

なお、`conf/opcua`ディレクトリには、`milo-example.properties`もあります。これは、Eclipse Miloに含まれているサンプルサーバをビルドした[milo-example-server](https://github.com/s5uishida/milo-example-server)への接続設定の例です。

参考までに、OPC-UAサーバのAddressSpaceを確認するための簡易ツールとして、[toem impulse OPC/UA Extension (Eclipse pulug-in)](https://toem.de/index.php/projects/impulse-opcua)があります。

<h2 id="run_rainy">rainy起動</h2>

- 起動  
  以下のように起動します。

```
# cd /path/to/rainy-felix/bin
# sh rainy-start.sh
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.felix.framework.ext.ClassPathExtenderFactory$DefaultClassLoaderExtender (file:/path/to/rainy-felix/bin/felix.jar) to method java.net.URLClassLoader.addURL(java.net.URL)
WARNING: Please consider reporting this to the maintainers of org.apache.felix.framework.ext.ClassPathExtenderFactory$DefaultClassLoaderExtender
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (6.0.3)
[   1] [Active     ] [    1] bcpkix (1.62)
[   2] [Active     ] [    1] bcprov (1.62)
[   3] [Active     ] [    1] bluetooth scanner (0.1.1)
[   4] [Active     ] [    1] bluez-dbus-osgi (0.1.2.201908052042)
[   5] [Active     ] [    1] bsd-parser-core (0.3.3)
[   6] [Active     ] [    1] bsd-parser-gson (0.3.3)
[   7] [Active     ] [    1] java driver for ti sensortag cc2650 (0.1.0)
[   8] [Active     ] [    1] Apache Commons Lang (3.9.0)
[   9] [Active     ] [    1] cron4j-osgi (2.2.5)
[  10] [Active     ] [    1] dbus-java-with-java-utils-osgi (3.0.2)
[  11] [Active     ] [    1] Gson (2.8.5)
[  12] [Active     ] [    1] Guava: Google Core Libraries for Java (26.0.0.jre)
[  13] [Active     ] [    1] Java client for InfluxDB (2.15)
[  14] [Active     ] [    1] jSerialComm (2.5.1)
[  15] [Active     ] [    1] Jackson-annotations (2.9.9)
[  16] [Active     ] [    1] Jackson-core (2.9.9)
[  17] [Active     ] [    1] jackson-databind (2.9.9.1)
[  18] [Active     ] [    1] JavaBeans Activation Framework (1.2.0)
[  19] [Active     ] [    1] jaxb-api (2.4.0.b1808300359)
[  20] [Active     ] [    1] file:/home/pi/rainy-felix/bundle/jaxb-runtime-2.4.0-b180830.0438.jar
[  21] [Active     ] [    1] java driver for mh-z19b - intelligent infrared co2 module (0.1.2)
[  22] [Active     ] [    1] A modern JSON library for Kotlin and Java (1.7.0)
[  23] [Active     ] [    1] MessagePack serializer implementation for Java (0.8.17)
[  24] [Active     ] [    1] Netty/Buffer (4.1.38.Final)
[  25] [Active     ] [    1] netty-channel-fsm-osgi (0.3.0)
[  26] [Active     ] [    1] Netty/Codec (4.1.38.Final)
[  27] [Active     ] [    1] Netty/Codec/HTTP (4.1.38.Final)
[  28] [Active     ] [    1] Netty/Common (4.1.38.Final)
[  29] [Active     ] [    1] Netty/Handler (4.1.38.Final)
[  30] [Active     ] [    1] Netty/Resolver (4.1.38.Final)
[  31] [Active     ] [    1] Netty/Transport (4.1.38.Final)
[  32] [Active     ] [    1] Apache Felix Shell Service (1.4.3)
[  33] [Active     ] [    1] Apache Felix Shell TUI (1.4.1)
[  34] [Active     ] [    1] Apache ServiceMix :: Bundles :: jsr305 (3.0.2.1)
[  35] [Active     ] [    1] Apache ServiceMix :: Bundles :: okhttp (3.14.1.1)
[  36] [Active     ] [    1] Apache ServiceMix :: Bundles :: okio (1.15.0.1)
[  37] [Active     ] [    1] Apache ServiceMix :: Bundles :: retrofit (2.5.0.2)
[  38] [Active     ] [    1] Paho MQTT Client (1.2.1)
[  39] [Active     ] [    1] OSGi LogService implemented over SLF4J (1.7.26)
[  40] [Active     ] [    1] Pi4J :: Java Library (Core) (1.2)
[  41] [Active     ] [    1] java driver for ppd42ns - dust sensor module (0.1.6)
[  42] [Active     ] [    1] osgi activator of rainy - a tiny tool for iot data collection and monitoring (0.1.6)
[  43] [Active     ] [    1] OPC-UA bundle of rainy - a tiny tool for iot data collection and monitoring (0.1.4)
[  44] [Active     ] [    1] rainy - a tiny tool for iot data collection and monitoring (0.1.14)
[  45] [Active     ] [    1] sdk-client (0.3.3)
[  46] [Active     ] [    1] sdk-core (0.3.3)
[  47] [Active     ] [    1] slf4j-api (1.7.26)
[  48] [Resolved   ] [    1] slf4j-jdk14 (1.7.26)
[  49] [Active     ] [    1] stack-client (0.3.3)
[  50] [Active     ] [    1] stack-core (0.3.3)
[  51] [Active     ] [    1] strict-machine-osgi (0.1.0)
-> 
```

- 停止  
  以下のように停止します。

```
-> stop 0
```

<h4 id="output_sensor_value">センサーデータをログファイルに出力する</h4>

`conf/logging.properties`の以下のログレベルを`INFO --> FINE`に変更して、**rainy**を再起動すると、取得したセンサーデータがログファイル`logs/rainy.log.0`に出力されます。

```
#io.github.s5uishida.level=INFO
-->
io.github.s5uishida.level=FINE
```

ログファイルの出力例は以下の通りです。なお、行の先頭を省略しています。

```
[/dev/ttyAMA0] co2:850 
[hci0] B0:B4:48:B9:92:86 obj:28.28125 amb:32.28125 
[hci0] B0:B4:48:B9:92:86 humidity:59.362793 
[hci0] B0:B4:48:B9:92:86 pressure:1012.27 
[hci0] B0:B4:48:B9:92:86 optical:227.28 
[hci0] B0:B4:48:B9:92:86 gyr[x]:-1.3198851 
[hci0] B0:B4:48:B9:92:86 gyr[y]:-0.2593994 
[hci0] B0:B4:48:B9:92:86 gyr[z]:0.7476806 
[hci0] B0:B4:48:B9:92:86 acc[x]:0.0056152344 
[hci0] B0:B4:48:B9:92:86 acc[y]:-0.007080078 
[hci0] B0:B4:48:B9:92:86 acc[z]:0.9707031 
[hci0] B0:B4:48:B9:92:86 mag[x]:127.0 
[hci0] B0:B4:48:B9:92:86 mag[y]:420.0 
[hci0] B0:B4:48:B9:92:86 mag[z]:302.0
[GPIO_10] pcs:1373.6702 ugm3:2.1420693
```

なお、Raspberry Pi 3BのSDカードへの書き込み回数を減らすため、通常はログレベルを`INFO`に設定することを推奨します。

<h4 id="check_database">InfluxDBに作成されたデータベース名を確認する</h4>

ログファイル`logs/rainy.log.0`から、InfluxDBに作成されたデータベース名を確認します。以下はそれぞれのセンサー用に作成されたデータベース名の例です。

- MH-Z19B ⇒ `RP3B_01__dev_ttyAMA0`
- CC2650 ⇒ `B0_B4_48_B9_92_86`と`B0_B4_48_ED_B6_04`
- Eclipse Milo公開デモサーバ ⇒ `milo_digitalpetri_com_62541_milo`
- PPD42NS ⇒ `RP3B_01_GPIO_10`

```
execute - CREATE DATABASE RP3B_01__dev_ttyAMA0
...
execute - CREATE DATABASE B0_B4_48_B9_92_86
...
execute - CREATE DATABASE B0_B4_48_ED_B6_04
...
execute - CREATE DATABASE milo_digitalpetri_com_62541_milo
...
execute - CREATE DATABASE RP3B_01_GPIO_10
```

これらのデータベース名は、GrafanaやChronografでダッシュボードを作成する際、InfluxDBに接続する情報として必要になります。

<h2 id="create_dashboards">可視化ツールでダッシュボードを作成する</h2>

時系列なセンサーデータをモニタリングするために、可視化ツールのGrafanaやChronografからInfluxDBに接続します。

<h4 id="case_grafana">Grafanaの場合</h4>

Grafanaの使い方は、[こちら](https://grafana.com/docs/)のGetting startedを参照して下さい。以下のグラフは、Grafanaで作成したダッシュボードのイメージ例です。 
<img width="800" alt="rainy_grafana_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/d474ad14-bd13-c0cb-ebeb-5d065f5803c2.png">
以下のグラフは、[Plotly](https://grafana.com/grafana/plugins/natel-plotly-panel)パネルを使用した磁気(3軸)の3Dイメージ例です。
<img width="800" alt="rainy_grafana_1_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/6680766c-260b-de8c-eb7b-3c14afafc98b.png">
以下のグラフは、[ImageIt](https://grafana.com/grafana/plugins/pierosavi-imageit-panel)パネルを使用してセンサーデータをフロアにマッピングしたイメージ例です。3つの部屋にCC2650を配置して、メインの部屋にMH-Z19B(CO2濃度)とPPD42NS(PM2.5濃度)を配置しています。
<img width="800" alt="rainy_floor_env_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/27f3b1c6-fe9e-098a-e3fd-39806df13574.png">

<h4 id="case_chronograf">Chronografの場合</h4>

Chronografの使い方は、[こちら](https://docs.influxdata.com/chronograf/v1.7/)のGetting startedを参照して下さい。以下のグラフは、Chronografで作成したダッシュボードのイメージ例です。 
<img width="800" alt="rainy_chronograf_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/b4148e11-0ee8-371d-5dd1-60f2cf06ba4d.png">
以下のグラフは、Eclipse Miloの公開デモサーバの次のノードIDを対象とするダッシュボードのイメージ例です。
- `1,VendorServerInfo/ProcessCpuLoad`
- `1,VendorServerInfo/SystemCpuLoad`
- `1,VendorServerInfo/UsedMemory`
- `2,Dynamic/RandomDouble`
- `2,Dynamic/RandomFloat`
- `2,Dynamic/RandomInt32`
- `2,Dynamic/RandomInt64`
<img width="800" alt="rainy_opcua_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457466/2bb7e8b0-58f2-f299-56f8-d17f73069d77.png">
上段は`1,VendorServerInfo/ProcessCpuLoad`、`1,VendorServerInfo/SystemCpuLoad`、`1, VendorServerInfo/UsedMemory`の各ノードIDのデータを表示しています。中段は`2,Dynamic/RandomDouble`と`2,Dynamic/RandomFloat`の各ノードIDのデータを重ねて表示しています。下段は`2,Dynamic/RandomInt32`と`2,Dynamic/RandomInt64`の各ノードIDのデータを表示しています。

可視化ツールのGrafanaやChronografを使用すると、InfluxDBに送られた各センサーの時系列データのダッシュボードを簡単に作成することができます。

<h2 id="check_mqtt_data">MQTTブローカに送られたデータを確認する</h2>

MQTTクライアントコマンドを以下のように実行して、MQTTブローカに送信されたデータを確認することができます。

```
# mosquitto_sub -d -t rainy/B0_B4_48_ED_B6_04
Client mosqsub|2095-u1804 sending CONNECT
Client mosqsub|2095-u1804 received CONNACK
Client mosqsub|2095-u1804 sending SUBSCRIBE (Mid: 1, Topic: rainy/B0_B4_48_ED_B6_04, QoS: 0)
Client mosqsub|2095-u1804 received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|2095-u1804 received PUBLISH (d0, q0, r0, m0, 'rainy/B0_B4_48_ED_B6_04', ... (670 bytes))
{"deviceID":"B0:B4:48:ED:B6:04","clientID":"RP3B-01","samplingDate":"2019-08-09 12:56:00.009","samplingTimeMillis":1565351760009,"samplingTimeNanos":0,"firmwareVersion":"1.30 (May 23 2016)","batteryLevel":{"value":72,"unit":"%"},"objectTemperature":{"value":27.46875,"unit":"deg C"},"ambientTemperature":{"value":32.03125,"unit":"deg C"},"humidity":{"value":34.61914,"unit":"%"},"pressure":{"value":1009.16,"unit":"hPa"},"optical":{"value":203.84,"unit":"lux"},"gyroscope":{"x":-10.589599,"y":-7.8887935,"z":-2.281189,"unit":"deg/s"},"accelerometer":{"x":-0.029785156,"y":-0.06347656,"z":1.1887207,"unit":"G"},"magnetometer":{"x":138.0,"y":125.0,"z":-199.0,"unit":"uT"}}
```

<h2 id="limitations">制限事項</h2>
- Bluetoothアダプタは同時に一つしか使えません。
- Bluetoothチップの制限で、同時に使用できるCC2650の個数は数個程度と思います。
- CC2650との接続が切れた時、自動再接続に失敗することがあります。
- PPD42NSはPi4Jから使用するため、**rainy**はRaspberry Pi (arm)シリーズでのみ、PPD42NSを使用できます。amd64のLinuxマシンではPi4Jを使えないため、PPD42NSを使用できません。
- OPC-UAサーバについて、観測対象のノードIDの個数とpublishing intervalの兼ね合いで、InfluxDBの負荷が極端に上がる可能性があります。

<h2 id="bundle_list">バンドル一覧</h2>

わたしが作成した以下のバンドルのライセンスはMITライセンスです。
- [bluetooth-scanner 0.1.1](https://github.com/s5uishida/bluetooth-scanner)
- [cc2650-driver 0.1.0](https://github.com/s5uishida/cc2650-driver)
- [mh-z19b-driver 0.1.2](https://github.com/s5uishida/mh-z19b-driver)
- [ppd42ns-driver 0.1.6](https://github.com/s5uishida/ppd42ns-driver)
- [rainy-activator 0.1.6](https://github.com/s5uishida/rainy-activator)
- [rainy-opcua 0.1.4](https://github.com/s5uishida/rainy-opcua)
- [rainy 0.1.14](https://github.com/s5uishida/rainy)

その他に利用している3rdパーティの以下のバンドルについては、各ライセンスをご確認下さい。
- [SLF4J 1.7.26](https://www.slf4j.org/)
- [Apache Commons Lang 3.9](https://commons.apache.org/proper/commons-lang/)
- [dbus-java-with-java-utils-osgi 3.0.2](https://github.com/s5uishida/dbus-java-with-java-utils-osgi)
- [bluez-dbus-osgi 0.1.2](https://github.com/s5uishida/bluez-dbus-osgi)
- [cron4j-osgi 2.2.5](https://github.com/s5uishida/cron4j-osgi)
- [influxdb-java-osgi 2.15.0](https://github.com/s5uishida/influxdb-java-osgi)
- [msgpack-core-osgi 0.8.17](https://github.com/s5uishida/msgpack-core-osgi)
- [moshi-osgi 1.7.0](https://github.com/s5uishida/moshi-osgi)
- [Jackson 2.9.9](https://github.com/FasterXML/jackson) [annotations](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations/2.9.9), [core](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core/2.9.9), [databind](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind/2.9.9.1)
- [Apache Felix 6.0.3](https://felix.apache.org/)
- [Apache Felix Shell 1.4.3](https://felix.apache.org/documentation/subprojects/apache-felix-shell.html)
- [Apache Felix Shell TUI 1.4.1](https://felix.apache.org/documentation/subprojects/apache-felix-shell-tui.html)
- [JSR 305 3.0.2](https://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsr305/3.0.2_1)
- [Okio 1.15.0](https://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.okio/1.15.0_1)
- [OkHttp 3.14.1](https://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.okhttp/3.14.1_1)
- [Retrofit 2.5.0](https://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.retrofit/2.5.0_2)
- [Eclipse Paho Client Mqttv3 1.2.1](https://mvnrepository.com/artifact/org.eclipse.paho/org.eclipse.paho.client.mqttv3/1.2.1)
- [jSerialComm 2.5.1](https://mvnrepository.com/artifact/com.fazecast/jSerialComm/2.5.1)
- [Netty 4.1.38](https://netty.io/index.html) netty-buffer-4.1.38.Final.jar, netty-codec-4.1.38.Final.jar, netty-codec-http-4.1.38.Final.jar, netty-common-4.1.38.Final.jar, netty-handler-4.1.38.Final.jar, netty-resolver-4.1.38.Final.jar, netty-transport-4.1.38.Final.jar
- [JAXB API 2.4.0](https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api/2.4.0-b180830.0359)
- [JAXB Runtime 2.4.0](https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime/2.4.0-b180830.0438)
- [JavaBeans Activation Framework (JAF) 1.2.0](https://mvnrepository.com/artifact/com.sun.activation/javax.activation/1.2.0)
- [strict-machine-osgi 0.1](https://github.com/s5uishida/strict-machine-osgi)
- [netty-channel-fsm-osgi 0.3](https://github.com/s5uishida/netty-channel-fsm-osgi)
- [bsd-parser-core 0.3.3](https://mvnrepository.com/artifact/org.eclipse.milo/bsd-parser-core/0.3.3)
- [bsd-parser-gson 0.3.3](https://mvnrepository.com/artifact/org.eclipse.milo/bsd-parser-gson/0.3.3)
- [stack-core 0.3.3](https://mvnrepository.com/artifact/org.eclipse.milo/stack-core/0.3.3)
- [stack-client 0.3.3](https://mvnrepository.com/artifact/org.eclipse.milo/stack-client/0.3.3)
- [sdk-core 0.3.3](https://mvnrepository.com/artifact/org.eclipse.milo/sdk-core/0.3.3)
- [sdk-client 0.3.3](https://mvnrepository.com/artifact/org.eclipse.milo/sdk-client/0.3.3)
- [Gson 2.8.5](https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5)
- [Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs 1.62](https://www.bouncycastle.org/download/bcpkix-jdk15on-162.jar)
- [Bouncy Castle Provider 1.62](https://www.bouncycastle.org/download/bcprov-jdk15on-162.jar)
- [Guava: Google Core Libraries for Java 26.0](https://repo1.maven.org/maven2/com/google/guava/guava/26.0-jre/guava-26.0-jre.jar)
- [Pi4J 1.2 (pi4j-core.jar)](https://pi4j.com/download/pi4j-1.2.zip)

これらのバンドルの開発者ならびに貢献された方々に感謝致します。

## 一連の記事
このシリーズは、以下の記事から構成されます。
1. [動機とコンセプト](https://qiita.com/items/9c31e6fd9b6eb0fa9c96)
2. [Bluetooth LEアドバタイズ信号をJavaでキャッチする(Bluetooth LE / bluez-dbus)](https://qiita.com/items/a4543c9e7fb13b4c7c6e)
　関連するGithubは[こちら](https://github.com/s5uishida/bluetooth-scanner)。
3. [TI SensorTag CC2650から温度/湿度/照度などをJavaで取得する(Bluetooth LE / bluez-dbus)](https://qiita.com/items/79a2de6a7026ef230e9b)
　関連するGithubは[こちら](https://github.com/s5uishida/cc2650-driver)。
4. [MH-Z19BからCO2濃度をJavaで取得する(シリアル通信 / jSerialComm)](https://qiita.com/items/1759498f8f706c4c3314)
　関連するGithubは[こちら](https://github.com/s5uishida/mh-z19b-driver)。
5. [PPD42NSからPM2.5濃度をJavaで取得する(GPIO / Pi4J)](https://qiita.com/items/4ae7784aeaf50df1e3d3)
　関連するGithubは[こちら](https://github.com/s5uishida/ppd42ns-driver)。
6. [産業オートメーション機器の稼動情報をJavaで取得する(OPC-UA / Eclipse Milo)](https://qiita.com/s5uishida/items/60954d356a3ea1048c61)
　関連するGithubは[こちら](https://github.com/s5uishida/rainy-opcua)。
7. **簡易ツールにまとめる(今回)**
　関連するGithubは[こちら](https://github.com/s5uishida/rainy)。
8. [後記](https://qiita.com/items/d2a888eb2d68e72f32ae)

## 追記
[2019.11.16]
簡易ツールの最新情報は、[こちら](https://github.com/s5uishida/rainy)をご参照下さい。