mindwaveからofxThinkgearでデータ取得した

# はじめに
久々にoFです。

[NeuroSky](https://www.neurosky.jp/)というメーカーが作っている、mindwaveという簡易脳波計があります。
現在一般向けには[mindwave mobile 2](https://www.neurosky.jp/mindwave-mobile2/)が出回っているようです。
研究室には[mindwave mobile](www.amazon.co.jp/dp/B00CFEFDKQ)が転がっていました、こちらは現在在庫切れらしいです。

どちらもスターターキットに同梱されるアプリケーションや既存のThinkgearConnector(TGC)対応アプリで扱う他に、自身で簡単なアプリを作って脳波のデータを取得することができるらしいです。
実装方法はいくつかあるようで、ググってみると[「MindWaveからPythonを使って脳波の値を取得し、好きなプログラムで利用する方法」](https://mikenerian.hatenablog.com/entry/2017/12/18/222633)というPythonで値を取得する記事がとっつきやすかったので書いてある通りセットアップしたところ、無事コンソールで値を取得できました。結構簡単。

次にTouchDesigner(TD)でTGCからTCP/IPで受け取ろうと試みましたが、接続まではいくもののなぜかデータが送られて来ませんでした。おそらく認証周りではないかと踏んでいます。TDで直で受け取りできた例があったら教えてほしいです。

ということでこちらは一旦お蔵入りし、openFrameworksのaddonに良さそうなのがあったのでそちらを使うことにしました。
今回はその実装時の備忘録です。

# 開発環境
macOS High Sierra 10.13.6
openFrameworks v0.10.1

[ofxThinkgear](https://github.com/labe-me/ofxThinkgear/tree/master/example/src)(別の方が作った同名のaddonもありますが、今回はこちらのlabe-meさんのaddon。)

# 下準備
下準備として、以下の2点をします。
・mindwave自体が正常に使えるか確認
・使用するシリアルポートを確認
ここは[前述のPython記事](https://mikenerian.hatenablog.com/entry/2017/12/18/222633)の途中まででわかるので省略。


# ofxThinkgearを動かす
exampleをそのまま動かしてみればいいと思いますが、自分はとりあえずイベントが発火しているかだけ確認するために、グラフの描画部分(Lineなど)は削りました。

この純粋にofxThinkgearのみを動かす段階でいくつか問題が出たのでそちらについて書いていきます。

## ofxThinkgear.cpp min()
min()がありませんとのこと。
こちらは関数名前にstd::を足して`std::min()`とすればOKです。
 
## ofxThinkgear.cpp tg.device.writeByte() 「call to 'writeByte()' is ambiguous」
「writeByteの引数が曖昧です」だそうです。
tg.deviceはofSerialの変数ですので、ofSerial.hにwriteByte()の定義を見にいきました。

```ofSerial.h
	/// \brief This writes bytes into the serial buffer from the buffer pointer passed in
	///
	/// ~~~~{.cpp}
	/// unsigned char buf[3] = {'o', 'f', '!'};
	/// device.writeBytes(&buf[0], 3);
	/// ~~~~

	long writeBytes(const unsigned char * buffer, size_t length);
	long writeBytes(const char * buffer, size_t length);
	long writeBytes(const ofBuffer & buffer);

	/// \brief Writes a single byte to the connected serial device.
	///
	/// Check the return value to be sure the data was written.
	/// ~~~~{.cpp}
	/// ofSerial mySerial;
	/// mySerial.setup(0, 57600);
	/// unsigned char myByte = 225;
	/// bool byteWasWritten = mySerial.writeByte(myByte);
	/// if ( !byteWasWritten )
	///	 ofLog(OF_LOG_ERROR, "Byte was not written to serial port");
	/// ~~~~
	bool writeByte(unsigned char singleByte);
	bool writeByte(char singleByte);
```
引数にはcharかunsigned char、そのポインタとサイズ、またはofBufferが入ります。
ここに16進数なのでunsigned charかcharとなるんでしょうが、このどちらに入れるかがわかりません。
これが「引数が曖昧」ということです。

解決策として、今回はキャストで指定しました。
値で入っている0xc2は10進数で194なので、0~255をとれるunsigned charにしました。

```diff:ofxThinkgear.cpp
- tg.device.writeByte(0xc2);
+ tg.device.writeByte((unsigned char)0xc2);
```

ofxThinkgear.cppに2箇所writeByteを使用している場所はあるので両方直してください。

## シリアルポートの指定
ここまででひとまずビルドは通りますが、実際に動かすと運がよくなければおそらく「デバイスが見つかりません」とか「接続できません」とかそういう類のログが出るでしょう。
ofxThinkgear.cppを見ると、ofSerial.setup()でポート指定を行うらしいのですが、ここには、ofxThinkgear.hにある`HOST`と`PORT`の定数が入っていました。
というわけで、それらの定数値を下準備で調べたシリアルポートに書き換えます。

```diff:ofxThinkgear.h
- #define THINKGEAR_PORT "/dev/tty.MindWave"
+ #define THINKGEAR_PORT "hoge"// hogeに自身の環境のシリアルポート名を入れる
```

以上でとりあえず動きました。

# おわりに
これでバリバリ脳波を使っていろいろできます。
が、脳波そのものからちゃんとどう言う状態か把握するのはまた別問題。
しばらくはattentionとmeditationで遊びます。

何か質問や間違いなどございましたらコメントよろしくお願いします。