やりたいこと:宅内に温湿度センサーを設置、温湿度を計測してデータをAppSheetにアップロード、スマフォでグラフ表示する
できたこと:Google スプレッドシートに計測データ管理用のシートを作成、ダミーデータを追記、AppSheetでテーブル間のRefを設定、Viewでチャートを指定してダミーデータをグラフ化。
スプレッドシートは以下(場所情報、センサ情報、計測データを各シートに分けて管理)
AppSheetの画面は以下。凝らなければチャートを選べばサクッとグラフになる。あぁ便利
残作業と方針:マイコンからどうにかしてAppSheetにデータを書き込みたい。スプレッドシートAPIはややこしいのでマイコンからは直接アクセスせず、GoogleのCloud Functionsで簡易的なWebAPIを作って、マイコンからは左記の簡易版WebAPIを叩いてAppSheetにデータをPOSTする*1
GCPの環境からSpreadSheetにアクセスするので、できたらIAMロールで権限管理したい(アカウント認証用の鍵が不要になるから)。実装サンプルにはアカウントに紐づいた権限ファイルを指定するようになっている。
IAMベストプラクティスを確認したが、IAM Roleだけで管理する方法は提示されておらず、サービスアカウントを作って、最小限の権限を与えるような説明。だから、、例に倣って、サービスアカウントを作ることにする。サンプルを見ていると、サービスアカウントにOwner権限を設定しているような。。権限が強すぎるのではなかろうか。
サービスアカウントを作る作業を始めると、「App EngineやCloud Functions」で使うのか?と選択があり、「Functionsで使う」を選ぶと「認証情報の自動検出が使えるので認証情報のファイルは要らないでしょ」と作られなかった。いわゆる、Cloud FunctionsにIAMロールが割り当てられたということだろうか。デフォルト認証方式(ADC)というらしい。余計なファイルを管理するのは漏洩リスクがあるので、IAMロールで?許可してもらえるのはありがたい。ただし、、よく見るサンプルは認証用ファイルを読み込ませているパターンであり、ファイルを指定しない方法に変更しないといけない。
Authenticating as a service account | Authentication | Google Cloud
認証処理をすっ飛ばして以下のコードでSpreadSheetsにアクセスしたら、権限異常のエラーになった。やっぱり許可されていないようだ
service = build('sheets', 'v4') # , credentials=creds
sheet = service.spreadsheets()
result = sheet.values().get(spreadsheetId=SPREADSHEET_ID,range=RANGE_NAME).execute()
print(result)
エラー内容
HttpError(resp, content, uri=self.uri) googleapiclient.errors.HttpError: <HttpError 403 when requesting https://sheets.googleapis.com/v4/spreadsheets/1gBvm-Ku1xxxxxxxxxxxxxxKCseM/values/%E3%82%BB%E3%83%B3%E3%82%B5%5B%21A1%3AB1%5D?alt=json returned "The caller does not have permission". Details: "The caller does not have permission">
エラーを見ていると、GCP内でサービス間接続ではなく、一般権限しかないClientが普通に正面からアクセスしているだけのように思えるのだが。。
ADCが動かないのだが?といったQA
python - Use Application Default Credentials on Google Compute Engine to access Sheets API - Stack Overflow
AIP-4110: Application Default Credentials
AIP-4115: Default Credentials From Google Virtual Machines
Google Cloud Platform Japan 公式ブログ: Application Default Credentials による Google Cloud API で認証設定をシンプルに
Credential credential = GoogleCredential.getApplicationDefault();
権限エラーが解消できず、ADCの設定がおかしいのか、Sheetsへのアクセスがおかしいのかどちらが原因かわからない。だから、、認証キーを生成して、GCP外からアクセスして、正しくアクセスできるのを確認してから、GCP内で同一リソースにアクセスするアプローチの方がいいのではないか。
ADC解説記事
GCP の Application Default Credentials を使った認証 - ぽ靴な缶
■補足
記事を読んでると、他の方々はgcloud CLIを使って動作確認をしているようだ。gcloud CLIとは何なのか詳細不明だが、テストのたびにデプロイしていたら時間がかかってしょうがないので、自分もgcloud CLI を調べて使えるようにセットアップしたい。
gcloud ツールのクイック リファレンス | Cloud SDK のドキュメント | Google Cloud
■ご参考URL
A Guide on Google Sheets with Python API using Google Cloud Platform
Google Spreadsheets and Python