見出し画像

switchbotの温湿度計を使って真夏の眠れない夜をなくす話

背景

とびっきりの御曹司でもない限り、
必ず一度は経験したことあるはずの、熱帯夜の眠れない日…

・暑苦しい⇒エアコンつける⇒朝起きたら寒いし喉がイガイガ
・暑苦しい⇒エアコンつける⇒寒い⇒エアコン消す⇒暑い⇒以降無限ループ

これをなんとか解消したいと思い立った夏。20代男の自由研究。

筆者のスキル

最近仕事でPythonを使い始めた初心者~中級者。
Python、非常に便利だしライブラリ豊富だしなんでもできるではないかと思った夏休み、ちょうどよさげな題材を見つけたので調べながらやってみた。

そもそも快適な部屋とは

快適な部屋というのはどういうものかを調べた。
DAIKINのページによると、快適性とは温度と湿度で決まるとのこと。

これはほとんどの人が納得していることであると思う。
では快適と感じられる具体的な数値はどういうところなのか?
他サイトによると、温度/湿度に対して快適範囲が定量的に記載されていた。

普通のエアコンってどういうロジックなのか疑問は残るが、
どうやら部屋の温度・湿度が人様の快適な範囲に入るように、
エアをコントロールすればよさそうだ。

わが家のエアコンの話

最近の高性能なエアコンだと
快適な温度湿度になるような制御が入っているらしい。

一方で、わが家は賃貸物件であり、
寝室エアコンは十数年前のモデルっぽい少し古めなエアコンが搭載されている。

SwitchBot hub mini経由でAlexaからON/OFFのみ可能。
温度設定とか風量設定はリモコンボタン登録をやり直さないと変更不可。
細かいエアコン制御(設定温度を変える、除湿に変えるとか)は
エアコンがSwitchBotの対象機種ではないため不可。

システム構成の話

システム構成図は下記の通り。

システム構成図

もともとは、Raspberry Piに汎用の温湿度計をつないで
部屋の温湿度をリアルタイムフィードバックする予定だった。

だが購入した温湿度計が初期不良で使い物にならなかったので、
納期優先でSwitchBotの旧型(?)温湿度計をamazonで購入し、
上記のシステム構成とした。

コーディングの話

初心者には分かりかねるが、誰もが考え付きそうなことには先駆者がいて、
私は下記のサイトを参考にさせていただいた。

この辺りを拝見すると、
SwitchBot APIの使い方だったり、コードの実装方法だったり、
何していけばいいのか がおぼろげながらも理解できる。
あとは、Pythonでコーディングしながら疑問に思ったことを詳細に調べていくというスタイルで進めた。

環境

・Windows PC
・Python3 (VS codeで実行)
・SwitchBot Hub mini
・SwitchBot 温湿度計
・エアコン(既述)


ライブラリのインストール

使用するライブラリをインストールする。
今回使用するライブラリは下記。
・requests
・json
・time
・datetime
・pandas
このうち、requestsとpandasをコマンドプロンプトでpip installしておく。
Pythonにすでに含まれているそうなので、残る3つはpip installはしなくてOK。

# ライブラリのインストール

pip install requests
pip install pandas


デバイス名,デバイスIDの取得

これまたコマンドプロンプトからSwitchBot APIから家電等デバイスを操作するときのデバイス名とデバイスIDを取得しておく。

# デバイス名の取得 デバイス名とIDが分からない場合、下記をコマンドプロンプトで実行し、デバイス名,IDを調べる
# ***にはSwitchBotアプリから調べられるトークンを記入

curl -H "Authorization:***" "https://api.switch-bot.com/v1.0/devices"

これで、多少見にくいが、寝室エアコンとか温湿度計とかのデバイス名とIDが調べられるのでメモっておく。
IDというのは、"deviceId"の後に書かれているほうを使う。

コードと詳細説明

今回作成した全体コードは下記。

### switchbot_API_acn.py ###


# ライブラリのインポート
import requests
import json
import time
import datetime
import pandas as pd

