TP-LINK TAPO P100/P105/P110をLinux/Windowsから直接制御する

ESP32用に作成したライブラリをLinux/Windows用に移殖しコマンドライン・アプリとして実行できるようにしてみた。

TP-LINK TAPO P100/P105をESP32から直接制御する

ESP32用からの変更点は、次の通り。
・JSONライブラリをArduino_JSONからPC向けとしては有名なnlohmann-jsonへ変更。
・HTTPライブラリをESP32/library/HTTPClientから独自作成の簡易型HTTPライブラリへ変更。
・MBEDTLSライブラリは、最新版(2.24.0)に差し替え。

base64ライブラリだが現在DL可能な最新版(1.2.1)については何か問題があるようだ。encode&decode或いはdecode&encodeにより元データが正確に復元できないことがある。パディングが不正になることを発見したのでデータバイト数の計算ミスなのかもしれない。結局、ESP32に含まれていたlibb64でないと正しく動作しなかったのでそのまま流用させてもらった。

しかし、未だにmakeの呪文のような記述方法は全く理解できない。とりあえず私の開発環境では動いているのだが何か間違ってるかも...

【対応ファームウェア】
P110M: 1.1.0 Build 231009 Rel.155719 以前
P105: 1.4.1 Build 20231103 Rel. 36519 以前

【修正】
2023-12-28
上記ファームウェア(Build 231009)以降に対応したものは下記を見るべし。
TP-LINK Tapo P105/P110M のKlapプロトコル対応版 (Windows/Linux)

2023-12-12
P110Mの最新ファームウェア(Build 231009)以降では通信プロトコルが変更されため1003エラーが発生します。動作中のP110Mをお持ちの方はTAPOアプリの自動更新をオフに設定することを推奨します。

2023-12-11
ダウンロード用のtapo.exe(tapo.zip)を動的リンクで生成していたために私の開発環境以外では動作しないことが判明。静的リンクに変更したものに差し替えした。気づくの遅すぎ!!m(_ _)m

2023-09-15
P110Mの電力モニター機能(getEnergyUsage)に対応。

2023-09-14
httpclient.hの不具合により[Tapo P110M]が動作しなかったため修正。

【ダウンロード(Download)】
tapo.exe (Windows実行形式 – Microsoft defender スキャン済み)
tapo app (ソースコード)
libraries (参照ライブラリ)

【フォルダ構成】
tapo/
+ json-develop/ … nlohmann-jsonの最新版(3.9.1)
+ libb64/ … ESP32に含まれているものを同梱
+ mbedtls-2.24.0/ … mbedtlsの最新版(2.24.0)
※ libb64は、最新版(1.2.1)では動作しないことに注意すべし!

【コンパイル(Compile)】
Downloadした圧縮ファイル2個を適当なフォルダ内に展開し次の事前準備を行った後にmakeを実行する。

【Linux – コンパイルの事前準備】
mbedtls-2.24.0に移動後、下記コマンドを実行しmbedtlsライブラリを生成する。

make no_test

【Windows(MinGW) – コンパイルの事前準備】
mbedtls-2.24.0に移動後、下記コマンドを実行しmbedtlsライブラリを生成する。

mingw32-make CC=gcc no_test WINDOWS=1

※makeが途中で失敗してもlibrary/libmbedcrypt.aが生成されていればOK。それしか使わないから...(-_-;)
※うまくいかない場合は、最後の参考情報を見て自己解決するべし。

【コマンドライン・アプリ(Command-Line App)】

【ライブラリ(Library)】

【参照ライブラリ】
libb64
JSONライブラリ – nlohmann/json
ARMmbed/mbedtls

【参考情報】
mbedtls – Knowledge Base / Compiling and Building

【関連投稿】
TP-LINK WiFiスマートプラグをESP32(Arduino)から制御する
TP-LINK WiFiスマートプラグをLinux/Windowsから直接制御する
TP-LINK TAPO P100/P105をESP32から直接制御する
TP-LINK TAPO P100/P105/P110をLinux/Windowsから直接制御する

