##はじめに
この記事は、Life is Tech ! アドベントカレンダー2016 23日目の記事です.
はじめまして岐阜のiOSメンター __watakemi__です.
普段はIAMASという学校でひっそりと息をしています.
そんな私が最近取り組んでいるのは大量のiPodを制御することです.大量にピカらせてます.
今回はMaxやswiftにおけるOSCの送受信をベースに大量の端末を制御するときの知見を共有できたらと思います.
##本記事について
OSCまわりで横断的にまとめられている記事が少なかったのでこの際まとめてみました.
Maxの基本操作やSwiftの基礎についてはあまり触れません、ごめんなさい.
- OSC通信
- Max,swiftでの実装
- 通信まわりとブロードキャスト
- 実践例
##OSC通信って
OSC(Open Sound Control)とは本来電子楽器同士を連携させるために開発された通信プロトコル.
複数端末間で信号が送受信可能、かつ超便利と簡単シンプルということから、
今では様々なソフトを架け橋するために利用されるようになりました.
詳しくは田所先生の記事がとても詳しく解説されています.
##【基礎】MaxにおけるOSC送受信
Maxでは一般的には以下のようなパッチを組むと送受信することがいとも簡単にできてします.
OSC通信でデバッグや簡単な通信を試してみたいときは簡単に試すことができるのでオススメです.
買わずとも体験版では"保存する"以外使えるので触ったことない方は是非試してみてください.
###実装
####1つの値を送る場合
__"udpsend"__によりOSCメッセージを送ることが可能
IPアドレス : 192.168.1.255
port : 3333
####複数の値を送る場合
__"sprintf"__により値をまとめる
__"%s %f"__はそれぞれ"整数 小数"を意味する
####受信するやで
__"udpreceive"__によりOSCメッセージを受信することが可能(portを指定)
__"route /OSCメッセージ"__によりOSCメッセージの場合分け可能
__"uppack"__により複数の値を切り分けが可能
__"0 0."__はそれぞれ"整数 小数"の型を指定
###余談
外部ライブラリ"OSC-route"の使用で楽ちんだったりもしますよう.
##【基礎】swiftにおけるOSC送受信
iOSアプリでのOSCのやりとりは"buzzOSC"というライブラリを使用することで簡単に実装します
###導入手順
1.buzzOSCファイル内の"F53OSC"を丸ごと自分のXcodeプロジェクトファイルの中にぶっ込みます
2.ブリッジングヘーダーを作成して以下のように入力しましょう.
(詳しいbridgingheader導入の仕方はこちら)
#import "F53OSC.h"
###実装
####OSC送信すんで
import UIKit
class OscSendViewController: UIViewController {
//osc送信のためのoscClientの初期化
let oscClient = F53OSCClient.init()
override func viewDidLoad() {
super.viewDidLoad()
//OSCを送りたい先のIPアドレスを指定
oscClient.host = "192.000.0.000"
//贈りたい先のport番号を指定
oscClient.port = 3333
}
@IBAction func sendOSC(){
//123というメッセージをOSCで送信
self.sendMessage(oscClient, addressPattern: "/value", arguments: [123])
//複数の値を送る場合はarguments:[123,231,312]
}
//osc送信のためのメソッド
func sendMessage(client: F53OSCClient, addressPattern: String, arguments: [AnyObject]) {
let message = F53OSCMessage(addressPattern: addressPattern, arguments: arguments)
client.sendPacket(message)
print("Sent '\(message)' to \(client.host):\(client.port)")
}
}
####OSC受信するわ
import UIKit
//デリゲートまわりでF53OSCPacketDestinationの追加
class OscRecieveViewController: UIViewController,F53OSCPacketDestination {
//osc受信のためのoscServerの初期化
let oscServer = F53OSCServer.init()
override func viewDidLoad() {
super.viewDidLoad()
//portの指定など
oscServer.port = 3333
oscServer.delegate = self
if oscServer.startListening() {
print("Listening for messages on port \(oscServer.port)")
} else {
print("Error: Server was unable to start listening on port \(oscServer.port)")
}
}
//OSC受信するためのメソッド
func takeMessage(message: F53OSCMessage!) {
print(message)
//OSCmessageによる比較
if message.addressPattern == "/value" {
//OSCargumentsによる比較
if message.arguments[0] as! Int == 123{
print("hello 123")
}else if message.arguments[0] as! Int == 321{
print("hello 321")
}
}
}
}
以上がswiftによるOSC送受信の基礎的な解説でした.
##通信方法とブロードキャスト
OSC通信ではメッセージを贈りたい相手のIPアドレスを指定してメッセージを送っていましたが30台のiPodのIPアドレスなんて…となりますよね
###1.各々のIPアドレスを吐き出してもらう
iOSアプリ側でアプリ起動したときに自分のIPアドレスをMacPCのIPドレス宛に送ってもらう案
####ブリッジングヘーダー(.h)内に追加するコード
#include <ifaddrs.h>
####自身のIPアドレス取得メソッド
func getIFAddresses() -> [String] {
var addresses = [String]()
var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
if getifaddrs(&ifaddr) == 0 {
for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) {
let flags = Int32(ptr.memory.ifa_flags)
var addr = ptr.memory.ifa_addr.memory
if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST) == 0) {
if let address = String.fromCString(hostname) {
addresses.append(address)
}
}
}
}
}
freeifaddrs(ifaddr)
}
print(addresses)
return addresses
}
####メソッドの使い方
let myIPaddress = getIFAddresses()[0]
あとは制御しているMacPC宛てに端末IPアドレスを送りつけて、oFアプリであれば受信したIPアドレスを配列にまとめて、一括管理可能なんてことが可能ですね.
でもめんどうという方は次のやり方!!
###2.ブロードキャストアドレス
ブロードキャストアドレスとは
同じネットワークに繋がっている全ての端末にメッセージを送りたいときに使う特殊なアドレス
宛先IPアドレスを "XXX.XXX.1.255" にすることでブロードキャストが実現可能です.(他にもやり方はあったり…)
(XXX.XXXは端末のIPアドレス上2つ数字を入力しください.例としは"192.168.1.255","10.10.1.255" となるはずです)
※ただし注意することとしては大学のLANとかでブロードキャストアドレスにメッセージを送るのはやめましょう.
他人がキャッチしてしまったり迷惑極まりないので気を付けましょう(めっちゃ飛ばして怒られました)
##20台繋げるときに気をつけること
###ad-hoc接続では限界がある
OSC通信は通常同じネットワークに繋がっていないと通信がうまくいきません.
そのためさまざまな現場に行ったときは自分のPCをルーター代わりにad-hoc通信をすることがよくあります.
いわゆるモバイルアドホックネットワークなこと.
少し詳しく言うと以下のようにネットワークをMacで作成することですね.
ですがad-hoc接続では通信量に限界があり、多くて13〜15台の接続で __遅延や
メッセージが届かないアクシデント(パケットロス)__が多発してしまいます.
###AirMacExtremeとかを使うと余裕マン
それを解決するために使用したのが通信容量の大きいApple純正無線LANルーター "Air Mac Extreme"
こちらに全てのiPodと制御用PCを繋げることで全台目立つ遅延なく通信ができました.
Appleさん曰くは __50台__まで接続が可能ということで、20台以上でもきっと __ヌルサク__に通信をすることが可能でしょう.
またad-hoc接続しているとネットワークを普通に繋げられないので毎回wifiを切り替えてはセットアップが必要という手間が省けるので素敵です.
##実践例
できることは未知数っていうのが正直な所
また個別のデバイスごとに __個別ID__をもたせると集合体のような動きが実現可能(制作途中の汚い写真でごめんなさい)
##最後に
さいごまで読んでいただきありがとうございます、
20台もiPodなんてねーよって方がたくさんだと思いますが、友達同士でMacに同じプロジェクトを配って
同じwifiに繋げて同じアプリ立ち上げれば似たようなことができます.忘年会とかでも使えるかもですね.
この記事が少しでも誰かの手助けorインスピレーションにつながれば幸いです.
ありがとうございました!コメントいいねストックお待ちしていおります!
さて明日は"東工大のハッカソン荒らし"またの名を"oF王子"こと"ぬま"です、お楽しみにー!