前回までで、EcoFlowのポータブル電源 と Nature Remo E lite を組み合わせることで、卒FIT後の太陽光発電システム(ソーラーパネル)で発電した余剰電力だけを自動でポータブル電源に充電することが出来る、という部分を解説しました。
ここまでで既に、自動で余剰電力(本来売電するはずだった電気)のみをポータブル電源に充電するプログラムは組み上げることが出来るはずですので、タイトルにある ポータブル電源自動充電システム としては最低限のことは実現出来ています。
ただし充電ではなく放電のほうにはまだ問題があり、今回は パススルー問題解決編 と題して解説します。
ちなみにポータブル電源自動充電システムのシステム構成とメリット・デメリットについては、以下の記事で紹介しています。
ポータブル電源自動充電システムにおけるパススルー問題
ポータブル電源の中には、パススルー充電という機能を備えたものがあります。
パススルー充電に対応したポータブル電源の場合、ポータブル電源をACコンセントに接続した状態で利用すると、ポータブル電源への充電と、ポータブル電源から家電製品への出力を同時に行うことが出来ます。
また、ポータブル電源の充電とポータブル電源に繋いだほかの機器の充電を同時に行うことも出来ます。
このパススルー充電機能は、ポータブル電源本来の利用を考えた場合にはとても重要(必要)な機能の一つです。
ただし私のようにポータブル電源を家庭用蓄電池の代わりとして使用する場合には、このパススルー機能があることで困ったことが起こります。
卒FIT後、太陽光発電システムで発電した電気が余っているとき(余剰電力がある ≒ 売電する電気がある)には、その電気を使ってポータブル電源を充電し かつ 他の機器への電力供給も行えるため全く問題ありません。
問題なのは、曇や雨の日 または 夜間など、余剰電力が無くて電力会社から電気を買わないといけない場合です。
このケースではポータブル電源の充電設定はOFFにし、充電は行われないのですがポータブル電源はACコンセントに接続されたままなのでパススルー機能は有効です。
この状態でポータブル電源に繋いだ家電製品を利用した場合、バッテリーにためた電気は利用されず、パススルー機能によりコンセントから供給された電気で家電製品を動かしてしまいます。
曇や雨の日 または 夜間の場合には、ポータブル電源に貯めた余剰電力を利用したいにも関わらず、パススルー機能があるせいで電力会社から電気を買ってしまうということです。
今回紹介しているポータブル電源自動充電システムでは、家庭で発生する余剰電力を自動で充電するためにポータブル電源は常にACコンセントに接続しておく必要があり、パススルー機能が有効になってしまうのです…
残念ながら私が利用しているポータブル電源(DELTA 2 MAX)の設定ではパススルー機能をOFFにすることは出来ませんでした。
そこで解決策としてスマートプラグを利用することにしました。
スマートプラグであれば遠隔でACコンセントの通電ON/OFFを切り替えられるため、ポータブル電源の充電をOFFにするのと同時に、ACコンセントの通電もOFFにしてしまえばパススルーされることも無くなると考えました。
以下のイメージの通り、余剰電力を充電する場合にはACコンセントの通電をONにして、ポータブル電源の充電とパススルーによる他の機器への電力供給を行います。
曇や雨の日 または 夜間の場合には、ポータブル電源の充電をOFFにするのと同時に、ACコンセントの通電もOFFにします。
当然ですがパススルー機能は動作せず、ポータブル電源に繋いだ機器は、ポータブル電源のバッテリーから供給された電気で動作します。
(これであれば昼間に貯めた余剰電力を利用して、夜間に家電製品を利用する事ができます)
SwitchBotプラグミニ とは
今回、パススルー問題を解決するために選んだスマートプラグは、SwitchBotのプラグミニ(JP)という製品です。
スマートプラグは各社から色々なものが発売されていますが、ポータブル電源自動充電システムで利用するためには、プログラム上から操作出来る製品である必要がありました。
SwitchBotであれば SwitchBotAPI というAPIが提供されていますので、プログラム上からON/OFFの制御が可能です。
SwitchBotアプリへの追加
SwitchBotプラグミニ(JP)を利用するためには、まずSwitchBotアプリをスマートフォンにインストールし、アプリ上にプラグミニを追加してあげる必要があります。
SwitchBotアプリをインストールしてSwitchBotのアカウント登録を行ったら、以下のイメージの順でスマートプラグ(プラグミニ)を追加してください。
上記のイメージ以降は、アプリ上の説明に従って追加を完了させてください。
プラグミニの追加が終わると、アプリ上から通電のON/OFFが行え用になるはずです。
トークンの発行
SwitchBotをプログラム上から利用するためにはSwitchBotAPIで利用するトークンとクライアントシークレットを発行する必要があります。
getting-started
SwitchBotApi
トークンとクライアントシークレットの発行は、SwitchBotアプリから行うことが出来ます。
手順は以下の通りとなっています。
- Step1設定画面の表示
SwitchBotアプリのプロフィールから設定画面を表示します。
- Step2アプリバージョンの表示
基本データをタップしてアプリバージョンを表示します。
- Step3開発者向けオプションの有効化
表示されたアプリバージョンを10回連続でタップすることで、開発者向けオプションが有効になります。
- Step4トークン及びクライアントシークレットの取得
「トークンを取得」をタップしてトークンとクライアントシークレットを発行します。
- Step5トークン及びクライアントシークレットの確認
SwitchBotアプリ上に発行されたトークンとクライアントシークレットが表示されます。
公式ドキュメント
SwitchBotAPIの公式ドキュメントは以下になります。
以降はこの公式ドキュメントに従い、順に以下の各API(リクエスト)について解説します。
Google Apps Script(GAS)でコーディング
SwitchBotプラグミニ(スマートプラグ)のデバイスID取得
SwitchBotAPIを利用してプログラム上からプラグミニ(スマートプラグ)の通電をON/OFFするためには、そのプラグミニ(スマートプラグ)に割り当てられたデバイスIDを指定してAPIへのリクエストを行う必要があります。
ですのでまずはデバイスIDを取得するためのAPIを実行します。
コードは以下になります。
ここではデバイスIDを取得したいだけですので、一度実行してデバイスIDが取得できたら以降は実行する必要はありません。
function sbDeviceList() {
// ① リクエストURL
const host = "https://api.switch-bot.com";
let requestUrl = host + "/v1.1/devices";
// ② トークンとクライアントシークレット
const token = "※SwitchBotアプリで発行したトークン";
const secret = "※SwitchBotアプリで発行したクライアントシークレット";
// ③ nonceとタイムスタンプを生成
let nonce = Utilities.getUuid();
let timestamp = String((new Date).getTime());
// ④ 署名用パラメータ
let signVal = token + timestamp + nonce;
// ⑤ 暗号化して16進文字列(大文字)に変換
let signature = Utilities.computeHmacSha256Signature(signVal, secret);
let sign = Utilities.base64Encode(signature).toUpperCase();
// ⑥ リクエストヘッダー
let requestHeaders = {
"Authorization": token,
"sign": sign,
"nonce": nonce,
"t": timestamp
}
// ⑦ リクエストオプション
let requestOptions = {
"method" : "GET",
"contentType": "application/json",
"headers" : requestHeaders,
"muteHttpExceptions" : true,
}
// ⑧ API実行(SwitchBotOpenApiへのリクエスト)
let response = UrlFetchApp.fetch(requestUrl, requestOptions);
// ⑨ 結果(レスポンス)を取得
let responseCode = response.getResponseCode();
let responseText = response.getContentText();
// ⑩ ログ出力
Logger.log("responseCode=" + responseCode);
Logger.log(JSON.stringify(JSON.parse(responseText), null, 2));
}
コードの解説
コードの内容をそれぞれ解説していきます。
// ① リクエストURL
const host = "https://api.switch-bot.com";
let requestUrl = host + "/v1.1/devices";
SwitchBotAPIにリクエストするためのURLを定義しています。
// ② トークンとクライアントシークレット
const token = "※SwitchBotアプリで発行したトークン";
const secret = "※SwitchBotアプリで発行したクライアントシークレット";
トークンとクライアントシークレットの定義になります。
SwitchBotアプリにて発行したトークンとクライアントシークレットをここに設定してください。
// ③ nonceとタイムスタンプを生成
let nonce = Utilities.getUuid();
let timestamp = String((new Date).getTime());
③ではnonceとtimestampの作成を行っています。
順に見ていきましょう。
- Code1Utilities.getUuid()
GoogleAppScriptで提供されているUtilitysクラスを利用して乱数を生成しています。
- Code1new Date
システム日時(現在日時)で日付オブジェクトを作成しています。
- Code2(new Date).getTime()
上記Code1で作成した日付オブジェクトに対してgetTime()することで、システム日時(現在日時)のミリ秒を取得しています。
- Code3String((new Date).getTime())
最後にString()で文字列に変換してtimestampは完成です。
- Qnonceとは?
- A
nonceとは、ノンス/ナンスと呼ばれます。
API呼び出し時に一度だけ有効な任意の値(乱数)になります。
SwitchBotAPIのドキュメントでは 「署名する文字列に組み込むために開発者自身が生成したランダムなUUID」と記載されています。
セキュリティ保護のためにAPIにリスエストする都度、新たな乱数を採番します。
- Qtimestampとは?
- A
名前の通りタイムスタンプ(現在日時)になります。
1970年1月1日00:00:00UTCからの経過ミリ秒数を設定します。
// ④ 署名用パラメータ
let signVal = token + timestamp + nonce;
④ではトークン および ③の手順で作成したタイムスタンプとナンスを文字列連結し、署名用のパラメータ文字列としています。
// ⑤ 暗号化して16進文字列(大文字)に変換
let signature = Utilities.computeHmacSha256Signature(signVal, secret);
let sign = Utilities.base64Encode(signature).toUpperCase();
ここでは署名用パラメータを暗号化して、署名(署名値)を作成しています。
GoogleAppScriptで提供されているUtilitysクラスを利用して変換を行っています。
一旦はお決まりとして「こういうものなんだなー」と思っていただければOKかと思います。
// ⑥ リクエストヘッダー
let requestHeaders = {
"Authorization": token,
"sign": sign,
"nonce": nonce,
"t": timestamp
}
SwitBotAPIにリクエストするためのHTTPヘッダーを作成しています。
SwitBotAPIではHTTPヘッダーに以下を設定してAPIを呼び出すルール(仕様)になっています。
- トークン(token)
- 署名(sign)
- ナンス/ノンス(nonce)
- タイムスタンプ(timestamp)
// ⑦ リクエストオプション
let requestOptions = {
"method" : "GET",
"contentType": "application/json",
"headers" : requestHeaders,
"muteHttpExceptions" : true,
}
こちらはリクエストのオプション設定になります。
メソッドはGET、⑥で作成したリクエストヘッダーを設定しています。
他、以下の指定はおまけ程度です(とりあえず無くても動くと思います)
- muteHttpExceptions
trueを指定することで、HTTPリクエスト時のエラー(例外)を抑制するオプションです。
※すべての例外を抑制できるわけではないという事と、例外が発生しないだけでエラー処理が不要になる訳では無い(本来は適切にエラー処理が必要)というところは注意が必要です。
// ⑧ API実行(SwitchBotOpenApiへのリクエスト)
let response = UrlFetchApp.fetch(requestUrl, requestOptions);
ここでは実際にAPI(SwitBotAPIへのリクエスト)の実行を行っています。
UrlFetchApp.fetch()を呼び出すことで、実際の通信が行われ、結果のレスポンスがresponse(変数)に格納されます。
// ⑨ 結果(レスポンス)を取得
let responseCode = response.getResponseCode();
let responseText = response.getContentText();
ここではHTTPステータスとAPIの実行結果レスポンスをそれぞれ変数に格納しています。
// ⑩ ログ出力
Logger.log("responseCode=" + responseCode);
Logger.log(JSON.stringify(JSON.parse(responseText), null, 2));
ここで一旦、HTTPステータスとAPIの実行結果をログに出力しています。
コード実行
コーディングを行ったら、変更を保存(フロッピーのアイコンをクリック)してから実行してみてください。
以下のような結果がレスポンスとして返ってくると思います。
結果レスポンスに記載の deviceId を以降のAPI実行で利用します。
- Q実行時に「認証が必要です」「このアプリはGoogleで確認されていません」といったセキュティの警告が表示される場合は?
- A
Google Apps Script(GAS)では、プログラムの初回実行時などに「認証が必要です」や「このアプリはGoogleで確認されていません」といったセキュリティの警告が出ることがあります。
今回のソースコードでは、外部サービス(SwitchBotAPI)に接続しようとしているため、その外部サービスに接続して本当に大丈夫ですか?安全ですか?とGoogleから確認されている状態です。
あなた自身がソースコードを理解し、外部サービス(SwitchBotAPI)に接続して問題ないと判断したのであれば以下の手順に従って、プログラムの実行を承認(許可)してください。
脅すわけではありませんが、これはセキュリティ警告です。
記事に記載してあるソースコードを鵜呑みにせず、必ずご自身で理解し、問題ないことを確認の上で『承認(許可)』の操作をお願いします。
SwitchBotプラグミニ(スマートプラグ)のリアルタイム情報取得
次に、プラグミニ(スマートプラグ)の状態を取得するAPIリクエストの方法を紹介します。
このプログラムを実行することで、スマートプラグの通電がONなのかOFFなのか、ONであればどれだけの電気を利用しているのか、などのリアルタイム情報を取得することが出来ます。
コードは以下のとおりです。
function sbDeviceStatus() {
// ① リクエストURL
const host = "https://api.switch-bot.com";
const deviceId = "※上記のデバイスIDの取得で取得したデバイスID";
let requestUrl = host + "/v1.1/devices/" + deviceId + "/status";
// ② トークンとクライアントシークレット
const token = "※SwitchBotアプリで発行したトークン";
const secret = "※SwitchBotアプリで発行したクライアントシークレット";
// ③ nonceとタイムスタンプを生成
let nonce = Utilities.getUuid();
let timestamp = String((new Date).getTime());
// ④ 署名用パラメータ
let signVal = token + timestamp + nonce;
// ⑤ 暗号化して16進文字列(大文字)に変換
let signature = Utilities.computeHmacSha256Signature(signVal, secret);
let sign = Utilities.base64Encode(signature).toUpperCase();
// ⑥ リクエストヘッダー
let requestHeaders = {
"Authorization": token,
"sign": sign,
"nonce": nonce,
"t": timestamp
}
// ⑦ リクエストオプション
let requestOptions = {
"method" : "GET",
"contentType": "application/json",
"headers" : requestHeaders,
"muteHttpExceptions" : true,
}
// ⑧ API実行(SwitchBotOpenApiへのリクエスト)
let response = UrlFetchApp.fetch(requestUrl, requestOptions);
// ⑨ 結果(レスポンス)を取得
let responseCode = response.getResponseCode();
let responseText = response.getContentText();
// ⑩ ログ出力
Logger.log("responseCode=" + responseCode);
Logger.log(JSON.stringify(JSON.parse(responseText), null, 2));
}
コードの解説
上記で紹介した デバイスID取得 と違うところはリクエストURLのみになります。
// ① リクエストURL
const host = "https://api.switch-bot.com";
const deviceId = "※上記のデバイスIDの取得で取得したデバイスID";
let requestUrl = host + "/v1.1/devices/" + deviceId + "/status";
SwitchBotAPIにリクエストするためのURLを定義しています。
デバイスID取得 のAPIで取得したデバイスIDをここに設定してください。
コード実行
コーディングを行ったら、変更を保存(フロッピーのアイコンをクリック)してから実行してみてください。
以下のような結果がレスポンスとして返ってくると思います。
結果レスポンスに記載の power が on であれば通電中、off であれば通電していないことを表しています。
また weight の値が利用している電力(W)になります。
SwitchBotプラグミニ(スマートプラグ)のON/OFF切り替え
最後に、プラグミニ(スマートプラグ)のON/OFFをプログラム上から変更するAPIリクエストの方法を紹介します。
このプログラムを実行することで、実際にスマートプラグの設定を切り替えることが出来ます。
コードは以下のとおりです。
function sbPlugCommand() {
// ① リクエストURL
const host = "https://api.switch-bot.com";
const deviceId = "※上記のデバイスIDの取得で取得したデバイスID";
let requestUrl = host + "/v1.1/devices/" + deviceId + "/commands";
// ② トークンとクライアントシークレット
const token = "※SwitchBotアプリで発行したトークン";
const secret = "※SwitchBotアプリで発行したクライアントシークレット";
// ③ nonceとタイムスタンプを生成
let nonce = Utilities.getUuid();
let timestamp = String((new Date).getTime());
// ④ 署名用パラメータ
let signVal = token + timestamp + nonce;
// ⑤ 暗号化して16進文字列(大文字)に変換
let signature = Utilities.computeHmacSha256Signature(signVal, secret);
let sign = Utilities.base64Encode(signature).toUpperCase();
// ⑥ リクエストヘッダー
let requestHeaders = {
"Authorization": token,
"sign": sign,
"nonce": nonce,
"t": timestamp
};
// ⑦ リクエストオプション
let requestOptions = {
"method": "POST",
"contentType": "application/json",
"headers": requestHeaders,
"payload": JSON.stringify({
'command': "turnOn" // ※スマートプラグをONにする場合は"turnOn"、OFFにする場合は"turnOff"
}),
"muteHttpExceptions" : true,
};
// ⑧ API実行(SwitchBotOpenApiへのリクエスト)
let response = UrlFetchApp.fetch(requestUrl, requestOptions);
// ⑨ 結果(レスポンス)を取得
let responseCode = response.getResponseCode();
let responseText = response.getContentText();
// ⑩ ログ出力
Logger.log("responseCode=" + responseCode);
Logger.log(JSON.stringify(JSON.parse(responseText), null, 2));
}
コードの解説
コードの内容をそれぞれ解説していきます。
上記で紹介した デバイスID取得 と違うところのみ記載します。
// ① リクエストURL
const host = "https://api.switch-bot.com";
const deviceId = "※上記のデバイスIDの取得で取得したデバイスID";
let requestUrl = host + "/v1.1/devices/" + deviceId + "/commands";
SwitchBotAPIにリクエストするためのURLを定義しています。
デバイスID取得 のAPIで取得したデバイスIDをここに設定してください。
// ⑦ リクエストオプション
let requestOptions = {
"method": "POST",
"contentType": "application/json",
"headers": requestHeaders,
"payload": JSON.stringify({
'command': "turnOn" // ※スマートプラグをONにする場合は"turnOn"、OFFにする場合は"turnOff"
}),
"muteHttpExceptions" : true,
};
SwitchBotAPIにリクエストするためのオプションの定義になります。
デバイスID取得 と違うところはmethodが POST になっている部分と、payload でOn/Offのコマンドを設定しているところになります。
コメントの通り command には、スマートプラグをONにする場合は“turnOn”、OFFにする場合は“turnOff”を設定してください。
コード実行
コーディングを行ったら、変更を保存(フロッピーのアイコンをクリック)してから実行してみてください。
以下のような結果がレスポンスとして返ってくると思います。
結果レスポンスに記載の power の on/off にて、設定が正しく切り替わっていることが確認できるはずです。
(スマートフォンのSwitchBotアプリでも設定が切り替わったことは確認できます)
まとめ
お疲れ様でした。
これでプログラム上から任意のタイミングでACコンセントのON/OFFを切り替えることが出来るようになりました。
悪天候時や夜間などポータブル電源に充電を行わない時にはスマートプラグ(ACコンセント)の通電をOFFにしておくことで、冒頭で説明したパススルー問題を回避することが可能になります。
逆にポータブル電源のバッテリーが無くなりそうだけど、余剰電力も無く充電を行えない場合には、ポータブル電源の充電設定はOFFにした状態で、スマートプラグ(ACコンセント)の通電のみをONにすることで、以降はポータブル電源のバッテリーを消費すること無く、パススルーで商用電源を利用するような制御も可能です。
これで自動充電システム(プログラム)を構築してしまえば、ポータブル電源を家庭用蓄電池の代わりとして十分利用することが出来ると思います。