“TP-LINK TAPO P100/P105/P110をLinux/Windowsから直接制御する” への18件の返信

  1. 貴重な情報、ありがとうございます。
    TP-LINK TAPO P105の制御がPython行え、RaspberryPiの停止と再起動が安全に遠隔で行うことが出来るようになりました。

    1. コメントありがとうございます。
      当サイトがお役に立てたようで嬉しく思います。って、なんか天皇陛下様の言葉尻みたいな?(笑)
      Pythonはなんとなく性格的に合わないのとプログラミングの基本を学んだり組み込み向け用途としてはPythonというよりもCやC++のほうが適切と考えているためついついポーティングしてしまいがちですが、ポーティングするたびにPythonってコンパクトにプログラムが作れるんだなといつもながら感心させられてしまいます。

  2. P110Mを制御出来るコマンドを求めてこのページにたどり着きました。
    P110Mを操作しようとすると TAPO Status: [1003] とメッセージが出て制御出来ませんでした。
    ファーム違い等で不可能になってしまったのでしょうか?試したP110Mは 1.1.0 Build 231009 Rel.155719
    ページ最終更新の9/15よりあとのファームのようです。

    P110M制御のつもりでこのページにたどり着きましたが
    P105制御はpythonよりも反応が速くこちらを利用し始めました。大変感謝しております。

    1. コメントありがとうございます。
      ご指摘の新しいファームでどうなるか試してみたいのですがどこで購入されたか参考までに教えて頂けないでしょうか?

      1. ttps://www.amazon.co.jp/dp/B0C9PYJZJ7 (先頭h抜き)
        こちらのAmazon限定Tapo P110M 2-pack品。12/7注文
        これを初期設定時にファームアップしてしまったため購入直後のファームは覚えていません。
        よろしくお願いします。

        1. ご連絡ありがとうございます。
          動作確認後の手持ちのP110Mのファームウェアを更新したら1003エラーが返されるようになってしまいました。どうやらP110Mの通信プロトコルが変更されてしまい数か月前から全世界で火の手があがっていたようです。新しい通信プロトコルへの対応にはそれなりに時間がかかりそうです。とりあえず連絡まで。

          1. 試して頂いて一つ制御不能になってしまい申し訳ありません。
            P105は何度かファームアップしても使えてたのでP110Mも気にせずファームアップしてしまい迂闊でした。P110Mの解析がされた頃にまだ興味があったらプログラムを対応して頂けたらと思います。
            ありがとう御座いました。

          2. 気にすることはないですよ。最新のTAPOアプリではデバイス追加時に強制アップデートさせられる仕様になってるのでいつかは対応しなければならないと思ってたところです。
            詳しいことはわかりませんが新しいプロトコルはKLAPというらしく既に解析されていて実装がいくつか公開されているようです。探してみられてはいかかでしょうか?

          3. 各種公開されてるpythonでは10月以降更新されてるもの適当にいくつか試しましたがダメでした。そもそも新プロトコル云々では無くプログラムが動作せず。pythonはイマイチわからんです。
            Go言語?を利用したプログラムで一応動作可能な物を見つけコマンド操作出来るようになりました。
            あと追加でプラグを購入して無理矢理アップデートせずに登録してこのプログラムで動作も出来ました。やはり反応速度が早く、取得失敗も起きず凄く安定してるのでこちらを主で使わせて頂きます。ありがとう御座いました。

            tapoアプリ初期登録時ファームアップが強制のように見えますが ファームを確認する ボタン表示時点で登録は済んでいるのでボタンは押さずアプリを強制終了させ登録画面を強制的に終了するとファームアップさせずに登録が可能でした。

          4. ご連絡ありがとうございます。
            登録画面を強制的に終了する方法は思いつきませんでした...大変貴重な情報ありがとうございました。<(_ _)>
            トリッキーな方法は嫌いではないので今後の参考にさせて頂きます。

            ちなみに公開されているKLAP対応のものとしては下記を見つけました。
            python: https://github.com/petretiandrea/plugp100
            Rust: https://github.com/mihai-dinculescu/tapo
            C#: https://github.com/cwakefie27/TapoConnect

            私もpythonはイマイチなのですが試してみるならRustやC#よりコンパイルなしで実行できるpythonがお勧めです。
            参考までにraspberry-piなどでのpython版のインストールは次のようになります。
            sudo apt install pip
            sudo pip install plugp100
            成功すると次の場所にplugp100がインストールされているので、
            /usr/local/lib/python3.x/dist-packages/plugp100
            そのサンブルコードのexample.pyを修正し、
            python example.py
            で実行できます。プラグ以外にも対応しているので色々試してみるときにはお勧めです。
            —————————————————————–
            import asyncio
            import os

            from plugp100.api.light_effect_preset import LightEffectPreset
            from plugp100.api.tapo_client import TapoClient, TapoProtocolType
            from plugp100.common.credentials import AuthCredential
            from plugp100.discovery.tapo_discovery import TapoDeviceFinder
            from plugp100.api.plug_device import PlugDevice

            async def main():
            # print(“Scanning network…”)
            # print(TapoDeviceFinder.classify(TapoDeviceFinder.scan(5)))

            # create generic tapo api
            username = os.getenv(“USERNAME”, “mail-address”)
            password = os.getenv(“PASSWORD”, “password”)

            credentials = AuthCredential(username, password)
            client = TapoClient.create(credentials, “ip-address”, 80, False, None, TapoProtocolType.KLAP)
            await client.initialize()

            plug: PlugDevice = PlugDevice(client)
            await plug.on()
            await plug.off()

            print(await client.get_device_info())
            print(await client.get_energy_usage())
            # print(await client.get_current_power())
            # print(await client.get_child_device_list())
            # print(await client.get_child_device_component_list())
            # print(await client.set_lighting_effect(LightEffectPreset.Aurora.to_effect()))
            await client.close()

            # plug = PlugDevice(TapoClient(username, password), ““)
            # light = LightDevice(TapoClient(username, password), “
            “)
            # ledstrip = LedStripDevice(TapoClient(username, password), “
            “)

            # – hub example
            # hub = HubDevice(client)
            # print(await hub.get_children())
            # print(await hub.get_state_as_json())

            if __name__ == “__main__”:
            loop = asyncio.new_event_loop()
            loop.run_until_complete(main())
            loop.run_until_complete(asyncio.sleep(0.1))
            loop.close()
            —————————————————————–

          5. アマゾンに注文したP110Mが届いたので”アプリを強制終了させ登録画面を強制的に終了”を試してみました。
            ファームウェアバージョン”1.0.4 build 230825 rel.115051″が動作することを確認しました。
            素晴らしいです。情報ありがとう!!

          6. python情報有り難う御座います。
            しかし、せっかく情報頂いたのですがダメでした。ubuntuでチャレンジ、結局usernameのところで何やらエラーが出るのですが対処が分からず轟沈です。pythonは情報が多いのですがどうも取っかかりがあってエラーが出ると対処法分からず大体諦めてます。
            python ./plug.py
            File “/home/user/./plug.py”, line 14
            username = os.getenv(“USERNAME”, “mail@mail.com”)
            ^
            IndentationError: expected an indented block after function definition on line 9

            一応こちらのアプリとKLAP対応tapogoというGoプログラムで何とか所持してるP110M全てを制御出来るようになってるのでpythonは保留(諦め)にしようかと思います。
            tapogo https://github.com/achetronic/tapogo

            ありがとう御座いました。

          7. わざわざ試して頂きありがとうございました。

            “IndentationError: expected an indented block after function definition on line 9”
            このエラー内容をGoogle翻訳にかけると、
            “IndentationError: 9 行目の関数定義の後にインデントされたブロックが必要です”
            となるのでインデントが必要な行にインデントがないというエラーであることがわかります。

            pythonは他言語のようにコードブロック{}を指定する記号がなく代わりにインデントによりコードブロックを指定する必要がありますが連絡したソースコードにインデントがなかったことがエラーの原因と思われます。ソースコードをコピベするとインデントが削除されてしまうみたいですね...インデントについては元のexample.pyを参考にして頂ければと思います。すいませんでした!<(_ _)>

          8. 対処法ご教授頂きありがとう御座いました。
            インデントはexample.pyを真似てなんとかなりました。しかしやはりエラーが出て動作してなかったですが
            await client.initialize() をコメントアウトしましたら動作しました。example.pyには無い行でしたので合わせるかたちで試しました。これでファームバージョンアップしてしまったP110Mでもenergy_usageが無事取得出来ました。Go言語よりも安定性ありそうです。
            いろいろありがとう御座いました。

          9. うまく動作して良かったです。
            少し気になったのでコメントアウトされたというawait client.initialize()が何をしているのか調べてみました。
            TapoClient.create(credentials, “tapo_device_ip”)
            のようにプロトコルタイプ省略時にプロトコルタイプを自動判定するためのメソッドのようです。最初にSecurePassthroughプロトコル(旧)を試してみて失敗したらKLAPプロトコル(新)を選択するという動作をするため最新ファームに対しては必ず一度は失敗することになります。今後のことを考えると新しいプロトコルを先に試すのが正しいとは思うのですがどちらにしても自動判定にはデメリットがあるのでinitialize()はコメントアウトで正解と思います。
            TapoClient.create(credentials, “tapo_device_ip”, 80, False, None, TapoProtocolType.KLAP)
            ちなみに上記のようにプロトコルタイプを指定した場合initialize()は無処理になるためコメントアウトしなくても無害なはずなのですが...
            以上、参考情報でした。

          10. ありがとうございます。
            ubuntuでは成功したのですがwinでは動作せず諦めかけてたところ再度このページを覗いたらKlap対応版exeが完成してたので早速利用させて頂きました。
            こんな早くに作成頂きありがとう御座いました。大切に使わせて頂きます。

          11. P105の最新ファームでも同様にプロトコル変更が行われていたようです。P105にも対応したものを公開しましたのでよろしければ使ってみてください。
            TP-LINK Tapo P110M のKlapプロトコル対応版 (Windows/Linux)
            https://lab.sasapea.mydns.jp/2023/12/24/tapo_klap_pc/

園田 誠 へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください