はじめに
本シリーズでは,Google Apps Script (GAS) と ESP32 を使って,外出先から自宅のPCをリモートで起動する方法を紹介しています。あくまで個人的な実践経験を共有することが目的のため正確性に欠ける部分があるかもしれませんが,参考にしていただければ幸いです。
前回の振り返り
▼ 前回の投稿 yhotta240.hatenablog.com
前回は,Google Apps Script(以下GAS)を使ってプロジェクトを作成し,APIをデプロイするところまで進めました。今回は,Apps Script APIを外部から呼び出すために必要な情報と実際にAPIをどのように呼び出していくかを具体的に見ていきます。
クライアントアプリの作成
APIを呼び出す作業に入りたいところですが,まずはクライアントアプリを作成します。ここでいうクライアントアプリとは,アプリケーションやデバイスのことです。GASではHTMLを扱うことができ,PCを起動するスイッチなどを作ってもいいのですが,HTMLを書くのはちょっと面倒ですし,ファイルのアップロードができないため,ここではAppSheetを使うことにしました。AppSheetはノーコードで簡単にウェブアプリを作成できるツールです。
まず,Google Sheetsに戻り,拡張機能から「AppSheet」を選択して作成を始めます。
すると,AppSheetの編集ページが表示されます。これで基本的には完成です。AppSheetはGoogle Sheetsをデータベースとして参照し,自動的にウェブアプリを作成してくれます。非常に簡単にアプリを作成できるので非常に便利です。
アプリができたらブラウザで開いてみましょう。このアプリは自分のアカウントでログインしないと見れないので,自分だけのアプリが完成したということです。また,スマホアプリを使ってログインすれば,スマホでも同じアプリを利用できます。もちろん,値を変更してSaveするとGoogle Sheetの内容も自動的に更新されます。
これでクライアントアプリの作成は完了です。
OAuth 2.0のフロー概要
Apps Script APIを呼び出す前にOAuth 2.0について確認しておきましょう。GoogleのAPIでは認証と認可に OAuth 2.0 プロトコルを使用します。つまりAPIを呼び出すには,OAuth認証を用いて認可コードを取得し,その後アクセストークンを取得する必要があります。
まず,クライアントアプリケーションは認可サーバに対して認可コードの取得を要求します。認可サーバはユーザに対して「このクライアントアプリケーションに権限を与えてもよいですか?」と尋ねます。ユーザが「OK」を選択すると認可サーバは認可コードを発行し,クライアントアプリケーションに返します。その後,クライアントアプリケーションは取得した認可コードを用いてアクセストークンを取得します。この一連の流れがOAuth 2.0認証の基本的な流れです。
次にクライアントアプリケーションは,取得したアクセストークンを用いてリソースサーバのAPIにアクセスします。APIリクエストには,アクセストークンを含める必要があります。これにより,Apps Script APIへのアクセスが認証され,適切なデータを取得することができます。
全体の流れ
OAuth 2.0のフロー概要からAPIを利用するために必要なパラメータと,その全体的な流れを以下に整理します。必要なパラメータでは,それぞれどこで取得できるか()内に書いています。
必要なパラメータ
- クライアントID(Google Cloud Console 認証情報)
- クライアントシークレット(Google Cloud Console 認証情報)
- スコープ(Google Cloud API ドキュメント)
- リダイレクトURI(後ほど説明)
- 認可コード(OAuth 2.0 認証フロー中に取得)
- アクセストークン(OAuth 2.0 認証フロー中に取得)
- リフレッシュトークン(OAuth 2.0 認証フロー中に取得)
- 実行可能API(Google Apps Script)
流れ
Apps Script APIの概要
Apps Script APIは,GASのプロジェクトや機能に対してプログラムから操作や情報の取得を行うための仕組みです。RESTful APIという設計方式を採用しており,HTTPリクエスト(GET、POSTなど)を送信することでGASの機能を呼び出したり,プロジェクトに関する情報を取得したりできます。
主なリソースとその役割
Apps Script APIは,複数のリソース(機能のグループ)で構成されています。
- projects: スクリプトプロジェクトを操作します。
- projects.deployments: プロジェクトを「デプロイ」(公開・配布)した際の状態を管理します。
- projects.versions: プロジェクトの「バージョン」を管理します。
- processes: スクリプトの実行プロセスを管理します。
- scripts: これが最もよく使われる機能で、Apps Scriptの関数をリモートから実行するためのエンドポイントです。例えば,特定のGAS関数を外部から実行して,その結果を受け取ることができます。
今回GAS関数を外部から実行したいので scriptリソース を用います。
▼ 以下の記事でscriptsリソースについてまとめています。 zenn.dev
APIを叩いてみる
それでは実際にAPIを叩いてみましょう。ここで「APIを叩く」とは,APIを呼び出すことを意味します。いきなりESP32からAPIを呼び出すプログラムを書くのは難しいかもしれませんし,急にC++やPythonのコードが提示されても,その動作をイメージするのは難しいでしょう。
Apps Script APIはHTTP通信を使用するため,まずはインターネット環境を通じてAPIが正しく動作するかをテストする必要があります。これにより,実際のプログラムを書く前にAPIが正しく応答するか確認できるので,スムーズに開発を進めることができます。
OAuth 2.0 PlaygroundでAPIを叩く
HTTP通信のテストには,GUI(グラフィカルユーザーインターフェース)やCUI(キャラクターユーザーインターフェース)の方法があります。ここでは,OAuth 2.0 Playgroundを活用することでGUI形式で簡単にAPIをテストすることができます。
OAuth 2.0 Playgroundは,GoogleのOAuth 2.0認証フローを使用してAPIを試すためのツールです。
以下のリンクからアクセスできます:
このツールを使うことで,アクセストークンを取得し,実際にAPIリクエストを送信して応答を確認することができます。これにより,APIの動作確認やトラブルシューティングが容易になります。
まず,Google Cloud コンソールからクライアントIDとクライアントシークレットを取得します。これらは,認証情報を作成したときにメモをしていたと思います。もし忘れていた場合は,Google Cloud コンソールの「APIとサービス」> 「認証情報」のOAuth 2.0 クライアントIDを作成した場所にあります。
次に,OAuth 2.0 Playgroundの設定を開きます。「Use your own OAuth credentials」にチェックを入れると,クライアントIDとクライアントシークレットを入力する欄が表示されるので,ここにそれぞれペーストします。
その後,「Step 1 Select & authorize APIs」のセクションで,APIのスコープを選択します。スコープとは、アプリケーションがアクセスするリソースや権限を定義するものです。「Apps Script API v1」を探し,タブを開くとスコープが表示されます。そこから「https://www.googleapis.com/auth/spreadsheets」を選択し,「Authorize APIs」ボタンをクリックします。
ここで認証画面が表示され,アカウントの認証を行うはずですが,エラーが発生することがあります。
これはOAuth 2.0 Playgroundがクライアントとして機能しているため,認可サーバにそのクライアントを正しく登録していないことが原因です。
認証情報を作成する
この問題を解決するには,Google Cloud Consoleの「認証情報」セクションで「承認済みのリダイレクト URI」を設定する必要があります。
ここに「https://developers.google.com/oauthplayground」をペーストしてください。URLの最後に「/」が含まれてしまうと認証が失敗するので,その点にも注意が必要です。ユーザーが認証されると指定したリダイレクトURIにリダイレクトされ,そのページに遷移することになります。
認可コードを取得
OAuth 2.0 Playgroundに戻り,再びスコープを選択して認証を進めます。 すると,Request / Responseのところに「HTTP/1.1 302 Found」というメッセージとLocationが表示されます。そして,その下にレスポンスメッセージとして「GET」が表示されたらOKです。レスポンスには認可コードが含まれているので,これを次のステップで使用します。
アクセストークンの取得
次に,「Step 2 Exchange authorization code for tokens」のセクションに進みます。ここでは,先ほど取得した認可コードを使ってアクセストークンに交換します。「Exchange authorization code for tokens」ボタンをクリックすると,アクセストークンとリフレッシュトークンが生成されます。
- リフレッシュトークン(Refresh token):アクセストークンの有効期限が切れた後,新しいアクセストークンを取得するために使用されるトークンです。
- アクセストークン(Access token):Google APIにアクセスするためのトークンで,有効期限が約1時間(3600秒)です。
リフレッシュトークンは,アクセストークンが無効になった後でも再度新しいアクセストークンを取得するために必要です。これにより,ユーザは再認証せずにAPIを継続して利用できます。
Apps Script API の呼び出し
最後に「Step 3 Configure request to API」では,実際にAPIへHTTPリクエストを送信します。
リクエストボディの構成
リクエストボディには次のようなJSON形式でデータを記述します:
{ "function": string, "parameters": [ value ], "sessionState": string, "devMode": boolean }
HTTP リクエスト
まず,HTTP Methodを「POST」に設定します。そして,Request URIには「実行可能API」のURLを入力します。次に,「Enter request body」には,実行するGAS関数の内容をJSON形式で記述します。
たとえば,getCellValue関数を実行したい場合は以下のように記述します:
{'function': 'getCellValue'}
setCellValue関数を実行したい場合は,以下のように記述します:
{ "function": "setCellValue", "parameters": ["TRUE"], }
ここでは,パラメータとしてTRUE
やFALSE
をAPIで送信することで,GASが指定した関数を実行してGoogle Sheetsの値を更新してくれます。これにより,APIを呼び出してGoogle Sheetsのデータを操作することが可能になります。
最後に「Send request」ボタンをクリックします。レスポンスに「HTTP/1.1 200 OK」と表示されれば,リクエストは正常に送信されて処理が成功したことを示します。
そして,レスポンス内容には以下のようなJSONが表示されるはずです:
{ "done": true, "response": { "@type": "type.googleapis.com/google.apps.script.v1.ExecutionResponse", "result": false } }
この "result" の部分には,GASで定義した関数の return 値が返ってきます。たとえば,getCellValue 関数を実行した場合,Google Sheetsの特定セルの値がここに表示されるでしょう。
これで,OAuth 2.0 Playgroundを使ってAPIをHTTPで叩くテストが無事に完了しました。
CUIでAPIを叩く
CUIでAPIを叩く方法もあるので紹介しておきます。主にBashやコマンドプロンプトでリクエストを送信する際に使用します。PowerShellも使えますが,書き方が少し複雑なのでここでは省略します。
Bashやコマンドプロンプトでは,cURL(Client URL)というコマンドラインツールを使ってHTTPリクエストを送信します。cURLは非常に強力で,さまざまなプロトコルをサポートしているため,APIテストやスクリプトの一部としてよく利用されます。
新たな認証情報を作成する
まず,認可コードの取得ですが,これはcURLでは送信できないため,任意のブラウザでURLにアクセスしてリダイレクトされたページのURLから認可コードを取得します。
ただ,OAuth 2.0を使用するためにはクライアントを設定する必要があります。クライアントを設定する際に「承認済みのリダイレクト URI」を指定する必要があります。これは,ユーザーがGoogleの認証ページでログインを完了した後にリダイレクトされる先のURLです。このリダイレクトURIは事前にクライアント設定で登録しておく必要があります。
例えば,OAuth 2.0 Playgroundを使う場合は,リダイレクトURIにhttps://developers.google.com/oauthplayground
を設定しましたが,ローカル開発環境でテストを行う場合はhttp://localhost:3000
のように設定することができます。
今回の場合,クライアントはAppSheetとして既に作成してあるので,そのURLをリダイレクトURIとして使います。まず,ブラウザで開いているAppSheetのURLをコピーしてください。
例えば,以下のようなURLになっていると思います:
https://www.appsheet.com/start/***?platform=desktop#vss=*****-**-**-**
ちょっと長いURLですが,リダイレクトURIに使う部分は ?platform=desktop
の直前までの https://www.appsheet.com/start/***
の部分だけです。?platform=desktop#vss=*****-**-**-**
の部分はプラットフォーム情報なので,ここでは不要です。
そして先述の通り,Google Cloud Consoleの「認証情報」セクションで「承認済みのリダイレクト URI」を設定する必要があります。前回,認証クライアントを作成しましたが,また新しい認証クライアントIDを作成します。
適当に名前を決めて,承認済みのリダイレクト URIに https://www.appsheet.com/start/***
をペーストして追加してください。
新たなクライアントIDとクライアントシークレットも忘れずにメモしておきましょう。
認可コードを取得
設定が完了したら,そのリダイレクトURIを使って認可コードを取得します。
URLは次のようになります(わかりやすいように改行しています):
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets& access_type=offline& include_granted_scopes=true& response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=YOUR_REDIRECT_URI& prompt=consent
YOUR_CLIENT_ID
クライアンIDYOUR_REDIRECT_URI
リダイレクトURI(AppSheet)
を変更してください。
このURLにアクセスすると,Googleアカウントの認証ページが表示され,承認するとAppSheetのページにリダイレクトされるはずです。 AppSheetのURLを見てみるとこのようになっています。
https://www.appsheet.com/start/***?code=***&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets&platform=desktop#***-24-09-10
AppSheetのアプリのURLにcode=***
と
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets
が追加されていることが分かります。
このURLの中で,code=***
という部分が認可コードになります。この部分をメモしておいてください。
ちなみに認可コードを取得する際のURLでは,access_type=offline
とprompt=consent
を含めることで,リフレッシュトークンも同時に取得できます。access_type=offline
はリフレッシュトークンを取得するための設定であり, prompt=consent
はユーザーに再度同意を求めるための設定です。公式ドキュメントでは,access_type=offline
を指定することでリフレッシュトークンを取得できるとされていますが,実際にはユーザーに再度同意を求める必要があるため,少しややこしく感じるかもしれません。prompt=consent
を併せて指定することで,ユーザーに明示的に再認証を促し,確実にリフレッシュトークンを取得することができます。
アクセストークンの取得
次に,cURLを使ってアクセストークンとリフレッシュトークンを取得します。cURLはBashやコマンドプロンプトで利用できるツールです。BashはUnix系OSで広く使われており,コマンドプロンプトはWindows OSに標準で搭載されています。
今回はWindowsで作業を行っていますが,Bashを中心に説明します。Windows環境でもGit BashなどをインストールすることでBashを使うことができます。もしBashをインストールしていない場合は,Google Cloud ConsoleのCloud Shellを使って作業を行うことも可能です。
Google Cloud Consoleにアクセスし,右上のCloud Shellをアクティブにしてください。 すると,ターミナルが画面下部に表示されます。$マークの後にコマンドを入力していきます。
以下のコマンドをBashに入力して実行してください:
curl -X POST https://oauth2.googleapis.com/token \ -d code=YOUR_AUTHORIZATION_CODE \ -d client_id=YOUR_CLIENT_ID \ -d client_secret=YOUR_CLIENT_SECRET \ -d redirect_uri=YOUR_REDIRECT_URI \ -d grant_type=authorization_code
YOUR_AUTHORIZATION_CODE
先ほど取得した認可コードYOUR_CLIENT_ID
クライアント IDYOUR_CLIENT_SECRET
クライアントシークレットYOUR_REDIRECT_URI
リダイレクトURI
を変更してください。
するとこのようなJSON形式でアクセストークンとリフレッシュトークンが返されます。
{ "access_token": "ya29.***", "expires_in": 3599, "refresh_token": "***", "scope": "https://www.googleapis.com/auth/spreadsheets", "token_type": "Bearer" }
Apps Script API の呼び出し
最後に,このトークンを使用してApps Script APIを呼び出します。
リクエストボディの構成
リクエストボディには次のようなJSON形式でデータを記述します:
{ "function": string, "parameters": [ value ], "sessionState": string, "devMode": boolean }
getCellValue関数を実行したい場合
curl -X POST \ -H "Authorization: Bearer access_token" \ -H "Content-Type: application/json" \ -d '{"function": "getCellValue"}' \ https://script.googleapis.com/v1/scripts/***/run
このコマンドの説明は以下の通りです:
-X POST: POSTリクエストを送信します。
-H "Authorization: Bearer access_token"
: リクエストヘッダーにアクセストークンを指定します(access_token は実際のアクセストークンに置き換えてください)。-H "Content-Type: application/json"
: リクエストボディのデータ形式をJSONと指定します。-d '...'
: リクエストボディのデータを指定します。ここでは実行したいGAS関数をJSON形式で指定しています。https://script.googleapis.com/v1/scripts/***/run
: リクエストを送信するAPIのエンドポイントです(実行可能API)。
このコマンドを実行すると やはりOAuth 2.0 Playgroundの時と同じようになります。
{ "done": true, "response": { "@type": "type.googleapis.com/google.apps.script.v1.ExecutionResponse", "result": false } }
resultがGoogle SheetのB2の値になっていることになります。 Google Sheetの値をTRUEに変えて同じコマンドで実行してみると
{ "done": true, "response": { "@type": "type.googleapis.com/google.apps.script.v1.ExecutionResponse", "result": true } }
resultがTRUEにになることが確認できました。
このようにして,CUI環境でも簡単にAPIを叩くことができます。レスポンスとしてJSONデータが返ってくるので,そこで結果を確認することが大切です。
setCellValue関数を実行したい場合
curl -X POST \ -H "Authorization: Bearer access_token" \ -H "Content-Type: application/json" \ -d '{"function": "setCellValue","parameters": ["TRUE"]}' \ https://script.googleapis.com/v1/scripts/***/run
setCellValue関数ではパラメータを受け取る仕様にしていたので,Google Sheetのセルの値をTRUE
にしたいときパラメータ "parameters": ["TRUE"]
とし,FALSE
にしたいときは"parameters": ["FALSE"]
にします。
アクセストークンの更新
curl -X POST https://oauth2.googleapis.com/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "refresh_token=YOUR_REFRESH_TOKEN" \ -d "grant_type=refresh_token"
アクセストークンの更新についてのリクエストは,次のように実行します。YOUR_CLIENT_IDやYOUR_CLIENT_SECRET,YOUR_REFRESH_TOKENを置き換えてください。
まとめ
今回は,OAuth 2.0を使って認可コードを取得し,そのアクセストークンを使用してAPIを呼び出すテストの流れを見ていきました。次回は,ESP32を使って実際にAPIを叩き,返ってきたresultデータをもとにプログラムを動かしていく方法について説明します。