t_sum = 0

# 時間閾値(お好みに調整)の設定
t_offmax = 2
t_onmax = 2
acn_flag = 0
acn_flag_old = 0

# 何秒間次の実行まで待つか
t_clock = 60

# 温湿度計のdeviceID($$$に記入)
sensor_id = "$$$"

# 寝室エアコンのdeviceID(+++に記入)
aircon_id = "+++"

# switchbotのtokenを入力(***に記入)
header = {"Authorization": "***"}

# dataframeのコラムを用意
df = pd.DataFrame(columns=['date','time', 'acn_flag', 't_sum', 'temp', 'humd', 'threshould'])

# csvでログを保存する用の事前準備として時間を表現する変数を用意
t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')


# 温湿度計から温度と湿度を読み取る
def job():
    global temp,humd

    url_for_sensor = "https://api.switch-bot.com/v1.0/devices/" + sensor_id + "/status"
    response = requests.get(url_for_sensor, headers=header)
    sensor_data = response.json()

    temp = float(sensor_data["body"]["temperature"])
    humd = float(sensor_data["body"]["humidity"])


# acn_flagを受け、エアコンをON/OFF/そのまま の指示を送る
def judge():
    # 寝室エアコンはON/OFF制御しかできないので、"command"をON/OFFするしかない(リビングエアコンなら上のコードでもう少し細かく設定可能)
    # 寝室エアコン ON/OFF   
    global acn_flag, acn_flag_old

    if acn_flag == 1:
        if acn_flag_old == 0:
            body = {
            "command" : "turnOn",
            "parameter" : "default",
            "comandType": "customize"
            }
            url_for_acn = "https://api.switch-bot.com/v1.0/devices/" + aircon_id + "/commands"
            requests.post(url_for_acn, headers=header, data=json.dumps(body))
        elif acn_flag_old == 1:
            pass

    elif acn_flag == 0:
        if acn_flag_old == 0:
            pass
        elif acn_flag_old ==1:
            body = {
            "command" : "turnOff",
            "parameter" : "default",
            "comandType": "customize"
            }
            url_for_acn = "https://api.switch-bot.com/v1.0/devices/" + aircon_id + "/commands"
            requests.post(url_for_acn, headers=header, data=json.dumps(body))


# 温度-湿度特性の閾値(快適性指標)を2次関数で表現
def threshold_humidity(x):
    a = 0.082735966
    b = -7.789461764
    c = 209.2591461

    calc = a * x**2 + b * x**1 + c
 
    return float (calc)


# 実行内容
while True:

    job()
    
    # 快適性指標を確認し、快適でなければエアコンをON、そうでなければOFF など
    if  humd > threshold_humidity(temp) :
        if t_sum < t_offmax:
            acn_flag = 0
        else:
            acn_flag = 1

    elif t_sum < t_onmax:
        acn_flag = acn_flag

    else:
        t_sum = 0
        acn_flag = 0
    
    judge()
    
    # csvデータに出力する
    now = datetime.datetime.now(JST)
    nowdate = now.date().strftime('%Y/%m/%d')
    nowdate_str = now.strftime('%Y%m%d')
    nowtime = now.time().strftime('%X')
    print(nowdate, nowtime, acn_flag, t_sum, f'{temp:.2f}', f'{humd:.2f}', f'{threshold_humidity(temp):.2f}')
    df = df.append({'date':nowdate, 'time':nowtime, 'acn_flag':acn_flag, 't_sum':t_sum, 'temp':f'{temp:.2f}', 'humd':f'{humd:.2f}', 'threshould':f'{threshold_humidity(temp):.2f}'}, ignore_index=True)
    df.to_csv(f'data_{nowdate_str}.csv')
    
    acn_flag_old = acn_flag
    t_sum += 1

    # t_clock秒間待つ
    time.sleep(t_clock)




  • 時間閾値の設定

まず時間閾値の設定というところについて。
今回はほぼ下記の制御アルゴリズムを考えコードを書いた。

