その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

SORACOM ArcをESP32のArduinoで動かすsoracom-arc-esp32-arduinoのご紹介

こんにちは、株式会社ソラコムでソフトウェア等のエンジニアをやっているmoznionです。
普段ブログには書かない所属を宣言するのはなぜか。それはこれが株式会社ソラコム Advent Calendar 2021 17日目の記事だからです。というわけで記事が書かれます。

前日のアドベントカレンダー16日目は @0x6b さんによる soratun を改造して AWS Lambda から簡単に SORACOM Arc を使ってみました でした。そして本記事もSORACOM Arcの記事になります。連チャンしていて景気が良いですね。


表題の通り、SORACOM ArcをESP32のArduinoで動かすためのライブラリであるsoracom-arc-esp32-arduinoをご紹介します。
SORACOM Arcというサービスはザックリ説明すると「WireGuardを使ってデバイスとSORACOMプラットフォームとの間にトンネルを張り、そのトンネル越しに通信することでSORACOMのサービスを使えるようにするサービス」です。つまり従来は必須であって携帯電話回線を使わなくてもSORACOMサービスが使えるという接続サービスになります。

github.com

なお本ライブラリはArduinoLibrary Registryにも登録してありますので、ArduinoのLibrary Managerから利用が可能です。

f:id:moznion:20211217095811p:plain


使い方は至って簡単で、このライブラリ (SoracomArcESP32.h) をincludeしてちょっとしたコードを書いてやることですぐにSORACOM Arcを利用することができます。

#include <SoracomArcESP32.h>
#include <WiFi.h>
#include <HTTPClient.h>

#define BAUDRATE 115200

static SoracomArc soracomArc;

void setup() {
  Serial.begin(BAUDRATE);
  while (!Serial)
    ;

  WiFi.begin("__YOUR_AP_SSID__", "__YOUR_AP_PASSWORD__");
  while (!WiFi.isConnected()) {
    delay(1000);
  }

  configTime(0, 0, "ntp.nict.jp", "time.google.com", "pool.ntp.org");

  std::string soracomAPIAuthKeyID = "keyId-__YOUR_SORACOM_API_KEY_ID__";
  std::string soracomAPIAuthKey = "secret-__YOUR_SORACOM_API_AUTH_KEY__";
  std::string caCert = "-----BEGIN CERTIFICATE-----\n"
                       "...\n"
                       "__CA_CERTIFICATION_STRING__\n"
                       "...\n"
                       "-----END CERTIFICATE-----\n";

  SoracomAPI soracomAPIClient(soracomAPIAuthKeyID, soracomAPIAuthKey, caCert);

  std::string simID = "__YOUR_SIM_ID__";
  while (!soracomArc.activate(soracomAPIClient, simID)) {
    delay(5000);
  }

  log_i("setup finished");
}

void loop() {
  HTTPClient http;

  http.begin("http://metadata.soracom.io/");
  http.setConnectTimeout(1000);
  http.setTimeout(1000);
  int statusCode = http.GET();

  String payload = http.getString();
  log_i("http status: %d", statusCode);
  log_i("%s", payload.c_str());

  http.end();

  delay(30000);
}

このコードは以下のシークエンスに従って動作します。

1. Wi-Fiに接続する
2. NTPを用いてシステムの時刻合わせをする
3. SORACOM APIのauthKeyIdとauthKeyを組み合わせて認証を行ない、apiKeyとapiTokenを取得する
4. 上記のapiKey/apiTokenを用いて使用するArcのSIMについてセッションの再生成を行う。この再生成時にWireGuardのcredentialsを動的に発行する
5. 生成したArcのセッション情報を引いてくる
6. WireGuardのcredentials情報とセッション情報に基いてWireGuardトンネルを張る
7. Arcが有効に。上記の例では30秒ごとにメタデータサービスにアクセスし、SIMの情報を取得している

という感じです。コード中のCA certについては https://api.soracom.io に対するものを良い感じに埋め込んでください。


内部的には@cinimlさんのWireGuard-ESP32-Arduinoを使ってWireGuardの接続を行なっています。このライブラリの技術詳細についてはSORACOM Advent Calendar 2021 7日目の@cinimlさんによるWireGuard for ESP32の実装的なところという記事でつまびらかにされているので、併せて是非ご参照ください。


もちろん、WireGuardの設定情報をそのまま利用して利用することも可能です。その例はこちらにございます: https://github.com/soracom-labs/soracom-arc-esp32-arduino/tree/main/examples/boot-static-wg-credentials


既知の課題としては、SORACOM APIを使う方法にせよWireGuardの設定をそのまま使う方法にせよセンシティヴな情報をボード上で取り扱う必要が出てくるため、それらをセキュアな領域に置くあるいは何らかセキュアな方法で操作する必要があります。細心の注意を払っていただければと思います。


というわけでsoracom-arc-esp32-arduinoのご紹介でした。詳しい使い方についてはREADMEexamplesをご参照ください。
ESP32 ArduinoでSORACOM Arcが動作するとプロトタイピング等で活躍してくれそうで夢が広がりそうです。ぜひご利用ください!

おまけ

PlatformIOを使ってライブラリ開発してたんですけど、これ死ぬほど便利な一方ハマりどころがちらほらあるのでそういった落し穴について記録しておきます。

platform = espressif32を指定していると古いバージョンが降ってくる

これ新しいバージョンを明示しないと古いのを使い続けてしまいます。結構ドラスティックにプログラミングインターフェイスが変わってたりするんで、バージョン間違えると確実にハマります。

github.com

ここから欲しいバージョンを探してきて、 platform = espressif32@3.4.0 みたいな感じで指定してあげると良いです。

C++17使いたいんだけど……

という時はこのように platformio.ini に記述してやると良いです。

build_flags =
  -std=gnu++17
build_unflags =
  -std=gnu++11

残念ながら gnu++20 (C++20) はまだ対応していない様子。std::format()、とにかくバキバキに使いたんだが……