MotoJapan's Tech-Memo

技術めも

【Linebot #3】家の温度をLineで通知するアプリ (BME280使用)

家の温度をサーバーに通知して、自分のスマホに通知したい。
でも開発は最小にしたいので、Linebotとして開発した。
サーバサイドのみの開発で済むしね。
忘れそうなことや注意点を書き残し。
主に、サーバーサイドとクライアントサイドのpython実装とかとか。

できたもの

自動通知された時
日中部屋は地獄のように熱い orz (外の方が涼しい)
f:id:motojapan:20170722121708p:plain

システム図

  • 家で稼働しているraspberry piから温度センサ値を取得
  • herokuに定期通知
  • MessagingAPIを用いて、自作Lineアプリに温度を定期通知、もしくは、要求する。

f:id:motojapan:20170722120819p:plain

温度取得に使ったもの

1. 温度センサ
使用した温度センサはBME280。
温度だけでなく、気圧、湿度も取得可能。
これ↓↓↓
BME280使用 温湿度・気圧センサモジュールキット: センサ一般 秋月電子通商 電子部品 ネット通販

2. Raspberry Pi 3 Model B
https://www.amazon.co.jp/Raspberry-Pi-TSI-PI018-Clear-Pi3-Model/dp/B01D1FR29M

やったこと(忘れやすいことのメモ)

1. raspberry piにraspbianをインストール(割愛)
2. raspberry piにログイン

Raspbianの初期パスワード

username password
pi raspberry
4. 初期設定とか
$sudo apt-get update
$sudo apt-get upgrade
5. I2Cを有効化、ツールインストー
$sudo raspi-config

“5 Interfacing Options” -> “P5 I2C”でEnableを選択
カーネルモジュールがロード確認 (無事、i2c_devがある)

$lsmod

f:id:motojapan:20170722123534p:plain

I2C関連ツールをインストー

$sudo apt-get install i2c-tools
$sudo apt-get install python-smbus
6. BME280を繋いでI2C接続確認

実際の配線とかは※1を参考にしているので割愛

こんな感じ
f:id:motojapan:20170722124641p:plain

接続確認は以下

$ i2cdetect -y 1

f:id:motojapan:20170722123444p:plain

7. raspberry piから温度取得(割愛)

※1がわかりやすいのでそちらを参照しました。

8. 温度情報をHerokuに送信する

raspbianはpython2.7系なので、次のコードでクライアントサイドを実装
urllibを使います。
今回はPOSTになります。

#the case of python 2.7
import urllib 
def post_message(t, p, h):
    print('post')
    data = {}
    data["temp"] = t
    data["pres"] = p
    data["hum"]  = h
    server_addr = 'https://xxxxxxxxx.herokuapp.com/info'
    try:
        data = urllib.urlencode(data).encode("utf-8")
        res = urllib.urlopen(server_addr, data=data)
        res = res.read().decode("utf-8")
        print(res)
    except:
        print('error')

3系だったらこんな感じのはず

#the case of python 3.xx
import urllib.request, urllib.parse
def post_message(t, p, h):
    print('post')
    data = {}
    data["temp"] = t
    data["pres"] = p
    data["hum"]  = h
    server_addr = 'https://xxxxxxxxx.herokuapp.com/info'
    try:
        data = urllib.parse.urlencode(data).encode("utf-8")
        with urllib.request.urlopen(server_addr, data=data) as res:
           res = res.read().decode("utf-8")
           print(res)
    except:
        print('error')
9. 温度情報をHeroku側で受信する

サーバーサイド。こっちはflaskです。
linebot側はこの辺の知識を活用です。
【Linebot #2】herokuでブックマークアプリを作ってみた - MotoJapan's Tech-Memo
今回はPOSTを受ける。

#the case of python 3.xx
@app.route("/info", methods=['POST'])
def info():
    param_t = float(request.form['temp'])
    param_p = float(request.form['pres'])
    param_h = float(request.form['hum'])
    content = ' temp : {0:3.1f} deg \n hum  : {1:2.1f} % \n pres  : {2:4.1f} hPa '.format(param_t, param_h, param_p)
    user_id = 'yyyyyyyyyyyyy'
    line_bot_api.push_message(user_id, TextSendMessage(text=content))
    return 'POST OK!'

注意
GETも同様に書けばよいですが、param_t, param_p, param_hをグローバル変数にいれておいて、GETするのは危険です。
Herokuは定期的に寝てしまうので、寝ると消えるようです。
ちゃんとDBに登録したものを返すようにしましょう。

HTMLを返すとブラウザからはこんな感じで見えます。
f:id:motojapan:20170722131251p:plain

10. raspberry piスクリプトを起動し続ける

普段はteratermから接続していますが、セッションを切るとプロセスもきれる。
なので、次の2つ方法で、永続化をします。

1. rc.localに書き込む
これは起動時に実行されるスクリプトを指定できます。

$sudo emacs /etc/rc.local

重要なのは、「exit 0」の前に書くこと。

sudo python [target].py & #<-ここを追記
exit 0


2. 実行時にnohupを使う
これはセッションを切ってもプロセスを残す方法です。

$nohup sudo python [target].py &


以上、のんびりやっても半日くらいもあればできました!

参考資料

※1: BME280をRaspberryPiから動かす話(すごくわかりやすい)
Raspberry Pi + BME280モジュールで自動で温度・湿度・気圧を測定してグラフ化する - karaage. [からあげ]