以前に比べるとUSB連動タップの購入が難しくなってきてるというか選択肢も少なくなってる気がする。かといってHWを自作するのも面倒なのでスマートプラグを利用する方法を考えてみた。
[連動元機器のUSB]–>[ESP32]–>[スマートプラグ]–>[連動先機器]
電源オン制御は連動元機器のUSBにESP32を接続(給電)するだけで良さそうとは思ったものの電源オフ制御をどうするかが問題だ。電源オフされると何もできなくなるから電源管理サーバーなるものを使う方法も考えられるがもっとシンプルに簡単にしたい。
何気にTP-LINKのTAPOアプリからスマートプラグ(P110M)の機能を調べていたら【自動オフタイマー】という設定があった。
電源オフ制御はそれで実現できそうと思ったがESP32から自動オフタイマーを設定する方法がわからない。資料も情報もないなかで宝探しのごとく適当に思いついた方法を何時間も試してみたが全てボツ...
もしかしたらTAPOアプリのバイナリーに含まれる文字列から何かヒントが得られるのではと調べてみたらそれっぽい文字列を発見。さらに幸運なことにその文字列から必要なパラメータ名も判明したりして試してみたら見事に成功してしまった。(/・ω・)/
宝くじには当たらないけどこういうのにはよく当たる。(笑)
自動オフタイマーを利用する方法ならESP32は一定間隔でスマートプラグを電源オンし自動オフタイマーを更新するだけとなるが問題点はリアルタイムに制御できないことだ。
電源オン制御はESP32がWiFi接続するまで待たされてしまうし電源オフ制御はスマートプラグの自動オフタイマーの仕様で行うため1-2分遅延してしまう。
ESP32-C3で試してみたがWiFi接続にDHCPで1-2分ほど固定アドレスでも1-40秒程度と不安定かつ劇遅だった。ESP32-S3ならもっと実用的になるのかなぁ...試してないけど。
【ライブラリのDLはここからどうぞ!】
TP-LINK Tapo P105/P110M のKlapプロトコル対応版 (ESP32)
【スケッチ】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <WiFi.h> #include <tapo2.h> #define TAPO_AUTO_OFF_MIN 1 #define TAPO_PLUG "192.168.xxx.xxx" #define TAPO_USER "xxxxxxx@xxxxxxx" #define TAPO_PSWD "xxxxxxxxxxxxxxx" #define WIFI_SSID "xxxxxxxxxxxxxxx" #define WIFI_PSWD "xxxxxxxxxxxxxxx" #define FIXED_IPADDRESS 1 #if FIXED_IPADDRESS #define WIFI_IP IPAddress(192, 168, xxx, xxx) #define WIFI_GATEWAY IPAddress(192, 168, xxx, xxx) #define WIFI_DNS IPAddress(192, 168, xxx, xxx) #define WIFI_SUBNET IPAddress(255, 255, 255, 0) #endif #define WIFI_CONNECT_TIMEOUT 1000 Tapo2 tapo; void setup() { // // Setup WiFi // #if FIXED_IPADDRESS WiFi.config(WIFI_IP, WIFI_GATEWAY, WIFI_SUBNET, WIFI_DNS); #endif WiFi.begin(WIFI_SSID, WIFI_PSWD); for (uint32_t t = millis(); WiFi.status() != WL_CONNECTED; yield()) { if (millis() - t >= WIFI_CONNECT_TIMEOUT) { t += WIFI_CONNECT_TIMEOUT; WiFi.disconnect(); WiFi.reconnect(); } } // // Setup Tapo Plug // tapo.begin(TAPO_PLUG, TAPO_USER, TAPO_PSWD); } void loop() { static int delay_min = 0; tapo.setDeviceOn(true); #if TAPO_AUTO_OFF_MIN tapo.setAutoOff((delay_min ^= 1) + TAPO_AUTO_OFF_MIN); #endif delay(1000); } |