SORACOM 、使ってますか?
製造業のお偉いさんが『やれ IoT だ!』『やれ プラットフォームだ!』と騒いだ後、キャッチアップされる担当の人は一度は見聞きしたことがあるサービスかと思います。
SORACOM は、ソフトウェア・ハードウェアのどちらのエンジニアにも『IoT の入り口』として良いサービスです。また、精力的にハンズオンやカンファレンス、セミナーなどを開催されていて、ユーザーグループなどのコミュニティも活発とのことです。
TL;DR
- GAS で SORACOM API を使うなら認証や API を叩く処理は汎用ライブラリを使うことで楽ができる
- 汎用ライブラリの API ID は
MJlievwjcIu8-7grDZqGf-FSucpP_quDO
- GAS のスクリプトプロパティに SORACOM の SAM ユーザー認証情報を設定すれば使うことができる。
- 自分の GAS のプロジェクトに
getAccessToken
関数の作成は必要(当記事のテンプレをコピペ)
この記事の内容
タイトルの通りです。Google Apps Script(以下、GAS)から SORACOM API を実行するための汎用ライブラリの使い方を説明します。
おまけとして Google Spreadsheets(以下、Spreadsheets)へ出力する方法も記載します
本記事の対象読者
- SORACOM で使う SIM や Inventory の Device、Sigfox Device 等々の情報が増えてきた or 今後増えそう
- GAS から SORACOM API をもっと簡単に使いたい
- ついでに Spreadsheets へ出力してごにょごにょしたい
経緯
弊社の関連会社が提供しているサービスで一部 SORACOM (Air, Harvest, Gate)を利用しております。SIM やデバイス、デバイスから取得したデータなどの管理は、数が少ないときは無料で提供されている SORACOM User Console で事足りるのですが数が多くなるに連れて全件を一覧で見たい 、データを別の形に加工したいといったニーズが出てきました。
具体的には、
- 登録されているグループや SIM の一覧を取得したり、
- Harvest に登録されたデータを取得したり、
- 閉域網(VPG)で遠隔操作するための簡易的な Web ページを作ったり
などです。
対応する方法としては、SORACOM とサードパーティのサービスを連携することで実現することもできるかもしれませんが、SORACOM では API が公開されているので、手っ取り早く無料でできる方法として GAS を使うことにしました。
ここで問題が。
処理ごとにスクリプトを分けると認証処理やAPIを叩くための関数をコピペするようになりました。これではメンテナンス性が悪く DRY(Don't repeat yourself)的にモヤるので汎用ライブラリとして切り出しました。実際に使ってみたところ(当然)コードの量も減り使い勝手が向上したので、同じように困っている人がいるかもしれないと考え、汎用ライブラリの使い方を公開しようと考えました。
SORACOM のAPIをGASから使うための認証処理(samUserAuthentication)とAPIを叩くための汎用処理(api)のライブラリ作った。需要があるかわからないけどQiitaに記事でも書こうかしらん
— takeru oyama (@takeru08ma) 2019年4月23日
一点補足しておきますと、SORACOM の API リファレンスは非常に丁寧に記載されており、API の基礎的なところが押さえられている人であればドキュメントを見て大体何ができるのかがすぐに分かります。この汎用ライブラリは単にAPI を使うための手続きを簡素化しただけなので自前で作れる人に対しては釈迦に説法になるかもしれません。
汎用ライブラリの使い方
使い方の前にまず事前準備からはじめます。既に準備が整っている場合は読み飛ばしてください。
事前準備
1. SORACOM のアカウントを取得
公式に説明を譲ります。
SORACOM アカウントの作成
2. SAM ユーザーを作成
公式に説明を譲ります。
SAM ユーザーの作成と認証設定
説明中に認証キーの設定の項がありますが、汎用ライブラリを使う上では必須ではないので実施しなくても問題ありません。
3. SAM ユーザーの権限を設定
公式の説明に設定方法が記載されています。
SAM ユーザーの権限設定
権限の設定方法は、
- ロールに権限を設定してから、ユーザーにロールを設定するか、
- ユーザーに直接指定で設定するか
の 2種類ありどちらでも問題ありません。ここでは後者の直接指定を行っています。
※補足
使用したい API や HTTP メソッドを絞った方が良いのですが、ここではひとまず全て使える状態で進めます。
4. GAS を利用可能にする
GAS を導入する方法はググれば腐るほど記事が出てきますが、念の為掲載しておきます。
- Google Drive を開く
-
新規
→その他
→アプリを追加
-
Google Apps Script
で検索し、ヒットしたら接続
を選択 -
Google ドライブに接続されました。
という説明が表示されれば OK。 - 改めて
新規
を選択するとGoogle Apps Script
が表示され、選択すれば無題のプロジェクト
(新規の GAS)が作成されます。
汎用ライブラリの使い方
1. GAS で汎用ライブラリを読み込む
- GAS のプロジェクトを開く
- メニューの
リソース
→ライブラリ
を選択 -
ライブラリを追加
と記載されているフォームに汎用ライブラリの API IDMJlievwjcIu8-7grDZqGf-FSucpP_quDO
を入力して追加
-
バージョン
でSORACOM API 汎用ライブラリ
を選択して保存
汎用ライブラリが正常に読み込めていると GAS のコードで識別子+ドット(Soracom.
)まで入力すると、使用可能な関数の選択肢(samUserAuthentication
や api
)が表示されるようになります。
2. GAS のスクリプトプロパティに SORACOM の SAM ユーザー認証情報を設定
基本的に、ユーザーアカウントや認証に必要な情報(API のキーやトークン)をハードコーディングすることは大変危険です。万が一情報が漏れてしまった場合、第三者が自由にアクセスできてしまうリスクは言うまでもないと思います。なので汎用ライブラリでは SORACOM の SAM ユーザーアカウントの情報を GAS のスクリプトプロパティに設定して使用します。
- GAS のプロジェクトを開く
- メニューの
ファイル
→プロジェクトプロパティ
を選択 -
スクリプトのプロパティ
タブを選択 -
SORACOM_SAM_USERNAME
には SORACOM User Console で作成した SAMユーザー名を設定 -
SORACOM_SAM_PASSWORD
には SAM ユーザーのパスワードを設定 -
SORACOM_OPERATORID
には SORACOM User Console にログインするアカウントのオペレーターID(OPxxxxxxxxxx
)を設定
3. GAS のプロジェクトに getAccessToken
関数を作成
下記のコードを コード.gs
に追加します。
function getAccessToken() {
var apiInfo = Soracom.samUserAuthentication({
"operatorId": PropertiesService.getScriptProperties().getProperty("SORACOM_OPERATORID"),
"userName": PropertiesService.getScriptProperties().getProperty("SORACOM_SAM_USERNAME"),
"password": PropertiesService.getScriptProperties().getProperty("SORACOM_SAM_PASSWORD"),
"apiTokenIssued": PropertiesService.getUserProperties().getProperty("SORACOM_API_TOKEN_ISSUED")
});
if (apiInfo !== true) {
Logger.log("New token");
PropertiesService.getUserProperties().setProperty("SORACOM_API_KEY", apiInfo.apiKey);
PropertiesService.getUserProperties().setProperty("SORACOM_API_TOKEN", apiInfo.token);
PropertiesService.getUserProperties().setProperty("SORACOM_API_TOKEN_ISSUED", apiInfo.dateAndTime); // YYYY/MM/DD HH:mm:ss
return {
"key": apiInfo.apiKey,
"token": apiInfo.token
};
}
else {
Logger.log("Exist token");
return {
"key": PropertiesService.getUserProperties().getProperty("SORACOM_API_KEY"),
"token": PropertiesService.getUserProperties().getProperty("SORACOM_API_TOKEN")
};
}
}
4. API を叩いてデータを JSON で取得
関数 myFunction
に汎用ライブラリで SORACOM API を叩く処理を書きます。ここでは、API リファレンスの listGroups を使って Group の一覧を返しています。
function myFunction() {
var api = getAccessToken();
var listGroups = Soracom.api({
"apiKey": api.key,
"apiToken": api.token,
"httpMethod": "get",
"subDirectory": "/v1/groups",
});
Logger.log(listGroups);
}
関数 myFunction
を選択して実行します。
GAS の初回実行時はアクセス権の承認を求められますので、GAS を使用している Google アカウントで許可します。
実際にデータが取得できたのか確認してみます。
メニューから 表示
→ ログ
を選択。(Ctrl
+ Enter
でも可)
上記画像の青くマスクしているところに Group の一覧が JSON 形式で表示されます。
New Token
と表示されている通り、新規でトークンを取得しています。
Soracom.samUserAuthentication
の処理内容
var apiInfo = Soracom.samUserAuthentication({
"operatorId": PropertiesService.getScriptProperties().getProperty("SORACOM_OPERATORID"),
"userName": PropertiesService.getScriptProperties().getProperty("SORACOM_SAM_USERNAME"),
"password": PropertiesService.getScriptProperties().getProperty("SORACOM_SAM_PASSWORD"),
"apiTokenIssued": PropertiesService.getUserProperties().getProperty("SORACOM_API_TOKEN_ISSUED")
});
- 内部的には認証するための auth の API を呼び出し、SAM ユーザーの情報で API Key と API Token を取得しています。
- 引数
operatorId
、userName
、password
は API を使うための API Key と API Token を取得するためのものです。 - 引数
apiTokenIssued
は API のトークンを取得した時間を保持しています。API の仕様としては最大 48時間の有効期限を設定できるのですが、汎用ライブラリでは 24時間(tokenTimeoutSeconds
=86400
)に設定しており、GAS のユーザープロパティに保存します。有効期限内に再度 API を使う場合はユーザープロパティに保持した API Key と API Token を使い回し、(24時間以内ではなく)23時間を経過している場合は新たに API Key と API Token を取得します。
Soracom.api
の処理内容
var listGroups = Soracom.api({
"apiKey": api.key,
"apiToken": api.token,
"httpMethod": "get",
"subDirectory": "/v1/groups",
});
- 引数
apiKey
、apiToken
には SORACOM API を使うために必要な情報(HTTP ヘッダーに設定する API Key と API Token)を設定します。 - 引数
httpMethod
使用したい API の HTTP メソッドを設定します(例:get
、post
、put
、delete
) - 引数
subDirectory
使用したい API のパスを設定します(例:/v1/groups
)- API のバージョンが
v1
じゃなくなったら... っていうのはまだ考えてないです
- API のバージョンが
-
Soracom.samUserAuthetication
では内部的には認証するための auth の API を呼び出し
と記載しましたが、このauth
の API の HTTP メソッドはpost
です。この場合は引数requestBody
を追加し、HTTP メソッドがpost
の場合のみ JSON でリクエストしたいパラメータを設定します。
var apiInfo = api({
"httpMethod": "post",
"subDirectory": "/v1/auth",
"requestBody": {
"operatorId": options.operatorId,
"userName": options.userName,
"password": options.password,
"tokenTimeoutSeconds": 86400
}
});
5. (おまけ)Spreadsheets にグループと SIM の一覧を出力
自身が使用している SORACOM の Group と SIM の情報を Spreadsheets に出力します。
Spreadsheets(テンプレート)をコピーしてマイドライブに追加
SORACOM から取得したデータを出力するための Spreadsheets(テンプレート) を、閲覧のみ可能な状態で公開しております。
- Spreadsheets(私が公開しているテンプレート) を開きます。
- メニューの
ファイル
→コピーを作成
を選択 - 適当なファイル名で
OK
を選択 - すると、マイドライブの配下にコピーされます。
コピーした Spreadsheets の ID を GAS のスクリプトプロパティに追加
Spreadsheets の ID
とは Spreadsheets の URI に記載されています。
例:
https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit#gid=0
の xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
の部分です。
コピーして先ほどの GAS のプロジェクトを開き、スクリプトプロパティに SORACOM_TABLE_ID
という名前で設定します。
SORACOM の Group と SIM の情報を Spreadsheets に出力するコードを追加
コード.gs
に下記のコードを追加。
function setGroup(groups) {
var sheet = SpreadsheetApp.openById(
PropertiesService.getScriptProperties().getProperty("SORACOM_TABLE_ID")
).getSheetByName("listGroups");
sheet.getRange("A2:D201").setValue("");
groups.forEach(function (values, index) {
var rowIndex = index + 2;
sheet.getRange("A" + rowIndex + ":D" + rowIndex).setValues([[
(rowIndex - 1),
values.operatorId,
values.groupId,
values.tags.name
]]);
});
}
function setSubscriber(subscribers) {
var sheet = SpreadsheetApp.openById(
PropertiesService.getScriptProperties().getProperty("SORACOM_TABLE_ID")
).getSheetByName("listSubscribers");
sheet.getRange("A2:M1001").setValue("");
subscribers.forEach(function (values, index) {
var rowIndex = index + 2;
sheet.getRange("A" + rowIndex + ":M" + rowIndex).setValues([[
(rowIndex - 1),
values.operatorId,
values.groupId,
values.imsi,
values.tags.name ? values.tags.name : "",
values.status,
values.sessionStatus.online,
values.ipAddress,
values.iccid,
values.serialNumber,
values.subscription,
values.speedClass,
values.moduleType
]]);
});
}
関数 myFunction
を下記のように書き換えます。
function myFunction() {
var api = getAccessToken();
var listGroups = Soracom.api({
"apiKey": api.key,
"apiToken": api.token,
"httpMethod": "get",
"subDirectory": "/v1/groups",
});
setGroup(listGroups);
var listSubscribers = Soracom.api({
"apiKey": api.key,
"apiToken": api.token,
"httpMethod": "get",
"subDirectory": "/v1/subscribers?tag_value_match_mode=exact",
});
setSubscriber(listSubscribers);
}
SORACOM API で取得したデータを Spreadsheets へ出力
関数 myFunction
を選択して実行します。
Spreadsheets API の初回実行時はアクセス権の承認を求められますので、GAS を使用している Google アカウントで許可します。
Spreadsheets の sheet listGroups
に API で取得したデータが出力されました。
Spreadsheets の sheet listSubscribers
に API で取得したデータが出力されました。
所感
-
汎用ライブラリ
、汎用ライブラリ
と書いておりましたが、記事の終盤あたりで『汎用
ってワード要らなくない?』と感じました... - API が充実してるって良いですよね。親切なドキュメントのおかげで助かりました
- 今回は(おまけで)Spreadsheets に出力しましたが、別のサービスやデータベースに流すことも簡単そうです。
- GAS のライブラリ(実行可能な API)は簡単に作れたので GAS 自体もオススメです。
参考文献
- SORACOM
- GAS
分かりやすく記事を書こうとして画像を貼りまくった結果、ボリュームが多くなってしまいました
最後まで読んでいただきありがとうございました
誤っている箇所やツッコミがありましたら、優しくご指摘いただけますと幸いです