iPhoneの画面タッチでLチカ - OSC 

iPhoneをタッチしたら、Lチカするプログラムを作成します。

**構成**
iPhone ->（OSC）-> Max ->（シリアル通信）->Arduino->Lチカ

**通信メッセージ**
iPhone -> **"touch/panel/down"** -> Max -> **"down**" -> **1** -> Arduino -> LED点灯
iPhone -> **"touch/panel/up**" -> Max -> **"up**"-> **0** -> Arduino -> LED消灯

**環境**
of_v0.9.3_ios_release
Xcode v7.3.1
Max/Msp 7
iPhone 6
Arduino v1.69

# openFrameworks
まずはofから。iPhoneのプログラムを記述します。
projectGeneratorで、Addonsに ofxOsc を入れてプロジェクトを作成します。

作成できたら`ofApp.h`を以下のようにします。

```C++:ofApp.h
#pragma once

#include "ofxiOS.h"
#include "ofxOsc.h"

//#define HOST "localhost"
#define HOST "192.168.100.101"
#define PORT 12345 

class ofApp : public ofxiOSApp {
  
    public:
        void setup();
        void update();
        void draw();
        void exit();
  
        void touchDown(ofTouchEventArgs & touch);
        void touchMoved(ofTouchEventArgs & touch);
        void touchUp(ofTouchEventArgs & touch);
        void touchDoubleTap(ofTouchEventArgs & touch);
        void touchCancelled(ofTouchEventArgs & touch);

        void lostFocus();
        void gotFocus();
        void gotMemoryWarning();
        void deviceOrientationChanged(int newOrientation);
    
    private:
        ofxOscSender sender;
        bool touch_down;
};
```

`#define HOST`は使用しているネットワークを指します。
MacからiPhoneのシュミレーターで確認する場合、IPアドレスか`"localhost"`で構いません。
実機のiPhoneからであれば、IPアドレスを記述します。

また、PORTは1024~65535番の範囲で記述します。
0~1023番はサーバのアプリケーションで使用するポートとして登録されているので、被らないようにします。

`ofxOscSender sender;`はOSCメッセージを送信するインスタンス、`bool touch_down`はiPhoneをタッチしたか否かを判定するために使用します。

---

続いてofApp.mm。
iPhoneをタッチした際にOSCメッセージが送られるようにします。
特に記述していないところは省略しました。

```C++:ofApp.mm
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    
    ofBackground(0, 0, 0);
    sender.setup(HOST,PORT);
    ofSetFrameRate(10);
    
    touch_down = false;
}

//--------------------------------------------------------------
void ofApp::draw(){
    
    ofSetColor(255, 255, 255);
    if(touch_down == true){
        ofSetColor(255,255,255);
        ofDrawCircle(ofGetWidth()/2, ofGetHeight()/2, 10);
    }
}

//--------------------------------------------------------------
void ofApp::touchDown(ofTouchEventArgs & touch){
    ofxOscMessage m;
    m.setAddress("touch/panel");
    m.addStringArg("down");
    sender.sendMessage(m);
    
    touch_down = true;
}

//--------------------------------------------------------------
void ofApp::touchUp(ofTouchEventArgs & touch){
    ofxOscMessage m;
    m.setAddress("touch/panel");
    m.addStringArg("up");
    sender.sendMessage(m);
    
    touch_down = false;
}
```
`sender.sendMessage(m);`によって`m.setAddress();`と`m.addStringArg();`の
引数がMaxに送られます。

今回はiPhoneの画面に指を置いた際に"touch/panel/up"が送信され、画面から指を離した際に"touch/panel/down"が送信されます。

また視覚的にタッチしているか否かが分かるようにするため、タッチをした際に画面中央に円が描かれるようにしています。



# Max
Maxのパッチです。
![スクリーンショット 2016-10-03 1.21.36.png](https://qiita-image-store.s3.amazonaws.com/0/72056/b30840de-49a7-48d3-7507-255d04897fb9.png)

**udpreceive**
`udpreceive`の引数にofで設定したポート番号を記述します。

**route**
`route`は「`route`のインレットの最初の引数」と「`route`の引数」が合致した場合、合致した次のインレットの引数の値を出力します。（説明難しい）

ofから送られてくるメッセージは"touch/panel/up"もしくは"touch/panel/down"です。

"touch/panel/down"->`route touch/panel/`->合致->"down"
"touch/panel/up"->`route touch/panel/`->合致->"up"

となり、"up"もしくは"down"が出力されます。

**sel**
`sel down up`ではupとdownを数値の0,1に置き換えています。
文字列だと`serial: doesn't understand`というエラーが出てしまうので、upやdownから数値に置き換える必要があります。

**serial**
`serial c 9600`のcはポートを、9600は通信速度を指しています。

**- ポートがcの理由**
`serial`に`print`メッセージを繋げます。
![スクリーンショット 2016-09-30 22.41.27.png](https://qiita-image-store.s3.amazonaws.com/0/72056/96c8ba56-2788-934c-70ad-5f5ba62ee2c4.png)

`print`をクリックすると、PCとシリアル通信が出来るデバイスの一覧がMax consoleに出力されます。

ArduinoをPCに接続し`print`を押すと、私のPCでは
![スクリーンショット 2016-09-30 23.33.01.png](https://qiita-image-store.s3.amazonaws.com/0/72056/e1c19661-92ec-4285-aa38-96476a6e150e.png)
と出力されます。これでArduinoのportはcだとわかりました。
使用環境によって、aだったりbだったりするので確認をしましょう。

# Arduino

```C++:osc_01.ino
void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {

  if(Serial.available()>0){
    
    int c = Serial.read();
    Serial.println(c);
    
    if(c == 1 ){
      digitalWrite(13,HIGH);
     }else if(c == 0){
      digitalWrite(13,LOW);
        }
    }

}
```

`Serial.begin();`の引数はMaxの`serial`で設定した、通信速度と同じです。

iPhoneをタッチするとMaxからは0,1の値が送信されるので、Arduinoにプログラムを書き込むことでLEDがチカチカするようになります。

コンパイルの順番によってはうまくいかなかったりしますが、Arduinoに書き込んでからMaxを立ち上げ、ofをコンパイルすると上手くいくかもしれません。

# 参考
[openFramewoks – OSC (Open Sound Control) を利用したネットワーク連携](http://yoppa.org/ma2_10/2279.html)
[Port Number](http://www.infraexpert.com/study/tea5.htm)