はじめに
本記事は旧Tuya APIの内容であり、2021年12月現在、実施できない状態になっています。
Tuya APIが刷新され、下記記事で新しいTuya APIの使い方を紹介していますのでご覧ください。
ノートパソコンのバッテリは消耗品で、使っているとだんだん弱っていきます。
バッテリーがすぐ切れると困るので、できるだけ長持ちさせたいですよね。
ノートパソコンのバッテリを長持ちさせる方法は様々なサイトで紹介されています。
この記事では、MacのApple Scriptを使って、自動的にバッテリーにやさしい充電をする方法を紹介します。
(2021年5月8日追記)
本記事のまとめに7ヶ月間試した結果を説明する動画のリンクを追加しました。
Liイオンバッテリについて
ノートパソコンのバッテリとして現在主流のLiイオンバッテリを長持ちさせるには、
- 電源つなぎっ放しはダメ
- 20%〜80%の間で使う
- 充電度合いが少ない状態で使う
- 充電度合いの変動幅は小さく
以上を考慮して、50%〜55%の充電状態をキープするようにしました。
構成一覧
構成要素 | バージョン |
---|---|
macOS | Catalina 10.15.7 |
Node.js | v12.18.0 |
npm | 8.2.0 |
スマートプラグ | 中国製Smart Life対応 型番: XS-A16 |
スマートプラグの設定
スマートプラグは、家庭のコンセントにつないでインターネット経由で電源のON/OFFを切り替えられる機器です。
Amazon EchoやGoogle Homeなどのスマートスピーカから制御できるもの、IFTTT経由で制御できるものなどがあります。
以下のようなSmart Homeアプリ対応のスマートプラグであれば、本記事と同じことができます。
スマートプラグ WiFi スマートコンセント Echo Alexa Google ホーム対応
スマートプラグの説明書に載っている2次元バーコードから「Smart Life」のアプリをインストールし、このページなどを参考に、メールアドレス登録→家族(自分)を作成→デバイス追加の順に設定します。
デバイスの追加はアプリの右上にある+マークをタップし、家電製品(Electrical Engeneerings)→コンセント(Socket)へと進み、Wifiのパスワードを登録します。
クラウド(Tuya IoT)の設定
クラウド側の設定をします。(参考)
まず、https://iot.tuya.com からアカウント作成してログインし、ページ上部のCloud Developmentを押すと以下のページが表示されます。
プロジェクトの作成
Createボタンを押すと下図のように表示されるので、記入していきます。
内容は何でも良いようです。
私は次のようにしました。
Project Name: Toggle Plug
Description: Operate the smart plug remotely.
industry: Smart Home
下図のようにAccess IDとAccess Secretが表示されます。
これらは後で使うので、Copyを押してコピーし、テキストエディタに貼り付けるなどしてメモを取っておきます。
アプリの作成
次にページ上部のApp Service→左メニューApp SDKを押して下の画面に移行します。
画面中央のObtain SDKボタンを押すと下のポップアップが出るので、Wi-Fi device solutionを選択して
Nextを押します。
以下のポップアップが出るのでアプリ情報を記入してConfirmを押します。
私は以下のようにしました。
App Name: Plug
iOS Bundle ID: com.smartlife.plug
Android Package Name: com.smartlife.plug
Channel ID: smartlifeplug
ここで入力したChannel IDも後で使うのでメモしておきます。
プロジェクトにアプリをリンク
上部メニューのCloud Development→左メニューLinked Devices→Linked devices by Apps
で以下のように表示されるので、Add Appsを押してアプリを追加します。
作成したアプリにチェックを入れ、OKを押します。
Tuya API環境構築
ここでの作業を行う環境して、以下である必要があるとのことです。
- 2.4GHz 帯のWi-Fiがあること。
- PCが、スマートプラグと同じWi-Fiにつながっていること。
- そのネットワークでクライアント間通信ができること。
- PCに他のネットワークインタフェイス(有線LANなど)がないこと。
複数のインターフェイスがあると、優先順位によってはパケットが正しく送られない場合あり。
CLIのインストール
npmがインストールしていない方はこちらからNode.jsの推奨版をインストールしてから以下を実行します。
$ sudo npm i -g @tuyapi/cli
ペアリング
スマートプラグを電源に接続し、ボタンを長押ししてペアリングモードにします。
ペアリングモードには2種類あり、LED点滅が速い方にします。
私の場合、電源を入れて単に長押しするとこのモードになりました。
Macのターミナルから次のコマンドを実行します。
$ tuya-cli link --api-key "Access ID" --api-secret "Access Secret" --schema "Channel ID" --ssid "ネットワークのSSID" --password "ネットワークのパスワード" --region us
以下のように表示されれば成功です。
✔ Device(s) registered! [ { id: 'xxxxxxxxxxxxxxxxxxxx', ip: 'xxx.xxx.xxx.xxx', localKey: 'xxxxxxxxxxxxxxxx', name: '智能插座' } ]
表示されたidとlocalKeyはAPI呼び出しの際に使うのでメモしておきます。
APIのダウンロード
APIをダウンロードします。
$ npm i -S codetheweb/tuyapi
同期版を使った場合でも、時々”Socket error”が発生するため、3回はトライするようにしました。
これで、大抵2回目には接続に成功するようになりました。
以下をplug_sync.jsなどのファイル名で保存します。
id, keyにはペアリングの際に表示されたidとlocalKeyを入れます。
const TuyAPI = require('tuyapi'); const device = new TuyAPI({ id: 'xxxxxxxxxxxxxxxxxxxx', key: 'xxxxxxxxxxxxxxxx'}); let powStat = process.argv[2] == "on" ? true : false; (async () => { await device.find(); await device.connect(); let status = await device.get(); console.log('Set:', status, '=>', powStat); await device.set({set: powStat}); device.disconnect(); })();
引数をonにすると電源ON、それ以外(offなど)は電源OFFにするプログラムになっています。
ここでAPIの動作確認を行います。
以下のコマンドでON/OFFできるか試します。
$ node plug_sync.js on Set: false => true $ node plug_sync.js off Set: true => false
これで正常にON/OFFできればよいです。
次にApple Scriptで充電の度合いに応じてこのコマンドを実行するようにします。
次の章へ進んでください。
以下、当初使っていた非同期版のスクリプトを参考までに掲載します。
const TuyAPI = require('tuyapi'); const device = new TuyAPI({ id: 'xxxxxxxxxxxxxxxxxxxx', key: 'xxxxxxxxxxxxxxxx'}); let powStat = process.argv[2] == "on" ? true : false; // Find device on network device.find().then(() => { // Connect to device device.connect(); }); // Add event listeners device.on('connected', () => { console.log('Connected to device!'); }); device.on('disconnected', () => { console.log('Disconnected from device.'); }); device.on('error', error => { console.log('Error!', error); }); device.on('data', data => { //console.log('Data from device:', data); // Plug on/off if (data.dps['1'] != powStat) { console.log('Set:', data.dps['1'], '=>', powStat); device.set({set: powStat}); } }); // Disconnect after 3 seconds setTimeout(() => { device.disconnect(); }, 3000);
Apple Scriptの作成
画面右上(メニューバー上)の虫眼鏡マーク(Sporlight Search)からScript Editor.appを検索してダブルクリックで起動します。
以下のコードをScript Editorに貼り付けます。
plug_async.jsのファイルパスはお使いの環境に合わせて変えてください。
use AppleScript version "2.4" -- Yosemite (10.10) or later use framework "Foundation" use framework "AppKit" use scripting additions global MIN, MAX, AWAKE set MIN to 50 set MAX to 55 set AWAKE to true set aCenter to current application's NSWorkspace's sharedWorkspace()'s notificationCenter() aCenter's addObserver:me selector:"notifSleep:" |name|:"NSWorkspaceWillSleepNotification" object:(missing value) aCenter's addObserver:me selector:"notifWaked:" |name|:"NSWorkspaceDidWakeNotification" object:(missing value) on exeAPI(message) -- say "The AWAKE value is " & AWAKE if AWAKE then try -- say "Start API" do shell script "/usr/local/bin/node /Users/user/plug_sync.js " & message & "> /Users/user/plug_sync.log 2>&1" -- say "Normal end" on error -- say "Error occurred" -- display dialog "Error occurred" return 1 end try end if return 0 end exeAPI on idle set per to (do shell script "pmset -g batt | grep % | sed 's/[%;]/ /' | awk '{print $3}'") as number set ret to 1 set cnt to 0 repeat while cnt < 3 and ret /= 0 -- say "The count is " & cnt if per ≤ MIN then set ret to my exeAPI("on") else if MAX ≤ per then set ret to my exeAPI("off") end if set cnt to cnt + 1 end repeat return 60 end idle on quit exeAPI("off") continue quit end quit on notifSleep:aNotif exeAPI("off") -- display notification "System will sleep" -- say "System will sleep" set AWAKE to false end notifSleep: on notifWaked:aNotif -- display notification "System did wake" -- say "System did wake" set AWAKE to true end notifWaked:
スクリプトの解説
MIN, MAXの値を変えればお好みの充電範囲にできます。
/usr/local/bin, /Users/userなどのパスはお使いの環境に合わせて変更してください。
on idle, return 60 として60秒毎にバッテリーの充電度合いを確認し、MIN以下なら充電開始、MAX以上なら充電停止しています。
nodeコマンドは3回トライしています。
当初は、on idle部のみで充電を制御しようとしていました。
しかし、電源ON状態でシャットダウンするとそのまま充電され続けてしまうため、on quitでシャットダウン時のApplication停止を検知して充電を停止するようにしました。
その後、電源ON時にスリープモードに入った場合も充電され続けてしまうことに気づきました。
notificationCenterの記述とon notifSleep:aNotifを追加し、スリープモードに入る通知を取得して充電を止めるようにしました。
ところが、スリープモードでもスクリプトは動作しているようでMIN以下になるとon idleの機能が働いて電源がONになります。
そのまま少し経つとディープスリープモードに移行してスクリプトが停止して充電し続けます。
これを避けるために、スリープと復帰の両方の通知を検知して、現在スリープモード中かどうかを確認し、スリープモード中は電源ON/OFFを変更しないようにしました。
これで、スリープ状態に入るときに電源をOFFにし、スリープから復帰するまで電源OFFをキープするようにしました。
スクリプトの保存
Script Editor上部のツルハシの絵が付いているボタンを押すとキーワードに色が付き、見やすくなります。
File→Saveから保存します。
File FormatをApplicationにし、オプション:ハンドラの実行後に終了しない(Stay open after run handler)にチェックを入れます。
私はPowerManagerAPI.appという名前で保存しました。
続いて、このApple Script ApplicationをMac起動時に立ち上がるように設定します。
Appleマークからシステム環境設定(System Preferences)
→ユーザーとグループ(Users & Groups)
→ログイン項目(Login Items)
から+マークを押すと選択画面が出るので、作成したPowerManagerAPI.appを選択します。
Macを再起動して、充電度合い50〜55%をキープするように自動的にスマートプラグがON/OFFされ、
シャットダウン時やスリープモード移行時にスマートプラグがOFFになれば成功です。
追加情報
本Apple ScriptをDockに表示させたくない場合は、以下を実行するとよいです。
(以下はPowerManagerAPI.appの保存場所がDocuments/scriptsの場合の例)
$ cd Documents/scripts $ plutil -insert 'LSUIElement' -bool true PowerManagerAPI.app/Contents/Info.plist
インターネットにつながらない場所では、1分おきにコマンドに失敗したというポップアップが出てしまいますが、Editを押してScript Editorを立ち上げておくと出なくなります。
このページのblife.shは、バッテリーに関する情報をまとめて表示してくれるので便利です。
$ blife.sh [2019-06-15 00:08:05] Your MacBook's Battery status is Charge Remaining 2127(mAh) State of Charge 50% Cycle Count 21 Cycle Count Remaining 979 Full Charge Capacity 4175(mAh) State of Health 96.8%
まとめ
Tuya APIを利用してスマートプラグをApple Scriptから操作し、バッテリーにやさしい充電をする仕掛けを作りました。
Tuya APIは同期版を採用していますが、ときどき通信に失敗するので、複数回トライするようにしてほぼ失敗を無くす工夫をしました。
Apple Scriptとしては、シャットダウン時やスリープ時などにも通知を利用して充電し続けない工夫をしました。
ご興味をお持ちの方のご参考になれば幸いです。
(2021年5月8日追記)
本記事の内容を7ヶ月間試した結果を以下の動画で説明していますので、よろしければご覧ください。
ただし、大きくは劣化していない、ということ以外断言できていないのですが・・・
お断り
充電度合いの測定には誤差があるのか、設定した充電範囲を多少越えることがあります。
別の観点として、常に充電状態にしておく方が充放電回数(Cycle Count)が進みづらいと書いているサイトもあるようなので、バッテリー劣化より充放電回数を重視する(売却時に参考されるため)場合、本サイトの内容は適さない可能性があります。
本サイトの内容に従って、何らかの損害が発生しても責任を負いかねますので、あくまで自己責任でお願いします。
参考文献
- 新版・中華製スマートプラグを node で制御する(https://qiita.com/plageoj/items/dd2f1c8b55c39625d550#fn1)
- MacBookのバッテリー寿命を長持ちさせる対処まとめ16選(https://www.imobie.jp/support/how-to-extend-macbook-battery-life.htm)
- ノートパソコンのバッテリーを長持ちさせる方法と、寿命を倍以上に延ばす方法(https://japan.norton.com/notepc-battery-4513)
- Smart Lifeアプリの設定と使い方。壁スマートスイッチを音声操作する為の準備(https://onogenki.com/blog/2018/10/13/smartlife/)
- APPLESCRIPT 最速基本文法マスター(https://mc909j.blogspot.com/p/document.html)
- AppleScript入門(Introduction)(http://tonbi.jp/AppleScript/Introduction/)
- awkでMacBookの電池情報を表示する(https://www.junk-works.science/awk_batterystatus/)
- AppleScriptの穴(http://piyocast.com/as/archives/5286)