制御アルゴリズム

SwitchBot APIから読める温湿度計の情報については、
おそらくサーバーの更新頻度が原因なのか、とにかく一定間隔ではなさそうであることがわかったので、
https://support.switch-bot.com/hc/ja/articles/360038241213

時間閾値の設定は自分にとって、都合の良い(結果的に寝苦しくならなかった)数値に設定している。


  • トークンの取得

これは既述した各リンクのSwitchBot賢者が教えてくれた。
Androidアプリで試したところ、token取得は手間取らずできたが、
妻のiPhoneから試したところ、"アプリバージョン"を連打しないと"開発者向けオプション"を表示できなかった。


  • APIからサーバーをたたく、APIからサーバーに送る

APIの取り扱いは今回が初めてだった。
難しそうに思っていたがやってみたら意外と簡単だし面白い。
・対象URLをrequests.getでたたく
・response.json()でまるっと格納
・格納した辞書リストから欲しい情報だけとってくる
・こっちから指示を送る場合はrequests.post
みたいな感じ。

    url_for_sensor = "https://api.switch-bot.com/v1.0/devices/" + sensor_id + "/status"
    response = requests.get(url_for_sensor, headers=header)
    sensor_data = response.json()

    temp = float(sensor_data["body"]["temperature"])
    humd = float(sensor_data["body"]["humidity"])

SwitchBotに限らず他のいろんなAPIでも同様にできるらしいので、
いろいろ試してみたい。APIってすごいな。めちゃ便利ーー。


  • 温度湿度の閾値特性

最初のサイトから、温度湿度の快適性指標を数値化した。
自分はAlrightよりも少し暑めがちょうどよかったので、
右図の通りのラインを設定した。

温度湿度の閾値特性
(左がサイトのスクショ、右が左を参考に自分に好みの閾線)

結果

おおむね、しっかりと動いてくれたぞ。
そもそもプログラムが動いてくれた時点でかなりうれしいぞ。

結果:ある夜のデータ

そしてエアコンは思ってたよりも頻繁にON/OFFを繰り返してくれた。

面白いのは、夜中の2:00~4:00くらいで室内の湿度がちょっと上がるところ。
結果として、エアコンの稼働率が朝になるにつれて上がる。
これは他の日も見られる傾向だった。
もしSwitchBotがエアコンのON/OFFだけでなく運転モードの変更にも対応できるのであれば、朝方は除湿メインで動かすとか、そういったことができてもっと快適性が向上する気がする。

こういったデータが取れたため、このまま何度か試したが、
暑くて夜中にエアコンつけたりとか、エアコンつけすぎて朝のどが痛い
みたいなことはなくなっている!!

一応、これにてお題は解決!! としておこう。
御曹司生活にもまたひとつ近づけた気がする。

さいごに

今回やってみた結果ちょっと悔やまれる点を書いておく。
まだまだ発展途上なのでもっとできるはず。

①温湿度計のタイムラグ
"時間閾値の設定"で述べた通り、
温湿度計のAPI経由での情報取得だと若干タイムラグがあるので、
温湿度計に表示されている数値なら、エアコンONになるはずなのに、
PCが読んでくる温湿度計の数値だと、エアコンOFFのまま…
みたいな状況が散見された。

もしSwitchBot温湿度計からのリアルタイム情報をすぐサーバーから取得できれば、もっと最適な温度/湿度の制御をエアコンのON/OFFだけでできる気がする・・・
ここはSwitchBotに唯一ご対応いただきたいところ・・・
もしくは一度諦めた温湿度センサを再度リベンジ購入するか。
いやそこまでお金かけたくないな…

②Pythonコードの実行環境
今回はいつも使っているPCからVSCode起動して毎夜実行するという荒業。
夜になったら勝手にプログラム実行するとか、Alexaから実行するとか
そういうのをさくっとできるようにしておきたい。


以上、"SwitchBotの温湿度計を使って真夏の眠れない夜をなくす話"でした。


この記事が気に入ったらサポートをしてみませんか?