ESP32をWiFi経由でコントロールするアーキテクチャとライブラリをまとめた

# はじめに

ESP32-WROOM-32を使い、スマホ/PCからWiFi経由でコントロールするちょっとしたデバイスを作ろうと思ったのですが、色々と方法があるようなので、自分の検討をまとめるために簡単にまとめてみました。

ここでは、ESP32をデータロガー的な使い方をする用途は無視して、ESP32を制御することに対象を絞ります。
また、個人的な使用が目的なので、多数のユーザが大量の端末を制御することは想定していません。

# ESP32のWiFiモード

ESP32は、Stationモード（STAモード）と、Soft Access Pointモード（APモード）のいずれかで動作することが出来ます。
前者はESP32が適当なアクセスポイントに接続する方式、後者はESP32自身がアクセスポイントになる方式です。

STAモードで動作させるにはネットワークのSSID/パスワードが必要になりますが、
作ったデバイスを他の人に渡すような際には、あらかじめSSID/パスワードをフラッシュメモリに書き込んで置くこともできません。
APモードは、こういった初期設定を行う際に重宝すると思います。
一方、自分ひとりで使う分には不要なので、ここではSTAモードを前提に書いていきます。

# ESP32のコントロールアーキテクチャ

## 1. ESP32をHTTPサーバとして使用、フロントエンドはESP32内に配置

