はじめに
組込み機器でも、ネットワーク通信が必要になる場面は多くあります。
AtomVM を使うと、TCP、UDP、MQTT、HTTP、Distributed Erlang など、複数の選択肢を考えることができます。
今回は、ネットワークの層を意識しながら、AtomVM で考えられる通信方式を見ていきます。
AtomVM とは
AtomVM は、小さな機器上で Erlang や Elixir のプログラムを動かすための軽量な仮想機械です。
たとえば ESP32 のようなマイコン上でも、Erlang/Elixir の実行環境を持ち込めます。
AtomVM の面白いところは、単に Elixir の文法が使えることだけではありません。
Erlang の持つ次の考え方を、組込み開発に持ち込める点にあります。
- 軽量プロセス
- メッセージ送受信
- 並行処理
- 障害に強い設計
Erlang VM、BEAM について
Erlang はもともと通信機器のために作られた言語です。
その実行環境である BEAM は、長年にわたり通信分野で使われてきました。
よく言われる特徴は次の通りです。
- 通信分野で使われてきた実績がある
- 多数の処理を並行して扱うのが得意
- 処理同士がメッセージで通信する
- 障害を前提に設計しやすい
ネットワークを扱うとき、この「処理同士がメッセージで通信する」という考え方はとても自然です。
Elixir について
Elixir は Erlang の実行環境で動く言語です。
文法は Ruby に近いところがあり、Ruby に親しんだ人にとっては比較的読みやすい言語です。
Elixir を使うことで、Erlang の強力な実行環境を、より書きやすい文法で扱えます。
AtomVM を使うと、この Elixir の世界を小さな機器にも少し持ち込めます。
ネットワークの層
ネットワークには多くの層があります。
ざっくり言うと、下の方には物理的な通信があり、上の方には利用者が直接意識する通信規約があります。
7 アプリケーション層 HTTP / MQTT / Distributed Erlang
6 プレゼンテーション層 データ形式 / 暗号化
5 セッション層 接続の管理
4 トランスポート層 TCP / UDP
3 ネットワーク層 IP
2 データリンク層 Ethernet / Wi-Fi
1 物理層 ケーブル / 電波 / 電気信号
TCP や UDP は、データを送るための基本的な仕組みです。
一方で、MQTT や HTTP は、その上に作られた、より高い層の通信規約です。
ソケット通信では、TCP や UDP を使ってバイト列を送受信できます。
ただし、そのバイト列が何を意味するのかは、自分たちで決める必要があります。
組込みシステムにおけるネットワーク
組込みシステムでは、使える資源が限られます。
たとえば次のような制約があります。
- メモリ
- CPU
- 電力
- 保存領域
- 通信の安定性
- 機器の価格
- 開発期間
そのため、Web 開発と同じ感覚で常に HTTP と JSON を使えばよい、とは限りません。
もちろん、HTTP と JSON が適している場面も多くあります。
しかし、小さな機器では、より低い層の通信を直接扱う方が単純で効率的な場合もあります。
TCP と UDP
TCP と UDP は、ネットワーク通信の基本的な部品です。
TCP は、順序が保たれた信頼性のあるバイト列を送受信できます。
UDP は、より軽量にデータを送れますが、到達保証や順序保証はありません。
どちらも単純で柔軟ですが、その分、自分で決めることが増えます。
- メッセージの区切り
- データの形式
- 再送の有無
- 時間切れの扱い
- 版の管理
- エラーの扱い
小さな用途では、TCP や UDP に簡単な規則を足すだけで十分なこともあります。
MQTT
MQTT は、IoT でよく使われる通信規約です。
特徴は、発行と購読の仕組みです。
+-------------+ publish +-------------+
| IoT device | ---------------------> | MQTT broker |
| sensor | | |
+-------------+ +-------------+
|
| subscribe
v
+-------------+
| server / app |
+-------------+
機器は MQTT broker にデータを送り、別の機器やサーバーが broker からデータを受け取ります。
broker は通常、センサーやマイコンそのものではなく、通信を中継する基盤です。
MQTT が合う場面は次のような場合です。
- センサー値を送る
- 機器に命令を送る
- 複数の機器をゆるくつなぐ
- broker を中心に通信を整理したい
一方で、MQTT broker を用意する必要があります。
便利ですが、構成要素が一つ増えることも意識する必要があります。
Distributed Erlang
Distributed Erlang も、AtomVM で考えられる面白い選択肢です。
Distributed Erlang は、Erlang のノード同士を接続し、メッセージを送受信する仕組みです。
Erlang/Elixir の世界では、これは特別な外部道具というより、言語環境に近い考え方です。
+----------------+ message +----------------+
| AtomVM node | <-------------------> | BEAM node |
| process A | | process B |
+----------------+ +----------------+
低い層では TCP が使われます。
ただし、利用する側から見ると、独自の通信規約をすぐに作るのではなく、Erlang のメッセージ送受信の延長として考えられる点が魅力です。
組込みで使う場合は、次の点を確認する必要があります。
- メモリ使用量
- 接続管理
- 名前解決
- 安全性
- 通信相手との互換性
- 機器の役割に対して過剰ではないか
Distributed Erlang は、万能の解ではありませんが、AtomVM らしいネットワーク通信の選択肢として、とても興味深いものです。
HTTP(S) と JSON
HTTP と JSON は、組込み開発でもよく使われます。
理由は明確です。
- 扱いやすい
- 調査しやすい
- 既存の Web システムとつなぎやすい
- 開発者にとって馴染みがある
- curl などで動作確認しやすい
資源に余裕がある場合、HTTP と JSON はとても現実的な選択肢です。
一方で、小さな機器では次の負荷も意識します。
- ヘッダーの大きさ
- JSON の解析
- TLS
- メモリ使用量
- 接続の管理
つまり、HTTP と JSON は便利ですが、常に最も軽い選択肢ではありません。
どう選ぶか
通信方式を選ぶときは、用途から考えるのがよいです。
UDP が合うのは、多少の取りこぼしが許され、低い負荷を優先したい場合です。
TCP が合うのは、信頼性のある通信が必要で、簡単な独自規則を定められる場合です。
MQTT が合うのは、発行と購読の形で複数の機器やサーバーをつなぎたい場合です。
Distributed Erlang が合うのは、Erlang/Elixir のメッセージ送受信の考え方を、そのままネットワーク越しに広げたい場合です。
HTTP と JSON が合うのは、Web システムとの接続や調査のしやすさを重視する場合です。
おわりに
AtomVM の面白さは、Erlang の持つ並行処理とメッセージ送受信の考え方を、組込み機器のネットワークにも持ち込めることにあります。
組込みシステムでは、通信方式の選択が設計そのものに関わります。
AtomVM は、その選択肢を少し広げてくれます。
