はじめに
猫は寒さには強いが、暑さには弱いそうな。
いつも留守番させてごめんね。
SwitchBotで部屋の温度が分かるから、暑くなったらエアコン自動で付けるくらいはしてあげたい。
あとどうせならエアコン操作時はLINEで通知を受けたいし、LINE Notifyの使い方の記事も書いときたい。
環境
AWSのAmazon Linux2023を使う。(私の記事は全部いっしょ!)
つまり配置は以下(図を書くほどの記事じゃない)
プログラム・・AWS
通知・・スマホのLINE
家・・SwitchBot製品の温湿度計とシーリングライト(ミニHUB代わり)
LINE作業
LINE Notifyをグループに参加させる (LINE Notifyは友だち登録しておく)
ちなみに、グループに参加させない状態で後述のプログラム使ってメッセージ送ろうとすると、こんなメッセージが来るのでLINE Notifyはちゃんと招待してあげる
パソコン作業
ブラウザでLINE Notify (https://notify-bot.line.me/ja/) にログインして、
マイページをクリック
「通知を送信するトークルーム」にさっき作ったグループを指定する。
トークン名はお好みで決める。ここでは「!」にした。(トークン名は後から変更できないっぽい!)
発行するボタンを押したら、次のようにトークンが表示されるのでメモする。
LINE Notifyを利用するプログラム
まずは単独で動かしてみて、通知が来るか確認しよう
import requests
YOUR_TOKEN = 'あなたのトークン'
# LINEにメッセージ送信
def send_message(text_message):
url = 'https://notify-api.line.me/api/notify'
headers = {'Authorization' : 'Bearer ' + YOUR_TOKEN}
payload = {'message' : text_message }
response = requests.post( url, headers = headers, params=payload)
if response.status_code != 200:
print('失敗!', response.status_code)
def main():
send_message('test')
if __name__ == '__main__':
main()
SwitchBotを利用するプログラム
SwitchBotの使い方は前の記事に書いた
今回はエアコンをON/OFFする関数を作る。
詳しいことは公式リファレンスを読む。
https://github.com/OpenWonderLabs/SwitchBotAPI
import json
import time
import hashlib
import hmac
import base64
import uuid
import requests
TOKEN = 'あなたのキー'
SECRET = 'あなたのキー'
TEMP_DEVICE_ID = '温湿度計のデバイスID'
EAKON_DEVICE_ID = 'エアコンのデバイスID'
# githubのリファレンスより、How to Sign
def create_header():
# Declare empty header dictionary
apiHeader = {}
nonce = uuid.uuid4()
t = int(round(time.time() * 1000))
string_to_sign = '{}{}{}'.format(TOKEN, t, nonce)
string_to_sign = bytes(string_to_sign, 'utf-8')
secret = bytes(SECRET, 'utf-8')
sign = base64.b64encode(hmac.new(secret, msg=string_to_sign, digestmod=hashlib.sha256).digest())
#Build api header JSON
apiHeader['Authorization']=TOKEN
apiHeader['Content-Type']='application/json'
apiHeader['charset']='utf8'
apiHeader['t']=str(t)
apiHeader['sign']=str(sign, 'utf-8')
apiHeader['nonce']=str(nonce)
return apiHeader
# デバイス一覧取得
def deviceid_view():
# ヘッダ作成
header =create_header()
response = requests.get("https://api.switch-bot.com/v1.1/devices", headers=header)
print(response.text.replace('}', '}\n'))
# 温湿度計の情報取得
def get_temp_and_humidity():
# ヘッダ作成
header = create_header()
url = 'https://api.switch-bot.com/v1.1/devices/' + TEMP_DEVICE_ID + '/status'
res = requests.get( url, headers=header )
return res.json()
# 寝室のエアコン
def shinshitu_eakon(temperature = 25, power='on'):
# ヘッダ作成
header = create_header()
# he unit of temperature is in celsius;
# modes include 0/1 (auto), 2 (cool), 3 (dry), 4 (fan), 5 (heat);
# fan speed includes 1 (auto), 2 (low), 3 (medium), 4 (high);
# power state includes on and off
# 設定温度、冷房、ファン速度:中、on or off で要求
body = {
"command" : "setAll",
"parameter" : f"{temperature},2,3,{power}", # 温度,モード,ファン速度,電源状態
"comandType": "command" # モード 1:自動 2:冷房 3:乾燥 4:ファン 5:加熱
} # ファン速度 1:自動 2:低 3:中 4:高
# 寝室のエアコン操作!
url = 'https://api.switch-bot.com/v1.1/devices/' + EAKON_DEVICE_ID + '/commands'
requests.post( url, headers=header, data=json.dumps(body) )
def main():
# デバイス一覧取得
deviceid_view()
if __name__ == "__main__":
main()
メイン関数
SwitchBotとLINE Notifyを組み合わせたメインプログラムを書く。
ざっくり仕様は
・温度が28℃以上になったらエアコンを冷房 26℃ でON
・温度が24℃以下になったらエアコンをOFF
・エアコン操作時にLINE通知
・ついでに温度と湿度が異常な場合もLINE通知
・一応、夏(5~8月)っぽくて日中(10~18時)と限定させておく。誤検知されても嫌なので、明らかに不要な時はなるべく排除しておきたいという心
from datetime import datetime
import line_notify
import switchbot
# 温度のLINE通知判定閾値
TEMP_MAX = 30
TEMP_MIN = 18
# 湿度のLINE通知判定閾値
HUMIDITY_MAX = 70
HUMIDITY_MIN = 35
# エアコンON/OFF 閾値
EAKON_ON = 28
EAKON_OFF = 24
# 設定温度をON閾値の何℃マイナスにするか
SET_TEMP = 2
# 室温と湿度をチェックし、異常ならLINEにて通知
def check_temp():
# 温湿度計情報の取得
meterplus = switchbot.get_temp_and_humidity()
temp = meterplus['body']['temperature']
humidity = meterplus['body']['humidity']
print( '温度=', temp, '湿度=', humidity )
# 温度/湿度に異常があればライン送信
if temp >= TEMP_MAX or\
temp <= TEMP_MIN or \
humidity >= HUMIDITY_MAX or \
humidity <= HUMIDITY_MIN:
msg = ' 温度/湿度が異常\n\n温度 ' + str(temp) + '℃\n湿度 ' + str(humidity) + '%\n\n'
msg = msg + '次の条件でお知らせします\n'
msg = msg + '温度 {:}℃以上 or {:}℃以下\n'.format( TEMP_MAX, TEMP_MIN )
msg = msg + '湿度 {:}%以上 or {:}%以下'.format( HUMIDITY_MAX, HUMIDITY_MIN )
line_notify.send_message(msg)
# 温度を返す
return temp
# 夏の暑い時に、寝室のエアコンをつける
def summer_eakon(temp):
# 現在時刻取得
dt_now = datetime.now()
# 夏(5~8月)の日中
if (dt_now.month >= 5 and dt_now.month <= 8) and \
(dt_now.hour >= 10 and dt_now.hour <= 18):
# 暑そうならエアコンON
if temp >= EAKON_ON:
switchbot.shinshitu_eakon(temperature = EAKON_ON - SET_TEMP, power = 'on')
msg = f'暑そうなのでエアコンONしました!\n' \
f'条件 : {EAKON_ON}℃ 以上\n' \
f'設定温度 : {EAKON_ON - SET_TEMP}℃'
line_notify.send_message(msg)
# 涼しくなったらエアコンOFF
elif temp <= EAKON_OFF:
switchbot.shinshitu_eakon(power = 'off')
msg = f'涼しそうなのでエアコンOFFしました!\n' \
f'条件 : {EAKON_OFF}℃ 以下'
line_notify.send_message(msg)
def main():
# 室温と湿度をチェックし、異常ならLINEにて通知
temp = check_temp()
# 夏の暑い時に、寝室のエアコンをつける
summer_eakon(temp)
if __name__ == "__main__":
main()
cronに登録
これをcronに登録しておく。
「crontab -l」コマンド結果は以下。1時間毎に起動するようにしている。
MAILTO=""
# 1時間毎
0 9-18 * * * cd /home/ec2-user/project/switchbot; python3 main.py
実際のLINE画面
ちなみに最初に書いた記事と同じLINEグループにしてるので、ネコが動いても通知がくる。
実はこんなプログラム書かなくても実現できる
「Switchbot エアコン 自動」 でググると分かるけどSwitchBotのスマホアプリだけで実現できるみたい!(笑)
なので普通はプログラム書かない気もする
おわりに
仕組み自体は去年に作ってたけど、自分の中でまとめるためにも記事にした。
1度やったはずなのに戸惑うところもあって、やっぱりちゃんと残しておくのって大事だな~と実感