[SORACOM Orbit] C/C++で実装されたサンプルWASMモジュールを試してみた

SORACOM OrbitでC/C++で実装されたサンプルWASMモジュールを試してみました
2021.02.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部のうらわです。

SORACOM Orbit(以下、Orbit)ではWASMモジュールを使用してIoTデバイスから送られてくるデータを変換できます。

本記事ではC/C++のサンプルコードを試してみます。

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.6
BuildVersion:   19G2021

$ docker --version
Docker version 20.10.2, build 2291f61

開発環境の準備

OrbitのWASMモジュールの開発に必要な環境は、Visual Sudio Code(以下、VSCode)ユーザーであればSORACOM開発者ガイドのセットアップ手順にしたがって簡単に構築できるようです。

私はVimを使用しているので、Dockerfileを新規作成してコンテナにログインして作業します。

とは言ってもそれほど難しくはなく、SDKのzipファイル内に含まれているDockerfileを元に、VSCodeの機能を使わずにコンテナを起動してログインするだけです。

SDKは上記の「WASM モジュール開発環境のセットアップ」ページ内にダウンロードリンクが記載されています。

ダウンロードしたSDKを任意のディレクトリに展開します。本記事の執筆時点では2020-11が最新バージョンです。

$ unzip orbit-development-environment-2020-11.zip -d orbit-dev

c/.devcontainer/Dockerfileを参考に、新しくDockerfileを作成します。

Dockerfile

FROM trzeci/emscripten:1.39.18-upstream

RUN apt-get update && apt-get install -y \
	wabt \
	&& rm -fr /var/lib/apt/lists

RUN curl -L -o - https://github.com/soracom/soracom-cli/releases/download/v0.6.1/soracom_0.6.1_linux_amd64.tar.gz | tar zxf - \
	&& mv ./soracom_0.6.1_linux_amd64/soracom /usr/local/bin/ \
	&& rmdir ./soracom_0.6.1_linux_amd64

任意のタグをつけてビルドします。

$ docker build -t soracom-orbit .

起動&ログインします。ローカルのSDKのディレクトリをマウントして、ローカルで編集したファイルをDockerコンテナ内で参照できるようにしておきます。

$ pwd
/Users/hoge/orbit-dev

$ docker run --it -rm -v $(pwd):/src soracom-orbit:latest /bin/bash

以降のコマンド操作は全てDockerコンテナ内で実行しています。ローカルマシンではありませんのでご注意ください。

Emscriptenとsoracom cliのバージョンを確認します。

$ emcc --version
emcc (Emscripten gcc/clang-like replacement) 1.39.18 (a3beeb0d6c9825bd1757d03677e817d819949a77)
Copyright (C) 2014 the Emscripten authors (see AUTHORS.txt)
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ soracom version
SORACOM API client v0.6.1

soracom cliのセットアップをしておきます。開発者ガイドを参考に必要な権限を付与したSAMユーザーを作成し、認証キーID(authKeyId)と認証キーシークレット(AuthKey)を入手しておきます。

参考: WASM モジュール開発環境のセットアップ SAM ユーザーの作成と SORACOM CLI のインストール

$ soracom configure
--- SORACOM CLI setup ---
This will create a directory /root/.soracom if it does not exist yet and place 'default.json' in it.

Please select which coverage type to use.

1. Global
2. Japan

select (1-2) > 2

Please select which authentication method to use.

1. Input AuthKeyId and AuthKey * Recommended *
2. Input Operator credentials (Operator Email and Password)
3. Input SAM credentials (OperatorId, User name and Password)

select (1-3) > 1
authKeyId:
authKey:

WASMモジュールのビルド・デプロイ

あとはSORACOM開発者ガイド通りに進めるだけです。

ビルド

C/C++のサンプルコードを使ってビルド・デプロイを試します。

$ cd c
$ make build
emcc -O0 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -I/src/orbit-sdk-c /src/orbit-sdk-c/soracom/orbit.c src/main.cpp -o build/soralet.wasm
warning: undefined symbol: orbit_log (referenced by top-level compiled C/C++ code)

警告については開発者ガイドに記載があります。ちなみに-s ERROR_ON_UNDEFINED_SYMBOLS=1を設定するとerrorに変わりビルドに失敗します。

ビルド時に、Orbit が提供するいくつかの関数 (orbit_log orbit_get_input_buffer など orbit_ の接頭辞で始まる関数) のシンボルが未定義であるという警告が表示されますが、これは実行時に Orbit の処理系から提供される関数なのでコンパイル時に未定義でも問題ありません。

引用: WASM モジュールの開発とテスト

デプロイ

デプロイ用WASMモジュールをビルドします。

$ make release
emcc -Os -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -I/src/orbit-sdk-c /src/orbit-sdk-c/soracom/orbit.c src/main.cpp -o build/soralet-optimized.wasm
warning: undefined symbol: orbit_log (referenced by top-level compiled C/C++ code)

make buildとの違いはemscriptenの最適化オプションの違いです。

参考: Emscripten Compiler Frontend (emcc)

ビルドしたWASMモジュールのアップロード先を作成します。

$ soracom soralets create --soralet-id my-soralet

WASMモジュールをアップロードします。

$ soracom soralets upload --soralet-id my-soralet \
    --content-type application/octet-stream \
    --body @build/soralet-optimized.wasm

テスト実行

テスト用のjsonを作成してテスト実行してみます。

$ cat test.json
{
  "source": { "resourceType": "Subscriber", "resourceId": "295050919999999999" },
  "payload": "{\"value\":23.54,\"name\":\"sorao\"}"
}

$ soracom soralets exec --soralet-id my-soralet \
    --version 1 \
    --direction uplink \
    --content-type application/json \
    --body @test.json

ブラウザでSORACOMユーザーコンソールを開き、SORACOM Orbit > Soralet管理から作成されたsoraletを参照します。

LOGSを確認するとsrc/main.cpp内のsoracom_log関数で出力している文字列が表示されていることがわかります。WASMモジュールが正常に動作しているようです。

おわりに

VSCodeを使わずにDockerコンテナを起動し、SORACOM開発者ガイドにしたがってテストWASMモジュールをビルド・デプロイしてみました。

SDKのzip内にはjsonを変換するもっと複雑なサンプルコードがあります。今後はこちらを参考にしてWASMモジュールをカスタマイズしてみたいと思います。