[Node.js]Requestモジュールを使ってSORACOMのAPI(Japan/Global)を利用する


はじめに

みなさんSORACOM使ってますか?
私はSORACOM社の社員ではありませんので詳細は割愛します。(詳しくはこちら)

今回のお話は、自社で開発したアプリケーションからSORACOMのSIMを管理したいとなった時のお話です。

プロローグ

お客様「管理画面みたいなの作って、自社のデバイスとSORACOMのSIMを管理したい。とりあえず 国内SIM 向けで」

弊社「御意!」
弊社「SORACOMのAPI使って実現しよう」
弊社「アプリケーション自体はNode.jsで動いているから、このsoracomっていうパッケージ使えばいけるやん!」
弊社「できたで。」

お客様「ありがとう」

~~ 数ヶ月後 ~~

お客様「海外展開したいから グローバルSIM でもできるようにする必要出てきそうなんやけど…」

弊社「なんですと……」
弊社「グローバルSIMはAPIのエンドポイントが違う…」
弊社「今まで使ってたパッケージには国内SIM用のエンドポイントがハードコーディングされているから使えない…」
弊社「自分たちで組むしかっ!」

というわけで、調査含め色々試してみました。

何したん?

前置きが長くなってしまいましたが、requestというモジュールを使って、SORACOMのAPIにリクエストを送信してみた。

前提

Node.jsフレームワークは Express を利用しています。
authKeyIdとauthKeySecretはあらかじめSORACOMユーザーコンソールから取得しておいてください。

参考

SORACOM APIの仕様はこちら
SORACOM APIドキュメントはこちら

ソースコード(SIM情報一覧取得)

APIを利用するためのAPIKey/Tokenを取得する方法と、アカウント内のSIM情報を取得するAPIを叩く例は、こんな感じです。
アプリケーションから /soracom に対してGETのリクエストを送信すると、アカウント内のSIM情報一覧を返します。

soracom.js
"use strict";

const express = require("express");
const router = express.Router();

const co = require("co");

const SoracomAPI = require("./soracom_api");

router.get("/", (req, res) => {
  co(function *() {
    const apiAuthenticate = yield SoracomAPI.authenticate();
    const apiKeyAndToken = {
      "apiKey": apiAuthenticate["apiKey"],
      "apiToken": apiAuthenticate["token"]
    };
    const subscribers = yield Promise.all([
      SoracomAPI.getSubscribers(apiKeyAndToken["apiKey"], apiKeyAndToken["apiToken"], "japan"),
      SoracomAPI.getSubscribers(apiKeyAndToken["apiKey"], apiKeyAndToken["apiToken"], "global")
    ]);
    return subscribers;
  }).then(data => {
    return data;
  }).catch(err => {
    return err;
  });
});

module.exports = router;

soracom_api.js

const request = require("request");
const API_URL = {
  japan: "https://api.soracom.io/v1", // 国内向けAPIのエンドポイント
  global: "https://g.api.soracom.io/v1" // グローバル向けのエンドポイント
};

class SoracomService {

  /**
   * APIKey/Token取得
   * @returns {Promise<any>}
   */
  static authenticate() {
    return new Promise((resolve, reject) => {
      const options = {
        // authは国内、グローバルどちらでも同じ
        url: API_URL["japan"] + "/auth",
        method: "POST",
        // bodyにauthKeyIdとauthKeySecretを埋め込む
        // authKeyIdはkeyId-から始まるランダム文字列
        // authKeySecretはsecret-から始まるめちゃ長いランダム文字列
        body: {
          "authKeyId": "your authKeyId",
          "authKey": "your authKeySecret"
        },
        json: true
      };
      request(options, (err, res, body) => {
        if(err) {
          return reject(err);
        } else {
          return resolve(body);
        }
      });
    });
  }

  /**
   * アカウント内のSIM情報を取得する
   * @param {string} key
   * @param {string} token
   * @param {string} coverageType
   * @returns {Promise<any>}
   */
  static getSubscribers(key, token, coverageType) {
    return new Promise((resolve, reject) => {
      const options = {
        // coverageType(japan or global)でAPIのエンドポイントを切り替える
        url: API_URL[coverageType] + "/subscribers",
        method: "GET",
        // authで取得したkey/tokenをヘッダーに埋め込む
        headers: {
          "X-Soracom-API-Key": key,
          "X-Soracom-Token": token
        }
      };
      request(options, (err, res, body) => {
        if(err) {
          return reject(err);
        } else {
          return resolve(body);
        }
      });
    });
  }
}

module.exports = SoracomService;

まとめ

自分の違う記事にも書きましたが、SORACOMのAPIが充実しているので、ユーザーコンソールを使わなくても、SIMの管理をすることができます。
例えば、アプリケーションからSIMを開通/中断などをコントロールしたり、特定のSIMの情報を取得してデバイスと情報を組み合わせたりすることができます。
SIM数枚であれば、ユーザーコンソールから手作業で行えばいいのですが、IoTデバイスの場合、デバイス自身が数百、数千とスケールしていくことが多いと思います。その度に手作業でSIMを管理していると面倒ですし、まず間違いなくヒューマンエラーを起こしてしまいます。まぁ管理しきれませんよね?ってことです。
だったら自分たちで自分たちにあったSIM管理画面を作ろうよってことで、こんなことをしてみました。
ただ国内とグローバルでエンドポイントが違ったので、グローバル展開が考えられる場合は注意が必要だなと感じた次第です…

ではまた!