【ラズパイ】温湿度センサーから得たデータをCSVに記録してグラフ化する [2]

2024/02/14

DHT11 Discord Matplotlib ラズパイ

  • B!
サムネ
サムネ
[ DHT11シリーズ ]

前回は温湿度センサ(DHT11)をラズパイに接続して値をCSVに記録することができました。

DHT11から温湿度データを取得して、CSVファイルに記録するプログラムの作成

今回は、

  • 1.取得されたデータに応じてDiscord Webhookで通知を飛ばす
  • 2.CSVデータからグラフを作成してDiscord Webhookで送る

という内容をやっていきます。

具体的な内容

1.取得されたデータに応じてDiscord Webhookで通知を飛ばす

例えば室内の気温が30℃を超えると警告メッセージをスマホに通知したり、エアコンを操作したり、などといった内容です。

家電の操作はSwitchBot API等を活用すれば簡単にできるので今回は通知のみにしておきます。


2.CSVデータからグラフを作成してDiscord Webhookで送る

温湿度センサで取得したデータは、CSVファイルのままだと内容を把握しにくいため、グラフを作成して分かりやすくします。

グラフの他にもCSVデータを読み取って様々な計算や処理を行うこともできます。

作成したグラフはラズパイに保存しますが、それだけでは不便なのでDiscord Webhookで様々なデバイスから閲覧できるようにします。

今回使用する物

  • RaspberryPi 4
  • DHT11
  • ブレッドボード
  • ジャンプワイヤ
  • Discord Webhook URL
  • 前回使用したプログラム

前回使用したプログラムを編集する形で進めます。

Discord Webhookの使い方は省略しています。

1.取得されたデータに応じてWebhookで通知する

このプログラムは取得した値が設定値より上か下かを判別すれば良いのでif文を追加していきます。

今回は温度についてのプログラムを書いていますが湿度に関しても同じように実装可能です。

DiscordWebhookに通知を送る部分は次のようになっています。

これを上の方に書いておきます。

example.py
  1. import requests, json
  2.  
  3. def attention_temp(dt, temp):
  4. webhook_url = 'webhook URL'
  5. main_content = {'content': '[Room temperature too high]\n' + str(dt) + '\n' + 'TEMP : ' + str(temp) + ' C',
  6. 'username': 'Attention'}
  7. headers = {'Content-Type': 'application/json'}
  8. response = requests.post(webhook_url, json.dumps(main_content), headers=headers)

次は指定した温度以上かどうか判断する部分です。

CSVに記録するデータを変数に代入している部分の下に次のコードを追加します。

example.py
  1. temp = result.temperature
  2. humi = result.humidity
  3. data = [[dt, temp, humi]]
  4. #ここから
  5. if temp > 20: #20℃以上になったら
  6. print('too high')
  7. attention_temp(dt, temp)
  8. else:
  9. pass
  10. #ここまで
  11. with open('data.csv', 'a') as f:
  12. writer = csv.writer(f)
  13. writer.writerows(data)

ここまでのコードをまとめておきます。

設定温度は自由に変更してみてください

example.py
  1. import RPi.GPIO as GPIO
  2. import dht11
  3. import time
  4. import datetime
  5. import csv
  6. from time import sleep
  7. import requests, json
  8.  
  9. GPIO.setwarnings(False)
  10. GPIO.setmode(GPIO.BCM)
  11. instance = dht11.DHT11(pin=14)
  12.  
  13. def attention_temp(dt, temp):
  14. webhook_url = 'webhook URL'
  15. main_content = {'content': '[Room temperature too high]\n' + str(dt) + '\n' + 'TEMP : ' + str(temp) + ' C',
  16. 'username': 'Attention'}
  17. headers = {'Content-Type': 'application/json'}
  18. response = requests.post(webhook_url, json.dumps(main_content), headers=headers)
  19.  
  20. try:
  21. while True:
  22. dt = datetime.datetime.now().replace(microsecond=0)
  23. unix = int(time.time())
  24. unix_15 = unix + 900
  25. print('Start: ' + str(dt))
  26. while True:
  27. result = instance.read()
  28. if result.is_valid():
  29. u_time = int(time.time())
  30. s_time = unix_15 - u_time
  31. print('\n')
  32. print("Last valid input: " + str(dt))
  33. print("Temperature: %-3.1f C" % result.temperature)
  34. print("Humidity: %-3.1f %%" % result.humidity)
  35. print('\n')
  36. temp = result.temperature
  37. humi = result.humidity
  38. data = [[dt, temp, humi]]
  39. if temp > 20:
  40. print('too high')
  41. attention_temp(dt, temp)
  42. else:
  43. pass
  44. with open('data.csv', 'a') as f:
  45. writer = csv.writer(f)
  46. writer.writerows(data)
  47. print('\nsleep')
  48. sleep(s_time)
  49. break
  50.  
  51. else:
  52. e_time = datetime.datetime.now().replace(microsecond=0)
  53. print("Error: " + str(e_time))
  54. sleep(1)
  55.  
  56. except KeyboardInterrupt:
  57. print("Cleanup")
  58. GPIO.cleanup()

