Edited at

SORACOM API を Google Apps Script から叩くための汎用ライブラリの使い方

SORACOM 、使ってますか?

製造業のお偉いさんが『やれ IoT だ!』『やれ プラットフォームだ!』と騒いだ後、キャッチアップされる担当の人は一度は見聞きしたことがあるサービスかと思います。

SORACOM は、ソフトウェア・ハードウェアのどちらのエンジニアにも『IoT の入り口』として良いサービスです。また、精力的にハンズオンやカンファレンス、セミナーなどを開催されていて、ユーザーグループなどのコミュニティも活発とのことです。


TL;DR


  • GAS で SORACOM API を使うなら認証や API を叩く処理は汎用ライブラリを使うことで楽ができる

  • 汎用ライブラリの API ID は :arrow_down:

MJlievwjcIu8-7grDZqGf-FSucpP_quDO


  • GAS のスクリプトプロパティに SORACOM の SAM ユーザー認証情報を設定すれば使うことができる。

  • 自分の GAS のプロジェクトに getAccessToken 関数の作成は必要(当記事のテンプレをコピペ)


この記事の内容

タイトルの通りです。Google Apps Script(以下、GAS)から SORACOM API を実行するための汎用ライブラリの使い方を説明します。

おまけとして Google Spreadsheets(以下、Spreadsheets)へ出力する方法も記載します :wink:


本記事の対象読者


  • 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 リファレンスは非常に丁寧に記載されており、API の基礎的なところが押さえられている人であればドキュメントを見て大体何ができるのかがすぐに分かります。この汎用ライブラリは単にAPI を使うための手続きを簡素化しただけなので自前で作れる人に対しては釈迦に説法になるかもしれません。


汎用ライブラリの使い方

使い方の前にまず事前準備からはじめます。既に準備が整っている場合は読み飛ばしてください。


事前準備


1. SORACOM のアカウントを取得

公式に説明を譲ります。

:arrow_right: SORACOM アカウントの作成


2. SAM ユーザーを作成

公式に説明を譲ります。

:arrow_right: SAM ユーザーの作成と認証設定

説明中に認証キーの設定の項がありますが、汎用ライブラリを使う上では必須ではないので実施しなくても問題ありません。


3. SAM ユーザーの権限を設定

公式の説明に設定方法が記載されています。

:arrow_right: SAM ユーザーの権限設定

権限の設定方法は、


  1. ロールに権限を設定してから、ユーザーにロールを設定するか、

  2. ユーザーに直接指定で設定するか

の 2種類ありどちらでも問題ありません。ここでは後者の直接指定を行っています。

※補足

使用したい API や HTTP メソッドを絞った方が良いのですが、ここではひとまず全て使える状態で進めます。


4. GAS を利用可能にする

GAS を導入する方法はググれば腐るほど記事が出てきますが、念の為掲載しておきます。



  1. Google Drive を開く


  2. 新規その他アプリを追加


  3. Google Apps Script で検索し、ヒットしたら 接続 を選択


  4. Google ドライブに接続されました。 という説明が表示されれば OK。

  5. 改めて 新規 を選択すると Google Apps Script が表示され、選択すれば 無題のプロジェクト (新規の GAS)が作成されます。


汎用ライブラリの使い方


1. GAS で汎用ライブラリを読み込む


  1. GAS のプロジェクトを開く

  2. メニューの リソースライブラリ を選択


  3. ライブラリを追加 と記載されているフォームに汎用ライブラリの API ID MJlievwjcIu8-7grDZqGf-FSucpP_quDO を入力して 追加


  4. バージョンSORACOM API 汎用ライブラリ を選択して 保存

汎用ライブラリが正常に読み込めていると GAS のコードで識別子+ドット(Soracom.)まで入力すると、使用可能な関数の選択肢(samUserAuthenticationapi)が表示されるようになります。


2. GAS のスクリプトプロパティに SORACOM の SAM ユーザー認証情報を設定

基本的に、ユーザーアカウントや認証に必要な情報(API のキーやトークン)をハードコーディングすることは大変危険です。万が一情報が漏れてしまった場合、第三者が自由にアクセスできてしまうリスクは言うまでもないと思います。なので汎用ライブラリでは SORACOM の SAM ユーザーアカウントの情報を GAS のスクリプトプロパティに設定して使用します。


  1. GAS のプロジェクトを開く

  2. メニューの ファイルプロジェクトプロパティ を選択


  3. スクリプトのプロパティ タブを選択


  4. SORACOM_SAM_USERNAME には SORACOM User Console で作成した SAMユーザー名を設定


  5. SORACOM_SAM_PASSWORD には SAM ユーザーのパスワードを設定


  6. SORACOM_OPERATORID には SORACOM User Console にログインするアカウントのオペレーターID(OPxxxxxxxxxx)を設定


3. GAS のプロジェクトに getAccessToken 関数を作成

下記のコードを コード.gs に追加します。


コード.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 の一覧を返しています。


コードgs

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 を取得しています。

  • 引数 operatorIduserNamepassword は 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",
});


  • 引数 apiKeyapiToken には SORACOM API を使うために必要な情報(HTTP ヘッダーに設定する API Key と API Token)を設定します。

  • 引数 httpMethod 使用したい API の HTTP メソッドを設定します(例: getpostputdelete

  • 引数 subDirectory 使用したい API のパスを設定します(例: /v1/groups


    • API のバージョンが v1 じゃなくなったら... っていうのはまだ考えてないです





  • Soracom.samUserAuthetication では 内部的には認証するための auth の API を呼び出し と記載しましたが、この auth の API の HTTP メソッドは post です。この場合は引数 requestBody を追加し、HTTP メソッドが post の場合のみ JSON でリクエストしたいパラメータを設定します。


汎用ライブラリの中でauth認証している部分の処理

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(テンプレート) を、閲覧のみ可能な状態で公開しております。



  1. Spreadsheets(私が公開しているテンプレート) を開きます。

  2. メニューの ファイルコピーを作成 を選択

  3. 適当なファイル名で OK を選択

  4. すると、マイドライブの配下にコピーされます。


コピーした Spreadsheets の ID を GAS のスクリプトプロパティに追加

Spreadsheets の ID とは Spreadsheets の URI に記載されています。

例:

https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit#gid=0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx の部分です。

コピーして先ほどの GAS のプロジェクトを開き、スクリプトプロパティに SORACOM_TABLE_ID という名前で設定します。


SORACOM の Group と SIM の情報を Spreadsheets に出力するコードを追加

コード.gs に下記のコードを追加。


コード.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 を下記のように書き換えます。


コード.gs

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 が充実してるって良いですよね。親切なドキュメントのおかげで助かりました :laughing:

  • 今回は(おまけで)Spreadsheets に出力しましたが、別のサービスやデータベースに流すことも簡単そうです。

  • GAS のライブラリ(実行可能な API)は簡単に作れたので GAS 自体もオススメです。


参考文献


分かりやすく記事を書こうとして画像を貼りまくった結果、ボリュームが多くなってしまいました:sweat:

最後まで読んでいただきありがとうございました:exclamation:

誤っている箇所やツッコミがありましたら、優しくご指摘いただけますと幸いです:bow: