2012年5月20日日曜日

ArduinoからWebSocketサーバへ、socket.ioをつかって接続するには

ArduinoにEthernet Shieldを積んで、WebSocketを使うときのKUFU。

WebSocketをつかうには

WebSocketClientというライブラリが公開されているので、それをつかって。Zipファイルをダウンロードしたら、Arduino.app/Contents/Resources/Java/librariesに展開。Arduino.appを再起動すると、Scketch→Import LibraryとFile→ExamplesにWebSocket関係の項目が追加されます。Mac以外の場合は知りません。然るべきディレクトリに解凍してください。

サンプルをうごかしてみる

#include "Arduino.h"
#include <Ethernet.h>
#include <SPI.h>
#include <WebSocketClient.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 100 };
char server[] = "echo.websocket.org";
WebSocketClient client;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  client.connect(server);
  client.setDataArrivedDelegate(dataArrived);
  client.send("Hello World!");
}

void loop() {
  client.monitor();
}

void dataArrived(WebSocketClient client, String data) {
  Serial.println("Data Arrived: " + data);
}

もともとのサンプルから、7行目にbyte ip〜を追加、13行目の引数をmac→mac, ipに変更しています。ipは適宜変更していただいて。ipが指定去れていない場合はDHCPとなりますが、試したArduino DuemilanoveとEthernet Shieldの組み合わせせはIPアドレスの取得に時間がかかり、echoサーバにつながっていないようでした。固定IPアドレスにすることでDHCPの時間をカットできます。

socket.ioをつかったWebSocketサーバにつなぐ

WebSocketサーバでsocket.ioをつかっている場合、これはちょっと特殊。そもそもWebSocket = socket.ioではなく、WebSocket ⊂ socket.ioといった具合。WebSocketが使えない・対応していない状況ではXMLHttpRequestやCometなどの代替手段でWebSocketふうの接続をまかなうのがsocket.ioなので、微妙に変えてあげる必要があります。

// Arduino (Client)
#include "Arduino.h"
#include <Ethernet.h>
#include <SPI.h>
#include <WebSocketClient.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 100 };
char server[] = "192.168.2.1";

WebSocketClient client;

void setup(){
  Serial.begin(9600);
  
  Ethernet.begin(mac, ip);
  delay(1000);
  if(client.connect(server, "/socket.io/1/websocket/", 3000)){
    client.setDataArrivedDelegate(dataArrived);
    //client.subscribe("atime");
    delay(1000);
  } else { while(1){} }
}

void dataArrived(WebSocketClient client, String data) {
  Serial.println("Data Arrived: "+data);
}

void loop(){
  client.monitor();
  
  //send a message
  String message = "{";
  message += "\"millis\":";
  message += millis();
  message += "}";
  
  client.send(message);
  delay(1000);
}

// Node.js (Server)
var io = require('socket.io').listen(3000);

io.sockets.on('connection', function(socket){
  socket.on('atime', function(data){
    console.log(data);
  });
});

クライアント側はこのスライドを参考に。でもコレ、ちょっと怪しい箇所があるので、動くものに書き直ししたのが上のもの。サーバ側のNode.jsは基本的にサイトのサンプルのまま。重要なのはクライアント側のclient.connectの部分。第2の引数をsocket.ioの仕様にて定義されているとおりに指定するだけ。プロトコルのバージョンを示している1と通信方法を示しているwebsocketの部分は基本的に変えません。socket.ioの部分が名前空間を示しているので、任意の名前空間を使用する場合には適宜書き換えとなりますここは試していますがうまくいきません。destroying non-socket.io upgradeというメッセージがコンソールに表示されているところ。socket.ioを使うサーバとWebSocketでやりとりするならコレでOK。

問題点

何らかの原因でサーバとクライアントとの接続が切れたとき、ブラウザ上のsocket.ioでは再接続のタイミングをねらって待機しますが、この実装ではそういった点は考慮していません。この実装ではリセット以外に再接続の方法はないので、必要ならうまいことスケッチに追加する必要があります。

もうひとつ。最後のdelay(1000)は1秒待てですが、これがないと3〜5msおきにメッセージを投げ続けます。このときに、Ethernet Shield上のチップが結構熱くなるのが心配。常温環境でもパッケージに触るといい具合に熱が伝わってくるので、あったかいところでは気がかりです。

2012年5月7日月曜日

アシッドたんぱ大放送復活スペシャルにいってきた

"日本の平均的かつ最先端のクラブ"でおなじみの渋谷アシッドパンダカフェ。アシパンのポッドキャスト公開録音イベントに行ってきたよ。Dommuneを参考にした2部構成で、1部にトーク。2部にDJミックス。

第1部は店主の高野政所さんトークショー。トップ5の裏話を。おかしな名前のゲストが呼ばれた背景などを、当人を交えてのお話。録音してポッドキャストの予定だったのですが、録音に失敗していたとのこと。現場とUstreamのみのお楽しみになってしまったので、ここには書きません。

2部のDJミックスがすごかった。高野政所 a.k.a. DJ JET BARONとプリキュアおじさん2人のDJで、先発はDJ JET BARON。Funkotが楽しくて盛り上がるのは当たり前で、それ以上に政所さんがかっこいい。曲にノリつつもびしびし選曲をすすめる。代官山の申し訳ないと年末スペシャルでも政所さんのDJは聞いていたんだけど、あのときは照明でよく見えなかったんだよね。DJブースとの距離が近いのがアシパンのいいところ。

そしてプリキュアおじさん(=プリキュアにはまりすぎるあまり、政所さんに命名された)のDJ。プリキュアを見たことないし曲も知らないけど、確実に楽しいDJミックス。政所さん曰く、曲を聞きすぎているから完璧につないでいくとのこと。みんな聞ける機会をつくって聞きにいくべき。加えてVJもプリキュアおじさん自身が。というか他の人では無理だろうと。一人二役をバキーッとこなしてフロアを盛り上げるプリキュアおじさん、こういう大人になりたいと思いました。

"アシパンこわい"という声はありますけども、アシパンがこわいというよりも、初めて飛び込む場所がこわいってことかなと。初めて参加する勉強会はなんとなくこわかったりするしね。アシパンの中の人はみなあったかいというか、自分たちが楽しいと思ってることを一緒に楽しんでくれる人なら心のハードルは下がるじゃないですか。アシパンこわくなかったよ。