LoginSignup
0
0

More than 3 years have passed since last update.

RaspberryPi Zeroを使った室温監視(& Slack通知)

Posted at

室温を監視し、設定温度を超えた際にslackで通知するものを作ったのでメモ。

使ったもの。

室温監視

raspbianのインストール

NOOBS LiteでRaspbian Liteをインストール。
https://www.raspberrypi.org/downloads/noobs/
特段気をつけることはなく、インストーラに従ってインストールする。
この辺り参考。

Thermometerの設定

Amazonから購入したが、ファームウェアのバージョンが2種類あり、どちらがやってくるかは運次第の模様。
今回手元に届いたのは、413d:2107 というバージョンのものだったので、ここから下は同バージョンで動作確認できた手順です。
(他のバージョンではgitからライブラリを持ってくるだけで動くとか動かないとか...)

HIDAPIのインストール

USBと通信するため、HIDAPIライブラリをインストールする。
https://github.com/signal11/hidapi

READMEにある通り、下記ライブラリが必要になるのでインストールする。

# まずは依存ライブラリのインストール
$ sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
$ sudo apt-get install autotools-dev autoconf automake libtool

# HIDAPIをインストール
$ git https://github.com/signal11/hidapi.git
$ cd linux/
$ make -f Makefile-manual

TEMPeredのインストール

いよいよ、thermometerから温度を取得するためのTEMPeredライブラリをインストールする。

$ git clone https://github.com/hughesr/TEMPered
$ cd TEMPered
# 上手くいかなかったのでissues見てたら最新リビジョンはMacに対応っぽかったので、
# Linuxに対応しているリビジョンまで戻してmake
# https://github.com/edorfaus/TEMPered/issues/51
$ git checkout hack-413d-2107
$ git reset --hard 75aa1e2
$ cmake .
$ make

これで温度が取得できるようになった。

$ sudo utils/tempered
/dev/hidraw1 0: temperature 25.37 °C
/dev/hidraw1 1: Failed to get the temperature: Not enough data was read from the sensor.
/dev/hidraw1 1: no sensor data available

室温監視スクリプト作成

温度が取れるようになったので、下記要件のスクリプトを作成。

  • 5分おきに温度を取得し、DBに格納する

※下記ソースは2019/8/18時点のもので、この後の機能追加及びリファクタリングで変更される可能性あり。

monitor.sh
#!/bin/bash

# TEMPeredで温度を取得し、awkで温度のみを切り出す
TEMPER=`sudo /home/pi/TEMPered/utils/tempered | head -n 1 | awk '{ print $4 }'`

# 温度を引数にDB登録、slack通知のpythonを起動
cd /home/pi/temperature_monitor/
python3 handle_temperature.py $TEMPER

monitor.shをcronに設定し、5分おきに起動するようにする。

Slack連携

下記の条件でslackに通知を送る。

  • 5回連続気温の取得に失敗したらslackで通知する
  • 気温が30度を上回ったらslackで通知する

SlackのAPIはいくつか種類があるみたいで、今回はメッセージを送信したいだけなので、Incoming Webhooksを使用。

下記URLからwebhookのエンドポイントを作成。
https://api.slack.com/apps?new_app=1

作成すると、 https://hooks.slack.com/services/********/*******/********** の様なエンドポイントが与えられる。
ここに対して正しいフォーマットでPOSTしてやればslackに投稿ができる。

スクリプトはpython3で作成。

handle_temperature.py
import logging
import configparser
import sys
import datetime
import sqlite3
from contextlib import closing
from messaging_slack import notice 

config = configparser.ConfigParser()
config.read('config')

SUCCESS = config['STATUS']['SUCCESS']
ERROR = config['STATUS']['ERROR']
COUNT_DEFAULT = config['ERROR_COUNT']['DEFAULT']
COUNT_LIMIT = config['ERROR_COUNT']['LIMIT']
DB = config['DB']['file']
log_file = config['LOG']['file']

THRESHOLD = 33.0

NOTICE_MESSAGE = "<!channel> 室温が {} 度になりました。"
ERROR_MESSAGE = "<!channel> デバイスに接続できません。"

logger = logging.getLogger(__name__)
fmt = "%(asctime)s %(levelname)s :%(message)s"
logging.basicConfig(level=logging.DEBUG, format=fmt, filename=log_file)


def error_check(flg):
    if flg == SUCCESS:
        update_error_count()
    else:
        error_count = get_error_count()
        error_count += 1

        if error_count == COUNT_LIMIT:
            notice(ERROR_MESSAGE.format(t))
            logger.error(ERROR_MESSAGE.format(datetime.datetime.now()))

        update_error_count(error_count)

def get_error_count():
    with closing(sqlite3.connect(DB)) as conn:
        cursor = conn.cursor()
        cursor.execute("select count from error_counts")
        res =  cursor.fetchone()
        conn.close()
        return res[0]

def update_error_count(error_count=COUNT_DEFAULT):
    with closing(sqlite3.connect(DB)) as conn:
        cursor = conn.cursor()
        sql = "update error_counts set count = ?, updated_at = ?"
        cursor.execute(sql, (error_count, datetime.datetime.now()))
        conn.commit()
        conn.close()

def str_add(s, num):
    i = int(s)
    i += num
    return str(i)

if __name__ == "__main__":
    args = sys.argv

    try:
        t = args[1]
        t = float(t)
        error_check(ERROR)
    except:
        error_check(ERROR)
        logger.error(ERROR_MESSAGE.format(datetime.datetime.now()))
        exit()

    if t > THRESHOLD:
        message = NOTICE_MESSAGE
        notice(message.format(t))

    with closing(sqlite3.connect(DB)) as conn:
        cursor = conn.cursor()
        sql = "insert into temperature (temperature, created_at) values (?, ?)"
        now = datetime.datetime.now()
        cursor.execute(sql, (t, now.strftime("%Y-%m-%d %H:%M")))
        conn.commit()
        conn.close()
messaging_slack.py
import json
import os
import urllib.request


def notice(message):
    data = {
            'text': message,
    }
    headers = {
            'Content-type': 'application/json'
    }

    # slackのIncoming WebhooksのURLは環境変数に設定
    req = urllib.request.Request(os.environ['SLACK_URL'], json.dumps(data).encode(), headers)
    urllib.request.urlopen(req)

以上でRaspberryPi Zeroを使った室温監視が構築できた。

次は、Slackのbotを使って室温の問い合わせや室温推移のグラフを描きたい。

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0