この記事はRaspberry Pi Advent Calendar 2017 20日目の記事です。
はじめに
この記事では僕が去年の夏休みぐらいから始めた、お家の温度監視botをちゃんと作り直したことについて、まとめ的なことを書こうと思います。
目標としては定期的に部屋の温度や湿度をつぶやいたり、集計してグラフをつぶやいたりできたらいいなと思っています。
最初はESP8266だけでStewGate Uというサービスを使ってbotを作っていました。
しかしESP8266だけじゃグラフ出せないし、データを常に保存するならSDカード必要だしな…ラズパイ使うか!という感じでラズパイをサーバーにbotを作りました。
用意するもの
- どこのご家庭にも転がっているラズパイ
- Python、PHP、Apach導入済みで、IPアドレスが固定されていたほうがいいかも
- 安価なWiFIモジュールでArduinoとして使えるESP8266
- 秋月電子で販売している**温湿度センサーモジュールSHT31**
- 以前はHDC1000を使っていましたが経年劣化(?)で湿度が高めに表示されていたので変更
全体の構成
ESP8266は温湿度センサーから値を取得してラズパイへ送信
ラズパイはESP8266から受け取った値を成型してcsvファイルへ保存し、定期的にTwitterへつぶやく
という役割になっています。
ESP8266とラズパイの通信
ESP8266はWiFiに接続することができ、HTTP通信のライブラリもあります。
そこでラズパイにPHPで入力フォームを作り、ESP8266でGETリクエストを送信することで値を受け渡しています。
こんな感じのよく見る入力フォームをラズパイ上で立ち上げます。
そして作った入力フォームに合わせてESP8266からGETリクエストを送ってやります。
送られてきたデータは20121225.csvというふうに日付ごとのファイルに保存しています。
SHT31の温度取得にはAdafruitのライブラリを使用しました。
ESP8266でのHTTP GETの使い方は以下を参考にしました。
ESP8266でHTTP GETするならWiFiClientじゃなくてHTTPClientのほうが良い
String url = "http://myipadress/php/gettest.php";
void loop() {
//SHT31
float temp = sht31.readTemperature();
float hum = sht31.readHumidity();
//クエリストリングの追加
url += "&temp=";
url += String(temp);
url += "&hum=";
url += String(hum);
char buf[100];
int len = url.length();
url.toCharArray(buf,len);
getESP(buf);
}
String getESP(char host[]) {
HTTPClient http;
http.begin(host);
int httpCode = http.GET();
String result = "";
if (httpCode < 0) {
result = http.errorToString(httpCode);
} else if (http.getSize() < 0) {
result = "size is invalid";
} else {
result = http.getString();
}
http.end();
return result;
}
全部書くと長くなるので重要なところだけ
GETリクエストはHTTPClientがやってくれるので、我々はセンサの値をクエリストリングにしてしまえば簡単にGETリクエストで値を送信することができます。
データを処理してつぶやく
ラズパイは受け取った値をcsvファイルに一度保存し、保存されたデータをもとにPythonでTwitterにつぶやいています。
なぜそのようになっているかというと、ESP8266はタイマーで5分おきにデータを送信してくるのに対し、Twitterにつぶやくのは20分毎にしたかったからです。また、グラフを作成するのにPythonを使いたかったというのも理由の一つです。
TwitterAPIを使うためにtwitterモジュールを、csvファイルの読み込みにはpandasを使いました。
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
from datetime import datetime
from twitter import *
CONSUMER_KEY = 'YOUR_CONSUMER_KEY'
CONSUMER_SECRET_KEY = 'YOUR_CONSUMER_SECRET_KEY'
ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN'
ACCESS_TOKEN_SECRET = 'YOUR_ACCESS_TOKEN_SECRET'
PATH = 'hogehoge'
t = Twitter(auth = OAuth(ACCESS_TOKEN, ACCESS_TOKEN_SECRET, CONSUMER_KEY,CONSUMER_SECRET_KEY))
now = datetime.now()
filename = '{0}{1}{2}'.format(now.year, now.month, now.day)
data = pd.read_csv(PATH + filename + '.csv')
sum = len(data) # 行数を読む
latest_temp = data.loc[sum-1, 'Temp']
latest_hum = data.loc[sum-1, 'Hum']
mes = 'Temperature : {0}℃\nHumidity : {1}%'.format(latest_temp, latest_hum)
t.statuses.update(status = mes)
csvファイルが日付ごとに保存されているためdatetimeを使ってファイル名を生成し、pandasで読み込んでいます。csvファイルの一番下の行が最新の値になるのでlocを使って読み込んでいます。
完成!
Pythonでデータを読み込みTwitterへつぶやく部分が書けたらcronで決まった時間に自動的にPythonスクリプトを実行するように設定すれば、botの完成です。
Temperature : 15.35℃
— Miθra (@mithraism_bot) 2017年12月23日
Humidity : 52.0%
終わりに
PHPとかPythonとかあんまり触ったことなくてやってみたいけど、ただ勉強するのもモチベーション上がらないな~ということでbotを作ってみましたが思ったより大変でした。
始めたの去年の夏休みなのに投稿が今年の冬でしかも、期限に間に合わせられなくて申し訳ない。
まだ必要最低限の部分しかできてなくて、ESP8266止まったらどうするの?とか、csvじゃなくてデータベース使えばいいじゃん、とかグラフはまだ??とかありますが今後の課題にしていきたいと思います。