植物の生育状況をお知らせ
私の家には観葉植物があるのですが、日光の当てすぎや水のあげ忘れ、あげすぎで枯らしてしまったことがあります。今回はそんな観葉植物の状態をLINEに通知して簡単に植物の状態をお知らせするプロダクトを作成しました。植物がすくすくと育つ喜びを感じてもらえるようになって貰えれば良いと思います。
どんなプロダクト??
Iot機器を用いて温度や照度を計測して、LINEへ送信をします。その際、植物に良くない環境の場合には警告も行います。
また、植物の画像も撮影して送信をするので今、観葉植物がどんな状態なのかも簡単に見ることができます。
環境
1.enebularをherokuへデプロイする
enebularはセッション時間の制限が60分と決まっているため、このままだとセッションが動いている間しか植物を監視することができません!
そのため、まずは↓の記事を参考にしてherokuへデプロイします。
記事を参考にデプロイをするとこのようにデプロイ履歴が確認できるようになります。
これで、永続的に動きますねと思いきやそうはいきません。
2.herokuが30分でスリープしてしまう問題
herokuへデプロイできたのはよかったですが、herokuは30分でスリープをしてしまいます。 ですので、Node-REDのフローのなかにWebトラフィックを30分以内の間隔で発生させて、スリープをさせないようにする必要があります。
↓参考記事
↓のようなフローを追加することでherokuのスリープを防ぐことができます!
3.土壌センサーで水分量を計測したい(obniz)
↓にあるような土壌センサーを貸してもらってobnizと連結させて水分量を計測しようと思ったのですが、obnizには対応していないようです。。。ラズパイでやろうと思いましたが色々部品がなかったためまたの機会に。
4.定期的に画像を送信する(ラズパイ)
次にラズベリーパイを使って定期的にWebカメラで植物を撮影し、LINEに送信しようと思います。
①cronで1時間ごとにmain.pyを起動させるようにする
②main関数からcamera.pyを呼び出し、Webカメラで撮影し画像を保存
③LINEに送信
といった流れになっています。
main.py
import requests
import camera
def main():
pic_path = camera.camera()
message="現在のコーヒーノキ"
url = "https://notify-api.line.me/api/notify"
token = "アクセストークン"
headers = {"Authorization" : "Bearer "+ token}
payload = {"message" : message}
files = {'imageFile': open(pic_path, 'rb')}
requests.post(url ,headers = headers ,data=payload, files=files)
if __name__ == '__main__':
main()
camera.py
import cv2
import datetime
def camera():
dt_now = datetime.datetime.now()
path = '/home/pi/python/CF/pic/'
file_name = dt_now.strftime('%Y年%m月%d日%H時%M分%S秒')
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cv2.imwrite(path + file_name + '.jpg', frame)
print("save")
cap.release()
return (path + file_name + '.jpg')
おわりに
今回は土壌センサーがうまく使えず、水分量を計測できなかったので今後は使用する前にきちんと調べて材料を揃えてから作ろうと思います。
ソースコード
[{"id":"bfe627fd.746d28","type":"tab","label":"obniz","disabled":false,"info":""},{"id":"5426c609.87e638","type":"debug","z":"bfe627fd.746d28","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":790,"y":200,"wires":[]},{"id":"6d546c8d.fbd874","type":"inject","z":"bfe627fd.746d28","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":80,"wires":[["63961c68.208214"]]},{"id":"63961c68.208214","type":"obniz-function","z":"bfe627fd.746d28","obniz":"a00257d3.c5aa28","name":"","code":"msg.payload = \"finish\";\nawait obniz.wait(1000); \nobniz.close();\n\nreturn msg;","x":340,"y":80,"wires":[["511e8ac0.68dbc4"]]},{"id":"511e8ac0.68dbc4","type":"debug","z":"bfe627fd.746d28","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":530,"y":80,"wires":[]},{"id":"d1635e53.90f1c","type":"inject","z":"bfe627fd.746d28","name":"現在時刻取得","topic":"","payload":"","payloadType":"str","repeat":"900","crontab":"","once":true,"onceDelay":"0.1","x":160,"y":200,"wires":[["6943507d.583c6"]]},{"id":"b296a415.bb55b8","type":"obniz-function","z":"bfe627fd.746d28","obniz":"a73f17fa.f80b98","name":"","code":"let temperature = await obnizParts.LM60.getWait();\nlet voltage = await obniz.ad1.getWait();\nlet message = \"\";\n\nobniz.display.clear(); // 画面を消去\nobniz.display.print(temperature+'c\\n'+voltage+'v\\n');\nobniz.display.print(msg.now_times);\nmsg.temp = temperature;\nmsg.volt = voltage;\n\nif (voltage > 1.5) {\n obniz.display.print('\\n\\nBAD');\n message = \"\\n\\n日差しが強すぎるよ~\\n日陰に移動して下さい!\";\n}\nelse if(voltage < 0.2){\n message = \"\\n\\nもう夜かな~\\nおやすみ\"; \n}\nelse {\n obniz.display.print('\\n\\nGOOD');\n message = \"\\n\\n快適~\"; \n}\n\nmsg.payload = '\\n温度:'+temperature+'℃\\n照度'+voltage+'v'+message;\n\nreturn msg;","x":620,"y":200,"wires":[["5426c609.87e638","9d6974ed.de7bd8"]]},{"id":"9d6974ed.de7bd8","type":"Notify","z":"bfe627fd.746d28","name":"","x":790,"y":280,"wires":[]},{"id":"2c8d48a9.c3adf8","type":"debug","z":"bfe627fd.746d28","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":590,"y":280,"wires":[]},{"id":"6943507d.583c6","type":"moment","z":"bfe627fd.746d28","name":"","topic":"","input":"now_time","inputType":"msg","inTz":"Asia/Tokyo","adjAmount":"0","adjType":"hours","adjDir":"add","format":"HHmm","locale":"ja-JP","output":"now_times","outputType":"msg","outTz":"Asia/Tokyo","x":380,"y":200,"wires":[["2c8d48a9.c3adf8","b296a415.bb55b8"]]},{"id":"a00257d3.c5aa28","type":"obniz","z":"","obnizId":"","deviceType":"obnizboard","name":"","accessToken":"","code":"obniz.display.clear(); // 画面を消去\r\n\r\n// 温度センサー\r\nobnizParts.LM60 = obniz.wired(\"LM60\",{ gnd: 4, output: 5, vcc: 6 }); \r\n//照度センサー\r\nobniz.io0.output(true); //io3を5vに\r\nobniz.io2.output(false); //io5をGNDに\r\n//LED\r\nobnizParts.led = obniz.wired('LED', { anode:8, cathode:9 });"},{"id":"a73f17fa.f80b98","type":"obniz","z":"","obnizId":"","deviceType":"obnizboard1y","name":"","accessToken":"","code":"obniz.display.clear(); // 画面を消去\r\n\r\n// 温度センサー\r\nobnizParts.LM60 = obniz.wired(\"LM60\",{ gnd: 4, output: 5, vcc: 6 }); \r\n//照度センサー\r\nobniz.io0.output(true); //io3を5vに\r\nobniz.io2.output(false); //io5をGNDに\r\n//LED\r\n// obnizParts.led = obniz.wired('LED', { anode:8, cathode:9 });\r\n"}]