ProcessingとSwiftを繋ぎたいだけなのに、
わざわざSocket.IOでNode.jsを経由したりするのがなんだか気持ち悪かったので、
ProcessingのWebsocketsと、SwiftのWebSocket用ライブラリのStarscreamを使用して直接繋いでみました。
今回は、Processingをサーバ、Swiftをクライアントとして開発しました。
なお、諸事情によりSwift3で実装していますが、Swift4でもStarscreamは使用できるはずです。
注意
- 動作環境 : Swift3, Processing
- 使用ライブラリ
- Processing... Websockets
- Swift... Starscream
- ライブラリ管理ツール... CocoaPods
- 同じWiFiに繋いだ環境のみ使用可能
内容
プログラムを書く前にCocoaPodsでStarscreamをインストールしておきましょう。
CocoaPods.org
GitHub: daltoniam/Starscream
余談ですが、
WebSocketとSocket.IOってプロトコルが違うみたいですね。
最初は一緒に使えるものだと思っていました。
リアルタイム双方向通信について
さて、インストールが完了したらプログラムを書いていきましょう。
import websockets.*;
WebsocketServer wsc;
PFont myFont;
String receivedText = "";
String sendingText = "";
void setup(){
size(300, 150);
wsc = new WebsocketServer(this, 5000, "/");
myFont = createFont("MS Gothic", 20, true);
fill(255);
}
void draw(){
background(0);
textAlign(CENTER);
textFont(myFont);
text("Received: " + receivedText, width/2, height/2);
textAlign(CORNER);
textSize(15);
text("sending: " + sendingText, 0, height-10);
}
void keyPressed(){
if(keyCode==ENTER) {
wsc.sendMessage(sendingText);
sendingText = "";
} else {
sendingText += str(key);
}
}
void webSocketServerEvent(String msg){
receivedText = msg;
// ここに直接
// text(msg, 100, 100);
// などと書いても何も描画されなかったので注意
}
webSocketServerEvent()
内でtext()
を使えないのは、
Processingのdraw()
に関係ない関数だからってことなんですかね?
SwiftはStoryBoardでUIを作成しています。
import UIKit
import Starscream
class ViewController: UIViewController {
// pc上でテストするならlocalhostでok
let socket = WebSocket(url: URL(string: "ws://localhost:5000")!)
// iPhone上でテストするならプライベートipアドレスで記述
// let socket = WebSocket(url: URL(string: "ws://192.168.x.x:5000")!)
override func viewDidLoad() {
super.viewDidLoad()
socket.delegate = self as? WebSocketDelegate
socket.connect()
// 受信時に実行される
socket.onText = {(text: String) in
self.receivedMessage.text = "Received: \(text)"
self.receivedMessage.textColor = UIColor.red
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBOutlet weak var receivedMessage: UILabel!
@IBOutlet weak var textField: UITextField!
@IBOutlet func sendMessage(_ sender: UIButton) {
// 送信内容が空だとエラーが発生するので回避
if textField.text != "" {
socket.write(string: textField.text!)
textField.text = ""
}
}
}
以上で接続できるはずです。
今回は、Processingでは押されたキーをsendingText
に追加することにしていますが、
日本語入力などをしたいのであれば、JavaのSwingを利用するといいと思います。
processing3でAWT/swingを使う。