CO2モニターでオフィスの空気環境をモニタリング

[Nextremer Advent Calendar 2017](https://qiita.com/advent-calendar/2017/nextremer) 5日目の記事です

いろいろな人が集まるオフィスの空間だと、暑い・寒いとかの感じ方に個人差があるので最適な環境にすることが難しいですよね
メンバーとそんな雑談をしている中で、結構空気がよどんで感じるときがある気がするし**CO2の濃度とかってどうなんだろうね？**という話になりました

そしたら一緒に仕事をしている外部のメンバーがCO2モニターを貸してくれることになったので、早速オフィスに設置して空気環境をモニタリングできるようにしました

# 適切なCO2濃度を維持しよう！

実際にセンサーを置いて計測してみると、特に換気をしないと気づかないうちに2000ppmくらいまでCO2濃度が上がってしまうことがわかりました
これは実際に計測したグラフですがこんな感じで時間の経過に伴って二酸化炭素濃度が上がっていきます
<img width="901" alt="7.png" src="https://qiita-image-store.s3.amazonaws.com/0/43699/eb89f06c-3a6d-1cab-a08d-8409ca300824.png">


今のところは、なるべく換気をして800ppm前後に保つぞー！というのを目指しています

こちらはCO2濃度が与える影響らしいです、参考までに

|CO2レベル|状況|
| --- | --- |
| ～ 300PPM |  通常の環境では起こらない低いレベル。施設栽培では 二酸化炭素飢餓 が懸念されます。|
| ～ 450PPM | 外気或いは窓を開放するなど健康的な換気管理のされたレベル。 |
| ～ 700PPM |長時間滞在しても健康に問題の無い室内レベル  |
| ～1000PPM | 健康に被害は無いが不快感や臭いを感ずる人が出るレベル |
| ～2000PPM |眠くなる人が多くなるなど体調の変化と空調に苦情が出てくるレベル  |
| ～3000PPM |肩こりや頭痛を感じる人が出るなど健康被害一歩前の限界レベル  |
| 3000PPM～ |頭痛、めまいなどの症状が出て、長時間では健康に危害を及ぼすレベル  |

※情報ソースはこちら
http://marvel-online.jp/co2-monitor-and-eco/health-standards/

# CO2濃度が上がるとSlackでアラート！
このセンサーを利用して、CO2の濃度が1000ppmを超えるとslackの東京オフィスチャンネルにアラートが飛んで換気を促してくれる仕組みを作りました
![anil_alerting.png](https://qiita-image-store.s3.amazonaws.com/0/43699/63d1d86b-9e49-99b6-0b02-b8134f7a471d.png)

換気をしてCO2の濃度が1000ppmを下回るとその旨の通知も飛びます
![anil_ok.png](https://qiita-image-store.s3.amazonaws.com/0/43699/dfb85bd9-aee4-8fd1-45c9-7f106736e9f5.png)


# 仕組み
Prometheus, Grafana を利用してセンサーの値を定期的にポーリングして監視します
センサーの値が設定したしきい値を超えるとslackに通知する仕組みです
それぞれのプログラムはdockerコンテナにして、docker-composeを使って動かしています

![5.png](https://qiita-image-store.s3.amazonaws.com/0/43699/3b869304-fde1-9e2a-bb85-c22c5bab0be8.png)


## センサー機器
センサーにはお借りした[Comet社のWeb sensor T6540](http://www.cometsystem.com/products/reg-T6540)というのを使っています

![IMG_0910.JPG](https://qiita-image-store.s3.amazonaws.com/0/43699/a0bbe397-81fc-78ea-e436-60039be820ef.jpeg)

センサー自身にWebサーバーが内蔵されていて、センサーの設定、測定値のレポート画面、測定値のAPI公開ができるようになっています

![1.png](https://qiita-image-store.s3.amazonaws.com/0/43699/d8a42c3c-ef3d-2cff-be76-db94aed85ed4.png)
![2.png](https://qiita-image-store.s3.amazonaws.com/0/43699/91c15b61-a8de-6c54-c92b-758d8d0b3d59.png)

## 測定値をAPIで取得

センサーの値を取得できるAPIを使いたきですが、Web sensorのマニュアルを探すのが面倒だったのでどうにかして見つけられるだろうと思い、レポート画面からアクセスしているURLをチェックしたら `history.xml?ch=hoge` にアクセスしてセンサーの値をとってグラフを描画していることがわかりました

![3.png](https://qiita-image-store.s3.amazonaws.com/0/43699/2c6774cc-4fa7-bbea-9e9e-e442ece8cb63.png)

このURLにアクセスしたらセンサー値をXMLで取得できたのでそこのデータを監視対象にしています
パラメータの `ch` は各センサーのチャンネルを表しているようでそれぞれ以下に対応してました

- 温度
  - http://ホスト名/history.xml?ch=1
- 湿度
  - http://ホスト名/history.xml?ch=2
- 露点温度
  - http://ホスト名/history.xml?ch=3
- CO2レベル
  - http://ホスト名/history.xml?ch=4

## Promethous でセンサー値を取得
APIで値が取れればPromethousでのリソース監視と同じ仕組みでイケそうだったのでそれを使っています
※ちなみに、Promethous & Grafana でのリソース監視は弊社の機械学習環境 [Shiva](https://qiita.com/Chan_moro/items/f1c4e948362014f8cf65) でも利用しています

センサーのAPIの値をPromethousに公開するexporterは実装しました
exporterの実装自体はめっちゃ簡単なのでこんな感じです

```python
class JsonCollector(object):

    def __init__(self):
        self._values = [(1, 'temperature'), (2, 'humidity'), (3, 'dew'), (4, 'co2')]
        self._base_url = 'http://hoge.hoge/history.xml?ch={}'

    def collect(self):
        response = {}
        metric = Metric('office', 'co2 monitor', 'gauge')

        for val in self._values:
            data = self.fetch_sensor_data(self._base_url, val[0])
            value = float(data['root']['chnl']['aval'])
            metric.add_sample(val[1], value=value, labels={'place': 'tokyo_7f'})

        yield metric

    def fetch_sensor_data(self, path, ch):
        url = path.format(ch)
        res = requests.get(url)
        response = res.content.decode(res.encoding)
        data = xmltodict.parse(response)
        return data

```

## Grafana で可視化
Promethousで取得したセンサーの値はこんな感じで表示することができます
![4.png](https://qiita-image-store.s3.amazonaws.com/0/43699/814908aa-f26f-c4fa-3e49-78c807e9c219.png)

readonlyのアカウントで社内から誰でも見れるようにしています


## Grafana でアラート
Promethousでもアラートの機能は提供されているんですが、Grafanaにもアラート機能がついています
slack通知する機能もデフォルトでついているので非常にお手軽に監視 & slackアラートの仕組みがつくれます
http://docs.grafana.org/alerting/notifications/

アラートのしきい値の設定はこんな感じにします
ここでは`10秒ごとにチェック`して`今から10秒間の最高が1000を超え`ていたらアラートを飛ばすようにしています
![6.png](https://qiita-image-store.s3.amazonaws.com/0/43699/795b1292-5a59-bdca-4b96-4829dd36ea38.png)


# オフィスの空気環境を改善しよう！
ぶっちゃけCO2の濃度が高くなっても体感では全然気づきません
なんとなく午前中の方が空気がキリっとして集中できる感じがしたのは実は二酸化炭素のせいだったのかも
(プラシーボ効果疑惑！)

こういう見えなかったものが捉えられるようになるところがIoTの面白いところですね

皆さんも空気環境を改善して快適なオフィスをつくりましょう！