実行結果(上限を20℃に設定した時)

これで室温をモニターできるようになりましたね。

webhookを送る部分の前後に「エアコンをONにする」「扇風機をONにする」などの処理を記述すれば室温をコントロールすることが可能になります。

webhook

2.グラフを作成してWebhookで送る

まずは、前回記録を取ったCSVファイルのグラフ化をやっていきます。

温度と湿度を同じグラフに表示させています。

csv_plot.py
  1. import pandas as pd
  2. import matplotlib.pyplot as plt
  3. import matplotlib.dates as mdates
  4. import datetime
  5.  
  6. path = 'data.csv'
  7. df = pd.read_csv(path)
  8.  
  9. fig = plt.figure()
  10. ax1 = fig.subplots()
  11. ax2 = ax1.twinx()
  12.  
  13. x_time = pd.to_datetime(df['DateTime'])
  14. y_temp = df['Temperature']
  15. y_humi = df['Humidity']
  16.  
  17. img_name = x_time[0].strftime('%Y_%m_%d_%H_%M_%S')
  18.  
  19. c_temp, c_humi = 'red', 'bule'
  20. l_temp, l_humi = 'Temperature[C]', 'Humidity[%]'
  21.  
  22. ax1.set_ylabel(l_temp)
  23. ax1.plot(x_time, y_temp, color='red', label='Temperature', marker='o', linestyle='dotted')
  24. ax1.legend(loc='upper right', bbox_to_anchor=(.5, 1.1))
  25.  
  26. ax2.set_ylabel(l_humi)
  27. ax2.plot(x_time, y_humi, color='blue', label='Humidity', marker='o', linestyle='dotted')
  28. ax2.legend(loc='upper left', bbox_to_anchor=(.5, 1.1))
  29.  
  30. labels = ax1.get_xticklabels()
  31.  
  32. #見やすい方を選択
  33. locator = mdates.MinuteLocator(15)
  34. #locator = mdates.AutoDateLocator()
  35.  
  36. ax1.xaxis.set_major_locator(locator)
  37. ax2.xaxis.set_major_locator(locator)
  38. plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y/%m/%d %H:%M:%S'))
  39.  
  40. plt.setp(labels, rotation=45, fontsize=6)
  41.  
  42. #グラフを画像として保存(dpi=解像度)
  43. plt.savefig('TempHumi_FROM[' + img_name + '].png', bbox_inches='tight', dpi=300)

実行結果(グラフの作成)

エアコンをつけて温度が上昇すると湿度が低下しています。

エアコンを切った後は緩やかに温度が低下、湿度が上昇していきました。

このように、グラフを作成することでデータの特徴を把握しやすくなります。

温度変化の様子

webhookで画像を送信

では、作成したグラフの画像をwebhookで送信していきます。

次のコードを先ほどのプログラムの最後に追記します。

csv_plot.py
  1. import json
  2. import requests
  3.  
  4. WEBHOOK_URL = "discord webhook URL"
  5.  
  6. with open('TempHumi_FROM[' + img_name + '].png', 'rb') as f:
  7. file_bin = f.read()
  8. dht_img = {
  9. "favicon" : ("TempHumi_FROM[' + img_name + '].png", file_bin),
  10. }
  11. res = requests.post(WEBHOOK_URL, files=dht_img)
  12. #print(res.status_code)
  13. #print(json.dumps(json.loads(res.content), indent=4, ensure_ascii=False))

実行結果(グラフの送信)

2日分のグラフを送信してみました。

グラフ

まとめ

今回は、ラズパイとDHT11によって得られたデータの視認性を向上させるためにグラフ化を行いました。

さらにDiscordWebhookを用いることでデータの共有も可能になりました。

次回は、

  • DiscordBotにグラフを作ってもらう

という内容をやっていきたいと思います。

Writer

アイコン
Python×Raspi IoTシステム・Bot・ラズパイの記録
  • プログラミング
  • IoT
  • Python
\FOLLOW ME/ 𝕏

Ranking

blogmura_pvcount

Community

Search