ccchartへWebSocketから流し込む

p.s. 2015/8/8 githubに置きました https://github.com/toshirot/ccchart

ccchartのv1.00をリリースしました。これを機に、WebSocketのインターフェイスを変更しています。

これまで使っていたmoveByWSメソッドは廃止し、よりw3cのWebScket APIライクな処理で扱えます。シンプルに、かつ汎用化し、速度も上げるという改変です。

![ccchart websocket](http://ccchart.com/doc/img/ws2.png)

![ccchart websocket](http://ccchart.com/doc/img/ws.png)

サンプルは、こうです。
http://ccchart.org/test/ws2.htm
http://ccchart.com/#85
(ちなみに、ccchartの開発版サイトはここです http://ccchart.org/)

## クライアント側 ccchart コード部分

```javascript
  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を含むフルコードは次の通り。

```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``` などで入れておきます。

```javascript
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イベントを自作してもかまいません。)

```javascript
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側は、コールバックを使用して、こんな風にも書けます。

```javascript
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などで利用されてる、一番ゆるいっぽいライセンスです。まぁ、かわいいコード達の為に、親として少しだけ胸を張ってみようかなと。