### 例
* [Create A Simple ESP32 Web Server In Arduino IDE](https://lastminuteengineers.com/creating-esp32-web-server-arduino-ide/)

### メリット
* 構成要素が少なく、シンプルで簡単

### デメリット
* インターネット越しの制御をするには相応のネットワーク設定が必要
    * ESP32のようなほぼ丸裸のデバイスをインターネットに晒すことはあまりしたくないですね
* ESP32からUIを持ってこようとすると遅そう
    * 測ってないので想像です


## 2. ESP32をHTTPサーバとして使用、フロントエンドはインターネット上に配置

インターネット上に配置したWebアプリから、クロスオリジンでESP32のリソースにアクセスするパターンです。

### 例
見当たりませんでした

### メリット
* UIの自由度が高くなる
* ESP32はjsonやxmlのやり取りのみで済むので、HTMLを出すよりは負荷が軽くなる

### デメリット
* フロントエンドをインターネット上に配置するコストがかかる
    * とはいえNetlifyなどを使えば無料か非常に安く済みますが
* フロントエンドへのアクセスを制御する必要がある
    * ESP32へは同一ネットワーク内にいないとアクセス出来ないので、無くても大丈夫とは思います


## 3. ESP32をHTTPサーバとして使用、フロントエンドはスマートフォンアプリ

Bluetoothを使うわけでもなく、フロントエンドをわざわざスマートフォンアプリで作るメリットが感じられないので割愛します。

### 例
探していません

## 4. ESP32をMQTTクライアントとして使用、フロントエンドはインターネット上に配置

### 例
* [ubidots](https://ubidots.com/)
    * https://www.youtube.com/watch?v=LvzCeBce2mU

### メリット
* 双方向の通信が簡単に出来る
    * インターネット上に晒す必要もありません
* HTTPと比べてプロトコルが軽量
* 操作者のフロントエンド、操作対象のESP32に加えて、ログを取る用のAWS Lambdaなどが簡単に追加できる
* 個人的にMQTTはわくわくする

### デメリット
* MQTTブローカーを用意する必要がある
    * 個人で使う範囲であれば、AWSIoTなら使った分だけの課金＆そこそこの無料枠でお手軽です
* HTTPに比べると使えるライブラリが少ない
    * フロントエンドを作るのがちょっと大変
    * MQTTブローカーによってはWebsocketで接続することも可能です
* フロントエンドはきちんと認証をかける必要がある


## アーキテクチャまとめ

いくつか方法はありますが、以下のような選び方で良いかなという結論に至りました。

* 操作の種類が少ない　→　1. ESP32 as a Web App Server
* 操作の種類が多い　→　2. ESP32 as a RPC Server
* 操作の種類が多く、非同期のやりとり（センサデータアップロード）も使いたい　→　4. ESP32 as a MQTT Client


# 使えそうなOS、フレームワーク、ライブラリ

## Amazon FreeRTOS

https://aws.amazon.com/jp/freertos/

言わずとしれた？RTOSですが、2017年よりAmazonから公開されています。
そのため、AWS IoTへの接続などサンプルコードが充実していて、Device Shadowなんかも簡単に使い始められます。
ただし、サンプルコードはMQTTあるいは生TCPのみで、HTTPサーバのサンプルコードは見当たりませんでした。

何よりすごいのが、AWS IoTを使ってインターネット越しのOTAアップデートが出来ることです。
自前で複雑なOTAサーバを用意する必要もありません。
個人用途ではさほど嬉しくはありませんが、仕事で現場に設置したマイコン製品をインターネット越しにアップデート出来るとなれば、オペレーションに革命が起きると言っても過言ではないかと思います。

またコードの書き方については、一度FreeRTOSの作法に慣れてしまえば、とても扱いやすいと思います。

## Mongoose OS

https://mongoose-os.com/mos.html

IoT機器開発のためのフレームワークです。
なんとJavascriptでマイコンの開発をすることが出来ます。

これは、RPC周りが非常によく出来ていそうです。
https://mongoose-os.com/docs/mongoose-os/userguide/rpc.md
MQTTでもHTTPでも、同じ要領で書けそうです。
これだけ簡単にハンドラがかければ、エンドポイントを増やすのも躊躇せずに済みます。

またクラウド接続についてもAWS、GCP、Azureがサポートされています。

#### 追記（2019/10/19）
実際に触ってみたら、Javascript”互換”のmJSというものが使える形で、意外と制約が多いものでした。
とはいえ、C言語と比べればかなりコードを書くのが楽になるのは間違いありません。
込み入ったことさえしなければ…
https://qiita.com/uhey22e/items/fba1647ba495059cbf0e

## MicroPython

Mongoose OSはJSですが、次はPythonです。

スクリプト言語で取っ掛かりやすい点は評価できますが、
HTTPライブラリが現状見当たらず、ソケットライブラリを直で使うしかなさそうです。
https://docs.micropython.org/en/latest/esp8266/tutorial/network_tcp.html

## obniz OS / obnizクラウド

https://obniz.io/

obnizは先の3つと比べると少し特殊で、デバイスにインストールしたobniz OSが、クラウドからプログラムをダウンロードして実行する形式を取っています。
そのような形なので、何もしなくてもOTAが使えます。一方で、インターネットがないと何も出来ないとも言えます。

obnizクラウドを使えば、スマホ、PCから操作を行うことも容易そうです。
お手軽に、わかりやすくはじめるには最も良い選択肢かもしれません。

ただ不安な点として、ドキュメントを見たところデバイス制御のAPIはあまり充実していなさそうです。
サポートされているディスプレイなどを使う分には問題ないかもしれませんが、ペリフェラルを駆使して様々な機器の制御を行うには心許なさそうです。
https://obniz.io/ja/doc/sdk/doc/io

## フレームワークまとめ

正直、Mongoose OS一択なのではないかという気がしています。
ペリフェラルの制御コードが未熟かもしれませんが、それはPRを出せば良い話です。

AWSの他サービスへの連携をしたくて、C/C++の開発が出来るならばAmazon FreeRTOSが良いと思います。
Javascriptでとにかくお手軽にしたい方はobnizという感じでしょうか。


# おわりに

色々とまとめてみましたが、多分に網羅できていない素敵なアーキテクチャやライブラリがまだあるかと思います。
コメントで教えてくださると嬉しいです。
ESP32はソフトウェアのエコシステム開発が活発でとてもワクワクしますね。