Omron環境センサの値をRaspberryPiでロギング（USB型）

# はじめに
本記事は、[**Omron環境センサ（BAG型）の記事**](https://qiita.com/c60evaporator/items/ed2ffde4c87001111c12)と同内容を、
Omron環境センサ（**USB型**）で実施した記事です。

# 環境センサとは？

Omronの環境センサは、温度、湿度、照度、気圧、騒音など、
複数のセンサーをひとまとめにしたデバイスです。
![オムロン環境センサ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/35831ff1-4d87-660a-71f4-5172bc462c81.png)
（左：BAG型の2JCIE-BL01、　右：USB型の2JCIE-BU01）

今回は、右側のUSB型のデータをRaspberryPiから取得します。

# 必要なもの
**・RaspberryPi**（今回はPi3Model Bを使用）
**・Python実行環境**（今回はpyenvでPython3.7.6使用）
**・Googleアカウント**（スプレッドシートを使うのに必要）
**・Omron 環境センサ（USB型の2JCIE-BU01）**

# 手順
**①RaspberryPiとセンサのBluetooth接続確認**
**②環境センサの測定値をPythonで取得**
**③PythonからGASのAPIを叩いてスプレッドシートにデータ書き込み**
**④スクリプトの定期実行**

# 詳細
## ①RaspberrypiとセンサのBluetooth接続確認
### 環境センサの認識確認
**・環境センサのUSBポートへの接続**
環境センサをUSBポートに差し込み、ランプが一瞬点くことを確認してください

**・Bluetooth機器のスキャン**
RaspberryPiで下記コマンドを実行

```
sudo hcitool lescan
```

```
LE Scan ...
CC:DD:BB:AA:66:77 Rbt
```
というように、「Rbt」という名前がでてきたら、これが環境センサのMACアドレスです。
出てこなければUSBの接触やRaspberryPiのBluetooth有効を確認してください。

## ②環境センサの測定値をPythonで取得
### bluepyでの認識確認
bluepyは、PythonでBluetooth Low Energy(BLE)にアクセスするためのライブラリです（[クラス定義](http://ianharvey.github.io/bluepy-doc/index.html)）

電池のないUSB型では、BAG型のようなブロードキャストモードへの変更が不要なため、作業の手間は少なく済みます。

**・必要なパッケージのインストール**
下記をインストールします

```
sudo apt install libglib2.0-dev
```

**・bluepyのインストール**

下記コマンドでpipでインストールします

```
pip install bluepy
```

**・bluepyに権限を付与**
スキャンにはbluepyにSudo権限を与える必要があります。

bluepyのインストールされているフォルダに移動し、

```
cd ~.pyenv/versions/3.7.6/lib/python3.7/site-packages/bluepy
```
※上記は、pyenvでPython3.7.6をインストールした場合。
環境により場所は異なるので注意（[参考](https://qiita.com/t-fuku/items/83c721ed7107ffe5d8ff)）

下記コマンドでbluepy-helperにSudo権限を付与する

```
sudo setcap 'cap_net_raw,cap_net_admin+eip' bluepy-helper
```

### センサ値取得スクリプトの作成
センサ値取得のため、下記のスクリプトを作成します

```python:omron_env_usb_connect.py
from bluepy import btle
import struct

def get_env_usb_data(macaddr):
    peripheral = btle.Peripheral(macaddr, addrType=btle.ADDR_TYPE_RANDOM)
    characteristic = peripheral.readCharacteristic(0x0059)
    (seq, temp, humid, light, press, noise, eTVOC, eCO2) = struct.unpack('<Bhhhlhhh', characteristic)
    sensorValue = {
            'SensorType': 'Omron_USB_EP',
            'Temperature': temp / 100,
            'Humidity': humid / 100,
            'Light': light,
            'Pressure': press / 1000,
            'Noise': noise / 100,
            'eTVOC': eTVOC,
            'eCO2': eCO2
        }
    return sensorValue
```
ブロードキャストモードのBAG型ではアドバタイズデータからセンサデータを取得していましたが、
コネクトモードのUSB型ではPeripheralクラスによる通信でデータを取得します。

### メインスクリプトの作成
センサ値取得スクリプトを呼び出すため、メインスクリプトを作成します

```python:omron_env_toSpreadSheet.py
from bluepy import btle
import omron_env_usb_connect

######オムロン環境センサ（BAG型）の値取得######
PERIPHERAL_MAC_ADDRESS = '①で取得したMACアドレス'
sensorValue = omron_env_usb_connect.get_env_usb_data(PERIPHERAL_MAC_ADDRESS)

#試しに温度を表示
print(sensorValue['Temperature'])

```

コンソールから実行してみます

```
python omron_env_toSpreadSheet.py
26.48
```
これで、Pythonでセンサ測定値を取得することができました。

なお[ユーザーズマニュアル](https://omronfs.omron.com/ja_JP/ecb/products/pdf/CDSC-016A-web1.pdf)によると、取得した値の単位は下図のようになっています
![usb_env.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/5c099b79-fc24-63c2-44e0-c9a3df315127.png)


## ③PythonからGASのAPIを叩いてスプレッドシートにデータ書き込み
[BAG型の記事](https://qiita.com/c60evaporator/items/ed2ffde4c87001111c12#python%E3%81%8B%E3%82%89gas%E3%81%AEapi%E3%82%92%E5%8F%A9%E3%81%84%E3%81%A6%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AB%E3%83%87%E3%83%BC%E3%82%BF%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF)ご参照ください

## ④スクリプトの定期実行
[BAG型の記事](https://qiita.com/c60evaporator/items/ed2ffde4c87001111c12#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E5%AE%9A%E6%9C%9F%E5%AE%9F%E8%A1%8C)ご参照ください

## ※注意点：DockerコンテナからのBluetooth取得

[参考](https://github.com/jessfraz/dockerfiles/issues/309)

Dockerコンテナ内からBluetoothのデータを取得する場合、`docker run`時のオプションとして`--net=host`を付ける必要があります（Docker composeの場合`network_mode: "host"`と指定）。これにより、該当のDockerコンテナはDockerネットワークでなくホストのネットワークが使用されるため、Docker composeで他のコンテナと通信する際には様々な制約が発生する事にご注意ください