ArduinoOSCを使ってOSC通信をしてみる

2020.05.20 追記
[ArduinoOSC] を大幅にアップデートしたため、それに合わせてこちらの記事も修正しました。

## 結論と使い方

とにかくラクにOSCを送受信したかったので、[ArduinoOSC](https://github.com/hideakitai/ArduinoOSC) ってやつを作りました。
こんな感じでサクッと送受信ができます。
WiFiではなくEthernetで使いたいときは、`OscWiFi` -> `OscEther` に変更して使ってください。

``` C++
#include <ArduinoOSC.h>

int i; float f; String s;

void setup()
{
    // WiFi stuff
    WiFi.begin(ssid, pwd);
    WiFi.config(ip, gateway, subnet);

    // 受信したOSCパケットを直接変数にバインドします
    OscWiFi.subscribe(bind_port, "/bind/values", i, f, s);

    // デフォルト毎秒30回で、OSCパケットを定期的に送信し続けます
    OscWiFi.publish("127.0.0.1", publish_port, "/publish/value", i, f, s);
}

void loop()
{
    OscWiFi.update(); // 自動的に送受信するために必須
}
```

単発でのOSC送信も一行で可能です。

``` C++
OscWiFi.send("127.0.0.1", send_port, "/send", 1, 2.2, "hello");
```

ラムダ式の引数として受信したOSCパケットをバインドすることも可能です。

``` C++
OscWiFi.subscribe(bind_port, "/lambda/bind/args",
    [&](int i, float f, String s)
    {
        Serial.print("/lambda/bind/args ");
        Serial.print(i); Serial.print(" ");
        Serial.print(f); Serial.print(" ");
        Serial.print(s); Serial.println();
    }
);
```

もちろん、これまで通り `OscMessage` を引数にしたラムダ式も使えます。

``` C++
OscWiFi.subscribe(recv_port, "/lambda/msg",
    [](const OscMessage& m)
    {
        Serial.print(m.remoteIP()); Serial.print(" ");
        Serial.print(m.remotePort()); Serial.print(" ");
        Serial.print(m.size()); Serial.print(" ");
        Serial.print(m.address()); Serial.print(" ");
        Serial.print(m.arg<int>(0)); Serial.print(" ");
        Serial.print(m.arg<float>(1)); Serial.print(" ");
        Serial.print(m.arg<String>(2)); Serial.println();
    }
);
```

もっと詳細な使い方は、[README](https://github.com/hideakitai/ArduinoOSC) をご参照くださいませ。
以下、補足です。



## ところでOSCってなに

詳細は[Wikipedia](https://ja.wikipedia.org/wiki/OpenSound_Control)をご覧ください。


### 簡単に言うと

- 主にUDPの通信プロトコル
- 主にLAN内で、リアルタイム性の高い短いメッセージをやりとりする
- 音楽、インタラクティブアート系のソフトウェアの通信によく使われる

いろんなアプリケーション間で通信するのにとても便利で重宝します。
[こちらの記事の言い回し](https://qiita.com/satoruhiga/items/63fea9616d5135a328d3)を真似させてもらいました。

### Arduinoで使える有名なライブラリ

- [OSC](https://github.com/CNMAT/OSC)
    - OSCのプロトコルを開発したCNMATの純正のやつ
    - 詳細省きますが、エンコード・デコードやSLIP-SERIALが一手間で、だるい
- [ArdOSC](https://github.com/recotana/ArdOSC)
    - Arduino UNOなど + Ethernetシールドを前提としたOSCライブラリ
    - つまり[W5100](https://www.switch-science.com/catalog/16/)が必須

とかです。

OSCのパケット構造は、Unityですが[こちらの記事](http://tips.hecomi.com/entry/2017/08/20/193823)の「OSCについて」の項目でざっくりわかりやすく説明してくれています。openFrameworksでは[こちらの記事](http://yoppa.org/ma2_10/2279.html)でもとてもわかり易く解説されています。

## 動機

- ESPとかいろんなプラットフォームで、__とにかくサクッと__使いたい
- ~~シリアルでOSC (っぽい感じで) 使いたい~~
  - -> シリアル対応は削除しました。サクッとシリアル通信したいときは [MsgPacketizer](https://github.com/hideakitai/MsgPacketizer) をどうぞ。


## 特徴

- ESPなどのWiFi、EthernetでのUDP、~~シリアル~~ などで使える
- 簡単にOSCに使えるアプリ・フレームワークから__サクッと__送受信できる
    - Max, Pd, Processing, openFrameworks, P5.js など (~~例としてMaxのサンプルがあります~~)
        - -> いろいろ追加してますが、欲しいアプリがあったらご連絡くださいませ
- ~~シリアルでも同じ感覚で使える (エセですが)~~

## ~~制限とTODO~~

- ~~現状 int32, float, String のメッセージのみ対応、拡張予定~~
- ~~シリアル用エセ拡張はまだMaxのみ、自分が必要なときに随時追加予定~~
- ~~あまりいないと思いますが、シリアル拡張ほしいアプリあればコメントください~~
- Arduino Uno などのSTLが使えないマイコンでは、色々なサイズ制限があります (機能はフルで使えます)


## まとめ

OSC最高ですね。
~~シリアルでも (エセですが) 使えて楽ちんですね。~~
OSC使ったことない方も、ぜひこの機会につかってみてください。
プルリク・Issue・コメントおまちしています！
~~(はやくシリアルも安定稼働させます、、、)~~