osc.js でブラウザから OSC Data Monitor に OSC over WebSocket でデータを送る（とりあえず片方向）

過去に OSC を使った記事をいくつか書いていたのですが、今回の記事はその中の以下に近いものです。

●osc.js で OSC Data Monitor に OSC over UDP でデータを送る（Node.js の keypress との組み合わせ） - Qiita
　https://qiita.com/youtoy/items/740686a8d2ffb0c6b8ba

上記は、Node.js のプログラムのみを使って OSC over UDP を使うものでしたが、今回はブラウザ上の JavaScript のプログラムから OSC over WebSocket でデータを送ります。
※ ブラウザ上では UDP を直接扱えないため、WebSocket の上にのる形になります

正確には、Node.js で作った仲介役を介して OSC Data Monitor にデータを送るような構成です。
そして、自分がこの後にやりたい事は、ブラウザから送信する側だけあれば良いので、その部分は片方向の通信を実装する形です（ちょっと処理を足せば、双方向もできてしまいますが）。

## osc.js と OSC Data Monitor の間の通信
### OSC Data Monitor について
OSC Data Monitor は、OSC で送られたデータの情報を、GUI上に表示してくれるアプリです（※ Windows、Mac、Linux　のそれぞれで利用可能）。
関連リンク等については、[以下の記事の中の「OSC Data Monitor」という部分](https://qiita.com/youtoy/items/fddc750759f4ecef7ca7#osc-data-monitor)の説明などをご参照ください。

●ZIG SIM と Node.js のプログラム（osc.js を利用）との間で UDP による OSC通信を軽く試す（OSC Data Monitor の話も） - Qiita
　https://qiita.com/youtoy/items/fddc750759f4ecef7ca7

### osc.js の OSC over WebSocket 
まずは、[osc.js](https://github.com/colinbdclark/osc.js/) を使って OSC over WebSocket の通信を実現する方法を確認します。

ちなみに、以下の赤線をひいた部分が WebSocket の話で、それ以外でシリアル通信などにも対応しているようです。
![対応プロトコル.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f964bed9-bc27-8a21-6bea-1ac59d91e536.jpeg)

ページの中を見ていくと、ブラウザ側の実装と Node.js側の実装のそれぞれの概要や、他のサンプルが置いてあるページへのリンクなどが書いてあります。
![ブラウザでOSC.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/111fc32c-0842-1656-efe1-a5ea96efa93f.jpeg)

https://github.com/colinbdclark/osc.js-examples/tree/master/udp-browser という URL にアクセスすると見られるサンプルを参考に、実装を進めていきます。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">やりたいこと的には、こちらかも。<a href="https://t.co/YXQWaaZ1kI">https://t.co/YXQWaaZ1kI</a> <a href="https://t.co/dvwYluJS7U">pic.twitter.com/dvwYluJS7U</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1462278318074433538?ref_src=twsrc%5Etfw">November 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#### Node.js側の実装
元のサンプルの実装は、[このリンク先の内容のとおり](https://github.com/colinbdclark/osc.js-examples/blob/master/udp-browser/index.js)なのですが、もっと簡略化できそうに見えるので、必要最低限となりそうな部分以外削ったり書きかえます。

なお、以下を実行する場合には、 `npm i osc` で osc.js を呼び出せるようにしておいてください。
ちなみに `ws` は、上記のインストール時に一緒に準備されるので、特に上記の npmコマンドでの指定は不要です。

```javascript
const osc = require("osc"),
    WebSocket = require("ws");

const udp = new osc.UDPPort({
    localAddress: "0.0.0.0",
    localPort: 7400, // 自分が UDP で待ち受ける時のポート番号
    remoteAddress: "127.0.0.1",
    remotePort: 8000 // OSC Data Monitor の待ち受けポート番号
});

udp.on("ready", function () {
    console.log("Listening for OSC over UDP.");
});
udp.open();

const wss = new WebSocket.Server({
    port: 8081 // WebSocket で接続する場合の接続先ポート番号
});

wss.on("connection", function (socket) {
    console.log("A Web Socket connection has been established!");
    const socketPort = new osc.WebSocketPort({
        socket: socket
    });

    const relay = new osc.Relay(udp, socketPort, {
        raw: true
    });
});
```

上記で 3つのポート番号が出てきますが、それぞれコメントに書いた通りです。

- localPort: 7400： Node.js のプログラム自身が UDP で待ち受けるポート（今回は不使用）
- remotePort: 8000： OSC Data Monitor に接続するためのポート番号（OSC Data Monitor のデフォルトの待ち受けポート番号）
- port: 8081： ブラウザ側から WebSocket で接続する場合のサーバーのポート番号

#### ブラウザ側の実装
次に、[サンプルのブラウザ側の実装](https://github.com/colinbdclark/osc.js-examples/blob/master/udp-browser/web/index.html)を見てみます。

以下のように、osc.js での OSC over WebSocket にはライブラリが必要なようです。
※ 念のため、素の WebSocket での通信を試したのですが、Node.js側のプログラムでデータが届いた後の部分でエラーが出ました...
![ブラウザ側でのライブラリの読み込み.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/04833b6e-4aec-357e-a278-97232c352c79.jpeg)

最低限、osc-browser.min.js があれば良さそうです。
検索してみると CDN からの読み込みができそうでした。

以下は、 https://www.jsdelivr.com/package/npm/osc というアドレスから、その中の [disｔフォルダ内](https://www.jsdelivr.com/package/npm/osc?path=dist)へと移動していった時のページのキャプチャです。
![distフォルダ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/fa8773b9-9d80-52de-5aeb-da7cf978b45d.jpeg)

![dist以下.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3f4f775e-ea00-0a3d-9003-c2b4cf0a512b.jpeg)

執筆時点では、以下のようにスクリプトタグで読み込めばよさそうでした。

```html
<script src="https://cdn.jsdelivr.net/npm/osc@2.4.2/dist/osc-browser.min.js"></script>
```

とりあえず、最低限、Node.js側に接続して何らかデータを送る、というプログラムを書いてみます。
元のサンプルから、必要最低限の部分のみが残るような感じで書きかえました（冒頭にも書いたとおり、ブラウザから送信するだけの、片方向通信用の処理になっています）。

```html
<!DOCTYPE html>
<html>
    <head>
        <title>osc.js Web Socket Demo</title>
        <meta charset="UTF-8" />
        <script src="https://cdn.jsdelivr.net/npm/osc@2.4.2/dist/osc-browser.min.js"></script>
        <script type="text/javascript">

            const port = new osc.WebSocketPort({
                url: "ws://localhost:8081"
            });
            port.open();

            const sayHello = function () {
                port.send({
                    address: "/hello",
                    args: ["world"]
                });
            };

        </script>
    </head>

    <body>
        <h1>osc.js Web Socket Demo</h1>
        <button onclick="sayHello()">Send OSC message</button>
    </body>
</html>
```

#### 動作させてみた結果
以下のツイートの添付画像にあるように、OSC Data Monitor側で、ブラウザから送られたデータを受信・表示できたのが確認できました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">osc.js を使ったブラウザでの OSC利用の件、<br>Node.js と HTML+JavaScript のプログラムをそれぞれ書いて動かした。<br><br>そして、ブラウザのページ上から OSC over WebSocket を使って、Node.js のプログラムを介し、OSC Data Monitor にデータが送られたのを確認できた！ <a href="https://t.co/fJNzbCSWXz">pic.twitter.com/fJNzbCSWXz</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1462284527716356097?ref_src=twsrc%5Etfw">November 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

添付画像の右端のほうの部分を、以下に掲載しておきます。
![データを受信.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6f614124-9d8d-4891-f358-341a36d1cfcf.jpeg)
HTML上のボタンを複数回押したので、メッセージ受信が複数受信されている、という状態です。

## おわりに
osc.js を使った Node.js のプログラムで WebSocket関連の処理を書くことで、UDP・WebSocket の両方で待ち受けができる仲介役ができあがりました。
そして、その仲介役にブラウザからアクセスして WebSocket でデータを送ることで、OSC Data Monitor へデータを送ることができました（仲介役が、WebSocket の通信を UDP の通信に変換していたりします）。

UDP・WebSocket の両方が使えると、いろいろ活用できる内容が拡がりそうです！

## 【追記】 その後
p5.js　から使う、というのもやってみました。

●p5.js Web Editor のプログラムから osc.js を使った OSC通信（OSC over WebSocket を利用） - Qiita
　https://qiita.com/youtoy/items/45bebdfb948b3f918c05