p.s. 2015/8/8 githubに置きました https://github.com/toshirot/ccchart
ccchartのv1.00をリリースしました。これを機に、WebSocketのインターフェイスを変更しています。
これまで使っていたmoveByWSメソッドは廃止し、よりw3cのWebScket APIライクな処理で扱えます。シンプルに、かつ汎用化し、速度も上げるという改変です。
サンプルは、こうです。
http://ccchart.org/test/ws2.htm
http://ccchart.com/#85
(ちなみに、ccchartの開発版サイトはここです http://ccchart.org/)
クライアント側 ccchart コード部分
ccchart
.init('hoge', chartdata85)
.ws('ws://ccchart.com:8016')
.on('message', ccchart.wscase.oneColAtATime)
簡単に、書式を説明するとこうなります。
ccchart
.init('チャート用キャンバスID', チャート設定)
.ws('ws://データを配信するアドレス:ポート')
.on('message', データ着信時に動作する関数)
// .onは、.addEventListenerのショートカットです
// .on('message' の他に .on('open' や .on('close' なども使えます
// oneColAtATimeは、ccchart専用WebSocketの受信パターン関数で
// 一度に1列ずつ [["2013"],[435],[600]] といった配列で届く場合用
// もちろん、自分で onmessage な関数を書いても全然かましまへん。
クライアント側のHTMLとJavaScript全コード
上記 #85 サンプルでのHTMLを含むフルコードは次の通り。
<script src="http://ccchart.com/js/ccchart.js" charset="utf-8"></script>
<canvas id="hoge"></canvas>
<script>
// チャート設定
var chartdata85 = {
"config": {
"title": "WebSocket test",
"subTitle": "列データをリアルタイム受信描画 受信パターンはoneColAtATime",
"type": "bezi2",
"lineWidth": 2,
"minY": 0,
"xScaleSkip": 3,
"maxWsColLen": 18,
"colorSet":
["#DDA0DD","#3CB000"]
},
"data": [
["年月"],
["データ1"],
["データ2"]
]
};
ccchart.wsCloseAll();//一旦クリア
ccchart
.init('hoge', chartdata85)
.ws('ws://ccchart.com:8016')
.on('message', ccchart.wscase.oneColAtATime)
</script>
ccchartがサーバーから受信するデータ
後述するWebSocketサーバーからは、以下の各行の配列データがJSON.stringifyされて順次送られてきます。(ccchartの送受信は、一応安全のためJSON.stringify必須としています)
["23:41:47",58,41]
["23:41:47",30,46]
["23:41:47",7,35]
["23:41:47",46,34]
["23:41:47",59,41]
["23:41:47",95,47]
["23:41:47",22,40]
["23:41:47",73,35]
・・・・
・・・・
・・・・
サーバー側 Node.js WebSocket
WebSocketサーバー側 Node.js は、まぁ、いろいろな書き方ができますが、たとえば以下のような感じ。もし、wsが入ってなければ $npm i ws
などで入れておきます。
var WsServer = require('ws').Server;
var tid;
// WebSocketサーバー作成
var ws = new WsServer({
host: 'ccchart.com',
port: 8016
});
broadCast();// データ配信開始
// クライアント接続時イベント
ws.on('connection', function(socket) {
console.log('conned: ' + ws.clients.length);
});
// 100ms毎にデータをブロードキャストする
function broadCast(){
tid = setInterval (function(){
var dataAry = mkData();
ws.clients.forEach(function(client) {
client.send(JSON.stringify(dataAry));
});
}, 100);
}
// データ配列を作る
function mkData(){
var data = [];
var now = new Date();
var H = now.getHours();
var M = now.getMinutes();
var S = now.getSeconds();
H = (H < 10)?'0'+H:H;
M = (M < 10)?'0'+M:M;
S = (S < 10)?'0'+S:S;
data[0]=H +':' + M +':' + S;
data[1]=Math.floor(Math.random(10) * 96 );
data[2]=32 + Math.floor(Math.random(10) * 18);
return data;
}
mkDataで作成した配列データを100ms間隔で、接続している全クライアントへブロードキャストしています。生成している値はとりあえずここではランダムな値ですが、実際には必要なデータを使います。
参考
参考までに、上記のデータを処理するために、クライアント側コードで使っている、WebSocketのonmessageイベント受信用パターン関数、ccchart.wscase.oneColAtATime
のコードは以下の通りです。( ※この簡易ハンドラを使わずに、普通にonmessageイベントを自作してもかまいません。)
oneColAtATime = function (msg) {
// 一度に1列ずつ [["2013"],[435],[600]] といった配列で届く場合
// e.g. ws.on('message', ccchart.wscase.oneColAtAtime)
var msgs = JSON.parse(msg.data);
var that = ccchart.ops[this.id];
if (that.drawing) {
console.log('I threw away the data: ', JSON.stringify(msgs));
return; // グラフ描画中なら着信データを捨てる
}
for (var i = 0; i < msgs.length; i++) {
var rowTitle = that.op.data[i].shift(); // 先頭を行タイトルとして削除
that.op.data[i].push(msgs[i]); // WSで受け取ったデータを追記
if (that.op.data[i].length > that.maxWsColLen) {
that.op.data[i].shift(); // maxWsColLen列以上は削除
}
that.op.data[i].unshift(rowTitle); // 先頭へ行タイトルを戻す
}
if (that.type === 'pie') {
that.op.config.maxWsColLen = 1
}
ccchart.init(that.id, that.op); //再起へ
}
WebSocketイベント messageのハンドラ関数をカスタマイズする参考になるかな?と思います。ちなみに、当然 カスタマイズするチャートtype が円グラフ(pie)でなければ、maxWsColLen = 1 (列数1)なんてブロックは不要です。
受信用パターン関数は、今のところこのoneColAtATime の他には、複数行まとめて送るsomeColsAtATimeがあります。
ちなみに、ccchart側は、コールバックを使用して、こんな風にも書けます。
ccchart
.init('hoge1', chartCfg, // 対象canvas要素, とチャートデータ
function () { // コールバック
this
.ws('ws://ccchart.com:8012')
.on('message', this.wscase.oneColAtATime);
}
);
未完のリファレンスがここにあります。
http://ccchart.com/doc/ccchart-1.00.pdf
*追記 http://ccchart.org/doc/ccchart-1.06.pdf
あと、ライセンスもv0.9xまではパブリックドメインにしてましたが、v1x以降はMITにしますので、サイトにv0.9xへのリンクも作ろうと思ってます。
MITは、jQueryやNode.jsなどで利用されてる、一番ゆるいっぽいライセンスです。まぁ、かわいいコード達の為に、親として少しだけ胸を張ってみようかなと。