はじめに
平日のテレワークは2Fで作業しており、1Fにあるドアホンの「ピンポーン」に気が付かないことが多々あった。そこで、
ドアホンが鳴ったらLINEに通知するガジェットをESP32のMicroPythonで作成した。
今やありきたりのネタであるが、検索でヒットした当Qiitaやブログ記事とはちょっと違う点があるので、そこを中心にまとめる。
1. トリガーはドアホンのA接点
いくつか拝見した記事では、ドアホン親機のモニターの輝度
やピンポーンの音
をセンサーで検知するものがほとんどであった。
我が家のドアホン親機(Panasonic VL-MV30)には、ドアホンの「ピンポーン」に連動してON
になる便利なA接点
が用意されていたので、これをプルアップしたGPIOに接続するだけでトリガーの実装は楽にできた(一方はGNDへ接続)。
最小適用負荷:DC5V/1mAの記載があるが、こんなにも電流は流れないはず。電圧も3.3V。
なお、ドアホンに応答しない場合、最長30秒間ON
が継続するため、その間に何度もLINEに通知しないロジックが必要。と言っても、LINEに通知後、while文
でOFF
になるのを待つだけ。
2. LINEへの通知はrequestsモジュールのpost
いくつか拝見した記事では、Arduino化したESP32(C++)しか見当たらず、MicroPythonでの例は見つけられなかったが、PCによるPythonでの実装例は簡単に見つけられる。
import requests
import json
url = 'https://notify-api.line.me/api/notify'
headers = {
'Authorization': 'Bearer ' + TOKEN
}
data = {
'message': '通知したいメッセージ'
}
response = requests.post(url, headers=headers, data=data).json()
print(response)
# {'status': 200, 'message': 'ok'}
PCで試したところ、わずか数行のコードで実現できることが確認できた。しかし、MicroPythonのurequestsでは、なぜかサーバに拒否されてしまう。
import urequests as requests
import ujson as json
url = 'https://notify-api.line.me/api/notify'
headers = {
'Authorization': 'Bearer ' + TOKEN
}
data = {
'message': '通知したいメッセージ'
}
response = requests.post(url, headers=headers, data=data).json()
#Traceback (most recent call last):
# File "<stdin>", line 13, in <module>
# File "urequests.py", line 120, in post
# File "urequests.py", line 82, in request
#TypeError: object with buffer protocol required
postパラメタの渡し方が悪いのか?
data = 'message=通知したいメッセージ'
response = requests.post(url, headers=headers, data=data).json()
print(response)
# {'message': 'message: must not be empty', 'status': 400}
message
を指定しているつもりだが?
Content-Type
の指定が必要か?
headers = {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + TOKEN
}
response = requests.post(url, headers=headers, data=data).json()
print(response)
# {'message': 'ok', 'status': 200}
試行錯誤の結果、上記のコードにたどり着くまでにかなりの時間を要した。うまく動作したコードは以下の通り。
import urequests as requests
import ujson as json
url = 'https://notify-api.line.me/api/notify'
headers = {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + TOKEN
}
data = 'message=通知したいメッセージ' #quote処理が必要
response = requests.post(url, headers=headers, data=data).json()
本来ならquote処理が必要だが、MicroPythonにurllib.parse
が無い・・・
import urllib.parse
data = 'message={}'.format(quote('通知したいメッセージ'))
↑こう書きたい所であるが、今回は固定メッセージのため、必要なら手動quoteで逃げる。
3. 運用
24H365D運用だが、ESP32がそんな連続運転に耐えるのか不明のため、1日1回強制リセットすることにした。午前3時にmachine.reset()
して基本は24H運用。
(boot.py
でWifiに接続済みの前提)
import machine
import time
import ntptime
ntptime.settime() #ntpによる時刻合わせ
JST_OFFSET = 9 * 60 * 60 # +09:00
def time_out(t):
now = time.localtime(time.time() + JST_OFFSET)
_, _, _, hour, minute, second, _, _ = now
if hour == 3 and minute == 0 and 0 <= second <= 3:
machine.reset() #再起動 (再起動には3秒以上かかる前提)
tim = Timer(-1)
tim.init(period=1000, mode=Timer.PERIODIC, callback=time_out)
深夜・未明にドアホンが押されることは通常では考えられないため、例えば、22時から翌朝6時まではDeepSleep
する運用も考えられる。
# 変更分のみ
def time_out(t):
now = time.localtime(time.time() + JST_OFFSET)
_, _, _, hour, minute, second, _, _ = now
if hour == 22 and minute == 0 and 0 <= second <= 3:
sleep_time = (6 - 22 + 24) * 60 * 60 * 1000
machine.deepsleep(sleep_time) #スリープ&再起動
DeepSleepからの目覚めは強制リセットと同じ動きとなるので、好都合でもある。
おわりに
何かの参考になれば幸いです。
こんなことが簡単に実現できてしまうとは、ホント便利な時代ですね。
ESP32だけなので、500円もあれば作れます(書き込み装置が別途必要)。
(機会があれば、自作の書き込み装置も紹介したい。 ⇒ ご参照ください。『ESP32書き込みボード』)
今回は14〜5年前のドアホンでしたが、もしかして最新のテレビドアホンは、最初からWifiに繋がってたりして・・・
以上