任意の場所に自宅の温度、湿度をPOSTしたい

前回はこんな記事書きました

hatappi.hateblo.jp

ただこれの欠点としてはUDPなので届いてるかも分からないですし、学習リモコンの電源が抜けてるとかで送信出来ないかもしれない
といった問題が考えられます

根本的な解決にはなりませんが、温度をとれるようにすることでエアコンが効いて温度がさがっているか把握できるのではないかと思ってやることにしました

どう実現するのか

おそらくみなさん家にRaspberry Piが転がってると思うのですが、今回はそれを使用しました
僕の場合はRaspberry Pi A+が転がってました

温度の取得はRHT03(or DHT22)を使用しました
このRHT03は温度だけでなく湿度とかもとれます
使用範囲としては湿度が0-100%RH、温度が-40~80℃と家庭で使用するには申し分なさそうです

Raspberry Piの設定

Raspberry Piのセットアップなどに関してはネットで検索すると出てくるので省略します

今回使用したRaspberry Pi A+にはwifibluetoothなどは内蔵していないので、USBタイプのLANアダプタを使用してネット環境に接続しました

RHT03をつないだ後はこんな感じです

f:id:hatappi1225:20170719085248j:plain

任意のサーバーにPOSTリクエストをする

今回はPython2.7.10を使用しました
まず温度と湿度に関してですが、すでに取得できるようなスクリプトがあるので使用させていただきます

github.com

セットアップなどはREADME.mdに書いても書いてありますが、下記で行えます

$ sudo apt-get update
$ sudo apt-get install build-essential python-dev
$ sudo python setup.py install

これをするとPythonスクリプトで下記のようにすることで温度と湿度がとれます

import Adafruit_DHT
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)
print "temperature is %f" % temperature
print "humidity is %f" % humidity

簡単ですね
Adafruit_DHT.read_retryに引数を渡すのですが、第一引数で使用しているセンサーを指定します
他にはAdafruit_DHT.DHT11Adafruit_DHT.AM2302があります
第2引数でGPIOの番号をわたします 番号はこちらを参考にしました

後はこれを任意の場所にPOSTできるようにするだけです
今回のPOST先は自宅サービスなのですが、自宅サービスは深夜の時間帯は費用削減のために落としているのでリクエストすることが出来ません
そこで今回はリクエストに成功しなかった場合は送るはずだった温度と湿度をファイルに書き出して、次に実行される時に一緒にリクエストをするようにしました
そのスクリプトが下記です

# -*- coding: utf-8 -*-
import requests
import json
import os
from logging import getLogger, FileHandler
from pytz import timezone
from datetime import datetime
import Adafruit_DHT

logger = getLogger(__name__)
logger.addHandler(FileHandler('hoge.log', 'a+'))

humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)

temperature_humidity_arr = [{
    "temperature": temperature,
    "humidity": humidity,
    "recorded_at": datetime.now(timezone('Asia/Tokyo')).strftime("%Y-%m-%d %H:%M:%S")
}]

temp_json_path = "data.json"

if os.path.isfile(temp_json_path):
    with open(temp_json_path, 'r') as f:
        temperature_humidity_arr = json.load(f) + temperature_humidity_arr

try:
    response = requests.post(
        'https://example.com',
        data=json.dumps({"temperature_humidity": temperature_humidity_arr}),
        headers={'Content-Type': 'application/json'},
        timeout=30
    )
    # 4xx, 5xxなどの場合に例外を出す 
    response.raise_for_status()
    if os.path.isfile(temp_json_path):
        os.remove(temp_json_path)
except Exception as e:
    logger.error('ERROR: %s' % e.message)
    with open(temp_json_path, 'w') as f:
        json.dump(temperature_humidity_arr, f)

これで無事自宅サービスに温度や湿度が送れるようになりました
もちろんPythonで温度や湿度がハンドリングできるので、Mackerelに送ってメトリクス監視しても良いですし自由自在です