Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

ccchartへWebSocketから流し込む

More than 5 years have passed since last update.

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

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

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

ccchart websocket

ccchart websocket

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

toshirot
今年立ち上げたシニアベンチャーでCTOしています。 「霊園ガイド」 というお墓探しのWebツール作ってますので使ってみてくださいね(_ _) 基本JavaScriptやNode.jsなどの周辺でうろうろしてます。 ●著作リスト http://www.amazon.co.jp/-/e/B004LRDBIG ●Github https://github.com/toshirot
https://reien.top/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away